判断两线段是否相交求交点

转:http://www.docin.com/p-575200015.html


bool IsLineSegmentCross(CPoint pFirst1,CPoint pFirst2,CPoint pSecond1,CPoint 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;
//判断pScond1和pScond2是否在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;
}


//求两直线交点,前提是两条直线必须有交点,在相交的情况下,可以应付各种情况(垂直、系数等)
CPoint GetCrossPoint(CPoint p1,CPoint p2,CPoint q1,CPoint q2)
{
//必须相交求出的才是线段的交点,但是下面的程序段是通用的
//assert(IsLineSegmentCross(p1,p2,q1,q2));
//根据两点式化为标准式,进而求线性方程组
CPoint 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;

}


void CCx05View::OnLButtonUp(UINT nFlags, CPoint point) 
{
// TODO: Add your message handler code here and/or call default

CPoint pointa,pointb,pointc,pointd;
CPoint pointCross;
bool bCross = false;
pointa.x = 400;pointa.y = 440;
pointb.x = 300;pointb.y = 440;
pointc.x = 399;pointc.y = 500;
pointd.x = 399;pointd.y = 400;


CClientDC dc(this);
dc.DPtoLP(&point);
dc.SelectStockObject(NULL_BRUSH);
CPen pen1,pen2;
pen1.CreatePen(PS_SOLID,1,RGB(255,0,0));
dc.SelectObject(pen1);


dc.MoveTo(pointa.x,pointa.y);
dc.LineTo(pointb.x,pointb.y);
dc.MoveTo(pointc.x,pointc.y);
dc.LineTo(pointd.x,pointd.y);


pen2.CreatePen(PS_SOLID,1,RGB(0,255,0));
dc.SelectObject(pen2);


bCross = IsLineSegmentCross(pointa,pointb,pointc,pointd);
if(bCross)
{
pointCross = GetCrossPoint(pointa,pointb,pointc,pointd);


dc.MoveTo(pointCross.x-5,pointCross.y);
dc.LineTo(pointCross.x+5,pointCross.y);
dc.MoveTo(pointCross.x,pointCross.y-5);
dc.LineTo(pointCross.x,pointCross.y+5);
}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值