Algorithm 确定三角形内部点的凸包算法

Algorithm 确定三角形内部点的凸包算法,algorithm,computational-geometry,point,convex-hull,Algorithm,Computational Geometry,Point,Convex Hull,我有一个双色集合S,在平面一般位置有红色和绿色点(S的三个点不共线)。红色三角形的三个顶点都是S的红色点。如果p位于三角形内部,则S的绿色点p称为被红色三角形包围 我应该做一个算法,找到三角形内的所有绿点。 在看到一些在线资源后,我尝试制作自己的算法,例如: 这是我的“解决方案”: 我不知道这个算法是否有效。 它的运行时间是n^3。另外,我不确定我是否可以说获取所有三角形。 这个算法,我应该创建应该是最有效的一个我可以想出,所以请任何其他的解决方案或建议是欢迎的 如果所有可能的三角形(所有可能

我有一个双色集合
S
,在平面一般位置有红色和绿色点(S的三个点不共线)。红色三角形的三个顶点都是S的红色点。如果
p
位于三角形内部,则S的绿色点
p
称为被红色三角形包围

我应该做一个算法,找到三角形内的所有绿点。 在看到一些在线资源后,我尝试制作自己的算法,例如:

这是我的“解决方案”:

我不知道这个算法是否有效。 它的运行时间是
n^3
。另外,我不确定我是否可以说
获取所有三角形
。 这个算法,我应该创建应该是最有效的一个我可以想出,所以请任何其他的解决方案或建议是欢迎的

如果所有可能的三角形(所有可能的三个红色点选项),您可以做得更简单:

Create the convex hull (CH) of the red points.
Check each of the green points is in the CH or not.
    If it is, there is a red triangle that contains that point.
    If it is not, there is no red triangle that contains the point.

创建
N
红点的凸包在
O(N log(N))
中,可以在
O(log(N))
中检查凸多边形内的点。因此,如果绿点的数量为
M
,则上述算法的总复杂度为
O((M+N)log(N))

让我们从问题中显示的图像开始。它显示不属于三角形的红点。而文本并没有给出具体的含义。所以在我的回答中,我忽略了它们

这将问题转化为:

给定一组(绿色)点和一组三角形,报告任何三角形内的所有点。

我希望这就是你想要的

根据默菲定律,在每个小问题的背后都潜藏着一堆更大的问题,它们在努力摆脱困境。这里,第一个更大的问题是,如何测试一个点是否在三角形内。维基、谷歌等都表明,有各种各样的解决方案。对于给定的问题,我认为重心坐标系方法是一个好的(最好的)候选,因为我们必须对每个点进行重新测试,并且该方法允许计算每个三角形的一组参数,然后在每个点测试中重复使用。 第二个问题是,在给定K个绿点和N个三角形的情况下,在执行的测试数量方面,我们是否能比naive方法做得更好

  • 天真:
    #Tests=N*K
    (针对所有三角形测试每个点)。(我看不出O(N^3)是怎么来的,但问题的作者没有说N是什么)

  • 改进:尝试找到一种只针对三角形子集测试点的方法。子集是“可能”的三角形:
    #Tests=K*N'
    其中
    N'
    希望小于或等于
    N
    <代码>K在这里没有变化-毕竟我们需要查看每个点

因此,我提出一种扫描线算法作为(潜在)改进的解决方案: 查看问题中的图像,想象一条垂直线从左向右移动到图片上方,移动到下一个绿点。
现在,根据垂直扫描线在给定时刻的位置,只有与扫描线相交的三角形才是扫描线所在点命中测试的候选。这是我们要测试点的三角形子集

为了实现扫描线算法,我们需要先进行一些重新排序

  • 按x坐标以升序对所有绿点进行排序。(O(K logk))
  • 按x升序对每个三角形的所有三角形顶点进行排序
  • 按三角形最左侧点的x坐标对所有三角形进行排序。(O(N logn))
然后,对于每个绿点P: *放下所有完全在P左边的剩余三角形。 *选择所有剩余三角形,这些三角形从P的左侧开始但不结束。 (开放三角形) *对每个开放三角形测试P。 如果P包含在任何一个开放三角形中,则P是包含的。 虽然它比我预期的要长一点,但下面是我用大家最喜欢的语言Haskell实现的原型:


导入数据。列表
--虽然颜色是问题的一部分,但在解决方案中它们并没有真正的用途。
--数据颜色=红色|绿色衍生(显示,等式)
--数据顶点=顶点{loc::Point,col::Color}派生(显示,Eq)
数据点=点{x::Float,y::Float}派生(显示,等式)
数据三角形=三角形[点]导出(显示,等式)
数据重臂=重臂
{dt::Float——行列式。
,dy23::Float
,dx32::Float
,dy31::Float
,dx13::Float
,x3::浮点数
,y3::Float
}推导(显示,等式)
--从三角形中获取点列表。当然,这个列表的长度总是3。
三点::三角形->[点]
三点(三角形ps)=ps
--我们做一些排序(三角形和点),这是我们的
--排序(在点的x坐标上从左到右。)
leftToRight::点->点->排序
左向右p1 p2
|x p1三角形
LTR三角形(三角形点)=三角形$LTR排序点
--计算一个点相对于
--给定三角形的bary参数。
toBaryCoords::BaryParts->Point->(浮动,浮动,浮动)
烟草合作社=
(l1、l2、l3)
哪里
l1=(dy23 bp*(xP-x3 bp)+(dx32 bp*(y p-y3 bp))/dt bp
l2=(DY31bp*(xp-x3bp)+(dx13bp*(yp-y3bp))/dtbp
l3=1-l1-l2
--预先计算一些我们需要的值
Create the convex hull (CH) of the red points.
Check each of the green points is in the CH or not.
    If it is, there is a red triangle that contains that point.
    If it is not, there is no red triangle that contains the point.
Then, for each green point P: * drop all of the remaining triangles which are entirely to the left of P. * select all of the remaining triangles, which start but do not end to the left of P. (open triangles) * test P against each of the open triangles. P is contained if it is contained in any of those open triangles.