Home > Back-end >  Why doesn't i get any intersections of these polygons?
Why doesn't i get any intersections of these polygons?

Time:11-16

I learn how to use boost::polygon library with custom polygons. I took an example with usage of custom polygons and tried to get intersections of these. I doesn't get any intersection and can't understand why. Also, you can see this constructor

CPoint(boost::polygon::point_data<int> pd) 

I can't compile my program without it. Can someone explain, why i need it? What do i do wrong ?

/*
Copyright 2008 Intel Corporation

Use, modification and distribution are subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
*/
#include <boost/polygon/polygon.hpp>
#include <cassert>
#include <list>
namespace gtl = boost::polygon;
using namespace boost::polygon::operators;


template <typename Polygon>
void test_polygon()  
{
  

  typedef typename gtl::polygon_traits<Polygon>::point_type Point;
  Point pts[] = {gtl::construct<Point>(6, 0),
                 gtl::construct<Point>(0, 6),
                 gtl::construct<Point>(-6, 0),
                 gtl::construct<Point>(0, -6),
                 };
  Polygon poly, poly2;
  gtl::set_points(poly, pts, pts 5);

  Point pts2[] = {gtl::construct<Point>(4, 0),
                 gtl::construct<Point>(4, 4),
                 gtl::construct<Point>(0, 4),
                 gtl::construct<Point>(0, 0),
                };

  gtl::set_points(poly2, pts2, pts2 5);


  std::vector<Polygon> res;
  //boost::polygon::polygon_set_data<int> res;
  //res  = poly;
  //assign(res, poly);
  res.push_back(poly);
  res &= poly2;
  std::cout << "size = " << res.size() << std::endl;
  assert(!res.empty());
  //for(auto it = res[0].begin(); it != res[0].end();   it)
  //    std::cout << "Point(" << it->x << ", " << it->y << ")" << std::endl;
  assert(gtl::area(poly) == 100.0f);
  
}

struct CPoint {
  CPoint()=default;
  CPoint(boost::polygon::point_data<int> pd) /*---> WHY? What for ? I implemented constructor with traits*/
  {
    x = pd.x();
    y = pd.y();
  }
  int x;
  int y;
};


namespace boost { namespace polygon {
  template <>
  struct geometry_concept<CPoint> { typedef point_concept type; };
  template <>
  struct point_traits<CPoint> {
    typedef int coordinate_type;

    static inline coordinate_type get(const CPoint& point,
    orientation_2d orient) {
      if(orient == HORIZONTAL)
        return point.x;
      return point.y;
    }
  };

  template <>
  struct point_mutable_traits<CPoint> {
    typedef int coordinate_type;

    static inline void set(CPoint& point, orientation_2d orient, int value) {
      if(orient == HORIZONTAL)
        point.x = value;
      else
        point.y = value;
    }
    static inline CPoint construct(int x_value, int y_value) {
      CPoint retval;
      retval.x = x_value;
      retval.y = y_value;
      return retval;
      }
    };
  } 
}


typedef std::list<CPoint> CPolygon;


namespace boost { 
  namespace polygon {

  template <>
  struct geometry_concept<CPolygon>{ typedef polygon_concept type; };

  template <>
  struct polygon_traits<CPolygon> {
    typedef int coordinate_type;
    typedef CPolygon::const_iterator iterator_type;
    typedef CPoint point_type;


    static inline iterator_type begin_points(const CPolygon& t) {
      return t.begin();
    }

    static inline iterator_type end_points(const CPolygon& t) {
      return t.end();
    }


    static inline std::size_t size(const CPolygon& t) {
      return t.size();
    }


    static inline winding_direction winding(const CPolygon& t) {
      return clockwise_winding;
    }
  };

  template <>
  struct polygon_mutable_traits<CPolygon> {
      template <typename iT>
      static inline CPolygon& set_points(CPolygon& t,
                                       iT input_begin, iT input_end) {
        t.clear();
        t.insert(t.end(), input_begin, input_end);
        return t;
      }

    };
  } 
}



int main() {
  test_polygon<CPolygon>();
  return 0;
}


I get size = 0 in the result vector of intersections.

CodePudding user response:

gtl::set_points(poly, pts, pts   5);

That's out of bounds, because the array has only 4 elements. Avoid the entire bug category by modernizing:

std::array const pts1{
    gtl::construct<Point>(6, 0),
    gtl::construct<Point>(0, 6),
    gtl::construct<Point>(-6, 0),
    gtl::construct<Point>(0, -6),
};

std::array const pts2{
    gtl::construct<Point>(4, 0),
    gtl::construct<Point>(4, 4),
    gtl::construct<Point>(0, 4),
    gtl::construct<Point>(0, 0),
};

And then

Polygon poly1;
gtl::set_points(poly1, pts1.begin(), pts1.end());

Polygon poly2;
gtl::set_points(poly2, pts2.begin(), pts2.end());

Next up you have:

static inline winding_direction winding(const CPolygon& t)
{
    return clockwise_winding;
}

But your sample data does not conform to that winding. Fixing your input data:

std::array const pts1{
    gtl::construct<Point>(0, -6),
    gtl::construct<Point>(-6, 0),
    gtl::construct<Point>(0, 6),
    gtl::construct<Point>(6, 0),
};

std::array const pts2{
    gtl::construct<Point>(0, 0),
    gtl::construct<Point>(0, 4),
    gtl::construct<Point>(4, 4),
    gtl::construct<Point>(4, 0),
};

Finally, the result of operators in Boost Polygon is a polygon set view. You can have the library assign that:

std::vector<Polygon> res;
gtl::assign(res, poly1 & poly2);

Or

std::vector<Polygon> res{poly1};
res &= poly2;

Which are both effectively equivalent, though the second might be more efficient?

fmt::print("poly1 {}, area {}\n", poly1, gtl::area(poly1));
fmt::print("poly2 {}, area {}\n", poly2, gtl::area(poly2));

fmt::print("res {}, area {}\n", res, gtl::area(res));

Prints

enter image description here

  • Related