File: gtl_custom_polygon_set.cpp

package info (click to toggle)
boost1.83 1.83.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 545,632 kB
  • sloc: cpp: 3,857,086; xml: 125,552; ansic: 34,414; python: 25,887; asm: 5,276; sh: 4,799; ada: 1,681; makefile: 1,629; perl: 1,212; pascal: 1,139; sql: 810; yacc: 478; ruby: 102; lisp: 24; csh: 6
file content (203 lines) | stat: -rw-r--r-- 6,043 bytes parent folder | download | duplicates (14)
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*
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 <list>
#include <time.h>
#include <cassert>
#include <deque>
#include <iostream>
namespace gtl = boost::polygon;
using namespace boost::polygon::operators;

//once again we make our usage of the library generic
//and parameterize it on the polygon set type
template <typename PolygonSet>
void test_polygon_set() {
  using namespace gtl; 
  PolygonSet ps;
  ps += rectangle_data<int>(0, 0, 10, 10);
  PolygonSet ps2;
  ps2 += rectangle_data<int>(5, 5, 15, 15);
  PolygonSet ps3;
  assign(ps3, ps * ps2); 
  PolygonSet ps4;
  ps4 += ps + ps2;
  assert(area(ps4) == area(ps) + area(ps2) - area(ps3));
  assert(equivalence((ps + ps2) - (ps * ps2), ps ^ ps2));
  rectangle_data<int> rect;
  assert(extents(rect, ps ^ ps2));
  assert(area(rect) == 225);
  assert(area(rect ^ (ps ^ ps2)) == area(rect) - area(ps ^ ps2)); 
}

//first thing is first, lets include all the code from previous examples

//the CPoint example
struct CPoint {
  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;
      }
    };
  } }

//the CPolygon example
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();
	while(input_begin != input_end) {
	  t.push_back(CPoint());
	  gtl::assign(t.back(), *input_begin);
	  ++input_begin;
	}
	return t;
      }

    };
  } }

//OK, finally we get to declare our own polygon set type
typedef std::deque<CPolygon> CPolygonSet;

//deque isn't automatically a polygon set in the library
//because it is a standard container there is a shortcut
//for mapping it to polygon set concept, but I'll do it
//the long way that you would use in the general case.
namespace boost { namespace polygon {
    //first we register CPolygonSet as a polygon set
    template <>
    struct geometry_concept<CPolygonSet> { typedef polygon_set_concept type; };

    //next we map to the concept through traits
    template <>
    struct polygon_set_traits<CPolygonSet> {
      typedef int coordinate_type;
      typedef CPolygonSet::const_iterator iterator_type;
      typedef CPolygonSet operator_arg_type;

      static inline iterator_type begin(const CPolygonSet& polygon_set) {
	return polygon_set.begin();
      }

      static inline iterator_type end(const CPolygonSet& polygon_set) {
	return polygon_set.end();
      }

      //don't worry about these, just return false from them
      static inline bool clean(const CPolygonSet& polygon_set) { return false; }
      static inline bool sorted(const CPolygonSet& polygon_set) { return false; }
    };

    template <>
    struct polygon_set_mutable_traits<CPolygonSet> {
      template <typename input_iterator_type>
      static inline void set(CPolygonSet& polygon_set, input_iterator_type input_begin, input_iterator_type input_end) {
	polygon_set.clear();
	//this is kind of cheesy. I am copying the unknown input geometry
	//into my own polygon set and then calling get to populate the
	//deque
	polygon_set_data<int> ps;
	ps.insert(input_begin, input_end);
	ps.get(polygon_set);
	//if you had your own odd-ball polygon set you would probably have
	//to iterate through each polygon at this point and do something
	//extra
      }
    };
} }

int main() {
  long long c1 = clock();
  for(int i = 0; i < 1000; ++i) 
    test_polygon_set<CPolygonSet>();
  long long c2 = clock();
  for(int i = 0; i < 1000; ++i) 
    test_polygon_set<gtl::polygon_set_data<int> >();
  long long c3 = clock();
  long long diff1 = c2 - c1;
  long long diff2 = c3 - c2;
  if(diff1 > 0 && diff2)
    std::cout << "library polygon_set_data is " << float(diff1)/float(diff2) << "X faster than custom polygon set deque of CPolygon" << std::endl;
  else
    std::cout << "operation was too fast" << std::endl;
  return 0;
}

//Now you know how to map your own data type to polygon set concept
//Now you also know how to make your application code that operates on geometry
//data type agnostic from point through polygon set