Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/polygon/detail/boolean_op.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 /* | |
2 Copyright 2008 Intel Corporation | |
3 | |
4 Use, modification and distribution are subject to the Boost Software License, | |
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
6 http://www.boost.org/LICENSE_1_0.txt). | |
7 */ | |
8 #ifndef BOOST_POLYGON_BOOLEAN_OP_HPP | |
9 #define BOOST_POLYGON_BOOLEAN_OP_HPP | |
10 namespace boost { namespace polygon{ | |
11 namespace boolean_op { | |
12 | |
13 //BooleanOp is the generic boolean operation scanline algorithm that provides | |
14 //all the simple boolean set operations on manhattan data. By templatizing | |
15 //the intersection count of the input and algorithm internals it is extensible | |
16 //to multi-layer scans, properties and other advanced scanline operations above | |
17 //and beyond simple booleans. | |
18 //T must cast to int | |
19 template <class T, typename Unit> | |
20 class BooleanOp { | |
21 public: | |
22 typedef std::map<Unit, T> ScanData; | |
23 typedef std::pair<Unit, T> ElementType; | |
24 protected: | |
25 ScanData scanData_; | |
26 typename ScanData::iterator nextItr_; | |
27 T nullT_; | |
28 public: | |
29 inline BooleanOp () : scanData_(), nextItr_(), nullT_() { nextItr_ = scanData_.end(); nullT_ = 0; } | |
30 inline BooleanOp (T nullT) : scanData_(), nextItr_(), nullT_(nullT) { nextItr_ = scanData_.end(); } | |
31 inline BooleanOp (const BooleanOp& that) : scanData_(that.scanData_), nextItr_(), | |
32 nullT_(that.nullT_) { nextItr_ = scanData_.begin(); } | |
33 inline BooleanOp& operator=(const BooleanOp& that); | |
34 | |
35 //moves scanline forward | |
36 inline void advanceScan() { nextItr_ = scanData_.begin(); } | |
37 | |
38 //proceses the given interval and T data | |
39 //appends output edges to cT | |
40 template <class cT> | |
41 inline void processInterval(cT& outputContainer, interval_data<Unit> ivl, T deltaCount); | |
42 | |
43 private: | |
44 inline typename ScanData::iterator lookup_(Unit pos){ | |
45 if(nextItr_ != scanData_.end() && nextItr_->first >= pos) { | |
46 return nextItr_; | |
47 } | |
48 return nextItr_ = scanData_.lower_bound(pos); | |
49 } | |
50 inline typename ScanData::iterator insert_(Unit pos, T count){ | |
51 return nextItr_ = scanData_.insert(nextItr_, ElementType(pos, count)); | |
52 } | |
53 template <class cT> | |
54 inline void evaluateInterval_(cT& outputContainer, interval_data<Unit> ivl, T beforeCount, T afterCount); | |
55 }; | |
56 | |
57 class BinaryAnd { | |
58 public: | |
59 inline BinaryAnd() {} | |
60 inline bool operator()(int a, int b) { return (a > 0) & (b > 0); } | |
61 }; | |
62 class BinaryOr { | |
63 public: | |
64 inline BinaryOr() {} | |
65 inline bool operator()(int a, int b) { return (a > 0) | (b > 0); } | |
66 }; | |
67 class BinaryNot { | |
68 public: | |
69 inline BinaryNot() {} | |
70 inline bool operator()(int a, int b) { return (a > 0) & !(b > 0); } | |
71 }; | |
72 class BinaryXor { | |
73 public: | |
74 inline BinaryXor() {} | |
75 inline bool operator()(int a, int b) { return (a > 0) ^ (b > 0); } | |
76 }; | |
77 | |
78 //BinaryCount is an array of two deltaCounts coming from two different layers | |
79 //of scan event data. It is the merged count of the two suitable for consumption | |
80 //as the template argument of the BooleanOp algorithm because BinaryCount casts to int. | |
81 //T is a binary functor object that evaluates the array of counts and returns a logical | |
82 //result of some operation on those values. | |
83 //BinaryCount supports many of the operators that work with int, particularly the | |
84 //binary operators, but cannot support less than or increment. | |
85 template <class T> | |
86 class BinaryCount { | |
87 public: | |
88 inline BinaryCount() | |
89 #ifndef BOOST_POLYGON_MSVC | |
90 : counts_() | |
91 #endif | |
92 { counts_[0] = counts_[1] = 0; } | |
93 // constructs from two integers | |
94 inline BinaryCount(int countL, int countR) | |
95 #ifndef BOOST_POLYGON_MSVC | |
96 : counts_() | |
97 #endif | |
98 { counts_[0] = countL, counts_[1] = countR; } | |
99 inline BinaryCount& operator=(int count) { counts_[0] = count, counts_[1] = count; return *this; } | |
100 inline BinaryCount& operator=(const BinaryCount& that); | |
101 inline BinaryCount(const BinaryCount& that) | |
102 #ifndef BOOST_POLYGON_MSVC | |
103 : counts_() | |
104 #endif | |
105 { *this = that; } | |
106 inline bool operator==(const BinaryCount& that) const; | |
107 inline bool operator!=(const BinaryCount& that) const { return !((*this) == that);} | |
108 inline BinaryCount& operator+=(const BinaryCount& that); | |
109 inline BinaryCount& operator-=(const BinaryCount& that); | |
110 inline BinaryCount operator+(const BinaryCount& that) const; | |
111 inline BinaryCount operator-(const BinaryCount& that) const; | |
112 inline BinaryCount operator-() const; | |
113 inline int& operator[](bool index) { return counts_[index]; } | |
114 | |
115 //cast to int operator evaluates data using T binary functor | |
116 inline operator int() const { return T()(counts_[0], counts_[1]); } | |
117 private: | |
118 int counts_[2]; | |
119 }; | |
120 | |
121 class UnaryCount { | |
122 public: | |
123 inline UnaryCount() : count_(0) {} | |
124 // constructs from two integers | |
125 inline explicit UnaryCount(int count) : count_(count) {} | |
126 inline UnaryCount& operator=(int count) { count_ = count; return *this; } | |
127 inline UnaryCount& operator=(const UnaryCount& that) { count_ = that.count_; return *this; } | |
128 inline UnaryCount(const UnaryCount& that) : count_(that.count_) {} | |
129 inline bool operator==(const UnaryCount& that) const { return count_ == that.count_; } | |
130 inline bool operator!=(const UnaryCount& that) const { return !((*this) == that);} | |
131 inline UnaryCount& operator+=(const UnaryCount& that) { count_ += that.count_; return *this; } | |
132 inline UnaryCount& operator-=(const UnaryCount& that) { count_ -= that.count_; return *this; } | |
133 inline UnaryCount operator+(const UnaryCount& that) const { UnaryCount tmp(*this); tmp += that; return tmp; } | |
134 inline UnaryCount operator-(const UnaryCount& that) const { UnaryCount tmp(*this); tmp -= that; return tmp; } | |
135 inline UnaryCount operator-() const { UnaryCount tmp; return tmp - *this; } | |
136 | |
137 //cast to int operator evaluates data using T binary functor | |
138 inline operator int() const { return count_ % 2; } | |
139 private: | |
140 int count_; | |
141 }; | |
142 | |
143 template <class T, typename Unit> | |
144 inline BooleanOp<T, Unit>& BooleanOp<T, Unit>::operator=(const BooleanOp& that) { | |
145 scanData_ = that.scanData_; | |
146 nextItr_ = scanData_.begin(); | |
147 nullT_ = that.nullT_; | |
148 return *this; | |
149 } | |
150 | |
151 //appends output edges to cT | |
152 template <class T, typename Unit> | |
153 template <class cT> | |
154 inline void BooleanOp<T, Unit>::processInterval(cT& outputContainer, interval_data<Unit> ivl, T deltaCount) { | |
155 typename ScanData::iterator lowItr = lookup_(ivl.low()); | |
156 typename ScanData::iterator highItr = lookup_(ivl.high()); | |
157 //add interval to scan data if it is past the end | |
158 if(lowItr == scanData_.end()) { | |
159 lowItr = insert_(ivl.low(), deltaCount); | |
160 highItr = insert_(ivl.high(), nullT_); | |
161 evaluateInterval_(outputContainer, ivl, nullT_, deltaCount); | |
162 return; | |
163 } | |
164 //ensure that highItr points to the end of the ivl | |
165 if(highItr == scanData_.end() || (*highItr).first > ivl.high()) { | |
166 T value = nullT_; | |
167 if(highItr != scanData_.begin()) { | |
168 --highItr; | |
169 value = highItr->second; | |
170 } | |
171 nextItr_ = highItr; | |
172 highItr = insert_(ivl.high(), value); | |
173 } | |
174 //split the low interval if needed | |
175 if(lowItr->first > ivl.low()) { | |
176 if(lowItr != scanData_.begin()) { | |
177 --lowItr; | |
178 nextItr_ = lowItr; | |
179 lowItr = insert_(ivl.low(), lowItr->second); | |
180 } else { | |
181 nextItr_ = lowItr; | |
182 lowItr = insert_(ivl.low(), nullT_); | |
183 } | |
184 } | |
185 //process scan data intersecting interval | |
186 for(typename ScanData::iterator itr = lowItr; itr != highItr; ){ | |
187 T beforeCount = itr->second; | |
188 T afterCount = itr->second += deltaCount; | |
189 Unit low = itr->first; | |
190 ++itr; | |
191 Unit high = itr->first; | |
192 evaluateInterval_(outputContainer, interval_data<Unit>(low, high), beforeCount, afterCount); | |
193 } | |
194 //merge the bottom interval with the one below if they have the same count | |
195 if(lowItr != scanData_.begin()){ | |
196 typename ScanData::iterator belowLowItr = lowItr; | |
197 --belowLowItr; | |
198 if(belowLowItr->second == lowItr->second) { | |
199 scanData_.erase(lowItr); | |
200 } | |
201 } | |
202 //merge the top interval with the one above if they have the same count | |
203 if(highItr != scanData_.begin()) { | |
204 typename ScanData::iterator beforeHighItr = highItr; | |
205 --beforeHighItr; | |
206 if(beforeHighItr->second == highItr->second) { | |
207 scanData_.erase(highItr); | |
208 highItr = beforeHighItr; | |
209 ++highItr; | |
210 } | |
211 } | |
212 nextItr_ = highItr; | |
213 } | |
214 | |
215 template <class T, typename Unit> | |
216 template <class cT> | |
217 inline void BooleanOp<T, Unit>::evaluateInterval_(cT& outputContainer, interval_data<Unit> ivl, | |
218 T beforeCount, T afterCount) { | |
219 bool before = (int)beforeCount > 0; | |
220 bool after = (int)afterCount > 0; | |
221 int value = (!before & after) - (before & !after); | |
222 if(value) { | |
223 outputContainer.insert(outputContainer.end(), std::pair<interval_data<Unit>, int>(ivl, value)); | |
224 } | |
225 } | |
226 | |
227 template <class T> | |
228 inline BinaryCount<T>& BinaryCount<T>::operator=(const BinaryCount<T>& that) { | |
229 counts_[0] = that.counts_[0]; | |
230 counts_[1] = that.counts_[1]; | |
231 return *this; | |
232 } | |
233 template <class T> | |
234 inline bool BinaryCount<T>::operator==(const BinaryCount<T>& that) const { | |
235 return counts_[0] == that.counts_[0] && | |
236 counts_[1] == that.counts_[1]; | |
237 } | |
238 template <class T> | |
239 inline BinaryCount<T>& BinaryCount<T>::operator+=(const BinaryCount<T>& that) { | |
240 counts_[0] += that.counts_[0]; | |
241 counts_[1] += that.counts_[1]; | |
242 return *this; | |
243 } | |
244 template <class T> | |
245 inline BinaryCount<T>& BinaryCount<T>::operator-=(const BinaryCount<T>& that) { | |
246 counts_[0] += that.counts_[0]; | |
247 counts_[1] += that.counts_[1]; | |
248 return *this; | |
249 } | |
250 template <class T> | |
251 inline BinaryCount<T> BinaryCount<T>::operator+(const BinaryCount<T>& that) const { | |
252 BinaryCount retVal(*this); | |
253 retVal += that; | |
254 return retVal; | |
255 } | |
256 template <class T> | |
257 inline BinaryCount<T> BinaryCount<T>::operator-(const BinaryCount<T>& that) const { | |
258 BinaryCount retVal(*this); | |
259 retVal -= that; | |
260 return retVal; | |
261 } | |
262 template <class T> | |
263 inline BinaryCount<T> BinaryCount<T>::operator-() const { | |
264 return BinaryCount<T>() - *this; | |
265 } | |
266 | |
267 | |
268 template <class T, typename Unit, typename iterator_type_1, typename iterator_type_2> | |
269 inline void applyBooleanBinaryOp(std::vector<std::pair<Unit, std::pair<Unit, int> > >& output, | |
270 //const std::vector<std::pair<Unit, std::pair<Unit, int> > >& input1, | |
271 //const std::vector<std::pair<Unit, std::pair<Unit, int> > >& input2, | |
272 iterator_type_1 itr1, iterator_type_1 itr1_end, | |
273 iterator_type_2 itr2, iterator_type_2 itr2_end, | |
274 T defaultCount) { | |
275 BooleanOp<T, Unit> boolean(defaultCount); | |
276 //typename std::vector<std::pair<Unit, std::pair<Unit, int> > >::const_iterator itr1 = input1.begin(); | |
277 //typename std::vector<std::pair<Unit, std::pair<Unit, int> > >::const_iterator itr2 = input2.begin(); | |
278 std::vector<std::pair<interval_data<Unit>, int> > container; | |
279 //output.reserve((std::max)(input1.size(), input2.size())); | |
280 | |
281 //consider eliminating dependecy on limits with bool flag for initial state | |
282 Unit UnitMax = (std::numeric_limits<Unit>::max)(); | |
283 Unit prevCoord = UnitMax; | |
284 Unit prevPosition = UnitMax; | |
285 T count(defaultCount); | |
286 //define the starting point | |
287 if(itr1 != itr1_end) { | |
288 prevCoord = (*itr1).first; | |
289 prevPosition = (*itr1).second.first; | |
290 count[0] += (*itr1).second.second; | |
291 } | |
292 if(itr2 != itr2_end) { | |
293 if((*itr2).first < prevCoord || | |
294 ((*itr2).first == prevCoord && (*itr2).second.first < prevPosition)) { | |
295 prevCoord = (*itr2).first; | |
296 prevPosition = (*itr2).second.first; | |
297 count = defaultCount; | |
298 count[1] += (*itr2).second.second; | |
299 ++itr2; | |
300 } else if((*itr2).first == prevCoord && (*itr2).second.first == prevPosition) { | |
301 count[1] += (*itr2).second.second; | |
302 ++itr2; | |
303 if(itr1 != itr1_end) ++itr1; | |
304 } else { | |
305 if(itr1 != itr1_end) ++itr1; | |
306 } | |
307 } else { | |
308 if(itr1 != itr1_end) ++itr1; | |
309 } | |
310 | |
311 while(itr1 != itr1_end || itr2 != itr2_end) { | |
312 Unit curCoord = UnitMax; | |
313 Unit curPosition = UnitMax; | |
314 T curCount(defaultCount); | |
315 if(itr1 != itr1_end) { | |
316 curCoord = (*itr1).first; | |
317 curPosition = (*itr1).second.first; | |
318 curCount[0] += (*itr1).second.second; | |
319 } | |
320 if(itr2 != itr2_end) { | |
321 if((*itr2).first < curCoord || | |
322 ((*itr2).first == curCoord && (*itr2).second.first < curPosition)) { | |
323 curCoord = (*itr2).first; | |
324 curPosition = (*itr2).second.first; | |
325 curCount = defaultCount; | |
326 curCount[1] += (*itr2).second.second; | |
327 ++itr2; | |
328 } else if((*itr2).first == curCoord && (*itr2).second.first == curPosition) { | |
329 curCount[1] += (*itr2).second.second; | |
330 ++itr2; | |
331 if(itr1 != itr1_end) ++itr1; | |
332 } else { | |
333 if(itr1 != itr1_end) ++itr1; | |
334 } | |
335 } else { | |
336 ++itr1; | |
337 } | |
338 | |
339 if(prevCoord != curCoord) { | |
340 boolean.advanceScan(); | |
341 prevCoord = curCoord; | |
342 prevPosition = curPosition; | |
343 count = curCount; | |
344 continue; | |
345 } | |
346 if(curPosition != prevPosition && count != defaultCount) { | |
347 interval_data<Unit> ivl(prevPosition, curPosition); | |
348 container.clear(); | |
349 boolean.processInterval(container, ivl, count); | |
350 for(std::size_t i = 0; i < container.size(); ++i) { | |
351 std::pair<interval_data<Unit>, int>& element = container[i]; | |
352 if(!output.empty() && output.back().first == prevCoord && | |
353 output.back().second.first == element.first.low() && | |
354 output.back().second.second == element.second * -1) { | |
355 output.pop_back(); | |
356 } else { | |
357 output.push_back(std::pair<Unit, std::pair<Unit, int> >(prevCoord, std::pair<Unit, int>(element.first.low(), | |
358 element.second))); | |
359 } | |
360 output.push_back(std::pair<Unit, std::pair<Unit, int> >(prevCoord, std::pair<Unit, int>(element.first.high(), | |
361 element.second * -1))); | |
362 } | |
363 } | |
364 prevPosition = curPosition; | |
365 count += curCount; | |
366 } | |
367 } | |
368 | |
369 template <class T, typename Unit> | |
370 inline void applyBooleanBinaryOp(std::vector<std::pair<Unit, std::pair<Unit, int> > >& inputOutput, | |
371 const std::vector<std::pair<Unit, std::pair<Unit, int> > >& input2, | |
372 T defaultCount) { | |
373 std::vector<std::pair<Unit, std::pair<Unit, int> > > output; | |
374 applyBooleanBinaryOp(output, inputOutput, input2, defaultCount); | |
375 if(output.size() < inputOutput.size() / 2) { | |
376 inputOutput = std::vector<std::pair<Unit, std::pair<Unit, int> > >(); | |
377 } else { | |
378 inputOutput.clear(); | |
379 } | |
380 inputOutput.insert(inputOutput.end(), output.begin(), output.end()); | |
381 } | |
382 | |
383 template <typename Unit> | |
384 inline void applyUnaryXOr(std::vector<std::pair<Unit, std::pair<Unit, int> > >& input) { | |
385 BooleanOp<UnaryCount, Unit> booleanXOr; | |
386 | |
387 } | |
388 | |
389 template <typename count_type = int> | |
390 struct default_arg_workaround { | |
391 template <typename Unit> | |
392 static inline void applyBooleanOr(std::vector<std::pair<Unit, std::pair<Unit, int> > >& input) { | |
393 BooleanOp<count_type, Unit> booleanOr; | |
394 std::vector<std::pair<interval_data<Unit>, int> > container; | |
395 std::vector<std::pair<Unit, std::pair<Unit, int> > > output; | |
396 output.reserve(input.size()); | |
397 //consider eliminating dependecy on limits with bool flag for initial state | |
398 Unit UnitMax = (std::numeric_limits<Unit>::max)(); | |
399 Unit prevPos = UnitMax; | |
400 Unit prevY = UnitMax; | |
401 int count = 0; | |
402 for(typename std::vector<std::pair<Unit, std::pair<Unit, int> > >::iterator itr = input.begin(); | |
403 itr != input.end(); ++itr) { | |
404 Unit pos = (*itr).first; | |
405 Unit y = (*itr).second.first; | |
406 if(pos != prevPos) { | |
407 booleanOr.advanceScan(); | |
408 prevPos = pos; | |
409 prevY = y; | |
410 count = (*itr).second.second; | |
411 continue; | |
412 } | |
413 if(y != prevY && count != 0) { | |
414 interval_data<Unit> ivl(prevY, y); | |
415 container.clear(); | |
416 booleanOr.processInterval(container, ivl, count_type(count)); | |
417 for(std::size_t i = 0; i < container.size(); ++i) { | |
418 std::pair<interval_data<Unit>, int>& element = container[i]; | |
419 if(!output.empty() && output.back().first == prevPos && | |
420 output.back().second.first == element.first.low() && | |
421 output.back().second.second == element.second * -1) { | |
422 output.pop_back(); | |
423 } else { | |
424 output.push_back(std::pair<Unit, std::pair<Unit, int> >(prevPos, std::pair<Unit, int>(element.first.low(), | |
425 element.second))); | |
426 } | |
427 output.push_back(std::pair<Unit, std::pair<Unit, int> >(prevPos, std::pair<Unit, int>(element.first.high(), | |
428 element.second * -1))); | |
429 } | |
430 } | |
431 prevY = y; | |
432 count += (*itr).second.second; | |
433 } | |
434 if(output.size() < input.size() / 2) { | |
435 input = std::vector<std::pair<Unit, std::pair<Unit, int> > >(); | |
436 } else { | |
437 input.clear(); | |
438 } | |
439 input.insert(input.end(), output.begin(), output.end()); | |
440 } | |
441 }; | |
442 | |
443 } | |
444 | |
445 } | |
446 | |
447 } | |
448 #endif |