Geometry 在重叠处分割三角形

Geometry 在重叠处分割三角形,geometry,2d,Geometry,2d,我有一个三角形(红色,下图)。(或三角形的二维网格) 如何计算从第一个三角形减去第二个三角形(绿色)后得到的多边形(并依次细分它们) (我正在使用Python,我正在寻找一种我可以采用的方法的解释和伪代码,而不是不透明库的建议。(我目前用于多边形的细分,但我自己如何进行细分的解释会很有趣;但我迫切的问题是布尔运算本身。)学习和理解这个解决方案将是令人兴奋的。我的三角形总是逆时针旋转的,如果这有什么区别的话。)这个问题的第一步是在你把绿色三角形放在红色三角形上之后,隔离红色三角形的剩余区域 一旦

我有一个三角形(红色,下图)。(或三角形的二维网格)

如何计算从第一个三角形减去第二个三角形(绿色)后得到的多边形(并依次细分它们)


(我正在使用Python,我正在寻找一种我可以采用的方法的解释和伪代码,而不是不透明库的建议。(我目前用于多边形的细分,但我自己如何进行细分的解释会很有趣;但我迫切的问题是布尔运算本身。)学习和理解这个解决方案将是令人兴奋的。我的三角形总是逆时针旋转的,如果这有什么区别的话。)

这个问题的第一步是在你把绿色三角形放在红色三角形上之后,隔离红色三角形的剩余区域

一旦您有了这些不同的形状(在上面的示例中,一个4边形状和一个3边形状),您将从“需要计算”列表中删除所有3边形状(因为它们已经是三角形)


接下来,您应该只剩下一个形状或没有形状(在一个三角形与另一个三角形重叠后,您只能有一个或两个形状),但实际上,如果您想要一个更通用的方法,您可以将此应用于剩下的所有形状(在三角形之后)。现在分离出每个形状的垂直方向,并给它们一个顺时针或逆时针的顺序。从顶点1开始,然后转到顶点1+2并尝试绘制一条线以生成三角形(检查边界问题,例如在原始三角形的边界之外绘制一条线)。如果遇到边界问题,请上移并尝试下一个顶点,尝试绘制一条到顶点1+3的线。关键是你要跳过最相邻的顶点,画一条线到紧靠该顶点之后的顶点,然后尝试所有超出该顶点的垂直,直到你再次碰到“邻接”。在这种情况下,根据定义,您正在构造三角形(因为使用这种方法,三角形必须有三条边)

生成三角形后(通过成功绘制从一个顶点到另一个顶点的直线),重新计算必须拆分为三角形的区域的其余部分,并重复此过程,直到只剩下三角形为止

下面是我制作的一个(无可否认很糟糕的)动画gif来展示这个方法:
也许这是一个愚蠢的方法,但是已经很晚了,而且我的大脑在工作了10个小时后已经超负荷了:

  • 将所有三角形合并为多边形(可能有孔)
  • 对多边形进行三角剖分
  • 对于每个结果三角形,检查它是否仅属于红色三角形
  • 合并和三角化多边形的示例:

    当一个三角形完全位于另一个三角形内时的示例:

    当三角剖分时,诀窍是重用完全封闭三角形中的任何点。您还将拥有一组“硬”线(绘制实线),它们表示现有三角形边的线段,以及必须通过三角测量确定的“软”线(绘制虚线)


    我很确定有更好的方法可以做到这一点,但你可以这样做……

    我相信你可以找到通用的多边形减法、剪裁和三角剖分算法,但由于你只限于三角形,所以更简单的方法适用

    基本方法是延伸第二个(绿色)三角形的边,将其视为无休止的线,然后将原始(红色)三角形拆分为三次,与红色三角形相交的每个绿色边一次,保留红色三角形外部的部分。算法:

    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
    

    (***)
    外部始终是三角形或四边形,因此三角化非常简单。

    让我们来看看一些场景

    情况1:三角形不重叠(或相切但不重叠)

    使用a测试此情况,以查看其中一个三角形的三个顶点中是否有任何一个位于另一个三角形的内部或之上

    如果我们在案例1中,我们不需要做任何事情

    案例2:绿色三角形位于红色三角形的内部

    通过使用多边形中的点算法来测试这种情况,以查看所有三个绿色顶点是否都位于红色三角形的内部。另一种测试方法是查看绿色三角形的3条线段中是否有任何一条与红色三角形的3条线段中的任何一条相交;使用这样的交叉点(此外,您还必须检查以确保多边形内部至少有一个绿色顶点-以确保缺少相交线不是因为您实际遇到情况1)

    现在,在本例中,从每个绿色顶点到每个红色顶点绘制一条线段(总共9条新线段)。如果这些新线段中的任何一条与绿色三角形相交,则将其删除(您可以对绿色三角形的每条边使用线段相交方法进行检查)。现在,测试剩余的新线段是否相互相交;如果有两条线段相交,则删除一条,然后重新测试,直到不再有新线段相交

    案例3:绿色三角形与红色三角形重叠,绿色三角形的两侧进入红色三角形,同时离开红色三角形

    通过检查两条绿色边是否与两条红色边相交来测试这种情况。再次使用线段相交算法

    现在,在这个例子中,画一条线