四角形ツリーで形状(長方形)はどのように機能しますか?


10

クワッドツリーはゲームにとって理想的なデータ構造であると言われましたが、クワッドツリー内でシェイプがどのように機能するかを正確に理解できません。

私はこれをJavaScriptで行っていますが、これらの質問はどの言語の四分木にも当てはまると思います。

基本的な(x、y)ポイントポイント挿入が四分木でどのように機能するか、そして紙の上でそれを実行できることはほぼ理解していると思います。

ここにあるJSfiddle私はポイントを試してのは。

クワッドツリーポイント

1つのケースを除いて、ポイントを使用した私のテストは期待どおりに機能しています。

しかし、私の混乱は、長方形のような形状が関係しているときに始まります。形状のある四角形ツリーから取得する場合、形状の各ポイントと、それらがどのノードに分類されるかをチェックしますか?また、各図形の(x、y、width、height)パラメーターを受け入れる場合、図形の挿入はどのように機能しますか?開始点からの幅/高さを使用して他のコーナーポイントを計算してから、適切なノードに分配しますか?挿入された形状が4つのノードにまたがる場合、その形状のデータは4つのノードすべてに保存されますか?

そして、検索メソッドが形状をパラメーター(x、y、width、height)として受け入れる場合、実際には何が行われているのでしょうか。挿入する場合、シェイプがどのノードにまたがるかを最初に確認してから、それらのノードのすべてのオブジェクトを取得しますか?

私はJSfiddleで形状を処理していますが、テストの結果に完全に混乱しています。重複したオブジェクトが返されます!

クワッドツリー形状

たとえば、赤い四角は、私の検索メソッドに入力しているパラメーターに相当する描画です。この赤い四角は4つのノードすべてにまたがるので、四角ツリーのすべてのオブジェクトを返すはずだと思います。しかし、そうではなく、私はそれが何を返すかを合理化するのに苦労しています。現在コメントアウトされている他のテストがいくつかありますが、コメントを外して実行すると、さらに混乱する結果を確認できます。

とはいえ、四分木のすべてのポイントを返す場合、どうすればよいですか?境界全体のサイズの形状を使用する取得メソッド?たとえば、retrieve(0、0、canvas.width、canvas.height)?

JavaScriptの四分木ライブラリ私が使用していますので、私は実際の実装が正しいと評判であると仮定し、様々な他のソースによって参照されています。

私の混乱の多くは、四分木の用語の誤解から生じていると思います。同様に、「ポイント」にも幅/高さのパラメーターがある場合、なぜ彼らは寸法ではなく境界と言うのですか?それは慣習/速記の問題ですか、それとも完全に異なる概念ですか?

御時間ありがとうございます!


それらは、通常どおり、位置によってクアッドツリーに格納されます。通常、これらは中央にありますが、定義したように隅に置くこともできます。あなたの質問はこれと同じ
MichaelHouse

私はその質問を読みましたが、答えを完全に理解していません:(。「これを完全に含む最小のノードに保存する必要があります-これが容量を超えている場合でも(サイズ変更可能なコンテナを使用してください)。」-彼がCOMPLETELYに含まれる最小のノードとは、オブジェクトが非常に大きい場合、そのノードは非リーフノードではないことが多いのではないですか?他のノードのみで構成される上位のノードのように、それは正しくないようですそれは、包含ノードが1つのリーフと4つの小さなノードを持つことを意味するためです
user2736286

1
@ user2736286 quadtree libのコードを見ると(それほど長くはありません)、ノードの境界にまたがらないように、上位レベルのノードに四角形を格納していることがわかります。への参照を参照してください_stuckChildrenコード内のフィールド。これは、「境界付きのアイテムを取得する」サンプルでも確認できます。クリックしたノードの境界にまたがるノードがルートノードに至るまで、常に赤で強調表示されます。
Nathan Reed

@ user2736286また、quadtree libには、境界を持つアイテムを取得する際にバグがあるようです。一部のノードの境界にまたがるクエリの四角形を指定した場合、クエリが接するノードのすべての四角形が返されません。これは、「境界付きのアイテムの取得」でも、ノードの境界の近くをクリックすると簡単に確認できます。
Nathan Reed

@NathanReed以前、私はコードを理解しようとしましたが、概念的な基礎なしでは理解するのに十分なスキルがありません。ジョン・マクドナルドの疑似コードのおかげで、長方形がノードに挿入される方法を理解しましたが、検索がどのように機能するかはまだはっきりしていません。「境界のあるアイテムの取得」については、この例に戸惑っています。同様に、最小ノードの1つにぴったり収まる四角形をクリックすると、そのノードの外側にある他のすべての四角形も同様に強調表示されるのはなぜですか。
user2736286 2013年

回答:


10

四分木は通常、四角形を格納および取得します。ポイントは、幅と高さがゼロの特定のケースです。次のロジックは、ルートノードから始めて、ツリー内の新しい四角形のホームを見つけるために使用されます。

void Store(Rectangle rect)
{
    if(I have children nodes)
    {
        bool storedInChild = false;
        foreach(Node childNode in nodes)
        {
            if(this rectangle fits entirely inside the childNode bounds)
            {
                childNode.Store(rect);   // Go deeper into the tree
                storedInChild = true;
                break;
            }
        }
        if(not storedInChild)
        {
            Add this rectangle to the current node
        }
    }
    else
    {
        Add this rectangle to the current node
    }
}

四角形は任意の深さに格納でき、リーフクワッドである必要はありません。四角形がルートレベルで境界をまたぐ場合、ルートクワッドは四角形を格納します。

たとえば、赤い四角は、私の検索メソッドに入力しているパラメーターに相当する描画です。この赤い四角は4つのノードすべてにまたがるので、四角ツリーのすべてのオブジェクトを返すはずだと思います。しかし、そうではなく、私はそれが何を返すかを合理化するのに苦労しています。

quadtreeをクエリすると、クエリに含まれる四角形のみが返されます。あなたの例では、赤いクエリの四角形が各子クワッドと交差しているため、4つの子クワッドのそれぞれをより詳細に見るように強制します。子にはそれ以上の子がないため、これらの子クワッドの各長方形は赤い長方形と比較されます。ツリー内のどの長方形も赤いクエリ長方形と衝突しないため、何も返されません。

クエリ領域と比較して、オブジェクトが多く、オブジェクトが存在するためのスペースがたくさんある場合、クアッドツリーの利点が実際にわかります。これらの場合、クエリ領域が小さいと、クアッドツリーの膨大なチャンクがすぐに考慮されなくなります。クエリ四角形と交差する四角形のみが、より詳細に表示されます。

編集

取得は通常、次のように行われます。

List<Rectangle> Query(Rectangle queryRect)
{
    List<Rectangle> results;
    foreach(Node childNode in children)
    {
        if(queryRect intersects with childNode bounds)
        {
            results += childNode.Query(queryRect);   // Dig deeper into the tree
        }
    }

    foreach(Rectangle I have stored in this quad)
    {
        if(queryRect intersects with rect)  // Your library doesn't do this
        {
            results += rect;
        }
    }

    return results;
}

ただし、ライブラリでは、返された四角形がクエリと交差するかどうかを確認できないため、自分で追加する必要があります。


ライブラリを詳細に調べた後、ライブラリは、指定したクエリ四角形のすべての可能な衝突候補のリストを返します。クエリの四角形を各候補と比較して、実際の衝突があるかどうかを確認するのはあなたの仕事のようです。ほとんどのライブラリは、最後のステップを実行して、クエリ領域との実際の衝突を返します。したがって、必要なのはretrieve、リストにプルーニングするロジックをメソッドに追加することだけです。あなたはそれがここでより明確にビットをやっているかを見ることができます。mikechambers.com/html5/javascript/QuadTree/examples/...
ジョン・マクドナルド

1
@ user2736286あなたがそれに気づかなかった場合、JohnMcDonaldが書いたクエリとストア関数の再帰に注意することが重要です。あなたがその部分を得なければ、それは多くの意味をなさないでしょう。どちらの場合も、各再帰はツリーのさらに深いところに行きます。
TASagent 2013年

Johnに感謝します。疑似コードは非常に役に立ちます。「if(queryRectがchildNode境界と交差する)」と言った場合、それは基本的にqueryRectが境界内に含まれているかどうかを意味しますか?100%明確にしたいだけです。また、説明されている「境界によるアイテムの取得」の例では、クリックの結果のイメージがあります。 Pic青い点は私がクリックした場所です。では、なぜノード内の2つの四角形だけが強調表示されていないのでしょうか。なぜそれから遠く離れた長方形も強調表示されるのですか?それが本当に私を混乱させていると思います。
user2736286 2013年

一部または完全。2つが接触した場合、またはいずれかが完全に他方に含まれている Quadtreesでwikiを読みたいのですが、私はあなたの写真を撮り、さまざまな子の境界を表すために色分けしました。すべての青い長方形は最初の子クワッドの境界と交差し、マゼンタは1層深く、緑はさらに1層深くなっています。赤い四角形はクリックした四角形と交差します。ライブラリは、子の境界上のすべての四角形に加えて、最後の子クワッド(赤)に含まれるすべての四角形を返します:i.imgur.com/InB8KBj.png
John McDonald

わかりましたので、私はlibのソースコードを精査するために最善を尽くし、stuckChildrenの動作を最終的に理解しました。また、私の写真にあるこれらすべての追加のrectは単にstuckChildrenであることを理解しています。もともと私は、複数のノードにまたがるすべての四角形は、そのデータが複製されて各小さなノードに挿入されるだけだと思っていました。stuckChildrenは、それがまたがるノードに挿入されず、単にそれを含む1つのノードに留まることに気づきました。そのため、クエリの四角形を含む最小のノードだけでなく、すべての親ノードもチェックする必要があります。写真ありがとうございます。それは今ではもっと理にかなっています:)
user2736286 '15
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.