如何解决重叠的三角形
| 我有一个三角形(下面是红色)。 (或2D三角形网格) 如何计算从第一个三角形减去第二个三角形(绿色)而得到的多边形(并细分它们)? (我正在使用Python,正在寻找我可以采用的方法的解释和伪代码,而不是不透明库的建议。(我目前使用gluTess*()
进行多边形的细分,但是对如何自己进行镶嵌细分会很有趣;我的紧迫问题实际上是布尔运算本身。)学习和理解该解决方案将是一件令人兴奋的事情。如果有任何区别,我的三角形总是逆时针缠绕。)
解决方法
让我们来看一些场景...
情况1:三角形不重叠(或切线但不重叠)
通过使用多边形中的点算法测试这种情况,以查看其中一个三角形的三个顶点中的任何一个位于另一个的内部或上方。
如果是案例1,则无需执行任何操作。
情况2:绿色三角形在红色三角形的内部。
通过使用多边形中的点算法来测试这种情况,以查看所有三个绿色顶点是否都在红色三角形内。另一种测试方法是查看绿色三角形的3个线段是否与红色三角形的3个线段相交;使用这样的算法进行交集(此外,还必须检查以确保多边形内至少有一个绿色顶点-只是要确保没有相交线不是因为您实际上遇到了情况1)。
现在,对于这种情况,从每个绿色顶点到每个红色顶点绘制一个线段(总共9个新线段)。如果这些新线段中的任何一个交叉到绿色三角形中,则将其删除(您可以通过对每个绿色三角形的边使用线段相交方法来进行检查)。现在,测试一下是否有剩余的新线段相互交叉;如果有两个,则消除一个,然后重新测试,直到不再有新的线段相互交叉为止。
情况3:绿色三角形与红色三角形重叠,其中绿色三角形的两侧进入红色三角形,并且也离开红色三角形。
通过检查是否有两个绿色的边与两个红色的边相交来测试这种情况。再次使用线段相交算法。
现在,在这种情况下,从每个交叉点(每个绿色边与红色边相交的地方)到每个红色顶点绘制一条线段。如果这些线段中的任何一条基本上重复了红色边缘,则将其删除。如果这些新线段中的任何一个交叉到绿色三角形中,则将其删除(您可以通过对每个绿色三角形的边使用线段相交方法来进行检查)。现在,测试一下是否有剩余的新线段相互交叉;如果有两个,则消除一个,然后重新测试,直到不再有新的线段相互交叉为止。
情况4:绿色三角形与红色三角形重叠,其中绿色三角形的两侧进入红色三角形,但它们并未将红色三角形留在另一侧。
通过检查是否有两个绿色面与一个红色面相交来测试这种情况(不一定每个面都必须是同一面)。再次使用线段相交算法。
现在,对于这种情况,从红色三角形内的绿色顶点(使用多边形中的点算法确定哪个绿色顶点在三角形内)到每个红色三角形顶点绘制一条线段。
情况5:绿色三角形与红色三角形重叠,其中绿色三角形的仅一侧进入红色三角形,而同一绿色侧退出红色三角形的另一侧。
通过检查是否有一个绿色边与两个红色边相交来测试这种情况。再次使用线段相交算法。
现在,在这种情况下,从每个交叉点(每个绿色边与红色边相交的地方)到每个红色顶点绘制一条线段。如果这些线段中的任何一条基本上重复了红色边缘,则将其删除。如果这些新线段中的任何一个交叉到绿色三角形中,则将其删除(您可以通过对每个绿色三角形的边使用线段相交方法来进行检查)。现在,测试一下是否有剩余的新线段相互交叉;如果有两个,则消除一个,然后重新测试,直到不再有新的线段相交。
希望您现在完成了!
,我敢肯定,您可以找到可以应用的通用多边形减法,修剪和三角剖分算法,但是由于您限于三角形,因此可以采用更简单的方法。
基本方法是扩展第二个(绿色)三角形的边缘,将它们视为无休止的线,然后将原始(红色)三角形最多拆分三遍,每个与红色三角形相交的绿色边缘一次,将保持在红色三角形之外。算法:
resultSet := {} // set of triangles
currentPoly := originalTriangle
for each edge E of secondTriangle:
if E intersects currentPoly (*):
Extend edge E to line L
Split currentPoly by L into outerPoly and otherPoly (**)
// outerPoly is on the side corresponding to the outside
// of secondTriangle (right side if going CCW)
resultSet += triangulatation of outerPoly (***)
currentPoly := otherPoly
if resultSet is empty:
resultSet := originalTriangle // no intersections
(*)
如果线段与多边形的任意一条边相交或完全包含在多边形中,则该线段与该多边形相交。对于此算法,最好将重合线视为不相交(因为不会发生分裂)。
(**)
用线分割凸多边形的算法
result := [[],[]] // two empty lists of points
intersectionCount = 0
for each point P in the polygon:
// each point is added to one of the result polygons
result[intersectionCount % 2] += P
E := edge between P and the next point Q
if E intersects L at R:
// each intersection point is added to both result polygons
if R is not equal to P:
result[intersectionCount % 2] += R
intersectionCount += 1
if R is not equal to Q:
result[intersectionCount % 2] += R
(***)
externalPoly始终是三角形或四边形,因此对三角剖分是微不足道的。
,此问题的第一步是将绿色三角形放在其上之后,将剩下的红色三角形区域隔离开。
一旦拥有了这些不同的形状(在上面的示例中,一个4边形和一个3边形),您将从“需要计算”列表中删除所有3个边的形状(因为这些已经是三角形)。
接下来,应该只留下一个形状或不包含任何形状(将一个三角形重叠在另一个顶部之后,只能有1个或两个形状),但实际上,如果您想采用更通用的方法,可以将其应用于所有形状您已经离开了(在三角形之后)。现在,将您拥有的每个形状的折点隔离开,并按顺时针或逆时针顺序对其进行排序。从顶点1开始,然后转到顶点1 + 2并尝试画一条线以产生一个三角形(检查边界问题,例如在原始三角形的边界之外画一条线)。如果遇到边界问题,请向上移动并尝试下一个顶点,尝试绘制一条线到顶点1 + 3。关键是要跳过最邻近的顶点,并在紧接该顶点之后的顶点上画一条线,然后尝试所有超出该顶点的顶点,直到再次邻接为止。在这种情况下,根据定义,您正在构造三角形(因为使用此方法必须具有3个边)。
生成三角形后(通过从一个顶点到另一顶点成功绘制一条线),重新计算其余区域,您必须将其拆分为三角形并重复该过程,直到仅剩下三角形为止。
这是我制作来展示该方法的(非常糟糕的)动画gif:
,也许是一个愚蠢的方法,但是已经很晚了,经过10个小时的工作,我的大脑超负荷了:
将所有三角形合并为一个多边形(可能有孔)。
对多边形进行三角剖分。
对于每个产生的三角形,检查它是否仅属于红色三角形。
合并和三角剖分的多边形的示例:
一个三角形完全在另一个三角形内的示例:
进行三角剖分时,诀窍是重用完全封闭的三角形中的任何点。您还将具有一组“硬”线(以实线绘制),它们代表现有三角形的边的线段,而有“软”线(以虚线绘制),您必须通过三角测量来确定。
我很确定有更好的方法可以做到这一点,但是您可以...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。