Question

I use a quad tree as a datastructure to store points. As I need to find in a fast way all points in certain area.

However I need to move the points. In my C++ program. As the movement happens to all points but for every point in an different direction I currently destroy my quadtree and rebuild it, which causes lots of allocation and deletion.

My question is therefore is there a better datastructure for this kind of problem?

I have the following requirements: I have n-Points.

I need to get in an fast way all points in a given certain area. With my quadtree this is about O(log(n)). However this operation is called m times where m > n therefore it is about O(m*log(n)).

I need to move all points. At the moment this runs in about O(n*logn). This method is only called once for all m.

However I find this solution at the moment unsatisfactory. As I always destroy my quadtree and rebuild it which causes an overhead due to the allocation.

UPDATE: The points are not uniformely distributed. There are positions where they are dense and some position where there are few points.

Here is some simplified code. Here the code of the pointer which are stored:

class Point
{
    public:
    Point(double x, double y):x(x),y(y){};

    void movePoint(double ux, double uy);

    double x;
    double y;
};

here is the interface of the quad tree

class QuadTree
{
public:
    QuadTree(double north, double west, double south, double east,
             int maxItems);

    //inserts a point into the tree runs in log(n)
    bool put(Point* pt);
    // returns all point in the rectange defined by the four variables runs in log(n)
    std::vector<Point*> get(double north, double west, double south, double east);
    // deletes everything in the quad tree
    void clear();

private:

    QuadTreeNode* top_=nullptr;

};

and here the interface of the QuadTreeNode with the get and put method implementation to show how a Point is stored.

class QuadTreeNode
{
public:

    QuadTreeNode(double north, double west, double south, double east,
                 int maximumItems);

    ~QuadTreeNode();

    //split the node if to much items are stored.
    void split();
    //returns the children of the node
    QuadTreeNode* getChild(double x, double y);

    bool put(Point* leaf){
      if (children_ == nullptr) {
        items_.push_back(leaf);

        if (items_.size() > maxItems_)
            split();
        return true;
      } else {
        QuadTreeNode* node = getChild(leaf->getX(), leaf->getY());
        if (node != nullptr) {
            return node->put(leaf);
        }
       }
      return false;
    }

    std::vector<Point*> QuadTreeNode::get(QuadRectangle rect, std::vector<Point*>& vector) {
      if (children_ == nullptr) {
        for (Point* pt : items_) {
            if (rect.pointWithinBounds(pt->getX(),pt->getY())) {
                vector.push_back(pt);
            }
        }
      } else {
        for (QuadTreeNode* child : *children_) {
            if (child->bounds_.within(rect)) {
                child->get(rect, vector);
            }
        }
      }
      return vector;
}

    std::vector<Point*> items_;

    unsigned int maxItems_;

    std::array<QuadTreeNode*,4>* children_ = nullptr;

    QuadRectangle bounds_;    
};
Was it helpful?

Solution

Some ideas that come to mind:

  1. For each moved point, check whether it moved out of the bounding rectangle (bounds_). If yes, remove it from the tree. After moving all points, either insert them into the same tree, or into another tree. Every once in a while (e.g. when the size of the other tree becomes 1/10 of the main tree), rebuild everything.
  2. When splitting nodes, you probably calculate a bounding rectangle for points in each child note. When doing it, allow some margin into the bounds, so it would be possible to move each point a few iterations without it getting out of bounds.

These ideas don't help complexity (it remains O(n*log(n)), but maybe improve speed by some factor.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top