5

http://img853.imageshack.us/img853/2475/picture1eu.jpg

直線多角形を表すポイント/座標のArrayListがあります。ArrayListに格納されているPointsを使用して、この形状を長方形に分割したいと思います。

アルゴリズムを開始しましたが、終了できず、もっと簡単な方法が必要だと感じています。

ArrayListは「allCoordinates」と呼ばれます。
ArrayList「xMatch」と「yMatch」はallCoordinatesのサブセットです。

アルゴリズム:

ArrayList yMatch = All matching Coordinates in respect to 'y'


したがって、上記の図の場合:
(Set 1 = [x1、y1]-[x8、y8]、
Set2 = [x7、y7]-[x2、y2]、
Set3 = [x4、y4] [x5、x5 ]、
Set4 = [x3、y3] [x6、x6])

ArrayList xMatch = All matching Coordinates in respect to 'x'


したがって、上記の図の場合:
(Set 1 = [x1、y1]-[x2、y2]、
Set2 = [x3、y3]-[x4、y4]、
Set3 = [x5、y5] [x6、x6 ]、
Set4 = [x7、y7] [x8、x8])



これで、すべて垂直エッジとすべて水平エッジの2つのarrayListができました。今、私はそれらがすべて一緒に接続されているかどうかを確認する方法が必要ですか?私が言ったように、もっと簡単な方法が必要です...?

編集:

長方形は、既存の座標で開始および終了する交差する線を使用して形成する必要があることを明確にできますか。たとえば、(x6、y6)から水平に線を引き、エッジ(x1、y1)-(x8、y8)で終了することができます。この線は既存の座標から始まりますが、既存の座標で終わることはありません。したがって、その行は無効になります。

4

4 に答える 4

7

お気づきかもしれませんが、私はこの問題に戻ってきます。この種の問題を解き明かすのが好きなこともありますが、とても簡単に思えるようなエレガントなアルゴリズムを見つけることができなかったので少しイライラしたこともあります。

まあ、だまされてはいけません。これは簡単なポイント操作で解決できる些細な問題ではありませんが、確かにそのように見えます。この理由の一部は、ポイントのみを操作していると思いますが、線分とそれらで囲まれた領域も暗黙的に操作しているためです。これらの線分にも独自の制約があります(つまり、線分は常に1つまたはより多くの閉じたチェーンであり、それらを定義する頂点を除いて交差することはできません)。

また、アルゴリズムは、フィードするあらゆる種類の入力に対して機能する必要があります。つまり、フィードしたポリゴンがアルゴリズムに合わない方向に向いているという理由だけで、答えがない、または間違った答えを生成することは許可されていません。
ただし、できることは、アルゴリズムが受け入れる入力のタイプを制限することです。したがって、入力ポリゴンに軸に位置合わせされたセグメントのみが含まれていることを要求することは完全に有効です。
(「間違った方向に向けられた」と「軸に沿ったセグメントのみ」の違いは、最初の基準はアルゴリズムでテストせずに決定できない漠然とした基準であるのに対し、2番目の要件は可能であるということです)。

要約すると、直線多角形(つまり、軸に沿った線分のみで構成される)を長方形に水平に分割する方法を探しています。

直線多角形の例 直線多角形の例

計画は次のとおりです。

  1. ビルディングブロックを選ぶ
  2. 追加の頂点を許可する
  3. グリッド上に配置します。
  4. 不等サイズのグリッドセルでの作業。
  5. ポリゴンの内側にあるセルはどれですか?
  6. 長方形の作成。

ビルディングブロックを選ぶ

これらは実装の詳細ですが、これを前もって明確にしておくと、アルゴリズムがどのように機能するかをよりよく理解するのに役立つ場合があります。

コードでは、次のタイプのオブジェクトを基本的な構成要素として使用して、ポリゴンを次のように表現します。

  • x座標とy座標で構成されるポイント。(たとえば、Point2D.Doubleを使用します)
  • 開始点と終了点で構成されるセグメント(例:Line2D.Doubleを使用)
  • セグメントの閉じたチェーンで構成されるポリゴン(たとえば、Line2D.DoubleのArrayListを使用)。1つのセグメントは、次のセグメントの開始点と同じ点で終了します。

また、2次元配列としてモデル化できるグリッドを使用します。

追加の頂点を許可します。

長方形は、既存の座標で開始および終了する交差する線を使用して形成する必要があります。」と述べました。ただし、ほとんどの直線ポリゴンは、既存の頂点のみを使用して長方形に分割できないことに注意してください。上記の例(および前に提供したキャラバンの例)を参照してください。

したがって、実際には新しい頂点を明示的に作成しない場合でも、この制約を適用する必要があります。

グリッド上に配置します。

思考実験:ポリゴンが長さ10、20、30、または40の(軸に沿った)セグメントのみ、つまり10の倍数で存在する場合はどうなりますか?次に、ポリゴンをグリッドに投影し、ポリゴンの内側にあるグリッドセルを使用して長方形を構成します。また、これらの長方形の寸法を決定するのは簡単です。ポリゴンの内側にある水平方向に連続するセルの数を数え、10を掛けるだけです。それがあなたの幅です。

グリッドに揃えられたポリゴン グリッドに揃えられたポリゴン

ただし、次の点を除いて、良い考えです。

  • ポリゴンは、同じまたは複数の長さのセグメントのみで構成されているわけではありません
  • どのグリッドセルがポリゴンの内側にあるかをどのように判断しますか?

次に、これらの各問題に取り組みます。

不等サイズのグリッドセルでの作業。

あなたがそれについて考えるならば、すべてのグリッドセルが同じ幅と高さを持つ本当の理由はありません。したがって、ポリゴンが完全に整列するように間隔を空けて配置されたグリッドを考案できます。

グリッドの水平軸の幅を取得するには:

  • ポリゴンを構成する頂点のすべてのx座標を収集します。
  • 重複を排除し、値が大きくなるにつれて並べ替えます。
  • 次に、2つの後続の値の差が、その列の幅を定義します。

ポリゴンに位置合わせされたグリッド ポリゴンに位置合わせされたグリッド

明らかに、セルの高さは同じ方法で決定できます。これらの幅と高さを決定し、それぞれとと呼ばれる2つの配列に格納する必要がありgridWidthsますgridHeights

セルの数とその寸法がわかったので、グリッドコンテンツのモデリングを開始できます。

ポリゴンの内側にあるセルはどれですか?

ポリゴンは線分のチェーンとして保存されていることに注意してください。グリッドセルがこのポリゴンの内側にあるかどうかを判断するには、偶数のルールを使用できます。ポリゴンの外側*からテストするセルの中心まで線分を作成し、この線分との交点の数を数えます。ポリゴンのセグメント(つまり、Line2D.DoubleのintersectsLine()メソッドを使用します)。数が偶数の場合はポリゴンの外側にあり、奇数の場合はポリゴンの内側にあります。

*-セルの中心の間に水平線分のみを作成することをお勧めします(例に示すように)。これにより、セグメントの端点と交差するリスクがなくなります。これは、0または2の交差としてカウントされ、カウントの合計を台無しにする可能性があります。 。

したがって、このグリッドgridをブール値の2次元配列としてモデル化します。グリッドの各セルをこのように処理し、対応するスポットをgridtrue(ポリゴンの内側)またはfalse(ポリゴンの外側)としてマークします。

偶数奇数ルールに基づく内側(T)または外側(F) 偶数奇数ルールに基づく内側(T)または外側(F)

長方形の作成。

これで、ポリゴンのグリッド表現と、各セルの実際の幅と高さが得られたので、長方形の作成を開始できます。各長方形の幅と高さだけに関心があり、長方形を形成する実際の頂点座標には関心がないと仮定します(これも簡単ですが)。

Foreach row in grid
  run_start = null
  Foreach cell C in row
    if C is marked as true and run_start = null
      //Found the start of a new run
      run_start = C
    else if C is marked as false and run_start != null
      //Found the end of a run
      The cells [run_start...C] form a horizontal rectangle.
      Use the gridWidths and gridHeights arrays to determine the 
      dimensions, and report this rectangle as a result
      
      //Prepare for the next run
      run_start = null

長方形に分割されたポリゴン。 長方形に分割されたポリゴン。

左上の2つの長方形は、同じ開始x座標と終了x座標を共有しているため、1つの長方形と見なすことができることに注意してください。必要に応じて、これらのタイプの長方形をマージする追加のパスを実装できます。

結論

直線ポリゴンをグリッドにマッピングすることで、より高度な幾何学的データ構造に頼ることなく、長方形に水平に簡単に分割できます。
このアルゴリズムをより高速に実行するためにいくつかの最適化が可能であることに注意してください。ただし、現在の入力サイズではそれほど重要ではないと思います。これにより、実装がより困難になります。

于 2012-12-01T13:11:33.260 に答える
4

これは簡単ではありません。

私はあなたがあなた自身でそれをうまく解決することはないと思います:

詳細はこちらをご覧ください

Preparata、Shamos:計算幾何学:第8章:長方形の幾何学。

まず、プレーンスイープアルゴリズムとインターバルツリーに精通している必要があります。

もっと見つけたら更新します。詳細:

重なり合うことなく長方形のセットをカバーするために最も少ない長方形を見つけるためのアルゴリズム

于 2012-11-26T18:11:41.210 に答える
1

注:ここでは理論的に最適なソリューションを使用するつもりはありませんが、正しい答えを生成し、たとえば100個の頂点の入力ポリゴンで十分に高速に機能するアプローチを使用するだけです。また、穴のある入力ポリゴンなどの特殊なケースは現在考慮されていません。また、x-monotone *ではないポリゴンには、まだ説明しない前処理が必要です。
*意味:Pの左端の位置から開始して、上、下、または右に移動することで他の位置に到達できますが、左に移動することはありません。

前提条件以前の投稿
で 述べたように、質問の一部は、使用されるデッキボードの数を最小限に抑えるために、デッキボード(または「長方形」)を配置する方向です。入力ポリゴンPは主に軸に位置合わせされたセグメントで構成されていると想定しているため、方向の選択は水平または垂直に絞り込まれます。残りの部分については、単一のデッキボードが常に垂直に向けられている(つまり、上から下に走っている)と仮定します。水平デッキボードで結果を計算するには、Pを90度回転させるだけです。

問題
の説明 Pをデッキボードでカバーしようとします。各デッキボードの長さは無制限で、最大幅はWです。具体的には、使用するすべてのデッキボードの全長を最小にするカバレッジを探しています。使用済みのデッキボードのPの外側にある部分(つまり、無駄)を使用して、Pの他の部分を覆うことはできません。無駄を最小限に抑えるために、デッキボードの左または右の境界線をPの頂点、または別のデッキボードのすぐ隣にデッキボードを配置します。

解決策
これに向けた最初のステップは、Pを垂直スラブのコレクションに分割することです。P内のすべての頂点の個別のx座標を取得し、それらを並べ替えます。次に、連続するx座標の各ペアがPのスラブSを定義します。 図1

次に、各スラブSについて、(1つまたは複数の)デッキボードをそれに位置合わせする4つの方法があることを認識してください。
*(SL)左から開始、つまり、デッキボードの左側をスラブの左側に位置合わせします。 。
*(CL)左に進みます。つまり、左側のスラブによって決定されたデッキボードのパターンを続けます。
*(CR)右に進みます。つまり、右側のスラブによって決定されたデッキボードのパターンを続けます。
*(SR)右から開始します。つまり、デッキボードの右側をスラブの右側に合わせます。

したがって、各スラブSの4つの配置のすべての可能な組み合わせを考慮すると、すべての可能なデッキ構成が得られます。配置のすべての組み合わせが許可されているわけではないことに注意してください。SLとSRはどのスラブにも使用できますが、CLは左側のスラブがSLまたはCLの場合にのみ使用でき、CRは右側のスラブがSRまたはCRの場合にのみ使用できます。

-Snip-問題はここで解決しようとしているものとは大幅に異なるように見えるので、この投稿を終了しません。

于 2012-11-27T22:47:35.310 に答える
0

私は解決策を見つけましたが、おそらくそれは最適ではありません。 これで、座標と前述の2つのArrayList(xMatchとyMatch)ができました。 xMatch=一致するx座標を持つ座標 ペアのArrayListyMatch=一致するy座標を持つ座標ペアのArrayList


リンク






2ロットの座標を特定の順序で保存する「Point2Point」というクラスを作成しました。xMatchとyMatchはどちらも「Point2Point」タイプです。他のベクトルと同様に、順序は重要です。私が使用した順序は次のとおりです。


Point1=開始点
Point2=終了点。

そこで、「for」ループを使用して、Point1(開始点)に関してxMatchの要素をyMatchの要素と一致させました。これらを組み合わせると、次のような形になります。



Link2


この図では、これら2つのベクトルが長方形の一部であるためには、座標(?、?)が存在する必要があることがわかります。長方形のプロパティを使用すると、(?、?)が(yMatch.Point2.x、xMatch.Point2.y)に等しいか、この図(x3、y2)に関して等しいことがわかります。


これで、検索する座標がわかったので、ArrayList "allCoordinates"を検索して、この座標が存在するかどうかを確認できます。もしそうなら-私は長方形を持っています、そうでなければ-それは不発弾です!!

于 2012-11-30T12:23:30.470 に答える