【问题标题】:Cannot remove element from boost::geometry::index::rtree by its index无法通过索引从 boost::geometry::index::rtree 中删除元素
【发布时间】:2016-01-22 16:27:35
【问题描述】:

我正在创建一个boost geometry rtree

从我创建的示例页面:

typedef bg::model::point<float, 2, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
typedef std::pair<box, unsigned> value;

我想将value 元素添加到树中:

bgi::rtree< value, bgi::quadratic<16> > rtree;
box b(point(2.0f, 2.0f), point(2.5f, 2.5f));
// insert new value
rtree.insert(std::make_pair(b, 2));

现在我想知道是否可以通过知道 box 标识符来删除一个元素(或者如果可以设置更多具有相同 id 的元素,则可以删除它的所有元素)。

我想要做的是删除我上面添加的元素,比如调用类似的东西:

rtree.remove(2); // why I can't do this?

我怎样才能做到这一点?

【问题讨论】:

    标签: c++ boost r-tree boost-geometry


    【解决方案1】:

    您必须使用迭代器。可能的重载是

    remove(value_type const &)
    remove(Iterator, Iterator)
    remove(ConvertibleOrRange const &)
    

    首先,您应该通过搜索找到要删除的值(可能会运行查询,但我认为您不需要这样做,因为您的问题不存在。)

    因此,您可能想使用std::find_if。我不确定如何提高性能(不求助于反向映射)。我想你的分析器应该用来在那里提供保证。

    更新:概念证明

    天真的方法失败了:

    // UNDEFINED BEHAVIOUR:
    template <typename Rtree, typename Id>
    size_t remove_ids_loop(Rtree& rtree, Id const& id) {
        using V = typename Rtree::value_type;
        static_assert(sizeof(V) == 0, "don't use; UNDEFINED BEHAVIOUR!");
    
        size_t removed = 0;
        std::for_each(rtree.begin(), rtree.end(), [&](V const& v) { 
                if (id == v.second)
                    removed += rtree.remove(v);
            });
    
        return removed;
    }
    

    这是因为as documented:

    ⚠ 警告

    修改rtree可能会使迭代器失效。

    简单的方法:

    template <typename Rtree, typename Id>
    size_t remove_ids_bulk(Rtree& rtree, Id const& id) {
        using V = typename Rtree::value_type;
        std::vector<V> v;
        std::copy_if(rtree.begin(), rtree.end(), back_inserter(v), [id](V const& v) { return v.second == id; });
    
        return rtree.remove(v.begin(), v.end());
    }
    

    这通过将查询与删除分开来回避竞争。请注意,这可能更有效,因为我们一次通过了整个范围。

    注意:重复条目应该没问题,因为rtree::remove 一次只删除一个值。

    现场演示

    Live On Coliru

    #include <boost/geometry.hpp>
    #include <boost/geometry/index/rtree.hpp>
    
    namespace bg = boost::geometry;
    namespace bgi = bg::index;
    
    typedef bg::model::point<float, 2, bg::cs::cartesian> point;
    typedef bg::model::box<point> box;
    
    typedef std::pair<box, unsigned> value;
    
    template <typename Rtree, typename Id>
    size_t remove_ids_bulk(Rtree& rtree, Id const& id) {
        using V = typename Rtree::value_type;
        std::vector<V> v;
        std::copy_if(rtree.begin(), rtree.end(), back_inserter(v), [id](V const& v) { return v.second == id; });
    
        return rtree.remove(v.begin(), v.end());
    }
    
    // UNDEFINED BEHAVIOUR:
    template <typename Rtree, typename Id>
    size_t remove_ids_loop(Rtree& rtree, Id const& id) {
        using V = typename Rtree::value_type;
        static_assert(sizeof(V) == 0, "don't use; UNDEFINED BEHAVIOUR!");
    
        size_t removed = 0;
        std::for_each(rtree.begin(), rtree.end(), [&](V const& v) { 
                if (id == v.second)
                    removed += rtree.remove(v);
            });
    
        return removed;
    }
    
    int main() {
        //I want to add value elements to the tree:
    
        bgi::rtree< value, bgi::quadratic<16> > rtree;
        box b(point(2.0f, 2.0f), point(2.5f, 2.5f));
        // insert new value
        rtree.insert(std::make_pair(b, 2));
        std::cout << "Elements: " << rtree.size() << "\n";
    
        // remove id 2
        remove_ids_bulk(rtree, 2u);
        std::cout << "Elements: " << rtree.size() << "\n";
    }
    

    打印

    Elements: 1
    Elements: 0
    

    【讨论】:

    • 添加关于迭代器失效规则的概念证明和公平警告。
    • 一个小评论,我知道你已经在更新中解决了这个问题,但要澄清一下。您写道:“首先,您应该通过搜索值类型来找到迭代器”。采用范围/迭代器的remove() 函数期望删除一系列元素,而不是一对指向存储在 rtree 中应删除的元素的迭代器。换句话说,它不像 erase() 在 STL 容器中那样工作,顺便说一句,这就是它被称为 remove() 的原因。
    • @AdamWulkiewicz 同意。修正了令人困惑的措辞。
    • 老问题,但你能评论一下删除的性能吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    • 1970-01-01
    • 2012-08-03
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    相关资源
    最近更新 更多