annotate DEPENDENCIES/generic/include/boost/polygon/detail/polygon_90_touch.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
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_POLYGON_90_TOUCH_HPP
Chris@16 9 #define BOOST_POLYGON_POLYGON_90_TOUCH_HPP
Chris@16 10 namespace boost { namespace polygon{
Chris@16 11
Chris@16 12 template <typename Unit>
Chris@16 13 struct touch_90_operation {
Chris@16 14 typedef interval_data<Unit> Interval;
Chris@16 15
Chris@16 16 class TouchScanEvent {
Chris@16 17 private:
Chris@16 18 typedef std::map<Unit, std::set<int> > EventData;
Chris@16 19 EventData eventData_;
Chris@16 20 public:
Chris@16 21
Chris@16 22 // The TouchScanEvent::iterator is a lazy algorithm that accumulates
Chris@16 23 // polygon ids in a set as it is incremented through the
Chris@16 24 // scan event data structure.
Chris@16 25 // The iterator provides a forward iterator semantic only.
Chris@16 26 class iterator {
Chris@16 27 private:
Chris@16 28 typename EventData::const_iterator itr_;
Chris@16 29 std::pair<Interval, std::set<int> > ivlIds_;
Chris@16 30 bool incremented_;
Chris@16 31 public:
Chris@16 32 inline iterator() : itr_(), ivlIds_(), incremented_(false) {}
Chris@16 33 inline iterator(typename EventData::const_iterator itr,
Chris@16 34 Unit prevPos, Unit curPos, const std::set<int>& ivlIds) : itr_(itr), ivlIds_(), incremented_(false) {
Chris@16 35 ivlIds_.second = ivlIds;
Chris@16 36 ivlIds_.first = Interval(prevPos, curPos);
Chris@16 37 }
Chris@16 38 inline iterator(const iterator& that) : itr_(), ivlIds_(), incremented_(false) { (*this) = that; }
Chris@16 39 inline iterator& operator=(const iterator& that) {
Chris@16 40 itr_ = that.itr_;
Chris@16 41 ivlIds_.first = that.ivlIds_.first;
Chris@16 42 ivlIds_.second = that.ivlIds_.second;
Chris@16 43 incremented_ = that.incremented_;
Chris@16 44 return *this;
Chris@16 45 }
Chris@16 46 inline bool operator==(const iterator& that) { return itr_ == that.itr_; }
Chris@16 47 inline bool operator!=(const iterator& that) { return itr_ != that.itr_; }
Chris@16 48 inline iterator& operator++() {
Chris@16 49 //std::cout << "increment\n";
Chris@16 50 //std::cout << "state\n";
Chris@16 51 //for(std::set<int>::iterator itr = ivlIds_.second.begin(); itr != ivlIds_.second.end(); ++itr) {
Chris@16 52 // std::cout << (*itr) << " ";
Chris@16 53 //} std::cout << std::endl;
Chris@16 54 //std::cout << "update\n";
Chris@16 55 for(std::set<int>::const_iterator itr = (*itr_).second.begin();
Chris@16 56 itr != (*itr_).second.end(); ++itr) {
Chris@16 57 //std::cout << (*itr) << " ";
Chris@16 58 std::set<int>::iterator lb = ivlIds_.second.find(*itr);
Chris@16 59 if(lb != ivlIds_.second.end()) {
Chris@16 60 ivlIds_.second.erase(lb);
Chris@16 61 } else {
Chris@16 62 ivlIds_.second.insert(*itr);
Chris@16 63 }
Chris@16 64 }
Chris@16 65 //std::cout << std::endl;
Chris@16 66 //std::cout << "new state\n";
Chris@16 67 //for(std::set<int>::iterator itr = ivlIds_.second.begin(); itr != ivlIds_.second.end(); ++itr) {
Chris@16 68 // std::cout << (*itr) << " ";
Chris@16 69 //} std::cout << std::endl;
Chris@16 70 ++itr_;
Chris@16 71 //ivlIds_.first = Interval(ivlIds_.first.get(HIGH), itr_->first);
Chris@16 72 incremented_ = true;
Chris@16 73 return *this;
Chris@16 74 }
Chris@16 75 inline const iterator operator++(int){
Chris@16 76 iterator tmpItr(*this);
Chris@16 77 ++(*this);
Chris@16 78 return tmpItr;
Chris@16 79 }
Chris@16 80 inline std::pair<Interval, std::set<int> >& operator*() {
Chris@16 81 if(incremented_) ivlIds_.first = Interval(ivlIds_.first.get(HIGH), itr_->first);
Chris@16 82 incremented_ = false;
Chris@16 83 if(ivlIds_.second.empty())(++(*this));
Chris@16 84 if(incremented_) ivlIds_.first = Interval(ivlIds_.first.get(HIGH), itr_->first);
Chris@16 85 incremented_ = false;
Chris@16 86 return ivlIds_; }
Chris@16 87 };
Chris@16 88
Chris@16 89 inline TouchScanEvent() : eventData_() {}
Chris@16 90 template<class iT>
Chris@16 91 inline TouchScanEvent(iT begin, iT end) : eventData_() {
Chris@16 92 for( ; begin != end; ++begin){
Chris@16 93 insert(*begin);
Chris@16 94 }
Chris@16 95 }
Chris@16 96 inline TouchScanEvent(const TouchScanEvent& that) : eventData_(that.eventData_) {}
Chris@16 97 inline TouchScanEvent& operator=(const TouchScanEvent& that){
Chris@16 98 eventData_ = that.eventData_;
Chris@16 99 return *this;
Chris@16 100 }
Chris@16 101
Chris@16 102 //Insert an interval polygon id into the EventData
Chris@16 103 inline void insert(const std::pair<Interval, int>& intervalId){
Chris@16 104 insert(intervalId.first.low(), intervalId.second);
Chris@16 105 insert(intervalId.first.high(), intervalId.second);
Chris@16 106 }
Chris@16 107
Chris@16 108 //Insert an position and polygon id into EventData
Chris@16 109 inline void insert(Unit pos, int id) {
Chris@16 110 typename EventData::iterator lb = eventData_.lower_bound(pos);
Chris@16 111 if(lb != eventData_.end() && lb->first == pos) {
Chris@16 112 std::set<int>& mr (lb->second);
Chris@16 113 std::set<int>::iterator mri = mr.find(id);
Chris@16 114 if(mri == mr.end()) {
Chris@16 115 mr.insert(id);
Chris@16 116 } else {
Chris@16 117 mr.erase(id);
Chris@16 118 }
Chris@16 119 } else {
Chris@16 120 lb = eventData_.insert(lb, std::pair<Unit, std::set<int> >(pos, std::set<int>()));
Chris@16 121 (*lb).second.insert(id);
Chris@16 122 }
Chris@16 123 }
Chris@16 124
Chris@16 125 //merge this scan event with that by inserting its data
Chris@16 126 inline void insert(const TouchScanEvent& that){
Chris@16 127 typename EventData::const_iterator itr;
Chris@16 128 for(itr = that.eventData_.begin(); itr != that.eventData_.end(); ++itr) {
Chris@16 129 eventData_[(*itr).first].insert(itr->second.begin(), itr->second.end());
Chris@16 130 }
Chris@16 131 }
Chris@16 132
Chris@16 133 //Get the begin iterator over event data
Chris@16 134 inline iterator begin() const {
Chris@16 135 //std::cout << "begin\n";
Chris@16 136 if(eventData_.empty()) return end();
Chris@16 137 typename EventData::const_iterator itr = eventData_.begin();
Chris@16 138 Unit pos = itr->first;
Chris@16 139 const std::set<int>& idr = itr->second;
Chris@16 140 ++itr;
Chris@16 141 return iterator(itr, pos, itr->first, idr);
Chris@16 142 }
Chris@16 143
Chris@16 144 //Get the end iterator over event data
Chris@16 145 inline iterator end() const { return iterator(eventData_.end(), 0, 0, std::set<int>()); }
Chris@16 146
Chris@16 147 inline void clear() { eventData_.clear(); }
Chris@16 148
Chris@16 149 inline Interval extents() const {
Chris@16 150 if(eventData_.empty()) return Interval();
Chris@16 151 return Interval((*(eventData_.begin())).first, (*(eventData_.rbegin())).first);
Chris@16 152 }
Chris@16 153 };
Chris@16 154
Chris@16 155 //declaration of a map of scan events by coordinate value used to store all the
Chris@16 156 //polygon data for a single layer input into the scanline algorithm
Chris@16 157 typedef std::pair<std::map<Unit, TouchScanEvent>, std::map<Unit, TouchScanEvent> > TouchSetData;
Chris@16 158
Chris@16 159 class TouchOp {
Chris@16 160 public:
Chris@16 161 typedef std::map<Unit, std::set<int> > ScanData;
Chris@16 162 typedef std::pair<Unit, std::set<int> > ElementType;
Chris@16 163 protected:
Chris@16 164 ScanData scanData_;
Chris@16 165 typename ScanData::iterator nextItr_;
Chris@16 166 public:
Chris@16 167 inline TouchOp () : scanData_(), nextItr_() { nextItr_ = scanData_.end(); }
Chris@16 168 inline TouchOp (const TouchOp& that) : scanData_(that.scanData_), nextItr_() { nextItr_ = scanData_.begin(); }
Chris@16 169 inline TouchOp& operator=(const TouchOp& that);
Chris@16 170
Chris@16 171 //moves scanline forward
Chris@16 172 inline void advanceScan() { nextItr_ = scanData_.begin(); }
Chris@16 173
Chris@16 174 //proceses the given interval and std::set<int> data
Chris@16 175 //the output data structre is a graph, the indicies in the vector correspond to graph nodes,
Chris@16 176 //the integers in the set are vector indicies and are the nodes with which that node shares an edge
Chris@16 177 template <typename graphT>
Chris@16 178 inline void processInterval(graphT& outputContainer, Interval ivl, const std::set<int>& ids, bool leadingEdge) {
Chris@16 179 //print();
Chris@16 180 typename ScanData::iterator lowItr = lookup_(ivl.low());
Chris@16 181 typename ScanData::iterator highItr = lookup_(ivl.high());
Chris@16 182 //std::cout << "Interval: " << ivl << std::endl;
Chris@16 183 //for(std::set<int>::const_iterator itr = ids.begin(); itr != ids.end(); ++itr)
Chris@16 184 // std::cout << (*itr) << " ";
Chris@16 185 //std::cout << std::endl;
Chris@16 186 //add interval to scan data if it is past the end
Chris@16 187 if(lowItr == scanData_.end()) {
Chris@16 188 //std::cout << "case0" << std::endl;
Chris@16 189 lowItr = insert_(ivl.low(), ids);
Chris@16 190 evaluateBorder_(outputContainer, ids, ids);
Chris@16 191 highItr = insert_(ivl.high(), std::set<int>());
Chris@16 192 return;
Chris@16 193 }
Chris@16 194 //ensure that highItr points to the end of the ivl
Chris@16 195 if(highItr == scanData_.end() || (*highItr).first > ivl.high()) {
Chris@16 196 //std::cout << "case1" << std::endl;
Chris@16 197 //std::cout << highItr->first << std::endl;
Chris@16 198 std::set<int> value = std::set<int>();
Chris@16 199 if(highItr != scanData_.begin()) {
Chris@16 200 --highItr;
Chris@16 201 //std::cout << highItr->first << std::endl;
Chris@16 202 //std::cout << "high set size " << highItr->second.size() << std::endl;
Chris@16 203 value = highItr->second;
Chris@16 204 }
Chris@16 205 nextItr_ = highItr;
Chris@16 206 highItr = insert_(ivl.high(), value);
Chris@16 207 } else {
Chris@16 208 //evaluate border with next higher interval
Chris@16 209 //std::cout << "case1a" << std::endl;
Chris@16 210 if(leadingEdge)evaluateBorder_(outputContainer, highItr->second, ids);
Chris@16 211 }
Chris@16 212 //split the low interval if needed
Chris@16 213 if(lowItr->first > ivl.low()) {
Chris@16 214 //std::cout << "case2" << std::endl;
Chris@16 215 if(lowItr != scanData_.begin()) {
Chris@16 216 //std::cout << "case3" << std::endl;
Chris@16 217 --lowItr;
Chris@16 218 nextItr_ = lowItr;
Chris@16 219 //std::cout << lowItr->first << " " << lowItr->second.size() << std::endl;
Chris@16 220 lowItr = insert_(ivl.low(), lowItr->second);
Chris@16 221 } else {
Chris@16 222 //std::cout << "case4" << std::endl;
Chris@16 223 nextItr_ = lowItr;
Chris@16 224 lowItr = insert_(ivl.low(), std::set<int>());
Chris@16 225 }
Chris@16 226 } else {
Chris@16 227 //evaluate border with next higher interval
Chris@16 228 //std::cout << "case2a" << std::endl;
Chris@16 229 typename ScanData::iterator nextLowerItr = lowItr;
Chris@16 230 if(leadingEdge && nextLowerItr != scanData_.begin()){
Chris@16 231 --nextLowerItr;
Chris@16 232 evaluateBorder_(outputContainer, nextLowerItr->second, ids);
Chris@16 233 }
Chris@16 234 }
Chris@16 235 //std::cout << "low: " << lowItr->first << " high: " << highItr->first << std::endl;
Chris@16 236 //print();
Chris@16 237 //process scan data intersecting interval
Chris@16 238 for(typename ScanData::iterator itr = lowItr; itr != highItr; ){
Chris@16 239 //std::cout << "case5" << std::endl;
Chris@16 240 //std::cout << itr->first << std::endl;
Chris@16 241 std::set<int>& beforeIds = itr->second;
Chris@16 242 ++itr;
Chris@16 243 evaluateInterval_(outputContainer, beforeIds, ids, leadingEdge);
Chris@16 244 }
Chris@16 245 //print();
Chris@16 246 //merge the bottom interval with the one below if they have the same count
Chris@16 247 if(lowItr != scanData_.begin()){
Chris@16 248 //std::cout << "case6" << std::endl;
Chris@16 249 typename ScanData::iterator belowLowItr = lowItr;
Chris@16 250 --belowLowItr;
Chris@16 251 if(belowLowItr->second == lowItr->second) {
Chris@16 252 //std::cout << "case7" << std::endl;
Chris@16 253 scanData_.erase(lowItr);
Chris@16 254 }
Chris@16 255 }
Chris@16 256 //merge the top interval with the one above if they have the same count
Chris@16 257 if(highItr != scanData_.begin()) {
Chris@16 258 //std::cout << "case8" << std::endl;
Chris@16 259 typename ScanData::iterator beforeHighItr = highItr;
Chris@16 260 --beforeHighItr;
Chris@16 261 if(beforeHighItr->second == highItr->second) {
Chris@16 262 //std::cout << "case9" << std::endl;
Chris@16 263 scanData_.erase(highItr);
Chris@16 264 highItr = beforeHighItr;
Chris@16 265 ++highItr;
Chris@16 266 }
Chris@16 267 }
Chris@16 268 //print();
Chris@16 269 nextItr_ = highItr;
Chris@16 270 }
Chris@16 271
Chris@16 272 // inline void print() const {
Chris@16 273 // for(typename ScanData::const_iterator itr = scanData_.begin(); itr != scanData_.end(); ++itr) {
Chris@16 274 // std::cout << itr->first << ": ";
Chris@16 275 // for(std::set<int>::const_iterator sitr = itr->second.begin();
Chris@16 276 // sitr != itr->second.end(); ++sitr){
Chris@16 277 // std::cout << *sitr << " ";
Chris@16 278 // }
Chris@16 279 // std::cout << std::endl;
Chris@16 280 // }
Chris@16 281 // }
Chris@16 282
Chris@16 283 private:
Chris@16 284 inline typename ScanData::iterator lookup_(Unit pos){
Chris@16 285 if(nextItr_ != scanData_.end() && nextItr_->first >= pos) {
Chris@16 286 return nextItr_;
Chris@16 287 }
Chris@16 288 return nextItr_ = scanData_.lower_bound(pos);
Chris@16 289 }
Chris@16 290
Chris@16 291 inline typename ScanData::iterator insert_(Unit pos, const std::set<int>& ids){
Chris@16 292 //std::cout << "inserting " << ids.size() << " ids at: " << pos << std::endl;
Chris@16 293 return nextItr_ = scanData_.insert(nextItr_, std::pair<Unit, std::set<int> >(pos, ids));
Chris@16 294 }
Chris@16 295
Chris@16 296 template <typename graphT>
Chris@16 297 inline void evaluateInterval_(graphT& outputContainer, std::set<int>& ids,
Chris@16 298 const std::set<int>& changingIds, bool leadingEdge) {
Chris@16 299 for(std::set<int>::const_iterator ciditr = changingIds.begin(); ciditr != changingIds.end(); ++ciditr){
Chris@16 300 //std::cout << "evaluateInterval " << (*ciditr) << std::endl;
Chris@16 301 evaluateId_(outputContainer, ids, *ciditr, leadingEdge);
Chris@16 302 }
Chris@16 303 }
Chris@16 304 template <typename graphT>
Chris@16 305 inline void evaluateBorder_(graphT& outputContainer, const std::set<int>& ids, const std::set<int>& changingIds) {
Chris@16 306 for(std::set<int>::const_iterator ciditr = changingIds.begin(); ciditr != changingIds.end(); ++ciditr){
Chris@16 307 //std::cout << "evaluateBorder " << (*ciditr) << std::endl;
Chris@16 308 evaluateBorderId_(outputContainer, ids, *ciditr);
Chris@16 309 }
Chris@16 310 }
Chris@16 311 template <typename graphT>
Chris@16 312 inline void evaluateBorderId_(graphT& outputContainer, const std::set<int>& ids, int changingId) {
Chris@16 313 for(std::set<int>::const_iterator scanItr = ids.begin(); scanItr != ids.end(); ++scanItr) {
Chris@16 314 //std::cout << "create edge: " << changingId << " " << *scanItr << std::endl;
Chris@16 315 if(changingId != *scanItr){
Chris@16 316 outputContainer[changingId].insert(*scanItr);
Chris@16 317 outputContainer[*scanItr].insert(changingId);
Chris@16 318 }
Chris@16 319 }
Chris@16 320 }
Chris@16 321 template <typename graphT>
Chris@16 322 inline void evaluateId_(graphT& outputContainer, std::set<int>& ids, int changingId, bool leadingEdge) {
Chris@16 323 //std::cout << "changingId: " << changingId << std::endl;
Chris@16 324 //for( std::set<int>::iterator itr = ids.begin(); itr != ids.end(); ++itr){
Chris@16 325 // std::cout << *itr << " ";
Chris@16 326 //}std::cout << std::endl;
Chris@16 327 std::set<int>::iterator lb = ids.lower_bound(changingId);
Chris@16 328 if(lb == ids.end() || (*lb) != changingId) {
Chris@16 329 if(leadingEdge) {
Chris@16 330 //std::cout << "insert\n";
Chris@16 331 //insert and add to output
Chris@16 332 for(std::set<int>::iterator scanItr = ids.begin(); scanItr != ids.end(); ++scanItr) {
Chris@16 333 //std::cout << "create edge: " << changingId << " " << *scanItr << std::endl;
Chris@16 334 if(changingId != *scanItr){
Chris@16 335 outputContainer[changingId].insert(*scanItr);
Chris@16 336 outputContainer[*scanItr].insert(changingId);
Chris@16 337 }
Chris@16 338 }
Chris@16 339 ids.insert(changingId);
Chris@16 340 }
Chris@16 341 } else {
Chris@16 342 if(!leadingEdge){
Chris@16 343 //std::cout << "erase\n";
Chris@16 344 ids.erase(lb);
Chris@16 345 }
Chris@16 346 }
Chris@16 347 }
Chris@16 348 };
Chris@16 349
Chris@16 350 template <typename graphT>
Chris@16 351 static inline void processEvent(graphT& outputContainer, TouchOp& op, const TouchScanEvent& data, bool leadingEdge) {
Chris@16 352 for(typename TouchScanEvent::iterator itr = data.begin(); itr != data.end(); ++itr) {
Chris@16 353 //std::cout << "processInterval" << std::endl;
Chris@16 354 op.processInterval(outputContainer, (*itr).first, (*itr).second, leadingEdge);
Chris@16 355 }
Chris@16 356 }
Chris@16 357
Chris@16 358 template <typename graphT>
Chris@16 359 static inline void performTouch(graphT& outputContainer, const TouchSetData& data) {
Chris@16 360 typename std::map<Unit, TouchScanEvent>::const_iterator leftItr = data.first.begin();
Chris@16 361 typename std::map<Unit, TouchScanEvent>::const_iterator rightItr = data.second.begin();
Chris@16 362 typename std::map<Unit, TouchScanEvent>::const_iterator leftEnd = data.first.end();
Chris@16 363 typename std::map<Unit, TouchScanEvent>::const_iterator rightEnd = data.second.end();
Chris@16 364 TouchOp op;
Chris@16 365 while(leftItr != leftEnd || rightItr != rightEnd) {
Chris@16 366 //std::cout << "loop" << std::endl;
Chris@16 367 op.advanceScan();
Chris@16 368 //rightItr cannont be at end if leftItr is not at end
Chris@16 369 if(leftItr != leftEnd && rightItr != rightEnd &&
Chris@16 370 leftItr->first <= rightItr->first) {
Chris@16 371 //std::cout << "case1" << std::endl;
Chris@16 372 //std::cout << leftItr ->first << std::endl;
Chris@16 373 processEvent(outputContainer, op, leftItr->second, true);
Chris@16 374 ++leftItr;
Chris@16 375 } else {
Chris@16 376 //std::cout << "case2" << std::endl;
Chris@16 377 //std::cout << rightItr ->first << std::endl;
Chris@16 378 processEvent(outputContainer, op, rightItr->second, false);
Chris@16 379 ++rightItr;
Chris@16 380 }
Chris@16 381 }
Chris@16 382 }
Chris@16 383
Chris@16 384 template <class iT>
Chris@16 385 static inline void populateTouchSetData(TouchSetData& data, iT beginData, iT endData, int id) {
Chris@16 386 Unit prevPos = ((std::numeric_limits<Unit>::max)());
Chris@16 387 Unit prevY = prevPos;
Chris@16 388 int count = 0;
Chris@16 389 for(iT itr = beginData; itr != endData; ++itr) {
Chris@16 390 Unit pos = (*itr).first;
Chris@16 391 if(pos != prevPos) {
Chris@16 392 prevPos = pos;
Chris@16 393 prevY = (*itr).second.first;
Chris@16 394 count = (*itr).second.second;
Chris@16 395 continue;
Chris@16 396 }
Chris@16 397 Unit y = (*itr).second.first;
Chris@16 398 if(count != 0 && y != prevY) {
Chris@16 399 std::pair<Interval, int> element(Interval(prevY, y), id);
Chris@16 400 if(count > 0) {
Chris@16 401 data.first[pos].insert(element);
Chris@16 402 } else {
Chris@16 403 data.second[pos].insert(element);
Chris@16 404 }
Chris@16 405 }
Chris@16 406 prevY = y;
Chris@16 407 count += (*itr).second.second;
Chris@16 408 }
Chris@16 409 }
Chris@16 410
Chris@16 411 static inline void populateTouchSetData(TouchSetData& data, const std::vector<std::pair<Unit, std::pair<Unit, int> > >& inputData, int id) {
Chris@16 412 populateTouchSetData(data, inputData.begin(), inputData.end(), id);
Chris@16 413 }
Chris@16 414
Chris@16 415 };
Chris@16 416 }
Chris@16 417 }
Chris@16 418 #endif