File indexing completed on 2025-12-15 10:04:19
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_POLYGON_POLYGON_90_TOUCH_HPP
0009 #define BOOST_POLYGON_POLYGON_90_TOUCH_HPP
0010 namespace boost { namespace polygon{
0011
0012 template <typename Unit>
0013 struct touch_90_operation {
0014 typedef interval_data<Unit> Interval;
0015
0016 class TouchScanEvent {
0017 private:
0018 typedef std::map<Unit, std::set<int> > EventData;
0019 EventData eventData_;
0020 public:
0021
0022
0023
0024
0025
0026 class iterator {
0027 private:
0028 typename EventData::const_iterator itr_;
0029 std::pair<Interval, std::set<int> > ivlIds_;
0030 bool incremented_;
0031 public:
0032 inline iterator() : itr_(), ivlIds_(), incremented_(false) {}
0033 inline iterator(typename EventData::const_iterator itr,
0034 Unit prevPos, Unit curPos, const std::set<int>& ivlIds) : itr_(itr), ivlIds_(), incremented_(false) {
0035 ivlIds_.second = ivlIds;
0036 ivlIds_.first = Interval(prevPos, curPos);
0037 }
0038 inline iterator(const iterator& that) : itr_(), ivlIds_(), incremented_(false) { (*this) = that; }
0039 inline iterator& operator=(const iterator& that) {
0040 itr_ = that.itr_;
0041 ivlIds_.first = that.ivlIds_.first;
0042 ivlIds_.second = that.ivlIds_.second;
0043 incremented_ = that.incremented_;
0044 return *this;
0045 }
0046 inline bool operator==(const iterator& that) { return itr_ == that.itr_; }
0047 inline bool operator!=(const iterator& that) { return itr_ != that.itr_; }
0048 inline iterator& operator++() {
0049
0050
0051
0052
0053
0054
0055 for(std::set<int>::const_iterator itr = (*itr_).second.begin();
0056 itr != (*itr_).second.end(); ++itr) {
0057
0058 std::set<int>::iterator lb = ivlIds_.second.find(*itr);
0059 if(lb != ivlIds_.second.end()) {
0060 ivlIds_.second.erase(lb);
0061 } else {
0062 ivlIds_.second.insert(*itr);
0063 }
0064 }
0065
0066
0067
0068
0069
0070 ++itr_;
0071
0072 incremented_ = true;
0073 return *this;
0074 }
0075 inline const iterator operator++(int){
0076 iterator tmpItr(*this);
0077 ++(*this);
0078 return tmpItr;
0079 }
0080 inline std::pair<Interval, std::set<int> >& operator*() {
0081 if(incremented_) ivlIds_.first = Interval(ivlIds_.first.get(HIGH), itr_->first);
0082 incremented_ = false;
0083 if(ivlIds_.second.empty())(++(*this));
0084 if(incremented_) ivlIds_.first = Interval(ivlIds_.first.get(HIGH), itr_->first);
0085 incremented_ = false;
0086 return ivlIds_; }
0087 };
0088
0089 inline TouchScanEvent() : eventData_() {}
0090 template<class iT>
0091 inline TouchScanEvent(iT begin, iT end) : eventData_() {
0092 for( ; begin != end; ++begin){
0093 insert(*begin);
0094 }
0095 }
0096 inline TouchScanEvent(const TouchScanEvent& that) : eventData_(that.eventData_) {}
0097 inline TouchScanEvent& operator=(const TouchScanEvent& that){
0098 eventData_ = that.eventData_;
0099 return *this;
0100 }
0101
0102
0103 inline void insert(const std::pair<Interval, int>& intervalId){
0104 insert(intervalId.first.low(), intervalId.second);
0105 insert(intervalId.first.high(), intervalId.second);
0106 }
0107
0108
0109 inline void insert(Unit pos, int id) {
0110 typename EventData::iterator lb = eventData_.lower_bound(pos);
0111 if(lb != eventData_.end() && lb->first == pos) {
0112 std::set<int>& mr (lb->second);
0113 std::set<int>::iterator mri = mr.find(id);
0114 if(mri == mr.end()) {
0115 mr.insert(id);
0116 } else {
0117 mr.erase(id);
0118 }
0119 } else {
0120 lb = eventData_.insert(lb, std::pair<Unit, std::set<int> >(pos, std::set<int>()));
0121 (*lb).second.insert(id);
0122 }
0123 }
0124
0125
0126 inline void insert(const TouchScanEvent& that){
0127 typename EventData::const_iterator itr;
0128 for(itr = that.eventData_.begin(); itr != that.eventData_.end(); ++itr) {
0129 eventData_[(*itr).first].insert(itr->second.begin(), itr->second.end());
0130 }
0131 }
0132
0133
0134 inline iterator begin() const {
0135
0136 if(eventData_.empty()) return end();
0137 typename EventData::const_iterator itr = eventData_.begin();
0138 Unit pos = itr->first;
0139 const std::set<int>& idr = itr->second;
0140 ++itr;
0141 return iterator(itr, pos, itr->first, idr);
0142 }
0143
0144
0145 inline iterator end() const { return iterator(eventData_.end(), 0, 0, std::set<int>()); }
0146
0147 inline void clear() { eventData_.clear(); }
0148
0149 inline Interval extents() const {
0150 if(eventData_.empty()) return Interval();
0151 return Interval((*(eventData_.begin())).first, (*(eventData_.rbegin())).first);
0152 }
0153 };
0154
0155
0156
0157 typedef std::pair<std::map<Unit, TouchScanEvent>, std::map<Unit, TouchScanEvent> > TouchSetData;
0158
0159 class TouchOp {
0160 public:
0161 typedef std::map<Unit, std::set<int> > ScanData;
0162 typedef std::pair<Unit, std::set<int> > ElementType;
0163 protected:
0164 ScanData scanData_;
0165 typename ScanData::iterator nextItr_;
0166 public:
0167 inline TouchOp () : scanData_(), nextItr_() { nextItr_ = scanData_.end(); }
0168 inline TouchOp (const TouchOp& that) : scanData_(that.scanData_), nextItr_() { nextItr_ = scanData_.begin(); }
0169 inline TouchOp& operator=(const TouchOp& that);
0170
0171
0172 inline void advanceScan() { nextItr_ = scanData_.begin(); }
0173
0174
0175
0176
0177 template <typename graphT>
0178 inline void processInterval(graphT& outputContainer, Interval ivl, const std::set<int>& ids, bool leadingEdge) {
0179
0180 typename ScanData::iterator lowItr = lookup_(ivl.low());
0181 typename ScanData::iterator highItr = lookup_(ivl.high());
0182
0183
0184
0185
0186
0187 if(lowItr == scanData_.end()) {
0188
0189 lowItr = insert_(ivl.low(), ids);
0190 evaluateBorder_(outputContainer, ids, ids);
0191 highItr = insert_(ivl.high(), std::set<int>());
0192 return;
0193 }
0194
0195 if(highItr == scanData_.end() || (*highItr).first > ivl.high()) {
0196
0197
0198 std::set<int> value = std::set<int>();
0199 if(highItr != scanData_.begin()) {
0200 --highItr;
0201
0202
0203 value = highItr->second;
0204 }
0205 nextItr_ = highItr;
0206 highItr = insert_(ivl.high(), value);
0207 } else {
0208
0209
0210 if(leadingEdge)evaluateBorder_(outputContainer, highItr->second, ids);
0211 }
0212
0213 if(lowItr->first > ivl.low()) {
0214
0215 if(lowItr != scanData_.begin()) {
0216
0217 --lowItr;
0218 nextItr_ = lowItr;
0219
0220 lowItr = insert_(ivl.low(), lowItr->second);
0221 } else {
0222
0223 nextItr_ = lowItr;
0224 lowItr = insert_(ivl.low(), std::set<int>());
0225 }
0226 } else {
0227
0228
0229 typename ScanData::iterator nextLowerItr = lowItr;
0230 if(leadingEdge && nextLowerItr != scanData_.begin()){
0231 --nextLowerItr;
0232 evaluateBorder_(outputContainer, nextLowerItr->second, ids);
0233 }
0234 }
0235
0236
0237
0238 for(typename ScanData::iterator itr = lowItr; itr != highItr; ){
0239
0240
0241 std::set<int>& beforeIds = itr->second;
0242 ++itr;
0243 evaluateInterval_(outputContainer, beforeIds, ids, leadingEdge);
0244 }
0245
0246
0247 if(lowItr != scanData_.begin()){
0248
0249 typename ScanData::iterator belowLowItr = lowItr;
0250 --belowLowItr;
0251 if(belowLowItr->second == lowItr->second) {
0252
0253 scanData_.erase(lowItr);
0254 }
0255 }
0256
0257 if(highItr != scanData_.begin()) {
0258
0259 typename ScanData::iterator beforeHighItr = highItr;
0260 --beforeHighItr;
0261 if(beforeHighItr->second == highItr->second) {
0262
0263 scanData_.erase(highItr);
0264 highItr = beforeHighItr;
0265 ++highItr;
0266 }
0267 }
0268
0269 nextItr_ = highItr;
0270 }
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283 private:
0284 inline typename ScanData::iterator lookup_(Unit pos){
0285 if(nextItr_ != scanData_.end() && nextItr_->first >= pos) {
0286 return nextItr_;
0287 }
0288 return nextItr_ = scanData_.lower_bound(pos);
0289 }
0290
0291 inline typename ScanData::iterator insert_(Unit pos, const std::set<int>& ids){
0292
0293 return nextItr_ = scanData_.insert(nextItr_, std::pair<Unit, std::set<int> >(pos, ids));
0294 }
0295
0296 template <typename graphT>
0297 inline void evaluateInterval_(graphT& outputContainer, std::set<int>& ids,
0298 const std::set<int>& changingIds, bool leadingEdge) {
0299 for(std::set<int>::const_iterator ciditr = changingIds.begin(); ciditr != changingIds.end(); ++ciditr){
0300
0301 evaluateId_(outputContainer, ids, *ciditr, leadingEdge);
0302 }
0303 }
0304 template <typename graphT>
0305 inline void evaluateBorder_(graphT& outputContainer, const std::set<int>& ids, const std::set<int>& changingIds) {
0306 for(std::set<int>::const_iterator ciditr = changingIds.begin(); ciditr != changingIds.end(); ++ciditr){
0307
0308 evaluateBorderId_(outputContainer, ids, *ciditr);
0309 }
0310 }
0311 template <typename graphT>
0312 inline void evaluateBorderId_(graphT& outputContainer, const std::set<int>& ids, int changingId) {
0313 for(std::set<int>::const_iterator scanItr = ids.begin(); scanItr != ids.end(); ++scanItr) {
0314
0315 if(changingId != *scanItr){
0316 outputContainer[changingId].insert(*scanItr);
0317 outputContainer[*scanItr].insert(changingId);
0318 }
0319 }
0320 }
0321 template <typename graphT>
0322 inline void evaluateId_(graphT& outputContainer, std::set<int>& ids, int changingId, bool leadingEdge) {
0323
0324
0325
0326
0327 std::set<int>::iterator lb = ids.lower_bound(changingId);
0328 if(lb == ids.end() || (*lb) != changingId) {
0329 if(leadingEdge) {
0330
0331
0332 for(std::set<int>::iterator scanItr = ids.begin(); scanItr != ids.end(); ++scanItr) {
0333
0334 if(changingId != *scanItr){
0335 outputContainer[changingId].insert(*scanItr);
0336 outputContainer[*scanItr].insert(changingId);
0337 }
0338 }
0339 ids.insert(changingId);
0340 }
0341 } else {
0342 if(!leadingEdge){
0343
0344 ids.erase(lb);
0345 }
0346 }
0347 }
0348 };
0349
0350 template <typename graphT>
0351 static inline void processEvent(graphT& outputContainer, TouchOp& op, const TouchScanEvent& data, bool leadingEdge) {
0352 for(typename TouchScanEvent::iterator itr = data.begin(); itr != data.end(); ++itr) {
0353
0354 op.processInterval(outputContainer, (*itr).first, (*itr).second, leadingEdge);
0355 }
0356 }
0357
0358 template <typename graphT>
0359 static inline void performTouch(graphT& outputContainer, const TouchSetData& data) {
0360 typename std::map<Unit, TouchScanEvent>::const_iterator leftItr = data.first.begin();
0361 typename std::map<Unit, TouchScanEvent>::const_iterator rightItr = data.second.begin();
0362 typename std::map<Unit, TouchScanEvent>::const_iterator leftEnd = data.first.end();
0363 typename std::map<Unit, TouchScanEvent>::const_iterator rightEnd = data.second.end();
0364 TouchOp op;
0365 while(leftItr != leftEnd || rightItr != rightEnd) {
0366
0367 op.advanceScan();
0368
0369 if(leftItr != leftEnd && rightItr != rightEnd &&
0370 leftItr->first <= rightItr->first) {
0371
0372
0373 processEvent(outputContainer, op, leftItr->second, true);
0374 ++leftItr;
0375 } else {
0376
0377
0378 processEvent(outputContainer, op, rightItr->second, false);
0379 ++rightItr;
0380 }
0381 }
0382 }
0383
0384 template <class iT>
0385 static inline void populateTouchSetData(TouchSetData& data, iT beginData, iT endData, int id) {
0386 Unit prevPos = ((std::numeric_limits<Unit>::max)());
0387 Unit prevY = prevPos;
0388 int count = 0;
0389 for(iT itr = beginData; itr != endData; ++itr) {
0390 Unit pos = (*itr).first;
0391 if(pos != prevPos) {
0392 prevPos = pos;
0393 prevY = (*itr).second.first;
0394 count = (*itr).second.second;
0395 continue;
0396 }
0397 Unit y = (*itr).second.first;
0398 if(count != 0 && y != prevY) {
0399 std::pair<Interval, int> element(Interval(prevY, y), id);
0400 if(count > 0) {
0401 data.first[pos].insert(element);
0402 } else {
0403 data.second[pos].insert(element);
0404 }
0405 }
0406 prevY = y;
0407 count += (*itr).second.second;
0408 }
0409 }
0410
0411 static inline void populateTouchSetData(TouchSetData& data, const std::vector<std::pair<Unit, std::pair<Unit, int> > >& inputData, int id) {
0412 populateTouchSetData(data, inputData.begin(), inputData.end(), id);
0413 }
0414
0415 };
0416 }
0417 }
0418 #endif