博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
两线段相交求交点
阅读量:5367 次
发布时间:2019-06-15

本文共 3959 字,大约阅读时间需要 13 分钟。

算法一

#include<stdio.h>  #include<stdlib.h>  #include<assert.h>

struct POINT  {  int x;  int y;  };

bool IsLineSegmentCross(POINT pFirst1, POINT pFirst2, POINT pSecond1, POINT pSecond2) 

//每个线段的两点都在另一个线段的左右不同侧,则能断定线段相交 
//公式对于向量(x1,y1)->(x2,y2),判断点(x3,y3)在向量的左边,右边,还是线上. 
//p=x1(y3-y2)+x2(y1-y3)+x3(y2-y1).p<0 左侧, p=0 线上, p>0 右侧 
long Linep1,Linep2;  //判断pSecond1和pSecond2是否在pFirst1->pFirst2两侧 
Linep1 = pFirst1.x * (pSecond1.y - pFirst2.y) + pFirst2.x * (pFirst1.y - pSecond1.y) +  pSecond1.x * (pFirst2.y  -pFirst1.y);  Linep2 = pFirst1.x * (pSecond2.y - pFirst2.y) + pFirst2.x * (pFirst1.y - pSecond2.y) +  pSecond2.x * (pFirst2.y - pFirst1.y);  if ( ((Linep1 ^ Linep2) >= 0 ) && !(Linep1==0 && Linep2==0))//符号位异或为0:pSecond1和pSecond2在pFirst1->pFirst2同侧 
{ return false;  }  //判断pFirst1和pFirst2是否在pSecond1->pSecond2两侧 
Linep1 = pSecond1.x * (pFirst1.y - pSecond2.y) +pSecond2.x * (pSecond1.y - pFirst1.y) + pFirst1.x * (pSecond2.y -pSecond1.y);  Linep2 = pSecond1.x * (pFirst2.y - pSecond2.y) + pSecond2.x * (pSecond1.y - pFirst2.y) + pFirst2.x * (pSecond2.y - pSecond1.y);  if ( ((Linep1 ^ Linep2) >= 0 ) && !(Linep1==0 && Linep2==0))//符号位异或为0:pFirst1和pFirst2在pSecond1->pSecond2同侧 
{ return false;  }  //否则判为相交  return true;  }  POINT GetCrossPoint(POINT p1, POINT p2, POINT q1, POINT q2) 
{ //必须相交求出的才是线段的交点,但是下面的程序段是通用的assert(IsLineSegmentCross(p1,p2,q1,q2));  POINT crossPoint;  long tempLeft,tempRight;  //求x坐标  tempLeft = (q2.x - q1.x) * (p1.y - p2.y) - (p2.x - p1.x) * (q1.y - q2.y); 
tempRight = (p1.y - q1.y) * (p2.x - p1.x) * (q2.x - q1.x) + q1.x * (q2.y - q1.y) * (p2.x - p1.x) - p1.x * (p2.y - p1.y) * (q2.x - q1.x); 
crossPoint.x =(int)( (double)tempRight / (double)tempLeft ); 
//求y坐标  tempLeft = (p1.x - p2.x) * (q2.y - q1.y) - (p2.y - p1.y) * (q1.x - q2.x); 
tempRight = p2.y * (p1.x - p2.x) * (q2.y - q1.y) + (q2.x- p2.x) * (q2.y - q1.y) * (p1.y - p2.y) - q2.y * (q1.x - q2.x) * (p2.y - p1.y); 
crossPoint.y =(int)( (double)tempRight / (double)tempLeft ); 
return crossPoint;  }  int main(void)  {  POINT pointA,pointB,pointC,pointD;  POINT pointCross;  bool bCross(false);  pointA.x = 400;pointA.y=440;  pointB.x = 300;pointB.y = 440;  pointC.x = 350;pointC.y = 500;  pointD.x = 350;pointD.y = 400;  bCross = IsLineSegmentCross(pointA,pointB,pointC,pointD);  if (bCross)  {

pointCross = GetCrossPoint(pointA,pointB,pointC,pointD);  printf("交点坐标x=%d,y=%d\n",pointCross.x,pointCross.y);  }  else  { 

printf("They are not crossed!");  }  return 0;  }

算法二

定义:平面上的三点P1(x1,y1),P2(x2,y2),P3(x3,y3)的面积量: 

|x1   x2   x3|
S(P1,P2,P3)   =   |y1   y2   y3|   =   (x1-x3)*(y2-y3)   -   (y1-y3)(x2-x3) 
|1   1  1|
已知一条线段的两个端点为A(x1,y1),B(x2,y2),另一条线段的两个端点为C(x3,y3),D(x4,y4),要判断AB与CD是否有交点,若有求出.
首先判断d   =   (y2-y1)(x4-x3)-(y4-y3)(x2-x1),
若d=0,则直线AB与CD平行或重合,
若d!=0,则直线AB与CD有交点,设交点为E(x0,y0):
则有:CE/ED   =   S(A,C,B)   /   S(A,B,D)
所以:CE/CD   =   S(A,C,B)   /   (S(A,C,B)   +   S(A,B,D))
故   x0   =   C.x   +   (D.x   -   C.x)   *   S(A,C,B)   /   (S(A,C,B)   +   S(A,B,D));
y0   =   C.y   +   (D.y   -   C.y)   *   S(A,C,B)   /   (S(A,C,B)   +   S(A,B,D));
也可以直接求
x0   =   [(x2-x1)*(x4-x3)*(y3-y1)+(y2-y1)*(x4-x3)*x1-(y4-y3)*(x2-x1)*x3]/d
y0   =   [(y2-y1)*(y4-y3)*(x3-x1)+(x2-x1)*(y4-y3)*y1-(x4-x3)*(y2-y1)*y3]/(-d)
求出交点后在判断交点是否在线段上,即判断以下的式子:
(x0-x1)*(x0-x2) <=0
(x0-x3)*(x0-x4) <=0
(y0-y1)*(y0-y2) <=0
(y0-y3)*(y0-y4) <=0
只有上面的四个式子都成立才可判定(x0,y0)是线段AB与CD的交点,否则两线段无交点

算法三

//求两个点的直线方程

LINE makeline(POINT p1,POINT p2) {
LINE tl;
int sign = 1;
tl.a=p2.y-p1.y;
if (tl.a<0) {
sign = -1;
tl.a=sign*tl.a;
}
tl.b=sign*(p1.x-p2.x);
tl.c=sign*(p1.y*p2.x-p1.x*p2.y);
return tl;
}
// 如果两条直线 l1(a1*x+b1*y+c1 = 0), l2(a2*x+b2*y+c2 = 0)相交,返回true,且返回交点p
bool lineintersect(LINE l1,LINE l2,POINT &p) {// 是 L1,L2
double d=l1.a*l2.b-l2.a*l1.b;
if (abs(d)<EP) return false;// 不相交
p.x = (l2.c*l1.b-l1.c*l2.b)/d;
p.y = (l2.a*l1.c-l1.a*l2.c)/d;
return true;
}
//计算叉积
double multiply(POINT sp,POINT ep,POINT op) {
return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
}
bool online(LINEl,POINT p)
{
return((multiply(l.b,p,l.a)==0)&&(((p.x-l.a.x)*(p.x-l.b.x)<=0)&&((p.y-l.a.y)*(p.y-l.b.y)<=0)));
}

转载于:https://www.cnblogs.com/lz-vic/p/4765912.html

你可能感兴趣的文章
vim自定义配置之自动括号
查看>>
Burst Balloons
查看>>
Maximum Subarray
查看>>
android sdk安装说明
查看>>
ThickBox弹出框的使用方法
查看>>
前端基础 之css
查看>>
java线程状态
查看>>
Android资源文件命名规范
查看>>
vue 中使用scss
查看>>
在Ubuntu上安装Arena
查看>>
javascript简要笔记
查看>>
挂载U盘到linux中
查看>>
怎么获得combobox的valueField值
查看>>
Quartz.net 开源job调度框架(二)----定点执行
查看>>
WPF中内嵌网页的两种方式
查看>>
人生么
查看>>
[再寄小读者之数学篇](2014-11-14 正整数的平方根要么为无理数, 要么为整数)
查看>>
为新生儿办理户口
查看>>
Bootstrap 中 下拉菜单和滚动监听插件(十一)(持续更新中。。。)
查看>>
团队-科学计算器-项目总结
查看>>