Yes, as far as your compiler can compile such deep recursive
tamplates.
AFAIU this is different use-case than the one mentioned above, where
samples are stored?
It could but is not supported. Otherwise the user could modify the
part of the stored Value keeping the geometrical data which would
brake the index. This is similar thing to the std::set<>
storing const Value and std::map<> storing const Key. And it's
a spatial index, not container.
Initially I thought about implementing a Container or two Containers
with the interface similar to std::set<> and std::map<>
but decided to go into the direction of the Index capable to store
arbitrary types.
We could of course return to the idea of Containers and think about
what should be done in order to implement some based on the R-tree
code. Should they be separate templates or could the rtree be
modified? E.g. what if the rtree for passed Value =
std::pair<Box, Id> always store std::pair<Box const,
Id>. Would it brake users' code? Probably yes. Should we rather
implement geometry::container::rtree_map<Indexable, Data> and
always store std::pair<Indexable const, Data>? Etc.
Custom, user-defined visitors would definietly work but might stop
compiling with some future release of Boost.Geometry if something
were changed internally.
It depends what you'd like to do. The visitors are quite simple to
write, they're similar to Boost.Variant static visitors. E.g. take a
look at
https://github.com/boostorg/geometry/blob/develop/include/boost/geometry/index/detail/rtree/utilities/print.hpp
line 132. It's a visitor recursively printing the contents of the
R-tree.
Definietly it could not just update the stored value. It might
naiively expand all of the ancestor nodes boxes but this would
result in great overlap of the nodes. So instead this moving_visitor
should search for the old value top-down remove it from the node
(handle underflow locally), search for the place to insert the new
one somewhere near the old node bottom-up and down again (handle
overflow locally) and then handle underflow and overflow globally
bottom-up. To implement it the inserting and removing visitors of
all balancing algorithms should probably be searched for parts which
could be reused, parts of the algorithms run per level. This in fact
could be a nice addon to the R-tree and could be a part of the
official interface.
It's very probable that in most of the cases the Value would be
moved inside the same node or somewhere very close. But still we'd
be forced to search for the old value which would be O(logN),
however in the case of the R-tree it could be quite ok since the
R-tree might have small number of levels. E.g. for Max = 16 to
represent 1M Values one'd need 5 levels.
It would be possible to implement a container similar to
std::map<> providing non-invalidated Iterators to Values. They
could be passed to the Rtree to indicate a position of the removed
Value (this would be O(1)). And they had to be not invalidated by
the remove() because otherwise it would be not possible to remove
more Values than one. To do this we'd be forced to add some pointers
to parents to the R-tree nodes and to allocate the memory for each
ValueNode separately but this could be done. On the other hand,
going bottom-up we'd be forced to search the parent node for the
child we came from (O(Max)). So we'd get the non-invalidated
Iterators and (probably) faster remove but the queries would
(probably) be slower.
The above are only my predictions since all of those things should
really be implemented and the performance measured to be sure.
Yes, but:
1. it could be not safe since one could modify the object pointed by
the shared_ptr (and modify the Indexable data or in other words a
Key),
2. it would probably be slower than storing the Geometry directly in
the R-tree because dereferencing shared_ptrs<> would ruin
cacheing of Values.
So I'd advice storing std::ptr<Box, ID> or std::ptr<Box,
shared_ptr<>>, but one can use whatever he like.
It would make sense in both situations to use some kind of spatial
indexing or partitioning technique. In some use-cases the R-tree
could be better than in the others.
Yes, currently the old value should be removed and the new one
inserted.
Bulk loading would definietly be faster than inserting each value
separately. I tested its speed and for Points it's as fast as the
kd-tree created in the contigeous memory using a recursive
algorithm.
The difference in the time of rebuilding the whole tree and
reinserting values would depend on the number of values. If it were
some big number it would probably be faster to create the container
from scratch.
A reasonable approach would be to pick some container/library which
is fairy simple to use and then check the performance, profile to
find bootlenecks and if they were caused by the container, test some
other one or think about an other algorithm.
Regards,
Adam