问题
I'm using boost 1.56 on OS X, installed through homebrew.
I'm running into a compilation problem - specifically, it appears that I cannot remove values from a boost::geometry::index::rtree.
Here's the code I've come up with so far:
#include <iostream>
#include <vector>
#include <string>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/index/rtree.hpp>
namespace bg = boost::geometry;
namespace bgm = bg::model;
namespace bgi = bg::index;
typedef bgm::point<float, 2, bg::cs::spherical_equatorial<bg::degree> > Point;
typedef bgm::box<Point> Box;
typedef std::pair<Box, int> BoxIdPair;
int main(int argc, char** argv) {
bgi::rtree<BoxIdPair, bgi::rstar<16>> tree;
// Some tree filling code excised from here for the sake of a minimal example.
BoxIdPair b1 = std::make_pair(Box(Point(24, 19), Point(35, 26)), 100);
BoxIdPair b2 = std::make_pair(Box(Point(41, 112), Point(54, 148)), 150);
BoxIdPair b3 = std::make_pair(Box(Point(34, 24), Point(36, 100)), 92);
BoxIdPair b4 = std::make_pair(Box(Point(21, 8), Point(43, 15)), 8);
tree.insert(b1);
tree.insert(b2);
tree.insert(b3);
tree.insert(b4);
while (!tree.empty()) {
std::cout << "Tree contains " << tree.size() << "box-id values." << std::endl;
// 1. Choose arbitrary BoxIdPair to be the leader of a new canopy.
// Remove it from the tree. Insert it into the canopy map, with its corresponding id.
Point origin(0.0, 0.0);
std::vector<BoxIdPair> result_set;
tree.query(bgi::nearest(origin, 1), std::back_inserter(result_set));
Box b = result_set[0].first;
int id = result_set[0].second;
tree.remove(result_set[0]); // This is the line that is giving me difficulty, I think.
// Additional code cut for minimal example
}
}
This code does not compile! Specifically, here is the invocation:
clang++ -g -std=c++11 -L/usr/local/Cellar/boost/1.56.0/lib -I/usr/local/Cellar/boost/1.56.0/include test.cc -o test
And here are the errors emitted by the compiler (link to pastebin for brevity): http://pastebin.com/d7E0A4Ee
The three relevant errors are:
test.cc:71:10: note: in instantiation of member function 'boost::geometry::index::rtree<std::__1::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, int>, boost::geometry::index::rstar<16, 4, 4, 32>,
boost::geometry::index::indexable<std::__1::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, int> >,
boost::geometry::index::equal_to<std::__1::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, int> >,
std::__1::allocator<std::__1::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, int> > >::remove' requested here
tree.remove(result_set[0]);
^
/usr/local/Cellar/boost/1.56.0/include/boost/geometry/strategies/concepts/within_concept.hpp:183:21: note: candidate template ignored: couldn't infer template argument 'ApplyMethod'
static void apply(ApplyMethod const&)
^
test.cc:71:10: note: in instantiation of member function 'boost::geometry::index::rtree<std::__1::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, int>, boost::geometry::index::rstar<16, 4, 4, 32>,
boost::geometry::index::indexable<std::__1::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, int> >,
boost::geometry::index::equal_to<std::__1::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, int> >,
std::__1::allocator<std::__1::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, int> > >::remove' requested here
tree.remove(result_set[0]);
^
/usr/local/Cellar/boost/1.56.0/include/boost/mpl/assert.hpp:83:5: note: candidate function [with C = false] not viable: no known conversion from 'boost::mpl::failed
************(boost::geometry::nyi::not_implemented_error<boost::geometry::info::BOX, boost::geometry::info::BOX, void>::THIS_OPERATION_IS_NOT_OR_NOT_YET_IMPLEMENTED::************)(types<boost::geometry::info::BOX,
boost::geometry::info::BOX, void>)' to 'typename assert<false>::type' (aka 'mpl_::assert<false>') for 1st argument
int assertion_failed( typename assert<C>::type );
^
test.cc:71:10: note: in instantiation of member function 'boost::geometry::index::rtree<std::__1::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2,
boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, int>, boost::geometry::index::rstar<16, 4, 4, 32>,
boost::geometry::index::indexable<std::__1::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, int> >,
boost::geometry::index::equal_to<std::__1::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, int> >,
std::__1::allocator<std::__1::pair<boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, int> > >::remove' requested here
tree.remove(result_set[0]);
^
/usr/local/Cellar/boost/1.56.0/include/boost/geometry/algorithms/detail/relate/relate.hpp:282:1: note: candidate template ignored: substitution failure [with MatrixOrMask =
boost::mpl::vector<boost::geometry::detail::relate::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'>, boost::geometry::detail::relate::static_mask<'*', 'T', 'F', '*', '*', 'F', '*', '*', '*'>,
boost::geometry::detail::relate::static_mask<'*', '*', 'F', 'T', '*', 'F', '*', '*', '*'>, boost::geometry::detail::relate::static_mask<'*', '*', 'F', '*', 'T', 'F', '*', '*', '*'>, mpl_::na, mpl_::na, mpl_::na, mpl_::na,
mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, Geometry1 = boost::geometry::model::box<boost::geometry::model::point<float, 2,
boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > >, Geometry2 = boost::geometry::model::box<boost::geometry::model::point<float, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> >
>]
relate(Geometry1 const& geometry1,
^
Anyone have thoughts on what might be going wrong? I'm mystified.
回答1:
I've looked your code over and it seems fine. You're just running into a limitation with the choosen coordinate system where your coordinate isn't fully supported (yet).
You can verify this by changing the coordinate (this renders the data a bit funny, but it's about compilation success here). See this test program that shows different, equivalent approaches to deleting items:
Live On Coliru
#include <iostream>
#include <vector>
#include <string>
#include <boost/geometry.hpp>
#include <boost/geometry/io/io.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/index/distance_predicates.hpp>
#include <boost/geometry/index/predicates.hpp>
#include <boost/geometry/index/rtree.hpp>
namespace bg = boost::geometry;
namespace bgi = bg::index;
namespace bgm = bg::model;
//typedef bgm::point<float, 2, bg::cs::spherical_equatorial<bg::degree> > Point;
typedef bgm::point<float, 2, bg::cs::cartesian> Point;
typedef bgm::box<Point> Box;
typedef std::pair<Box, int> BoxIdPair;
int main() {
using Tree = bgi::rtree<BoxIdPair, bgi::rstar<16> >;
Tree tree;
// Some tree filling code excised from here for the sake of a minimal example.
tree.insert({ { Point(24, 19), Point(35, 26) }, 100 });
tree.insert({ { Point(41, 112), Point(54, 148) }, 150 });
tree.insert({ { Point(34, 24), Point(36, 100) }, 92 });
tree.insert({ { Point(21, 8), Point(43, 15) }, 8 });
while (!tree.empty()) {
std::cout << "Tree contains " << tree.size() << " box-id values." << std::endl;
// 1. Choose arbitrary BoxIdPair to be the leader of a new canopy.
// Remove it from the tree. Insert it into the canopy map, with its
// corresponding id.
Point origin(0.0, 0.0);
auto first = bgi::qbegin(tree, bgi::nearest(origin, 1)),
last = bgi::qend(tree);
if (first != last) {
tree.remove(*first); // assuming single result
}
}
std::cout << "Tree emptied\n";
}
Note Don't use the iterator-based
remove()
with iterators into the same rtree becauseremove()
may invalidate them.Note All of the
remove()
overloads end up deferring toraw_remove
internally.
I'm not completely sure why it's not working. It appears that a trait that determines whether an index operation is interruptible
is not defined for this particular combinarion of Geometries.
Update Thanks to Adam's comment below we know that it is because internally within()
is used to decide which node should be checked during the tree traversal. And within(box, box)
is currently not implemented for non-cartesian coordinate systems.
来源:https://stackoverflow.com/questions/27613220/issue-with-removing-points-from-a-boostgeometryindexrtree