쿼드 트리에서 모양 (사각형)은 어떻게 작동합니까?


10

쿼드 트리가 내 게임에 이상적인 데이터 구조라고 들었지만, 쿼드 트리 내에서 정확히 모양이 작동하는 방식을 이해하는 데 어려움이 있습니다.

JavaScript 로이 작업을 수행하고 있지만이 질문이 모든 언어의 쿼드 트리에 적용될 수 있다고 생각합니다.

나는 기본 (x, y) 포인트포인트 삽입 이 쿼드 트리에서 어떻게 작동하는지 이해 하고 종이에서 할 수 있다고 생각합니다.

다음은 포인트 실험에 대한 JSfiddle 입니다.

쿼드 트리 포인트

한 가지 경우를 제외하고 포인트가있는 테스트가 예상대로 작동합니다.

그러나 직사각형과 같은 모양이 관련되면 혼란이 시작됩니다. 도형이있는 쿼드 트리에서 검색 할 때 도형의 각 점과 어떤 노드에 속하는지 확인합니까? 그리고 각 도형에 (x, y, width, height) 매개 변수를 사용할 때 도형 삽입은 어떻게 작동합니까? 시작점의 너비 / 높이를 사용하여 다른 모퉁이 점을 계산 한 다음 적절한 노드에 분배합니까? 삽입 된 모양이 4 개의 노드에 걸쳐있는 경우 해당 모양의 데이터가 4 개의 모든 노드에 저장됩니까?

그리고 검색 방법이 모양을 매개 변수 (x, y, width, height)로 받아들이면 실제로 무슨 일이 일어나고 있습니까? 먼저 모양을 삽입 할 때 모양이 어떤 노드에 걸쳐 있는지 확인한 다음 해당 노드의 모든 객체를 검색합니까?

형태로 작업 하는 JSfiddle이 있지만 테스트 결과에 완전히 혼란 스럽습니다. 중복 객체가 반환됩니다!

쿼드 트리 모양

예를 들어, 빨간색 사각형은 검색 방법에 입력하는 매개 변수와 동일하게 그려집니다. 이 빨간색 사각형이 네 노드 모두에 걸쳐 있으므로 쿼드 트리의 모든 개체를 반환해야한다고 생각합니다! 그러나 그것은 그렇지 않으며, 그것이 돌아 오는 것을 합리화하는 데 어려움을 겪고 있습니다. 현재 주석 처리 된 다른 여러 테스트가 있지만 주석을 풀고 실행하여 더 혼란스러운 결과를 볼 수 있습니다!

예를 들어 쿼드 트리의 모든 포인트를 반환하려면 어떻게해야합니까? 경계의 전체 크기를 사용하는 검색 방법? 예를 들어 retrieve (0, 0, canvas.width, canvas.height)?

내가 사용 하는 JavaScript QuadTree 라이브러리 는 다양한 다른 소스에서 참조되었으므로 실제 구현이 정확하고 유명하다고 가정합니다.

나는 많은 혼란이 쿼드 트리 용어에 대한 오해에서 비롯된 것이라고 생각합니다. 마찬가지로 "포인트"에 너비 / 높이 매개 변수가있는 경우 치수 대신 경계를 말하는 이유는 무엇입니까? 그것은 관습 / 속기의 문제입니까, 아니면 완전히 다른 개념입니까?

시간 내 줘서 고마워!


그것들은 그들의 위치에 따라 쿼드 트리에 정상적으로 저장됩니다. 일반적으로 중앙에 있지만 정의한대로 코너에있을 수 있습니다. 귀하의 질문은 다음 중 하나 일 수 있습니다 : QuadTree : 포인트 만 저장합니까?
MichaelHouse

나는 그 질문을 읽었지만 여전히 답을 완전히 이해하지 못한다 :(. "이 용량을 초과하더라도 (크기 조정 컨테이너 사용)-그것을 포함하는 가장 작은 노드에 저장해야합니다." 객체가 매우 큰 경우, 노드가 완전하게 포함 된 가장 작은 노드는 다른 노드로만 구성된 상위 노드 에서처럼 노드가 비 리프 노드가 아니라고 말합니다. 그것은 포함 노드가 그 안에 1 개의 리프와 4 개의 더 작은 노드를 가질 것이라는 것을 의미하기 때문에
user2736286

1
@ user2736286 quadtree lib의 코드를 보면 (매우 길지 않음) 높은 수준의 노드에 사각형을 저장하여 노드 경계를 넘어 가지 않도록 할 수 있습니다. _stuckChildren코드 의 필드에 대한 참조를 참조하십시오 . "경계가있는 항목 검색"샘플에서도이를 확인할 수 있습니다. 클릭 한 노드의 경계에 걸쳐있는 노드는 루트 노드까지 항상 빨간색으로 강조 표시됩니다.
Nathan Reed

@ user2736286 또한 quadtree lib는 범위가있는 항목을 검색하는 데 버그가있는 것으로 보입니다. 일부 노드 경계에 걸쳐있는 쿼리 rect를 제공하면 쿼리가 터치하는 노드의 모든 rect를 반환하지 않습니다. 노드 경계 근처를 클릭하면 "경계가있는 항목 검색"에서도이를 쉽게 확인할 수 있습니다.
Nathan Reed

@NathanReed 이전에 코드를 이해하려고했지만 개념적 기초 없이는 코드를 이해할만큼 숙련되지 않았습니다. John McDonald의 의사 코드 덕분에 이제 사각형이 노드에 삽입되는 방법을 이해하지만 검색 방법에 대해서는 아직 확실하지 않습니다. "경계가있는 항목 검색"에 관해서는-예제에 혼란스러워합니다. 예를 들어 가장 작은 노드 중 하나에 잘 맞는 rect를 클릭하면 해당 노드 외부의 다른 rect가 모두 강조 표시되는 이유는 무엇입니까?
user2736286

답변:


10

쿼드 트리는 일반적으로 사각형을 저장하고 검색합니다. 포인트는 너비와 높이가 0 인 특정 경우입니다. 다음 논리는 루트 노드부터 시작하여 트리에서 새 사각형의 홈을 찾는 데 사용됩니다.

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 개의 자식 쿼드 각각을 더 자세히 볼 수 있습니다. 자식에는 더 이상 자식이 없으므로이 자식 쿼드의 각 사각형은 빨간색 사각형과 비교됩니다. 트리의 사각형은 빨간색 쿼리 사각형과 충돌하지 않으므로 반환되는 것은 없습니다.

쿼리 영역과 비교할 때 개체가 많고 개체가 존재할 공간이 많을 때 쿼드 트리의 이점이 실제로 보이기 시작합니다. 이러한 경우 작은 쿼리 영역으로 인해 쿼드 트리의 방대한 청크를 고려하지 않아도됩니다. 쿼리 사각형과 교차하는 쿼드 만 더 자세히 살펴볼 것입니다.

편집하다

검색은 일반적으로 다음과 같이 수행됩니다.

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/…
John McDonald

1
@ user2736286 선택하지 않은 경우 JohnMcDonald가 작성한 Query and Store 함수의 재귀를 기록하는 것이 중요합니다. 당신이 그 부분을 얻지 못하면별로 의미가 없습니다. 두 가지 모두에 대해, 각 재귀는 나무, 즉 가지와 잎으로 더 깊숙이 들어갑니다.
TASagent

감사합니다 John, 의사 코드가 매우 유용합니다. "if (queryRects가 childNode 경계와 교차 함)"이라고 말하면 기본적으로 queryRect가 경계 내에 포함되어 있는지 ( 부분적으로 또는 완전히) 의미합니까? 100 % 명확하고 싶습니다. 또한 논의되는 "경계 별 항목 검색"예제에서 클릭 결과 이미지가 있습니다. 그림 파란 점은 내가 클릭 한 곳입니다. 그렇다면 왜 그 노드 안에있는 두 개의 리 센트 만 강조 표시되지 않습니까? 사각형이 멀리 떨어져있는 이유는 무엇입니까? 나는 그것이 정말로 혼란 스럽다고 생각한다.
user2736286

일부 또는 전체 두 터치 또는 다른 하나가 완전히 포함 된 경우. Quadtrees 에서 위키를 읽고 싶지만 사진을 가져 와서 다른 자식 경계를 나타내는 색으로 코딩했습니다. 모든 파란색 사각형은 첫 번째 자식 쿼드의 경계와 교차하며 자홍색은 한 레이어 깊고 녹색 한 레이어는 더 깊습니다. 빨간색 사각형이 클릭 한 쿼드와 교차합니다. 당신 최종 아이 쿼드 (적색)에 포함 된 라이브러리 반환 모든 하위 경계의 구형 플러스의 모든 : i.imgur.com/InB8KBj.png
존 맥도날드

좋아, 그래서 lib의 소스 코드를 살펴보기 위해 최선을 다했고, stuckChildren의 동작을 마침내 이해했으며 내 그림에있는 모든 rects는 단순히 stuckChildren이라는 것을 알았습니다. 원래 여러 노드에 걸쳐있는 모든 rect가 데이터를 복제하여 각 작은 노드에 삽입한다고 생각했습니다. 이제 stuckChildren이 확장 된 노드에 삽입되지 않지만 단순히 포함 된 하나의 노드에 머 무르므로 쿼리 rect가 포함 된 가장 작은 노드뿐만 아니라 모든 부모 노드도 확인해야합니다. 그림 주셔서 감사합니다; 그것은 지금 훨씬 더 의미가 있습니다 :)
user2736286
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.