【发布时间】:2021-11-26 19:26:03
【问题描述】:
我一直在研究四叉树类以检测可能的碰撞,但我添加的项目越多,堆栈溢出的速度就越快。
我还注意到,随着程序运行,内存使用量呈线性增加,所以我认为我没有正确删除某些内容,它只是相互堆叠?
我知道大多数堆栈溢出错误是由递归引起的,但它不应该只发生在 100 个对象上。
#include "Quadtree.h"
Quadtree::Quadtree(Rectangle* bounds)
{
this->bIsSplit = false;
this->bounds = bounds;
this->maxObjects = 5;
}
void Quadtree::Split(std::vector<std::pair<SpaceObject*, SpaceObject*>> &collidingObjects)
{
float x = bounds->x;
float y = bounds->y;
float subWidth = bounds->width / 2;
float subHeight = bounds->height / 2;
// Top Left
nodes.push_back(new Quadtree(new Rectangle(x, y, subWidth, subHeight)));
// Top Right
nodes.push_back(new Quadtree(new Rectangle(x + subWidth, y, subWidth, subHeight)));
// Bottom Left
nodes.push_back(new Quadtree(new Rectangle(x, y + subHeight, subWidth, subHeight)));
// Bottom Right
nodes.push_back(new Quadtree(new Rectangle(x + subWidth, y + subHeight, subWidth, subHeight)));
// takes all the objects in the parent node and splits them into there corresponding subdivided quadtree
for (auto o : this->objects)
{
for (int i = 0; i < nodes.size(); i++)
{
if (nodes[i]->bounds->Contains(o->x, o->y, o->size))
{
nodes[i]->Insert(o, collidingObjects);
}
}
}
this->objects.clear();
this->bIsSplit = true;
}
void Quadtree::Insert(SpaceObject* spaceObject, std::vector<std::pair<SpaceObject*, SpaceObject*>> &collidingObjects)
{
// if the object does not fit inside this quadtree, this isn't the right quadtree
if (!bounds->Contains(spaceObject->x, spaceObject->y, spaceObject->size))
{
return;
}
if (!bIsSplit && this->objects.size() < maxObjects) // add the object to the quadtree if the max has not been hit
{
objects.push_back(spaceObject);
for (auto o : this->objects)
{
// if the objects are not the same and overlapping (pythag)
if (spaceObject != o &&
((spaceObject->x - o->x) * (spaceObject->x - o->x)) + ((spaceObject->y - o->y) * (spaceObject->y - o->y)) <= (spaceObject->size + o->size) * (spaceObject->size + o->size))
{
// Add colliding pair to the collidingObjects vector
collidingObjects.push_back(std::make_pair(spaceObject, o));
}
}
}
else
{
if (!this->bIsSplit) // splits the quadtree if this quadtree has not been split yet
{
this->Split(collidingObjects);
}
// adds the passed in object to one of the subnodes
for (auto n : nodes)
{
n->Insert(spaceObject, collidingObjects);
}
}
}
void Quadtree::Delete(SpaceObject* spaceObject)
{
if (!bounds->Contains(spaceObject->x, spaceObject->y, spaceObject->size))
{
return;
}
if (!bIsSplit)
{
for (int i = 0; i < objects.size(); i++)
{
if (objects[i] == spaceObject)
{
this->objects.erase(objects.begin() + i);
return;
}
}
}
else
{
for (auto n : nodes)
{
n->Delete(spaceObject);
}
}
}
void Quadtree::Clear()
{
if (bIsSplit)
{
for (auto n : nodes)
{
n->Clear();
}
this->bIsSplit = false;
}
nodes.clear();
objects.clear();
}
【问题讨论】:
-
如果它们完全重合,即使场景中只有两个对象也可能导致四叉树遍历中的无限递归(如果您以非递归方式编写代码,则会导致无限循环)。您通常需要对此类空间索引进行一些最大深度限制或有效限制最大深度的最小像元大小。无意粗鲁,我认为在您的水平上,使用空间散列比四叉树要好得多。确定单元格大小后,所涉及的摆弄就更少了,我真的认为您会从中获得更好的结果,直到您开始掌握事情的窍门。
标签: c++ recursion stack-overflow