Boost r-tree "correct" way to access objects

515 views Asked by At

TLDR: is there a way to update object directly in a Boost r-tree (by setting the location class property to const, or something similar)?

More info:

I am using C++ Boost's R-tree to store objects with spatial coordinates (for reference, please see my previous question). For the sake of the discussion, let's assume my objects are City-ies with spatial cartesian coordinates and some class properties; say population and size.

Currently, I have a separate std::map whose keys are some indices and values are the City objects. In the tree, as suggested in the answer to my previous question, I store some struct whose fields are the City index and its coordinates. When I need update a City class property, all I do is search for the city in the tree, and update the std::map:

// The struct stored in the tree
struct CityRef {
        size_t index;
        point location;
};

typedef bgi::rtree< CityRef, bgi::quadratic<16>, bgi::indexable<CityRef>,  index::equal_to<CityRef> > rtree_t;

//A map storing the cities:
std::map<size_t, City *> cityDict;

I think that just for code readably, it would be much more comprehensible if I did not need to store a separate City map. Is there a way to directly update the object stored in the tree? I understand this may lead to unwanted behavior, as the tree needs to be re-balanced if the location property is ever changed. However, at least conceptually, it would be nice if there was a way to define just the location field as a const (so it couldn't be changed), and do something like:

City::City() {
const point location;
double population;
double size;
}

And store that object in the tree:

typedef bgi::rtree< City, bgi::quadratic<16>, index::indexable<City>,  index::equal_to<City> > rtree_t;

Then, it would be possible to use a nearest neighbor iterator rtree_t::const_query_iterator it scroll through the values, and do something like

it->population = newPopulation;
1

There are 1 answers

0
Adam Wulkiewicz On BEST ANSWER

No, it's not possible to store mutable values in the rtree right now.

You could store the point and index in the rtree and then the rest of the data in a different container. It could be vector/deque if the index is preserved (you don't remove elements from the container) or map if you need sorting by key or unoredered_map if you don't. So e.g.:

struct data_t { double population; double size; };
point_t point;

bgi::rtree<std::pair<point_t, size_t>, bgi::quadratic<16>> rt;
std::unordered_map<size_t, data_t> umap;
for (auto it = rt.qbegin(bgi::nearest(point, 3)); it != rt.qend(); ++it)
    data_t& data = umap[it->second];

Another option would be to use const_cast and be careful to not modify the location. So something like:

point_t point;
bgi::rtree<City, bgi::quadratic<16>> rt;
for (auto it = rt.qbegin(bgi::nearest(point, 3)); it != rt.qend(); ++it)
    const_cast<double&>(it->population) = 123.4;