]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <html> |
2 | ||
3 | <head> | |
4 | <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | |
5 | <title>Custom Polygon Set</title> | |
6 | </head> | |
7 | ||
8 | <body> | |
9 | ||
10 | <p><font face="Courier New">/*<br> | |
11 | Copyright 2008 Intel Corporation<br> | |
12 | <br> | |
13 | Use, modification and distribution are subject to the Boost Software License,<br> | |
14 | Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at<br> | |
15 | http://www.boost.org/LICENSE_1_0.txt).<br> | |
16 | */<br> | |
17 | #include <boost/polygon/polygon.hpp><br> | |
18 | #include <list><br> | |
19 | #include <time.h><br> | |
20 | #include <cassert><br> | |
21 | #include <deque><br> | |
22 | #include <iostream><br> | |
23 | namespace gtl = boost::polygon;<br> | |
24 | using namespace boost::polygon::operators;<br><br> | |
25 | //once again we make our usage of the library generic<br> | |
26 | //and parameterize it on the polygon set type<br> | |
27 | template <typename PolygonSet><br> | |
28 | void test_polygon_set() {<br> | |
29 | using namespace gtl; <br> | |
30 | PolygonSet ps;<br> | |
31 | ps += rectangle_data<int>(0, 0, 10, 10);<br> | |
32 | PolygonSet ps2;<br> | |
33 | ps2 += rectangle_data<int>(5, 5, 15, 15);<br> | |
34 | PolygonSet ps3;<br> | |
35 | assign(ps3, ps * ps2); <br> | |
36 | PolygonSet ps4;<br> | |
37 | ps4 += ps + ps2;<br> | |
38 | assert(area(ps4) == area(ps) + area(ps2) - area(ps3));<br> | |
39 | assert(equivalence((ps + ps2) - (ps * ps2), ps ^ ps2));<br> | |
40 | rectangle_data<int> rect;<br> | |
41 | assert(extents(rect, ps ^ ps2));<br> | |
42 | assert(area(rect) == 225);<br> | |
43 | assert(area(rect ^ (ps ^ ps2)) == area(rect) - area(ps ^ ps2)); <br> | |
44 | }<br> | |
45 | <br> | |
46 | //first thing is first, lets include all the code from previous examples<br> | |
47 | <br> | |
48 | //the CPoint example<br> | |
49 | struct CPoint {<br> | |
50 | int x;<br> | |
51 | int y;<br> | |
52 | };<br> | |
53 | <br> | |
54 | namespace boost { namespace polygon {<br> | |
55 | template <><br> | |
56 | struct geometry_concept<CPoint> { typedef point_concept type; };<br> | |
57 | template <><br> | |
58 | struct point_traits<CPoint> {<br> | |
59 | typedef int coordinate_type;<br> | |
60 | <br> | |
61 | static inline coordinate_type get(const CPoint& point, <br> | |
62 | | |
63 | orientation_2d orient) {<br> | |
64 | if(orient == HORIZONTAL)<br> | |
65 | return point.x;<br> | |
66 | return point.y;<br> | |
67 | }<br> | |
68 | };<br> | |
69 | <br> | |
70 | template <><br> | |
71 | struct point_mutable_traits<CPoint> {<br> | |
72 | typedef int coordinate_type;<br> | |
73 | <br> | |
74 | static inline void set(CPoint& point, orientation_2d orient, | |
75 | int value) {<br> | |
76 | if(orient == HORIZONTAL)<br> | |
77 | point.x = value;<br> | |
78 | else<br> | |
79 | point.y = value;<br> | |
80 | }<br> | |
81 | static inline CPoint construct(int x_value, int y_value) {<br> | |
82 | CPoint retval;<br> | |
83 | retval.x = x_value;<br> | |
84 | retval.y = y_value; <br> | |
85 | return retval;<br> | |
86 | }<br> | |
87 | };<br> | |
88 | } }<br> | |
89 | <br> | |
90 | //the CPolygon example<br> | |
91 | typedef std::list<CPoint> CPolygon;<br> | |
92 | <br> | |
93 | //we need to specialize our polygon concept mapping in boost polygon<br> | |
94 | namespace boost { namespace polygon {<br> | |
95 | //first register CPolygon as a polygon_concept type<br> | |
96 | template <><br> | |
97 | struct geometry_concept<CPolygon>{ typedef polygon_concept type; };<br> | |
98 | <br> | |
99 | template <><br> | |
100 | struct polygon_traits<CPolygon> {<br> | |
101 | typedef int coordinate_type;<br> | |
102 | typedef CPolygon::const_iterator iterator_type;<br> | |
103 | typedef CPoint point_type;<br> | |
104 | <br> | |
105 | // Get the begin iterator<br> | |
106 | static inline iterator_type begin_points(const CPolygon& t) {<br> | |
107 | return t.begin();<br> | |
108 | }<br> | |
109 | <br> | |
110 | // Get the end iterator<br> | |
111 | static inline iterator_type end_points(const CPolygon& t) {<br> | |
112 | return t.end();<br> | |
113 | }<br> | |
114 | <br> | |
115 | // Get the number of sides of the polygon<br> | |
116 | static inline std::size_t size(const CPolygon& t) {<br> | |
117 | return t.size();<br> | |
118 | }<br> | |
119 | <br> | |
120 | // Get the winding direction of the polygon<br> | |
121 | static inline winding_direction winding(const CPolygon& t) {<br> | |
122 | return unknown_winding;<br> | |
123 | }<br> | |
124 | };<br> | |
125 | <br> | |
126 | template <><br> | |
127 | struct polygon_mutable_traits<CPolygon> {<br> | |
128 | //expects stl style iterators<br> | |
129 | template <typename iT><br> | |
130 | static inline CPolygon& set_points(CPolygon& t, <br> | |
131 | | |
132 | iT input_begin, iT input_end) {<br> | |
133 | t.clear();<br> | |
134 | while(input_begin != input_end) {<br> | |
135 | t.push_back(CPoint());<br> | |
136 | gtl::assign(t.back(), *input_begin);<br> | |
137 | ++input_begin;<br> | |
138 | }<br> | |
139 | return t;<br> | |
140 | }<br> | |
141 | <br> | |
142 | };<br> | |
143 | } }<br> | |
144 | <br> | |
145 | //OK, finally we get to declare our own polygon set type<br> | |
146 | typedef std::deque<CPolygon> CPolygonSet;<br> | |
147 | <br> | |
148 | //deque isn't automatically a polygon set in the library<br> | |
149 | //because it is a standard container there is a shortcut<br> | |
150 | //for mapping it to polygon set concept, but I'll do it<br> | |
151 | //the long way that you would use in the general case.<br> | |
152 | namespace boost { namespace polygon {<br> | |
153 | //first we register CPolygonSet as a polygon set<br> | |
154 | template <><br> | |
155 | struct geometry_concept<CPolygonSet> { typedef polygon_set_concept type; | |
156 | };<br> | |
157 | <br> | |
158 | //next we map to the concept through traits<br> | |
159 | template <><br> | |
160 | struct polygon_set_traits<CPolygonSet> {<br> | |
161 | typedef int coordinate_type;<br> | |
162 | typedef CPolygonSet::const_iterator iterator_type;<br> | |
163 | typedef CPolygonSet operator_arg_type;<br> | |
164 | <br> | |
165 | static inline iterator_type begin(const CPolygonSet& | |
166 | polygon_set) {<br> | |
167 | return polygon_set.begin();<br> | |
168 | }<br> | |
169 | <br> | |
170 | static inline iterator_type end(const CPolygonSet& | |
171 | polygon_set) {<br> | |
172 | return polygon_set.end();<br> | |
173 | }<br> | |
174 | <br> | |
175 | //don't worry about these, just return false from them<br> | |
176 | static inline bool clean(const CPolygonSet& polygon_set) { | |
177 | return false; }<br> | |
178 | static inline bool sorted(const CPolygonSet& polygon_set) { | |
179 | return false; }<br> | |
180 | };<br> | |
181 | <br> | |
182 | template <><br> | |
183 | struct polygon_set_mutable_traits<CPolygonSet> {<br> | |
184 | template <typename input_iterator_type><br> | |
185 | static inline void set(CPolygonSet& polygon_set, | |
186 | input_iterator_type input_begin, input_iterator_type input_end) {<br> | |
187 | polygon_set.clear();<br> | |
188 | //this is kind of cheesy. I am copying the | |
189 | unknown input geometry<br> | |
190 | //into my own polygon set and then calling get to | |
191 | populate the<br> | |
192 | //deque<br> | |
193 | polygon_set_data<int> ps;<br> | |
194 | ps.insert(input_begin, input_end);<br> | |
195 | ps.get(polygon_set);<br> | |
196 | //if you had your own odd-ball polygon set you | |
197 | would probably have<br> | |
198 | //to iterate through each polygon at this point | |
199 | and do something<br> | |
200 | //extra<br> | |
201 | }<br> | |
202 | };<br> | |
203 | } }<br> | |
204 | <br> | |
205 | int main() {<br> | |
206 | long long c1 = clock();<br> | |
207 | for(int i = 0; i < 1000; ++i) <br> | |
208 | test_polygon_set<CPolygonSet>();<br> | |
209 | long long c2 = clock();<br> | |
210 | for(int i = 0; i < 1000; ++i) <br> | |
211 | test_polygon_set<gtl::polygon_set_data<int> >();<br> | |
212 | long long c3 = clock();<br> | |
213 | long long diff1 = c2 - c1;<br> | |
214 | long long diff2 = c3 - c2;<br> | |
215 | if(diff1 > 0 && diff2)<br> | |
216 | std::cout << "library polygon_set_data is " << | |
217 | float(diff1)/float(diff2) << "X faster than custom polygon set deque of CPolygon" | |
218 | << std::endl;<br> | |
219 | else<br> | |
220 | std::cout << "operation was too fast" << std::endl;<br> | |
221 | return 0;<br> | |
222 | }</font></p> | |
223 | <p><font face="Courier New">//Now you know how to map your own data type to | |
224 | polygon set concept<br> | |
225 | //Now you also know how to make your application code that operates on geometry<br> | |
226 | //data type agnostic from point through polygon set | |
227 | </font></p> | |
228 | ||
229 | ||
230 | <table class="docinfo" rules="none" frame="void" id="table1"> | |
231 | <colgroup> | |
232 | <col class="docinfo-name"><col class="docinfo-content"> | |
233 | </colgroup> | |
234 | <tbody vAlign="top"> | |
235 | <tr> | |
236 | <th class="docinfo-name">Copyright:</th> | |
237 |