多个三角形交叉点

时间:2015-08-27 12:05:40

标签: algorithm intersection triangulation

我在2D空间中有一系列点。我试图从这些点创建尽可能多的三角形,但是:

  • 所有三角形必须有效(a< b + c和b< a + c和c< a + b)
  • 没有三角形可以包含一个点(只是它们的顶点)
  • 没有三角形可以与任何其他三角形相交

通过交叉,我的意思是三角形不能在另一个三角形内,而三角形的一边不能与另一个三角形交叉(但它们可以共享边缘)。

我认为我的算法没有问题(为简单而假):

newTriangles := false
do:
    newTriangles := false
    for a in points:
        for b in points:
            if b = a:
                continue

            for c in points:
                if c = a or c = b:
                    continue
                // So now we have every combination of a, b and c

                // Now the tests
                if not valid_triangle(a, b, c) then continue

                containsPoint := false
                for p in points:
                    if p = a or p = b or p = c:
                        continue

                    if contains(a, b, c, p):
                        containsPoint := true // first 3 params are the vertices of the triangle, the 4th is the point for test

                if containsPoint:
                    continue

                // Now the last test, the existing triangle intersection
                intersects := false
                for triangle in triangles:
                    if intersects(triangle, a, b, c):
                        intersects := true

                // It passed every test, it can be a triangle
                if not intersects:
                    triangles.add(new triange(a, b, c))
                    newTriangles := true
while newTriangles

这会连接一些三角形,但每个三角形都与其他三角形隔离。我想交叉检查会返回true。现在来说明我的问题好一点: enter image description here

所以第一步发生了,但第二步不会发生,它会保持每个三角形(有时是单个点)被隔离。但是,如果我更改交叉检查代码,则此代码将永远不会停止。可能是什么解决方案?

编辑:

这是我的交叉算法(这是真正的Java代码):

public static boolean intersects(Vector2f a, Vector2f b, Vector2f c, Triangle other) {
        boolean x = (Line.segmentIntersects(a, b, other.a, other.b) || Line.segmentIntersects(b, c, other.a, other.b)) ||
                    (Line.segmentIntersects(a, b, other.a, other.b) || Line.segmentIntersects(a, c, other.a, other.b)) ||
                    (Line.segmentIntersects(a, c, other.a, other.b) || Line.segmentIntersects(b, c, other.a, other.b));

        boolean y = (Line.segmentIntersects(a, b, other.b, other.c) || Line.segmentIntersects(b, c, other.b, other.c)) ||
                    (Line.segmentIntersects(a, b, other.b, other.c) || Line.segmentIntersects(a, c, other.b, other.c)) ||
                    (Line.segmentIntersects(a, c, other.b, other.c) || Line.segmentIntersects(b, c, other.b, other.c));

        boolean z = (Line.segmentIntersects(a, b, other.a, other.c) || Line.segmentIntersects(b, c, other.a, other.c)) ||
                    (Line.segmentIntersects(a, b, other.a, other.c) || Line.segmentIntersects(a, c, other.a, other.c)) ||
                    (Line.segmentIntersects(a, c, other.a, other.c) || Line.segmentIntersects(b, c, other.a, other.c));

        return (x || y || z ||
                other.contains(a) || other.contains(b) || other.contains(c));
    }

段相交是:

public static boolean segmentIntersects(Vector2f ps1, Vector2f pe1, Vector2f ps2, Vector2f pe2) {
        return (Line2D.linesIntersect(ps1.x, ps1.y, pe1.x, pe1.y, ps2.x, ps2.y, pe2.x, pe2.y));
}

并包含:

private static float sign(Vector2f p1, Vector2f p2, Vector2f p3) {
        return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
    }
public static boolean contains(Vector2f a, Vector2f b, Vector2f c, Vector2f p) {
        boolean b1, b2, b3;
        b1 = sign(p, a, b) < 0.0f;
        b2 = sign(p, b, c) < 0.0f;
        b3 = sign(p, c, a) < 0.0f;
        return ((b1 == b2) && (b2 == b3));
    }

1 个答案:

答案 0 :(得分:1)

我不能给你完整的工作代码,但我可以给你一些建议和一些可能的错误点:

首先请注意,在intersects方法中,您正在进行大量冗余检查!

boolean x = (Line.segmentIntersects(a, b, other.a, other.b) ||
            (Line.segmentIntersects(a, b, other.a, other.c) ||
            (Line.segmentIntersects(a, b, other.b, other.c);

boolean y = (Line.segmentIntersects(a, c, other.a, other.b) ||
            (Line.segmentIntersects(a, c, other.a, other.c) ||
            (Line.segmentIntersects(a, c, other.b, other.c);

boolean z = (Line.segmentIntersects(b, c, other.a, other.b) ||
            (Line.segmentIntersects(b, c, other.a, other.c) ||
            (Line.segmentIntersects(b, c, other.b, other.c);

你需要的一切!在这里,您要检查三角形abc的每一边是否与另一个三角形的任何一边相交。

在您的回程中,您还可以通过不检查other.contains(a) || other.contains(b) || other.contains(c)来节省一些时间。由于other被选为有效三角形,我们可以假设other不包含三角形abc中的任何点。

如果您的代码永远在运行,那么我愿意打赌,因为您没有检查三角形abc 是否等于另一个三角形。如果确实如此,那么你应该停止查看abc,因为它已经被添加了!

请注意,根据您的伪代码,您的代码确实应该暂停,因为您只使用for循环,应该保证终止。也许您应该检查这些循环的退出条件:)

希望这有帮助!