订购地理点以便将它们连接到关闭区域的算法

时间:2015-08-15 09:19:00

标签: algorithm geolocation geospatial graph-theory graph-algorithm

我有地理位置(位置),这意味着:带有纬度/经度的OOP对象+我需要对它们进行处理,保持众所周知的位置空间关系 - 50N,15E是右上角到49N,14E ...... enter image description here

他们在阵列中的顺序是随机的。我需要以这种方式对它们进行排序,其他众所周知的标准地理方法,即从数组中按顺序获取点并将它们连接到线,将导致关闭周围的线:

enter image description here

例如,如果我将这个应用于我得到的点的当前随机顺序:

enter image description here

问题在于排序阶段的algorithm / pseudo。为简单起见,我们假设Java(ArrayList,没有内存管理......)。

1 个答案:

答案 0 :(得分:1)

开始是找到中心点,获取每个点相对于中心点的极坐标(=方向和距中心点的距离),然后根据这些坐标对点进行排序。最简单的只是看方向。运行Javascript代码段以查看正在运行的简单版本(我不知道Java) 进一步改进:避免距离大跳跃。您也可以尝试几个中心点,并使用导致最短线的点。

function geoOrder(points) {
    var center = {x: 0, y: 0};
    for (var i in points) {
        center.x += points[i].x;
        center.y += points[i].y;
    }
    center.x /= points.length;
    center.y /= points.length;
    paintDot(canvas, center.x, center.y, 5, "red");
    for (var i in points) {
        var dx = points[i].x - center.x;
        var dy = points[i].y - center.y;
        points[i].a = Math.atan2(dx, dy);
        points[i].d = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
    }
    points.sort(polarSort);
    for (var i in points) {
        delete points[i].a;
        delete points[i].d;
    }

    function polarSort(p, q) {
        if (p.a < q.a) return -1
        else if (p.a > q.a) return 1
        return 0;
    }
}

// PREPARE CANVAS
var canvas = document.getElementById("canvas");
canvas.width = 440; canvas.height = 346;
canvas = canvas.getContext("2d");

// RUN FUNCTION ON TEST DATA
var points = [{x:38,y:136},{x:151,y:96},{x:152,y:282},{x:172,y:270},{x:173,y:30},{x:181,y:177},{x:200,y:179},{x:273,y:125},{x:295,y:59},{x:350,y:172},{x:361,y:216},{x:370,y:190}];
geoOrder(points);

// SHOW RESULT ON CANVAS
for (var i in points) {
    if (i > 0) paintLine(canvas, points[i-1].x, points[i-1].y, points[i].x, points[i].y, 1, "blue")
    else paintLine(canvas, points[points.length-1].x, points[points.length-1].y, points[i].x, points[i].y, 1, "blue");
    paintDot(canvas, points[i].x, points[i].y, 5, "black");
}
function paintDot(canvas, x, y, size, color) {
canvas.beginPath();
canvas.arc(x, y, size, 0, 6.2831853);
canvas.closePath();
canvas.fillStyle = color;
canvas.fill();
}
function paintLine(canvas, x1, y1, x2, y2, width, color) {
canvas.beginPath();
canvas.moveTo(x1, y1);
canvas.lineTo(x2, y2);
canvas.strokeStyle = color;
canvas.stroke();
}
<BODY STYLE="margin: 0; border: 0; padding: 0;">
<CANVAS ID="canvas" STYLE="width: 254px; height: 200px; background-color: #EEE;"></CANVAS>