How to set Boost RTree coordinate system

46 Views Asked by At

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(
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1

There are 1 best solutions below

0
sehe On BEST ANSWER

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.