[英]Quadtree implementation in C++ : Exception Thrown Read Access Violation
我試圖在 C++ 中實現四叉樹,但是我有一個讀訪問沖突,我花了幾個小時試圖弄清楚。 請注意,我已將所有成員變量公開,僅用於調試工作。
每當我試圖細分一個象限,即根象限,我得到
拋出異常:讀取訪問沖突。 std::_Vector_alloc > >::_Myend(...) 返回 0xDDDDDDE9。
四叉樹由指向連續象限數組的指針和點組成。 這些指針被傳遞到每個象限,因此它們可以在不復制的情況下寫入它。
我做錯了什么+你能提出改進建議嗎?
這是我的四叉樹類:
class Quadtree
{
private:
Boundary rootBoundary;
public:
std::vector<Ball>* dataPtr = nullptr;
std::vector<Quadrant>* quadrantPtr = nullptr;
Quadtree(const Boundary& b);
};
Quadtree::Quadtree(const Boundary& bo)
:rootBoundary(bo)
{
std::vector<Ball>* bPtr = new std::vector<Ball>;
std::vector<Quadrant>* qPtr = new std::vector<Quadrant>;
quadrantPtr = qPtr;
dataPtr = bPtr;
Quadrant Root(bo, quadrantPtr, dataPtr);
}
四叉樹包含所有象限以及數據存儲。
這是象限類:
class Quadrant
{
private:
public:
std::vector<Quadrant>* quadrantPtr = nullptr;
std::vector<Ball>* dataPtr = nullptr;
Boundary m_boundary;
std::vector<unsigned int> elementIndex;
int first_child_index = -1;
int count = 0;
Quadrant(Boundary b, std::vector<Quadrant>* qPtr, std::vector<Ball>* dPtr);
void Subdivide();
bool Insert(Ball* Ball);
void Display(sf::RenderWindow& myWindow);
};
Quadrant::Quadrant(Boundary b, std::vector<Quadrant>* qPtr, std::vector<Ball>* bPtr)
:dataPtr(bPtr), quadrantPtr(qPtr), m_boundary(b)
{
qPtr->push_back(*this);
}
void Quadrant::Subdivide()
{
float cx = m_boundary.m_Centre.x;
float cy = m_boundary.m_Centre.y;
float qw = m_boundary.m_halfSize.x / 2;
float qh = m_boundary.m_halfSize.y / 2;
sf::Vector2f halfSize{ qw, qh };
first_child_index = quadrantPtr->size();
Boundary NE(sf::Vector2f{ cx + qw, cy - qh }, halfSize);
Quadrant NEQ(NE, quadrantPtr, dataPtr);
Boundary NW(sf::Vector2f{ cx - qw, cy - qh }, halfSize);
Quadrant NWQ(NW, quadrantPtr, dataPtr);
Boundary SE(sf::Vector2f{ cx + qw, cy + qh }, halfSize);
Quadrant SEQ(SE, quadrantPtr, dataPtr);
Boundary SW(sf::Vector2f{ cx - qw, cy + qh }, halfSize);
Quadrant SWQ(SW, quadrantPtr, dataPtr);
}
bool Quadrant::Insert(Ball* ball)
{
if (!m_boundary.ContainsPoint(*ball))
{
return false;
}
if (count < 4)
{
elementIndex.push_back(dataPtr->size());
count++;
return true;
}
else
{
if (first_child_index == -1)
{
std::cout << "subdividing" << std::endl;
Subdivide();
}
for (int i = 0; i < 4; i++)
{
if (quadrantPtr->at(first_child_index + i).Insert(ball))
{
return true;
}
}
}
}
void Quadrant::Display(sf::RenderWindow& myWindow)
{
myWindow.draw(m_boundary.boundary);
if (first_child_index != -1)
{
for (int i = 0; i < 4; i++)
{
quadrantPtr->at(first_child_index + i).Display(myWindow);
}
}
}
這是代表象限的 AABB 的邊界類:
class Boundary
{
private:
public:
sf::Vector2f m_Centre;
sf::Vector2f m_halfSize;
sf::RectangleShape boundary;
Boundary();
Boundary(const sf::Vector2f& centre, const sf::Vector2f& halfSize);
bool ContainsPoint(const Ball& ball) const;
~Boundary();
};
Boundary::Boundary()
{
}
Boundary::Boundary(const sf::Vector2f& Centre, const sf::Vector2f& HalfSize)
:m_Centre(Centre), m_halfSize(HalfSize)
{
boundary.setSize(m_halfSize + m_halfSize);
boundary.setOrigin(m_halfSize);
boundary.setPosition(m_Centre);
boundary.setFillColor(sf::Color::Transparent);
boundary.setOutlineColor(sf::Color::White);
boundary.setOutlineThickness(2);
}
bool Boundary::ContainsPoint(const Ball& ball) const
{
bool contains = false;
if (ball.ball.position.x > m_Centre.x - m_halfSize.x && ball.ball.position.x < m_Centre.x + m_halfSize.x)
{
if (ball.ball.position.y > m_Centre.y - m_halfSize.y && ball.ball.position.y < m_Centre.y + m_halfSize.y)
{
contains = true;
}
}
return contains;
}
您的Root
對構造函數來說是本地的。 也就是說,它在Quadtree
構建結束時被銷毀。 改為使其成為班級成員。
此外,您不需要使用new
創建向量,它們本身基本上就是指針。 也讓他們成為班級成員,並使用&
獲取地址以傳遞到Quadrant
(或傳遞引用)。
NB Member order 很重要,就是它們被初始化的順序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.