web-dev-qa-db-ja.com

順序付けられた座標のセットが単純な曲線を形成しているかどうかを判断する方法は?

これを尋ねる適切な場所であることを願っています。 Stack Overflow または Computer Science のどちらに属しているかはわかりませんでした。
最終的にはこれがより適切に思えました。

とにかく、最初にいくつかの背景:
A閉じた曲線は、端点がなく、領域を完全に囲む曲線です。
A単純な曲線は、それ自体と交差しない曲線です。

例:

enter image description here

nが与えられた場合、(x,y)マウスの動きを表す座標。これらが閉曲線を形成しているかどうかは簡単に判断できます(もちろん、2点間の許容距離に上限がある場合)。ただし、座標かどうかを判断するアルゴリズムがあります。単純な曲線を形成しますか?

オンラインで答えを探しましたが、関連する解決策が見つかりませんでした。

6
so.very.tired

線が交差するようなポイント間に2つの線分がない場合、曲線は単純であると主張できます。つまり、この条件がないことを確認することにより、曲線が単純かどうかを確認できます。

アルゴリズムは次のようになります。

for each p1, p2 in pointlist
  for each p3, p4 in pointlist
     if line_segment(p1, p2) intersects line_segment(p3, p4)
        return false
return true   

P2はp1の後の連続ポイントであり、同様に、p4はp3の後の連続ポイントになることに注意してください。冗長性を回避するために、ポイントp3およびp4は、ポイントp1およびp2の後に開始できます。これはO(n ^ 2)時間で簡単に実行できます。少なくとも一度は線が同じになるため(ゼロで除算しない)、交差のチェックに注意してください。

このようなポイントが多数ある場合は、1つおきのポイントをスキップできます。このアルゴリズムは、曲線が接線に近づいた場合に真に交差する線が検出されないという小さなリスクで4倍速く実行されます。

4
Neil

各ポイントペアを確認できますP[i],P[i+1]各ポイントペアに対してP[j],P[j+1]

それらが作成するラインセグメントのいずれかが交差する場合、カーブは単純ではありません。

単純に各行を確認します。

for(int i = 0; i < n-3; i++)
    for(int j = i+2; j < n-1; j++)
        if(doIntersect(new Line(P[i],P[i+1]), new Line(P[j],P[j+1]));

チェックをスキップしますP[i],P[i+1]に対してP[i+1],P[i+2]エンドポイントで常に交差するためP[i+1]

このアルゴリズムは、セグメントのリストを左端のxでソートし、現在のセグメントの右端のxの左端に端点がある行のみをチェックすることで高速化できます。

3
ratchet freak

概念は単純かもしれませんが、多くの悪魔のような詳細があります。

まず、ポイントを表す数値は実際の曲線の近似ではなく正確であり、アウトラインは実際の曲線ではなく直線セグメントで構成されることを規定する必要があります。

第二に、境界条件は至る所にあります。線ABが点Eでのみ線DEFに接触する場合、それは十字として数えられますか? Figureの全体的なジオメトリを考慮する必要があります。 Cの「口」に入るように後ろから周りに伸びる仮足を備えた「C」形の図形を考えてみましょう。次に、Cのあごを徐々に閉じて1点で出会います。

1
ddyer