boostr-tree

How to set Boost RTree coordinate system


this example, I wrote one method for allowing rtree.query to work: i want to get intersects with two segments

using Point2d =
    boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>;
using Segment2d = boost::geometry::model::segment<Point2d>;
using SegmentRtree =
    boost::geometry::index::rtree<Segment2d, boost::geometry::index::rstar<16>>;
          for (int point_index = 0;
               point_index + 1 < segment.line_segment().point_size();
               point_index++) {
            const Segment2d segment_in_range = {
                {segment.line_segment().point()[point_index].x(),
                 segment.line_segment().point()[point_index].y()},
                {segment.line_segment().point()[point_index + 1].x(),
                 segment.line_segment().point()[point_index + 1].y()}};
            uncrossable_segments_in_range.insert(segment_in_range);

Some of the errors I am getting:


/home/xx/xx/xx/xx/xx/xx/xx/xx.cc:220:66:   required from here
/home/xx/xx/xx/build_x86/_deps/boost-src/include/boost/geometry/strategies/index/services.hpp:31:5: error: static assertion failed: Not implemented for this coordinate system.
   31 |     BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Solution

  • It looks 100% like you've forgotten to include some header.

    The message doesn't state "you don't specify a coordinate system" (you do, it's in your point type). It says "the specialization (for this algorithm/strategy/trait etc...) for this combination has not been found".

    Code Forensics

    However, you don't show the includes, so we can't tell. Also, the code you do show refers to a lot of proprietary types not related to Boost Geometry (point_size(), line_segment(), point()[] all seem unrelated to Boost Geometry).

    Even the .x() and .y() contradict the point type you defined. point<> does not have these members. boost::geometry::model::d2::point_xy<> does, though.

    So, the best I can do is make up a lot (!!!) of code to make your code compile:

    Live On Coliru

    #include <boost/geometry.hpp>
    #include <boost/geometry/geometries/point_xy.hpp>
    #include <boost/geometry/geometries/segment.hpp>
    namespace bg  = boost::geometry;
    namespace bgm = bg::model;
    namespace bgi = bg::index;
    
    // using Point2d      = bgm::point<double, 2, bg::cs::cartesian>;
    using Point2d      = bgm::d2::point_xy<double, bg::cs::cartesian>;
    using Segment2d    = bgm::segment<Point2d>;
    using SegmentRtree = bgi::rtree<Segment2d, bgi::rstar<16>>;
    
    /////// stubs to make the code look like the question code...
    struct {
        auto const& line_segment() { return ls_; }
    
      private:
        struct {
            Segment2d data_;
            size_t    point_size() const { return 2; }
    
            struct proxy {
                Segment2d const& ref_;
    
                auto operator[](unsigned i) const {
                    switch (i) {
                    case 0: return ref_.first;
                    case 1: return ref_.second;
                    }
                    throw std::range_error("i");
                }
            };
            proxy point() const { return {data_}; }
        } ls_;
    } segment;
    
    struct Comparer {
        using Point = Point2d;
        using Base  = std::pair<Point2d, Point2d>;
        bool operator()(Point const& a, Point const& b) const {
            return std::tie(a.x(), a.y()) < std::tie(b.x(), b.y());
        }
        bool operator()(Base const& a, Base const& b) const {
            return operator()(a.first, b.first) ||
                (bg::equals(a.first, b.first) && operator()(a.second, b.second));
        }
    };
    std::set<Segment2d, Comparer> uncrossable_segments_in_range;
    /////// end stubs
    
    int main() {
        for (unsigned point_index = 0; point_index + 1 < segment.line_segment().point_size(); point_index++) {
            Segment2d segment_in_range{{segment.line_segment().point()[point_index].x(),
                                        segment.line_segment().point()[point_index].y()},
                                       {segment.line_segment().point()[point_index + 1].x(),
                                        segment.line_segment().point()[point_index + 1].y()}};
            uncrossable_segments_in_range.insert(segment_in_range);
        }
    }
    

    It would help a little to make your loop more readable:

    auto& ls = segment.line_segment();
    for (unsigned i = 0; i + 1 < ls.point_size(); i++) {
        auto&& p = ls.point();
        uncrossable_segments_in_range.emplace(Point2d{p[i].x(), p[i].y()},
                                              Point2d{p[i + 1].x(), p[i + 1].y()});
    }
    

    Now, this looks like improbable amounts of (poor) code to have to imagine. Also, it does nothing with rtree, which is supposedly your question?

    Brainwave - More reasonable code

    I just had a brainwave. Probably uncrossable_segments_in_range was supposed to be your rtree? And the whole loop was building the rtree from [some unrelated data structure]. Here's how I imagine you'd write that code:

    Live On Coliru

    #include <boost/geometry.hpp>
    #include <boost/geometry/geometries/segment.hpp>
    namespace bg  = boost::geometry;
    namespace bgm = bg::model;
    namespace bgi = bg::index;
    
    using Point2d      = bgm::point<double, 2, bg::cs::cartesian>;
    using Segment2d    = bgm::segment<Point2d>;
    using LineString   = bgm::linestring<Point2d>;
    using SegmentRtree = bgi::rtree<Segment2d, bgi::rstar<16>>;
    
    int main() {
        SegmentRtree segments;
    
        LineString input;
        bg::read_wkt("LINESTRING(2 0, 5 3, 8 0, 4 -4, 11 -4, 11 5, 14 5)", input);
        
        for (auto it = bg::segments_begin(input); it != bg::segments_end(input); ++it)
            segments.insert({*it->first, *it->second});
    
        for (auto& el : segments)
            std::cout << "in tree: " << bg::dsv(el) << std::endl;
    }
    

    Which prints

    in tree: ((2, 0), (5, 3))
    in tree: ((5, 3), (8, 0))
    in tree: ((8, 0), (4, -4))
    in tree: ((4, -4), (11, -4))
    in tree: ((11, -4), (11, 5))
    in tree: ((11, 5), (14, 5))
    

    Summary

    In all likelihood, you just had to add one of the includes you can cross-reference from my examples.