简体   繁体   中英

Boost r-tree "correct" way to access objects

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;

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 eg:

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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