Question

I have trouble understanding how to register my own type as a boost::geometry::model::ring. I have my own point class:

struct Point { double x, y; };

And rings are stored as std::vector<Point>. I therefore registered them like this:

BOOST_GEOMETRY_REGISTER_POINT_2D(Point , double, cs::cartesian, x, y);
BOOST_GEOMETRY_REGISTER_RING(std::vector<Point>);

Now I would like to correct the orientation of a ring, and indeed, the following compiles:

void foo(std::vector<Point>& ring) {
  boost::geometry::correct(ring);
}

Trouble is, how can I define the "correct" orientation of a ring? It's more obvious when using boost::geometry::model::polygon, where a template parameter allows me to specify the expected orientation. However, the following does not compile:

void foo(std::vector<Point>& ring) {
    typedef boost::geometry::model::polygon<vector> clockwise_closed_polygon;
    clockwise_closed_polygon cwcp;
    boost::geometry::exterior_ring(cwcp) = ring; //<<< fails to compile
    boost::geometry::correct(cwcp);
}

Apparently, my own ring type cannot be converted to the one defined by clockwise_closed_polygon.

So I have two questions:

  1. How can I specify the correct ring orientation?
  2. Why can't my ring type be used with the polygon, as declared above?
Was it helpful?

Solution

Trouble is, how can I define the "correct" orientation of a ring?

You may try to specialize boost::geometry::point_order:

live demo

#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/geometries/register/ring.hpp>
#include <boost/geometry/geometries/geometries.hpp> 
#include <boost/geometry/core/point_order.hpp> 
#include <boost/geometry.hpp>
#include <iostream>
#include <ostream>
#include <vector>

using namespace boost::geometry;
using namespace std;

struct Point { double x, y; };

BOOST_GEOMETRY_REGISTER_POINT_2D(Point , double, cs::cartesian, x, y)
BOOST_GEOMETRY_REGISTER_RING(vector<Point>)

namespace boost { namespace geometry
{
   template<>
   struct point_order<vector<Point>>
   {
      //static const order_selector value=counterclockwise;
      static const order_selector value=clockwise;
   };
}}

template<typename Ring>
void print(const Ring &r)
{
   for(auto p : r)
      cout << "(" << p.x << "," << p.y << ")";
   cout << endl;
}

int main()
{
   std::vector<Point> ring{{0.0,0.0},{1.0,0.0},{0.0,1.0},{0.0,0.0}};
   print(ring);
   correct(ring);
   print(ring);
}

Output is:

(0,0)(1,0)(0,1)(0,0)
(0,0)(0,1)(1,0)(0,0)

If change from clockwise to counterclockwise then output is:

(0,0)(1,0)(0,1)(0,0)
(0,0)(1,0)(0,1)(0,0)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top