简体   繁体   English

C++ 中的四叉树实现:异常抛出读取访问冲突

[英]Quadtree implementation in C++ : Exception Thrown Read Access Violation

I am attempting to implement a quadtree in C++, however I have a read access violation that I have been spending hours trying to figure out.我试图在 C++ 中实现四叉树,但是我有一个读访问冲突,我花了几个小时试图弄清楚。 Note that I have put all the member variables in public, just for debugging efforts.请注意,我已将所有成员变量公开,仅用于调试工作。

Whenever I attempt to subdivide a quadrant, ie the root quadrant, I get每当我试图细分一个象限,即根象限,我得到

Exception thrown: read access violation.抛出异常:读取访问冲突。 std::_Vector_alloc > >::_Myend(...) returned 0xDDDDDDE9. std::_Vector_alloc > >::_Myend(...) 返回 0xDDDDDDE9。

The quadtree consists of a pointer to an array of contiguous Quadrants, as well as points.四叉树由指向连续象限数组的指针和点组成。 These pointers are passed onto every quadrant, so they are able to write to it without making copies.这些指针被传递到每个象限,因此它们可以在不复制的情况下写入它。

What am I doing wrong + could you suggest improvements?我做错了什么+你能提出改进建议吗?

Here is my Quadtree Class:这是我的四叉树类:

  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);

}

The quadtree houses all of the quadrants, as well as the data storage.四叉树包含所有象限以及数据存储。

Here is the Quadrant class:这是象限类:

 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);
        }
    }
}

Here is the boundary class which represents the AABB for the quadrant:这是代表象限的 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;
}

Your Root is local to the constructor.您的Root对构造函数来说是本地的。 That is, it is destroyed right at the end of Quadtree construction.也就是说,它在Quadtree构建结束时被销毁。 Make it a class member instead.改为使其成为班级成员。

Also you don't need to create vectors with new , they are basically pointers themselves.此外,您不需要使用new创建向量,它们本身基本上就是指针。 Make them class members too, and use & to take address to pass into Quadrant (or pass a reference).也让他们成为班级成员,并使用&获取地址以传递到Quadrant (或传递引用)。

NB Member order is important, it is the order in which they are initialized. NB Member order 很重要,就是它们被初始化的顺序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM