File: gtl_custom_polygon.cpp

package info (click to toggle)
boost1.74 1.74.0%2Bds1-21
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 463,588 kB
  • sloc: cpp: 3,338,117; xml: 131,293; python: 33,088; ansic: 14,292; asm: 4,038; sh: 3,353; makefile: 1,193; perl: 1,036; yacc: 478; php: 212; ruby: 102; lisp: 24; sql: 13; csh: 6
file content (146 lines) | stat: -rw-r--r-- 4,236 bytes parent folder | download | duplicates (17)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
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;

//first lets turn our polygon usage code into a generic
//function parameterized by polygon type
template <typename Polygon>
void test_polygon() {
  //lets construct a 10x10 rectangle shaped polygon
  typedef typename gtl::polygon_traits<Polygon>::point_type Point;
  Point pts[] = {gtl::construct<Point>(0, 0),
		 gtl::construct<Point>(10, 0),
		 gtl::construct<Point>(10, 10),
		 gtl::construct<Point>(0, 10) };
  Polygon poly;
  gtl::set_points(poly, pts, pts+4);

  //now lets see what we can do with this polygon
  assert(gtl::area(poly) == 100.0f);
  assert(gtl::contains(poly, gtl::construct<Point>(5, 5)));
  assert(!gtl::contains(poly, gtl::construct<Point>(15, 5)));
  gtl::rectangle_data<int> rect;
  assert(gtl::extents(rect, poly)); //get bounding box of poly
  assert(gtl::equivalence(rect, poly)); //hey, that's slick
  assert(gtl::winding(poly) == gtl::COUNTERCLOCKWISE);
  assert(gtl::perimeter(poly) == 40.0f);

  //add 5 to all coords of poly
  gtl::convolve(poly, gtl::construct<Point>(5, 5));
  //multiply all coords of poly by 2
  gtl::scale_up(poly, 2);
  gtl::set_points(rect, gtl::point_data<int>(10, 10),
		  gtl::point_data<int>(30, 30));
  assert(gtl::equivalence(poly, rect));
}

//Now lets declare our own polygon class
//Oops, we need a point class to support our polygon, lets borrow
//the CPoint example
struct CPoint {
  int x;
  int y;
};

//we have to get CPoint working with boost polygon to make our polygon
//that uses CPoint working with boost polygon
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;
      }
    };
  } }

//I'm lazy and use the stl everywhere to avoid writing my own classes
//my toy polygon is a std::list<CPoint>
typedef std::list<CPoint> CPolygon;

//we need to specialize our polygon concept mapping in boost polygon
namespace boost { namespace polygon {
    //first register CPolygon as a polygon_concept type
    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;

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

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

      // Get the number of sides of the polygon
      static inline std::size_t size(const CPolygon& t) {
	return t.size();
      }

      // Get the winding direction of the polygon
      static inline winding_direction winding(const CPolygon& t) {
	return unknown_winding;
      }
    };

    template <>
    struct polygon_mutable_traits<CPolygon> {
      //expects stl style iterators
      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;
      }

    };
  } }

//now there's nothing left to do but test that our polygon
//works with library interfaces
int main() {
  test_polygon<CPolygon>(); //woot!
  return 0;
}