naivebird
naivebird

Reputation: 33

boost geometry within result not correct

#include <iostream>
#include <list>

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>


int main()
{

  using Point = boost::geometry::model::d2::point_xy<double>;
  using MultiPoint = boost::geometry::model::multi_point<Point>;

  MultiPoint test_poly;
  boost::geometry::append(test_poly, Point(2, 0));
  boost::geometry::append(test_poly, Point(-2, 0));
  boost::geometry::append(test_poly, Point(0, 2));
  boost::geometry::append(test_poly, Point(2, 0));

  std::cout << "within_result: "
            << boost::geometry::within(Point(0, 1), test_poly) << std::endl;

  return 0;
}

Why the result is false, although (0,0) is obviously inside the polygon? Is it the problem caused by multipoint?

Upvotes: 2

Views: 156

Answers (1)

sehe
sehe

Reputation: 393064

Yes. (0,0) is obviously inside the polygon.

You call the variable a test_poly but your model isn't a polygon. Multi-points do not have any area. The only way for a point to be "within" the multipoint, is for the exact point to be in the set of points.

Compare with the below testbed:

Live On Compiler Explorer

#include <boost/core/demangle.hpp>
#include <iostream>

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>

namespace bg     = boost::geometry;
using Point      = bg::model::d2::point_xy<double>;
using Polygon    = bg::model::polygon<Point>;
using MultiPoint = bg::model::multi_point<Point>;
using MultiPoly  = bg::model::multi_polygon<Polygon>;

template <typename Geometry> void buildBox(int offset, Geometry& g) {
    using P = typename bg::point_type<Geometry>::type;
    bg::append(g, P(offset, 0));
    bg::append(g, P(-offset, 0));
    bg::append(g, P(0, offset));
    bg::append(g, P(offset, 0));
}

void buildBox(int offset, MultiPoly& g) { buildBox(offset, g.emplace_back()); }

template <typename Geometry> void do_test() {
    Geometry g;
    buildBox(2, g);

    std::cout << "\n--- " << boost::core::demangle(typeid(Geometry).name())
              << " --- \n"
              << bg::wkt(g) << "\n";

    if (std::string reason; not bg::is_valid(g, reason)) {
        std::cout << "trying to correct: " << reason << "\n";
        bg::correct(g);
        std::cout << " -> (" << bg::wkt(g) << ")\n";
    }

    for (auto test : {Point{0, 1}, {0, 2}, {0, 3}})
        std::cout << "within(" << bg::wkt(test)
                  << ", g): " << bg::within(test, g) << std::endl;
}

int main() {
    std::cout << std::boolalpha;
    do_test<MultiPoint>();
    do_test<Polygon>();
    do_test<MultiPoly>();
}

Which prints

--- boost::geometry::model::multi_point<boost::geometry::model::d2::point_xy<double, boost::geometry::cs::cartesian>, std::vector, std::allocator> ---
MULTIPOINT((2 0),(-2 0),(0 2),(2 0))
within(POINT(0 1), g): false
within(POINT(0 2), g): true

--- boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double, boost::geometry::cs::cartesian>, true, true, std::vector, std::vector, std::allocator, std::allocator> ---
POLYGON((2 0,-2 0,0 2,2 0))
within(POINT(0 1), g): true
within(POINT(0 2), g): false

--- boost::geometry::model::multi_polygon<boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double, boost::geometry::cs::cartesian>, true, true, std::vector, std::vector, std::a
llocator, std::allocator>, std::vector, std::allocator> ---
MULTIPOLYGON(((2 0,-2 0,0 2,2 0)))
within(POINT(0 1), g): true
within(POINT(0 2), g): false

Upvotes: 2

Related Questions