更精确的顺时针顶点排序

时间:2016-06-12 21:36:03

标签: javascript algorithm sorting vertices

我使用了很少的算法进行顺时针顶点排序,但仍然无法排序,因为它应该排序。

poly总是正方形,切割相同大小的小方块(让我们将它们命名为块)。所以说我有6x6方块,大块是1x1。更具体地说:square具有顶点:[0,0],[5,0],[5,5],[0,5]。 如果我将在位置[0,0]处切掉块(就像从[0,0]到[1,1]的顶点上的较小正方形所做的那样),正方形看起来像这样:

Beautiful chunk intersection

他的顶点现在是:[0,1],[1,1],[1,0],[5,0],[5,5],[0,5]

没关系。但是,让我们做更多的交叉点。我不会在位置[1,0]显示第二个块的交叉点因为一切都很好。现在,如果我要进行第三次交叉,比如位置[0,1],它看起来像这样:

Ugly intersection

当然,它应该是这样的:

enter image description here

正如您所看到的,它只是排序失败,它在[0,2]

之前对顶点[1,2]进行排序

我想知道当我添加诸如检查质心距离之类的东西时它是否会很好。嗯..这是这个排序的代码:

function (a, b) {

    var distance1 = Math.sqrt(Math.pow(a.x - centroid.x, 2) + Math.pow(a.y - centroid.y, 2));
    var distance2 = Math.sqrt(Math.pow(b.x - centroid.x, 2) + Math.pow(b.y - centroid.y, 2));
    var a1 = Math.acos((a.x - centroid.x) / distance1);
    var a2 = Math.acos((b.x - centroid.x) / distance2);

    if (a.y > centroid.y)
        a1 = Math.PI + Math.PI - a1;

    if (b.y > centroid.y)
        a2 = Math.PI + Math.PI - a2;

    return a1 - a2;

}

和质心:

function (vertices) {
    var 
        x = 0,
        y = 0,
        pointCount = vertices.length;

    for (var i = 0; i < pointCount; i++){
        x += vertices[i].x;
        y += vertices[i].y;
    }

    x = x/pointCount;
    y = y/pointCount;

    return new vec2(x, y);
}

2 个答案:

答案 0 :(得分:1)

我没有真正检查你的比较函数中是否有任何错误,但它过于复杂。你可以使用Math.atan2来获得两点之间的角度。你的功能应该是

function(a, b) {
    return Math.atan2(a.y - centroid.y, a.x - centroid.x)
         - Math.atan2(b.y - centroid.y, b.x - centroid.x);
}

答案 1 :(得分:0)

好的,我在clockWise排序后实现了新功能,即角度优化。整个算法的工作原理如下:

super algorithm

如果有任何吸烟,请随意

这是角度优化的代码:

for (var i = 1; i < vertices.length; i++) {
        var a = vertices[i - 1];
        var b = vertices[i];
        var j = i;

        do {
            var distanceAngle = Math.abs(Math.atan2(a.y - b.y, a.x - b.x));
            if (
                distanceAngle == Math.PI / 2 ||
                distanceAngle == Math.PI ||
                distanceAngle == 3 * Math.PI / 2 ||
                distanceAngle == 2 * Math.PI ||
                distanceAngle == 0
            )
            {
                var tmp = vertices[i];
                vertices[i] = vertices[j];
                vertices[j] = tmp;
                break;
            }
            j++;
            b = vertices[j];
        } while (j < vertices.length);
    }