C++ 从boost::geometry::index::rtree中删除点时出现问题

C++ 从boost::geometry::index::rtree中删除点时出现问题,c++,boost,boost-geometry,C++,Boost,Boost Geometry,我在OSX上使用Boost1.56,通过自制软件安装 我遇到了一个编译问题——特别是,我似乎无法从boost::geometry::index::rtree中删除值 以下是我迄今为止提出的代码: #include <iostream> #include <vector> #include <string> #include <boost/geometry.hpp> #include <boost/geometry/geometries/poi

我在OSX上使用Boost1.56,通过自制软件安装

我遇到了一个编译问题——特别是,我似乎无法从boost::geometry::index::rtree中删除值

以下是我迄今为止提出的代码:

#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
  }
}
^
test.cc:71:10:注意:在成员函数的实例化中,此处请求“boost::geometry::index::rtree::remove”
tree.remove(结果集[0]);
^
/usr/local/cillar/boost/1.56.0/include/boost/mpl/assert.hpp:83:5:注意:候选函数[C=false]不可行:没有已知的从“boost::mpl::失败”的转换
************(boost::geometry::nyi::not_implemented_error::THIS_OPERATION_IS_not_或_not_not_implemented::**************)(types)“”到第一个参数的“typename assert::type”(又名“mplĀ::assert”)
int断言_失败(类型名称断言::类型);
^
test.cc:71:10:注意:在成员函数的实例化中,此处请求“boost::geometry::index::rtree::remove”
tree.remove(结果集[0]);
^
/usr/local/cillar/boost/1.56.0/include/boost/geometry/algorithms/detail/relate/relate.hpp:282:1:注意:忽略候选模板:替换失败[使用矩阵任务]=
boost::mpl::vector,Geometry1=boost::geometry::model::box,Geometry2=boost::geometry::model::box]
相关(几何量1常数和几何量1,
^

有人对可能出现的问题有想法吗?我很困惑。

我已经仔细查看了您的代码,它看起来很好。您只是在choosen坐标系中遇到了一个限制,您的坐标还没有得到完全支持

您可以通过更改坐标来验证这一点(这会使数据有点滑稽,但这里是关于编译成功的)。请参阅此测试程序,该程序显示了删除项的不同等效方法:

#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";
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
名称空间bg=boost::geometry;
名称空间bgi=bg::index;
名称空间bgm=bg::model;
//typedef bgm::point;
typedef bgm::point;
typedef bgm::box;
typedef std::对BoxIdPair;
int main(){
使用Tree=bgi::rtree;
树木;
//为了一个简单的例子,这里删除了一些树填充代码。
插入({点(24,19),点(35,26)},100});
插入({点(41112),点(54148)},150});
插入({点(34,24),点(36,100)},92});
插入({点(21,8),点(43,15)},8});
而(!tree.empty()){

std::cout这个限制似乎有点随意,特别是在这种情况下,因为它只适用于
remove
。这里有一个在dev邮件列表上询问时可以使用的最小示例:还请注意,当使用
最近的
谓词时,您将按照距离的增加顺序获得匹配,因此您可以更高效通过查询一次而不是在循环中重复查询一个项,请参阅,特别是库开发人员的注释。上述代码中存在严重问题。
remove()
可能会使迭代器无效!顺便说一句,这就是为什么它被称为
remove()
,而不是
erase()
。但我明白为什么这样做似乎很明显。我想,如果传递了rtree迭代器,编译可能会失败;如果为同一个rtree对象创建了迭代器,则运行时断言可能会失败。但是如果迭代器包装在其他类型的迭代器中(Boost.Range adapters)这个问题仍然存在。非常清楚地说,这个函数被称为
remove()
,因为应该向它传递一个值或一系列不属于rtree索引的值。STL的
erase()
使用一个指向容器元素的迭代器。顺便说一句,
remove()
不编译在CS中定义的框,因为内部
in()
用于决定在树遍历期间应检查哪个节点。而
in(box,box)
目前未针对非笛卡尔坐标系实现。
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,
^
#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";
}