閉じた多角形を表す線分の配列を生成するライブラリ ( JavaScript-Voronoi ) を使用しています。これらのセグメントは、セグメントが表示される順序とセグメントの各端点の順序の両方で、順不同で表示されます。
(編集:以下のコメントに記載されているように、私は間違っていました:ライブラリのセグメントは適切に順序付けられています。ただし、質問は書かれているとおりです:セグメントには順序付けがないと仮定しましょう。これにより、より一般的に便利になります。 .)
例えば:
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 } ];
最初のセグメントが最後のセグメント (共通点を共有する) と、最後から 2 番目のセグメントにどのようにリンクしているかに注意してください。すべてのセグメントがちょうど 1 つの他のセグメントと端を共有することが保証されています。
これをポイントのリストに変換して、適切な 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;
}