0

I am new to boost and c++. I am trying to code r tree using boost library. In my code, i want to store some information x at each internal node. I have two questions now.

1) How to perform traversing(depth-first) in the r star tree?

2) Suppose I can traverse the nodes of tree. There needs to be some member variables defined for the Box(INTERNAL node) class where I can store x at each node. What would be appropriate and efficient method for it?

1 Answers1

0

From reading your comments I get an impression that you only want to store additional data in points stored in the R-tree and not to store additional data in the internal nodes of the R-tree. So here is an example showing how to store points with additional data and how to perform a query to get some of them. In the example I also show how to achieve the same with std::pair holding a point and some additional data which works by default and you do not have to register your own point type.

Includes:

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <vector>
#include <iostream>

Namespaces for convenience:

namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;

Definition of your own point type with 2-d coordinates and additional data (color):

enum color {red, green, blue};

struct my_point
{
    double x, y;
    color c;
};

Adaptation of my_point to Boost.Geometry Point concept with a macro so the library knows that this struct is a 2-d Point and how to get the coordinates:

BOOST_GEOMETRY_REGISTER_POINT_2D(my_point, double, bg::cs::cartesian, x, y)

Some Boost.Geometry models that will be used as well:

typedef bg::model::point<double, 2, bg::cs::cartesian> bg_point;
typedef bg::model::box<bg_point> bg_box;

Main:

int main()
{
    {

Creation of the R-tree and insertion of several points:

        bgi::rtree<my_point, bgi::rstar<4> > rtree;
        rtree.insert(my_point{ 0, 0, red });
        rtree.insert(my_point{ 1, 1, green });
        rtree.insert(my_point{ 2, 5, blue });
        rtree.insert(my_point{ 7, 3, red });
        rtree.insert(my_point{ 8, 8, green });
        rtree.insert(my_point{ 1, 9, blue });

Query for points that intersect the following box and are red:

        std::vector<my_point> res;
        rtree.query(bgi::intersects(bg_box{ {1, 1}, {8, 8} })
                 && bgi::satisfies([](my_point const& p) {
                        return p.c == red;
                    }),
                    std::back_inserter(res));

Print the result:

        for (my_point const& p : res)
            std::cout << bg::wkt(p) << std::endl;
    }

The same but std::pair<bg_point, color> is used instead of my_point so no registration is needed:

    {
        bgi::rtree<std::pair<bg_point, color>, bgi::rstar<4> > rtree;
        rtree.insert(std::pair<bg_point, color>{ {0, 0}, red });
        rtree.insert(std::pair<bg_point, color>{ {1, 1}, green });
        rtree.insert(std::pair<bg_point, color>{ {2, 5}, blue });
        rtree.insert(std::pair<bg_point, color>{ {7, 3}, red });
        rtree.insert(std::pair<bg_point, color>{ {8, 8}, green });
        rtree.insert(std::pair<bg_point, color>{ {1, 9}, blue });

        std::vector<std::pair<bg_point, color> > res;
        rtree.query(bgi::intersects(bg_box{ { 1, 1 },{ 8, 8 } })
                 && bgi::satisfies([](std::pair<bg_point, color> const& p) {
                        return p.second == red;
                    }),
                    std::back_inserter(res));

        for (std::pair<bg_point, color> const& p : res)
            std::cout << bg::wkt(p.first) << std::endl;
    }
}

The program above prints the following line two times:

POINT(7 3)

This is the only one red point which intersects the box.


Original answer (if you indeed want to modify the internal structure of the R-tree):

What you want to do is not supported from the public R-tree interface. You'd have to play with the internals which might change in the future.

  1. Here is a thread explaining how you can write a visitor to traverse the R-tree nodes.

  2. Using your own node types is harder. You'd have to:

    1. add new node tag like this
    2. specialize internal and leaf nodes (adding members you like in nodes) and all other required classes for this tag like in this file
    3. implement your own R-tree parameters type, e.g. based on bgi::rstar, like this
    4. specialize bgi::detail::rtree::options_type in order to tell the R-tree what nodes should be used for your parameters type like this

    See also this node implementation used for R-tree testing. This is a node which can throw an exception on construction. It's used to test exception-safety.

Adam Wulkiewicz
  • 2,068
  • 18
  • 24
  • https://stackoverflow.com/questions/18061728/how-to-inherit-from-boostgeometrymodelpoint i was trying to do this way, by using my own box type as internal node derived from box class. Would this be correct? – user9500575 May 07 '19 at 23:21
  • @user9500575 You can of course use your own box class and store objects of this class in the R-tree. Then query the R-tree for the objects as usual (see the documentation). But is this what you wanted to do originally? I though you wanted to store additional data in the internal nodes? Your comment suggests that you simply want to store additional data together with values/objects stored in the R-tree without affecting the internal nodes. Could you clarify what would you like to use the R-tree for? – Adam Wulkiewicz May 08 '19 at 15:01
  • I want to store additional variables at the internal nodes, earlier i thought it wont be possible to modify internal node so used a derived class. I think both would serve the same purpose(or not)?? however i don't understand how can I access them while visiting as you suggested in 1 as the internal node accepts a box type as parameter. – user9500575 May 08 '19 at 23:57
  • This is why I wrote how to implement your own nodes in 2 an store whatever information you like in them, e.g. additional variable in node, container of some measurements for children nodes, etc. Another possibility is to modify the implementation however you like, change the Box type used in the R-tree etc. But then you'll be forced to keep your copy of the library, maintain the code etc. But I'm wondering, what are you doing exactly? What kind of data do you want to store in the nodes and what is the purpose of this? Maybe it would be possible to find another solution for your problem. – Adam Wulkiewicz May 13 '19 at 11:28
  • this seems really tough to understand, i am doing something similar to http://boost-geometry.203548.n3.nabble.com/Rtree-in-a-Hierarchical-Method-td4025859.html – user9500575 May 20 '19 at 12:38
  • i get your explanation but cannot figure out how to exactly do it. I have seen a lot of questions asking similar queries but couldn't found a proper answer(except for hierarchically traversing). May be,if possible, please post a simple example code where a person can use his own point type, box type and store additional variables at internal nodes while visiting. Thanks for answers. – user9500575 May 20 '19 at 13:07
  • Ok, I'll prepare an example but I need to know a few things. What additional information would you like to store with your points in the R-tree? What additional information would you like to store in the internal nodes? How should the query using this information work? – Adam Wulkiewicz May 21 '19 at 15:30
  • currently, i am not very sure about implementation, i am trying some things(also learning), if it can be done. Points are simple points, but just for FLEXIBILITY and learning purpose, i want to store "my points". So,a general query like DFS on rtree while storing some Integer(or any) value at internal nodes. Then, re-traversing to Get those values. This simple example would be helpful for all. – user9500575 May 23 '19 at 22:31
  • @user9500575 I updated the answer. I get the impression that this is what you're asking about. Let me know if that's correct. – Adam Wulkiewicz May 25 '19 at 21:04
  • thats useful,thanks. although my major concern was to store some variables at internal nodes. "So,a general query like DFS on rtree while storing some Integer(or any) value at internal nodes." – user9500575 May 27 '19 at 01:06
  • basically, i need a visitor kind of implementation as in 1, just with additional 1-2 step which allows storing at internal nodes. – user9500575 May 28 '19 at 01:54