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