QuadTrees и переполнение стека рекурсивного конструктора

Я создаю фрагментированный ландшафт QuadTree и стараюсь обеспечить, чтобы между двумя узлами никогда не было более одного уровня детализации. Мой текущий код конструктора таков:

QuadNode::QuadNode(Rect area, QuadNode * p, QuadRoot * r)
{
    Root = r;

    Parent = p;
    Level = p->Level + 1;

    InitializeGeometry(area);

    for(int iii = 0; iii < 4; iii++)
            Children[iii] = 0;

    for(int iii = 0; iii < 4; iii++)
    {
            if(QuadrantNeedsChild(iii))
                    Children[iii] = new QuadNode(GetRect(iii), this, Root);
    }
}

И это прекрасно работает. Но чтобы установить не более одного уровня разницы между двумя соседними узлами, я пытаюсь добавить это в конец конструктора:

QuadNode * neighbour;

for(int direction = 0; direction < 4; direction++)
{
    neighbour = FindNeighbour(direction);
    if(neighbour)
    {
        while(Level - neighbour->Level > 1)
        {
            neighbour->Subdivide();
            neighbour = FindNeighbour(direction);
                    //neighbour should now be a child of the previous neighbour
        }
    }
}

Но этот стек переполняется. Одна из причин, по которой я думаю, заключается в том, что часть присваивания оператора Children[iii] = new QuadNode(GetRect(iii), this, Root); никогда не выполняется, а FindNeighbour() требует, чтобы дочерние элементы находили правильного соседа. Но я не думаю, что это единственная проблема, поскольку код на самом деле никогда не достигает второй neighbour = FindNeighbour(direction); строки, и я понятия не имею, чем это вызвано.

Если я запускаю этот второй фрагмент кода в новой функции после базового создания дерева, он более или менее работает, но тогда требуется несколько проходов, чтобы убедиться, что вновь созданные узлы сами не создают разницу уровней> 1. Итак, я ' Я бы предпочел иметь этот код в конструкторе, если это вообще возможно. Кто-нибудь может придумать способ достижения этого?

Несколько замечаний по классу на случай, если он поможет QuadrantNeedsChild(int quadrant) гарантировать, что уровень никогда не превышает 8, так что я знаю, что я не слишком углубляюсь. Subdivide() просто запускает Children[iii] = new QuadNode(GetRect(iii), this, Root); во всех квадрантах. FindNeighbour(int direction) может возвращать родителя или предка. Например, если D ищет северного соседа, он получит его прародителя (всю диаграмму), если B никогда не подразделялся следующим образом:

 - - - - - -
|     |     |
|  A  |  B  |
|     |     |
|- - - - - -|
|     | D|  |
|  C  |-----|
|     |  |  |
 - - - - - -

Функция subdivide просто разделяет данный квадрант или все квадранты, если предоставляется квадрант вне диапазона.

void QuadNode::Subdivide(int quadrant)
{
    if(quadrant > -1 && quadrant < 4)
    {
        if(!Children[quadrant])
            Children[quadrant] = new QuadNode(GetRect(quadrant), this, Root);
    }
    else
        for(int iii = 0; iii < 4; iii++)
            if(Children[iii] == 0)
                Children[iii] = new QuadNode(GetRect(iii), this, Root);
}

person Spectralist    schedule 12.06.2012    source источник
comment
Я должен добавить сюда обязательный тег stackoverflow.   -  person Richard J. Ross III    schedule 13.06.2012
comment
Боковое примечание: имена переменных в C ++ по большинству соглашений начинаются с букв нижнего регистра, а имена классов начинаются с верхнего регистра.   -  person tmpearce    schedule 13.06.2012
comment
Пожалуйста, опубликуйте полный компилируемый пример.   -  person Kuba hasn't forgotten Monica    schedule 13.06.2012
comment
Почему на всей диаграмме северный сосед D, а не B? Что является южным соседом «Б»?   -  person Rook    schedule 13.06.2012
comment
У B нет соседей, так как он не был подразделен. Пока квадрант не разделен, он не является узлом.   -  person Spectralist    schedule 14.06.2012
comment
Можете ли вы также отправить код на Subdivide?   -  person jxh    schedule 15.06.2012
comment
Конечно, я добавил функцию subdivide.   -  person Spectralist    schedule 16.06.2012


Ответы (1)


Когда создается первый дочерний элемент узла, находит ли он своего родителя в качестве соседа, поскольку у этого родителя еще нет дочерних элементов (первый только что будет создан)?

Это приведет к тому, что узел вызовет Subdivide() для своего собственного родителя, что создаст новый дочерний элемент, который снова вызовет _2 _, ...

И даже без этого создание первого узла на новом уровне будет Subdivide() всех его соседей, которые, в свою очередь, рекурсивно разделят всех соседей этих соседей. Это как должно работать? Для самого глубокого уровня это вызовет что-то вроде 4 8 уровней рекурсии.

person sth    schedule 16.06.2012