Boost logo

Geometry :

Subject: [geometry] Trouble with polygon/box intersection when polygon/box point types are different
From: Gratton, Michael (gratton_at_[hidden])
Date: 2016-05-16 12:48:52


Hello,

I'm trying to adapt polygons using Eigen::Vector2d point types (http://eigen.tuxfamily.org) for use with boost::geometry. Things mostly work great, but the rtree implementation uses the internal boost::geometry box type, and I get errors when attempting to intersect my Eigen polygon with the internal box.

I made a small program to isolate the compilation error I get:

%<------------------------------------------------
#include <Eigen/Core>
#include <Eigen/StdVector>
#include <Eigen/Geometry>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/geometries/register/box.hpp>
#include <boost/geometry/geometries/register/ring.hpp>
#include <boost/geometry/geometries/register/linestring.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry.hpp>

using Eigen::Vector2d;
typedef std::vector<Vector2d, Eigen::aligned_allocator<Vector2d> > EigenVector2d;

BOOST_GEOMETRY_REGISTER_POINT_2D(Vector2d, double, cs::cartesian, coeffRef(0), coeffRef(1))
BOOST_GEOMETRY_REGISTER_LINESTRING(EigenVector2d)
BOOST_GEOMETRY_REGISTER_BOX(Eigen::AlignedBox2d, Vector2d, min(), max());

typedef boost::geometry::model::polygon<
                    Vector2d, // Point type
               true, // Orientation is counter-clockwises in NED sense (south-east-north-west)
               false, // Closure is implied (last point != first point)
               std::vector, // Store for points (efficient if all points known in advance)
               std::vector, // Store for rings (efficient if all holes known in advance)
               Eigen::aligned_allocator // Need to allocate Vector2d with special allocator
>
               EigenPolygon;

int main(int argc, char** argv)
{
    namespace bg = boost::geometry;
    EigenVector2d point(3);
    point[0] << 0.5, 0.5;
    point[1] << 0.5, 6.0;
    point[2] << -1.0, 2.0;
    EigenPolygon poly;
    bg::append(poly, point);
    Vector2d ll(0,0);
    Vector2d ur(5.0,5.0);
    Eigen::AlignedBox2d box(ll, ur);
    std::cout << "poly intersect box? " << bg::intersects(poly, box) << "\n";
    bg::model::box<bg::model::point<double, 2ul, bg::cs::cartesian> > bbox;
    bbox.min_corner().set<0>(ll(0));
    bbox.min_corner().set<1>(ll(1));
    bbox.max_corner().set<0>(ur(0));
    bbox.max_corner().set<1>(ur(1));
    // Fails
    std::cout << "poly intersect bbox? " << bg::intersects(poly, bbox) << "\n";
    bg::model::polygon<bg::model::point<double, 2ul, bg::cs::cartesian>, true, false> poly2;
    bg::append(poly2, point);
    std::cout << "poly2 intersect bbox? " << bg::intersects(poly2, bbox) << "\n";
    // Fails
    std::cout << "poly2 intersect box? " << bg::intersects(poly2, box) << "\n";
}
%<------------------------------------------------------------------

I don't know if I am doing something wrong with the registration macros, but it looks okay to me. Working from the 1.60 source, I found that boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp_at_222 is trying to use a strategy::apply that assumes Point1 is the same type as Point2. If I change

    intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk,
                      Point2 const& qi, Point2 const& qj, Point2 const& qk,
                      RobustPolicy const& robust_policy)
        : base(pi, pj, pk, qi, qj, qk, robust_policy)
        , m_result(strategy::apply(segment_type1(pi, pj),
                                   segment_type2(qi, qj),
                                   robust_policy,
                                   base::rpi(), base::rpj(),
                                   base::rqi(), base::rqj()))
        , m_robust_policy(robust_policy)
    {}

to read

    intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk,
                      Point2 const& qi, Point2 const& qj, Point2 const& qk,
                      RobustPolicy const& robust_policy)
        : base(pi, pj, pk, qi, qj, qk, robust_policy)
        , m_result(strategy::apply(segment_type1(pi, pj),
                                   segment_type2(qi, qj),
                                   robust_policy))
        , m_robust_policy(robust_policy)
    {}

then everything builds and works. Looking inside, it looks like the later makes copies of the four points, storing them in the point type of the first segment type. So this change would be a bit of a performance hit compared to what is already there.

Is this a bug or am I mixing something up with my custom polygon type?

Thanks,

Michael Gratton, Ph.D. | Senior Research Analyst

Metron | Computing and Engineering Technologies for Unmanned Systems (CETUS) Division

1818 Library St Ste 600 | Reston VA 20190

703.326.2833 | gratton_at_[hidden]<mailto:gratton_at_[hidden]>


Geometry list run by mateusz at loskot.net