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 #ifndef BOOST_POLYGON_BOOLEAN_OP_45_HPP
|
Chris@16
|
9 #define BOOST_POLYGON_BOOLEAN_OP_45_HPP
|
Chris@16
|
10 namespace boost { namespace polygon{
|
Chris@16
|
11
|
Chris@16
|
12 template <typename Unit>
|
Chris@16
|
13 struct boolean_op_45 {
|
Chris@16
|
14 typedef point_data<Unit> Point;
|
Chris@16
|
15 typedef typename coordinate_traits<Unit>::manhattan_area_type LongUnit;
|
Chris@16
|
16
|
Chris@16
|
17 class Count2 {
|
Chris@16
|
18 public:
|
Chris@16
|
19 inline Count2()
|
Chris@16
|
20 #ifndef BOOST_POLYGON_MSVC
|
Chris@16
|
21 : counts()
|
Chris@16
|
22 #endif
|
Chris@16
|
23 { counts[0] = counts[1] = 0; }
|
Chris@16
|
24 //inline Count2(int count) { counts[0] = counts[1] = count; }
|
Chris@16
|
25 inline Count2(int count1, int count2)
|
Chris@16
|
26 #ifndef BOOST_POLYGON_MSVC
|
Chris@16
|
27 : counts()
|
Chris@16
|
28 #endif
|
Chris@16
|
29 { counts[0] = count1; counts[1] = count2; }
|
Chris@16
|
30 inline Count2(const Count2& count)
|
Chris@16
|
31 #ifndef BOOST_POLYGON_MSVC
|
Chris@16
|
32 : counts()
|
Chris@16
|
33 #endif
|
Chris@16
|
34 { counts[0] = count.counts[0]; counts[1] = count.counts[1]; }
|
Chris@16
|
35 inline bool operator==(const Count2& count) const { return counts[0] == count.counts[0] && counts[1] == count.counts[1]; }
|
Chris@16
|
36 inline bool operator!=(const Count2& count) const { return !((*this) == count); }
|
Chris@16
|
37 inline Count2& operator=(int count) { counts[0] = counts[1] = count; return *this; }
|
Chris@16
|
38 inline Count2& operator=(const Count2& count) { counts[0] = count.counts[0]; counts[1] = count.counts[1]; return *this; }
|
Chris@16
|
39 inline int& operator[](bool index) { return counts[index]; }
|
Chris@16
|
40 inline int operator[](bool index) const {return counts[index]; }
|
Chris@16
|
41 inline Count2& operator+=(const Count2& count){
|
Chris@16
|
42 counts[0] += count[0];
|
Chris@16
|
43 counts[1] += count[1];
|
Chris@16
|
44 return *this;
|
Chris@16
|
45 }
|
Chris@16
|
46 inline Count2& operator-=(const Count2& count){
|
Chris@16
|
47 counts[0] -= count[0];
|
Chris@16
|
48 counts[1] -= count[1];
|
Chris@16
|
49 return *this;
|
Chris@16
|
50 }
|
Chris@16
|
51 inline Count2 operator+(const Count2& count) const {
|
Chris@16
|
52 return Count2(*this)+=count;
|
Chris@16
|
53 }
|
Chris@16
|
54 inline Count2 operator-(const Count2& count) const {
|
Chris@16
|
55 return Count2(*this)-=count;
|
Chris@16
|
56 }
|
Chris@16
|
57 inline Count2 invert() const {
|
Chris@16
|
58 return Count2(-counts[0], -counts[1]);
|
Chris@16
|
59 }
|
Chris@16
|
60 private:
|
Chris@16
|
61 int counts[2];
|
Chris@16
|
62 };
|
Chris@16
|
63
|
Chris@16
|
64 class Count1 {
|
Chris@16
|
65 public:
|
Chris@16
|
66 inline Count1() : count_(0) { }
|
Chris@16
|
67 inline Count1(int count) : count_(count) { }
|
Chris@16
|
68 inline Count1(const Count1& count) : count_(count.count_) { }
|
Chris@16
|
69 inline bool operator==(const Count1& count) const { return count_ == count.count_; }
|
Chris@16
|
70 inline bool operator!=(const Count1& count) const { return !((*this) == count); }
|
Chris@16
|
71 inline Count1& operator=(int count) { count_ = count; return *this; }
|
Chris@16
|
72 inline Count1& operator=(const Count1& count) { count_ = count.count_; return *this; }
|
Chris@16
|
73 inline Count1& operator+=(const Count1& count){
|
Chris@16
|
74 count_ += count.count_;
|
Chris@16
|
75 return *this;
|
Chris@16
|
76 }
|
Chris@16
|
77 inline Count1& operator-=(const Count1& count){
|
Chris@16
|
78 count_ -= count.count_;
|
Chris@16
|
79 return *this;
|
Chris@16
|
80 }
|
Chris@16
|
81 inline Count1 operator+(const Count1& count) const {
|
Chris@16
|
82 return Count1(*this)+=count;
|
Chris@16
|
83 }
|
Chris@16
|
84 inline Count1 operator-(const Count1& count) const {
|
Chris@16
|
85 return Count1(*this)-=count;
|
Chris@16
|
86 }
|
Chris@16
|
87 inline Count1 invert() const {
|
Chris@16
|
88 return Count1(-count_);
|
Chris@16
|
89 }
|
Chris@16
|
90 int count_;
|
Chris@16
|
91 };
|
Chris@16
|
92
|
Chris@16
|
93 // inline std::ostream& operator<< (std::ostream& o, const Count2& c) {
|
Chris@16
|
94 // o << c[0] << " " << c[1];
|
Chris@16
|
95 // return o;
|
Chris@16
|
96 // }
|
Chris@16
|
97
|
Chris@16
|
98 template <typename CountType>
|
Chris@16
|
99 class Scan45ElementT {
|
Chris@16
|
100 public:
|
Chris@16
|
101 Unit x;
|
Chris@16
|
102 Unit y;
|
Chris@16
|
103 int rise; //-1, 0, +1
|
Chris@16
|
104 mutable CountType count;
|
Chris@16
|
105 inline Scan45ElementT() : x(), y(), rise(), count() {}
|
Chris@16
|
106 inline Scan45ElementT(Unit xIn, Unit yIn, int riseIn, CountType countIn = CountType()) :
|
Chris@16
|
107 x(xIn), y(yIn), rise(riseIn), count(countIn) {}
|
Chris@16
|
108 inline Scan45ElementT(const Scan45ElementT& that) :
|
Chris@16
|
109 x(that.x), y(that.y), rise(that.rise), count(that.count) {}
|
Chris@16
|
110 inline Scan45ElementT& operator=(const Scan45ElementT& that) {
|
Chris@16
|
111 x = that.x; y = that.y; rise = that.rise; count = that.count;
|
Chris@16
|
112 return *this;
|
Chris@16
|
113 }
|
Chris@16
|
114 inline Unit evalAtX(Unit xIn) const {
|
Chris@16
|
115 return y + rise * (xIn - x);
|
Chris@16
|
116 }
|
Chris@16
|
117
|
Chris@16
|
118 inline bool cross(Point& crossPoint, const Scan45ElementT& edge, Unit currentX) const {
|
Chris@16
|
119 Unit y1 = evalAtX(currentX);
|
Chris@16
|
120 Unit y2 = edge.evalAtX(currentX);
|
Chris@16
|
121 int rise1 = rise;
|
Chris@16
|
122 int rise2 = edge.rise;
|
Chris@16
|
123 if(rise > edge.rise){
|
Chris@16
|
124 if(y1 > y2) return false;
|
Chris@16
|
125 } else if(rise < edge.rise){
|
Chris@16
|
126 if(y2 > y1) return false;
|
Chris@16
|
127 std::swap(y1, y2);
|
Chris@16
|
128 std::swap(rise1, rise2);
|
Chris@16
|
129 } else { return false; }
|
Chris@16
|
130 if(rise1 == 1) {
|
Chris@16
|
131 if(rise2 == 0) {
|
Chris@16
|
132 crossPoint = Point(currentX + y2 - y1, y2);
|
Chris@16
|
133 } else {
|
Chris@16
|
134 //rise2 == -1
|
Chris@16
|
135 Unit delta = (y2 - y1)/2;
|
Chris@16
|
136 crossPoint = Point(currentX + delta, y1 + delta);
|
Chris@16
|
137 }
|
Chris@16
|
138 } else {
|
Chris@16
|
139 //rise1 == 0 and rise2 == -1
|
Chris@16
|
140 crossPoint = Point(currentX + y2 - y1, y1);
|
Chris@16
|
141 }
|
Chris@16
|
142 return true;
|
Chris@16
|
143 }
|
Chris@16
|
144 };
|
Chris@16
|
145
|
Chris@16
|
146 typedef Scan45ElementT<Count2> Scan45Element;
|
Chris@16
|
147
|
Chris@16
|
148 // inline std::ostream& operator<< (std::ostream& o, const Scan45Element& c) {
|
Chris@16
|
149 // o << c.x << " " << c.y << " " << c.rise << " " << c.count;
|
Chris@16
|
150 // return o;
|
Chris@16
|
151 // }
|
Chris@16
|
152
|
Chris@16
|
153 class lessScan45ElementRise : public std::binary_function<Scan45Element, Scan45Element, bool> {
|
Chris@16
|
154 public:
|
Chris@16
|
155 inline lessScan45ElementRise() {} //default constructor is only constructor
|
Chris@16
|
156 inline bool operator () (Scan45Element elm1, Scan45Element elm2) const {
|
Chris@16
|
157 return elm1.rise < elm2.rise;
|
Chris@16
|
158 }
|
Chris@16
|
159 };
|
Chris@16
|
160
|
Chris@16
|
161 template <typename CountType>
|
Chris@16
|
162 class lessScan45Element {
|
Chris@16
|
163 private:
|
Chris@16
|
164 Unit *x_; //x value at which to apply comparison
|
Chris@16
|
165 int *justBefore_;
|
Chris@16
|
166 public:
|
Chris@16
|
167 inline lessScan45Element() : x_(0), justBefore_(0) {}
|
Chris@16
|
168 inline lessScan45Element(Unit *x, int *justBefore) : x_(x), justBefore_(justBefore) {}
|
Chris@16
|
169 inline lessScan45Element(const lessScan45Element& that) : x_(that.x_), justBefore_(that.justBefore_) {}
|
Chris@16
|
170 inline lessScan45Element& operator=(const lessScan45Element& that) { x_ = that.x_; justBefore_ = that.justBefore_; return *this; }
|
Chris@16
|
171 inline bool operator () (const Scan45ElementT<CountType>& elm1,
|
Chris@16
|
172 const Scan45ElementT<CountType>& elm2) const {
|
Chris@16
|
173 Unit y1 = elm1.evalAtX(*x_);
|
Chris@16
|
174 Unit y2 = elm2.evalAtX(*x_);
|
Chris@16
|
175 if(y1 < y2) return true;
|
Chris@16
|
176 if(y1 == y2) {
|
Chris@16
|
177 //if justBefore is true we invert the result of the comparison of slopes
|
Chris@16
|
178 if(*justBefore_) {
|
Chris@16
|
179 return elm1.rise > elm2.rise;
|
Chris@16
|
180 } else {
|
Chris@16
|
181 return elm1.rise < elm2.rise;
|
Chris@16
|
182 }
|
Chris@16
|
183 }
|
Chris@16
|
184 return false;
|
Chris@16
|
185 }
|
Chris@16
|
186 };
|
Chris@16
|
187
|
Chris@16
|
188 template <typename CountType>
|
Chris@16
|
189 class Scan45CountT {
|
Chris@16
|
190 public:
|
Chris@16
|
191 inline Scan45CountT() : counts() {} //counts[0] = counts[1] = counts[2] = counts[3] = 0; }
|
Chris@16
|
192 inline Scan45CountT(CountType count) : counts() { counts[0] = counts[1] = counts[2] = counts[3] = count; }
|
Chris@16
|
193 inline Scan45CountT(const CountType& count1, const CountType& count2, const CountType& count3,
|
Chris@16
|
194 const CountType& count4) : counts() {
|
Chris@16
|
195 counts[0] = count1;
|
Chris@16
|
196 counts[1] = count2;
|
Chris@16
|
197 counts[2] = count3;
|
Chris@16
|
198 counts[3] = count4;
|
Chris@16
|
199 }
|
Chris@16
|
200 inline Scan45CountT(const Scan45CountT& count) : counts() {
|
Chris@16
|
201 (*this) = count;
|
Chris@16
|
202 }
|
Chris@16
|
203 inline bool operator==(const Scan45CountT& count) const {
|
Chris@16
|
204 for(unsigned int i = 0; i < 4; ++i) {
|
Chris@16
|
205 if(counts[i] != count.counts[i]) return false;
|
Chris@16
|
206 }
|
Chris@16
|
207 return true;
|
Chris@16
|
208 }
|
Chris@16
|
209 inline bool operator!=(const Scan45CountT& count) const { return !((*this) == count); }
|
Chris@16
|
210 inline Scan45CountT& operator=(CountType count) {
|
Chris@16
|
211 counts[0] = counts[1] = counts[2] = counts[3] = count; return *this; }
|
Chris@16
|
212 inline Scan45CountT& operator=(const Scan45CountT& count) {
|
Chris@16
|
213 for(unsigned int i = 0; i < 4; ++i) {
|
Chris@16
|
214 counts[i] = count.counts[i];
|
Chris@16
|
215 }
|
Chris@16
|
216 return *this;
|
Chris@16
|
217 }
|
Chris@16
|
218 inline CountType& operator[](int index) { return counts[index]; }
|
Chris@16
|
219 inline CountType operator[](int index) const {return counts[index]; }
|
Chris@16
|
220 inline Scan45CountT& operator+=(const Scan45CountT& count){
|
Chris@16
|
221 for(unsigned int i = 0; i < 4; ++i) {
|
Chris@16
|
222 counts[i] += count.counts[i];
|
Chris@16
|
223 }
|
Chris@16
|
224 return *this;
|
Chris@16
|
225 }
|
Chris@16
|
226 inline Scan45CountT& operator-=(const Scan45CountT& count){
|
Chris@16
|
227 for(unsigned int i = 0; i < 4; ++i) {
|
Chris@16
|
228 counts[i] -= count.counts[i];
|
Chris@16
|
229 }
|
Chris@16
|
230 return *this;
|
Chris@16
|
231 }
|
Chris@16
|
232 inline Scan45CountT operator+(const Scan45CountT& count) const {
|
Chris@16
|
233 return Scan45CountT(*this)+=count;
|
Chris@16
|
234 }
|
Chris@16
|
235 inline Scan45CountT operator-(const Scan45CountT& count) const {
|
Chris@16
|
236 return Scan45CountT(*this)-=count;
|
Chris@16
|
237 }
|
Chris@16
|
238 inline Scan45CountT invert() const {
|
Chris@16
|
239 return Scan45CountT(CountType())-=(*this);
|
Chris@16
|
240 }
|
Chris@16
|
241 inline Scan45CountT& operator+=(const Scan45ElementT<CountType>& element){
|
Chris@16
|
242 counts[element.rise+1] += element.count; return *this;
|
Chris@16
|
243 }
|
Chris@16
|
244 private:
|
Chris@16
|
245 CountType counts[4];
|
Chris@16
|
246 };
|
Chris@16
|
247
|
Chris@16
|
248 typedef Scan45CountT<Count2> Scan45Count;
|
Chris@16
|
249
|
Chris@16
|
250 // inline std::ostream& operator<< (std::ostream& o, const Scan45Count& c) {
|
Chris@16
|
251 // o << c[0] << ", " << c[1] << ", ";
|
Chris@16
|
252 // o << c[2] << ", " << c[3];
|
Chris@16
|
253 // return o;
|
Chris@16
|
254 // }
|
Chris@16
|
255
|
Chris@16
|
256
|
Chris@16
|
257 // inline std::ostream& operator<< (std::ostream& o, const Scan45Vertex& c) {
|
Chris@16
|
258 // o << c.first << ": " << c.second;
|
Chris@16
|
259 // return o;
|
Chris@16
|
260 // }
|
Chris@16
|
261
|
Chris@16
|
262
|
Chris@16
|
263 //vetex45 is sortable
|
Chris@16
|
264 template <typename ct>
|
Chris@16
|
265 class Vertex45T {
|
Chris@16
|
266 public:
|
Chris@16
|
267 Point pt;
|
Chris@16
|
268 int rise; // 1, 0 or -1
|
Chris@16
|
269 ct count; //dxdydTheta
|
Chris@16
|
270 inline Vertex45T() : pt(), rise(), count() {}
|
Chris@16
|
271 inline Vertex45T(const Point& point, int riseIn, ct countIn) : pt(point), rise(riseIn), count(countIn) {}
|
Chris@16
|
272 inline Vertex45T(const Vertex45T& vertex) : pt(vertex.pt), rise(vertex.rise), count(vertex.count) {}
|
Chris@16
|
273 inline Vertex45T& operator=(const Vertex45T& vertex){
|
Chris@16
|
274 pt = vertex.pt; rise = vertex.rise; count = vertex.count; return *this; }
|
Chris@16
|
275 inline Vertex45T(const std::pair<Point, Point>& vertex) : pt(), rise(), count() {}
|
Chris@16
|
276 inline Vertex45T& operator=(const std::pair<Point, Point>& vertex){ return *this; }
|
Chris@16
|
277 inline bool operator==(const Vertex45T& vertex) const {
|
Chris@16
|
278 return pt == vertex.pt && rise == vertex.rise && count == vertex.count; }
|
Chris@16
|
279 inline bool operator!=(const Vertex45T& vertex) const { return !((*this) == vertex); }
|
Chris@16
|
280 inline bool operator==(const std::pair<Point, Point>& vertex) const { return false; }
|
Chris@16
|
281 inline bool operator!=(const std::pair<Point, Point>& vertex) const { return !((*this) == vertex); }
|
Chris@16
|
282 inline bool operator<(const Vertex45T& vertex) const {
|
Chris@16
|
283 if(pt.x() < vertex.pt.x()) return true;
|
Chris@16
|
284 if(pt.x() == vertex.pt.x()) {
|
Chris@16
|
285 if(pt.y() < vertex.pt.y()) return true;
|
Chris@16
|
286 if(pt.y() == vertex.pt.y()) { return rise < vertex.rise; }
|
Chris@16
|
287 }
|
Chris@16
|
288 return false;
|
Chris@16
|
289 }
|
Chris@16
|
290 inline bool operator>(const Vertex45T& vertex) const { return vertex < (*this); }
|
Chris@16
|
291 inline bool operator<=(const Vertex45T& vertex) const { return !((*this) > vertex); }
|
Chris@16
|
292 inline bool operator>=(const Vertex45T& vertex) const { return !((*this) < vertex); }
|
Chris@16
|
293 inline Unit evalAtX(Unit xIn) const { return pt.y() + rise * (xIn - pt.x()); }
|
Chris@16
|
294 };
|
Chris@16
|
295
|
Chris@16
|
296 typedef Vertex45T<int> Vertex45;
|
Chris@16
|
297
|
Chris@16
|
298 // inline std::ostream& operator<< (std::ostream& o, const Vertex45& c) {
|
Chris@16
|
299 // o << c.pt << " " << c.rise << " " << c.count;
|
Chris@16
|
300 // return o;
|
Chris@16
|
301 // }
|
Chris@16
|
302
|
Chris@16
|
303 //when scanning Vertex45 for polygon formation we need a scanline comparator functor
|
Chris@16
|
304 class lessVertex45 {
|
Chris@16
|
305 private:
|
Chris@16
|
306 Unit *x_; //x value at which to apply comparison
|
Chris@16
|
307 int *justBefore_;
|
Chris@16
|
308 public:
|
Chris@16
|
309 inline lessVertex45() : x_(0), justBefore_() {}
|
Chris@16
|
310
|
Chris@16
|
311 inline lessVertex45(Unit *x, int *justBefore) : x_(x), justBefore_(justBefore) {}
|
Chris@16
|
312
|
Chris@16
|
313 inline lessVertex45(const lessVertex45& that) : x_(that.x_), justBefore_(that.justBefore_) {}
|
Chris@16
|
314
|
Chris@16
|
315 inline lessVertex45& operator=(const lessVertex45& that) { x_ = that.x_; justBefore_ = that.justBefore_; return *this; }
|
Chris@16
|
316
|
Chris@16
|
317 template <typename ct>
|
Chris@16
|
318 inline bool operator () (const Vertex45T<ct>& elm1, const Vertex45T<ct>& elm2) const {
|
Chris@16
|
319 Unit y1 = elm1.evalAtX(*x_);
|
Chris@16
|
320 Unit y2 = elm2.evalAtX(*x_);
|
Chris@16
|
321 if(y1 < y2) return true;
|
Chris@16
|
322 if(y1 == y2) {
|
Chris@16
|
323 //if justBefore is true we invert the result of the comparison of slopes
|
Chris@16
|
324 if(*justBefore_) {
|
Chris@16
|
325 return elm1.rise > elm2.rise;
|
Chris@16
|
326 } else {
|
Chris@16
|
327 return elm1.rise < elm2.rise;
|
Chris@16
|
328 }
|
Chris@16
|
329 }
|
Chris@16
|
330 return false;
|
Chris@16
|
331 }
|
Chris@16
|
332 };
|
Chris@16
|
333
|
Chris@16
|
334 // 0 right to left
|
Chris@16
|
335 // 1 upper right to lower left
|
Chris@16
|
336 // 2 high to low
|
Chris@16
|
337 // 3 upper left to lower right
|
Chris@16
|
338 // 4 left to right
|
Chris@16
|
339 // 5 lower left to upper right
|
Chris@16
|
340 // 6 low to high
|
Chris@16
|
341 // 7 lower right to upper left
|
Chris@16
|
342 static inline int classifyEdge45(const Point& prevPt, const Point& nextPt) {
|
Chris@16
|
343 if(prevPt.x() == nextPt.x()) {
|
Chris@16
|
344 //2 or 6
|
Chris@16
|
345 return predicated_value(prevPt.y() < nextPt.y(), 6, 2);
|
Chris@16
|
346 }
|
Chris@16
|
347 if(prevPt.y() == nextPt.y()) {
|
Chris@16
|
348 //0 or 4
|
Chris@16
|
349 return predicated_value(prevPt.x() < nextPt.x(), 4, 0);
|
Chris@16
|
350 }
|
Chris@16
|
351 if(prevPt.x() < nextPt.x()) {
|
Chris@16
|
352 //3 or 5
|
Chris@16
|
353 return predicated_value(prevPt.y() < nextPt.y(), 5, 3);
|
Chris@16
|
354 }
|
Chris@16
|
355 //prevPt.x() > nextPt.y()
|
Chris@16
|
356 //1 or 7
|
Chris@16
|
357 return predicated_value(prevPt.y() < nextPt.y(), 7, 1);
|
Chris@16
|
358 }
|
Chris@16
|
359
|
Chris@16
|
360 template <int op, typename CountType>
|
Chris@16
|
361 static int applyLogic(CountType count1, CountType count2){
|
Chris@16
|
362 bool l1 = applyLogic<op>(count1);
|
Chris@16
|
363 bool l2 = applyLogic<op>(count2);
|
Chris@16
|
364 if(l1 && !l2)
|
Chris@16
|
365 return -1; //was true before and became false like a trailing edge
|
Chris@16
|
366 if(!l1 && l2)
|
Chris@16
|
367 return 1; //was false before and became true like a leading edge
|
Chris@16
|
368 return 0; //no change in logic between the two counts
|
Chris@16
|
369 }
|
Chris@16
|
370 template <int op>
|
Chris@16
|
371 static bool applyLogic(Count2 count) {
|
Chris@16
|
372 #ifdef BOOST_POLYGON_MSVC
|
Chris@16
|
373 #pragma warning (push)
|
Chris@16
|
374 #pragma warning (disable: 4127)
|
Chris@16
|
375 #endif
|
Chris@16
|
376 if(op == 0) { //apply or
|
Chris@16
|
377 return count[0] > 0 || count[1] > 0;
|
Chris@16
|
378 } else if(op == 1) { //apply and
|
Chris@16
|
379 return count[0] > 0 && count[1] > 0;
|
Chris@16
|
380 } else if(op == 2) { //apply not
|
Chris@16
|
381 return count[0] > 0 && !(count[1] > 0);
|
Chris@16
|
382 } else if(op == 3) { //apply xor
|
Chris@16
|
383 return (count[0] > 0) ^ (count[1] > 0);
|
Chris@16
|
384 } else
|
Chris@16
|
385 return false;
|
Chris@16
|
386 #ifdef BOOST_POLYGON_MSVC
|
Chris@16
|
387 #pragma warning (pop)
|
Chris@16
|
388 #endif
|
Chris@16
|
389 }
|
Chris@16
|
390
|
Chris@16
|
391 template <int op>
|
Chris@16
|
392 struct boolean_op_45_output_functor {
|
Chris@16
|
393 template <typename cT>
|
Chris@16
|
394 void operator()(cT& output, const Count2& count1, const Count2& count2,
|
Chris@16
|
395 const Point& pt, int rise, direction_1d end) {
|
Chris@16
|
396 int edgeType = applyLogic<op>(count1, count2);
|
Chris@16
|
397 if(edgeType) {
|
Chris@16
|
398 int multiplier = end == LOW ? -1 : 1;
|
Chris@16
|
399 //std::cout << "cross logic: " << edgeType << "\n";
|
Chris@16
|
400 output.insert(output.end(), Vertex45(pt, rise, edgeType * multiplier));
|
Chris@16
|
401 //std::cout << "write out: " << crossPoint << " " << Point(eraseItrs[i]->x, eraseItrs[i]->y) << "\n";
|
Chris@16
|
402 }
|
Chris@16
|
403 }
|
Chris@16
|
404 };
|
Chris@16
|
405
|
Chris@16
|
406 template <int op>
|
Chris@16
|
407 static bool applyLogic(Count1 count) {
|
Chris@16
|
408 #ifdef BOOST_POLYGON_MSVC
|
Chris@16
|
409 #pragma warning (push)
|
Chris@16
|
410 #pragma warning (disable: 4127)
|
Chris@16
|
411 #endif
|
Chris@16
|
412 if(op == 0) { //apply or
|
Chris@16
|
413 return count.count_ > 0;
|
Chris@16
|
414 } else if(op == 1) { //apply and
|
Chris@16
|
415 return count.count_ > 1;
|
Chris@16
|
416 } else if(op == 3) { //apply xor
|
Chris@16
|
417 return (count.count_ % 2) != 0;
|
Chris@16
|
418 } else
|
Chris@16
|
419 return false;
|
Chris@16
|
420 #ifdef BOOST_POLYGON_MSVC
|
Chris@16
|
421 #pragma warning (pop)
|
Chris@16
|
422 #endif
|
Chris@16
|
423 }
|
Chris@16
|
424
|
Chris@16
|
425 template <int op>
|
Chris@16
|
426 struct unary_op_45_output_functor {
|
Chris@16
|
427 template <typename cT>
|
Chris@16
|
428 void operator()(cT& output, const Count1& count1, const Count1& count2,
|
Chris@16
|
429 const Point& pt, int rise, direction_1d end) {
|
Chris@16
|
430 int edgeType = applyLogic<op>(count1, count2);
|
Chris@16
|
431 if(edgeType) {
|
Chris@16
|
432 int multiplier = end == LOW ? -1 : 1;
|
Chris@16
|
433 //std::cout << "cross logic: " << edgeType << "\n";
|
Chris@16
|
434 output.insert(output.end(), Vertex45(pt, rise, edgeType * multiplier));
|
Chris@16
|
435 //std::cout << "write out: " << crossPoint << " " << Point(eraseItrs[i]->x, eraseItrs[i]->y) << "\n";
|
Chris@16
|
436 }
|
Chris@16
|
437 }
|
Chris@16
|
438 };
|
Chris@16
|
439
|
Chris@16
|
440 class lessScan45Vertex {
|
Chris@16
|
441 public:
|
Chris@16
|
442 inline lessScan45Vertex() {} //default constructor is only constructor
|
Chris@16
|
443 template <typename Scan45Vertex>
|
Chris@16
|
444 inline bool operator () (const Scan45Vertex& v1, const Scan45Vertex& v2) const {
|
Chris@16
|
445 return (v1.first.x() < v2.first.x()) || (v1.first.x() == v2.first.x() && v1.first.y() < v2.first.y());
|
Chris@16
|
446 }
|
Chris@16
|
447 };
|
Chris@16
|
448 template <typename S45V>
|
Chris@16
|
449 static inline void sortScan45Vector(S45V& vec) {
|
Chris@16
|
450 polygon_sort(vec.begin(), vec.end(), lessScan45Vertex());
|
Chris@16
|
451 }
|
Chris@16
|
452
|
Chris@16
|
453 template <typename CountType, typename output_functor>
|
Chris@16
|
454 class Scan45 {
|
Chris@16
|
455 public:
|
Chris@16
|
456 typedef Scan45CountT<CountType> Scan45Count;
|
Chris@16
|
457 typedef std::pair<Point, Scan45Count> Scan45Vertex;
|
Chris@16
|
458
|
Chris@16
|
459 //index is the index into the vertex
|
Chris@16
|
460 static inline Scan45Element getElement(const Scan45Vertex& vertex, int index) {
|
Chris@16
|
461 return Scan45Element(vertex.first.x(), vertex.first.y(), index - 1, vertex.second[index]);
|
Chris@16
|
462 }
|
Chris@16
|
463
|
Chris@16
|
464 class lessScan45Point : public std::binary_function<Point, Point, bool> {
|
Chris@16
|
465 public:
|
Chris@16
|
466 inline lessScan45Point() {} //default constructor is only constructor
|
Chris@16
|
467 inline bool operator () (const Point& v1, const Point& v2) const {
|
Chris@16
|
468 return (v1.x() < v2.x()) || (v1.x() == v2.x() && v1.y() < v2.y());
|
Chris@16
|
469 }
|
Chris@16
|
470 };
|
Chris@16
|
471
|
Chris@16
|
472 typedef std::vector<Scan45Vertex> Scan45Vector;
|
Chris@16
|
473
|
Chris@16
|
474 //definitions
|
Chris@16
|
475 typedef std::set<Scan45ElementT<CountType>, lessScan45Element<CountType> > Scan45Data;
|
Chris@16
|
476 typedef typename Scan45Data::iterator iterator;
|
Chris@16
|
477 typedef typename Scan45Data::const_iterator const_iterator;
|
Chris@16
|
478 typedef std::set<Point, lessScan45Point> CrossQueue;
|
Chris@16
|
479
|
Chris@16
|
480 //data
|
Chris@16
|
481 Scan45Data scanData_;
|
Chris@16
|
482 CrossQueue crossQueue_;
|
Chris@16
|
483 Scan45Vector crossVector_;
|
Chris@16
|
484 Unit x_;
|
Chris@16
|
485 int justBefore_;
|
Chris@16
|
486 public:
|
Chris@16
|
487 inline Scan45() : scanData_(), crossQueue_(), crossVector_(),
|
Chris@16
|
488 x_((std::numeric_limits<Unit>::min)()), justBefore_(false) {
|
Chris@16
|
489 lessScan45Element<CountType> lessElm(&x_, &justBefore_);
|
Chris@16
|
490 scanData_ = std::set<Scan45ElementT<CountType>, lessScan45Element<CountType> >(lessElm);
|
Chris@16
|
491 }
|
Chris@16
|
492 inline Scan45(const Scan45& that) : scanData_(), crossQueue_(), crossVector_(),
|
Chris@16
|
493 x_((std::numeric_limits<Unit>::min)()), justBefore_(false) {
|
Chris@16
|
494 (*this) = that; }
|
Chris@16
|
495 inline Scan45& operator=(const Scan45& that) {
|
Chris@16
|
496 x_ = that.x_;
|
Chris@16
|
497 justBefore_ = that.justBefore_;
|
Chris@16
|
498 crossQueue_ = that.crossQueue_;
|
Chris@16
|
499 crossVector_ = that.crossVector_;
|
Chris@16
|
500 lessScan45Element<CountType> lessElm(&x_, &justBefore_);
|
Chris@16
|
501 scanData_ = std::set<Scan45ElementT<CountType>, lessScan45Element<CountType> >(lessElm);
|
Chris@16
|
502 for(const_iterator itr = that.scanData_.begin(); itr != that.scanData_.end(); ++itr){
|
Chris@16
|
503 scanData_.insert(scanData_.end(), *itr);
|
Chris@16
|
504 }
|
Chris@16
|
505 return *this;
|
Chris@16
|
506 }
|
Chris@16
|
507
|
Chris@16
|
508 //cT is an output container of Vertex45
|
Chris@16
|
509 //iT is an iterator over Scan45Vertex elements
|
Chris@16
|
510 template <class cT, class iT>
|
Chris@16
|
511 void scan(cT& output, iT inputBegin, iT inputEnd) {
|
Chris@16
|
512 //std::cout << "1\n";
|
Chris@16
|
513 while(inputBegin != inputEnd) {
|
Chris@16
|
514 //std::cout << "2\n";
|
Chris@16
|
515 //std::cout << "x_ = " << x_ << "\n";
|
Chris@16
|
516 //std::cout << "scan line size: " << scanData_.size() << "\n";
|
Chris@16
|
517 //for(iterator iter = scanData_.begin();
|
Chris@16
|
518 // iter != scanData_.end(); ++iter) {
|
Chris@16
|
519 // std::cout << "scan element\n";
|
Chris@16
|
520 // std::cout << *iter << " " << iter->evalAtX(x_) << "\n";
|
Chris@16
|
521 // }
|
Chris@16
|
522 // std::cout << "cross queue size: " << crossQueue_.size() << "\n";
|
Chris@16
|
523 // std::cout << "cross vector size: " << crossVector_.size() << "\n";
|
Chris@16
|
524 //for(CrossQueue::iterator cqitr = crossQueue_.begin(); cqitr != crossQueue_.end(); ++cqitr) {
|
Chris@16
|
525 // std::cout << *cqitr << " ";
|
Chris@16
|
526 //} std::cout << "\n";
|
Chris@16
|
527 Unit nextX = (*inputBegin).first.x();
|
Chris@16
|
528 if(!crossVector_.empty() && crossVector_[0].first.x() < nextX) nextX = crossVector_[0].first.x();
|
Chris@16
|
529 if(nextX != x_) {
|
Chris@16
|
530 //std::cout << "3\n";
|
Chris@16
|
531 //we need to move to the next scanline stop
|
Chris@16
|
532 //we need to process end events then cross events
|
Chris@16
|
533 //process end events
|
Chris@16
|
534 if(!crossQueue_.empty() &&
|
Chris@16
|
535 (*crossQueue_.begin()).x() < nextX) {
|
Chris@16
|
536 //std::cout << "4\n";
|
Chris@16
|
537 nextX = (std::min)(nextX, (*crossQueue_.begin()).x());
|
Chris@16
|
538 }
|
Chris@16
|
539 //std::cout << "6\n";
|
Chris@16
|
540 justBefore_ = true;
|
Chris@16
|
541 x_ = nextX;
|
Chris@16
|
542 advance_(output);
|
Chris@16
|
543 justBefore_ = false;
|
Chris@16
|
544 if(!crossVector_.empty() &&
|
Chris@16
|
545 nextX == (*inputBegin).first.x()) {
|
Chris@16
|
546 inputBegin = mergeCross_(inputBegin, inputEnd);
|
Chris@16
|
547 }
|
Chris@16
|
548 processEvent_(output, crossVector_.begin(), crossVector_.end());
|
Chris@16
|
549 crossVector_.clear();
|
Chris@16
|
550 } else {
|
Chris@16
|
551 //std::cout << "7\n";
|
Chris@16
|
552 //our scanline has progressed to the event that is next in the queue
|
Chris@16
|
553 inputBegin = processEvent_(output, inputBegin, inputEnd);
|
Chris@16
|
554 }
|
Chris@16
|
555 }
|
Chris@16
|
556 //std::cout << "done scanning\n";
|
Chris@16
|
557 }
|
Chris@16
|
558
|
Chris@16
|
559 private:
|
Chris@16
|
560 //functions
|
Chris@16
|
561
|
Chris@16
|
562 template <class cT>
|
Chris@16
|
563 inline void advance_(cT& output) {
|
Chris@16
|
564 //process all cross points on the cross queue at the current x_
|
Chris@16
|
565 //std::cout << "advance_\n";
|
Chris@16
|
566 std::vector<iterator> eraseVec;
|
Chris@16
|
567 while(!crossQueue_.empty() &&
|
Chris@16
|
568 (*crossQueue_.begin()).x() == x_){
|
Chris@16
|
569 //std::cout << "loop\n";
|
Chris@16
|
570 //pop point off the cross queue
|
Chris@16
|
571 Point crossPoint = *(crossQueue_.begin());
|
Chris@16
|
572 //std::cout << crossPoint << "\n";
|
Chris@16
|
573 //for(iterator iter = scanData_.begin();
|
Chris@16
|
574 // iter != scanData_.end(); ++iter) {
|
Chris@16
|
575 // std::cout << "scan element\n";
|
Chris@16
|
576 // std::cout << *iter << " " << iter->evalAtX(x_) << "\n";
|
Chris@16
|
577 //}
|
Chris@16
|
578 crossQueue_.erase(crossQueue_.begin());
|
Chris@16
|
579 Scan45Vertex vertex(crossPoint, Scan45Count());
|
Chris@16
|
580 iterator lowIter = lookUp_(vertex.first.y());
|
Chris@16
|
581 //std::cout << "searching at: " << vertex.first.y() << "\n";
|
Chris@16
|
582 //if(lowIter == scanData_.end()) std::cout << "could not find\n";
|
Chris@16
|
583 //else std::cout << "found: " << *lowIter << "\n";
|
Chris@16
|
584 if(lowIter == scanData_.end() ||
|
Chris@16
|
585 lowIter->evalAtX(x_) != vertex.first.y()) {
|
Chris@16
|
586 // std::cout << "skipping\n";
|
Chris@16
|
587 //there weren't any edges at this potential cross point
|
Chris@16
|
588 continue;
|
Chris@16
|
589 }
|
Chris@16
|
590 CountType countBelow;
|
Chris@16
|
591 iterator searchDownItr = lowIter;
|
Chris@16
|
592 while(searchDownItr != scanData_.begin()
|
Chris@16
|
593 && searchDownItr->evalAtX(x_) == vertex.first.y()) {
|
Chris@16
|
594 //get count from below
|
Chris@16
|
595 --searchDownItr;
|
Chris@16
|
596 countBelow = searchDownItr->count;
|
Chris@16
|
597 }
|
Chris@16
|
598 //std::cout << "Below Count: " << countBelow << "\n";
|
Chris@16
|
599 Scan45Count count(countBelow);
|
Chris@16
|
600 std::size_t numEdges = 0;
|
Chris@16
|
601 iterator eraseItrs[3];
|
Chris@16
|
602 while(lowIter != scanData_.end() &&
|
Chris@16
|
603 lowIter->evalAtX(x_) == vertex.first.y()) {
|
Chris@16
|
604 for(int index = lowIter->rise +1; index >= 0; --index)
|
Chris@16
|
605 count[index] = lowIter->count;
|
Chris@16
|
606 //std::cout << count << "\n";
|
Chris@16
|
607 eraseItrs[numEdges] = lowIter;
|
Chris@16
|
608 ++numEdges;
|
Chris@16
|
609 ++lowIter;
|
Chris@16
|
610 }
|
Chris@16
|
611 if(numEdges == 1) {
|
Chris@16
|
612 //look for the next crossing point and continue
|
Chris@16
|
613 //std::cout << "found only one edge\n";
|
Chris@16
|
614 findCross_(eraseItrs[0]);
|
Chris@16
|
615 continue;
|
Chris@16
|
616 }
|
Chris@16
|
617 //before we erase the elements we need to decide if they should be written out
|
Chris@16
|
618 CountType currentCount = countBelow;
|
Chris@16
|
619 for(std::size_t i = 0; i < numEdges; ++i) {
|
Chris@16
|
620 output_functor f;
|
Chris@16
|
621 f(output, currentCount, eraseItrs[i]->count, crossPoint, eraseItrs[i]->rise, LOW);
|
Chris@16
|
622 currentCount = eraseItrs[i]->count;
|
Chris@16
|
623 }
|
Chris@16
|
624 //schedule erase of the elements
|
Chris@16
|
625 for(std::size_t i = 0; i < numEdges; ++i) {
|
Chris@16
|
626 eraseVec.push_back(eraseItrs[i]);
|
Chris@16
|
627 }
|
Chris@16
|
628
|
Chris@16
|
629 //take the derivative wrt theta of the count at the crossing point
|
Chris@16
|
630 vertex.second[2] = count[2] - countBelow;
|
Chris@16
|
631 vertex.second[1] = count[1] - count[2];
|
Chris@16
|
632 vertex.second[0] = count[0] - count[1];
|
Chris@16
|
633 //add the point, deriviative pair into the cross vector
|
Chris@16
|
634 //std::cout << "LOOK HERE!\n";
|
Chris@16
|
635 //std::cout << count << "\n";
|
Chris@16
|
636 //std::cout << vertex << "\n";
|
Chris@16
|
637 crossVector_.push_back(vertex);
|
Chris@16
|
638 }
|
Chris@16
|
639 //erase crossing elements
|
Chris@16
|
640 std::vector<iterator> searchVec;
|
Chris@16
|
641 for(std::size_t i = 0; i < eraseVec.size(); ++i) {
|
Chris@16
|
642 if(eraseVec[i] != scanData_.begin()) {
|
Chris@16
|
643 iterator searchItr = eraseVec[i];
|
Chris@16
|
644 --searchItr;
|
Chris@16
|
645 if(searchVec.empty() ||
|
Chris@16
|
646 searchVec.back() != searchItr)
|
Chris@16
|
647 searchVec.push_back(searchItr);
|
Chris@16
|
648 }
|
Chris@16
|
649 scanData_.erase(eraseVec[i]);
|
Chris@16
|
650 }
|
Chris@16
|
651 for(std::size_t i = 0; i < searchVec.size(); ++i) {
|
Chris@16
|
652 findCross_(searchVec[i]);
|
Chris@16
|
653 }
|
Chris@16
|
654 }
|
Chris@16
|
655
|
Chris@16
|
656 template <class iT>
|
Chris@16
|
657 inline iT mergeCross_(iT inputBegin, iT inputEnd) {
|
Chris@16
|
658 Scan45Vector vec;
|
Chris@16
|
659 swap(vec, crossVector_);
|
Chris@16
|
660 iT mergeEnd = inputBegin;
|
Chris@16
|
661 std::size_t mergeCount = 0;
|
Chris@16
|
662 while(mergeEnd != inputEnd &&
|
Chris@16
|
663 (*mergeEnd).first.x() == x_) {
|
Chris@16
|
664 ++mergeCount;
|
Chris@16
|
665 ++mergeEnd;
|
Chris@16
|
666 }
|
Chris@16
|
667 crossVector_.reserve((std::max)(vec.capacity(), vec.size() + mergeCount));
|
Chris@16
|
668 for(std::size_t i = 0; i < vec.size(); ++i){
|
Chris@16
|
669 while(inputBegin != mergeEnd &&
|
Chris@16
|
670 (*inputBegin).first.y() < vec[i].first.y()) {
|
Chris@16
|
671 crossVector_.push_back(*inputBegin);
|
Chris@16
|
672 ++inputBegin;
|
Chris@16
|
673 }
|
Chris@16
|
674 crossVector_.push_back(vec[i]);
|
Chris@16
|
675 }
|
Chris@16
|
676 while(inputBegin != mergeEnd){
|
Chris@16
|
677 crossVector_.push_back(*inputBegin);
|
Chris@16
|
678 ++inputBegin;
|
Chris@16
|
679 }
|
Chris@16
|
680 return inputBegin;
|
Chris@16
|
681 }
|
Chris@16
|
682
|
Chris@16
|
683 template <class cT, class iT>
|
Chris@16
|
684 inline iT processEvent_(cT& output, iT inputBegin, iT inputEnd) {
|
Chris@16
|
685 //std::cout << "processEvent_\n";
|
Chris@16
|
686 CountType verticalCount = CountType();
|
Chris@16
|
687 Point prevPoint;
|
Chris@16
|
688 iterator prevIter = scanData_.end();
|
Chris@16
|
689 while(inputBegin != inputEnd &&
|
Chris@16
|
690 (*inputBegin).first.x() == x_) {
|
Chris@16
|
691 //std::cout << (*inputBegin) << "\n";
|
Chris@16
|
692 //std::cout << "loop\n";
|
Chris@16
|
693 Scan45Vertex vertex = *inputBegin;
|
Chris@16
|
694 //std::cout << vertex.first << "\n";
|
Chris@16
|
695 //if vertical count propigating up fake a null event at the next element
|
Chris@16
|
696 if(verticalCount != CountType() && (prevIter != scanData_.end() &&
|
Chris@16
|
697 prevIter->evalAtX(x_) < vertex.first.y())) {
|
Chris@16
|
698 //std::cout << "faking null event\n";
|
Chris@16
|
699 vertex = Scan45Vertex(Point(x_, prevIter->evalAtX(x_)), Scan45Count());
|
Chris@16
|
700 } else {
|
Chris@16
|
701 ++inputBegin;
|
Chris@16
|
702 //std::cout << "after increment\n";
|
Chris@16
|
703 //accumulate overlapping changes in Scan45Count
|
Chris@16
|
704 while(inputBegin != inputEnd &&
|
Chris@16
|
705 (*inputBegin).first.x() == x_ &&
|
Chris@16
|
706 (*inputBegin).first.y() == vertex.first.y()) {
|
Chris@16
|
707 //std::cout << "accumulate\n";
|
Chris@16
|
708 vertex.second += (*inputBegin).second;
|
Chris@16
|
709 ++inputBegin;
|
Chris@16
|
710 }
|
Chris@16
|
711 }
|
Chris@16
|
712 //std::cout << vertex.second << "\n";
|
Chris@16
|
713 //integrate vertex
|
Chris@16
|
714 CountType currentCount = verticalCount;// + vertex.second[0];
|
Chris@16
|
715 for(unsigned int i = 0; i < 3; ++i) {
|
Chris@16
|
716 vertex.second[i] = currentCount += vertex.second[i];
|
Chris@16
|
717 }
|
Chris@16
|
718 //std::cout << vertex.second << "\n";
|
Chris@16
|
719 //vertex represents the change in state at this point
|
Chris@16
|
720
|
Chris@16
|
721 //get counts at current vertex
|
Chris@16
|
722 CountType countBelow;
|
Chris@16
|
723 iterator lowIter = lookUp_(vertex.first.y());
|
Chris@16
|
724 if(lowIter != scanData_.begin()) {
|
Chris@16
|
725 //get count from below
|
Chris@16
|
726 --lowIter;
|
Chris@16
|
727 countBelow = lowIter->count;
|
Chris@16
|
728 ++lowIter;
|
Chris@16
|
729 }
|
Chris@16
|
730 //std::cout << "Count Below: " << countBelow[0] << " " << countBelow[1] << "\n";
|
Chris@16
|
731 //std::cout << "vertical count: " << verticalCount[0] << " " << verticalCount[1] << "\n";
|
Chris@16
|
732 Scan45Count countAt(countBelow - verticalCount);
|
Chris@16
|
733 //check if the vertical edge should be written out
|
Chris@16
|
734 if(verticalCount != CountType()) {
|
Chris@16
|
735 output_functor f;
|
Chris@16
|
736 f(output, countBelow - verticalCount, countBelow, prevPoint, 2, HIGH);
|
Chris@16
|
737 f(output, countBelow - verticalCount, countBelow, vertex.first, 2, LOW);
|
Chris@16
|
738 }
|
Chris@16
|
739 currentCount = countBelow - verticalCount;
|
Chris@16
|
740 while(lowIter != scanData_.end() &&
|
Chris@16
|
741 lowIter->evalAtX(x_) == vertex.first.y()) {
|
Chris@16
|
742 for(unsigned int i = lowIter->rise + 1; i < 3; ++i) {
|
Chris@16
|
743 countAt[i] = lowIter->count;
|
Chris@16
|
744 }
|
Chris@16
|
745 Point lp(lowIter->x, lowIter->y);
|
Chris@16
|
746 if(lp != vertex.first) {
|
Chris@16
|
747 output_functor f;
|
Chris@16
|
748 f(output, currentCount, lowIter->count, vertex.first, lowIter->rise, LOW);
|
Chris@16
|
749 }
|
Chris@16
|
750 currentCount = lowIter->count;
|
Chris@16
|
751 iterator nextIter = lowIter;
|
Chris@16
|
752 ++nextIter;
|
Chris@16
|
753 //std::cout << "erase\n";
|
Chris@16
|
754 scanData_.erase(lowIter);
|
Chris@16
|
755 if(nextIter != scanData_.end())
|
Chris@16
|
756 findCross_(nextIter);
|
Chris@16
|
757 lowIter = nextIter;
|
Chris@16
|
758 }
|
Chris@16
|
759 verticalCount += vertex.second[3];
|
Chris@16
|
760 prevPoint = vertex.first;
|
Chris@16
|
761 //std::cout << "new vertical count: " << verticalCount[0] << " " << verticalCount[1] << "\n";
|
Chris@16
|
762 prevIter = lowIter;
|
Chris@16
|
763 //count represents the current state at this point
|
Chris@16
|
764 //std::cout << vertex.second << "\n";
|
Chris@16
|
765 //std::cout << countAt << "\n";
|
Chris@16
|
766 //std::cout << "ADD\n";
|
Chris@16
|
767 vertex.second += countAt;
|
Chris@16
|
768 //std::cout << vertex.second << "\n";
|
Chris@16
|
769
|
Chris@16
|
770 //add elements to the scanline
|
Chris@16
|
771 for(int i = 0; i < 3; ++i) {
|
Chris@16
|
772 if(vertex.second[i] != countBelow) {
|
Chris@16
|
773 //std::cout << "insert: " << vertex.first.x() << " " << vertex.first.y() << " " << i-1 <<
|
Chris@16
|
774 // " " << vertex.second[i][0] << " " << vertex.second[i][1] << "\n";
|
Chris@16
|
775 iterator insertIter = scanData_.insert(scanData_.end(),
|
Chris@16
|
776 Scan45ElementT<CountType>(vertex.first.x(),
|
Chris@16
|
777 vertex.first.y(),
|
Chris@16
|
778 i - 1, vertex.second[i]));
|
Chris@16
|
779 findCross_(insertIter);
|
Chris@16
|
780 output_functor f;
|
Chris@16
|
781 f(output, countBelow, vertex.second[i], vertex.first, i - 1, HIGH);
|
Chris@16
|
782 }
|
Chris@16
|
783 countBelow = vertex.second[i];
|
Chris@16
|
784 }
|
Chris@16
|
785 }
|
Chris@16
|
786 //std::cout << "end processEvent\n";
|
Chris@16
|
787 return inputBegin;
|
Chris@16
|
788 }
|
Chris@16
|
789
|
Chris@16
|
790 //iter1 is horizontal
|
Chris@16
|
791 inline void scheduleCross0_(iterator iter1, iterator iter2) {
|
Chris@16
|
792 //std::cout << "0, ";
|
Chris@16
|
793 Unit y1 = iter1->evalAtX(x_);
|
Chris@16
|
794 Unit y2 = iter2->evalAtX(x_);
|
Chris@16
|
795 LongUnit delta = local_abs(LongUnit(y1) - LongUnit(y2));
|
Chris@16
|
796 if(delta + static_cast<LongUnit>(x_) <= (std::numeric_limits<Unit>::max)())
|
Chris@16
|
797 crossQueue_.insert(crossQueue_.end(), Point(x_ + static_cast<Unit>(delta), y1));
|
Chris@16
|
798 //std::cout << Point(x_ + delta, y1);
|
Chris@16
|
799 }
|
Chris@16
|
800
|
Chris@16
|
801 //neither iter is horizontal
|
Chris@16
|
802 inline void scheduleCross1_(iterator iter1, iterator iter2) {
|
Chris@16
|
803 //std::cout << "1, ";
|
Chris@16
|
804 Unit y1 = iter1->evalAtX(x_);
|
Chris@16
|
805 Unit y2 = iter2->evalAtX(x_);
|
Chris@16
|
806 //std::cout << y1 << " " << y2 << ": ";
|
Chris@16
|
807 //note that half the delta cannot exceed the positive inter range
|
Chris@16
|
808 LongUnit delta = y1;
|
Chris@16
|
809 delta -= y2;
|
Chris@16
|
810 Unit UnitMax = (std::numeric_limits<Unit>::max)();
|
Chris@16
|
811 if((delta & 1) == 1) {
|
Chris@16
|
812 //delta is odd, division by 2 will result in integer trunctaion
|
Chris@16
|
813 if(delta == 1) {
|
Chris@16
|
814 //the cross point is not on the integer grid and cannot be represented
|
Chris@16
|
815 //we must throw an exception
|
Chris@16
|
816 std::string msg = "GTL 45 Boolean error, precision insufficient to represent edge intersection coordinate value.";
|
Chris@16
|
817 throw(msg);
|
Chris@16
|
818 } else {
|
Chris@16
|
819 //note that result of this subtraction is always positive because itr1 is above itr2 in scanline
|
Chris@16
|
820 LongUnit halfDelta2 = (LongUnit)((((LongUnit)y1) - y2)/2);
|
Chris@16
|
821 //note that halfDelta2 has been truncated
|
Chris@16
|
822 if(halfDelta2 + x_ <= UnitMax && halfDelta2 + y2 <= UnitMax) {
|
Chris@16
|
823 crossQueue_.insert(crossQueue_.end(), Point(x_+static_cast<Unit>(halfDelta2), y2+static_cast<Unit>(halfDelta2)));
|
Chris@16
|
824 crossQueue_.insert(crossQueue_.end(), Point(x_+static_cast<Unit>(halfDelta2), y2+static_cast<Unit>(halfDelta2)+1));
|
Chris@16
|
825 }
|
Chris@16
|
826 }
|
Chris@16
|
827 } else {
|
Chris@16
|
828 LongUnit halfDelta = (LongUnit)((((LongUnit)y1) - y2)/2);
|
Chris@16
|
829 if(halfDelta + x_ <= UnitMax && halfDelta + y2 <= UnitMax)
|
Chris@16
|
830 crossQueue_.insert(crossQueue_.end(), Point(x_+static_cast<Unit>(halfDelta), y2+static_cast<Unit>(halfDelta)));
|
Chris@16
|
831 //std::cout << Point(x_+halfDelta, y2+halfDelta);
|
Chris@16
|
832 }
|
Chris@16
|
833 }
|
Chris@16
|
834
|
Chris@16
|
835 inline void findCross_(iterator iter) {
|
Chris@16
|
836 //std::cout << "find cross ";
|
Chris@16
|
837 iterator iteratorBelow = iter;
|
Chris@16
|
838 iterator iteratorAbove = iter;
|
Chris@16
|
839 if(iter != scanData_.begin() && iter->rise < 1) {
|
Chris@16
|
840 --iteratorBelow;
|
Chris@16
|
841 if(iter->rise == 0){
|
Chris@16
|
842 if(iteratorBelow->rise == 1) {
|
Chris@16
|
843 scheduleCross0_(iter, iteratorBelow);
|
Chris@16
|
844 }
|
Chris@16
|
845 } else {
|
Chris@16
|
846 //iter->rise == -1
|
Chris@16
|
847 if(iteratorBelow->rise == 1) {
|
Chris@16
|
848 scheduleCross1_(iter, iteratorBelow);
|
Chris@16
|
849 } else if(iteratorBelow->rise == 0) {
|
Chris@16
|
850 scheduleCross0_(iteratorBelow, iter);
|
Chris@16
|
851 }
|
Chris@16
|
852 }
|
Chris@16
|
853 }
|
Chris@16
|
854 ++iteratorAbove;
|
Chris@16
|
855 if(iteratorAbove != scanData_.end() && iter->rise > -1) {
|
Chris@16
|
856 if(iter->rise == 0) {
|
Chris@16
|
857 if(iteratorAbove->rise == -1) {
|
Chris@16
|
858 scheduleCross0_(iter, iteratorAbove);
|
Chris@16
|
859 }
|
Chris@16
|
860 } else {
|
Chris@16
|
861 //iter->rise == 1
|
Chris@16
|
862 if(iteratorAbove->rise == -1) {
|
Chris@16
|
863 scheduleCross1_(iteratorAbove, iter);
|
Chris@16
|
864 } else if(iteratorAbove->rise == 0) {
|
Chris@16
|
865 scheduleCross0_(iteratorAbove, iter);
|
Chris@16
|
866 }
|
Chris@16
|
867 }
|
Chris@16
|
868 }
|
Chris@16
|
869 //std::cout << "\n";
|
Chris@16
|
870 }
|
Chris@16
|
871
|
Chris@16
|
872 inline iterator lookUp_(Unit y){
|
Chris@16
|
873 //if just before then we need to look from 1 not -1
|
Chris@16
|
874 return scanData_.lower_bound(Scan45ElementT<CountType>(x_, y, -1+2*justBefore_));
|
Chris@16
|
875 }
|
Chris@16
|
876 };
|
Chris@16
|
877
|
Chris@16
|
878 //template <typename CountType>
|
Chris@16
|
879 //static inline void print45Data(const std::set<Scan45ElementT<CountType>,
|
Chris@16
|
880 // lessScan45Element<CountType> >& data) {
|
Chris@16
|
881 // typename std::set<Scan45ElementT<CountType>, lessScan45Element<CountType> >::const_iterator iter;
|
Chris@16
|
882 // for(iter = data.begin(); iter != data.end(); ++iter) {
|
Chris@16
|
883 // std::cout << iter->x << " " << iter->y << " " << iter->rise << "\n";
|
Chris@16
|
884 // }
|
Chris@16
|
885 //}
|
Chris@16
|
886
|
Chris@16
|
887 template <typename streamtype>
|
Chris@16
|
888 static inline bool testScan45Data(streamtype& stdcout) {
|
Chris@16
|
889 Unit x = 0;
|
Chris@16
|
890 int justBefore = false;
|
Chris@16
|
891 lessScan45Element<Count2> lessElm(&x, &justBefore);
|
Chris@16
|
892 std::set<Scan45ElementT<Count2>, lessScan45Element<Count2> > testData(lessElm);
|
Chris@16
|
893 //Unit size = testData.size();
|
Chris@16
|
894 typedef std::set<Scan45ElementT<Count2>, lessScan45Element<Count2> > Scan45Data;
|
Chris@16
|
895 typename Scan45Data::iterator itr10 = testData.insert(testData.end(), Scan45Element(0, 10, 1));
|
Chris@16
|
896 typename Scan45Data::iterator itr20 = testData.insert(testData.end(), Scan45Element(0, 20, 1));
|
Chris@16
|
897 typename Scan45Data::iterator itr30 = testData.insert(testData.end(), Scan45Element(0, 30, -1));
|
Chris@16
|
898 typename Scan45Data::iterator itr40 = testData.insert(testData.end(), Scan45Element(0, 40, -1));
|
Chris@16
|
899 typename Scan45Data::iterator itrA = testData.lower_bound(Scan45Element(0, 29, -1));
|
Chris@16
|
900 typename Scan45Data::iterator itr1 = testData.lower_bound(Scan45Element(0, 10, -1));
|
Chris@16
|
901 x = 4;
|
Chris@16
|
902 //now at 14 24 26 36
|
Chris@16
|
903 typename Scan45Data::iterator itrB = testData.lower_bound(Scan45Element(4, 29, -1));
|
Chris@16
|
904 typename Scan45Data::iterator itr2 = testData.lower_bound(Scan45Element(4, 14, -1));
|
Chris@16
|
905 if(itr1 != itr2) stdcout << "test1 failed\n";
|
Chris@16
|
906 if(itrA == itrB) stdcout << "test2 failed\n";
|
Chris@16
|
907 //remove crossing elements
|
Chris@16
|
908 testData.erase(itr20);
|
Chris@16
|
909 testData.erase(itr30);
|
Chris@16
|
910 x = 5;
|
Chris@16
|
911 itr20 = testData.insert(testData.end(), Scan45Element(0, 20, 1));
|
Chris@16
|
912 itr30 = testData.insert(testData.end(), Scan45Element(0, 30, -1));
|
Chris@16
|
913 //now at 15 25 25 35
|
Chris@16
|
914 typename Scan45Data::iterator itr = testData.begin();
|
Chris@16
|
915 if(itr != itr10) stdcout << "test3 failed\n";
|
Chris@16
|
916 ++itr;
|
Chris@16
|
917 if(itr != itr30) stdcout << "test4 failed\n";
|
Chris@16
|
918 ++itr;
|
Chris@16
|
919 if(itr != itr20) stdcout << "test5 failed\n";
|
Chris@16
|
920 ++itr;
|
Chris@16
|
921 if(itr != itr40) stdcout << "test6 failed\n";
|
Chris@16
|
922 stdcout << "done testing Scan45Data\n";
|
Chris@16
|
923 return true;
|
Chris@16
|
924 }
|
Chris@16
|
925
|
Chris@16
|
926 template <typename stream_type>
|
Chris@16
|
927 static inline bool testScan45Rect(stream_type& stdcout) {
|
Chris@16
|
928 stdcout << "testing Scan45Rect\n";
|
Chris@16
|
929 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
|
Chris@16
|
930 std::vector<Vertex45 > result;
|
Chris@16
|
931 typedef std::pair<Point, Scan45Count> Scan45Vertex;
|
Chris@16
|
932 std::vector<Scan45Vertex> vertices;
|
Chris@16
|
933 //is a Rectnagle(0, 0, 10, 10);
|
Chris@16
|
934 Count2 count(1, 0);
|
Chris@16
|
935 Count2 ncount(-1, 0);
|
Chris@16
|
936 vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
|
Chris@16
|
937 vertices.push_back(Scan45Vertex(Point(0,10), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
|
Chris@16
|
938 vertices.push_back(Scan45Vertex(Point(10,0), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
|
Chris@16
|
939 vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
|
Chris@16
|
940 stdcout << "scanning\n";
|
Chris@16
|
941 scan45.scan(result, vertices.begin(), vertices.end());
|
Chris@16
|
942 stdcout << "done scanning\n";
|
Chris@16
|
943 // result size == 8
|
Chris@16
|
944 // result == 0 0 0 1
|
Chris@16
|
945 // result == 0 0 2 1
|
Chris@16
|
946 // result == 0 10 2 -1
|
Chris@16
|
947 // result == 0 10 0 -1
|
Chris@16
|
948 // result == 10 0 0 -1
|
Chris@16
|
949 // result == 10 0 2 -1
|
Chris@16
|
950 // result == 10 10 2 1
|
Chris@16
|
951 // result == 10 10 0 1
|
Chris@16
|
952 std::vector<Vertex45> reference;
|
Chris@16
|
953 reference.push_back(Vertex45(Point(0, 0), 0, 1));
|
Chris@16
|
954 reference.push_back(Vertex45(Point(0, 0), 2, 1));
|
Chris@16
|
955 reference.push_back(Vertex45(Point(0, 10), 2, -1));
|
Chris@16
|
956 reference.push_back(Vertex45(Point(0, 10), 0, -1));
|
Chris@16
|
957 reference.push_back(Vertex45(Point(10, 0), 0, -1));
|
Chris@16
|
958 reference.push_back(Vertex45(Point(10, 0), 2, -1));
|
Chris@16
|
959 reference.push_back(Vertex45(Point(10, 10), 2, 1));
|
Chris@16
|
960 reference.push_back(Vertex45(Point(10, 10), 0, 1));
|
Chris@16
|
961 if(result != reference) {
|
Chris@16
|
962 stdcout << "result size == " << result.size() << "\n";
|
Chris@16
|
963 for(std::size_t i = 0; i < result.size(); ++i) {
|
Chris@16
|
964 //std::cout << "result == " << result[i]<< "\n";
|
Chris@16
|
965 }
|
Chris@16
|
966 stdcout << "reference size == " << reference.size() << "\n";
|
Chris@16
|
967 for(std::size_t i = 0; i < reference.size(); ++i) {
|
Chris@16
|
968 //std::cout << "reference == " << reference[i]<< "\n";
|
Chris@16
|
969 }
|
Chris@16
|
970 return false;
|
Chris@16
|
971 }
|
Chris@16
|
972 stdcout << "done testing Scan45Rect\n";
|
Chris@16
|
973 return true;
|
Chris@16
|
974 }
|
Chris@16
|
975
|
Chris@16
|
976 template <typename stream_type>
|
Chris@16
|
977 static inline bool testScan45P1(stream_type& stdcout) {
|
Chris@16
|
978 stdcout << "testing Scan45P1\n";
|
Chris@16
|
979 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
|
Chris@16
|
980 std::vector<Vertex45 > result;
|
Chris@16
|
981 typedef std::pair<Point, Scan45Count> Scan45Vertex;
|
Chris@16
|
982 std::vector<Scan45Vertex> vertices;
|
Chris@16
|
983 //is a Rectnagle(0, 0, 10, 10);
|
Chris@16
|
984 Count2 count(1, 0);
|
Chris@16
|
985 Count2 ncount(-1, 0);
|
Chris@16
|
986 vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
|
Chris@16
|
987 vertices.push_back(Scan45Vertex(Point(0,10), Scan45Count(Count2(0, 0), Count2(0, 0), ncount, ncount)));
|
Chris@16
|
988 vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), Count2(0, 0), ncount, ncount)));
|
Chris@16
|
989 vertices.push_back(Scan45Vertex(Point(10,20), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
|
Chris@16
|
990 stdcout << "scanning\n";
|
Chris@16
|
991 scan45.scan(result, vertices.begin(), vertices.end());
|
Chris@16
|
992 stdcout << "done scanning\n";
|
Chris@16
|
993 // result size == 8
|
Chris@16
|
994 // result == 0 0 1 1
|
Chris@16
|
995 // result == 0 0 2 1
|
Chris@16
|
996 // result == 0 10 2 -1
|
Chris@16
|
997 // result == 0 10 1 -1
|
Chris@16
|
998 // result == 10 10 1 -1
|
Chris@16
|
999 // result == 10 10 2 -1
|
Chris@16
|
1000 // result == 10 20 2 1
|
Chris@16
|
1001 // result == 10 20 1 1
|
Chris@16
|
1002 std::vector<Vertex45> reference;
|
Chris@16
|
1003 reference.push_back(Vertex45(Point(0, 0), 1, 1));
|
Chris@16
|
1004 reference.push_back(Vertex45(Point(0, 0), 2, 1));
|
Chris@16
|
1005 reference.push_back(Vertex45(Point(0, 10), 2, -1));
|
Chris@16
|
1006 reference.push_back(Vertex45(Point(0, 10), 1, -1));
|
Chris@16
|
1007 reference.push_back(Vertex45(Point(10, 10), 1, -1));
|
Chris@16
|
1008 reference.push_back(Vertex45(Point(10, 10), 2, -1));
|
Chris@16
|
1009 reference.push_back(Vertex45(Point(10, 20), 2, 1));
|
Chris@16
|
1010 reference.push_back(Vertex45(Point(10, 20), 1, 1));
|
Chris@16
|
1011 if(result != reference) {
|
Chris@16
|
1012 stdcout << "result size == " << result.size() << "\n";
|
Chris@16
|
1013 for(std::size_t i = 0; i < result.size(); ++i) {
|
Chris@16
|
1014 //std::cout << "result == " << result[i]<< "\n";
|
Chris@16
|
1015 }
|
Chris@16
|
1016 stdcout << "reference size == " << reference.size() << "\n";
|
Chris@16
|
1017 for(std::size_t i = 0; i < reference.size(); ++i) {
|
Chris@16
|
1018 //std::cout << "reference == " << reference[i]<< "\n";
|
Chris@16
|
1019 }
|
Chris@16
|
1020 return false;
|
Chris@16
|
1021 }
|
Chris@16
|
1022 stdcout << "done testing Scan45P1\n";
|
Chris@16
|
1023 return true;
|
Chris@16
|
1024 }
|
Chris@16
|
1025
|
Chris@16
|
1026 template <typename stream_type>
|
Chris@16
|
1027 static inline bool testScan45P2(stream_type& stdcout) {
|
Chris@16
|
1028 stdcout << "testing Scan45P2\n";
|
Chris@16
|
1029 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
|
Chris@16
|
1030 std::vector<Vertex45 > result;
|
Chris@16
|
1031 typedef std::pair<Point, Scan45Count> Scan45Vertex;
|
Chris@16
|
1032 std::vector<Scan45Vertex> vertices;
|
Chris@16
|
1033 //is a Rectnagle(0, 0, 10, 10);
|
Chris@16
|
1034 Count2 count(1, 0);
|
Chris@16
|
1035 Count2 ncount(-1, 0);
|
Chris@16
|
1036 vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
|
Chris@16
|
1037 vertices.push_back(Scan45Vertex(Point(10,0), Scan45Count(Count2(0, 0), ncount, count, Count2(0, 0))));
|
Chris@16
|
1038 vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), ncount, count, Count2(0, 0))));
|
Chris@16
|
1039 vertices.push_back(Scan45Vertex(Point(20,10), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
|
Chris@16
|
1040 stdcout << "scanning\n";
|
Chris@16
|
1041 scan45.scan(result, vertices.begin(), vertices.end());
|
Chris@16
|
1042 stdcout << "done scanning\n";
|
Chris@16
|
1043 // result size == 8
|
Chris@16
|
1044 // result == 0 0 0 1
|
Chris@16
|
1045 // result == 0 0 1 -1
|
Chris@16
|
1046 // result == 10 0 0 -1
|
Chris@16
|
1047 // result == 10 0 1 1
|
Chris@16
|
1048 // result == 10 10 1 1
|
Chris@16
|
1049 // result == 10 10 0 -1
|
Chris@16
|
1050 // result == 20 10 1 -1
|
Chris@16
|
1051 // result == 20 10 0 1
|
Chris@16
|
1052 std::vector<Vertex45> reference;
|
Chris@16
|
1053 reference.push_back(Vertex45(Point(0, 0), 0, 1));
|
Chris@16
|
1054 reference.push_back(Vertex45(Point(0, 0), 1, -1));
|
Chris@16
|
1055 reference.push_back(Vertex45(Point(10, 0), 0, -1));
|
Chris@16
|
1056 reference.push_back(Vertex45(Point(10, 0), 1, 1));
|
Chris@16
|
1057 reference.push_back(Vertex45(Point(10, 10), 1, 1));
|
Chris@16
|
1058 reference.push_back(Vertex45(Point(10, 10), 0, -1));
|
Chris@16
|
1059 reference.push_back(Vertex45(Point(20, 10), 1, -1));
|
Chris@16
|
1060 reference.push_back(Vertex45(Point(20, 10), 0, 1));
|
Chris@16
|
1061 if(result != reference) {
|
Chris@16
|
1062 stdcout << "result size == " << result.size() << "\n";
|
Chris@16
|
1063 for(std::size_t i = 0; i < result.size(); ++i) {
|
Chris@16
|
1064 //stdcout << "result == " << result[i]<< "\n";
|
Chris@16
|
1065 }
|
Chris@16
|
1066 stdcout << "reference size == " << reference.size() << "\n";
|
Chris@16
|
1067 for(std::size_t i = 0; i < reference.size(); ++i) {
|
Chris@16
|
1068 //stdcout << "reference == " << reference[i]<< "\n";
|
Chris@16
|
1069 }
|
Chris@16
|
1070 return false;
|
Chris@16
|
1071 }
|
Chris@16
|
1072 stdcout << "done testing Scan45P2\n";
|
Chris@16
|
1073 return true;
|
Chris@16
|
1074 }
|
Chris@16
|
1075
|
Chris@16
|
1076 template <typename streamtype>
|
Chris@16
|
1077 static inline bool testScan45And(streamtype& stdcout) {
|
Chris@16
|
1078 stdcout << "testing Scan45And\n";
|
Chris@16
|
1079 Scan45<Count2, boolean_op_45_output_functor<1> > scan45;
|
Chris@16
|
1080 std::vector<Vertex45 > result;
|
Chris@16
|
1081 typedef std::pair<Point, Scan45Count> Scan45Vertex;
|
Chris@16
|
1082 std::vector<Scan45Vertex> vertices;
|
Chris@16
|
1083 //is a Rectnagle(0, 0, 10, 10);
|
Chris@16
|
1084 Count2 count(1, 0);
|
Chris@16
|
1085 Count2 ncount(-1, 0);
|
Chris@16
|
1086 vertices.push_back(Scan45Vertex(Point(0,0), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
|
Chris@16
|
1087 vertices.push_back(Scan45Vertex(Point(0,10), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
|
Chris@16
|
1088 vertices.push_back(Scan45Vertex(Point(10,0), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
|
Chris@16
|
1089 vertices.push_back(Scan45Vertex(Point(10,10), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
|
Chris@16
|
1090 count = Count2(0, 1);
|
Chris@16
|
1091 ncount = count.invert();
|
Chris@16
|
1092 vertices.push_back(Scan45Vertex(Point(2,2), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
|
Chris@16
|
1093 vertices.push_back(Scan45Vertex(Point(2,12), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
|
Chris@16
|
1094 vertices.push_back(Scan45Vertex(Point(12,2), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
|
Chris@16
|
1095 vertices.push_back(Scan45Vertex(Point(12,12), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
|
Chris@16
|
1096 sortScan45Vector(vertices);
|
Chris@16
|
1097 stdcout << "scanning\n";
|
Chris@16
|
1098 scan45.scan(result, vertices.begin(), vertices.end());
|
Chris@16
|
1099 stdcout << "done scanning\n";
|
Chris@16
|
1100 //result size == 8
|
Chris@16
|
1101 //result == 2 2 0 1
|
Chris@16
|
1102 //result == 2 2 2 1
|
Chris@16
|
1103 //result == 2 10 2 -1
|
Chris@16
|
1104 //result == 2 10 0 -1
|
Chris@16
|
1105 //result == 10 2 0 -1
|
Chris@16
|
1106 //result == 10 2 2 -1
|
Chris@16
|
1107 //result == 10 10 2 1
|
Chris@16
|
1108 //result == 10 10 0 1
|
Chris@16
|
1109 std::vector<Vertex45> reference;
|
Chris@16
|
1110 reference.push_back(Vertex45(Point(2, 2), 0, 1));
|
Chris@16
|
1111 reference.push_back(Vertex45(Point(2, 2), 2, 1));
|
Chris@16
|
1112 reference.push_back(Vertex45(Point(2, 10), 2, -1));
|
Chris@16
|
1113 reference.push_back(Vertex45(Point(2, 10), 0, -1));
|
Chris@16
|
1114 reference.push_back(Vertex45(Point(10, 2), 0, -1));
|
Chris@16
|
1115 reference.push_back(Vertex45(Point(10, 2), 2, -1));
|
Chris@16
|
1116 reference.push_back(Vertex45(Point(10, 10), 2, 1));
|
Chris@16
|
1117 reference.push_back(Vertex45(Point(10, 10), 0, 1));
|
Chris@16
|
1118 if(result != reference) {
|
Chris@16
|
1119 stdcout << "result size == " << result.size() << "\n";
|
Chris@16
|
1120 for(std::size_t i = 0; i < result.size(); ++i) {
|
Chris@16
|
1121 //stdcout << "result == " << result[i]<< "\n";
|
Chris@16
|
1122 }
|
Chris@16
|
1123 stdcout << "reference size == " << reference.size() << "\n";
|
Chris@16
|
1124 for(std::size_t i = 0; i < reference.size(); ++i) {
|
Chris@16
|
1125 //stdcout << "reference == " << reference[i]<< "\n";
|
Chris@16
|
1126 }
|
Chris@16
|
1127 return false;
|
Chris@16
|
1128 }
|
Chris@16
|
1129 stdcout << "done testing Scan45And\n";
|
Chris@16
|
1130 return true;
|
Chris@16
|
1131 }
|
Chris@16
|
1132
|
Chris@16
|
1133 template <typename stream_type>
|
Chris@16
|
1134 static inline bool testScan45Star1(stream_type& stdcout) {
|
Chris@16
|
1135 stdcout << "testing Scan45Star1\n";
|
Chris@16
|
1136 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
|
Chris@16
|
1137 std::vector<Vertex45 > result;
|
Chris@16
|
1138 typedef std::pair<Point, Scan45Count> Scan45Vertex;
|
Chris@16
|
1139 std::vector<Scan45Vertex> vertices;
|
Chris@16
|
1140 //is a Rectnagle(0, 0, 10, 10);
|
Chris@16
|
1141 Count2 count(1, 0);
|
Chris@16
|
1142 Count2 ncount(-1, 0);
|
Chris@16
|
1143 vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0))));
|
Chris@16
|
1144 vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount)));
|
Chris@16
|
1145 vertices.push_back(Scan45Vertex(Point(8,16), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
|
Chris@16
|
1146 count = Count2(0, 1);
|
Chris@16
|
1147 ncount = count.invert();
|
Chris@16
|
1148 vertices.push_back(Scan45Vertex(Point(12,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0))));
|
Chris@16
|
1149 vertices.push_back(Scan45Vertex(Point(4,0), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
|
Chris@16
|
1150 vertices.push_back(Scan45Vertex(Point(4,16), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount)));
|
Chris@16
|
1151 sortScan45Vector(vertices);
|
Chris@16
|
1152 stdcout << "scanning\n";
|
Chris@16
|
1153 scan45.scan(result, vertices.begin(), vertices.end());
|
Chris@16
|
1154 stdcout << "done scanning\n";
|
Chris@16
|
1155 // result size == 24
|
Chris@16
|
1156 // result == 0 8 -1 1
|
Chris@16
|
1157 // result == 0 8 1 -1
|
Chris@16
|
1158 // result == 4 0 1 1
|
Chris@16
|
1159 // result == 4 0 2 1
|
Chris@16
|
1160 // result == 4 4 2 -1
|
Chris@16
|
1161 // result == 4 4 -1 -1
|
Chris@16
|
1162 // result == 4 12 1 1
|
Chris@16
|
1163 // result == 4 12 2 1
|
Chris@16
|
1164 // result == 4 16 2 -1
|
Chris@16
|
1165 // result == 4 16 -1 -1
|
Chris@16
|
1166 // result == 6 2 1 -1
|
Chris@16
|
1167 // result == 6 14 -1 1
|
Chris@16
|
1168 // result == 6 2 -1 1
|
Chris@16
|
1169 // result == 6 14 1 -1
|
Chris@16
|
1170 // result == 8 0 -1 -1
|
Chris@16
|
1171 // result == 8 0 2 -1
|
Chris@16
|
1172 // result == 8 4 2 1
|
Chris@16
|
1173 // result == 8 4 1 1
|
Chris@16
|
1174 // result == 8 12 -1 -1
|
Chris@16
|
1175 // result == 8 12 2 -1
|
Chris@16
|
1176 // result == 8 16 2 1
|
Chris@16
|
1177 // result == 8 16 1 1
|
Chris@16
|
1178 // result == 12 8 1 -1
|
Chris@16
|
1179 // result == 12 8 -1 1
|
Chris@16
|
1180 if(result.size() != 24) {
|
Chris@16
|
1181 //stdcout << "result size == " << result.size() << "\n";
|
Chris@16
|
1182 //stdcout << "reference size == " << 24 << "\n";
|
Chris@16
|
1183 return false;
|
Chris@16
|
1184 }
|
Chris@16
|
1185 stdcout << "done testing Scan45Star1\n";
|
Chris@16
|
1186 return true;
|
Chris@16
|
1187 }
|
Chris@16
|
1188
|
Chris@16
|
1189 template <typename stream_type>
|
Chris@16
|
1190 static inline bool testScan45Star2(stream_type& stdcout) {
|
Chris@16
|
1191 stdcout << "testing Scan45Star2\n";
|
Chris@16
|
1192 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
|
Chris@16
|
1193 std::vector<Vertex45 > result;
|
Chris@16
|
1194 typedef std::pair<Point, Scan45Count> Scan45Vertex;
|
Chris@16
|
1195 std::vector<Scan45Vertex> vertices;
|
Chris@16
|
1196 //is a Rectnagle(0, 0, 10, 10);
|
Chris@16
|
1197 Count2 count(1, 0);
|
Chris@16
|
1198 Count2 ncount(-1, 0);
|
Chris@16
|
1199 vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
|
Chris@16
|
1200 vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
|
Chris@16
|
1201 vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
|
Chris@16
|
1202 count = Count2(0, 1);
|
Chris@16
|
1203 ncount = count.invert();
|
Chris@16
|
1204 vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
|
Chris@16
|
1205 vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
|
Chris@16
|
1206 vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
|
Chris@16
|
1207 sortScan45Vector(vertices);
|
Chris@16
|
1208 stdcout << "scanning\n";
|
Chris@16
|
1209 scan45.scan(result, vertices.begin(), vertices.end());
|
Chris@16
|
1210 stdcout << "done scanning\n";
|
Chris@16
|
1211 // result size == 24
|
Chris@16
|
1212 // result == 0 4 0 1
|
Chris@16
|
1213 // result == 0 4 1 -1
|
Chris@16
|
1214 // result == 0 8 -1 1
|
Chris@16
|
1215 // result == 0 8 0 -1
|
Chris@16
|
1216 // result == 2 6 1 1
|
Chris@16
|
1217 // result == 2 6 -1 -1
|
Chris@16
|
1218 // result == 4 4 0 -1
|
Chris@16
|
1219 // result == 4 8 0 1
|
Chris@16
|
1220 // result == 4 4 -1 1
|
Chris@16
|
1221 // result == 4 8 1 -1
|
Chris@16
|
1222 // result == 8 0 -1 -1
|
Chris@16
|
1223 // result == 8 0 1 1
|
Chris@16
|
1224 // result == 8 12 1 1
|
Chris@16
|
1225 // result == 8 12 -1 -1
|
Chris@16
|
1226 // result == 12 4 1 -1
|
Chris@16
|
1227 // result == 12 8 -1 1
|
Chris@16
|
1228 // result == 12 4 0 1
|
Chris@16
|
1229 // result == 12 8 0 -1
|
Chris@16
|
1230 // result == 14 6 -1 -1
|
Chris@16
|
1231 // result == 14 6 1 1
|
Chris@16
|
1232 // result == 16 4 0 -1
|
Chris@16
|
1233 // result == 16 4 -1 1
|
Chris@16
|
1234 // result == 16 8 1 -1
|
Chris@16
|
1235 // result == 16 8 0 1
|
Chris@16
|
1236 if(result.size() != 24) {
|
Chris@16
|
1237 //std::cout << "result size == " << result.size() << "\n";
|
Chris@16
|
1238 //std::cout << "reference size == " << 24 << "\n";
|
Chris@16
|
1239 return false;
|
Chris@16
|
1240 }
|
Chris@16
|
1241 stdcout << "done testing Scan45Star2\n";
|
Chris@16
|
1242 return true;
|
Chris@16
|
1243 }
|
Chris@16
|
1244
|
Chris@16
|
1245 template <typename stream_type>
|
Chris@16
|
1246 static inline bool testScan45Star3(stream_type& stdcout) {
|
Chris@16
|
1247 stdcout << "testing Scan45Star3\n";
|
Chris@16
|
1248 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
|
Chris@16
|
1249 std::vector<Vertex45 > result;
|
Chris@16
|
1250 typedef std::pair<Point, Scan45Count> Scan45Vertex;
|
Chris@16
|
1251 std::vector<Scan45Vertex> vertices;
|
Chris@16
|
1252 //is a Rectnagle(0, 0, 10, 10);
|
Chris@16
|
1253 Count2 count(1, 0);
|
Chris@16
|
1254 Count2 ncount(-1, 0);
|
Chris@16
|
1255 vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0))));
|
Chris@16
|
1256 vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount)));
|
Chris@16
|
1257 vertices.push_back(Scan45Vertex(Point(8,16), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
|
Chris@16
|
1258
|
Chris@16
|
1259 vertices.push_back(Scan45Vertex(Point(6,0), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
|
Chris@16
|
1260 vertices.push_back(Scan45Vertex(Point(6,14), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
|
Chris@16
|
1261 vertices.push_back(Scan45Vertex(Point(12,0), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
|
Chris@16
|
1262 vertices.push_back(Scan45Vertex(Point(12,14), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
|
Chris@16
|
1263 count = Count2(0, 1);
|
Chris@16
|
1264 ncount = count.invert();
|
Chris@16
|
1265 vertices.push_back(Scan45Vertex(Point(12,8), Scan45Count(count, Count2(0, 0), ncount, Count2(0, 0))));
|
Chris@16
|
1266 vertices.push_back(Scan45Vertex(Point(4,0), Scan45Count(Count2(0, 0), Count2(0, 0), count, count)));
|
Chris@16
|
1267 vertices.push_back(Scan45Vertex(Point(4,16), Scan45Count(ncount, Count2(0, 0), Count2(0, 0), ncount)));
|
Chris@16
|
1268 sortScan45Vector(vertices);
|
Chris@16
|
1269 stdcout << "scanning\n";
|
Chris@16
|
1270 scan45.scan(result, vertices.begin(), vertices.end());
|
Chris@16
|
1271 stdcout << "done scanning\n";
|
Chris@16
|
1272 // result size == 28
|
Chris@16
|
1273 // result == 0 8 -1 1
|
Chris@16
|
1274 // result == 0 8 1 -1
|
Chris@16
|
1275 // result == 4 0 1 1
|
Chris@16
|
1276 // result == 4 0 2 1
|
Chris@16
|
1277 // result == 4 4 2 -1
|
Chris@16
|
1278 // result == 4 4 -1 -1
|
Chris@16
|
1279 // result == 4 12 1 1
|
Chris@16
|
1280 // result == 4 12 2 1
|
Chris@16
|
1281 // result == 4 16 2 -1
|
Chris@16
|
1282 // result == 4 16 -1 -1
|
Chris@16
|
1283 // result == 6 2 1 -1
|
Chris@16
|
1284 // result == 6 14 -1 1
|
Chris@16
|
1285 // result == 6 0 0 1
|
Chris@16
|
1286 // result == 6 0 2 1
|
Chris@16
|
1287 // result == 6 2 2 -1
|
Chris@16
|
1288 // result == 6 14 1 -1
|
Chris@16
|
1289 // result == 8 0 0 -1
|
Chris@16
|
1290 // result == 8 0 0 1
|
Chris@16
|
1291 // result == 8 14 0 -1
|
Chris@16
|
1292 // result == 8 14 2 -1
|
Chris@16
|
1293 // result == 8 16 2 1
|
Chris@16
|
1294 // result == 8 16 1 1
|
Chris@16
|
1295 // result == 12 0 0 -1
|
Chris@16
|
1296 // result == 12 0 2 -1
|
Chris@16
|
1297 // result == 12 8 2 1
|
Chris@16
|
1298 // result == 12 8 2 -1
|
Chris@16
|
1299 // result == 12 14 2 1
|
Chris@16
|
1300 // result == 12 14 0 1
|
Chris@16
|
1301 if(result.size() != 28) {
|
Chris@16
|
1302 //std::cout << "result size == " << result.size() << "\n";
|
Chris@16
|
1303 //std::cout << "reference size == " << 28 << "\n";
|
Chris@16
|
1304 return false;
|
Chris@16
|
1305 }
|
Chris@16
|
1306
|
Chris@16
|
1307 stdcout << "done testing Scan45Star3\n";
|
Chris@16
|
1308 return true;
|
Chris@16
|
1309 }
|
Chris@16
|
1310
|
Chris@16
|
1311
|
Chris@16
|
1312 template <typename stream_type>
|
Chris@16
|
1313 static inline bool testScan45Star4(stream_type& stdcout) {
|
Chris@16
|
1314 stdcout << "testing Scan45Star4\n";
|
Chris@16
|
1315 Scan45<Count2, boolean_op_45_output_functor<0> > scan45;
|
Chris@16
|
1316 std::vector<Vertex45 > result;
|
Chris@16
|
1317 typedef std::pair<Point, Scan45Count> Scan45Vertex;
|
Chris@16
|
1318 std::vector<Scan45Vertex> vertices;
|
Chris@16
|
1319 //is a Rectnagle(0, 0, 10, 10);
|
Chris@16
|
1320 Count2 count(1, 0);
|
Chris@16
|
1321 Count2 ncount(-1, 0);
|
Chris@16
|
1322 vertices.push_back(Scan45Vertex(Point(0,4), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
|
Chris@16
|
1323 vertices.push_back(Scan45Vertex(Point(16,4), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
|
Chris@16
|
1324 vertices.push_back(Scan45Vertex(Point(8,12), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
|
Chris@16
|
1325
|
Chris@16
|
1326 vertices.push_back(Scan45Vertex(Point(0,6), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
|
Chris@16
|
1327 vertices.push_back(Scan45Vertex(Point(0,12), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
|
Chris@16
|
1328 vertices.push_back(Scan45Vertex(Point(16,6), Scan45Count(Count2(0, 0), ncount, Count2(0, 0), ncount)));
|
Chris@16
|
1329 vertices.push_back(Scan45Vertex(Point(16,12), Scan45Count(Count2(0, 0), count, Count2(0, 0), count)));
|
Chris@16
|
1330 count = Count2(0, 1);
|
Chris@16
|
1331 ncount = count.invert();
|
Chris@16
|
1332 vertices.push_back(Scan45Vertex(Point(0,8), Scan45Count(count, ncount, Count2(0, 0), Count2(0, 0))));
|
Chris@16
|
1333 vertices.push_back(Scan45Vertex(Point(16,8), Scan45Count(Count2(0, 0), count, ncount, Count2(0, 0))));
|
Chris@16
|
1334 vertices.push_back(Scan45Vertex(Point(8,0), Scan45Count(ncount, Count2(0, 0), count, Count2(0, 0))));
|
Chris@16
|
1335 sortScan45Vector(vertices);
|
Chris@16
|
1336 stdcout << "scanning\n";
|
Chris@16
|
1337 scan45.scan(result, vertices.begin(), vertices.end());
|
Chris@16
|
1338 stdcout << "done scanning\n";
|
Chris@16
|
1339 // result size == 28
|
Chris@16
|
1340 // result == 0 4 0 1
|
Chris@16
|
1341 // result == 0 4 1 -1
|
Chris@16
|
1342 // result == 0 6 0 1
|
Chris@16
|
1343 // result == 0 6 2 1
|
Chris@16
|
1344 // result == 0 8 2 -1
|
Chris@16
|
1345 // result == 0 8 2 1
|
Chris@16
|
1346 // result == 0 12 2 -1
|
Chris@16
|
1347 // result == 0 12 0 -1
|
Chris@16
|
1348 // result == 2 6 1 1
|
Chris@16
|
1349 // result == 2 6 0 -1
|
Chris@16
|
1350 // result == 4 4 0 -1
|
Chris@16
|
1351 // result == 4 4 -1 1
|
Chris@16
|
1352 // result == 8 12 0 1
|
Chris@16
|
1353 // result == 8 0 -1 -1
|
Chris@16
|
1354 // result == 8 0 1 1
|
Chris@16
|
1355 // result == 8 12 0 -1
|
Chris@16
|
1356 // result == 12 4 1 -1
|
Chris@16
|
1357 // result == 12 4 0 1
|
Chris@16
|
1358 // result == 14 6 -1 -1
|
Chris@16
|
1359 // result == 14 6 0 1
|
Chris@16
|
1360 // result == 16 4 0 -1
|
Chris@16
|
1361 // result == 16 4 -1 1
|
Chris@16
|
1362 // result == 16 6 0 -1
|
Chris@16
|
1363 // result == 16 6 2 -1
|
Chris@16
|
1364 // result == 16 8 2 1
|
Chris@16
|
1365 // result == 16 8 2 -1
|
Chris@16
|
1366 // result == 16 12 2 1
|
Chris@16
|
1367 // result == 16 12 0 1
|
Chris@16
|
1368 if(result.size() != 28) {
|
Chris@16
|
1369 //stdcout << "result size == " << result.size() << "\n";
|
Chris@16
|
1370 //stdcout << "reference size == " << 28 << "\n";
|
Chris@16
|
1371 return false;
|
Chris@16
|
1372 }
|
Chris@16
|
1373
|
Chris@16
|
1374 stdcout << "done testing Scan45Star4\n";
|
Chris@16
|
1375 return true;
|
Chris@16
|
1376 }
|
Chris@16
|
1377
|
Chris@16
|
1378 template <typename stream_type>
|
Chris@16
|
1379 static inline bool testScan45(stream_type& stdcout) {
|
Chris@16
|
1380 if(!testScan45Rect(stdcout)) return false;
|
Chris@16
|
1381 if(!testScan45P1(stdcout)) return false;
|
Chris@16
|
1382 if(!testScan45P2(stdcout)) return false;
|
Chris@16
|
1383 if(!testScan45And(stdcout)) return false;
|
Chris@16
|
1384 if(!testScan45Star1(stdcout)) return false;
|
Chris@16
|
1385 if(!testScan45Star2(stdcout)) return false;
|
Chris@16
|
1386 if(!testScan45Star3(stdcout)) return false;
|
Chris@16
|
1387 if(!testScan45Star4(stdcout)) return false;
|
Chris@16
|
1388 return true;
|
Chris@16
|
1389 }
|
Chris@16
|
1390
|
Chris@16
|
1391 };
|
Chris@16
|
1392
|
Chris@16
|
1393 }
|
Chris@16
|
1394
|
Chris@16
|
1395 }
|
Chris@16
|
1396 #endif
|