0

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;
liorr
  • 764
  • 5
  • 21
  • 1
    Doesn't look like it. One of the devs entertained a few ideas to work in non-const data in this old [mailing list](http://boost-geometry.203548.n3.nabble.com/Are-all-query-iterators-const-td4026626.html) e-mail. But that was in 2015 and today there is no non-const query iterator in the public namespace. – parktomatomi Oct 15 '20 at 05:52

1 Answers1

1

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;

Adam Wulkiewicz
  • 2,068
  • 18
  • 24