File indexing completed on 2025-12-15 10:04:21
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_POLYGON_PROPERTY_MERGE_HPP
0009 #define BOOST_POLYGON_PROPERTY_MERGE_HPP
0010 namespace boost { namespace polygon{
0011
0012 template <typename coordinate_type>
0013 class property_merge_point {
0014 private:
0015 coordinate_type x_, y_;
0016 public:
0017 inline property_merge_point() : x_(), y_() {}
0018 inline property_merge_point(coordinate_type x, coordinate_type y) : x_(x), y_(y) {}
0019
0020 inline bool operator==(const property_merge_point& that) const { return x_ == that.x_ && y_ == that.y_; }
0021 inline bool operator!=(const property_merge_point& that) const { return !((*this) == that); }
0022 inline bool operator<(const property_merge_point& that) const {
0023 if(x_ < that.x_) return true;
0024 if(x_ > that.x_) return false;
0025 return y_ < that.y_;
0026 }
0027 inline coordinate_type x() const { return x_; }
0028 inline coordinate_type y() const { return y_; }
0029 inline void x(coordinate_type value) { x_ = value; }
0030 inline void y(coordinate_type value) { y_ = value; }
0031 };
0032
0033 template <typename coordinate_type>
0034 class property_merge_interval {
0035 private:
0036 coordinate_type low_, high_;
0037 public:
0038 inline property_merge_interval() : low_(), high_() {}
0039 inline property_merge_interval(coordinate_type low, coordinate_type high) : low_(low), high_(high) {}
0040
0041 inline bool operator==(const property_merge_interval& that) const { return low_ == that.low_ && high_ == that.high_; }
0042 inline bool operator!=(const property_merge_interval& that) const { return !((*this) == that); }
0043 inline bool operator<(const property_merge_interval& that) const {
0044 if(low_ < that.low_) return true;
0045 if(low_ > that.low_) return false;
0046 return high_ < that.high_;
0047 }
0048 inline coordinate_type low() const { return low_; }
0049 inline coordinate_type high() const { return high_; }
0050 inline void low(coordinate_type value) { low_ = value; }
0051 inline void high(coordinate_type value) { high_ = value; }
0052 };
0053
0054 template <typename coordinate_type, typename property_type, typename polygon_set_type, typename keytype = std::set<property_type> >
0055 class merge_scanline {
0056 public:
0057
0058
0059 typedef keytype property_set;
0060 typedef std::vector<std::pair<property_type, int> > property_map;
0061 typedef std::pair<property_merge_point<coordinate_type>, std::pair<property_type, int> > vertex_property;
0062 typedef std::pair<property_merge_point<coordinate_type>, property_map> vertex_data;
0063 typedef std::vector<vertex_property> property_merge_data;
0064
0065 typedef std::map<coordinate_type, property_map> scanline_type;
0066 typedef typename scanline_type::iterator scanline_iterator;
0067 typedef std::pair<property_merge_interval<coordinate_type>, std::pair<property_set, property_set> > edge_property;
0068 typedef std::vector<edge_property> edge_property_vector;
0069
0070
0071
0072 template <typename iT, typename orientation_2d_type>
0073 static inline void
0074 populate_property_merge_data(property_merge_data& pmd, iT input_begin, iT input_end,
0075 const property_type& property, orientation_2d_type orient) {
0076 for( ; input_begin != input_end; ++input_begin) {
0077 std::pair<property_merge_point<coordinate_type>, std::pair<property_type, int> > element;
0078 if(orient == HORIZONTAL)
0079 element.first = property_merge_point<coordinate_type>((*input_begin).second.first, (*input_begin).first);
0080 else
0081 element.first = property_merge_point<coordinate_type>((*input_begin).first, (*input_begin).second.first);
0082 element.second.first = property;
0083 element.second.second = (*input_begin).second.second;
0084 pmd.push_back(element);
0085 }
0086 }
0087
0088
0089
0090 merge_scanline() : output(), scanline(), currentVertex(), tmpVector(), previousY(), countFromBelow(), scanlinePosition() {}
0091 merge_scanline(const merge_scanline& that) :
0092 output(that.output),
0093 scanline(that.scanline),
0094 currentVertex(that.currentVertex),
0095 tmpVector(that.tmpVector),
0096 previousY(that.previousY),
0097 countFromBelow(that.countFromBelow),
0098 scanlinePosition(that.scanlinePosition)
0099 {}
0100 merge_scanline& operator=(const merge_scanline& that) {
0101 output = that.output;
0102 scanline = that.scanline;
0103 currentVertex = that.currentVertex;
0104 tmpVector = that.tmpVector;
0105 previousY = that.previousY;
0106 countFromBelow = that.countFromBelow;
0107 scanlinePosition = that.scanlinePosition;
0108 return *this;
0109 }
0110
0111 template <typename result_type>
0112 inline void perform_merge(result_type& result, property_merge_data& data) {
0113 if(data.empty()) return;
0114
0115 polygon_sort(data.begin(), data.end(), less_vertex_data<vertex_property>());
0116
0117 bool firstIteration = true;
0118 scanlinePosition = scanline.end();
0119 for(std::size_t i = 0; i < data.size(); ++i) {
0120 if(firstIteration) {
0121 mergeProperty(currentVertex.second, data[i].second);
0122 currentVertex.first = data[i].first;
0123 firstIteration = false;
0124 } else {
0125 if(data[i].first != currentVertex.first) {
0126 if(data[i].first.x() != currentVertex.first.x()) {
0127 processVertex(output);
0128
0129 countFromBelow.clear();
0130 writeOutput(currentVertex.first.x(), result, output);
0131 currentVertex.second.clear();
0132 mergeProperty(currentVertex.second, data[i].second);
0133 currentVertex.first = data[i].first;
0134
0135 } else {
0136 processVertex(output);
0137 currentVertex.second.clear();
0138 mergeProperty(currentVertex.second, data[i].second);
0139 currentVertex.first = data[i].first;
0140 }
0141 } else {
0142 mergeProperty(currentVertex.second, data[i].second);
0143 }
0144 }
0145 }
0146 processVertex(output);
0147 writeOutput(currentVertex.first.x(), result, output);
0148
0149
0150 }
0151
0152 private:
0153
0154
0155 template <class T>
0156 class less_vertex_data {
0157 public:
0158 less_vertex_data() {}
0159 bool operator()(const T& lvalue, const T& rvalue) const {
0160 if(lvalue.first.x() < rvalue.first.x()) return true;
0161 if(lvalue.first.x() > rvalue.first.x()) return false;
0162 if(lvalue.first.y() < rvalue.first.y()) return true;
0163 return false;
0164 }
0165 };
0166
0167 template <typename T>
0168 struct lessPropertyCount {
0169 lessPropertyCount() {}
0170 bool operator()(const T& a, const T& b) {
0171 return a.first < b.first;
0172 }
0173 };
0174
0175
0176
0177 static inline void mergeProperty(property_map& lvalue, std::pair<property_type, int>& rvalue) {
0178 typename property_map::iterator itr = std::lower_bound(lvalue.begin(), lvalue.end(), rvalue,
0179 lessPropertyCount<std::pair<property_type, int> >());
0180 if(itr == lvalue.end() ||
0181 (*itr).first != rvalue.first) {
0182 lvalue.insert(itr, rvalue);
0183 } else {
0184 (*itr).second += rvalue.second;
0185 if((*itr).second == 0)
0186 lvalue.erase(itr);
0187 }
0188
0189
0190
0191
0192 }
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213 static inline void setProperty(property_set& pset, property_map& pmap) {
0214 for(typename property_map::iterator itr = pmap.begin(); itr != pmap.end(); ++itr) {
0215 if((*itr).second > 0) {
0216 pset.insert(pset.end(), (*itr).first);
0217 }
0218 }
0219 }
0220
0221
0222
0223 edge_property_vector output;
0224 scanline_type scanline;
0225 vertex_data currentVertex;
0226 property_map tmpVector;
0227 coordinate_type previousY;
0228 property_map countFromBelow;
0229 scanline_iterator scanlinePosition;
0230
0231
0232
0233 inline void mergeCount(property_map& lvalue, property_map& rvalue) {
0234 typename property_map::iterator litr = lvalue.begin();
0235 typename property_map::iterator ritr = rvalue.begin();
0236 tmpVector.clear();
0237 while(litr != lvalue.end() && ritr != rvalue.end()) {
0238 if((*litr).first <= (*ritr).first) {
0239 if(!tmpVector.empty() &&
0240 (*litr).first == tmpVector.back().first) {
0241 tmpVector.back().second += (*litr).second;
0242 } else {
0243 tmpVector.push_back(*litr);
0244 }
0245 ++litr;
0246 } else if((*ritr).first <= (*litr).first) {
0247 if(!tmpVector.empty() &&
0248 (*ritr).first == tmpVector.back().first) {
0249 tmpVector.back().second += (*ritr).second;
0250 } else {
0251 tmpVector.push_back(*ritr);
0252 }
0253 ++ritr;
0254 }
0255 }
0256 while(litr != lvalue.end()) {
0257 if(!tmpVector.empty() &&
0258 (*litr).first == tmpVector.back().first) {
0259 tmpVector.back().second += (*litr).second;
0260 } else {
0261 tmpVector.push_back(*litr);
0262 }
0263 ++litr;
0264 }
0265 while(ritr != rvalue.end()) {
0266 if(!tmpVector.empty() &&
0267 (*ritr).first == tmpVector.back().first) {
0268 tmpVector.back().second += (*ritr).second;
0269 } else {
0270 tmpVector.push_back(*ritr);
0271 }
0272 ++ritr;
0273 }
0274 lvalue.clear();
0275 for(std::size_t i = 0; i < tmpVector.size(); ++i) {
0276 if(tmpVector[i].second != 0) {
0277 lvalue.push_back(tmpVector[i]);
0278 }
0279 }
0280
0281
0282
0283
0284 }
0285
0286 inline void processVertex(edge_property_vector& output) {
0287 if(!countFromBelow.empty()) {
0288
0289
0290
0291
0292
0293
0294 property_merge_interval<coordinate_type> currentInterval(previousY, currentVertex.first.y());
0295 coordinate_type currentY = currentInterval.low();
0296 if(scanlinePosition == scanline.end() ||
0297 (*scanlinePosition).first != previousY) {
0298 scanlinePosition = scanline.lower_bound(previousY);
0299 }
0300 scanline_iterator previousScanlinePosition = scanlinePosition;
0301 ++scanlinePosition;
0302 while(scanlinePosition != scanline.end()) {
0303 coordinate_type elementY = (*scanlinePosition).first;
0304 if(elementY <= currentInterval.high()) {
0305 property_map& countOnLeft = (*previousScanlinePosition).second;
0306 edge_property element;
0307 output.push_back(element);
0308 output.back().first = property_merge_interval<coordinate_type>((*previousScanlinePosition).first, elementY);
0309 setProperty(output.back().second.first, countOnLeft);
0310 mergeCount(countOnLeft, countFromBelow);
0311 setProperty(output.back().second.second, countOnLeft);
0312 if(output.back().second.first == output.back().second.second) {
0313 output.pop_back();
0314 }
0315 else if(output.size() > 1) {
0316 edge_property& secondToLast = output[output.size()-2];
0317 if(secondToLast.first.high() == output.back().first.low() &&
0318 secondToLast.second.first == output.back().second.first &&
0319 secondToLast.second.second == output.back().second.second) {
0320
0321
0322 secondToLast.first.high(output.back().first.high());
0323 output.pop_back();
0324 }
0325 }
0326 if(previousScanlinePosition == scanline.begin()) {
0327 if(countOnLeft.empty()) {
0328 scanline.erase(previousScanlinePosition);
0329 }
0330 } else {
0331 scanline_iterator tmpitr = previousScanlinePosition;
0332 --tmpitr;
0333 if((*tmpitr).second == (*previousScanlinePosition).second)
0334 scanline.erase(previousScanlinePosition);
0335 }
0336
0337 } else if(currentY < currentInterval.high()){
0338
0339
0340 std::pair<coordinate_type, property_map> elementScan;
0341 elementScan.first = currentInterval.high();
0342 elementScan.second = (*previousScanlinePosition).second;
0343 scanlinePosition = scanline.insert(scanlinePosition, elementScan);
0344 continue;
0345 } else {
0346 break;
0347 }
0348 previousScanlinePosition = scanlinePosition;
0349 currentY = previousY = elementY;
0350 ++scanlinePosition;
0351 if(scanlinePosition == scanline.end() &&
0352 currentY < currentInterval.high()) {
0353
0354 std::pair<coordinate_type, property_map> elementScan;
0355 elementScan.first = currentInterval.high();
0356 scanlinePosition = scanline.insert(scanline.end(), elementScan);
0357 }
0358 }
0359 if(scanlinePosition == scanline.end() &&
0360 currentY < currentInterval.high()) {
0361
0362
0363
0364
0365 mergeCount(scanline[currentY], countFromBelow);
0366 std::pair<coordinate_type, property_map> elementScan;
0367 elementScan.first = currentInterval.high();
0368 scanline.insert(scanline.end(), elementScan);
0369
0370 edge_property element;
0371 output.push_back(element);
0372 output.back().first = property_merge_interval<coordinate_type>(currentY, currentInterval.high());
0373 setProperty(output.back().second.second, countFromBelow);
0374 mergeCount(countFromBelow, currentVertex.second);
0375 } else {
0376 mergeCount(countFromBelow, currentVertex.second);
0377 if(countFromBelow.empty()) {
0378 if(previousScanlinePosition == scanline.begin()) {
0379 if((*previousScanlinePosition).second.empty()) {
0380 scanline.erase(previousScanlinePosition);
0381
0382
0383 }
0384 } else {
0385 scanline_iterator tmpitr = previousScanlinePosition;
0386 --tmpitr;
0387 if((*tmpitr).second == (*previousScanlinePosition).second) {
0388 scanline.erase(previousScanlinePosition);
0389
0390
0391 }
0392 }
0393 }
0394 }
0395 } else {
0396
0397 countFromBelow = currentVertex.second;
0398 scanlinePosition = scanline.lower_bound(currentVertex.first.y());
0399 if(scanlinePosition != scanline.end()) {
0400 if((*scanlinePosition).first != currentVertex.first.y()) {
0401 if(scanlinePosition != scanline.begin()) {
0402
0403 --scanlinePosition;
0404
0405 property_map& countOnLeft = (*scanlinePosition).second;
0406 std::pair<coordinate_type, property_map> element(currentVertex.first.y(), countOnLeft);
0407 scanlinePosition = scanline.insert(scanlinePosition, element);
0408 } else {
0409 property_map countOnLeft;
0410 std::pair<coordinate_type, property_map> element(currentVertex.first.y(), countOnLeft);
0411 scanlinePosition = scanline.insert(scanlinePosition, element);
0412 }
0413 }
0414 } else {
0415 property_map countOnLeft;
0416 std::pair<coordinate_type, property_map> element(currentVertex.first.y(), countOnLeft);
0417 scanlinePosition = scanline.insert(scanlinePosition, element);
0418 }
0419 }
0420 previousY = currentVertex.first.y();
0421 }
0422
0423 template <typename T>
0424 inline int assertRedundant(T& t) {
0425 if(t.empty()) return 0;
0426 int count = 0;
0427 typename T::iterator itr = t.begin();
0428 if((*itr).second.empty())
0429 ++count;
0430 typename T::iterator itr2 = itr;
0431 ++itr2;
0432 while(itr2 != t.end()) {
0433 if((*itr).second == (*itr2).second)
0434 ++count;
0435 itr = itr2;
0436 ++itr2;
0437 }
0438 return count;
0439 }
0440
0441 template <typename T>
0442 inline void performExtract(T& result, property_merge_data& data) {
0443 if(data.empty()) return;
0444
0445 polygon_sort(data.begin(), data.end(), less_vertex_data<vertex_property>());
0446
0447
0448 bool firstIteration = true;
0449 scanlinePosition = scanline.end();
0450 for(std::size_t i = 0; i < data.size(); ++i) {
0451 if(firstIteration) {
0452 mergeProperty(currentVertex.second, data[i].second);
0453 currentVertex.first = data[i].first;
0454 firstIteration = false;
0455 } else {
0456 if(data[i].first != currentVertex.first) {
0457 if(data[i].first.x() != currentVertex.first.x()) {
0458 processVertex(output);
0459
0460 countFromBelow.clear();
0461 writeGraph(result, output, scanline);
0462 currentVertex.second.clear();
0463 mergeProperty(currentVertex.second, data[i].second);
0464 currentVertex.first = data[i].first;
0465 } else {
0466 processVertex(output);
0467 currentVertex.second.clear();
0468 mergeProperty(currentVertex.second, data[i].second);
0469 currentVertex.first = data[i].first;
0470 }
0471 } else {
0472 mergeProperty(currentVertex.second, data[i].second);
0473 }
0474 }
0475 }
0476 processVertex(output);
0477 writeGraph(result, output, scanline);
0478
0479 }
0480
0481 template <typename T>
0482 inline void insertEdges(T& graph, property_set& p1, property_set& p2) {
0483 for(typename property_set::iterator itr = p1.begin(); itr != p1.end(); ++itr) {
0484 for(typename property_set::iterator itr2 = p2.begin(); itr2 != p2.end(); ++itr2) {
0485 if(*itr != *itr2) {
0486 graph[*itr].insert(*itr2);
0487 graph[*itr2].insert(*itr);
0488 }
0489 }
0490 }
0491 }
0492
0493 template <typename T>
0494 inline void propertySetAbove(coordinate_type y, property_set& ps, T& scanline) {
0495 ps.clear();
0496 typename T::iterator itr = scanline.find(y);
0497 if(itr != scanline.end())
0498 setProperty(ps, (*itr).second);
0499 }
0500
0501 template <typename T>
0502 inline void propertySetBelow(coordinate_type y, property_set& ps, T& scanline) {
0503 ps.clear();
0504 typename T::iterator itr = scanline.find(y);
0505 if(itr != scanline.begin()) {
0506 --itr;
0507 setProperty(ps, (*itr).second);
0508 }
0509 }
0510
0511 template <typename T, typename T2>
0512 inline void writeGraph(T& graph, edge_property_vector& output, T2& scanline) {
0513 if(output.empty()) return;
0514 edge_property* previousEdgeP = &(output[0]);
0515 bool firstIteration = true;
0516 property_set ps;
0517 for(std::size_t i = 0; i < output.size(); ++i) {
0518 edge_property& previousEdge = *previousEdgeP;
0519 edge_property& edge = output[i];
0520 if(previousEdge.first.high() == edge.first.low()) {
0521
0522 insertEdges(graph, edge.second.first, previousEdge.second.first);
0523
0524 insertEdges(graph, edge.second.first, previousEdge.second.second);
0525
0526 insertEdges(graph, edge.second.second, previousEdge.second.second);
0527
0528 insertEdges(graph, edge.second.second, previousEdge.second.first);
0529 } else {
0530 if(!firstIteration){
0531
0532 propertySetAbove(previousEdge.first.high(), ps, scanline);
0533 insertEdges(graph, ps, previousEdge.second.first);
0534 insertEdges(graph, ps, previousEdge.second.second);
0535 }
0536
0537 propertySetBelow(edge.first.high(), ps, scanline);
0538 insertEdges(graph, ps, edge.second.first);
0539 insertEdges(graph, ps, edge.second.second);
0540 }
0541 firstIteration = false;
0542
0543 insertEdges(graph, edge.second.second, edge.second.first);
0544
0545 insertEdges(graph, edge.second.second, edge.second.second);
0546
0547 insertEdges(graph, edge.second.first, edge.second.first);
0548 previousEdgeP = &(output[i]);
0549 }
0550 edge_property& previousEdge = *previousEdgeP;
0551 propertySetAbove(previousEdge.first.high(), ps, scanline);
0552 insertEdges(graph, ps, previousEdge.second.first);
0553 insertEdges(graph, ps, previousEdge.second.second);
0554 output.clear();
0555 }
0556
0557 template <typename Result>
0558 inline void writeOutput(coordinate_type x, Result& result, edge_property_vector& output) {
0559 for(std::size_t i = 0; i < output.size(); ++i) {
0560 edge_property& edge = output[i];
0561
0562 if(!edge.second.first.empty()) {
0563 typename Result::iterator itr = result.find(edge.second.first);
0564 if(itr == result.end()) {
0565 std::pair<property_set, polygon_set_type> element(edge.second.first, polygon_set_type(VERTICAL));
0566 itr = result.insert(result.end(), element);
0567 }
0568 std::pair<interval_data<coordinate_type>, int> element2(interval_data<coordinate_type>(edge.first.low(), edge.first.high()), -1);
0569 (*itr).second.insert(x, element2);
0570 }
0571 if(!edge.second.second.empty()) {
0572
0573 typename Result::iterator itr = result.find(edge.second.second);
0574 if(itr == result.end()) {
0575 std::pair<property_set, polygon_set_type> element(edge.second.second, polygon_set_type(VERTICAL));
0576 itr = result.insert(result.end(), element);
0577 }
0578 std::pair<interval_data<coordinate_type>, int> element3(interval_data<coordinate_type>(edge.first.low(), edge.first.high()), 1);
0579 (*itr).second.insert(x, element3);
0580 }
0581 }
0582 output.clear();
0583 }
0584 };
0585
0586 }
0587 }
0588 #endif