我正在使用一个图书馆(JavaScript-Voronoi https://github.com/gorhill/Javascript-Voronoi),它生成表示闭合多边形的线段数组。这些线段显示无序,无论是线段出现的顺序还是线段每端点的顺序。
(Edit: As noted in a comment below, I was wrong: the segments from the library are well-ordered. However, the question stands as written: let's assume that the segments do not have any ordering, as this makes it more generally useful.)
例如:
var p1 = {x:13.6,y:13.1}, p2 = {x:37.2,y:35.8}, p3 = {x:99.9,y:14.6},
p4 = {x:99.9,y:45.5}, p5 = {x:33.7,y:66.7};
var segments = [
{ va:p1, vb:p2 },
{ va:p3, vb:p4 },
{ va:p5, vb:p4 },
{ va:p3, vb:p2 },
{ va:p1, vb:p5 } ];
请注意第一个片段如何链接到最后一个片段(它们共享一个公共点)以及倒数第二个片段。保证每个段与另一个段恰好共享一端。
我想将其转换为点列表以生成正确的 SVG 多边形:
console.log( orderedPoints(segments) );
// [
// {"x":33.7,"y":66.7},
// {"x":13.6,"y":13.1},
// {"x":37.2,"y":35.8},
// {"x":99.9,"y":14.6},
// {"x":99.9,"y":45.5}
// ]
这些点是按顺时针顺序还是逆时针顺序并不重要。
以下代码是我想出的,但在最坏的情况下,它需要n^2+n
点比较。是否有更有效的算法将所有这些连接在一起?
function orderedPoints(segs){
segs = segs.concat(); // make a mutable copy
var seg = segs.pop(), pts = [seg.va], link = seg.vb;
for (var ct=segs.length;ct--;){
for (var i=segs.length;i--;){
if (segs[i].va==link){
seg = segs.splice(i,1)[0]; pts.push(seg.va); link = seg.vb;
break;
}else if (segs[i].vb==link){
seg = segs.splice(i,1)[0]; pts.push(seg.vb); link = seg.va;
break;
}
}
}
return pts;
}