我正在使用Javascript编写一个使用谷歌地图的应用程序,并根据最近的腿计算一系列腿之间的完整路线。
说我在地图上有4条腿,每条腿都有一个开始和结束纬度和经度。用户指定哪条腿是路线的起点和终点。一条腿的每一端只能连接另一条腿开始。然后那条腿的末端连接到另一条腿开始,依此类推。该代码根据它可以找到的最近的腿确定哪些腿开始连接。
例如这样的东西(虚线是腿):
start-----------end <-connector-> start----------end <-connector-> start----------end
我有一个所有腿部坐标的数组,我想对这个数组进行排序,以便它遵循正确的连接进程。然后我可以利用数组通过线性循环生成连接器。
数组看起来像这样:
[
{start_lat: X, start_lng: X, end_lat: X, end_lng: X},
{start_lat: X, start_lng: X, end_lat: X, end_lng: X},
]
那些将是内在的腿。然后我将存储在变量中的外腿(两条腿是整个路线的起点和终点):
var start = {end_lat: X, end_lng: X}
var end = {start_lat: X, start_lng: X}
作为一个例子,它可能最终会像:
start -> array[0] -> array[1] -> end
或者它最终会像:
start -> array[1] -> array[0] -> end
算法需要根据起始腿end_lat,end_lng和结束腿end_lat,end_lng对数组进行排序。
最终结果将是一条以最短路径连接在一起的大路。
我正在努力想出一种编写排序算法的方法,该算法考虑了这些独特的因素。
很难把它说成文字,而且我不确定如何帮助它更清晰,但如果我能想到任何有用的东西,我会编辑这篇文章。感谢。
修改:
这是我正在谈论的图片:
黑线是腿,红线是我将腿坐标数组排序到正确顺序后需要生成的连接器。生成连接器不是这个算法的一部分,但它只是我想要完成的一个例子,所以你可以理解大局。如您所见,腿之间存在间隙,没有任何坐标重叠。
答案 0 :(得分:2)
你可以这样做:
var start = { end_lat: 1, end_lng: 1 },
end = { start_lat: 4, start_lng: 4 },
coordsBetween = [
{ start_lat: 2, start_lng: 2, end_lat: 3, end_lng: 3 },
{ start_lat: 1, start_lng: 1, end_lat: 2, end_lng: 2 },
{ start_lat: 3, start_lng: 3, end_lat: 4, end_lng: 4 }
];
function orderedCoords(start, coords) {
var result = [],
point = start;
while (point = coords.filter(function (item) {
return item.start_lat === point.end_lat
&& item.start_lng === point.end_lng;
})[0]) {
result.push(point);
}
return result;
}
console.log(orderedCoords(start, coordsBetween));
基本上我们会发现下一个point
从start
结束开始,让point
成为下一个start
,直到没有匹配为止,在每一步我们推动这一点进入result
。
编辑:
这可以起点和终点的坐标 重叠,但我的没有,他们之间有很大的差距 我需要在它们之间生成“连接器”......
我通过使用algorithm to calculate the closest point寻找重叠坐标来扩展我的第一个想法。
var start = { end_lat: 1, end_lng: 1 },
end = { start_lat: 4, start_lng: 4 },
segments = [
{ start_lat: 2, start_lng: 2, end_lat: 3, end_lng: 3 },
{ start_lat: 1, start_lng: 1, end_lat: 2, end_lng: 2 },
{ start_lat: 3, start_lng: 3, end_lat: 4, end_lng: 4 }
];
function orderedSegments(start, segments) {
var result = [],
segment = start,
i;
while ((i = indexOfClosestSegment(segment, segments)) !== -1) {
result.push(segment = segments.splice(i, 1)[0]);
}
return result;
}
function indexOfClosestSegment(segment, segments) {
var i = 0,
len = segments.length,
segIndex = -1,
tempDistance, smallestDistance;
for (; i < len; i++) {
if (
(tempDistance = distanceBetween(segment, segments[i])) < smallestDistance
|| typeof smallestDistance === 'undefined') {
smallestDistance = tempDistance;
segIndex = i;
}
}
return segIndex;
}
function distanceBetween(segmentA, segmentB) {
return Math.sqrt(
Math.pow(segmentB.start_lat - segmentA.end_lat, 2)
+ Math.pow(segmentB.start_lng - segmentA.end_lng, 2)
);
}
console.log(orderedSegments(start, segments));
请注意,这些点是地理坐标,您需要使用a 球面距离算法,而不是平凡的毕达哥拉斯。我认为通用汽车 为其数据结构提供了这样的辅助函数;当然 该算法仍然可以使用不同的distanceBetween 实现。 - @Bergi
答案 1 :(得分:0)
我认为DFS是好的并且将访问的有序腿列表转移到下一个递归。 并且在每次递归中选择最后一条腿,并对每条未经检查的腿进行递归。