Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating boost.geometry.model.polygon from 2D C List

Supposed I have the following dataset

double * data = (double *) malloc(sizeof(double) * 100 * 2);
for (ii = 0; ii < 100; ii++) {
    data[2*ii] = ii;
    data[2*ii + 1] = ii;
}

how can I create a boost polygon from this data?

thanks

like image 433
adk Avatar asked Sep 17 '12 17:09

adk


1 Answers

A complete example

#include <iostream>
#include <boost/polygon/polygon.hpp>
#include <vector>

// Some typedefs
namespace bpl = boost::polygon;
typedef bpl::polygon_data<double> Polygon;
typedef bpl::polygon_traits<Polygon>::point_type Point;

int main() {

  // Your C-style data (assumed (x,y) pairs)
  double * data = (double *) malloc(sizeof(double) * 100 * 2);
  for (int ii = 0; ii < 100; ii++) {
    data[2*ii] = ii;
    data[2*ii + 1] = ii;
  }

  // Convert to points
  std::vector<Point> points;
  for (int i=0;i<100;++i)
    points.push_back(Point(data[2*i],data[2*i+1]));

  // Create a polygon
  Polygon polygon;
  polygon.set(points.begin(),points.end());

  // Do something with the polygon
  std::cout << "Perimeter : " << bpl::perimeter(polygon) << std::endl;
  std::cout << "Area      : " << bpl::area(polygon) << std::endl;

  return 0;
}

Just to illustrate the flexibility you actually have: with a bit of extra typedef work, its possible to define your own pair-of-doubles point type which can be aliased onto your data, which avoids the intermediate copy...

#include <iostream>
#include <boost/polygon/polygon.hpp>
#include <vector>

// Define a point type which can be aliased to your 'C' points
struct Pt {
  double x;
  double y;
};

// Some typedefs
namespace bpl = boost::polygon;
typedef bpl::polygon_data<double> Polygon;

// Add the necessary to use Pt
namespace boost { 
  namespace polygon {

    template <> struct geometry_concept<Pt> {typedef point_concept type;};

    template <> struct point_traits<Pt> {
      typedef double coordinate_type;

      static inline coordinate_type get(const Pt& pt,orientation_2d orient) {
    return (orient == HORIZONTAL ? pt.x : pt.y);
      }
    };

    template <> struct point_mutable_traits<Pt> {
      static inline void set(Pt& pt, orientation_2d orient, int value) {
    if(orient == HORIZONTAL)
      pt.x = value;
    else
      pt.y = value;
      }
      static inline Pt construct(double x,double y) {
    Pt r;
    r.x=x;
    r.y=y;
    return r;
      }
    };
  } 
}

int main() {

  // Your C-style data (assumed (x,y) pairs)
  double * data = (double *) malloc(sizeof(double) * 100 * 2);
  for (int ii = 0; ii < 100; ii++) {
    data[2*ii] = ii;
    data[2*ii + 1] = ii;
  }

  // Reinterpret your data as an array of Pt
  const Pt*const pts=reinterpret_cast<const Pt*>(data);

  // Create a polygon
  Polygon polygon;
  polygon.set(pts,pts+100);

  // Do something with the polygon
  std::cout << "Perimeter : " << bpl::perimeter(polygon) << std::endl;
  std::cout << "Area      : " << bpl::area(polygon) << std::endl;

  return 0;
}

And this trend could be continued to a custom polygon class.

like image 163
timday Avatar answered Nov 05 '22 10:11

timday