Chris@16
|
1 /*
|
Chris@16
|
2 Copyright 2008 Intel Corporation
|
Chris@16
|
3
|
Chris@16
|
4 Use, modification and distribution are subject to the Boost Software License,
|
Chris@16
|
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 http://www.boost.org/LICENSE_1_0.txt).
|
Chris@16
|
7 */
|
Chris@16
|
8 #include<iostream>
|
Chris@16
|
9 #include<cassert>
|
Chris@16
|
10 #ifndef BOOST_POLYGON_POLYGON_FORMATION_HPP
|
Chris@16
|
11 #define BOOST_POLYGON_POLYGON_FORMATION_HPP
|
Chris@16
|
12 namespace boost { namespace polygon{
|
Chris@16
|
13
|
Chris@16
|
14 namespace polygon_formation {
|
Chris@16
|
15
|
Chris@16
|
16 /*
|
Chris@16
|
17 * End has two states, HEAD and TAIL as is represented by a bool
|
Chris@16
|
18 */
|
Chris@16
|
19 typedef bool End;
|
Chris@16
|
20
|
Chris@16
|
21 /*
|
Chris@16
|
22 * HEAD End is represented as false because it is the lesser state
|
Chris@16
|
23 */
|
Chris@16
|
24 const End HEAD = false;
|
Chris@16
|
25
|
Chris@16
|
26 /*
|
Chris@16
|
27 * TAIL End is represented by true because TAIL comes after head and 1 after 0
|
Chris@16
|
28 */
|
Chris@16
|
29 const End TAIL = true;
|
Chris@16
|
30
|
Chris@16
|
31 /*
|
Chris@16
|
32 * 2D turning direction, left and right sides (is a boolean value since it has two states.)
|
Chris@16
|
33 */
|
Chris@16
|
34 typedef bool Side;
|
Chris@16
|
35
|
Chris@16
|
36 /*
|
Chris@16
|
37 * LEFT Side is 0 because we inuitively think left to right; left < right
|
Chris@16
|
38 */
|
Chris@16
|
39 const Side LEFT = false;
|
Chris@16
|
40
|
Chris@16
|
41 /*
|
Chris@16
|
42 * RIGHT Side is 1 so that right > left
|
Chris@16
|
43 */
|
Chris@16
|
44 const Side RIGHT = true;
|
Chris@16
|
45
|
Chris@16
|
46 /*
|
Chris@16
|
47 * The PolyLine class is data storage and services for building and representing partial polygons.
|
Chris@16
|
48 * As the polyline is added to it extends its storage to accomodate the data.
|
Chris@16
|
49 * PolyLines can be joined head-to-head/head-to-tail when it is determined that two polylines are
|
Chris@16
|
50 * part of the same polygon.
|
Chris@16
|
51 * PolyLines keep state information about what orientation their incomplete head and tail geometry have,
|
Chris@16
|
52 * which side of the polyline is solid and whether the polyline is joined head-to-head and tail-to-head.
|
Chris@16
|
53 * PolyLines have nothing whatsoever to do with holes.
|
Chris@16
|
54 * It may be valuable to collect a histogram of PolyLine lengths used by an algorithm on its typical data
|
Chris@16
|
55 * sets and tune the allocation of the initial vector of coordinate data to be greater than or equal to
|
Chris@16
|
56 * the mean, median, mode, or mean plus some number of standard deviation, or just generally large enough
|
Chris@16
|
57 * to prevent too much unnecesary reallocations, but not too big that it wastes a lot of memory and degrades cache
|
Chris@16
|
58 * performance.
|
Chris@16
|
59 */
|
Chris@16
|
60 template <typename Unit>
|
Chris@16
|
61 class PolyLine {
|
Chris@16
|
62 private:
|
Chris@16
|
63 //data
|
Chris@16
|
64
|
Chris@16
|
65 /*
|
Chris@16
|
66 * ptdata_ a vector of coordiantes
|
Chris@16
|
67 * if VERTICAL_HEAD, first coordiante is an X
|
Chris@16
|
68 * else first coordinate is a Y
|
Chris@16
|
69 */
|
Chris@16
|
70 std::vector<Unit> ptdata_;
|
Chris@16
|
71
|
Chris@16
|
72 /*
|
Chris@16
|
73 * head and tail points to other polylines before and after this in a chain
|
Chris@16
|
74 */
|
Chris@16
|
75 PolyLine* headp_;
|
Chris@16
|
76 PolyLine* tailp_;
|
Chris@16
|
77
|
Chris@16
|
78 /*
|
Chris@16
|
79 * state bitmask
|
Chris@16
|
80 * bit zero is orientation, 0 H, 1 V
|
Chris@16
|
81 * bit 1 is head connectivity, 0 for head, 1 for tail
|
Chris@16
|
82 * bit 2 is tail connectivity, 0 for head, 1 for tail
|
Chris@16
|
83 * bit 3 is solid to left of PolyLine when 1, right when 0
|
Chris@16
|
84 */
|
Chris@16
|
85 int state_;
|
Chris@16
|
86
|
Chris@16
|
87 public:
|
Chris@16
|
88 /*
|
Chris@16
|
89 * default constructor (for preallocation)
|
Chris@16
|
90 */
|
Chris@16
|
91 PolyLine();
|
Chris@16
|
92
|
Chris@16
|
93 /*
|
Chris@16
|
94 * constructor that takes the orientation, coordiante and side to which there is solid
|
Chris@16
|
95 */
|
Chris@16
|
96 PolyLine(orientation_2d orient, Unit coord, Side side);
|
Chris@16
|
97
|
Chris@16
|
98 //copy constructor
|
Chris@16
|
99 PolyLine(const PolyLine& pline);
|
Chris@16
|
100
|
Chris@16
|
101 //destructor
|
Chris@16
|
102 ~PolyLine();
|
Chris@16
|
103
|
Chris@16
|
104 //assignment operator
|
Chris@16
|
105 PolyLine& operator=(const PolyLine& that);
|
Chris@16
|
106
|
Chris@16
|
107 //equivalence operator
|
Chris@16
|
108 bool operator==(const PolyLine& b) const;
|
Chris@16
|
109
|
Chris@16
|
110 /*
|
Chris@16
|
111 * valid PolyLine (only default constructed polylines are invalid.)
|
Chris@16
|
112 */
|
Chris@16
|
113 bool isValid() const;
|
Chris@16
|
114
|
Chris@16
|
115 /*
|
Chris@16
|
116 * Orientation of Head
|
Chris@16
|
117 */
|
Chris@16
|
118 orientation_2d headOrient() const;
|
Chris@16
|
119
|
Chris@16
|
120 /*
|
Chris@16
|
121 * returns true if first coordinate is an X value (first segment is vertical)
|
Chris@16
|
122 */
|
Chris@16
|
123 bool verticalHead() const;
|
Chris@16
|
124
|
Chris@16
|
125 /*
|
Chris@16
|
126 * returns the orientation_2d fo the tail
|
Chris@16
|
127 */
|
Chris@16
|
128 orientation_2d tailOrient() const;
|
Chris@16
|
129
|
Chris@16
|
130 /*
|
Chris@16
|
131 * returns true if last coordinate is an X value (last segment is vertical)
|
Chris@16
|
132 */
|
Chris@16
|
133 bool verticalTail() const;
|
Chris@16
|
134
|
Chris@16
|
135 /*
|
Chris@16
|
136 * retrun true if PolyLine has odd number of coordiantes
|
Chris@16
|
137 */
|
Chris@16
|
138 bool oddLength() const;
|
Chris@16
|
139
|
Chris@16
|
140 /*
|
Chris@16
|
141 * retrun the End of the other polyline that the specified end of this polyline is connected to
|
Chris@16
|
142 */
|
Chris@16
|
143 End endConnectivity(End end) const;
|
Chris@16
|
144
|
Chris@16
|
145 /*
|
Chris@16
|
146 * retrun true if the head of this polyline is connect to the tail of a polyline
|
Chris@16
|
147 */
|
Chris@16
|
148 bool headToTail() const;
|
Chris@16
|
149 /*
|
Chris@16
|
150 * retrun true if the head of this polyline is connect to the head of a polyline
|
Chris@16
|
151 */
|
Chris@16
|
152 bool headToHead() const;
|
Chris@16
|
153
|
Chris@16
|
154 /*
|
Chris@16
|
155 * retrun true if the tail of this polyline is connect to the tail of a polyline
|
Chris@16
|
156 */
|
Chris@16
|
157 bool tailToTail() const;
|
Chris@16
|
158 /*
|
Chris@16
|
159 * retrun true if the tail of this polyline is connect to the head of a polyline
|
Chris@16
|
160 */
|
Chris@16
|
161 bool tailToHead() const;
|
Chris@16
|
162
|
Chris@16
|
163 /*
|
Chris@16
|
164 * retrun the side on which there is solid for this polyline
|
Chris@16
|
165 */
|
Chris@16
|
166 Side solidSide() const;
|
Chris@16
|
167
|
Chris@16
|
168 /*
|
Chris@16
|
169 * retrun true if there is solid to the right of this polyline
|
Chris@16
|
170 */
|
Chris@16
|
171 bool solidToRight() const;
|
Chris@16
|
172
|
Chris@16
|
173 /*
|
Chris@16
|
174 * returns true if the polyline tail is not connected
|
Chris@16
|
175 */
|
Chris@16
|
176 bool active() const;
|
Chris@16
|
177
|
Chris@16
|
178 /*
|
Chris@16
|
179 * adds a coordinate value to the end of the polyline changing the tail orientation
|
Chris@16
|
180 */
|
Chris@16
|
181 PolyLine& pushCoordinate(Unit coord);
|
Chris@16
|
182
|
Chris@16
|
183 /*
|
Chris@16
|
184 * removes a coordinate value at the end of the polyline changing the tail orientation
|
Chris@16
|
185 */
|
Chris@16
|
186 PolyLine& popCoordinate();
|
Chris@16
|
187
|
Chris@16
|
188 /*
|
Chris@16
|
189 * extends the tail of the polyline to include the point, changing orientation if needed
|
Chris@16
|
190 */
|
Chris@16
|
191 PolyLine& pushPoint(const point_data<Unit>& point);
|
Chris@16
|
192
|
Chris@16
|
193 /*
|
Chris@16
|
194 * changes the last coordinate of the tail of the polyline by the amount of the delta
|
Chris@16
|
195 */
|
Chris@16
|
196 PolyLine& extendTail(Unit delta);
|
Chris@16
|
197
|
Chris@16
|
198 /*
|
Chris@16
|
199 * join thisEnd of this polyline to that polyline's end
|
Chris@16
|
200 */
|
Chris@16
|
201 PolyLine& joinTo(End thisEnd, PolyLine& that, End end);
|
Chris@16
|
202
|
Chris@16
|
203 /*
|
Chris@16
|
204 * join an end of this polyline to the tail of that polyline
|
Chris@16
|
205 */
|
Chris@16
|
206 PolyLine& joinToTail(PolyLine& that, End end);
|
Chris@16
|
207
|
Chris@16
|
208 /*
|
Chris@16
|
209 * join an end of this polyline to the head of that polyline
|
Chris@16
|
210 */
|
Chris@16
|
211 PolyLine& joinToHead(PolyLine& that, End end);
|
Chris@16
|
212
|
Chris@16
|
213 /*
|
Chris@16
|
214 * join the head of this polyline to the head of that polyline
|
Chris@16
|
215 */
|
Chris@16
|
216 //join this to that in the given way
|
Chris@16
|
217 PolyLine& joinHeadToHead(PolyLine& that);
|
Chris@16
|
218
|
Chris@16
|
219 /*
|
Chris@16
|
220 * join the head of this polyline to the tail of that polyline
|
Chris@16
|
221 */
|
Chris@16
|
222 PolyLine& joinHeadToTail(PolyLine& that);
|
Chris@16
|
223
|
Chris@16
|
224 /*
|
Chris@16
|
225 * join the tail of this polyline to the head of that polyline
|
Chris@16
|
226 */
|
Chris@16
|
227 PolyLine& joinTailToHead(PolyLine& that);
|
Chris@16
|
228
|
Chris@16
|
229 /*
|
Chris@16
|
230 * join the tail of this polyline to the tail of that polyline
|
Chris@16
|
231 */
|
Chris@16
|
232 PolyLine& joinTailToTail(PolyLine& that);
|
Chris@16
|
233
|
Chris@16
|
234 /*
|
Chris@16
|
235 * dissconnect the tail at the end of the polygon
|
Chris@16
|
236 */
|
Chris@16
|
237 PolyLine& disconnectTails();
|
Chris@16
|
238
|
Chris@16
|
239 /*
|
Chris@16
|
240 * get the coordinate at one end of this polyline, by default the tail end
|
Chris@16
|
241 */
|
Chris@16
|
242 Unit getEndCoord(End end = TAIL) const;
|
Chris@16
|
243
|
Chris@16
|
244 /*
|
Chris@16
|
245 * get the point on the polyline at the given index (polylines have the same number of coordinates as points
|
Chris@16
|
246 */
|
Chris@16
|
247 point_data<Unit> getPoint(unsigned int index) const;
|
Chris@16
|
248
|
Chris@16
|
249 /*
|
Chris@16
|
250 * get the point on one end of the polyline, by default the tail
|
Chris@16
|
251 */
|
Chris@16
|
252 point_data<Unit> getEndPoint(End end = TAIL) const;
|
Chris@16
|
253
|
Chris@16
|
254 /*
|
Chris@16
|
255 * get the orientation of a segment by index
|
Chris@16
|
256 */
|
Chris@16
|
257 orientation_2d segmentOrient(unsigned int index = 0) const;
|
Chris@16
|
258
|
Chris@16
|
259 /*
|
Chris@16
|
260 * get a coordinate by index using the square bracket operator
|
Chris@16
|
261 */
|
Chris@16
|
262 Unit operator[] (unsigned int index) const;
|
Chris@16
|
263
|
Chris@16
|
264 /*
|
Chris@16
|
265 * get the number of segments/points/coordinates in the polyline
|
Chris@16
|
266 */
|
Chris@16
|
267 unsigned int numSegments() const;
|
Chris@16
|
268
|
Chris@16
|
269 /*
|
Chris@16
|
270 * get the pointer to the next polyline at one end of this
|
Chris@16
|
271 */
|
Chris@16
|
272 PolyLine* next(End end) const;
|
Chris@16
|
273
|
Chris@16
|
274 /*
|
Chris@16
|
275 * write out coordinates of this and all attached polylines to a single vector
|
Chris@16
|
276 */
|
Chris@16
|
277 PolyLine* writeOut(std::vector<Unit>& outVec, End startEnd = TAIL) const;
|
Chris@16
|
278
|
Chris@16
|
279 private:
|
Chris@16
|
280 //methods
|
Chris@16
|
281 PolyLine& joinTo_(End thisEnd, PolyLine& that, End end);
|
Chris@16
|
282 };
|
Chris@16
|
283
|
Chris@16
|
284 //forward declaration
|
Chris@16
|
285 template<bool orientT, typename Unit>
|
Chris@16
|
286 class PolyLinePolygonData;
|
Chris@16
|
287
|
Chris@16
|
288 //forward declaration
|
Chris@16
|
289 template<bool orientT, typename Unit>
|
Chris@16
|
290 class PolyLinePolygonWithHolesData;
|
Chris@16
|
291
|
Chris@16
|
292 /*
|
Chris@16
|
293 * ActiveTail represents an edge of an incomplete polygon.
|
Chris@16
|
294 *
|
Chris@16
|
295 * An ActiveTail object is the active tail end of a polyline object, which may (should) be the attached to
|
Chris@16
|
296 * a chain of polyline objects through a pointer. The ActiveTail class provides an abstraction between
|
Chris@16
|
297 * and algorithm that builds polygons and the PolyLine data representation of incomplete polygons that are
|
Chris@16
|
298 * being built. It does this by providing an iterface to access the information about the last edge at the
|
Chris@16
|
299 * tail of the PolyLine it is associated with. To a polygon constructing algorithm, an ActiveTail is a floating
|
Chris@16
|
300 * edge of an incomplete polygon and has an orientation and coordinate value, as well as knowing which side of
|
Chris@16
|
301 * that edge is supposed to be solid or space. Any incomplete polygon will have two active tails. Active tails
|
Chris@16
|
302 * may be joined together to merge two incomplete polygons into a larger incomplete polygon. If two active tails
|
Chris@16
|
303 * that are to be merged are the oppositve ends of the same incomplete polygon that indicates that the polygon
|
Chris@16
|
304 * has been closed and is complete. The active tail keeps a pointer to the other active tail of its incomplete
|
Chris@16
|
305 * polygon so that it is easy to check this condition. These pointers are updated when active tails are joined.
|
Chris@16
|
306 * The active tail also keeps a list of pointers to active tail objects that serve as handles to closed holes. In
|
Chris@16
|
307 * this way a hole can be associated to another incomplete polygon, which will eventually be its enclosing shell,
|
Chris@16
|
308 * or reassociate the hole to another incomplete polygon in the case that it become a hole itself. Alternately,
|
Chris@16
|
309 * the active tail may add a filiment to stitch a hole into a shell and "fracture" the hole out of the interior
|
Chris@16
|
310 * of a polygon. The active tail maintains a static output buffer to temporarily write polygon data to when
|
Chris@16
|
311 * it outputs a figure so that outputting a polygon does not require the allocation of a temporary buffer. This
|
Chris@16
|
312 * static buffer should be destroyed whenever the program determines that it won't need it anymore and would prefer to
|
Chris@16
|
313 * release the memory it has allocated back to the system.
|
Chris@16
|
314 */
|
Chris@16
|
315 template <typename Unit>
|
Chris@16
|
316 class ActiveTail {
|
Chris@16
|
317 private:
|
Chris@16
|
318 //data
|
Chris@16
|
319 PolyLine<Unit>* tailp_;
|
Chris@16
|
320 ActiveTail *otherTailp_;
|
Chris@16
|
321 std::list<ActiveTail*> holesList_;
|
Chris@16
|
322 //Sum of all the polylines which constitute the active tail (including holes)//
|
Chris@16
|
323 size_t polyLineSize_;
|
Chris@16
|
324 public:
|
Chris@16
|
325
|
Chris@16
|
326 inline size_t getPolyLineSize(){
|
Chris@16
|
327 return polyLineSize_;
|
Chris@16
|
328 }
|
Chris@16
|
329
|
Chris@16
|
330 inline void setPolyLineSize(int delta){
|
Chris@16
|
331 polyLineSize_ = delta;
|
Chris@16
|
332 }
|
Chris@16
|
333
|
Chris@16
|
334 inline void addPolyLineSize(int delta){
|
Chris@16
|
335 polyLineSize_ += delta;
|
Chris@16
|
336 }
|
Chris@16
|
337
|
Chris@16
|
338 /*
|
Chris@16
|
339 * iterator over coordinates of the figure
|
Chris@16
|
340 */
|
Chris@16
|
341 class iterator {
|
Chris@16
|
342 private:
|
Chris@16
|
343 const PolyLine<Unit>* pLine_;
|
Chris@16
|
344 const PolyLine<Unit>* pLineEnd_;
|
Chris@16
|
345 unsigned int index_;
|
Chris@16
|
346 unsigned int indexEnd_;
|
Chris@16
|
347 End startEnd_;
|
Chris@16
|
348 public:
|
Chris@16
|
349 inline iterator() : pLine_(), pLineEnd_(), index_(), indexEnd_(), startEnd_() {}
|
Chris@16
|
350 inline iterator(const ActiveTail* at, bool isHole, orientation_2d orient) :
|
Chris@16
|
351 pLine_(), pLineEnd_(), index_(), indexEnd_(), startEnd_() {
|
Chris@16
|
352 //if it is a hole and orientation is vertical or it is not a hole and orientation is horizontal
|
Chris@16
|
353 //we want to use this active tail, otherwise we want to use the other active tail
|
Chris@16
|
354 startEnd_ = TAIL;
|
Chris@16
|
355 if(!isHole ^ (orient == HORIZONTAL)) {
|
Chris@16
|
356 //switch winding direction
|
Chris@16
|
357 at = at->getOtherActiveTail();
|
Chris@16
|
358 }
|
Chris@16
|
359 //now we have the right winding direction
|
Chris@16
|
360 //if it is horizontal we need to skip the first element
|
Chris@16
|
361 pLine_ = at->getTail();
|
Chris@16
|
362
|
Chris@16
|
363 if(at->getTail()->numSegments() > 0)
|
Chris@16
|
364 index_ = at->getTail()->numSegments() - 1;
|
Chris@16
|
365
|
Chris@16
|
366 if((at->getOrient() == HORIZONTAL) ^ (orient == HORIZONTAL)) {
|
Chris@16
|
367 pLineEnd_ = at->getTail();
|
Chris@16
|
368 indexEnd_ = pLineEnd_->numSegments() - 1;
|
Chris@16
|
369 if(index_ == 0) {
|
Chris@16
|
370 pLine_ = at->getTail()->next(HEAD);
|
Chris@16
|
371 if(at->getTail()->endConnectivity(HEAD) == TAIL) {
|
Chris@16
|
372 index_ = pLine_->numSegments() -1;
|
Chris@16
|
373 } else {
|
Chris@16
|
374 startEnd_ = HEAD;
|
Chris@16
|
375 index_ = 0;
|
Chris@16
|
376 }
|
Chris@16
|
377 } else { --index_; }
|
Chris@16
|
378 } else {
|
Chris@16
|
379 pLineEnd_ = at->getOtherActiveTail()->getTail();
|
Chris@16
|
380 if(pLineEnd_->numSegments() > 0)
|
Chris@16
|
381 indexEnd_ = pLineEnd_->numSegments() - 1;
|
Chris@16
|
382 }
|
Chris@16
|
383 at->getTail()->joinTailToTail(*(at->getOtherActiveTail()->getTail()));
|
Chris@16
|
384 }
|
Chris@16
|
385
|
Chris@16
|
386 inline size_t size(void){
|
Chris@16
|
387 size_t count = 0;
|
Chris@16
|
388 End dir = startEnd_;
|
Chris@16
|
389 PolyLine<Unit> const * currLine = pLine_;
|
Chris@16
|
390 size_t ops = 0;
|
Chris@16
|
391 while(currLine != pLineEnd_){
|
Chris@16
|
392 ops++;
|
Chris@16
|
393 count += currLine->numSegments();
|
Chris@16
|
394 currLine = currLine->next(dir == HEAD ? TAIL : HEAD);
|
Chris@16
|
395 dir = currLine->endConnectivity(dir == HEAD ? TAIL : HEAD);
|
Chris@16
|
396 }
|
Chris@16
|
397 count += pLineEnd_->numSegments();
|
Chris@16
|
398 return count; //no. of vertices
|
Chris@16
|
399 }
|
Chris@16
|
400
|
Chris@16
|
401 //use bitwise copy and assign provided by the compiler
|
Chris@16
|
402 inline iterator& operator++() {
|
Chris@16
|
403 if(pLine_ == pLineEnd_ && index_ == indexEnd_) {
|
Chris@16
|
404 pLine_ = 0;
|
Chris@16
|
405 index_ = 0;
|
Chris@16
|
406 return *this;
|
Chris@16
|
407 }
|
Chris@16
|
408 if(startEnd_ == HEAD) {
|
Chris@16
|
409 ++index_;
|
Chris@16
|
410 if(index_ == pLine_->numSegments()) {
|
Chris@16
|
411 End end = pLine_->endConnectivity(TAIL);
|
Chris@16
|
412 pLine_ = pLine_->next(TAIL);
|
Chris@16
|
413 if(end == TAIL) {
|
Chris@16
|
414 startEnd_ = TAIL;
|
Chris@16
|
415 index_ = pLine_->numSegments() -1;
|
Chris@16
|
416 } else {
|
Chris@16
|
417 index_ = 0;
|
Chris@16
|
418 }
|
Chris@16
|
419 }
|
Chris@16
|
420 } else {
|
Chris@16
|
421 if(index_ == 0) {
|
Chris@16
|
422 End end = pLine_->endConnectivity(HEAD);
|
Chris@16
|
423 pLine_ = pLine_->next(HEAD);
|
Chris@16
|
424 if(end == TAIL) {
|
Chris@16
|
425 index_ = pLine_->numSegments() -1;
|
Chris@16
|
426 } else {
|
Chris@16
|
427 startEnd_ = HEAD;
|
Chris@16
|
428 index_ = 0;
|
Chris@16
|
429 }
|
Chris@16
|
430 } else {
|
Chris@16
|
431 --index_;
|
Chris@16
|
432 }
|
Chris@16
|
433 }
|
Chris@16
|
434 return *this;
|
Chris@16
|
435 }
|
Chris@16
|
436 inline const iterator operator++(int) {
|
Chris@16
|
437 iterator tmp(*this);
|
Chris@16
|
438 ++(*this);
|
Chris@16
|
439 return tmp;
|
Chris@16
|
440 }
|
Chris@16
|
441 inline bool operator==(const iterator& that) const {
|
Chris@16
|
442 return pLine_ == that.pLine_ && index_ == that.index_;
|
Chris@16
|
443 }
|
Chris@16
|
444 inline bool operator!=(const iterator& that) const {
|
Chris@16
|
445 return pLine_ != that.pLine_ || index_ != that.index_;
|
Chris@16
|
446 }
|
Chris@16
|
447 inline Unit operator*() { return (*pLine_)[index_]; }
|
Chris@16
|
448 };
|
Chris@16
|
449
|
Chris@16
|
450 /*
|
Chris@16
|
451 * iterator over holes contained within the figure
|
Chris@16
|
452 */
|
Chris@16
|
453 typedef typename std::list<ActiveTail*>::const_iterator iteratorHoles;
|
Chris@16
|
454
|
Chris@16
|
455 //default constructor
|
Chris@16
|
456 ActiveTail();
|
Chris@16
|
457
|
Chris@16
|
458 //constructor
|
Chris@16
|
459 ActiveTail(orientation_2d orient, Unit coord, Side solidToRight, ActiveTail* otherTailp);
|
Chris@16
|
460
|
Chris@16
|
461 //constructor
|
Chris@16
|
462 ActiveTail(PolyLine<Unit>* active, ActiveTail* otherTailp);
|
Chris@16
|
463
|
Chris@16
|
464 //copy constructor
|
Chris@16
|
465 ActiveTail(const ActiveTail& that);
|
Chris@16
|
466
|
Chris@16
|
467 //destructor
|
Chris@16
|
468 ~ActiveTail();
|
Chris@16
|
469
|
Chris@16
|
470 //assignment operator
|
Chris@16
|
471 ActiveTail& operator=(const ActiveTail& that);
|
Chris@16
|
472
|
Chris@16
|
473 //equivalence operator
|
Chris@16
|
474 bool operator==(const ActiveTail& b) const;
|
Chris@16
|
475
|
Chris@16
|
476 /*
|
Chris@16
|
477 * comparison operators, ActiveTail objects are sortable by geometry
|
Chris@16
|
478 */
|
Chris@16
|
479 bool operator<(const ActiveTail& b) const;
|
Chris@16
|
480 bool operator<=(const ActiveTail& b) const;
|
Chris@16
|
481 bool operator>(const ActiveTail& b) const;
|
Chris@16
|
482 bool operator>=(const ActiveTail& b) const;
|
Chris@16
|
483
|
Chris@16
|
484 /*
|
Chris@16
|
485 * get the pointer to the polyline that this is an active tail of
|
Chris@16
|
486 */
|
Chris@16
|
487 PolyLine<Unit>* getTail() const;
|
Chris@16
|
488
|
Chris@16
|
489 /*
|
Chris@16
|
490 * get the pointer to the polyline at the other end of the chain
|
Chris@16
|
491 */
|
Chris@16
|
492 PolyLine<Unit>* getOtherTail() const;
|
Chris@16
|
493
|
Chris@16
|
494 /*
|
Chris@16
|
495 * get the pointer to the activetail at the other end of the chain
|
Chris@16
|
496 */
|
Chris@16
|
497 ActiveTail* getOtherActiveTail() const;
|
Chris@16
|
498
|
Chris@16
|
499 /*
|
Chris@16
|
500 * test if another active tail is the other end of the chain
|
Chris@16
|
501 */
|
Chris@16
|
502 bool isOtherTail(const ActiveTail& b);
|
Chris@16
|
503
|
Chris@16
|
504 /*
|
Chris@16
|
505 * update this end of chain pointer to new polyline
|
Chris@16
|
506 */
|
Chris@16
|
507 ActiveTail& updateTail(PolyLine<Unit>* newTail);
|
Chris@16
|
508
|
Chris@16
|
509 /*
|
Chris@16
|
510 * associate a hole to this active tail by the specified policy
|
Chris@16
|
511 */
|
Chris@16
|
512 ActiveTail* addHole(ActiveTail* hole, bool fractureHoles);
|
Chris@16
|
513
|
Chris@16
|
514 /*
|
Chris@16
|
515 * get the list of holes
|
Chris@16
|
516 */
|
Chris@16
|
517 const std::list<ActiveTail*>& getHoles() const;
|
Chris@16
|
518
|
Chris@16
|
519 /*
|
Chris@16
|
520 * copy holes from that to this
|
Chris@16
|
521 */
|
Chris@16
|
522 void copyHoles(ActiveTail& that);
|
Chris@16
|
523
|
Chris@16
|
524 /*
|
Chris@16
|
525 * find out if solid to right
|
Chris@16
|
526 */
|
Chris@16
|
527 bool solidToRight() const;
|
Chris@16
|
528
|
Chris@16
|
529 /*
|
Chris@16
|
530 * get coordinate (getCoord and getCoordinate are aliases for eachother)
|
Chris@16
|
531 */
|
Chris@16
|
532 Unit getCoord() const;
|
Chris@16
|
533 Unit getCoordinate() const;
|
Chris@16
|
534
|
Chris@16
|
535 /*
|
Chris@16
|
536 * get the tail orientation
|
Chris@16
|
537 */
|
Chris@16
|
538 orientation_2d getOrient() const;
|
Chris@16
|
539
|
Chris@16
|
540 /*
|
Chris@16
|
541 * add a coordinate to the polygon at this active tail end, properly handle degenerate edges by removing redundant coordinate
|
Chris@16
|
542 */
|
Chris@16
|
543 void pushCoordinate(Unit coord);
|
Chris@16
|
544
|
Chris@16
|
545 /*
|
Chris@16
|
546 * write the figure that this active tail points to out to the temp buffer
|
Chris@16
|
547 */
|
Chris@16
|
548 void writeOutFigure(std::vector<Unit>& outVec, bool isHole = false) const;
|
Chris@16
|
549
|
Chris@16
|
550 /*
|
Chris@16
|
551 * write the figure that this active tail points to out through iterators
|
Chris@16
|
552 */
|
Chris@16
|
553 void writeOutFigureItrs(iterator& beginOut, iterator& endOut, bool isHole = false, orientation_2d orient = VERTICAL) const;
|
Chris@16
|
554 iterator begin(bool isHole, orientation_2d orient) const;
|
Chris@16
|
555 iterator end() const;
|
Chris@16
|
556
|
Chris@16
|
557 /*
|
Chris@16
|
558 * write the holes that this active tail points to out through iterators
|
Chris@16
|
559 */
|
Chris@16
|
560 void writeOutFigureHoleItrs(iteratorHoles& beginOut, iteratorHoles& endOut) const;
|
Chris@16
|
561 iteratorHoles beginHoles() const;
|
Chris@16
|
562 iteratorHoles endHoles() const;
|
Chris@16
|
563
|
Chris@16
|
564 /*
|
Chris@16
|
565 * joins the two chains that the two active tail tails are ends of
|
Chris@16
|
566 * checks for closure of figure and writes out polygons appropriately
|
Chris@16
|
567 * returns a handle to a hole if one is closed
|
Chris@16
|
568 */
|
Chris@16
|
569 static ActiveTail* joinChains(ActiveTail* at1, ActiveTail* at2, bool solid, std::vector<Unit>& outBufferTmp);
|
Chris@16
|
570 template <typename PolygonT>
|
Chris@16
|
571 static ActiveTail* joinChains(ActiveTail* at1, ActiveTail* at2, bool solid, typename std::vector<PolygonT>& outBufferTmp);
|
Chris@16
|
572
|
Chris@16
|
573 /*
|
Chris@16
|
574 * deallocate temp buffer
|
Chris@16
|
575 */
|
Chris@16
|
576 static void destroyOutBuffer();
|
Chris@16
|
577
|
Chris@16
|
578 /*
|
Chris@16
|
579 * deallocate all polygon data this active tail points to (deep delete, call only from one of a pair of active tails)
|
Chris@16
|
580 */
|
Chris@16
|
581 void destroyContents();
|
Chris@16
|
582 };
|
Chris@16
|
583
|
Chris@16
|
584 /* allocate a polyline object */
|
Chris@16
|
585 template <typename Unit>
|
Chris@16
|
586 PolyLine<Unit>* createPolyLine(orientation_2d orient, Unit coord, Side side);
|
Chris@16
|
587
|
Chris@16
|
588 /* deallocate a polyline object */
|
Chris@16
|
589 template <typename Unit>
|
Chris@16
|
590 void destroyPolyLine(PolyLine<Unit>* pLine);
|
Chris@16
|
591
|
Chris@16
|
592 /* allocate an activetail object */
|
Chris@16
|
593 template <typename Unit>
|
Chris@16
|
594 ActiveTail<Unit>* createActiveTail();
|
Chris@16
|
595
|
Chris@16
|
596 /* deallocate an activetail object */
|
Chris@16
|
597 template <typename Unit>
|
Chris@16
|
598 void destroyActiveTail(ActiveTail<Unit>* aTail);
|
Chris@16
|
599
|
Chris@16
|
600 template<bool orientT, typename Unit>
|
Chris@16
|
601 class PolyLineHoleData {
|
Chris@16
|
602 private:
|
Chris@16
|
603 ActiveTail<Unit>* p_;
|
Chris@16
|
604 public:
|
Chris@16
|
605 typedef Unit coordinate_type;
|
Chris@16
|
606 typedef typename ActiveTail<Unit>::iterator compact_iterator_type;
|
Chris@16
|
607 typedef iterator_compact_to_points<compact_iterator_type, point_data<coordinate_type> > iterator_type;
|
Chris@16
|
608 inline PolyLineHoleData() : p_(0) {}
|
Chris@16
|
609 inline PolyLineHoleData(ActiveTail<Unit>* p) : p_(p) {}
|
Chris@16
|
610 //use default copy and assign
|
Chris@16
|
611 inline compact_iterator_type begin_compact() const { return p_->begin(true, (orientT ? VERTICAL : HORIZONTAL)); }
|
Chris@16
|
612 inline compact_iterator_type end_compact() const { return p_->end(); }
|
Chris@16
|
613 inline iterator_type begin() const { return iterator_type(begin_compact(), end_compact()); }
|
Chris@16
|
614 inline iterator_type end() const { return iterator_type(end_compact(), end_compact()); }
|
Chris@16
|
615 inline std::size_t size() const {
|
Chris@16
|
616 return p_->getPolyLineSize();
|
Chris@16
|
617 }
|
Chris@16
|
618 inline ActiveTail<Unit>* yield() { return p_; }
|
Chris@16
|
619 template<class iT>
|
Chris@16
|
620 inline PolyLineHoleData& set(iT inputBegin, iT inputEnd) {
|
Chris@16
|
621 return *this;
|
Chris@16
|
622 }
|
Chris@16
|
623 template<class iT>
|
Chris@16
|
624 inline PolyLineHoleData& set_compact(iT inputBegin, iT inputEnd) {
|
Chris@16
|
625 return *this;
|
Chris@16
|
626 }
|
Chris@16
|
627
|
Chris@16
|
628 };
|
Chris@16
|
629
|
Chris@16
|
630 template<bool orientT, typename Unit>
|
Chris@16
|
631 class PolyLinePolygonWithHolesData {
|
Chris@16
|
632 private:
|
Chris@16
|
633 ActiveTail<Unit>* p_;
|
Chris@16
|
634 public:
|
Chris@16
|
635 typedef Unit coordinate_type;
|
Chris@16
|
636 typedef typename ActiveTail<Unit>::iterator compact_iterator_type;
|
Chris@16
|
637 typedef iterator_compact_to_points<compact_iterator_type, point_data<coordinate_type> > iterator_type;
|
Chris@16
|
638 typedef PolyLineHoleData<orientT, Unit> hole_type;
|
Chris@16
|
639 typedef typename coordinate_traits<Unit>::area_type area_type;
|
Chris@16
|
640 class iteratorHoles {
|
Chris@16
|
641 private:
|
Chris@16
|
642 typename ActiveTail<Unit>::iteratorHoles itr_;
|
Chris@16
|
643 public:
|
Chris@16
|
644 inline iteratorHoles() : itr_() {}
|
Chris@16
|
645 inline iteratorHoles(typename ActiveTail<Unit>::iteratorHoles itr) : itr_(itr) {}
|
Chris@16
|
646 //use bitwise copy and assign provided by the compiler
|
Chris@16
|
647 inline iteratorHoles& operator++() {
|
Chris@16
|
648 ++itr_;
|
Chris@16
|
649 return *this;
|
Chris@16
|
650 }
|
Chris@16
|
651 inline const iteratorHoles operator++(int) {
|
Chris@16
|
652 iteratorHoles tmp(*this);
|
Chris@16
|
653 ++(*this);
|
Chris@16
|
654 return tmp;
|
Chris@16
|
655 }
|
Chris@16
|
656 inline bool operator==(const iteratorHoles& that) const {
|
Chris@16
|
657 return itr_ == that.itr_;
|
Chris@16
|
658 }
|
Chris@16
|
659 inline bool operator!=(const iteratorHoles& that) const {
|
Chris@16
|
660 return itr_ != that.itr_;
|
Chris@16
|
661 }
|
Chris@16
|
662 inline PolyLineHoleData<orientT, Unit> operator*() { return PolyLineHoleData<orientT, Unit>(*itr_);}
|
Chris@16
|
663 };
|
Chris@16
|
664 typedef iteratorHoles iterator_holes_type;
|
Chris@16
|
665
|
Chris@16
|
666 inline PolyLinePolygonWithHolesData() : p_(0) {}
|
Chris@16
|
667 inline PolyLinePolygonWithHolesData(ActiveTail<Unit>* p) : p_(p) {}
|
Chris@16
|
668 //use default copy and assign
|
Chris@16
|
669 inline compact_iterator_type begin_compact() const { return p_->begin(false, (orientT ? VERTICAL : HORIZONTAL)); }
|
Chris@16
|
670 inline compact_iterator_type end_compact() const { return p_->end(); }
|
Chris@16
|
671 inline iterator_type begin() const { return iterator_type(begin_compact(), end_compact()); }
|
Chris@16
|
672 inline iterator_type end() const { return iterator_type(end_compact(), end_compact()); }
|
Chris@16
|
673 inline iteratorHoles begin_holes() const { return iteratorHoles(p_->beginHoles()); }
|
Chris@16
|
674 inline iteratorHoles end_holes() const { return iteratorHoles(p_->endHoles()); }
|
Chris@16
|
675 inline ActiveTail<Unit>* yield() { return p_; }
|
Chris@16
|
676 //stub out these four required functions that will not be used but are needed for the interface
|
Chris@16
|
677 inline std::size_t size_holes() const { return 0; }
|
Chris@16
|
678 inline std::size_t size() const { return 0; }
|
Chris@16
|
679 template<class iT>
|
Chris@16
|
680 inline PolyLinePolygonWithHolesData& set(iT inputBegin, iT inputEnd) {
|
Chris@16
|
681 return *this;
|
Chris@16
|
682 }
|
Chris@16
|
683 template<class iT>
|
Chris@16
|
684 inline PolyLinePolygonWithHolesData& set_compact(iT inputBegin, iT inputEnd) {
|
Chris@16
|
685 return *this;
|
Chris@16
|
686 }
|
Chris@16
|
687
|
Chris@16
|
688 // initialize a polygon from x,y values, it is assumed that the first is an x
|
Chris@16
|
689 // and that the input is a well behaved polygon
|
Chris@16
|
690 template<class iT>
|
Chris@16
|
691 inline PolyLinePolygonWithHolesData& set_holes(iT inputBegin, iT inputEnd) {
|
Chris@16
|
692 return *this;
|
Chris@16
|
693 }
|
Chris@16
|
694 };
|
Chris@16
|
695
|
Chris@16
|
696
|
Chris@16
|
697 template <bool orientT, typename Unit, typename polygon_concept_type>
|
Chris@16
|
698 struct PolyLineType { };
|
Chris@16
|
699 template <bool orientT, typename Unit>
|
Chris@16
|
700 struct PolyLineType<orientT, Unit, polygon_90_with_holes_concept> { typedef PolyLinePolygonWithHolesData<orientT, Unit> type; };
|
Chris@16
|
701 template <bool orientT, typename Unit>
|
Chris@16
|
702 struct PolyLineType<orientT, Unit, polygon_45_with_holes_concept> { typedef PolyLinePolygonWithHolesData<orientT, Unit> type; };
|
Chris@16
|
703 template <bool orientT, typename Unit>
|
Chris@16
|
704 struct PolyLineType<orientT, Unit, polygon_with_holes_concept> { typedef PolyLinePolygonWithHolesData<orientT, Unit> type; };
|
Chris@16
|
705 template <bool orientT, typename Unit>
|
Chris@16
|
706 struct PolyLineType<orientT, Unit, polygon_90_concept> { typedef PolyLineHoleData<orientT, Unit> type; };
|
Chris@16
|
707 template <bool orientT, typename Unit>
|
Chris@16
|
708 struct PolyLineType<orientT, Unit, polygon_45_concept> { typedef PolyLineHoleData<orientT, Unit> type; };
|
Chris@16
|
709 template <bool orientT, typename Unit>
|
Chris@16
|
710 struct PolyLineType<orientT, Unit, polygon_concept> { typedef PolyLineHoleData<orientT, Unit> type; };
|
Chris@16
|
711
|
Chris@16
|
712 template <bool orientT, typename Unit, typename polygon_concept_type>
|
Chris@16
|
713 class ScanLineToPolygonItrs {
|
Chris@16
|
714 private:
|
Chris@16
|
715 std::map<Unit, ActiveTail<Unit>*> tailMap_;
|
Chris@16
|
716 typedef typename PolyLineType<orientT, Unit, polygon_concept_type>::type PolyLinePolygonData;
|
Chris@16
|
717 std::vector<PolyLinePolygonData> outputPolygons_;
|
Chris@16
|
718 bool fractureHoles_;
|
Chris@16
|
719 public:
|
Chris@16
|
720 typedef typename std::vector<PolyLinePolygonData>::iterator iterator;
|
Chris@16
|
721 inline ScanLineToPolygonItrs() : tailMap_(), outputPolygons_(), fractureHoles_(false) {}
|
Chris@16
|
722 /* construct a scanline with the proper offsets, protocol and options */
|
Chris@16
|
723 inline ScanLineToPolygonItrs(bool fractureHoles) : tailMap_(), outputPolygons_(), fractureHoles_(fractureHoles) {}
|
Chris@16
|
724
|
Chris@16
|
725 ~ScanLineToPolygonItrs() { clearOutput_(); }
|
Chris@16
|
726
|
Chris@16
|
727 /* process all vertical edges, left and right, at a unique x coordinate, edges must be sorted low to high */
|
Chris@16
|
728 void processEdges(iterator& beginOutput, iterator& endOutput,
|
Chris@16
|
729 Unit currentX, std::vector<interval_data<Unit> >& leftEdges,
|
Chris@16
|
730 std::vector<interval_data<Unit> >& rightEdges,
|
Chris@16
|
731 size_t vertexThreshold=(std::numeric_limits<size_t>::max)() );
|
Chris@16
|
732
|
Chris@16
|
733 /**********************************************************************
|
Chris@16
|
734 *methods implementing new polygon formation code
|
Chris@16
|
735 *
|
Chris@16
|
736 **********************************************************************/
|
Chris@16
|
737 void updatePartialSimplePolygonsWithRightEdges(Unit currentX,
|
Chris@16
|
738 const std::vector<interval_data<Unit> >& leftEdges, size_t threshold);
|
Chris@16
|
739
|
Chris@16
|
740 void updatePartialSimplePolygonsWithLeftEdges(Unit currentX,
|
Chris@16
|
741 const std::vector<interval_data<Unit> >& leftEdges, size_t threshold);
|
Chris@16
|
742
|
Chris@16
|
743 void closePartialSimplePolygon(Unit, ActiveTail<Unit>*, ActiveTail<Unit>*);
|
Chris@16
|
744
|
Chris@16
|
745 void maintainPartialSimplePolygonInvariant(iterator& ,iterator& ,Unit,
|
Chris@16
|
746 const std::vector<interval_data<Unit> >&,
|
Chris@16
|
747 const std::vector<interval_data<Unit> >&,
|
Chris@16
|
748 size_t vertexThreshold=(std::numeric_limits<size_t>::max)());
|
Chris@16
|
749
|
Chris@16
|
750 void insertNewLeftEdgeIntoTailMap(Unit, Unit, Unit,
|
Chris@16
|
751 typename std::map<Unit, ActiveTail<Unit>*>::iterator &);
|
Chris@16
|
752 /**********************************************************************/
|
Chris@16
|
753
|
Chris@16
|
754 inline size_t getTailMapSize(){
|
Chris@16
|
755 typename std::map<Unit, ActiveTail<Unit>* >::const_iterator itr;
|
Chris@16
|
756 size_t tsize = 0;
|
Chris@16
|
757 for(itr=tailMap_.begin(); itr!=tailMap_.end(); ++itr){
|
Chris@16
|
758 tsize += (itr->second)->getPolyLineSize();
|
Chris@16
|
759 }
|
Chris@16
|
760 return tsize;
|
Chris@16
|
761 }
|
Chris@16
|
762 /*print the active tails in this map:*/
|
Chris@16
|
763 inline void print(){
|
Chris@16
|
764 typename std::map<Unit, ActiveTail<Unit>* >::const_iterator itr;
|
Chris@16
|
765 printf("=========TailMap[%lu]=========\n", tailMap_.size());
|
Chris@16
|
766 for(itr=tailMap_.begin(); itr!=tailMap_.end(); ++itr){
|
Chris@16
|
767 std::cout<< "[" << itr->first << "] : " << std::endl;
|
Chris@16
|
768 //print active tail//
|
Chris@16
|
769 ActiveTail<Unit> const *t = (itr->second);
|
Chris@16
|
770 PolyLine<Unit> const *pBegin = t->getTail();
|
Chris@16
|
771 PolyLine<Unit> const *pEnd = t->getOtherActiveTail()->getTail();
|
Chris@16
|
772 std::string sorient = pBegin->solidToRight() ? "RIGHT" : "LEFT";
|
Chris@16
|
773 std::cout<< " ActiveTail.tailp_ (solid= " << sorient ;
|
Chris@16
|
774 End dir = TAIL;
|
Chris@16
|
775 while(pBegin!=pEnd){
|
Chris@16
|
776 std::cout << pBegin << "={ ";
|
Chris@16
|
777 for(size_t i=0; i<pBegin->numSegments(); i++){
|
Chris@16
|
778 point_data<Unit> u = pBegin->getPoint(i);
|
Chris@16
|
779 std::cout << "(" << u.x() << "," << u.y() << ") ";
|
Chris@16
|
780 }
|
Chris@16
|
781 std::cout << "} ";
|
Chris@16
|
782 pBegin = pBegin->next(dir == HEAD ? TAIL : HEAD);
|
Chris@16
|
783 dir = pBegin->endConnectivity(dir == HEAD ? TAIL : HEAD);
|
Chris@16
|
784 }
|
Chris@16
|
785 if(pEnd){
|
Chris@16
|
786 std::cout << pEnd << "={ ";
|
Chris@16
|
787 for(size_t i=0; i<pEnd->numSegments(); i++){
|
Chris@16
|
788 point_data<Unit> u = pEnd->getPoint(i);
|
Chris@16
|
789 std::cout << "(" << u.x() << "," << u.y() << ") ";
|
Chris@16
|
790 }
|
Chris@16
|
791 std::cout << "} ";
|
Chris@16
|
792 }
|
Chris@16
|
793 std::cout << " end= " << pEnd << std::endl;
|
Chris@16
|
794 }
|
Chris@16
|
795 }
|
Chris@16
|
796
|
Chris@16
|
797 private:
|
Chris@16
|
798 void clearOutput_();
|
Chris@16
|
799 };
|
Chris@16
|
800
|
Chris@16
|
801 /*
|
Chris@16
|
802 * ScanLine does all the work of stitching together polygons from incoming vertical edges
|
Chris@16
|
803 */
|
Chris@16
|
804 // template <typename Unit, typename polygon_concept_type>
|
Chris@16
|
805 // class ScanLineToPolygons {
|
Chris@16
|
806 // private:
|
Chris@16
|
807 // ScanLineToPolygonItrs<true, Unit> scanline_;
|
Chris@16
|
808 // public:
|
Chris@16
|
809 // inline ScanLineToPolygons() : scanline_() {}
|
Chris@16
|
810 // /* construct a scanline with the proper offsets, protocol and options */
|
Chris@16
|
811 // inline ScanLineToPolygons(bool fractureHoles) : scanline_(fractureHoles) {}
|
Chris@16
|
812
|
Chris@16
|
813 // /* process all vertical edges, left and right, at a unique x coordinate, edges must be sorted low to high */
|
Chris@16
|
814 // inline void processEdges(std::vector<Unit>& outBufferTmp, Unit currentX, std::vector<interval_data<Unit> >& leftEdges,
|
Chris@16
|
815 // std::vector<interval_data<Unit> >& rightEdges) {
|
Chris@16
|
816 // typename ScanLineToPolygonItrs<true, Unit>::iterator itr, endItr;
|
Chris@16
|
817 // scanline_.processEdges(itr, endItr, currentX, leftEdges, rightEdges);
|
Chris@16
|
818 // //copy data into outBufferTmp
|
Chris@16
|
819 // while(itr != endItr) {
|
Chris@16
|
820 // typename PolyLinePolygonData<true, Unit>::iterator pditr;
|
Chris@16
|
821 // outBufferTmp.push_back(0);
|
Chris@16
|
822 // unsigned int sizeIndex = outBufferTmp.size() - 1;
|
Chris@16
|
823 // int count = 0;
|
Chris@16
|
824 // for(pditr = (*itr).begin(); pditr != (*itr).end(); ++pditr) {
|
Chris@16
|
825 // outBufferTmp.push_back(*pditr);
|
Chris@16
|
826 // ++count;
|
Chris@16
|
827 // }
|
Chris@16
|
828 // outBufferTmp[sizeIndex] = count;
|
Chris@16
|
829 // typename PolyLinePolygonData<true, Unit>::iteratorHoles pdHoleItr;
|
Chris@16
|
830 // for(pdHoleItr = (*itr).beginHoles(); pdHoleItr != (*itr).endHoles(); ++pdHoleItr) {
|
Chris@16
|
831 // outBufferTmp.push_back(0);
|
Chris@16
|
832 // unsigned int sizeIndex2 = outBufferTmp.size() - 1;
|
Chris@16
|
833 // int count2 = 0;
|
Chris@16
|
834 // for(pditr = (*pdHoleItr).begin(); pditr != (*pdHoleItr).end(); ++pditr) {
|
Chris@16
|
835 // outBufferTmp.push_back(*pditr);
|
Chris@16
|
836 // ++count2;
|
Chris@16
|
837 // }
|
Chris@16
|
838 // outBufferTmp[sizeIndex2] = -count;
|
Chris@16
|
839 // }
|
Chris@16
|
840 // ++itr;
|
Chris@16
|
841 // }
|
Chris@16
|
842 // }
|
Chris@16
|
843 // };
|
Chris@16
|
844
|
Chris@16
|
845 const int VERTICAL_HEAD = 1, HEAD_TO_TAIL = 2, TAIL_TO_TAIL = 4, SOLID_TO_RIGHT = 8;
|
Chris@16
|
846
|
Chris@16
|
847 //EVERY FUNCTION in this DEF file should be explicitly defined as inline
|
Chris@16
|
848
|
Chris@16
|
849 //microsoft compiler improperly warns whenever you cast an integer to bool
|
Chris@16
|
850 //call this function on an integer to convert it to bool without a warning
|
Chris@16
|
851 template <class T>
|
Chris@16
|
852 inline bool to_bool(const T& val) { return val != 0; }
|
Chris@16
|
853
|
Chris@16
|
854 //default constructor (for preallocation)
|
Chris@16
|
855 template <typename Unit>
|
Chris@16
|
856 inline PolyLine<Unit>::PolyLine() : ptdata_() ,headp_(0), tailp_(0), state_(-1) {}
|
Chris@16
|
857
|
Chris@16
|
858 //constructor
|
Chris@16
|
859 template <typename Unit>
|
Chris@16
|
860 inline PolyLine<Unit>::PolyLine(orientation_2d orient, Unit coord, Side side) :
|
Chris@16
|
861 ptdata_(1, coord),
|
Chris@16
|
862 headp_(0),
|
Chris@16
|
863 tailp_(0),
|
Chris@16
|
864 state_(orient.to_int() +
|
Chris@16
|
865 (side << 3)){}
|
Chris@16
|
866
|
Chris@16
|
867 //copy constructor
|
Chris@16
|
868 template <typename Unit>
|
Chris@16
|
869 inline PolyLine<Unit>::PolyLine(const PolyLine<Unit>& pline) : ptdata_(pline.ptdata_),
|
Chris@16
|
870 headp_(pline.headp_),
|
Chris@16
|
871 tailp_(pline.tailp_),
|
Chris@16
|
872 state_(pline.state_) {}
|
Chris@16
|
873
|
Chris@16
|
874 //destructor
|
Chris@16
|
875 template <typename Unit>
|
Chris@16
|
876 inline PolyLine<Unit>::~PolyLine() {
|
Chris@16
|
877 //clear out data just in case it is read later
|
Chris@16
|
878 headp_ = tailp_ = 0;
|
Chris@16
|
879 state_ = 0;
|
Chris@16
|
880 }
|
Chris@16
|
881
|
Chris@16
|
882 template <typename Unit>
|
Chris@16
|
883 inline PolyLine<Unit>& PolyLine<Unit>::operator=(const PolyLine<Unit>& that) {
|
Chris@16
|
884 if(!(this == &that)) {
|
Chris@16
|
885 headp_ = that.headp_;
|
Chris@16
|
886 tailp_ = that.tailp_;
|
Chris@16
|
887 ptdata_ = that.ptdata_;
|
Chris@16
|
888 state_ = that.state_;
|
Chris@16
|
889 }
|
Chris@16
|
890 return *this;
|
Chris@16
|
891 }
|
Chris@16
|
892
|
Chris@16
|
893 template <typename Unit>
|
Chris@16
|
894 inline bool PolyLine<Unit>::operator==(const PolyLine<Unit>& b) const {
|
Chris@16
|
895 return this == &b || (state_ == b.state_ &&
|
Chris@16
|
896 headp_ == b.headp_ &&
|
Chris@16
|
897 tailp_ == b.tailp_);
|
Chris@16
|
898 }
|
Chris@16
|
899
|
Chris@16
|
900 //valid PolyLine
|
Chris@16
|
901 template <typename Unit>
|
Chris@16
|
902 inline bool PolyLine<Unit>::isValid() const {
|
Chris@16
|
903 return state_ > -1; }
|
Chris@16
|
904
|
Chris@16
|
905 //first coordinate is an X value
|
Chris@16
|
906 //first segment is vertical
|
Chris@16
|
907 template <typename Unit>
|
Chris@16
|
908 inline bool PolyLine<Unit>::verticalHead() const {
|
Chris@16
|
909 return state_ & VERTICAL_HEAD;
|
Chris@16
|
910 }
|
Chris@16
|
911
|
Chris@16
|
912 //retrun true is PolyLine has odd number of coordiantes
|
Chris@16
|
913 template <typename Unit>
|
Chris@16
|
914 inline bool PolyLine<Unit>::oddLength() const {
|
Chris@16
|
915 return to_bool((ptdata_.size()-1) % 2);
|
Chris@16
|
916 }
|
Chris@16
|
917
|
Chris@16
|
918 //last coordiante is an X value
|
Chris@16
|
919 //last segment is vertical
|
Chris@16
|
920 template <typename Unit>
|
Chris@16
|
921 inline bool PolyLine<Unit>::verticalTail() const {
|
Chris@16
|
922 return to_bool(verticalHead() ^ oddLength());
|
Chris@16
|
923 }
|
Chris@16
|
924
|
Chris@16
|
925 template <typename Unit>
|
Chris@16
|
926 inline orientation_2d PolyLine<Unit>::tailOrient() const {
|
Chris@16
|
927 return (verticalTail() ? VERTICAL : HORIZONTAL);
|
Chris@16
|
928 }
|
Chris@16
|
929
|
Chris@16
|
930 template <typename Unit>
|
Chris@16
|
931 inline orientation_2d PolyLine<Unit>::headOrient() const {
|
Chris@16
|
932 return (verticalHead() ? VERTICAL : HORIZONTAL);
|
Chris@16
|
933 }
|
Chris@16
|
934
|
Chris@16
|
935 template <typename Unit>
|
Chris@16
|
936 inline End PolyLine<Unit>::endConnectivity(End end) const {
|
Chris@16
|
937 //Tail should be defined as true
|
Chris@16
|
938 if(end) { return tailToTail(); }
|
Chris@16
|
939 return headToTail();
|
Chris@16
|
940 }
|
Chris@16
|
941
|
Chris@16
|
942 template <typename Unit>
|
Chris@16
|
943 inline bool PolyLine<Unit>::headToTail() const {
|
Chris@16
|
944 return to_bool(state_ & HEAD_TO_TAIL);
|
Chris@16
|
945 }
|
Chris@16
|
946
|
Chris@16
|
947 template <typename Unit>
|
Chris@16
|
948 inline bool PolyLine<Unit>::headToHead() const {
|
Chris@16
|
949 return to_bool(!headToTail());
|
Chris@16
|
950 }
|
Chris@16
|
951
|
Chris@16
|
952 template <typename Unit>
|
Chris@16
|
953 inline bool PolyLine<Unit>::tailToHead() const {
|
Chris@16
|
954 return to_bool(!tailToTail());
|
Chris@16
|
955 }
|
Chris@16
|
956
|
Chris@16
|
957 template <typename Unit>
|
Chris@16
|
958 inline bool PolyLine<Unit>::tailToTail() const {
|
Chris@16
|
959 return to_bool(state_ & TAIL_TO_TAIL);
|
Chris@16
|
960 }
|
Chris@16
|
961
|
Chris@16
|
962 template <typename Unit>
|
Chris@16
|
963 inline Side PolyLine<Unit>::solidSide() const {
|
Chris@16
|
964 return solidToRight(); }
|
Chris@16
|
965
|
Chris@16
|
966 template <typename Unit>
|
Chris@16
|
967 inline bool PolyLine<Unit>::solidToRight() const {
|
Chris@16
|
968 return to_bool(state_ & SOLID_TO_RIGHT) != 0;
|
Chris@16
|
969 }
|
Chris@16
|
970
|
Chris@16
|
971 template <typename Unit>
|
Chris@16
|
972 inline bool PolyLine<Unit>::active() const {
|
Chris@16
|
973 return !to_bool(tailp_);
|
Chris@16
|
974 }
|
Chris@16
|
975
|
Chris@16
|
976 template <typename Unit>
|
Chris@16
|
977 inline PolyLine<Unit>& PolyLine<Unit>::pushCoordinate(Unit coord) {
|
Chris@16
|
978 ptdata_.push_back(coord);
|
Chris@16
|
979 return *this;
|
Chris@16
|
980 }
|
Chris@16
|
981
|
Chris@16
|
982 template <typename Unit>
|
Chris@16
|
983 inline PolyLine<Unit>& PolyLine<Unit>::popCoordinate() {
|
Chris@16
|
984 ptdata_.pop_back();
|
Chris@16
|
985 return *this;
|
Chris@16
|
986 }
|
Chris@16
|
987
|
Chris@16
|
988 template <typename Unit>
|
Chris@16
|
989 inline PolyLine<Unit>& PolyLine<Unit>::pushPoint(const point_data<Unit>& point) {
|
Chris@16
|
990 if(numSegments()){
|
Chris@16
|
991 point_data<Unit> endPt = getEndPoint();
|
Chris@16
|
992 //vertical is true, horizontal is false
|
Chris@16
|
993 if((tailOrient().to_int() ? point.get(VERTICAL) == endPt.get(VERTICAL) : point.get(HORIZONTAL) == endPt.get(HORIZONTAL))) {
|
Chris@16
|
994 //we were pushing a colinear segment
|
Chris@16
|
995 return popCoordinate();
|
Chris@16
|
996 }
|
Chris@16
|
997 }
|
Chris@16
|
998 return pushCoordinate(tailOrient().to_int() ? point.get(VERTICAL) : point.get(HORIZONTAL));
|
Chris@16
|
999 }
|
Chris@16
|
1000
|
Chris@16
|
1001 template <typename Unit>
|
Chris@16
|
1002 inline PolyLine<Unit>& PolyLine<Unit>::extendTail(Unit delta) {
|
Chris@16
|
1003 ptdata_.back() += delta;
|
Chris@16
|
1004 return *this;
|
Chris@16
|
1005 }
|
Chris@16
|
1006
|
Chris@16
|
1007 //private member function that creates a link from this PolyLine to that
|
Chris@16
|
1008 template <typename Unit>
|
Chris@16
|
1009 inline PolyLine<Unit>& PolyLine<Unit>::joinTo_(End thisEnd, PolyLine<Unit>& that, End end) {
|
Chris@16
|
1010 if(thisEnd){
|
Chris@16
|
1011 tailp_ = &that;
|
Chris@16
|
1012 state_ &= ~TAIL_TO_TAIL; //clear any previous state_ of bit (for safety)
|
Chris@16
|
1013 state_ |= (end << 2); //place bit into mask
|
Chris@16
|
1014 } else {
|
Chris@16
|
1015 headp_ = &that;
|
Chris@16
|
1016 state_ &= ~HEAD_TO_TAIL; //clear any previous state_ of bit (for safety)
|
Chris@16
|
1017 state_ |= (end << 1); //place bit into mask
|
Chris@16
|
1018 }
|
Chris@16
|
1019 return *this;
|
Chris@16
|
1020 }
|
Chris@16
|
1021
|
Chris@16
|
1022 //join two PolyLines (both ways of the association)
|
Chris@16
|
1023 template <typename Unit>
|
Chris@16
|
1024 inline PolyLine<Unit>& PolyLine<Unit>::joinTo(End thisEnd, PolyLine<Unit>& that, End end) {
|
Chris@16
|
1025 joinTo_(thisEnd, that, end);
|
Chris@16
|
1026 that.joinTo_(end, *this, thisEnd);
|
Chris@16
|
1027 return *this;
|
Chris@16
|
1028 }
|
Chris@16
|
1029
|
Chris@16
|
1030 //convenience functions for joining PolyLines
|
Chris@16
|
1031 template <typename Unit>
|
Chris@16
|
1032 inline PolyLine<Unit>& PolyLine<Unit>::joinToTail(PolyLine<Unit>& that, End end) {
|
Chris@16
|
1033 return joinTo(TAIL, that, end);
|
Chris@16
|
1034 }
|
Chris@16
|
1035 template <typename Unit>
|
Chris@16
|
1036 inline PolyLine<Unit>& PolyLine<Unit>::joinToHead(PolyLine<Unit>& that, End end) {
|
Chris@16
|
1037 return joinTo(HEAD, that, end);
|
Chris@16
|
1038 }
|
Chris@16
|
1039 template <typename Unit>
|
Chris@16
|
1040 inline PolyLine<Unit>& PolyLine<Unit>::joinHeadToHead(PolyLine<Unit>& that) {
|
Chris@16
|
1041 return joinToHead(that, HEAD);
|
Chris@16
|
1042 }
|
Chris@16
|
1043 template <typename Unit>
|
Chris@16
|
1044 inline PolyLine<Unit>& PolyLine<Unit>::joinHeadToTail(PolyLine<Unit>& that) {
|
Chris@16
|
1045 return joinToHead(that, TAIL);
|
Chris@16
|
1046 }
|
Chris@16
|
1047 template <typename Unit>
|
Chris@16
|
1048 inline PolyLine<Unit>& PolyLine<Unit>::joinTailToHead(PolyLine<Unit>& that) {
|
Chris@16
|
1049 return joinToTail(that, HEAD);
|
Chris@16
|
1050 }
|
Chris@16
|
1051 template <typename Unit>
|
Chris@16
|
1052 inline PolyLine<Unit>& PolyLine<Unit>::joinTailToTail(PolyLine<Unit>& that) {
|
Chris@16
|
1053 return joinToTail(that, TAIL);
|
Chris@16
|
1054 }
|
Chris@16
|
1055
|
Chris@16
|
1056 template <typename Unit>
|
Chris@16
|
1057 inline PolyLine<Unit>& PolyLine<Unit>::disconnectTails() {
|
Chris@16
|
1058 next(TAIL)->state_ &= !TAIL_TO_TAIL;
|
Chris@16
|
1059 next(TAIL)->tailp_ = 0;
|
Chris@16
|
1060 state_ &= !TAIL_TO_TAIL;
|
Chris@16
|
1061 tailp_ = 0;
|
Chris@16
|
1062 return *this;
|
Chris@16
|
1063 }
|
Chris@16
|
1064
|
Chris@16
|
1065 template <typename Unit>
|
Chris@16
|
1066 inline Unit PolyLine<Unit>::getEndCoord(End end) const {
|
Chris@16
|
1067 if(end)
|
Chris@16
|
1068 return ptdata_.back();
|
Chris@16
|
1069 return ptdata_.front();
|
Chris@16
|
1070 }
|
Chris@16
|
1071
|
Chris@16
|
1072 template <typename Unit>
|
Chris@16
|
1073 inline orientation_2d PolyLine<Unit>::segmentOrient(unsigned int index) const {
|
Chris@16
|
1074 return (to_bool((unsigned int)verticalHead() ^ (index % 2)) ? VERTICAL : HORIZONTAL);
|
Chris@16
|
1075 }
|
Chris@16
|
1076
|
Chris@16
|
1077 template <typename Unit>
|
Chris@16
|
1078 inline point_data<Unit> PolyLine<Unit>::getPoint(unsigned int index) const {
|
Chris@16
|
1079 //assert(isValid() && headp_->isValid()) ("PolyLine: headp_ must be valid");
|
Chris@16
|
1080 point_data<Unit> pt;
|
Chris@16
|
1081 pt.set(HORIZONTAL, ptdata_[index]);
|
Chris@16
|
1082 pt.set(VERTICAL, ptdata_[index]);
|
Chris@16
|
1083 Unit prevCoord;
|
Chris@16
|
1084 if(index == 0) {
|
Chris@16
|
1085 prevCoord = headp_->getEndCoord(headToTail());
|
Chris@16
|
1086 } else {
|
Chris@16
|
1087 prevCoord = ptdata_[index-1];
|
Chris@16
|
1088 }
|
Chris@16
|
1089 pt.set(segmentOrient(index), prevCoord);
|
Chris@16
|
1090 return pt;
|
Chris@16
|
1091 }
|
Chris@16
|
1092
|
Chris@16
|
1093 template <typename Unit>
|
Chris@16
|
1094 inline point_data<Unit> PolyLine<Unit>::getEndPoint(End end) const {
|
Chris@16
|
1095 return getPoint((end ? numSegments() - 1 : (unsigned int)0));
|
Chris@16
|
1096 }
|
Chris@16
|
1097
|
Chris@16
|
1098 template <typename Unit>
|
Chris@16
|
1099 inline Unit PolyLine<Unit>::operator[] (unsigned int index) const {
|
Chris@16
|
1100 //assert(ptdata_.size() > index) ("PolyLine: out of bounds index");
|
Chris@16
|
1101 return ptdata_[index];
|
Chris@16
|
1102 }
|
Chris@16
|
1103
|
Chris@16
|
1104 template <typename Unit>
|
Chris@16
|
1105 inline unsigned int PolyLine<Unit>::numSegments() const {
|
Chris@16
|
1106 return ptdata_.size();
|
Chris@16
|
1107 }
|
Chris@16
|
1108
|
Chris@16
|
1109 template <typename Unit>
|
Chris@16
|
1110 inline PolyLine<Unit>* PolyLine<Unit>::next(End end) const {
|
Chris@16
|
1111 return (end ? tailp_ : headp_);
|
Chris@16
|
1112 }
|
Chris@16
|
1113
|
Chris@16
|
1114 template <typename Unit>
|
Chris@16
|
1115 inline ActiveTail<Unit>::ActiveTail() : tailp_(0), otherTailp_(0), holesList_(),
|
Chris@16
|
1116 polyLineSize_(0) {}
|
Chris@16
|
1117
|
Chris@16
|
1118 template <typename Unit>
|
Chris@16
|
1119 inline ActiveTail<Unit>::ActiveTail(orientation_2d orient, Unit coord, Side solidToRight, ActiveTail* otherTailp) :
|
Chris@16
|
1120 tailp_(0), otherTailp_(0), holesList_(), polyLineSize_(0) {
|
Chris@16
|
1121 tailp_ = createPolyLine(orient, coord, solidToRight);
|
Chris@16
|
1122 otherTailp_ = otherTailp;
|
Chris@16
|
1123 polyLineSize_ = tailp_->numSegments();
|
Chris@16
|
1124 }
|
Chris@16
|
1125
|
Chris@16
|
1126 template <typename Unit>
|
Chris@16
|
1127 inline ActiveTail<Unit>::ActiveTail(PolyLine<Unit>* active, ActiveTail<Unit>* otherTailp) :
|
Chris@16
|
1128 tailp_(active), otherTailp_(otherTailp), holesList_(),
|
Chris@16
|
1129 polyLineSize_(0) {}
|
Chris@16
|
1130
|
Chris@16
|
1131 //copy constructor
|
Chris@16
|
1132 template <typename Unit>
|
Chris@16
|
1133 inline ActiveTail<Unit>::ActiveTail(const ActiveTail<Unit>& that) : tailp_(that.tailp_), otherTailp_(that.otherTailp_), holesList_(), polyLineSize_(that.polyLineSize_) {}
|
Chris@16
|
1134
|
Chris@16
|
1135 //destructor
|
Chris@16
|
1136 template <typename Unit>
|
Chris@16
|
1137 inline ActiveTail<Unit>::~ActiveTail() {
|
Chris@16
|
1138 //clear them in case the memory is read later
|
Chris@16
|
1139 tailp_ = 0; otherTailp_ = 0;
|
Chris@16
|
1140 }
|
Chris@16
|
1141
|
Chris@16
|
1142 template <typename Unit>
|
Chris@16
|
1143 inline ActiveTail<Unit>& ActiveTail<Unit>::operator=(const ActiveTail<Unit>& that) {
|
Chris@16
|
1144 //self assignment is safe in this case
|
Chris@16
|
1145 tailp_ = that.tailp_;
|
Chris@16
|
1146 otherTailp_ = that.otherTailp_;
|
Chris@16
|
1147 polyLineSize_ = that.polyLineSize_;
|
Chris@16
|
1148 return *this;
|
Chris@16
|
1149 }
|
Chris@16
|
1150
|
Chris@16
|
1151 template <typename Unit>
|
Chris@16
|
1152 inline bool ActiveTail<Unit>::operator==(const ActiveTail<Unit>& b) const {
|
Chris@16
|
1153 return tailp_ == b.tailp_ && otherTailp_ == b.otherTailp_;
|
Chris@16
|
1154 }
|
Chris@16
|
1155
|
Chris@16
|
1156 template <typename Unit>
|
Chris@16
|
1157 inline bool ActiveTail<Unit>::operator<(const ActiveTail<Unit>& b) const {
|
Chris@16
|
1158 return tailp_->getEndPoint().get(VERTICAL) < b.tailp_->getEndPoint().get(VERTICAL);
|
Chris@16
|
1159 }
|
Chris@16
|
1160
|
Chris@16
|
1161 template <typename Unit>
|
Chris@16
|
1162 inline bool ActiveTail<Unit>::operator<=(const ActiveTail<Unit>& b) const {
|
Chris@16
|
1163 return !(*this > b); }
|
Chris@16
|
1164
|
Chris@16
|
1165 template <typename Unit>
|
Chris@16
|
1166 inline bool ActiveTail<Unit>::operator>(const ActiveTail<Unit>& b) const {
|
Chris@16
|
1167 return b < (*this); }
|
Chris@16
|
1168
|
Chris@16
|
1169 template <typename Unit>
|
Chris@16
|
1170 inline bool ActiveTail<Unit>::operator>=(const ActiveTail<Unit>& b) const {
|
Chris@16
|
1171 return !(*this < b); }
|
Chris@16
|
1172
|
Chris@16
|
1173 template <typename Unit>
|
Chris@16
|
1174 inline PolyLine<Unit>* ActiveTail<Unit>::getTail() const {
|
Chris@16
|
1175 return tailp_; }
|
Chris@16
|
1176
|
Chris@16
|
1177 template <typename Unit>
|
Chris@16
|
1178 inline PolyLine<Unit>* ActiveTail<Unit>::getOtherTail() const {
|
Chris@16
|
1179 return otherTailp_->tailp_; }
|
Chris@16
|
1180
|
Chris@16
|
1181 template <typename Unit>
|
Chris@16
|
1182 inline ActiveTail<Unit>* ActiveTail<Unit>::getOtherActiveTail() const {
|
Chris@16
|
1183 return otherTailp_; }
|
Chris@16
|
1184
|
Chris@16
|
1185 template <typename Unit>
|
Chris@16
|
1186 inline bool ActiveTail<Unit>::isOtherTail(const ActiveTail<Unit>& b) {
|
Chris@16
|
1187 // assert( (tailp_ == b.getOtherTail() && getOtherTail() == b.tailp_) ||
|
Chris@16
|
1188 // (tailp_ != b.getOtherTail() && getOtherTail() != b.tailp_))
|
Chris@16
|
1189 // ("ActiveTail: Active tails out of sync");
|
Chris@16
|
1190 return otherTailp_ == &b;
|
Chris@16
|
1191 }
|
Chris@16
|
1192
|
Chris@16
|
1193 template <typename Unit>
|
Chris@16
|
1194 inline ActiveTail<Unit>& ActiveTail<Unit>::updateTail(PolyLine<Unit>* newTail) {
|
Chris@16
|
1195 //subtract the old size and add new size//
|
Chris@16
|
1196 int delta = newTail->numSegments() - tailp_->numSegments();
|
Chris@16
|
1197 addPolyLineSize(delta);
|
Chris@16
|
1198 otherTailp_->addPolyLineSize(delta);
|
Chris@16
|
1199 tailp_ = newTail;
|
Chris@16
|
1200 return *this;
|
Chris@16
|
1201 }
|
Chris@16
|
1202
|
Chris@16
|
1203 template <typename Unit>
|
Chris@16
|
1204 inline ActiveTail<Unit>* ActiveTail<Unit>::addHole(ActiveTail<Unit>* hole, bool fractureHoles) {
|
Chris@16
|
1205
|
Chris@16
|
1206 if(!fractureHoles){
|
Chris@16
|
1207 holesList_.push_back(hole);
|
Chris@16
|
1208 copyHoles(*hole);
|
Chris@16
|
1209 copyHoles(*(hole->getOtherActiveTail()));
|
Chris@16
|
1210 return this;
|
Chris@16
|
1211 }
|
Chris@16
|
1212 ActiveTail<Unit>* h, *v;
|
Chris@16
|
1213 ActiveTail<Unit>* other = hole->getOtherActiveTail();
|
Chris@16
|
1214 if(other->getOrient() == VERTICAL) {
|
Chris@16
|
1215 //assert that hole.getOrient() == HORIZONTAL
|
Chris@16
|
1216 //this case should never happen
|
Chris@16
|
1217 h = hole;
|
Chris@16
|
1218 v = other;
|
Chris@16
|
1219 } else {
|
Chris@16
|
1220 //assert that hole.getOrient() == VERTICAL
|
Chris@16
|
1221 h = other;
|
Chris@16
|
1222 v = hole;
|
Chris@16
|
1223 }
|
Chris@16
|
1224 h->pushCoordinate(v->getCoordinate());
|
Chris@16
|
1225 //assert that h->getOrient() == VERTICAL
|
Chris@16
|
1226 //v->pushCoordinate(getCoordinate());
|
Chris@16
|
1227 //assert that v->getOrient() == VERTICAL
|
Chris@16
|
1228 //I can't close a figure by adding a hole, so pass zero for xMin and yMin
|
Chris@16
|
1229 std::vector<Unit> tmpVec;
|
Chris@16
|
1230 ActiveTail<Unit>::joinChains(this, h, false, tmpVec);
|
Chris@16
|
1231 return v;
|
Chris@16
|
1232 }
|
Chris@16
|
1233
|
Chris@16
|
1234 template <typename Unit>
|
Chris@16
|
1235 inline const std::list<ActiveTail<Unit>*>& ActiveTail<Unit>::getHoles() const {
|
Chris@16
|
1236 return holesList_;
|
Chris@16
|
1237 }
|
Chris@16
|
1238
|
Chris@16
|
1239 template <typename Unit>
|
Chris@16
|
1240 inline void ActiveTail<Unit>::copyHoles(ActiveTail<Unit>& that) {
|
Chris@16
|
1241 holesList_.splice(holesList_.end(), that.holesList_); //splice the two lists together
|
Chris@16
|
1242 }
|
Chris@16
|
1243
|
Chris@16
|
1244 template <typename Unit>
|
Chris@16
|
1245 inline bool ActiveTail<Unit>::solidToRight() const {
|
Chris@16
|
1246 return getTail()->solidToRight(); }
|
Chris@16
|
1247
|
Chris@16
|
1248 template <typename Unit>
|
Chris@16
|
1249 inline Unit ActiveTail<Unit>::getCoord() const {
|
Chris@16
|
1250 return getTail()->getEndCoord(); }
|
Chris@16
|
1251
|
Chris@16
|
1252 template <typename Unit>
|
Chris@16
|
1253 inline Unit ActiveTail<Unit>::getCoordinate() const {
|
Chris@16
|
1254 return getCoord(); }
|
Chris@16
|
1255
|
Chris@16
|
1256 template <typename Unit>
|
Chris@16
|
1257 inline orientation_2d ActiveTail<Unit>::getOrient() const {
|
Chris@16
|
1258 return getTail()->tailOrient(); }
|
Chris@16
|
1259
|
Chris@16
|
1260 template <typename Unit>
|
Chris@16
|
1261 inline void ActiveTail<Unit>::pushCoordinate(Unit coord) {
|
Chris@16
|
1262 //appropriately handle any co-linear polyline segments by calling push point internally
|
Chris@16
|
1263 point_data<Unit> p;
|
Chris@16
|
1264 p.set(HORIZONTAL, coord);
|
Chris@16
|
1265 p.set(VERTICAL, coord);
|
Chris@16
|
1266 //if we are vertical assign the last coordinate (an X) to p.x, else to p.y
|
Chris@16
|
1267 p.set(getOrient().get_perpendicular(), getCoordinate());
|
Chris@16
|
1268 int oldSegments = tailp_->numSegments();
|
Chris@16
|
1269 tailp_->pushPoint(p);
|
Chris@16
|
1270 int delta = tailp_->numSegments() - oldSegments;
|
Chris@16
|
1271 addPolyLineSize(delta);
|
Chris@16
|
1272 otherTailp_->addPolyLineSize(delta);
|
Chris@16
|
1273 }
|
Chris@16
|
1274
|
Chris@16
|
1275
|
Chris@16
|
1276 //global utility functions
|
Chris@16
|
1277 template <typename Unit>
|
Chris@16
|
1278 inline PolyLine<Unit>* createPolyLine(orientation_2d orient, Unit coord, Side side) {
|
Chris@16
|
1279 return new PolyLine<Unit>(orient, coord, side);
|
Chris@16
|
1280 }
|
Chris@16
|
1281
|
Chris@16
|
1282 template <typename Unit>
|
Chris@16
|
1283 inline void destroyPolyLine(PolyLine<Unit>* pLine) {
|
Chris@16
|
1284 delete pLine;
|
Chris@16
|
1285 }
|
Chris@16
|
1286
|
Chris@16
|
1287 template <typename Unit>
|
Chris@16
|
1288 inline ActiveTail<Unit>* createActiveTail() {
|
Chris@16
|
1289 //consider replacing system allocator with ActiveTail memory pool
|
Chris@16
|
1290 return new ActiveTail<Unit>();
|
Chris@16
|
1291 }
|
Chris@16
|
1292
|
Chris@16
|
1293 template <typename Unit>
|
Chris@16
|
1294 inline void destroyActiveTail(ActiveTail<Unit>* aTail) {
|
Chris@16
|
1295 delete aTail;
|
Chris@16
|
1296 }
|
Chris@16
|
1297
|
Chris@16
|
1298
|
Chris@16
|
1299 //no recursion, to prevent max recursion depth errors
|
Chris@16
|
1300 template <typename Unit>
|
Chris@16
|
1301 inline void ActiveTail<Unit>::destroyContents() {
|
Chris@16
|
1302 tailp_->disconnectTails();
|
Chris@16
|
1303 PolyLine<Unit>* nextPolyLinep = tailp_->next(HEAD);
|
Chris@16
|
1304 End end = tailp_->endConnectivity(HEAD);
|
Chris@16
|
1305 destroyPolyLine(tailp_);
|
Chris@16
|
1306 while(nextPolyLinep) {
|
Chris@16
|
1307 End nextEnd = nextPolyLinep->endConnectivity(!end); //get the direction of next polyLine
|
Chris@16
|
1308 PolyLine<Unit>* nextNextPolyLinep = nextPolyLinep->next(!end); //get the next polyline
|
Chris@16
|
1309 destroyPolyLine(nextPolyLinep); //destroy the current polyline
|
Chris@16
|
1310 end = nextEnd;
|
Chris@16
|
1311 nextPolyLinep = nextNextPolyLinep;
|
Chris@16
|
1312 }
|
Chris@16
|
1313 }
|
Chris@16
|
1314
|
Chris@16
|
1315 template <typename Unit>
|
Chris@16
|
1316 inline typename ActiveTail<Unit>::iterator ActiveTail<Unit>::begin(bool isHole, orientation_2d orient) const {
|
Chris@16
|
1317 return iterator(this, isHole, orient);
|
Chris@16
|
1318 }
|
Chris@16
|
1319
|
Chris@16
|
1320 template <typename Unit>
|
Chris@16
|
1321 inline typename ActiveTail<Unit>::iterator ActiveTail<Unit>::end() const {
|
Chris@16
|
1322 return iterator();
|
Chris@16
|
1323 }
|
Chris@16
|
1324
|
Chris@16
|
1325 template <typename Unit>
|
Chris@16
|
1326 inline typename ActiveTail<Unit>::iteratorHoles ActiveTail<Unit>::beginHoles() const {
|
Chris@16
|
1327 return holesList_.begin();
|
Chris@16
|
1328 }
|
Chris@16
|
1329
|
Chris@16
|
1330 template <typename Unit>
|
Chris@16
|
1331 inline typename ActiveTail<Unit>::iteratorHoles ActiveTail<Unit>::endHoles() const {
|
Chris@16
|
1332 return holesList_.end();
|
Chris@16
|
1333 }
|
Chris@16
|
1334
|
Chris@16
|
1335 template <typename Unit>
|
Chris@16
|
1336 inline void ActiveTail<Unit>::writeOutFigureItrs(iterator& beginOut, iterator& endOut, bool isHole, orientation_2d orient) const {
|
Chris@16
|
1337 beginOut = begin(isHole, orient);
|
Chris@16
|
1338 endOut = end();
|
Chris@16
|
1339 }
|
Chris@16
|
1340
|
Chris@16
|
1341 template <typename Unit>
|
Chris@16
|
1342 inline void ActiveTail<Unit>::writeOutFigureHoleItrs(iteratorHoles& beginOut, iteratorHoles& endOut) const {
|
Chris@16
|
1343 beginOut = beginHoles();
|
Chris@16
|
1344 endOut = endHoles();
|
Chris@16
|
1345 }
|
Chris@16
|
1346
|
Chris@16
|
1347 template <typename Unit>
|
Chris@16
|
1348 inline void ActiveTail<Unit>::writeOutFigure(std::vector<Unit>& outVec, bool isHole) const {
|
Chris@16
|
1349 //we start writing out the polyLine that this active tail points to at its tail
|
Chris@16
|
1350 std::size_t size = outVec.size();
|
Chris@16
|
1351 outVec.push_back(0); //place holder for size
|
Chris@16
|
1352 PolyLine<Unit>* nextPolyLinep = 0;
|
Chris@16
|
1353 if(!isHole){
|
Chris@16
|
1354 nextPolyLinep = otherTailp_->tailp_->writeOut(outVec);
|
Chris@16
|
1355 } else {
|
Chris@16
|
1356 nextPolyLinep = tailp_->writeOut(outVec);
|
Chris@16
|
1357 }
|
Chris@16
|
1358 Unit firsty = outVec[size + 1];
|
Chris@16
|
1359 if((getOrient() == HORIZONTAL) ^ !isHole) {
|
Chris@16
|
1360 //our first coordinate is a y value, so we need to rotate it to the end
|
Chris@16
|
1361 typename std::vector<Unit>::iterator tmpItr = outVec.begin();
|
Chris@16
|
1362 tmpItr += size;
|
Chris@16
|
1363 outVec.erase(++tmpItr); //erase the 2nd element
|
Chris@16
|
1364 }
|
Chris@16
|
1365 End startEnd = tailp_->endConnectivity(HEAD);
|
Chris@16
|
1366 if(isHole) startEnd = otherTailp_->tailp_->endConnectivity(HEAD);
|
Chris@16
|
1367 while(nextPolyLinep) {
|
Chris@16
|
1368 bool nextStartEnd = nextPolyLinep->endConnectivity(!startEnd);
|
Chris@16
|
1369 nextPolyLinep = nextPolyLinep->writeOut(outVec, startEnd);
|
Chris@16
|
1370 startEnd = nextStartEnd;
|
Chris@16
|
1371 }
|
Chris@16
|
1372 if((getOrient() == HORIZONTAL) ^ !isHole) {
|
Chris@16
|
1373 //we want to push the y value onto the end since we ought to have ended with an x
|
Chris@16
|
1374 outVec.push_back(firsty); //should never be executed because we want first value to be an x
|
Chris@16
|
1375 }
|
Chris@16
|
1376 //the vector contains the coordinates of the linked list of PolyLines in the correct order
|
Chris@16
|
1377 //first element is supposed to be the size
|
Chris@16
|
1378 outVec[size] = outVec.size() - 1 - size; //number of coordinates in vector
|
Chris@16
|
1379 //assert outVec[size] % 2 == 0 //it should be even
|
Chris@16
|
1380 //make the size negative for holes
|
Chris@16
|
1381 outVec[size] *= (isHole ? -1 : 1);
|
Chris@16
|
1382 }
|
Chris@16
|
1383
|
Chris@16
|
1384 //no recursion to prevent max recursion depth errors
|
Chris@16
|
1385 template <typename Unit>
|
Chris@16
|
1386 inline PolyLine<Unit>* PolyLine<Unit>::writeOut(std::vector<Unit>& outVec, End startEnd) const {
|
Chris@16
|
1387 if(startEnd == HEAD){
|
Chris@16
|
1388 //forward order
|
Chris@16
|
1389 outVec.insert(outVec.end(), ptdata_.begin(), ptdata_.end());
|
Chris@16
|
1390 return tailp_;
|
Chris@16
|
1391 }else{
|
Chris@16
|
1392 //reverse order
|
Chris@16
|
1393 //do not reserve because we expect outVec to be large enough already
|
Chris@16
|
1394 for(int i = ptdata_.size() - 1; i >= 0; --i){
|
Chris@16
|
1395 outVec.push_back(ptdata_[i]);
|
Chris@16
|
1396 }
|
Chris@16
|
1397 //NT didn't know about this version of the API....
|
Chris@16
|
1398 //outVec.insert(outVec.end(), ptdata_.rbegin(), ptdata_.rend());
|
Chris@16
|
1399 return headp_;
|
Chris@16
|
1400 }
|
Chris@16
|
1401 }
|
Chris@16
|
1402
|
Chris@16
|
1403 //solid indicates if it was joined by a solit or a space
|
Chris@16
|
1404 template <typename Unit>
|
Chris@16
|
1405 inline ActiveTail<Unit>* ActiveTail<Unit>::joinChains(ActiveTail<Unit>* at1, ActiveTail<Unit>* at2, bool solid, std::vector<Unit>& outBufferTmp)
|
Chris@16
|
1406 {
|
Chris@16
|
1407 //checks to see if we closed a figure
|
Chris@16
|
1408 if(at1->isOtherTail(*at2)){
|
Chris@16
|
1409 //value of solid tells us if we closed solid or hole
|
Chris@16
|
1410 //and output the solid or handle the hole appropriately
|
Chris@16
|
1411 //if the hole needs to fracture across horizontal partition boundary we need to notify
|
Chris@16
|
1412 //the calling context to do so
|
Chris@16
|
1413 if(solid) {
|
Chris@16
|
1414 //the chains are being joined because there is solid to the right
|
Chris@16
|
1415 //this means that if the figure is closed at this point it must be a hole
|
Chris@16
|
1416 //because otherwise it would have to have another vertex to the right of this one
|
Chris@16
|
1417 //and would not be closed at this point
|
Chris@16
|
1418 return at1;
|
Chris@16
|
1419 } else {
|
Chris@16
|
1420 //assert pG != 0
|
Chris@16
|
1421 //the figure that was closed is a shell
|
Chris@16
|
1422 at1->writeOutFigure(outBufferTmp);
|
Chris@16
|
1423 //process holes of the polygon
|
Chris@16
|
1424 at1->copyHoles(*at2); //there should not be holes on at2, but if there are, copy them over
|
Chris@16
|
1425 const std::list<ActiveTail<Unit>*>& holes = at1->getHoles();
|
Chris@16
|
1426 for(typename std::list<ActiveTail<Unit>*>::const_iterator litr = holes.begin(); litr != holes.end(); ++litr) {
|
Chris@16
|
1427 (*litr)->writeOutFigure(outBufferTmp, true);
|
Chris@16
|
1428 //delete the hole
|
Chris@16
|
1429 (*litr)->destroyContents();
|
Chris@16
|
1430 destroyActiveTail((*litr)->getOtherActiveTail());
|
Chris@16
|
1431 destroyActiveTail((*litr));
|
Chris@16
|
1432 }
|
Chris@16
|
1433 //delete the polygon
|
Chris@16
|
1434 at1->destroyContents();
|
Chris@16
|
1435 //at2 contents are the same as at1, so it should not destroy them
|
Chris@16
|
1436 destroyActiveTail(at1);
|
Chris@16
|
1437 destroyActiveTail(at2);
|
Chris@16
|
1438 }
|
Chris@16
|
1439 return 0;
|
Chris@16
|
1440 }
|
Chris@16
|
1441 //join the two partial polygons into one large partial polygon
|
Chris@16
|
1442 at1->getTail()->joinTailToTail(*(at2->getTail()));
|
Chris@16
|
1443 *(at1->getOtherActiveTail()) = ActiveTail(at1->getOtherTail(), at2->getOtherActiveTail());
|
Chris@16
|
1444 *(at2->getOtherActiveTail()) = ActiveTail(at2->getOtherTail(), at1->getOtherActiveTail());
|
Chris@16
|
1445
|
Chris@16
|
1446 int accumulate = at2->getPolyLineSize() + at1->getPolyLineSize();
|
Chris@16
|
1447 (at1->getOtherActiveTail())->setPolyLineSize(accumulate);
|
Chris@16
|
1448 (at2->getOtherActiveTail())->setPolyLineSize(accumulate);
|
Chris@16
|
1449
|
Chris@16
|
1450 at1->getOtherActiveTail()->copyHoles(*at1);
|
Chris@16
|
1451 at1->getOtherActiveTail()->copyHoles(*at2);
|
Chris@16
|
1452 destroyActiveTail(at1);
|
Chris@16
|
1453 destroyActiveTail(at2);
|
Chris@16
|
1454 return 0;
|
Chris@16
|
1455 }
|
Chris@16
|
1456
|
Chris@16
|
1457 //solid indicates if it was joined by a solit or a space
|
Chris@16
|
1458 template <typename Unit>
|
Chris@16
|
1459 template <typename PolygonT>
|
Chris@16
|
1460 inline ActiveTail<Unit>* ActiveTail<Unit>::joinChains(ActiveTail<Unit>* at1, ActiveTail<Unit>* at2, bool solid,
|
Chris@16
|
1461 std::vector<PolygonT>& outBufferTmp) {
|
Chris@16
|
1462 //checks to see if we closed a figure
|
Chris@16
|
1463 if(at1->isOtherTail(*at2)){
|
Chris@16
|
1464 //value of solid tells us if we closed solid or hole
|
Chris@16
|
1465 //and output the solid or handle the hole appropriately
|
Chris@16
|
1466 //if the hole needs to fracture across horizontal partition boundary we need to notify
|
Chris@16
|
1467 //the calling context to do so
|
Chris@16
|
1468 if(solid) {
|
Chris@16
|
1469 //the chains are being joined because there is solid to the right
|
Chris@16
|
1470 //this means that if the figure is closed at this point it must be a hole
|
Chris@16
|
1471 //because otherwise it would have to have another vertex to the right of this one
|
Chris@16
|
1472 //and would not be closed at this point
|
Chris@16
|
1473 return at1;
|
Chris@16
|
1474 } else {
|
Chris@16
|
1475 //assert pG != 0
|
Chris@16
|
1476 //the figure that was closed is a shell
|
Chris@16
|
1477 outBufferTmp.push_back(at1);
|
Chris@16
|
1478 at1->copyHoles(*at2); //there should not be holes on at2, but if there are, copy them over
|
Chris@16
|
1479 }
|
Chris@16
|
1480 return 0;
|
Chris@16
|
1481 }
|
Chris@16
|
1482 //join the two partial polygons into one large partial polygon
|
Chris@16
|
1483 at1->getTail()->joinTailToTail(*(at2->getTail()));
|
Chris@16
|
1484 *(at1->getOtherActiveTail()) = ActiveTail<Unit>(at1->getOtherTail(), at2->getOtherActiveTail());
|
Chris@16
|
1485 *(at2->getOtherActiveTail()) = ActiveTail<Unit>(at2->getOtherTail(), at1->getOtherActiveTail());
|
Chris@16
|
1486
|
Chris@16
|
1487 int accumulate = at2->getPolyLineSize() + at1->getPolyLineSize();
|
Chris@16
|
1488 (at1->getOtherActiveTail())->setPolyLineSize(accumulate);
|
Chris@16
|
1489 (at2->getOtherActiveTail())->setPolyLineSize(accumulate);
|
Chris@16
|
1490
|
Chris@16
|
1491 at1->getOtherActiveTail()->copyHoles(*at1);
|
Chris@16
|
1492 at1->getOtherActiveTail()->copyHoles(*at2);
|
Chris@16
|
1493 destroyActiveTail(at1);
|
Chris@16
|
1494 destroyActiveTail(at2);
|
Chris@16
|
1495 return 0;
|
Chris@16
|
1496 }
|
Chris@16
|
1497
|
Chris@16
|
1498 template <class TKey, class T> inline typename std::map<TKey, T>::iterator findAtNext(std::map<TKey, T>& theMap,
|
Chris@16
|
1499 typename std::map<TKey, T>::iterator pos, const TKey& key)
|
Chris@16
|
1500 {
|
Chris@16
|
1501 if(pos == theMap.end()) return theMap.find(key);
|
Chris@16
|
1502 //if they match the mapItr is pointing to the correct position
|
Chris@16
|
1503 if(pos->first < key) {
|
Chris@16
|
1504 return theMap.find(key);
|
Chris@16
|
1505 }
|
Chris@16
|
1506 if(pos->first > key) {
|
Chris@16
|
1507 return theMap.end();
|
Chris@16
|
1508 }
|
Chris@16
|
1509 //else they are equal and no need to do anything to the iterator
|
Chris@16
|
1510 return pos;
|
Chris@16
|
1511 }
|
Chris@16
|
1512
|
Chris@16
|
1513 // createActiveTailsAsPair is called in these two end cases of geometry
|
Chris@16
|
1514 // 1. lower left concave corner
|
Chris@16
|
1515 // ###|
|
Chris@16
|
1516 // ###|
|
Chris@16
|
1517 // ###|###
|
Chris@16
|
1518 // ###|###
|
Chris@16
|
1519 // 2. lower left convex corner
|
Chris@16
|
1520 // |###
|
Chris@16
|
1521 // |###
|
Chris@16
|
1522 // |
|
Chris@16
|
1523 // |
|
Chris@16
|
1524 // In case 1 there may be a hole propigated up from the bottom. If the fracture option is enabled
|
Chris@16
|
1525 // the two active tails that form the filament fracture line edges can become the new active tail pair
|
Chris@16
|
1526 // by pushing x and y onto them. Otherwise the hole simply needs to be associated to one of the new active tails
|
Chris@16
|
1527 // with add hole
|
Chris@16
|
1528 template <typename Unit>
|
Chris@16
|
1529 inline std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> createActiveTailsAsPair(Unit x, Unit y, bool solid, ActiveTail<Unit>* phole, bool fractureHoles) {
|
Chris@16
|
1530 ActiveTail<Unit>* at1 = 0;
|
Chris@16
|
1531 ActiveTail<Unit>* at2 = 0;
|
Chris@16
|
1532 if(!phole || !fractureHoles){
|
Chris@16
|
1533 at1 = createActiveTail<Unit>();
|
Chris@16
|
1534 at2 = createActiveTail<Unit>();
|
Chris@16
|
1535 (*at1) = ActiveTail<Unit>(VERTICAL, x, solid, at2);
|
Chris@16
|
1536 (*at2) = ActiveTail<Unit>(HORIZONTAL, y, !solid, at1);
|
Chris@16
|
1537 //provide a function through activeTail class to provide this
|
Chris@16
|
1538 at1->getTail()->joinHeadToHead(*(at2->getTail()));
|
Chris@16
|
1539
|
Chris@16
|
1540 at1->addPolyLineSize(1);
|
Chris@16
|
1541 at2->addPolyLineSize(1);
|
Chris@16
|
1542
|
Chris@16
|
1543 if(phole)
|
Chris@16
|
1544 at1->addHole(phole, fractureHoles); //assert fractureHoles == false
|
Chris@16
|
1545 return std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*>(at1, at2);
|
Chris@16
|
1546 }
|
Chris@16
|
1547 //assert phole is not null
|
Chris@16
|
1548 //assert fractureHoles is true
|
Chris@16
|
1549 if(phole->getOrient() == VERTICAL) {
|
Chris@16
|
1550 at2 = phole;
|
Chris@16
|
1551 } else {
|
Chris@16
|
1552 at2 = phole->getOtherActiveTail(); //should never be executed since orientation is expected to be vertical
|
Chris@16
|
1553 }
|
Chris@16
|
1554 //assert solid == false, we should be creating a corner with solid below and to the left if there was a hole
|
Chris@16
|
1555 at1 = at2->getOtherActiveTail();
|
Chris@16
|
1556 //assert at1 is horizontal
|
Chris@16
|
1557 at1->pushCoordinate(x);
|
Chris@16
|
1558 //assert at2 is vertical
|
Chris@16
|
1559 at2->pushCoordinate(y);
|
Chris@16
|
1560
|
Chris@16
|
1561 return std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*>(at1, at2);
|
Chris@16
|
1562 }
|
Chris@16
|
1563
|
Chris@16
|
1564 /*
|
Chris@16
|
1565 * |
|
Chris@16
|
1566 * |
|
Chris@16
|
1567 * =
|
Chris@16
|
1568 * |########
|
Chris@16
|
1569 * |######## (add a new ActiveTail in the tailMap_).
|
Chris@16
|
1570 * |########
|
Chris@16
|
1571 * |########
|
Chris@16
|
1572 * |########
|
Chris@16
|
1573 * =
|
Chris@16
|
1574 * |
|
Chris@16
|
1575 * |
|
Chris@16
|
1576 *
|
Chris@16
|
1577 * NOTE: Call this only if you are sure that the $ledege$ is not in the tailMap_
|
Chris@16
|
1578 */
|
Chris@16
|
1579 template<bool orientT, typename Unit, typename polygon_concept_type>
|
Chris@16
|
1580 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
|
Chris@16
|
1581 insertNewLeftEdgeIntoTailMap(Unit currentX, Unit yBegin, Unit yEnd,
|
Chris@16
|
1582 typename std::map<Unit, ActiveTail<Unit> *>::iterator &hint){
|
Chris@16
|
1583 ActiveTail<Unit> *currentTail = NULL;
|
Chris@16
|
1584 std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair =
|
Chris@16
|
1585 createActiveTailsAsPair(currentX, yBegin, true, currentTail,
|
Chris@16
|
1586 fractureHoles_);
|
Chris@16
|
1587 currentTail = tailPair.first;
|
Chris@16
|
1588 if(!tailMap_.empty()){
|
Chris@16
|
1589 ++hint;
|
Chris@16
|
1590 }
|
Chris@16
|
1591 hint = tailMap_.insert(hint, std::make_pair(yBegin, tailPair.second));
|
Chris@16
|
1592 currentTail->pushCoordinate(yEnd); ++hint;
|
Chris@16
|
1593 hint = tailMap_.insert(hint, std::make_pair(yEnd, currentTail));
|
Chris@16
|
1594 }
|
Chris@16
|
1595
|
Chris@16
|
1596 template<bool orientT, typename Unit, typename polygon_concept_type>
|
Chris@16
|
1597 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
|
Chris@16
|
1598 closePartialSimplePolygon(Unit currentX, ActiveTail<Unit>*pfig,
|
Chris@16
|
1599 ActiveTail<Unit>*ppfig){
|
Chris@16
|
1600 pfig->pushCoordinate(currentX);
|
Chris@16
|
1601 ActiveTail<Unit>::joinChains(pfig, ppfig, false, outputPolygons_);
|
Chris@16
|
1602 }
|
Chris@16
|
1603 /*
|
Chris@16
|
1604 * If the invariant is maintained correctly then left edges can do the
|
Chris@16
|
1605 * following.
|
Chris@16
|
1606 *
|
Chris@16
|
1607 * =###
|
Chris@16
|
1608 * #######
|
Chris@16
|
1609 * #######
|
Chris@16
|
1610 * #######
|
Chris@16
|
1611 * #######
|
Chris@16
|
1612 * =###
|
Chris@16
|
1613 * |### (input left edge)
|
Chris@16
|
1614 * |###
|
Chris@16
|
1615 * =###
|
Chris@16
|
1616 * #######
|
Chris@16
|
1617 * #######
|
Chris@16
|
1618 * =###
|
Chris@16
|
1619 */
|
Chris@16
|
1620 template<bool orientT, typename Unit, typename polygon_concept_type>
|
Chris@16
|
1621 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
|
Chris@16
|
1622 updatePartialSimplePolygonsWithLeftEdges(Unit currentX,
|
Chris@16
|
1623 const std::vector<interval_data<Unit> > &leftEdges, size_t vertexThreshold){
|
Chris@16
|
1624 typename std::map<Unit, ActiveTail<Unit>* >::iterator succ, succ1;
|
Chris@16
|
1625 typename std::map<Unit, ActiveTail<Unit>* >::iterator pred, pred1, hint;
|
Chris@16
|
1626 Unit begin, end;
|
Chris@16
|
1627 ActiveTail<Unit> *pfig, *ppfig;
|
Chris@16
|
1628 std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair;
|
Chris@16
|
1629 size_t pfig_size = 0;
|
Chris@16
|
1630
|
Chris@16
|
1631 hint = tailMap_.begin();
|
Chris@16
|
1632 for(size_t i=0; i < leftEdges.size(); i++){
|
Chris@16
|
1633 begin = leftEdges[i].get(LOW); end = leftEdges[i].get(HIGH);
|
Chris@16
|
1634 succ = findAtNext(tailMap_, hint, begin);
|
Chris@16
|
1635 pred = findAtNext(tailMap_, hint, end);
|
Chris@16
|
1636
|
Chris@16
|
1637 if(succ != tailMap_.end() && pred != tailMap_.end()){ //CASE-1//
|
Chris@16
|
1638 //join the corresponding active tails//
|
Chris@16
|
1639 pfig = succ->second; ppfig = pred->second;
|
Chris@16
|
1640 pfig_size = pfig->getPolyLineSize() + ppfig->getPolyLineSize();
|
Chris@16
|
1641
|
Chris@16
|
1642 if(pfig_size >= vertexThreshold){
|
Chris@16
|
1643 size_t bsize = pfig->getPolyLineSize();
|
Chris@16
|
1644 size_t usize = ppfig->getPolyLineSize();
|
Chris@16
|
1645
|
Chris@16
|
1646 if(usize+2 < vertexThreshold){
|
Chris@16
|
1647 //cut-off the lower piece (succ1, succ) join (succ1, pred)//
|
Chris@16
|
1648 succ1 = succ; --succ1;
|
Chris@16
|
1649 assert((succ1 != tailMap_.end()) &&
|
Chris@16
|
1650 ((succ->second)->getOtherActiveTail() == succ1->second));
|
Chris@16
|
1651 closePartialSimplePolygon(currentX, succ1->second, succ->second);
|
Chris@16
|
1652 tailPair = createActiveTailsAsPair<Unit>(currentX, succ1->first,
|
Chris@16
|
1653 true, NULL, fractureHoles_);
|
Chris@16
|
1654
|
Chris@16
|
1655 //just update the succ1 with new ActiveTail<Unit>*//
|
Chris@16
|
1656 succ1->second = tailPair.second;
|
Chris@16
|
1657 ActiveTail<Unit>::joinChains(tailPair.first, pred->second, true,
|
Chris@16
|
1658 outputPolygons_);
|
Chris@16
|
1659 }else if(bsize+2 < vertexThreshold){
|
Chris@16
|
1660 //cut-off the upper piece () join ()//
|
Chris@16
|
1661 pred1 = pred; ++pred1;
|
Chris@16
|
1662 assert(pred1 != tailMap_.end() &&
|
Chris@16
|
1663 ((pred1->second)->getOtherActiveTail() == pred->second));
|
Chris@16
|
1664 closePartialSimplePolygon(currentX, pred->second, pred1->second);
|
Chris@16
|
1665
|
Chris@16
|
1666 //just update the pred1 with ActiveTail<Unit>* = pfig//
|
Chris@16
|
1667 pred1->second = pfig;
|
Chris@16
|
1668 pfig->pushCoordinate(currentX);
|
Chris@16
|
1669 pfig->pushCoordinate(pred1->first);
|
Chris@16
|
1670 }else{
|
Chris@16
|
1671 //cut both and create an left edge between (pred->first, succ1)//
|
Chris@16
|
1672 succ1 = succ; --succ1;
|
Chris@16
|
1673 pred1 = pred; ++pred1;
|
Chris@16
|
1674 assert(pred1 != tailMap_.end() && succ1 != tailMap_.end());
|
Chris@16
|
1675 assert((pred1->second)->getOtherActiveTail() == pred->second);
|
Chris@16
|
1676 assert((succ1->second)->getOtherActiveTail() == succ->second);
|
Chris@16
|
1677
|
Chris@16
|
1678 closePartialSimplePolygon(currentX, succ1->second, succ->second);
|
Chris@16
|
1679 closePartialSimplePolygon(currentX, pred->second, pred1->second);
|
Chris@16
|
1680
|
Chris@16
|
1681 tailPair = createActiveTailsAsPair<Unit>(currentX, succ1->first,
|
Chris@16
|
1682 true, NULL, fractureHoles_);
|
Chris@16
|
1683 succ1->second = tailPair.second;
|
Chris@16
|
1684 pred1->second = tailPair.first;
|
Chris@16
|
1685 (tailPair.first)->pushCoordinate(pred1->first);
|
Chris@16
|
1686 }
|
Chris@16
|
1687 }else{
|
Chris@16
|
1688 //just join them with closing//
|
Chris@16
|
1689 pfig->pushCoordinate(currentX);
|
Chris@16
|
1690 ActiveTail<Unit>::joinChains(pfig, ppfig, true, outputPolygons_);
|
Chris@16
|
1691 }
|
Chris@16
|
1692 hint = pred; ++hint;
|
Chris@16
|
1693 tailMap_.erase(succ); tailMap_.erase(pred);
|
Chris@16
|
1694 }else if(succ == tailMap_.end() && pred != tailMap_.end()){ //CASE-2//
|
Chris@16
|
1695 //succ is missing in the map, first insert it into the map//
|
Chris@16
|
1696 tailPair = createActiveTailsAsPair<Unit>(currentX, begin, true, NULL,
|
Chris@16
|
1697 fractureHoles_);
|
Chris@16
|
1698 hint = pred; ++hint;
|
Chris@16
|
1699 hint = tailMap_.insert(hint, std::make_pair(begin, tailPair.second));
|
Chris@16
|
1700
|
Chris@16
|
1701 pfig = pred->second;
|
Chris@16
|
1702 pfig_size = pfig->getPolyLineSize() + 2;
|
Chris@16
|
1703 if(pfig_size >= vertexThreshold){
|
Chris@16
|
1704 //cut-off piece from [pred, pred1] , add [begin, pred1]//
|
Chris@16
|
1705 pred1 = pred; ++pred1;
|
Chris@16
|
1706 assert((pred1 != tailMap_.end()) &&
|
Chris@16
|
1707 ((pred1->second)->getOtherActiveTail() == pred->second));
|
Chris@16
|
1708 closePartialSimplePolygon(currentX, pred->second, pred1->second);
|
Chris@16
|
1709
|
Chris@16
|
1710 //update: we need left edge between (begin, pred1->first)//
|
Chris@16
|
1711 pred1->second = tailPair.first;
|
Chris@16
|
1712 (tailPair.first)->pushCoordinate(pred1->first);
|
Chris@16
|
1713 }else{
|
Chris@16
|
1714 //just join//
|
Chris@16
|
1715 ActiveTail<Unit>::joinChains(tailPair.first, pfig,
|
Chris@16
|
1716 true, outputPolygons_);
|
Chris@16
|
1717 }
|
Chris@16
|
1718 tailMap_.erase(pred);
|
Chris@16
|
1719 }else if(succ != tailMap_.end() && pred == tailMap_.end()){ //CASE-3//
|
Chris@16
|
1720 //pred is missing in the map, first insert it into the map//
|
Chris@16
|
1721 hint = succ; ++hint;
|
Chris@16
|
1722 hint = tailMap_.insert(hint, std::make_pair(end, (ActiveTail<Unit> *) NULL));
|
Chris@16
|
1723 pfig = succ->second;
|
Chris@16
|
1724 pfig_size = pfig->getPolyLineSize() + 2;
|
Chris@16
|
1725 if(pfig_size >= vertexThreshold){
|
Chris@16
|
1726 //this figure needs cutting here//
|
Chris@16
|
1727 succ1 = succ; --succ1;
|
Chris@16
|
1728 assert((succ1 != tailMap_.end()) &&
|
Chris@16
|
1729 (succ1->second == pfig->getOtherActiveTail()));
|
Chris@16
|
1730 ppfig = succ1->second;
|
Chris@16
|
1731 closePartialSimplePolygon(currentX, ppfig, pfig);
|
Chris@16
|
1732
|
Chris@16
|
1733 //update: we need a left edge between (succ1->first, end)//
|
Chris@16
|
1734 tailPair = createActiveTailsAsPair<Unit>(currentX, succ1->first,
|
Chris@16
|
1735 true, NULL, fractureHoles_);
|
Chris@16
|
1736 succ1->second = tailPair.second;
|
Chris@16
|
1737 hint->second = tailPair.first;
|
Chris@16
|
1738 (tailPair.first)->pushCoordinate(end);
|
Chris@16
|
1739 }else{
|
Chris@16
|
1740 //no cutting needed//
|
Chris@16
|
1741 hint->second = pfig;
|
Chris@16
|
1742 pfig->pushCoordinate(currentX);
|
Chris@16
|
1743 pfig->pushCoordinate(end);
|
Chris@16
|
1744 }
|
Chris@16
|
1745 tailMap_.erase(succ);
|
Chris@16
|
1746 }else{
|
Chris@16
|
1747 //insert both pred and succ//
|
Chris@16
|
1748 insertNewLeftEdgeIntoTailMap(currentX, begin, end, hint);
|
Chris@16
|
1749 }
|
Chris@16
|
1750 }
|
Chris@16
|
1751 }
|
Chris@16
|
1752
|
Chris@16
|
1753 template<bool orientT, typename Unit, typename polygon_concept_type>
|
Chris@16
|
1754 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
|
Chris@16
|
1755 updatePartialSimplePolygonsWithRightEdges(Unit currentX,
|
Chris@16
|
1756 const std::vector<interval_data<Unit> > &rightEdges, size_t vertexThreshold)
|
Chris@16
|
1757 {
|
Chris@16
|
1758
|
Chris@16
|
1759 typename std::map<Unit, ActiveTail<Unit>* >::iterator succ, pred, hint;
|
Chris@16
|
1760 std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair;
|
Chris@16
|
1761 Unit begin, end;
|
Chris@16
|
1762 size_t i = 0;
|
Chris@16
|
1763 //If rightEdges is non-empty Then tailMap_ is non-empty //
|
Chris@16
|
1764 assert(rightEdges.empty() || !tailMap_.empty() );
|
Chris@16
|
1765
|
Chris@16
|
1766 while( i < rightEdges.size() ){
|
Chris@16
|
1767 //find the interval in the tailMap which contains this interval//
|
Chris@16
|
1768 pred = tailMap_.lower_bound(rightEdges[i].get(HIGH));
|
Chris@16
|
1769 assert(pred != tailMap_.end());
|
Chris@16
|
1770 succ = pred; --succ;
|
Chris@16
|
1771 assert(pred != succ);
|
Chris@16
|
1772 end = pred->first; begin = succ->first;
|
Chris@16
|
1773
|
Chris@16
|
1774 //we now have a [begin, end] //
|
Chris@16
|
1775 bool found_solid_opening = false;
|
Chris@16
|
1776 bool erase_succ = true, erase_pred = true;
|
Chris@16
|
1777 Unit solid_opening_begin = 0;
|
Chris@16
|
1778 Unit solid_opening_end = 0;
|
Chris@16
|
1779 size_t j = i+1;
|
Chris@16
|
1780 ActiveTail<Unit> *pfig = succ->second;
|
Chris@16
|
1781 ActiveTail<Unit> *ppfig = pred->second;
|
Chris@16
|
1782 size_t partial_fig_size = pfig->getPolyLineSize();
|
Chris@16
|
1783 //Invariant://
|
Chris@16
|
1784 assert(succ->second && (pfig)->getOtherActiveTail() == ppfig);
|
Chris@16
|
1785
|
Chris@16
|
1786 hint = succ;
|
Chris@16
|
1787 Unit key = rightEdges[i].get(LOW);
|
Chris@16
|
1788 if(begin != key){
|
Chris@16
|
1789 found_solid_opening = true;
|
Chris@16
|
1790 solid_opening_begin = begin; solid_opening_end = key;
|
Chris@16
|
1791 }
|
Chris@16
|
1792
|
Chris@16
|
1793 while(j < rightEdges.size() && rightEdges[j].get(HIGH) <= end){
|
Chris@16
|
1794 if(rightEdges[j-1].get(HIGH) != rightEdges[j].get(LOW)){
|
Chris@16
|
1795 if(!found_solid_opening){
|
Chris@16
|
1796 found_solid_opening = true;
|
Chris@16
|
1797 solid_opening_begin = rightEdges[j-1].get(HIGH);
|
Chris@16
|
1798 solid_opening_end = rightEdges[j].get(LOW);
|
Chris@16
|
1799 }else{
|
Chris@16
|
1800 ++hint;
|
Chris@16
|
1801 insertNewLeftEdgeIntoTailMap(currentX,
|
Chris@16
|
1802 rightEdges[j-1].get(HIGH), rightEdges[j].get(LOW), hint);
|
Chris@16
|
1803 }
|
Chris@16
|
1804 }
|
Chris@16
|
1805 j++;
|
Chris@16
|
1806 }
|
Chris@16
|
1807
|
Chris@16
|
1808 //trailing edge//
|
Chris@16
|
1809 if(end != rightEdges[j-1].get(HIGH)){
|
Chris@16
|
1810 if(!found_solid_opening){
|
Chris@16
|
1811 found_solid_opening = true;
|
Chris@16
|
1812 solid_opening_begin = rightEdges[j-1].get(HIGH); solid_opening_end = end;
|
Chris@16
|
1813 }else{
|
Chris@16
|
1814 // a solid opening has been found already, we need to insert a new left
|
Chris@16
|
1815 // between [rightEdges[j-1].get(HIGH), end]
|
Chris@16
|
1816 Unit lbegin = rightEdges[j-1].get(HIGH);
|
Chris@16
|
1817 tailPair = createActiveTailsAsPair<Unit>(currentX, lbegin, true, NULL,
|
Chris@16
|
1818 fractureHoles_);
|
Chris@16
|
1819 hint = tailMap_.insert(pred, std::make_pair(lbegin, tailPair.second));
|
Chris@16
|
1820 pred->second = tailPair.first;
|
Chris@16
|
1821 (tailPair.first)->pushCoordinate(end);
|
Chris@16
|
1822 erase_pred = false;
|
Chris@16
|
1823 }
|
Chris@16
|
1824 }
|
Chris@16
|
1825
|
Chris@16
|
1826 size_t vertex_delta = ((begin != solid_opening_begin) &&
|
Chris@16
|
1827 (end != solid_opening_end)) ? 4 : 2;
|
Chris@16
|
1828
|
Chris@16
|
1829 if(!found_solid_opening){
|
Chris@16
|
1830 //just close the figure, TODO: call closePartialPolygon//
|
Chris@16
|
1831 pfig->pushCoordinate(currentX);
|
Chris@16
|
1832 ActiveTail<Unit>::joinChains(pfig, ppfig, false, outputPolygons_);
|
Chris@16
|
1833 hint = pred; ++hint;
|
Chris@16
|
1834 }else if(partial_fig_size+vertex_delta >= vertexThreshold){
|
Chris@16
|
1835 //close the figure and add a pseudo left-edge//
|
Chris@16
|
1836 closePartialSimplePolygon(currentX, pfig, ppfig);
|
Chris@16
|
1837 assert(begin != solid_opening_begin || end != solid_opening_end);
|
Chris@16
|
1838
|
Chris@16
|
1839 if(begin != solid_opening_begin && end != solid_opening_end){
|
Chris@16
|
1840 insertNewLeftEdgeIntoTailMap(currentX, solid_opening_begin,
|
Chris@16
|
1841 solid_opening_end, hint);
|
Chris@16
|
1842 }else if(begin == solid_opening_begin){
|
Chris@16
|
1843 //we just need to update the succ in the tailMap_//
|
Chris@16
|
1844 tailPair = createActiveTailsAsPair<Unit>(currentX, solid_opening_begin,
|
Chris@16
|
1845 true, NULL, fractureHoles_);
|
Chris@16
|
1846 succ->second = tailPair.second;
|
Chris@16
|
1847 hint = succ; ++hint;
|
Chris@16
|
1848 hint = tailMap_.insert(pred, std::make_pair(solid_opening_end,
|
Chris@16
|
1849 tailPair.first));
|
Chris@16
|
1850 (tailPair.first)->pushCoordinate(solid_opening_end);
|
Chris@16
|
1851 erase_succ = false;
|
Chris@16
|
1852 }else{
|
Chris@16
|
1853 //we just need to update the pred in the tailMap_//
|
Chris@16
|
1854 tailPair = createActiveTailsAsPair<Unit>(currentX, solid_opening_begin,
|
Chris@16
|
1855 true, NULL, fractureHoles_);
|
Chris@16
|
1856 hint = tailMap_.insert(pred, std::make_pair(solid_opening_begin,
|
Chris@16
|
1857 tailPair.second));
|
Chris@16
|
1858 pred->second = tailPair.first;
|
Chris@16
|
1859 (tailPair.first)->pushCoordinate(solid_opening_end);
|
Chris@16
|
1860 erase_pred = false;
|
Chris@16
|
1861 }
|
Chris@16
|
1862 }else{
|
Chris@16
|
1863 //continue the figure (by adding at-most two new vertices)//
|
Chris@16
|
1864 if(begin != solid_opening_begin){
|
Chris@16
|
1865 pfig->pushCoordinate(currentX);
|
Chris@16
|
1866 pfig->pushCoordinate(solid_opening_begin);
|
Chris@16
|
1867 //insert solid_opening_begin//
|
Chris@16
|
1868 hint = succ; ++hint;
|
Chris@16
|
1869 hint = tailMap_.insert(hint, std::make_pair(solid_opening_begin, pfig));
|
Chris@16
|
1870 }else{
|
Chris@16
|
1871 erase_succ = false;
|
Chris@16
|
1872 }
|
Chris@16
|
1873
|
Chris@16
|
1874 if(end != solid_opening_end){
|
Chris@16
|
1875 std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair =
|
Chris@16
|
1876 createActiveTailsAsPair<Unit>(currentX, solid_opening_end, false,
|
Chris@16
|
1877 NULL, fractureHoles_);
|
Chris@16
|
1878 hint = pred; ++hint;
|
Chris@16
|
1879 hint = tailMap_.insert(hint, std::make_pair(solid_opening_end,
|
Chris@16
|
1880 tailPair.second));
|
Chris@16
|
1881 ActiveTail<Unit>::joinChains(tailPair.first, ppfig, false,
|
Chris@16
|
1882 outputPolygons_);
|
Chris@16
|
1883 }else{
|
Chris@16
|
1884 erase_pred = false;
|
Chris@16
|
1885 }
|
Chris@16
|
1886 }
|
Chris@16
|
1887
|
Chris@16
|
1888 //Remove the pred and succ if necessary//
|
Chris@16
|
1889 if(erase_succ){
|
Chris@16
|
1890 tailMap_.erase(succ);
|
Chris@16
|
1891 }
|
Chris@16
|
1892 if(erase_pred){
|
Chris@16
|
1893 tailMap_.erase(pred);
|
Chris@16
|
1894 }
|
Chris@16
|
1895 i = j;
|
Chris@16
|
1896 }
|
Chris@16
|
1897 }
|
Chris@16
|
1898
|
Chris@16
|
1899 // Maintains the following invariant:
|
Chris@16
|
1900 // a. All the partial polygons formed at any state can be closed
|
Chris@16
|
1901 // by a single edge.
|
Chris@16
|
1902 template<bool orientT, typename Unit, typename polygon_concept_type>
|
Chris@16
|
1903 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
|
Chris@16
|
1904 maintainPartialSimplePolygonInvariant(iterator& beginOutput,
|
Chris@16
|
1905 iterator& endOutput, Unit currentX, const std::vector<interval_data<Unit> >& l,
|
Chris@16
|
1906 const std::vector<interval_data<Unit> >& r, size_t vertexThreshold) {
|
Chris@16
|
1907
|
Chris@16
|
1908 clearOutput_();
|
Chris@16
|
1909 if(!l.empty()){
|
Chris@16
|
1910 updatePartialSimplePolygonsWithLeftEdges(currentX, l, vertexThreshold);
|
Chris@16
|
1911 }
|
Chris@16
|
1912
|
Chris@16
|
1913 if(!r.empty()){
|
Chris@16
|
1914 updatePartialSimplePolygonsWithRightEdges(currentX, r, vertexThreshold);
|
Chris@16
|
1915 }
|
Chris@16
|
1916 beginOutput = outputPolygons_.begin();
|
Chris@16
|
1917 endOutput = outputPolygons_.end();
|
Chris@16
|
1918
|
Chris@16
|
1919 }
|
Chris@16
|
1920
|
Chris@16
|
1921 //Process edges connects vertical input edges (right or left edges of figures) to horizontal edges stored as member
|
Chris@16
|
1922 //data of the scanline object. It also creates now horizontal edges as needed to construct figures from edge data.
|
Chris@16
|
1923 //
|
Chris@16
|
1924 //There are only 12 geometric end cases where the scanline intersects a horizontal edge and even fewer unique
|
Chris@16
|
1925 //actions to take:
|
Chris@16
|
1926 // 1. Solid on both sides of the vertical partition after the current position and space on both sides before
|
Chris@16
|
1927 // ###|###
|
Chris@16
|
1928 // ###|###
|
Chris@16
|
1929 // |
|
Chris@16
|
1930 // |
|
Chris@16
|
1931 // This case does not need to be handled because there is no vertical edge at the current x coordinate.
|
Chris@16
|
1932 //
|
Chris@16
|
1933 // 2. Solid on both sides of the vertical partition before the current position and space on both sides after
|
Chris@16
|
1934 // |
|
Chris@16
|
1935 // |
|
Chris@16
|
1936 // ###|###
|
Chris@16
|
1937 // ###|###
|
Chris@16
|
1938 // This case does not need to be handled because there is no vertical edge at the current x coordinate.
|
Chris@16
|
1939 //
|
Chris@16
|
1940 // 3. Solid on the left of the vertical partition after the current position and space elsewhere
|
Chris@16
|
1941 // ###|
|
Chris@16
|
1942 // ###|
|
Chris@16
|
1943 // |
|
Chris@16
|
1944 // |
|
Chris@16
|
1945 // The horizontal edge from the left is found and turns upward because of the vertical right edge to become
|
Chris@16
|
1946 // the currently active vertical edge.
|
Chris@16
|
1947 //
|
Chris@16
|
1948 // 4. Solid on the left of the vertical partion before the current position and space elsewhere
|
Chris@16
|
1949 // |
|
Chris@16
|
1950 // |
|
Chris@16
|
1951 // ###|
|
Chris@16
|
1952 // ###|
|
Chris@16
|
1953 // The horizontal edge from the left is found and joined to the currently active vertical edge.
|
Chris@16
|
1954 //
|
Chris@16
|
1955 // 5. Solid to the right above and below and solid to the left above current position.
|
Chris@16
|
1956 // ###|###
|
Chris@16
|
1957 // ###|###
|
Chris@16
|
1958 // |###
|
Chris@16
|
1959 // |###
|
Chris@16
|
1960 // The horizontal edge from the left is found and joined to the currently active vertical edge,
|
Chris@16
|
1961 // potentially closing a hole.
|
Chris@16
|
1962 //
|
Chris@16
|
1963 // 6. Solid on the left of the vertical partion before the current position and solid to the right above and below
|
Chris@16
|
1964 // |###
|
Chris@16
|
1965 // |###
|
Chris@16
|
1966 // ###|###
|
Chris@16
|
1967 // ###|###
|
Chris@16
|
1968 // The horizontal edge from the left is found and turns upward because of the vertical right edge to become
|
Chris@16
|
1969 // the currently active vertical edge.
|
Chris@16
|
1970 //
|
Chris@16
|
1971 // 7. Solid on the right of the vertical partition after the current position and space elsewhere
|
Chris@16
|
1972 // |###
|
Chris@16
|
1973 // |###
|
Chris@16
|
1974 // |
|
Chris@16
|
1975 // |
|
Chris@16
|
1976 // Create two new ActiveTails, one is added to the horizontal edges and the other becomes the vertical currentTail
|
Chris@16
|
1977 //
|
Chris@16
|
1978 // 8. Solid on the right of the vertical partion before the current position and space elsewhere
|
Chris@16
|
1979 // |
|
Chris@16
|
1980 // |
|
Chris@16
|
1981 // |###
|
Chris@16
|
1982 // |###
|
Chris@16
|
1983 // The currentTail vertical edge turns right and is added to the horizontal edges data
|
Chris@16
|
1984 //
|
Chris@16
|
1985 // 9. Solid to the right above and solid to the left above and below current position.
|
Chris@16
|
1986 // ###|###
|
Chris@16
|
1987 // ###|###
|
Chris@16
|
1988 // ###|
|
Chris@16
|
1989 // ###|
|
Chris@16
|
1990 // The currentTail vertical edge turns right and is added to the horizontal edges data
|
Chris@16
|
1991 //
|
Chris@16
|
1992 // 10. Solid on the left of the vertical partion above and below the current position and solid to the right below
|
Chris@16
|
1993 // ###|
|
Chris@16
|
1994 // ###|
|
Chris@16
|
1995 // ###|###
|
Chris@16
|
1996 // ###|###
|
Chris@16
|
1997 // Create two new ActiveTails, one is added to the horizontal edges data and the other becomes the vertical currentTail
|
Chris@16
|
1998 //
|
Chris@16
|
1999 // 11. Solid to the right above and solid to the left below current position.
|
Chris@16
|
2000 // |###
|
Chris@16
|
2001 // |###
|
Chris@16
|
2002 // ###|
|
Chris@16
|
2003 // ###|
|
Chris@16
|
2004 // The currentTail vertical edge joins the horizontal edge from the left (may close a polygon)
|
Chris@16
|
2005 // Create two new ActiveTails, one is added to the horizontal edges data and the other becomes the vertical currentTail
|
Chris@16
|
2006 //
|
Chris@16
|
2007 // 12. Solid on the left of the vertical partion above the current position and solid to the right below
|
Chris@16
|
2008 // ###|
|
Chris@16
|
2009 // ###|
|
Chris@16
|
2010 // |###
|
Chris@16
|
2011 // |###
|
Chris@16
|
2012 // The currentTail vertical edge turns right and is added to the horizontal edges data.
|
Chris@16
|
2013 // The horizontal edge from the left turns upward and becomes the currentTail vertical edge
|
Chris@16
|
2014 //
|
Chris@16
|
2015 template <bool orientT, typename Unit, typename polygon_concept_type>
|
Chris@16
|
2016 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::
|
Chris@16
|
2017 processEdges(iterator& beginOutput, iterator& endOutput,
|
Chris@16
|
2018 Unit currentX, std::vector<interval_data<Unit> >& leftEdges,
|
Chris@16
|
2019 std::vector<interval_data<Unit> >& rightEdges,
|
Chris@16
|
2020 size_t vertexThreshold) {
|
Chris@16
|
2021 clearOutput_();
|
Chris@16
|
2022 typename std::map<Unit, ActiveTail<Unit>*>::iterator nextMapItr;
|
Chris@16
|
2023 //foreach edge
|
Chris@16
|
2024 unsigned int leftIndex = 0;
|
Chris@16
|
2025 unsigned int rightIndex = 0;
|
Chris@16
|
2026 bool bottomAlreadyProcessed = false;
|
Chris@16
|
2027 ActiveTail<Unit>* currentTail = 0;
|
Chris@16
|
2028 const Unit UnitMax = (std::numeric_limits<Unit>::max)();
|
Chris@16
|
2029
|
Chris@16
|
2030 if(vertexThreshold < (std::numeric_limits<size_t>::max)()){
|
Chris@16
|
2031 maintainPartialSimplePolygonInvariant(beginOutput, endOutput, currentX,
|
Chris@16
|
2032 leftEdges, rightEdges, vertexThreshold);
|
Chris@16
|
2033 return;
|
Chris@16
|
2034 }
|
Chris@16
|
2035
|
Chris@16
|
2036 nextMapItr = tailMap_.begin();
|
Chris@16
|
2037 while(leftIndex < leftEdges.size() || rightIndex < rightEdges.size()) {
|
Chris@16
|
2038 interval_data<Unit> edges[2] = {interval_data<Unit> (UnitMax, UnitMax),
|
Chris@16
|
2039 interval_data<Unit> (UnitMax, UnitMax)};
|
Chris@16
|
2040 bool haveNextEdge = true;
|
Chris@16
|
2041 if(leftIndex < leftEdges.size())
|
Chris@16
|
2042 edges[0] = leftEdges[leftIndex];
|
Chris@16
|
2043 else
|
Chris@16
|
2044 haveNextEdge = false;
|
Chris@16
|
2045 if(rightIndex < rightEdges.size())
|
Chris@16
|
2046 edges[1] = rightEdges[rightIndex];
|
Chris@16
|
2047 else
|
Chris@16
|
2048 haveNextEdge = false;
|
Chris@16
|
2049 bool trailingEdge = edges[1].get(LOW) < edges[0].get(LOW);
|
Chris@16
|
2050 interval_data<Unit> & edge = edges[trailingEdge];
|
Chris@16
|
2051 interval_data<Unit> & nextEdge = edges[!trailingEdge];
|
Chris@16
|
2052 //process this edge
|
Chris@16
|
2053 if(!bottomAlreadyProcessed) {
|
Chris@16
|
2054 //assert currentTail = 0
|
Chris@16
|
2055
|
Chris@16
|
2056 //process the bottom end of this edge
|
Chris@16
|
2057 typename std::map<Unit, ActiveTail<Unit>*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(LOW));
|
Chris@16
|
2058 if(thisMapItr != tailMap_.end()) {
|
Chris@16
|
2059 //there is an edge in the map at the low end of this edge
|
Chris@16
|
2060 //it needs to turn upward and become the current tail
|
Chris@16
|
2061 ActiveTail<Unit>* tail = thisMapItr->second;
|
Chris@16
|
2062 if(currentTail) {
|
Chris@16
|
2063 //stitch currentTail into this tail
|
Chris@16
|
2064 currentTail = tail->addHole(currentTail, fractureHoles_);
|
Chris@16
|
2065 if(!fractureHoles_)
|
Chris@16
|
2066 currentTail->pushCoordinate(currentX);
|
Chris@16
|
2067 } else {
|
Chris@16
|
2068 currentTail = tail;
|
Chris@16
|
2069 currentTail->pushCoordinate(currentX);
|
Chris@16
|
2070 }
|
Chris@16
|
2071 //assert currentTail->getOrient() == VERTICAL
|
Chris@16
|
2072 nextMapItr = thisMapItr; //set nextMapItr to the next position after this one
|
Chris@16
|
2073 ++nextMapItr;
|
Chris@16
|
2074 //remove thisMapItr from the map
|
Chris@16
|
2075 tailMap_.erase(thisMapItr);
|
Chris@16
|
2076 } else {
|
Chris@16
|
2077 //there is no edge in the map at the low end of this edge
|
Chris@16
|
2078 //we need to create one and another one to be the current vertical tail
|
Chris@16
|
2079 //if this is a trailing edge then there is space to the right of the vertical edge
|
Chris@16
|
2080 //so pass the inverse of trailingEdge to indicate solid to the right
|
Chris@16
|
2081 std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair =
|
Chris@16
|
2082 createActiveTailsAsPair(currentX, edge.get(LOW), !trailingEdge, currentTail, fractureHoles_);
|
Chris@16
|
2083 currentTail = tailPair.first;
|
Chris@16
|
2084 tailMap_.insert(nextMapItr, std::pair<Unit, ActiveTail<Unit>*>(edge.get(LOW), tailPair.second));
|
Chris@16
|
2085 // leave nextMapItr unchanged
|
Chris@16
|
2086 }
|
Chris@16
|
2087
|
Chris@16
|
2088 }
|
Chris@16
|
2089 if(haveNextEdge && edge.get(HIGH) == nextEdge.get(LOW)) {
|
Chris@16
|
2090 //the top of this edge is equal to the bottom of the next edge, process them both
|
Chris@16
|
2091 bottomAlreadyProcessed = true;
|
Chris@16
|
2092 typename std::map<Unit, ActiveTail<Unit>*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(HIGH));
|
Chris@16
|
2093 if(thisMapItr == tailMap_.end()) //assert this should never happen
|
Chris@16
|
2094 return;
|
Chris@16
|
2095 if(trailingEdge) {
|
Chris@16
|
2096 //geometry at this position
|
Chris@16
|
2097 // |##
|
Chris@16
|
2098 // |##
|
Chris@16
|
2099 // -----
|
Chris@16
|
2100 // ##|
|
Chris@16
|
2101 // ##|
|
Chris@16
|
2102 //current tail should join thisMapItr tail
|
Chris@16
|
2103 ActiveTail<Unit>* tail = thisMapItr->second;
|
Chris@16
|
2104 //pass false because they are being joined because space is to the right and it will close a solid figure
|
Chris@16
|
2105 ActiveTail<Unit>::joinChains(currentTail, tail, false, outputPolygons_);
|
Chris@16
|
2106 //two new tails are created, the vertical becomes current tail, the horizontal becomes thisMapItr tail
|
Chris@16
|
2107 //pass true becuase they are created at the lower left corner of some solid
|
Chris@16
|
2108 //pass null because there is no hole pointer possible
|
Chris@16
|
2109 std::pair<ActiveTail<Unit>*, ActiveTail<Unit>*> tailPair =
|
Chris@16
|
2110 createActiveTailsAsPair<Unit>(currentX, edge.get(HIGH), true, 0, fractureHoles_);
|
Chris@16
|
2111 currentTail = tailPair.first;
|
Chris@16
|
2112 thisMapItr->second = tailPair.second;
|
Chris@16
|
2113 } else {
|
Chris@16
|
2114 //geometry at this position
|
Chris@16
|
2115 // ##|
|
Chris@16
|
2116 // ##|
|
Chris@16
|
2117 // -----
|
Chris@16
|
2118 // |##
|
Chris@16
|
2119 // |##
|
Chris@16
|
2120 //current tail should turn right
|
Chris@16
|
2121 currentTail->pushCoordinate(edge.get(HIGH));
|
Chris@16
|
2122 //thisMapItr tail should turn up
|
Chris@16
|
2123 thisMapItr->second->pushCoordinate(currentX);
|
Chris@16
|
2124 //thisMapItr tail becomes current tail and current tail becomes thisMapItr tail
|
Chris@16
|
2125 std::swap(currentTail, thisMapItr->second);
|
Chris@16
|
2126 }
|
Chris@16
|
2127 nextMapItr = thisMapItr; //set nextMapItr to the next position after this one
|
Chris@16
|
2128 ++nextMapItr;
|
Chris@16
|
2129 } else {
|
Chris@16
|
2130 //there is a gap between the top of this edge and the bottom of the next, process the top of this edge
|
Chris@16
|
2131 bottomAlreadyProcessed = false;
|
Chris@16
|
2132 //process the top of this edge
|
Chris@16
|
2133 typename std::map<Unit, ActiveTail<Unit>*>::iterator thisMapItr = findAtNext(tailMap_, nextMapItr, edge.get(HIGH));
|
Chris@16
|
2134 if(thisMapItr != tailMap_.end()) {
|
Chris@16
|
2135 //thisMapItr is pointing to a horizontal edge in the map at the top of this vertical edge
|
Chris@16
|
2136 //we need to join them and potentially close a figure
|
Chris@16
|
2137 //assert currentTail != 0
|
Chris@16
|
2138 ActiveTail<Unit>* tail = thisMapItr->second;
|
Chris@16
|
2139 //pass the opositve of trailing edge to mean that they are joined because of solid to the right
|
Chris@16
|
2140 currentTail = ActiveTail<Unit>::joinChains(currentTail, tail, !trailingEdge, outputPolygons_);
|
Chris@16
|
2141 nextMapItr = thisMapItr; //set nextMapItr to the next position after this one
|
Chris@16
|
2142 ++nextMapItr;
|
Chris@16
|
2143 if(currentTail) { //figure is not closed//
|
Chris@16
|
2144 Unit nextItrY = UnitMax;
|
Chris@16
|
2145 if(nextMapItr != tailMap_.end()) {
|
Chris@16
|
2146 nextItrY = nextMapItr->first;
|
Chris@16
|
2147 }
|
Chris@16
|
2148 //for it to be a hole this must have been a left edge
|
Chris@16
|
2149 Unit leftY = UnitMax;
|
Chris@16
|
2150 if(leftIndex + 1 < leftEdges.size())
|
Chris@16
|
2151 leftY = leftEdges[leftIndex+1].get(LOW);
|
Chris@16
|
2152 Unit rightY = nextEdge.get(LOW);
|
Chris@16
|
2153 if(!haveNextEdge || (nextItrY < leftY && nextItrY < rightY)) {
|
Chris@16
|
2154 //we need to add it to the next edge above it in the map
|
Chris@16
|
2155 tail = nextMapItr->second;
|
Chris@16
|
2156 tail = tail->addHole(currentTail, fractureHoles_);
|
Chris@16
|
2157 if(fractureHoles_) {
|
Chris@16
|
2158 //some small additional work stitching in the filament
|
Chris@16
|
2159 tail->pushCoordinate(nextItrY);
|
Chris@16
|
2160 nextMapItr->second = tail;
|
Chris@16
|
2161 }
|
Chris@16
|
2162 //set current tail to null
|
Chris@16
|
2163 currentTail = 0;
|
Chris@16
|
2164 }
|
Chris@16
|
2165 }
|
Chris@16
|
2166 //delete thisMapItr from the map
|
Chris@16
|
2167 tailMap_.erase(thisMapItr);
|
Chris@16
|
2168 } else {
|
Chris@16
|
2169 //currentTail must turn right and be added into the map
|
Chris@16
|
2170 currentTail->pushCoordinate(edge.get(HIGH));
|
Chris@16
|
2171 //assert currentTail->getOrient() == HORIZONTAL
|
Chris@16
|
2172 tailMap_.insert(nextMapItr, std::pair<Unit, ActiveTail<Unit>*>(edge.get(HIGH), currentTail));
|
Chris@16
|
2173 //set currentTail to null
|
Chris@16
|
2174 currentTail = 0;
|
Chris@16
|
2175 //leave nextMapItr unchanged, it is still next
|
Chris@16
|
2176 }
|
Chris@16
|
2177 }
|
Chris@16
|
2178
|
Chris@16
|
2179 //increment index
|
Chris@16
|
2180 leftIndex += !trailingEdge;
|
Chris@16
|
2181 rightIndex += trailingEdge;
|
Chris@16
|
2182 } //end while
|
Chris@16
|
2183 beginOutput = outputPolygons_.begin();
|
Chris@16
|
2184 endOutput = outputPolygons_.end();
|
Chris@16
|
2185 } //end function
|
Chris@16
|
2186
|
Chris@16
|
2187 template<bool orientT, typename Unit, typename polygon_concept_type>
|
Chris@16
|
2188 inline void ScanLineToPolygonItrs<orientT, Unit, polygon_concept_type>::clearOutput_() {
|
Chris@16
|
2189 for(std::size_t i = 0; i < outputPolygons_.size(); ++i) {
|
Chris@16
|
2190 ActiveTail<Unit>* at1 = outputPolygons_[i].yield();
|
Chris@16
|
2191 const std::list<ActiveTail<Unit>*>& holes = at1->getHoles();
|
Chris@16
|
2192 for(typename std::list<ActiveTail<Unit>*>::const_iterator litr = holes.begin(); litr != holes.end(); ++litr) {
|
Chris@16
|
2193 //delete the hole
|
Chris@16
|
2194 (*litr)->destroyContents();
|
Chris@16
|
2195 destroyActiveTail((*litr)->getOtherActiveTail());
|
Chris@16
|
2196 destroyActiveTail((*litr));
|
Chris@16
|
2197 }
|
Chris@16
|
2198 //delete the polygon
|
Chris@16
|
2199 at1->destroyContents();
|
Chris@16
|
2200 //at2 contents are the same as at1, so it should not destroy them
|
Chris@16
|
2201 destroyActiveTail((at1)->getOtherActiveTail());
|
Chris@16
|
2202 destroyActiveTail(at1);
|
Chris@16
|
2203 }
|
Chris@16
|
2204 outputPolygons_.clear();
|
Chris@16
|
2205 }
|
Chris@16
|
2206
|
Chris@16
|
2207 } //polygon_formation namespace
|
Chris@16
|
2208
|
Chris@16
|
2209 template <bool orientT, typename Unit>
|
Chris@16
|
2210 struct geometry_concept<polygon_formation::PolyLinePolygonWithHolesData<orientT, Unit> > {
|
Chris@16
|
2211 typedef polygon_90_with_holes_concept type;
|
Chris@16
|
2212 };
|
Chris@16
|
2213
|
Chris@16
|
2214 template <bool orientT, typename Unit>
|
Chris@16
|
2215 struct geometry_concept<polygon_formation::PolyLineHoleData<orientT, Unit> > {
|
Chris@16
|
2216 typedef polygon_90_concept type;
|
Chris@16
|
2217 };
|
Chris@16
|
2218
|
Chris@16
|
2219 //public API to access polygon formation algorithm
|
Chris@16
|
2220 template <typename output_container, typename iterator_type, typename concept_type>
|
Chris@16
|
2221 unsigned int get_polygons(output_container& container,
|
Chris@16
|
2222 iterator_type begin, iterator_type end, orientation_2d orient,
|
Chris@16
|
2223 bool fracture_holes, concept_type,
|
Chris@16
|
2224 size_t sliceThreshold = (std::numeric_limits<size_t>::max)() ) {
|
Chris@16
|
2225 typedef typename output_container::value_type polygon_type;
|
Chris@16
|
2226 typedef typename std::iterator_traits<iterator_type>::value_type::first_type coordinate_type;
|
Chris@16
|
2227 polygon_type poly;
|
Chris@16
|
2228 unsigned int countPolygons = 0;
|
Chris@16
|
2229 typedef typename geometry_concept<polygon_type>::type polygon_concept_type;
|
Chris@16
|
2230 polygon_formation::ScanLineToPolygonItrs<true, coordinate_type, polygon_concept_type> scanlineToPolygonItrsV(fracture_holes);
|
Chris@16
|
2231 polygon_formation::ScanLineToPolygonItrs<false, coordinate_type, polygon_concept_type> scanlineToPolygonItrsH(fracture_holes);
|
Chris@16
|
2232 std::vector<interval_data<coordinate_type> > leftEdges;
|
Chris@16
|
2233 std::vector<interval_data<coordinate_type> > rightEdges;
|
Chris@16
|
2234 coordinate_type prevPos = (std::numeric_limits<coordinate_type>::max)();
|
Chris@16
|
2235 coordinate_type prevY = (std::numeric_limits<coordinate_type>::max)();
|
Chris@16
|
2236 int count = 0;
|
Chris@16
|
2237 for(iterator_type itr = begin;
|
Chris@16
|
2238 itr != end; ++ itr) {
|
Chris@16
|
2239 coordinate_type pos = (*itr).first;
|
Chris@16
|
2240 if(pos != prevPos) {
|
Chris@16
|
2241 if(orient == VERTICAL) {
|
Chris@16
|
2242 typename polygon_formation::ScanLineToPolygonItrs<true, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd;
|
Chris@16
|
2243 scanlineToPolygonItrsV.processEdges(itrPoly, itrPolyEnd, prevPos,
|
Chris@16
|
2244 leftEdges, rightEdges, sliceThreshold);
|
Chris@16
|
2245 for( ; itrPoly != itrPolyEnd; ++ itrPoly) {
|
Chris@16
|
2246 ++countPolygons;
|
Chris@16
|
2247 assign(poly, *itrPoly);
|
Chris@16
|
2248 container.insert(container.end(), poly);
|
Chris@16
|
2249 }
|
Chris@16
|
2250 } else {
|
Chris@16
|
2251 typename polygon_formation::ScanLineToPolygonItrs<false, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd;
|
Chris@16
|
2252 scanlineToPolygonItrsH.processEdges(itrPoly, itrPolyEnd, prevPos,
|
Chris@16
|
2253 leftEdges, rightEdges, sliceThreshold);
|
Chris@16
|
2254 for( ; itrPoly != itrPolyEnd; ++ itrPoly) {
|
Chris@16
|
2255 ++countPolygons;
|
Chris@16
|
2256 assign(poly, *itrPoly);
|
Chris@16
|
2257 container.insert(container.end(), poly);
|
Chris@16
|
2258 }
|
Chris@16
|
2259 }
|
Chris@16
|
2260 leftEdges.clear();
|
Chris@16
|
2261 rightEdges.clear();
|
Chris@16
|
2262 prevPos = pos;
|
Chris@16
|
2263 prevY = (*itr).second.first;
|
Chris@16
|
2264 count = (*itr).second.second;
|
Chris@16
|
2265 continue;
|
Chris@16
|
2266 }
|
Chris@16
|
2267 coordinate_type y = (*itr).second.first;
|
Chris@16
|
2268 if(count != 0 && y != prevY) {
|
Chris@16
|
2269 std::pair<interval_data<coordinate_type>, int> element(interval_data<coordinate_type>(prevY, y), count);
|
Chris@16
|
2270 if(element.second == 1) {
|
Chris@16
|
2271 if(leftEdges.size() && leftEdges.back().high() == element.first.low()) {
|
Chris@16
|
2272 encompass(leftEdges.back(), element.first);
|
Chris@16
|
2273 } else {
|
Chris@16
|
2274 leftEdges.push_back(element.first);
|
Chris@16
|
2275 }
|
Chris@16
|
2276 } else {
|
Chris@16
|
2277 if(rightEdges.size() && rightEdges.back().high() == element.first.low()) {
|
Chris@16
|
2278 encompass(rightEdges.back(), element.first);
|
Chris@16
|
2279 } else {
|
Chris@16
|
2280 rightEdges.push_back(element.first);
|
Chris@16
|
2281 }
|
Chris@16
|
2282 }
|
Chris@16
|
2283
|
Chris@16
|
2284 }
|
Chris@16
|
2285 prevY = y;
|
Chris@16
|
2286 count += (*itr).second.second;
|
Chris@16
|
2287 }
|
Chris@16
|
2288 if(orient == VERTICAL) {
|
Chris@16
|
2289 typename polygon_formation::ScanLineToPolygonItrs<true, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd;
|
Chris@16
|
2290 scanlineToPolygonItrsV.processEdges(itrPoly, itrPolyEnd, prevPos, leftEdges, rightEdges, sliceThreshold);
|
Chris@16
|
2291 for( ; itrPoly != itrPolyEnd; ++ itrPoly) {
|
Chris@16
|
2292 ++countPolygons;
|
Chris@16
|
2293 assign(poly, *itrPoly);
|
Chris@16
|
2294 container.insert(container.end(), poly);
|
Chris@16
|
2295 }
|
Chris@16
|
2296 } else {
|
Chris@16
|
2297 typename polygon_formation::ScanLineToPolygonItrs<false, coordinate_type, polygon_concept_type>::iterator itrPoly, itrPolyEnd;
|
Chris@16
|
2298 scanlineToPolygonItrsH.processEdges(itrPoly, itrPolyEnd, prevPos, leftEdges, rightEdges, sliceThreshold);
|
Chris@16
|
2299
|
Chris@16
|
2300 for( ; itrPoly != itrPolyEnd; ++ itrPoly) {
|
Chris@16
|
2301 ++countPolygons;
|
Chris@16
|
2302 assign(poly, *itrPoly);
|
Chris@16
|
2303 container.insert(container.end(), poly);
|
Chris@16
|
2304 }
|
Chris@16
|
2305 }
|
Chris@16
|
2306 return countPolygons;
|
Chris@16
|
2307 }
|
Chris@16
|
2308
|
Chris@16
|
2309 }
|
Chris@16
|
2310 }
|
Chris@16
|
2311 #endif
|