判断连个线段是否相交,分为两步:
(1).快速排斥试验
设以线段 P1P2 为对角线的矩形为R, 设以线段 Q1Q2 为对角线的矩形为T,如果R和T不相交,显然两线段不会相交;
(2).跨立试验
如果两线段相交,则两线段必然相互跨立对方,P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ) 和( P2 - Q1 )位于矢量( Q2 - Q1 ) 的两侧,即
( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0
上式可改写成
( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0
当( P1 - Q1 ) × ( Q2 - Q1 ) = 0 时,说明( P1 - Q1 ) 和 ( Q2 - Q1 )共线,但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;
同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2上。
所以判断P1P2跨立Q1Q2的依据是:
( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) ≥ 0
同理判断Q1Q2跨立P1P2的依据是:
( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) ≥ 0
// segmentLine.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <set>
#include <math.h>
using namespace std;
bool JudgeStatus(double line01Coords[], double line02Coords[])
{
bool returnResult = true;
//先判断在XY方向的最值
double maxX1, minX1, maxY1, minY1;
maxX1 = minX1 = line01Coords[0];
maxY1 = minY1 = line01Coords[1];
if (line01Coords[0] < line01Coords[2])
maxX1 = line01Coords[2];
else
minX1 = line01Coords[2];
if (line01Coords[1] < line01Coords[3])
maxY1 = line01Coords[3];
else
minY1 = line01Coords[3];
double maxX2, minX2, maxY2, minY2;
maxX2 = minX2 = line02Coords[0];
maxY2 = minY2 = line02Coords[1];
if (line02Coords[0] < line02Coords[2])
maxX2 = line02Coords[2];
else
minX2 = line02Coords[2];
if (line02Coords[1] < line02Coords[3])
maxY2 = line02Coords[3];
else
minY2 = line02Coords[3];
//比较最值大小
if ((minX1 > maxX2) || (maxX1 < minX2) || (minY1 > maxY2) || (maxY1 < minY2))
{
returnResult = false;
}
return returnResult;
}
typedef struct{
double x;
double y;
}point;
bool lineCross(double line1[], double line2[])
{
bool returnResult;
returnResult = JudgeStatus(line1, line2);
if(returnResult == true)
{
point p1,p2,p3,p4;
point v1,v2,v3;
p1.x = line1[0];
p1.y = line1[1];
p2.x = line1[2];
p2.y = line1[3];
p3.x = line2[0];
p3.y = line2[1];
p4.x = line2[2];
p4.y = line2[3];
v1.x = p2.x - p1.x;
v1.y = p2.y - p1.y;
v2.x = p3.x - p1.x;
v2.y = p3.y - p1.y;
v3.x = p4.x - p1.x;
v3.y = p4.y - p1.y;
double cross_mult1 = v1.x *v2.y - v1.y*v2.x;
double cross_mult2 = v1.x *v3.y - v1.y*v3.x;
double cross1 = cross_mult1*cross_mult2;
v1.x = p4.x - p3.x;
v1.y = p4.y - p3.y;
v2.x = p1.x - p3.x;
v2.y = p1.y - p3.y;
v3.x = p2.x - p3.x;
v3.y = p2.y - p3.y;
double cross_mult3 = v1.x *v2.y - v1.y*v2.x;
double cross_mult4 = v1.x *v3.y - v1.y*v3.x;
double cross2 = cross_mult3*cross_mult4;
if(cross1<=0 && cross1 <=0)
{
return true;
}
}
return false;
}
double culculate(double line[])
{
double r;
r =sqrt( pow(float(line[0]-line[2]),2) + pow(float(line[1]-line[3]),2));
return r;
}
void main()
{
int line_num;
int i;
double line_points[100][4];
vector<int> temp;
vector<int> remain;
scanf("%d",&line_num);
for(i=0; i < line_num; i++)
{
for(int j = 0; j < 4; j++)
{
scanf("%lf,",&(line_points[i][j]));
}
}
for(i=0; i < line_num; i++)
{
for(int j = 0; j < 4; j++)
{
printf("%lf ",line_points[i][j]);
}
printf("\n");
}
int count = line_num;
double maxLen=-1;
double len=0;
for(i = 0; i < line_num; i++)
{
remain.push_back(i);
}
while(!remain.empty())
{
int kk = *(remain.begin());
len = culculate(line_points[kk]);
temp.clear();
temp.push_back(kk);
std::vector<int>::iterator it = remain.begin();
remain.erase(it);
for(vector<int>::iterator ite = remain.begin(); ite != remain.end();)
{
bool flag = false;
for(std::vector<int>::iterator it_temp = temp.begin(); it_temp!= temp.end(); it_temp++)
{
if(lineCross(line_points[*it_temp],line_points[*ite]))
{
flag = true;
break;
}
}
if(flag)
{
len += culculate(line_points[*ite]);
temp.push_back(*ite);
ite = remain.erase(ite);
}
else{ite++;}
}
printf("\n");
if(len > maxLen)
{
maxLen = len;
}
}
printf("%lf",maxLen);
while(1);
}
注意:使用容器的erase函数在for循环中删除元素时,使用:
for(ite = v.begin(); ite != v.end();)
{
if(*ite == 1){ ite = v.erase(ite); }
else{ite ++;}
}