DetectingCoincidentSubsetsofTwoCoincidentLineSegments这个问题是相关的:但是要注意,一个有趣的子问题包含在大多数解决方案中完全掩盖,即使有三个子情况下,如果它们重合,它们只返回null:例如,我们可以这样设计一个C#函数:publicstaticPointF[]Intersection(PointFa1,PointFa2,PointFb1,PointFb2)其中(a1,a2)是一条线段和(b1,b2)是另一条线段。此功能需要涵盖大多数实现或解释所掩盖的所有奇怪情况。为了解决重合线的奇怪问题,该函数可以返回一个PointF数组:听起来您有自己的解决方案,这很棒。我有一些改进建议。这种方法存在一个主要的可用性问题,因为理解(1)参数的含义以及(2)结果的含义非常混乱。如果你想使用这个方法,你必须弄清楚这两个小谜题。我更愿意使用类型系统来更清楚地说明这种方法的作用。我首先定义一个类型——可能是一个结构,特别是如果它是不可变的——称为LineSegment。LineSegment由两个表示端点的PointF结构组成。其次,我将定义一个抽象基类型“Locus”,并派生类型EmptyLocus、PointLocus、LineSegmentLocus和UnionLocus(如果您需要一个表示两个或多个位点联合的位点)。一个空位点就是一个基因,一个点位点就是一个点,等等。现在,您的方法签名变得更加清晰:staticLocusIntersect(LineSegmentl1,LineSegmentl2)此方法采用两条线段并计算作为它们交点的点的轨迹-空白、单点或线段。请注意,您可以推广此方法。计算线段与线段的交点很棘手,但计算线段与点的交点,或点与点的交点,或任何具有空轨迹的东西,都很容易。并且将交集扩展到任意轨迹并集并不困难。所以你实际上可以写:staticLocusIntersect(Locusl1,Locusl2)嘿,现在很明显Intersect可能是轨迹的扩展方法:staticLocusIntersect(thisLocusl1,Locusl2)addsfromPointFtoPointLocusandLineSegmentImplicit转换为LineSegmentLocus,你可以这样说varpoint=newPointF(whatever);varlineseg=newLineSegment(somepoint,someotherpoint);varintersection=lineseg.Intersect(点);if(intersectionisEmptyLocus)...使用类型系统可以大大提高程序的可读性。//这个JavaScript代码的端口有一些变化://http://www.kevlindev.com/gui/math/intersection/Intersection.js//在这里找到://http://stackoverflow.com/questions/563198/如何检测双线段相交/563240#563240公共类相交{staticdoubleMyEpsilon=0.00001;privatestaticfloat[]OverlapIntervals(floatub1,floatub2){floatl=Math.Min(ub1,ub2);floatr=Math.Max(ub1,ub2);浮动A=Math.Max(0,l);浮动B=Math.Min(1,r);if(A>B)//没有交集returnnewfloat[]{};elseif(A==B)返回新的float[]{A};else//if(AMath.Abs??(denomy)){ub1=(b1.X-a1.X)/denomx;ub2=(b2.X-a1.X)/denomx;}else{ub1=(b1.Y-a1.Y)/denomy;ub2=(b2.Y-a1.Y)/denomy;}列表ret=newList();浮动[]间隔=OverlapIntervals(ub1,ub2);foreach(floatfininterval){floatx=a2.X*f+a1.X*(1.0f-f);浮动y=a2.Y*f+a1.Y*(1.0f-f);PointFp=newPointF(x,y);关于t.Add(p);}返回ret.ToArray();}privatestaticboolPointOnLine(PointFp,PointFa1,PointFa2){floatdummyU=0.0f;双d=DistFromSeg(p,a1,a2,MyEpsilon,refdummyU);returnd这是测试代码:publicclassIntersectTest{publicstaticvoidPrintPoints(PointF[]pf){if(pf==null||pf.Length这是输出:--------------------------------------------------------线段相交-------------------------------------------------------{X=0,Y=0}-{X=100,Y=100}相交{X=100,Y=0}-{X=0,Y=100}如果是,在哪里?{X=50,Y=50}---------------------------------------------------------{X=5,Y=17}-{X=100,Y=100}相交{X=100,Y=29}-{X=8,Y=100}如果是,在哪里?{X=56.85001,Y=62.30054}------------------------------------------------------------------------------------------------------------------------只需触摸点和线交叉----------------------------------------------------------{X=0,Y=0}-{X=25,Y=25}相交{X=25--------感人之处与巧合!------------------------------------------------------{X=0,Y=0}-{X=25,Y=25}与{X=25,Y=25}-{X=100,Y=100}相交,如果是,在哪里?{X=25,Y=25}-------------------------------------------------------------------------------------------------------------------重叠/一致----------------------------------------------------------{X=0,Y=0}-{X=75,Y=75}与{X=25,Y=25}-{X=100,Y=100}相交,如果是,在哪里?{X=25,Y=25}-{X=75,Y=75}--------------------------------------------------------{X=0,Y=0}-{X=100,Y=100}相交{X=0,Y=0}-{X=100,Y=100}如果是,在哪里?{X=0,Y=0}-{X=100,Y=100}--------------------------------------------------------@Jared,JosephO'Rourke'sCGAFAQ中的好问题和好答案如上所述,问题可以通过将点的位置表示为单个参数的函数来简化。设r为参数,表示P在包含AB的直线上的位置,其含义如下:r=0P=Ar=1P=Br<0P在ABr的后延上1P在AB0的前向延伸上按照这些行,对于任何点C(cx,cy),我们计算r如下:doubledeltax=bx-ax;双增量=by-ay;doublel2=deltax*deltax+deltay*deltay;doubler=(ay-cy)*(ay-by)-(ax-cx)*(bx-ax)/l2;这应该可以更容易地计算重叠段。请注意,我们避免了平方根,因为只需要长度的平方。这真的很简单。如果有两条线,则可以找到y=mx+bforms的两个方程。例如:y=2x+5y=x-3所以,当y1=y2在同一个x坐标时,两条直线相交,所以...2x+5=x-3x+5=-3x=-8当x=-8y1=y2时,你找到了交点。这应该很容易转换为代码。如果没有交点,那么每条线的斜率m将相等,在这种情况下您甚至不需要执行计算。以上就是C#学习教程:检测两条重合线段的重合子集的全部内容。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
