/*定义点的结构*/
struct point
{
int x;
int y;
}
/*定义线段的结构*/
struct line
{
point start; //开始结点
point end; //结束结点
}
/*计算两条直线的叉积*/
int crossProduct(line *l1,line *l2) //将直线v1v2转变成从原点出发的直线vt1vt2的叉乘
{
line l1,l2;
int result = 0;
lt1.start.x = 0;
lt1.start.y = 0;
lt1.end.x = l1->end.x - l1->start.x;
lt1.end.y = l1->end.y - l1->start.y;
lt2.start.x = 0;
lt2.start.y = 0;
lt2.end.x = l2->end.x - l2->start.x;
lt2.end.y = l2->end.y - l2->start.y;
result = lt1.end.x * lt2.end.y - lt2.end.x * lt1.end.y;
return result;
}
/*折线段的拐向判断*/
int segmentTurn(point p0,point p1,point p2)
{
int result = 0;
point pt1,pt2;
pt1.x = p1->x - p0->x;
pt1.y = p1->y - p0->y;
pt2.x = p2->x - p0->x;
pt2.y = p2->y - p0->y;
result = pt2.x * pt1.y - pt1.x * pt2.y;
if (result > 0)
return 1;
else if (result < 0)
return -1;
else
return 0;
}
/*判断两直线是否相交*/
//可直接调用叉乘的代码,计算两个向量的叉积,如果为0,则是平行或者重合的,否则两直线相交。
/*判断点是否在线段上*/
int isPointOnSegment(point p,point q1,point q2)
{
if(segmentTurn(q1,p,q2) == 0)
{
if((min(q1->x,q2->x) <= p->x <= max(q1->x,q2->x)) &&
(min(q1->y,q2->y) <= p->y <= max(q1->y,q2->y))
return 1;
else
return 0;
}
}
/*判断矩形是否包含点*/
int pointInRectangle(point p,point q1,point q2) //输入点和矩形主对角线的两个端点
{
if((min(q1->x,q2->x) <= p->x <= max(q1->x,q2->x) &&
min(q1->y,q2->y) <= p->y <= max(q1->y,q2->y))
return 1;
else
return 0;
}
/*判断两线段是否相交*/
int segmentIntersec(point q1,point q2,point p1,point p2)
{
//快速排斥实验
if(pointInRectangle(p1,q1,q2) || pointInRectangle(p2,q1,q2))
{
//跨立实验
int d1 = segmentTurn(q1,q2,p1);
int d2 = segmentTurn(q1,q2,p2);
int d3 = segmentTurn(p1,p2,q1);
int d4 = segmentTurn(p1,p2,q2);
if(d1 * d2 < 0 && d3 * d4 < 0)
return 1;
else if(!d1 && pointOnSegment(p1,q1,q2)
return 1;
else if(!d2 && pointOnSegment(p2,q1,q2)
return 1;
else if(!d3 && pointOnSegment(q1,p1,p2)
return 1;
else if(!d4 && pointOnSegment(q2,p1,p2)
return 1;
else
return 0;
}
}
/*判断圆是否在矩形内*/
int circleInRectangle(point center,int radius,point r1,point r2) //输入圆心、半径和矩形主对角线的两个端点
{
if(pointInRectangle(center,r1,r2))
{
int d1 = abs(r1->x - center->x);
int d2 = abs(r2->x - center->x);
int d3 = abs(r1->y - center->y);
int d4 = abs(r2->y - center->y);
if(min(d1,d2,d3,d4) >= radius)
return 1;
}
return 0;
}
/*判断点是否在多边形内*/
int isPointInPolygon(point p,point *ch,int n) //转角法
{
int wn = 0;
for(int i = 0;i < n;++i)
{
if(isPointOnSegment(p,ch[i],ch[(i+1)%n]))
return -1; //在边上
int k = segmentTurn(ch[i],p,ch[(i+1)%n]);
int d1 = ch[i].y - p.y;
int d2 = ch[(i+1)%n].y - p.y;
if(k > 0 && d1 <= 0 && d2 > 0)
wn++;
if(k < 0 && d2 <= 0 && d1 > 0)
wn--;
}
if(wn != 0)
return 1; //在多边形内
return 0; //在多边形外
}
/*点集的冒泡排序算法*/
void BubbleSort(point pointSet[],int n)
{ //x坐标小的排在前面;x坐标相同的,y坐标小的排在前面;
int i,j,flag;
point temp;
for(i = n -1;i >= 1;--i)
{
flag = 0;
for(j = 1;j <= i;++j)
if(pointSet[j - 1].x > pointSet[j].x)
{
temp = pointSet[j];
pointSet[j] = pointSet[j - 1];
pointSet[j - 1] = temp;
flag = 1;
}
else if(pointSet[j - 1].x == pointSet[j].x && pointSet[j - 1].y > pointSet[j].y)
{
temp = pointSet[j];
pointSet[j] = pointSet[j - 1];
pointSet[j - 1] = temp;
flag = 1;
}
if(flag == 0)
return;
}
}
/*判断线段是否在多边形内*/
int isSegmentInPolygon(point p1,point p2,point *ch,int n)
{
//先判断线段的两个端点是否在多边形内。
//如果两个端点不全在多边形内,则线段肯定是不在多边形内。
if(isPointInPolygon(p1,ch,n) && isPointInPolygon(p2,ch,n)) //线段PQ的端点不都在多边形内
return 0;
//其次,如果线段和多边形的某条边内交(两线段内交是指两线段相交且交点不在两线段的端点),则线段肯定不在多边形内。
point pointSet[n]; //点集pointSet初始化为空;
for(int i = 0,j = -1;i < n;++i)
{
if(isPointOnSegment(p1,ch[i],ch[(i+1)%n])) //线段的某个端点在S上
pointSet[++j] = p1;
else if(isPointOnSegment(p2,ch[i],ch[(i+1)%n]))
pointSet[++j] = p2;
else if(ch[i],p1,p2) //S的某个端点在线段PQ上
pointSet[++j] = ch[i];
else if(segmentIntersec(p1,p2,ch[i],ch[(i+1)%n])) //线段PQ与S相交
return 0; //此时可以判断是内交了
}
//如果多边形的某个顶点和线段相交,则必须判断两相交交点之间的线段是否包含于多边形内。
//将pointSet中的点按照X-Y坐标排序;
//根据实际情况选择合适的排序方法
BubbleSort(pointSet[],j); //冒泡排序
point p0; //pointSet中每两个相邻点的中点
for(int i = 0;i < n-1;++i)
{
p0.x = (pointSet[i].x + pointSet[i+1].x) / 2;
p0.y = (pointSet[i].y + pointSet[i+1].y) / 2;
if(isPointInPolygon(p0,ch,n) != 1) //p0不在多边形中
teturn 0;
}
return 1;
}
//to be continue…
####参考文章
计算几何的基本代码模板
{计算几何}怎样判断线段相交
判断点及线段是否在多边形内