快速计算三角形与单位平方的交叉区域

时间:2014-03-25 12:02:07

标签: geometry polygon intersection

在我目前的项目中,我需要计算三角形的交叉区域和无限网格中的单位正方形。

enter image description here

对于每个三角形(由三对浮点数给出),我需要知道它与它相交的每个方格共有的区域(在区间(0,1]中)。

现在我将两者(三角形和正方形)转换为多边形,并使用Sutherland-Hodgman polygon clipping计算交叉点多边形,然后将其用于calculate its area

此方法现在显示为我的应用程序中的性能瓶颈。我想更专业(分析)算法会更快。是否有针对此问题的标准解决方案,或者您有任何想法吗?我只需要区域,而不是交叉点的形状。

4 个答案:

答案 0 :(得分:2)

你的多边形是凸的。凸多边形的算法比一般多快。我已经成功使用了O'Rourke算法(code from his book here,我相信存在良好的描述)。请注意,某些值可能会为您的方块预先计算。

如果您的多边形不总是相交,那么您可能首先检查与分离轴方法相交的事实。

另一种选择 - Liang-Barski algorithm用于按正方形剪切每个三角形边缘。

修改:您可以使用Amanatides and Woo example in grid traversal section here({{3}})

的算法快速找到三角形边的所有交点

答案 1 :(得分:2)

要以高性能处理此任务,我建议对其进行一些修改 Vatti线扫描剪辑。 http://en.wikipedia.org/wiki/Vatti_clipping_algorithm

从三角形的最小Y顶点步进,可以执行以下步骤:

  1. 按Y坐标排序顶点
  2. 步骤Y更高到MIN(nextVertex.Y,nextGridBottom)
  3. 计算网格与边缘的交点。
  4. 收集当前的梯形
  5. 从步骤2开始重复,直到具有最高Y坐标的顶点。
  6. 如果需要,按X坐标分割梯形。
  7. 这里是X方向的梯形化的例子 http://www.personal.kent.edu/~rmuhamma/Compgeometry/MyCG/PolyPart/polyPartition.htm

    说明了线扫描算法的主要思想。祝好运。

答案 2 :(得分:2)

你没有提到你想要的精度。如果您正在寻找分析方法,请忽略此答案,但如果您只想进行抗锯齿,我建议Kiia Kallio scanline edge-flag algorithm。我已经使用了几次,它非常快,可以设置非常高的精度。如果你有兴趣,我有一个java实现。

答案 3 :(得分:2)

您可以利用常规的正方形图案。

我假设这是一个瓶颈的原因是因为你必须等待你的算法找到所有正方形与任何三角形相交并计算所有交叉区域。因此,我们将计算所有区域,但是为了从最少的计算中获取最多信息,每个三角形都会批量计算。

首先,正如其他人所解释的,对于三角形的每个边缘,您可以找到边缘经过的正方形序列,以及它与正方形的每个垂直或水平边缘交叉的点。

为所有三个方面执行此操作,保留您遇到的所有方块的列表,但每个方块只保留一个副本。将正方形存储在多个列表中可能很有用,这样给定行上的所有正方形都保存在同一列表中。

当你发现所有正方形时,三角形的边缘都会通过,如果其中两个正方形位于同一行,那么两个不在列表中的正方形完全在三角形内,所以这些方格的100%都被覆盖了。

对于其他正方形,面积的计算可以取决于三角形在正方形(0,1,2或3)中的顶点数量,以及三角形边缘与正方形边相交的位置。您可以在一些铅笔纸图纸中总结所有案例,并为每个案例进行计算。例如,当三角形边缘穿过正方形的两边时,正方形的一角在"外面"边缘的一侧,那个角是一个小三角形的一个角落"切断"通过较大三角形的边缘;使用方形边上的交点来计算小三角形的面积,并从正方形区域中扣除它。如果两个点而不是一个是"在"之外,你有一个梯形,其两个基本长度是从交点出发的,其高度是方形的宽度;从广场上扣除它的面积。如果三个点在外面,则扣除正方形的整个区域,然后添加小三角形的区域。

正方形内的大三角形的一个顶点,该角度外的正方形的三个角:从剩下的角线到三角形的顶点画一条线,所以你有两个小三角形,扣除整个正方形和添加这些三角形'区域。角度外的正方形的两个角,向顶点绘制线以获得三个小三角形等。

我这样做是为了让你总是假设你从正方形的整个区域开始,并根据三角形边缘与正方形相交的方式将面积减少一些。这样,在三角形的边缘与正方形相交两次以上的情况下 - 例如一条边切割正方形的一个角,另一条边穿过另一个角,你可以直接扣除被切割的区域。第一个边缘,然后扣除第二个边缘切断的区域。

这将是相当多的特殊情况,尽管你可以利用对称性;例如,您不必编写"在一个角落切掉一个三角形的完整计算"四次。

如果您只是将某人的凸多边形库从架子上取下来,您会编写更多代码,并且您将需要测试其中的生活日光,以确保您没有这样做。忘记对任何情况进行编码,但是一旦你开始工作,它就不应该花费更多的精力来使它合理地快速。