搜索结果 来自网络的精选片段 对于n = 1:您需要两条线相交,因此最大交点数为0. n = 2:两条不同的线总是在最多一个点相交,而与尺寸无关。 ...说明:每组2条线可以在一个点相交。或者一个点是两条线的共同交点。
我想Q的答案应该分为两部分。
I.如何知道给定的三个点属于同一条线? 问题的这一部分的答案由@Lurd给出,然后由Mbo扩展。 让我们说出他们的解决方案 function BelongToOneLine(Pnts: array [1..3] of TPoint): boolean; 我们可以认为这部分已经解决。
function BelongToOneLine(Pnts: array [1..3] of TPoint): boolean;
II。如何减少算法的时间消耗,换句话说:如何避免调用 BelongToOneLilne 每个可能的点组合作为参数?
BelongToOneLilne
这是算法。
我们选择5 不同 任务集中的点。 5就够了(检查组合可能性)。
我们找到问题的答案,如果给定的五个中至少有三个点属于一条线。
如果不 - 然后我们不需要迭代其余的点 - 答案是我们需要两行以上。
如是 - (假设Pt1,Pt2和Pt3属于同一条线,而Pt4和Pt5则不属于同一条线)。
然后,我们将不属于Pt1-Pt2-Pt3线的点存储在不同的“局外人”点阵列中(或将其索引存储在主阵列中)。它可能有 Length = 0 到这一步结束。这不会影响算法的其余部分。
Length = 0
我们得到函数的布尔结果 BelongToOneLine([Pt1, Pt2, Pt[i]]) 。
BelongToOneLine([Pt1, Pt2, Pt[i]])
如是 - 我们跳过这一点 - 它属于Pt1-Pt2-Pt3线。
如果不 - 我们将这一点存储在“局外人”数组中。
我们观察OutsidersArray的长度。
如果是< = 2 那么整个Q的答案是肯定的,它们确实属于2行或更少行。
如果> 2 然后我们迭代函数 BelongToOneLine([OutsiderPt1, OutsiderPt2, OutsiderPt[i]]) 直到高(OutsiderArray)或直到何时 OutsiderPt[i] 不属于OutsiderPt1-OutsiderPt2行。 OutsiderArray的所有点必须属于同一行,否则整个Q的答案将为负。
BelongToOneLine([OutsiderPt1, OutsiderPt2, OutsiderPt[i]])
OutsiderPt[i]
数学笔记
如果没有优化,就会有不合理的数量 n! / ((n - k)! * k!) 。 通过优化,它将是: 5! / ((5-3)! * 3!) + (n - 3) + P(q)outsiders * n 对于n = 10000,大约是15000.大多数负数 - 大约20000。
n! / ((n - k)! * k!)
5! / ((5-3)! * 3!)
(n - 3)
P(q)outsiders * n
另一个优化说明
用整数变量替换TPoint的声明。
如果矢量AB和AC是共线的或反共线的,则三个点A,B和C位于同一直线上。我们可以使用检查共线性 交叉产品 向量 - 它应该为零。
@LU RD已经描述过这种方法是评论,但作者可能错过了它。
请注意,该方法不会受到除零的影响 - 根本没有除法。
ABx := B.X - A.X; ACx := C.X - A.X; ABy := B.Y - A.Y; ACy := C.Y - A.Y; Cross := ABx * ACy - ABy * ACx; // for integer coordinates if Cross = 0 then A,B,C are collinear
如果坐标是浮点数,则必须考虑一些容差水平。变种:
//better if available: if Math.IsZero(Cross) if Math.SameValue(Cross, 0) //otherwise if Abs(Cross) <= SomeEpsilonValue
如果坐标范围非常大,则数值误差可能很大,因此值得通过坐标差异的平方幅度来标准化公差:
if Math.IsZero(Cross / Max(ABx * ABx + ABy * ABy, ACx * ACx + ACy * ACy))