8

複数のポイントを持つポリゴンがあり、新しいポイントを追加する必要があります。既存のポイントは配列に格納されます。

var points = [
    {x: 0, y:0},
    {x: 100, y: 0},
    {x: 100, y: 100},
    {x: 0, y: 100}
];

newPointこれを追加するアレイの位置をどのように決定しますか?

試行:既存のすべてのポイントを反復処理しnewPoint、それらからの距離を計算し、既存のポイントを、からの距離の昇順で、これらのポイントのインデックスを含む配列に並べ替えましたnewPoint

私の現在の試みの方法に従って、次のステップは、2つの最も近いポイントが隣接しているかどうかを確認することです。newPointそうである場合は、それらの間にpoints配列を追加します。それらが隣接していない場合、私はここでちょっと立ち往生しています:) 2つのポイントが隣接しているかどうかをどのように確認しますか?

どんな助けでも大歓迎です!

jsfiddle: http: //jsfiddle.net/y3kmm/


順序が重要な理由は、シェイプは通常時計回りに描画されるためです。これは、青いポリゴンの正しい場所にポイントが追加されたjsfiddleと、points配列の最後にポイントが追加された赤いポリゴンのjsfiddleです。

jsfiddle: http: //jsfiddle.net/TyQXV/

4

4 に答える 4

4

前に述べたように、並べ替えを使用してプログラムの複雑さを実際に大きくする必要はありません。単純に 2 つの初期点を保存し、それらを最も近いと見なし、他の点を反復するときにそれらを置き換えます。

ただし、問題には複数の解決策があります。さらに制約を定義する必要があります。

たとえば、正方形を形成する 4 つの点を考えてみましょう。

·-------·
|       |
|       |
|       |
·-------·

次に、ポリゴン内のランダムな位置にポイントを追加します。

·-------·
|       |
| ·     |
|       |
·-------·

それでも、ポリゴンの凸面を維持する可能性のある順序は 2 つ以上あります。

·-------·
 \      |
  ·     |
 /      |
·-------·

·   ____·
|\ /    |
| ·     |
|       |
·-------·
于 2012-12-24T20:58:34.130 に答える
3

では、ポリゴンを詳しく見てみましょう。

テッド

私たちは彼をテッドと呼びます。テッド(または一般的に多角形)が点を見ると、彼はそれを自分の中に同化させようとします。そして同化のために、彼は彼の多くの側面の1つに手を差し伸べてポイントをつかむという名誉を与えることにしました. 現在、テッドはもっと重要なことで忙しいので、両陣営はどちらが善行を行うかを決める必要があります。もう一度言います。側面

ここに画像の説明を入力

ほら、テッドの近くにポイントがあり、すぐにそれが悪意を持って消費されることに幸いなことに気づいていません. では、テッドの陣営は、どちらがポイントを獲得するかをどのように決定するのでしょうか? まあ、それは公正なゲームである必要があります。そこから点までの垂直距離が最短だと感じた側がやります。最短垂直距離

ここに画像の説明を入力

同化完了!

心に留めておくべきもう 1 つのことは、Ted のようなポリゴンは同化よりも生存を重視するということです。点からの垂直距離が最も短い側は、他の側を通り抜けない場合にのみ同化を開始します。したがって、同化が有効な陣営のみが考慮されます。そうしないと、悪いことが起こります。

ここに画像の説明を入力

私の不必要な演説には、2 つの重要なポイントがあります。

  • ポイントを追加するは、ポイントからの垂直距離が最短である必要があります。
  • ポイントからの垂直距離が最短であることは別として、この側へのポイントの追加は有効である必要があります。これは重要です。結局のところ、ポリゴンの大量殺人を犯したくありません。

それで、ここにいくつかの疑似コードがあります。

For each side S in polygon P
Do
    d := perpendicularDistanceFromSide(S, point);
    If d is less than shortestPerpendicularDistance
    Do
        If additionIsValid(S, point, P)
        Do
            shortestPerpendicularDistance := d;
            index = S.index;
        End If
    End If
End For

側面からの垂直距離を見つけるのは簡単です。

var perpendicularDistance = function(side, point) {
    //Find direction vector of side
    var dir = {x: side.p2.x - side.p1.x, y: side.p2.y - side.p1.y};
    var m = Math.sqrt(dir.x*dir.x + dir.y*dir.y);
    if(m !== 0) {
        d.x = d.x/m;
        d.y = d.y/m;
    }

    //Find position vector of point, from side
    var pVec = {x: point.x - side.p1.x, y: point.y - side.p1.y};

    //Absolut of cross product of dir and pVec. 
    //It's essentially |pVec|*Sin(q), q is the angle between
    //dir and pVec.
    return Math.abs(dir.x*pVec.y - dir.y*pVec.x);
};

では、妥当性を見てみましょう。多角形にポイントを追加した後、新しい辺が他の辺のいずれかを通過した場合、小さな男は終わりです。アルゴリズムがこれを考慮していることを確認する必要があります。

これには 2 つのバージョンを考えました。安いものと高いもの。

方法 1 :

ポリゴンに凹みがほとんどまたはまったくない場合、この方法は完全に機能します。このメソッドは、新しい辺が古い辺に隣接する辺と交差しないことのみをチェックします。

側があるとしましょうS。隣接する 2 つの辺はSprevSnextです。2 つの新しい面はS1pS2pです。S1pと共通Sprev点があります。と共通点があります。S.p1S2pSnextS.p2

この方法によれば、追加は次の間に交差がない場合にのみ有効です。

  • SprevS2p
  • SnextS1p

したがって、この方法は拒否に対して機能します。交点が見つからない場合、側Sは有効にポイントを追加できます。

方法 1 のデモ

方法 2 :

方法 1 は、多角形の凹みが大きくなると失敗します。そのため、ポイントの追加が有効であることを確認するために、さらにチェックを行う必要があります。

この方法は実際には方法 1 の拡張です。ペアSprevS2p、およびSnextS1p交差していないことを確認した後、新しい辺が多角形の他のすべての辺と交差しているかどうかを確認します (もちろんSprevとは別Snextとして)。

すべての側面がチェックされた後、追加が拒否されない場合、この追加が有効であると完全に確信しています。

問題は、拒否は十分に迅速に行われますが、受け入れられるまでには長い時間がかかり、この方法は非常に高価になることです。

さらに、複雑さは多角形の辺の数に依存します。ポリゴンの複雑さが増すにつれて、有効性の確認に時間がかかります。

方法 2 デモ

線分の交差をチェックするために使用したアルゴリズムは、2 つの線分が交差する場所をどのように検出しますか? . それは完全に素晴らしいです。

そして、それは私が持っているすべてです。これはそれを行う1つの方法です、私は言わなければなりません。まだ私を驚かせていない別のより良い方法があるかもしれません。テッドをひどく気にかけなかったことを願っています。また、良い質問をしてくれてありがとう、楽しかったです。

于 2012-12-25T17:08:20.917 に答える
2

あなたの計算では、あなたが経験している問題は解決しないと思います。たとえば、次の 2 つのポリゴンを考えてみましょう。

var poly3 = new Kinetic.Polygon({
    x: 200,
    y: 100,
    points: [0,25,25,0,150,100,75,125],
    fill: 'green',
    stroke: 'black',
    strokeWidth: 0,
    name: 'poly',
    draggable: false
});
group.add(poly3);

var poly4 = new Kinetic.Polygon({
    x: 300,
    y: 100,
    points: [0,25,25,0,75,125,150,100],
    fill: 'yellow',
    stroke: 'black',
    strokeWidth: 0,
    name: 'poly',
    draggable: false
});
group.add(poly4);

最も近い点は、次に描画する必要がある点とは限りません。

于 2012-12-24T21:01:27.443 に答える
0

The reason why the order matters is because Shapes are usually drawn in a clockwise manner.

あなたはちょうどあなたの質問に答えました。新しいポイントを追加する場所は、必要な形状によって異なるため、距離とは関係ありません。描画したい場所にポイントを追加するだけです。

たとえば、形状がどうあるべきかをすでに知っていますか、それともユーザーがマウスをクリックした場所に基づいて形状を推測する必要がありますか?推測する必要がある場合は、デフォルトの動作を設定する必要があります。それ以外の場合は、ユーザーに追加のパラメーターを指定します。

于 2012-12-25T00:44:24.483 に答える