如何知道一条线是否与一个矩形相交C#中的飞机?-Basic2DGeometry是否有任何.NET方法可以知道由两点定义的线是否与矩形相交?publicboolIntersects(Pointa,Pointb,Rectangler){//如果直线与矩形相交,则返回true//否则返回false}提前致谢。publicstaticboolLineIntersectsRect(Pointp1,Pointp2,Rectangler){返回LineIntersectsLine(p1,p2,newPoint(rX,rY),newPoint(rX+r.Width,rY))||LineIntersectsLine(p1,p2,newPoint(rX+r.Width,rY),newPoint(rX+r.Width,rY+r.Height))||LineIntersectsLine(p1,p2,newPoint(rX+r.Width,rY+r.Height),newPoint(rX,rY+r.Height))||LineIntersectsLine(p1,p2,newPoint(rX,rY+r.Height),newPoint(rX,rY))||(r.Contains(p1)&&r.Contains(p2));}privatestaticboolLineIntersectsLine(Pointl1p1,Pointl1p2,Pointl2p1,Pointl2p2){floatq=(l1p1.Y-l2p1.Y)*(l2p2.X-l2p1.X)-(l1p1.X-l2p1.X)*(l2p2.Y-l2p1.Y);floatd=(l1p2.X-l1p1.X)*(l2p2.Y-l2p1.Y)-(l1p2.Y-l1p1.Y)*(l2p2.X-l2p1.X);如果(d==0){返回假;}浮动r=q/d;q=(l1p1.Y-l2p1.Y)*(l1p2.X-l1p1.X)-(l1p1.X-l2p1.X)*(l1p2.Y-l1p1.Y);浮动s=q/d;如果(r1||s1){返回假;}返回真;}不幸的是,错误的答案已被否决计算实际的交叉点太昂贵了,您只需要进行比较即可。要查找的关键字是“LineClipping”(http://en.wikipedia.org/wiki/Line_clipping)。当你想要快速拒绝时,维基百科推荐Cohen-Sutherland算法(http://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland),这可能是最常见的情况。维基百科页面上有一个C++实现。如果你对实际切断线路不感兴趣,你可以跳过大部分。@Johann的回答看起来与该算法非常相似,但我没有详细研究它。蛮力算法...首先检查矩形是否在线端点的左侧或右侧:然后,如果以上不足以排除交叉点,请检查矩形是否在线端点上方或下方:然后,如果以上不足以排除相交,你需要检查直线方程y=m*x+b看矩形是否在线上方:那么,如果以上不足以排除相交,你需要检查rect是否在线下:然后,如果你到达这里:NB我敢肯定还有更优雅的代数解决方案,但是用笔和纸以几何方式执行这些步骤很容易理解。一些未经测试和未编译的代码:publicstructLine{publicintXMin{get{...}}publicintXMax{get{...}}publicintYMin{get{...}}publicintYMax{get{...}}publicLine(Pointa,Pointb){...}publicfloatCalculateYForX(intx){...}}publicboolIntersects(Pointa,Pointb,Rectangler){varline=newLine(a,b);如果(r.Left>line.XMax||r.Rightline.YMax){returnfalse;}varyAtRectLeft=line.CalculateYForX(r.Left);变种yAtRectRight=线。计算YForX(r.Right);如果(r.Bottom>yAtRectLeft&&r.Bottom>yAtRectRight){returnfalse;}if(r.Top我采用了HABJAN的解决方案,效果很好,并将其转换为Objective-C。Objective-C代码如下:boolLineIntersectsLine(CGPointl1p1,CGPointl1p2,CGPointl2p1,CGPointl2p2){CGFloatq=(l1p1.y-l2p1.y)*(l2p2.x-l2p1.x)-(l1p1.x-l2p1.x)*(l2p2.y-l2p1.y);CGFloatd=(l1p2.x-l1p1.x)*(l2p2.y-l2p1.y)-(l1p2.y-l1p1.y)*(l2p2.x-l2p1.x);如果(d==0){返回假;}浮动r=q/d;q=(l1p1.y-l2p1.y)*(l1p2.x-l1p1.x)-(l1p1.x-l2p1.x)*(l1p2.y-l1p1.y);浮动s=q/d;如果(r1||s1){返回假;}返回真;}boolLineIntersectsRect(CGPointp1,CGPointp2,CGRectr){returnLineIntersectsLine(p1,p2,CGPointMake(r.origin.x,r.origin.y),CGPointMake(r.origin.x+r.size.width,r.origin.y))||LineIntersectsLine(p1,p2,CGPointMake(r.origin.x+r.size.width,r.origin.y),CGPointMake(r.origin.x+r.size.width,r.origin.y+r.size.height))||LineIntersectsLine(p1,p2,CGPointMake(r.origin.x+r.size.width,r.origin.y+r.size.height),CGPointMake(r.origin.x,r.origin.y+r.size。H八))||LineIntersectsLine(p1,p2,CGPointMake(r.origin.x,r.origin.y+r.size.height),CGPointMake(r.origin.x,r.origin.y))||(CGRectContainsPoint(r,p1)&&CGRectContainsPoint(r,p2));非常感谢HABJAN我会注意到,起初我编写了自己的例程来检查梯度中的每个点,并且我做了我能做的一切来最大化性能,但这立即快得多。这种代码具有更好的性能:publicstaticboolSegmentIntersectRectangle(doublerectangleMinX,doublerectangleMinY,doublerectangleMaxX,doublerectangleMaxY,doublep1X,doublep1Y,doublep2X,doublep2Y){//为线段找到最小和最大XdoubleminX=p1X;双maxX=p2X;如果(p1X>p2X){minX=p2X;maxX=p1X;}//找到线段和矩形的x投影的交点if(maxX>rectangleMaxX){maxX=rectangleMaxX;}if(minXmaxX)//如果它们的投影不相交returnfalse{returnfalse;}//为我们之前找到的min和maxX找到对应的min和maxYdoubleminY=p1Y;双最大Y=p2Y;双dx=p2X-p1X;如果(Math.Abs??(dx)>0.0000001){双a=(p2Y-p1Y)/dx;双b=p1Y-a*p1X;minY=a*minX+b;maxY=a*maxX+b;}if(minY>maxY){doubletmp=maxY;最大Y=最小Y;minY=tmp;}//找到线段和矩形的y投影的交点if(maxY>rectangleMaxY){maxY=rec缠结最大Y;}if(minYmaxY)//如果Y投影不相交returnfalse{returnfalse;}返回真;你也可以在JS演示中看到它是如何工作的:http://jsfiddle.net/77eej/2/如果你有两个点和矩形,你可以这样调用这个函数:publicstaticboolLineIntersectsRect(Pointp1,Pointp2,Rectr){returnSegmentIntersectRectangle(rX,rY,rX+r.Width,rY+r.Height,p1.X,p1.Y,p2.X,p2.Y);没有简单的预定义.NET方法可以调用来实现此目的,但是,使用Win32API,有一个非常简单的方法(实现方面很容易,性能不是强项):LineDDABOOLLineDDA(intnXStart,intnYStart,intnXEnd,intnYEnd,LINEDDAPROClpLineFunc,LPARAMlpData)该函数为要绘制的线条的每个像素调用回调函数。在此函数中,您检查像素是否在矩形内-如果找到,则它相交。正如我所说,这不是最快的解决方案,但很容易实现。要在C#中使用它,您当然需要将其从gdi32.dll中删除。[DllImport("gdi32.dll")]publicstaticexternintLineDDA(intn1,intn2,intn3,intn4,intlpLineDDAProc,intlParam);最简单的计算几何技术是遍历多边形的各个部分,看它是否与任何部分相交,因为它也必须与多边形相交。这种方法(以及大部分CG)的唯一警告是我们必须小心处理边缘情况。如果直线在某个点穿过矩形怎么办?我们将其视为十字路口吗?实施时要小心。编辑:用于线相交段计算的典型工具是LeftOf(Ray,Point)测试,如果点位于射线的左侧,则返回该测试。给定一条线l(我们用作射线)和一条包含点a和b的线段,如果一个点在左边而另一个点不在左边,则该线与线段相交:(LeftOf(l,a)&&!LeftOf(l,b))||(LeftOf(l,b)&&!LeftOf(l,a))同样,当点在一条线上时,您需要处理边缘情况,但这取决于您想要如何实际定义交点。对于Unity(反转y!)。这样就可以解决其他方法被零除的问题:以上就是C#学习教程:如何知道直线是否与矩形相交的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注--usingSystem;使用统一引擎;namespaceUtil{publicstaticclassMath2D{publicstaticboolIntersects(Vector2a,Vector2b,Rectr){varminX=Math.Min(ax,bx);varmaxX=Math.Max(ax,bx);varminY=Math.Min(ay,by);varmaxY=Math.Max(ay,by);如果(r.xMin>maxX||r.xMaxmaxY||r.yMaxyForX=x=>ay-(x-ax)*((ay-by)/(bx-ax));varyAtRectLeft=yForX(r.xMin);varyAtRectRight=yForX(r.xMax);if(r.yMaxyAtRectLeft&&r.yMin>yAtRectRight){returnfalse;}returntrue;}}}本文收集自网络,不代表一个职位,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处:
