2 Copyright 2008 Intel Corporation
4 Use, modification and distribution are subject to the Boost Software License,
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 http://www.boost.org/LICENSE_1_0.txt).
8 #include <boost/polygon/polygon.hpp>
14 namespace gtl
= boost::polygon
;
15 using namespace boost::polygon::operators
;
17 //once again we make our usage of the library generic
18 //and parameterize it on the polygon set type
19 template <typename PolygonSet
>
20 void test_polygon_set() {
23 ps
+= rectangle_data
<int>(0, 0, 10, 10);
25 ps2
+= rectangle_data
<int>(5, 5, 15, 15);
27 assign(ps3
, ps
* ps2
);
30 assert(area(ps4
) == area(ps
) + area(ps2
) - area(ps3
));
31 assert(equivalence((ps
+ ps2
) - (ps
* ps2
), ps
^ ps2
));
32 rectangle_data
<int> rect
;
33 assert(extents(rect
, ps
^ ps2
));
34 assert(area(rect
) == 225);
35 assert(area(rect
^ (ps
^ ps2
)) == area(rect
) - area(ps
^ ps2
));
38 //first thing is first, lets include all the code from previous examples
46 namespace boost
{ namespace polygon
{
48 struct geometry_concept
<CPoint
> { typedef point_concept type
; };
50 struct point_traits
<CPoint
> {
51 typedef int coordinate_type
;
53 static inline coordinate_type
get(const CPoint
& point
,
54 orientation_2d orient
) {
55 if(orient
== HORIZONTAL
)
62 struct point_mutable_traits
<CPoint
> {
63 typedef int coordinate_type
;
65 static inline void set(CPoint
& point
, orientation_2d orient
, int value
) {
66 if(orient
== HORIZONTAL
)
71 static inline CPoint
construct(int x_value
, int y_value
) {
80 //the CPolygon example
81 typedef std::list
<CPoint
> CPolygon
;
83 //we need to specialize our polygon concept mapping in boost polygon
84 namespace boost
{ namespace polygon
{
85 //first register CPolygon as a polygon_concept type
87 struct geometry_concept
<CPolygon
>{ typedef polygon_concept type
; };
90 struct polygon_traits
<CPolygon
> {
91 typedef int coordinate_type
;
92 typedef CPolygon::const_iterator iterator_type
;
93 typedef CPoint point_type
;
95 // Get the begin iterator
96 static inline iterator_type
begin_points(const CPolygon
& t
) {
100 // Get the end iterator
101 static inline iterator_type
end_points(const CPolygon
& t
) {
105 // Get the number of sides of the polygon
106 static inline std::size_t size(const CPolygon
& t
) {
110 // Get the winding direction of the polygon
111 static inline winding_direction
winding(const CPolygon
& t
) {
112 return unknown_winding
;
117 struct polygon_mutable_traits
<CPolygon
> {
118 //expects stl style iterators
119 template <typename iT
>
120 static inline CPolygon
& set_points(CPolygon
& t
,
121 iT input_begin
, iT input_end
) {
123 while(input_begin
!= input_end
) {
124 t
.push_back(CPoint());
125 gtl::assign(t
.back(), *input_begin
);
134 //OK, finally we get to declare our own polygon set type
135 typedef std::deque
<CPolygon
> CPolygonSet
;
137 //deque isn't automatically a polygon set in the library
138 //because it is a standard container there is a shortcut
139 //for mapping it to polygon set concept, but I'll do it
140 //the long way that you would use in the general case.
141 namespace boost
{ namespace polygon
{
142 //first we register CPolygonSet as a polygon set
144 struct geometry_concept
<CPolygonSet
> { typedef polygon_set_concept type
; };
146 //next we map to the concept through traits
148 struct polygon_set_traits
<CPolygonSet
> {
149 typedef int coordinate_type
;
150 typedef CPolygonSet::const_iterator iterator_type
;
151 typedef CPolygonSet operator_arg_type
;
153 static inline iterator_type
begin(const CPolygonSet
& polygon_set
) {
154 return polygon_set
.begin();
157 static inline iterator_type
end(const CPolygonSet
& polygon_set
) {
158 return polygon_set
.end();
161 //don't worry about these, just return false from them
162 static inline bool clean(const CPolygonSet
& polygon_set
) { return false; }
163 static inline bool sorted(const CPolygonSet
& polygon_set
) { return false; }
167 struct polygon_set_mutable_traits
<CPolygonSet
> {
168 template <typename input_iterator_type
>
169 static inline void set(CPolygonSet
& polygon_set
, input_iterator_type input_begin
, input_iterator_type input_end
) {
171 //this is kind of cheesy. I am copying the unknown input geometry
172 //into my own polygon set and then calling get to populate the
174 polygon_set_data
<int> ps
;
175 ps
.insert(input_begin
, input_end
);
177 //if you had your own odd-ball polygon set you would probably have
178 //to iterate through each polygon at this point and do something
185 long long c1
= clock();
186 for(int i
= 0; i
< 1000; ++i
)
187 test_polygon_set
<CPolygonSet
>();
188 long long c2
= clock();
189 for(int i
= 0; i
< 1000; ++i
)
190 test_polygon_set
<gtl::polygon_set_data
<int> >();
191 long long c3
= clock();
192 long long diff1
= c2
- c1
;
193 long long diff2
= c3
- c2
;
194 if(diff1
> 0 && diff2
)
195 std::cout
<< "library polygon_set_data is " << float(diff1
)/float(diff2
) << "X faster than custom polygon set deque of CPolygon" << std::endl
;
197 std::cout
<< "operation was too fast" << std::endl
;
201 //Now you know how to map your own data type to polygon set concept
202 //Now you also know how to make your application code that operates on geometry
203 //data type agnostic from point through polygon set