Chris@16: /* Chris@16: Copyright 2008 Intel Corporation Chris@16: Chris@16: Use, modification and distribution are subject to the Boost Software License, Chris@16: Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: http://www.boost.org/LICENSE_1_0.txt). Chris@16: */ Chris@16: #ifndef BOOST_POLYGON_PROPERTY_MERGE_HPP Chris@16: #define BOOST_POLYGON_PROPERTY_MERGE_HPP Chris@16: namespace boost { namespace polygon{ Chris@16: Chris@16: template Chris@16: class property_merge_point { Chris@16: private: Chris@16: coordinate_type x_, y_; Chris@16: public: Chris@16: inline property_merge_point() : x_(), y_() {} Chris@16: inline property_merge_point(coordinate_type x, coordinate_type y) : x_(x), y_(y) {} Chris@16: //use builtin assign and copy Chris@16: inline bool operator==(const property_merge_point& that) const { return x_ == that.x_ && y_ == that.y_; } Chris@16: inline bool operator!=(const property_merge_point& that) const { return !((*this) == that); } Chris@16: inline bool operator<(const property_merge_point& that) const { Chris@16: if(x_ < that.x_) return true; Chris@16: if(x_ > that.x_) return false; Chris@16: return y_ < that.y_; Chris@16: } Chris@16: inline coordinate_type x() const { return x_; } Chris@16: inline coordinate_type y() const { return y_; } Chris@16: inline void x(coordinate_type value) { x_ = value; } Chris@16: inline void y(coordinate_type value) { y_ = value; } Chris@16: }; Chris@16: Chris@16: template Chris@16: class property_merge_interval { Chris@16: private: Chris@16: coordinate_type low_, high_; Chris@16: public: Chris@16: inline property_merge_interval() : low_(), high_() {} Chris@16: inline property_merge_interval(coordinate_type low, coordinate_type high) : low_(low), high_(high) {} Chris@16: //use builtin assign and copy Chris@16: inline bool operator==(const property_merge_interval& that) const { return low_ == that.low_ && high_ == that.high_; } Chris@16: inline bool operator!=(const property_merge_interval& that) const { return !((*this) == that); } Chris@16: inline bool operator<(const property_merge_interval& that) const { Chris@16: if(low_ < that.low_) return true; Chris@16: if(low_ > that.low_) return false; Chris@16: return high_ < that.high_; Chris@16: } Chris@16: inline coordinate_type low() const { return low_; } Chris@16: inline coordinate_type high() const { return high_; } Chris@16: inline void low(coordinate_type value) { low_ = value; } Chris@16: inline void high(coordinate_type value) { high_ = value; } Chris@16: }; Chris@16: Chris@16: template > Chris@16: class merge_scanline { Chris@16: public: Chris@16: //definitions Chris@16: Chris@16: typedef keytype property_set; Chris@16: typedef std::vector > property_map; Chris@16: typedef std::pair, std::pair > vertex_property; Chris@16: typedef std::pair, property_map> vertex_data; Chris@16: typedef std::vector property_merge_data; Chris@16: //typedef std::map Result; Chris@16: typedef std::map scanline_type; Chris@16: typedef typename scanline_type::iterator scanline_iterator; Chris@16: typedef std::pair, std::pair > edge_property; Chris@16: typedef std::vector edge_property_vector; Chris@16: Chris@16: //static public member functions Chris@16: Chris@16: template Chris@16: static inline void Chris@16: populate_property_merge_data(property_merge_data& pmd, iT input_begin, iT input_end, Chris@16: const property_type& property, orientation_2d_type orient) { Chris@16: for( ; input_begin != input_end; ++input_begin) { Chris@16: std::pair, std::pair > element; Chris@16: if(orient == HORIZONTAL) Chris@16: element.first = property_merge_point((*input_begin).second.first, (*input_begin).first); Chris@16: else Chris@16: element.first = property_merge_point((*input_begin).first, (*input_begin).second.first); Chris@16: element.second.first = property; Chris@16: element.second.second = (*input_begin).second.second; Chris@16: pmd.push_back(element); Chris@16: } Chris@16: } Chris@16: Chris@16: //public member functions Chris@16: Chris@16: merge_scanline() : output(), scanline(), currentVertex(), tmpVector(), previousY(), countFromBelow(), scanlinePosition() {} Chris@16: merge_scanline(const merge_scanline& that) : Chris@16: output(that.output), Chris@16: scanline(that.scanline), Chris@16: currentVertex(that.currentVertex), Chris@16: tmpVector(that.tmpVector), Chris@16: previousY(that.previousY), Chris@16: countFromBelow(that.countFromBelow), Chris@16: scanlinePosition(that.scanlinePosition) Chris@16: {} Chris@16: merge_scanline& operator=(const merge_scanline& that) { Chris@16: output = that.output; Chris@16: scanline = that.scanline; Chris@16: currentVertex = that.currentVertex; Chris@16: tmpVector = that.tmpVector; Chris@16: previousY = that.previousY; Chris@16: countFromBelow = that.countFromBelow; Chris@16: scanlinePosition = that.scanlinePosition; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: template Chris@16: inline void perform_merge(result_type& result, property_merge_data& data) { Chris@16: if(data.empty()) return; Chris@16: //sort Chris@16: polygon_sort(data.begin(), data.end(), less_vertex_data()); Chris@16: //scanline Chris@16: bool firstIteration = true; Chris@16: scanlinePosition = scanline.end(); Chris@16: for(std::size_t i = 0; i < data.size(); ++i) { Chris@16: if(firstIteration) { Chris@16: mergeProperty(currentVertex.second, data[i].second); Chris@16: currentVertex.first = data[i].first; Chris@16: firstIteration = false; Chris@16: } else { Chris@16: if(data[i].first != currentVertex.first) { Chris@16: if(data[i].first.x() != currentVertex.first.x()) { Chris@16: processVertex(output); Chris@16: //std::cout << scanline.size() << " "; Chris@16: countFromBelow.clear(); //should already be clear Chris@16: writeOutput(currentVertex.first.x(), result, output); Chris@16: currentVertex.second.clear(); Chris@16: mergeProperty(currentVertex.second, data[i].second); Chris@16: currentVertex.first = data[i].first; Chris@16: //std::cout << assertRedundant(scanline) << "/" << scanline.size() << " "; Chris@16: } else { Chris@16: processVertex(output); Chris@16: currentVertex.second.clear(); Chris@16: mergeProperty(currentVertex.second, data[i].second); Chris@16: currentVertex.first = data[i].first; Chris@16: } Chris@16: } else { Chris@16: mergeProperty(currentVertex.second, data[i].second); Chris@16: } Chris@16: } Chris@16: } Chris@16: processVertex(output); Chris@16: writeOutput(currentVertex.first.x(), result, output); Chris@16: //std::cout << assertRedundant(scanline) << "/" << scanline.size() << "\n"; Chris@16: //std::cout << scanline.size() << "\n"; Chris@16: } Chris@16: Chris@16: private: Chris@16: //private supporting types Chris@16: Chris@16: template Chris@16: class less_vertex_data { Chris@16: public: Chris@16: less_vertex_data() {} Chris@16: bool operator()(const T& lvalue, const T& rvalue) const { Chris@16: if(lvalue.first.x() < rvalue.first.x()) return true; Chris@16: if(lvalue.first.x() > rvalue.first.x()) return false; Chris@16: if(lvalue.first.y() < rvalue.first.y()) return true; Chris@16: return false; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct lessPropertyCount { Chris@16: lessPropertyCount() {} Chris@16: bool operator()(const T& a, const T& b) { Chris@16: return a.first < b.first; Chris@16: } Chris@16: }; Chris@16: Chris@16: //private static member functions Chris@16: Chris@16: static inline void mergeProperty(property_map& lvalue, std::pair& rvalue) { Chris@16: typename property_map::iterator itr = std::lower_bound(lvalue.begin(), lvalue.end(), rvalue, Chris@16: lessPropertyCount >()); Chris@16: if(itr == lvalue.end() || Chris@16: (*itr).first != rvalue.first) { Chris@16: lvalue.insert(itr, rvalue); Chris@16: } else { Chris@16: (*itr).second += rvalue.second; Chris@16: if((*itr).second == 0) Chris@16: lvalue.erase(itr); Chris@16: } Chris@16: // if(assertSorted(lvalue)) { Chris@16: // std::cout << "in mergeProperty\n"; Chris@16: // exit(0); Chris@16: // } Chris@16: } Chris@16: Chris@16: // static inline bool assertSorted(property_map& pset) { Chris@16: // bool result = false; Chris@16: // for(std::size_t i = 1; i < pset.size(); ++i) { Chris@16: // if(pset[i] < pset[i-1]) { Chris@16: // std::cout << "Out of Order Error "; Chris@16: // result = true; Chris@16: // } Chris@16: // if(pset[i].first == pset[i-1].first) { Chris@16: // std::cout << "Duplicate Property Error "; Chris@16: // result = true; Chris@16: // } Chris@16: // if(pset[0].second == 0 || pset[1].second == 0) { Chris@16: // std::cout << "Empty Property Error "; Chris@16: // result = true; Chris@16: // } Chris@16: // } Chris@16: // return result; Chris@16: // } Chris@16: Chris@16: static inline void setProperty(property_set& pset, property_map& pmap) { Chris@16: for(typename property_map::iterator itr = pmap.begin(); itr != pmap.end(); ++itr) { Chris@16: if((*itr).second > 0) { Chris@16: pset.insert(pset.end(), (*itr).first); Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: //private data members Chris@16: Chris@16: edge_property_vector output; Chris@16: scanline_type scanline; Chris@16: vertex_data currentVertex; Chris@16: property_map tmpVector; Chris@16: coordinate_type previousY; Chris@16: property_map countFromBelow; Chris@16: scanline_iterator scanlinePosition; Chris@16: Chris@16: //private member functions Chris@16: Chris@16: inline void mergeCount(property_map& lvalue, property_map& rvalue) { Chris@16: typename property_map::iterator litr = lvalue.begin(); Chris@16: typename property_map::iterator ritr = rvalue.begin(); Chris@16: tmpVector.clear(); Chris@16: while(litr != lvalue.end() && ritr != rvalue.end()) { Chris@16: if((*litr).first <= (*ritr).first) { Chris@16: if(!tmpVector.empty() && Chris@16: (*litr).first == tmpVector.back().first) { Chris@16: tmpVector.back().second += (*litr).second; Chris@16: } else { Chris@16: tmpVector.push_back(*litr); Chris@16: } Chris@16: ++litr; Chris@16: } else if((*ritr).first <= (*litr).first) { Chris@16: if(!tmpVector.empty() && Chris@16: (*ritr).first == tmpVector.back().first) { Chris@16: tmpVector.back().second += (*ritr).second; Chris@16: } else { Chris@16: tmpVector.push_back(*ritr); Chris@16: } Chris@16: ++ritr; Chris@16: } Chris@16: } Chris@16: while(litr != lvalue.end()) { Chris@16: if(!tmpVector.empty() && Chris@16: (*litr).first == tmpVector.back().first) { Chris@16: tmpVector.back().second += (*litr).second; Chris@16: } else { Chris@16: tmpVector.push_back(*litr); Chris@16: } Chris@16: ++litr; Chris@16: } Chris@16: while(ritr != rvalue.end()) { Chris@16: if(!tmpVector.empty() && Chris@16: (*ritr).first == tmpVector.back().first) { Chris@16: tmpVector.back().second += (*ritr).second; Chris@16: } else { Chris@16: tmpVector.push_back(*ritr); Chris@16: } Chris@16: ++ritr; Chris@16: } Chris@16: lvalue.clear(); Chris@16: for(std::size_t i = 0; i < tmpVector.size(); ++i) { Chris@16: if(tmpVector[i].second != 0) { Chris@16: lvalue.push_back(tmpVector[i]); Chris@16: } Chris@16: } Chris@16: // if(assertSorted(lvalue)) { Chris@16: // std::cout << "in mergeCount\n"; Chris@16: // exit(0); Chris@16: // } Chris@16: } Chris@16: Chris@16: inline void processVertex(edge_property_vector& output) { Chris@16: if(!countFromBelow.empty()) { Chris@16: //we are processing an interval of change in scanline state between Chris@16: //previous vertex position and current vertex position where Chris@16: //count from below represents the change on the interval Chris@16: //foreach scanline element from previous to current we Chris@16: //write the interval on the scanline that is changing Chris@16: //the old value and the new value to output Chris@16: property_merge_interval currentInterval(previousY, currentVertex.first.y()); Chris@16: coordinate_type currentY = currentInterval.low(); Chris@16: if(scanlinePosition == scanline.end() || Chris@16: (*scanlinePosition).first != previousY) { Chris@16: scanlinePosition = scanline.lower_bound(previousY); Chris@16: } Chris@16: scanline_iterator previousScanlinePosition = scanlinePosition; Chris@16: ++scanlinePosition; Chris@16: while(scanlinePosition != scanline.end()) { Chris@16: coordinate_type elementY = (*scanlinePosition).first; Chris@16: if(elementY <= currentInterval.high()) { Chris@16: property_map& countOnLeft = (*previousScanlinePosition).second; Chris@16: edge_property element; Chris@16: output.push_back(element); Chris@16: output.back().first = property_merge_interval((*previousScanlinePosition).first, elementY); Chris@16: setProperty(output.back().second.first, countOnLeft); Chris@16: mergeCount(countOnLeft, countFromBelow); Chris@16: setProperty(output.back().second.second, countOnLeft); Chris@16: if(output.back().second.first == output.back().second.second) { Chris@16: output.pop_back(); //it was an internal vertical edge, not to be output Chris@16: } Chris@16: else if(output.size() > 1) { Chris@16: edge_property& secondToLast = output[output.size()-2]; Chris@16: if(secondToLast.first.high() == output.back().first.low() && Chris@16: secondToLast.second.first == output.back().second.first && Chris@16: secondToLast.second.second == output.back().second.second) { Chris@16: //merge output onto previous output because properties are Chris@16: //identical on both sides implying an internal horizontal edge Chris@16: secondToLast.first.high(output.back().first.high()); Chris@16: output.pop_back(); Chris@16: } Chris@16: } Chris@16: if(previousScanlinePosition == scanline.begin()) { Chris@16: if(countOnLeft.empty()) { Chris@16: scanline.erase(previousScanlinePosition); Chris@16: } Chris@16: } else { Chris@16: scanline_iterator tmpitr = previousScanlinePosition; Chris@16: --tmpitr; Chris@16: if((*tmpitr).second == (*previousScanlinePosition).second) Chris@16: scanline.erase(previousScanlinePosition); Chris@16: } Chris@16: Chris@16: } else if(currentY < currentInterval.high()){ Chris@16: //elementY > currentInterval.high() Chris@16: //split the interval between previous and current scanline elements Chris@16: std::pair elementScan; Chris@16: elementScan.first = currentInterval.high(); Chris@16: elementScan.second = (*previousScanlinePosition).second; Chris@16: scanlinePosition = scanline.insert(scanlinePosition, elementScan); Chris@16: continue; Chris@16: } else { Chris@16: break; Chris@16: } Chris@16: previousScanlinePosition = scanlinePosition; Chris@16: currentY = previousY = elementY; Chris@16: ++scanlinePosition; Chris@16: if(scanlinePosition == scanline.end() && Chris@16: currentY < currentInterval.high()) { Chris@16: //insert a new element for top of range Chris@16: std::pair elementScan; Chris@16: elementScan.first = currentInterval.high(); Chris@16: scanlinePosition = scanline.insert(scanline.end(), elementScan); Chris@16: } Chris@16: } Chris@16: if(scanlinePosition == scanline.end() && Chris@16: currentY < currentInterval.high()) { Chris@16: //handle case where we iterated to end of the scanline Chris@16: //we need to insert an element into the scanline at currentY Chris@16: //with property value coming from below Chris@16: //and another one at currentInterval.high() with empty property value Chris@16: mergeCount(scanline[currentY], countFromBelow); Chris@16: std::pair elementScan; Chris@16: elementScan.first = currentInterval.high(); Chris@16: scanline.insert(scanline.end(), elementScan); Chris@16: Chris@16: edge_property element; Chris@16: output.push_back(element); Chris@16: output.back().first = property_merge_interval(currentY, currentInterval.high()); Chris@16: setProperty(output.back().second.second, countFromBelow); Chris@16: mergeCount(countFromBelow, currentVertex.second); Chris@16: } else { Chris@16: mergeCount(countFromBelow, currentVertex.second); Chris@16: if(countFromBelow.empty()) { Chris@16: if(previousScanlinePosition == scanline.begin()) { Chris@16: if((*previousScanlinePosition).second.empty()) { Chris@16: scanline.erase(previousScanlinePosition); Chris@16: //previousScanlinePosition = scanline.end(); Chris@16: //std::cout << "ERASE_A "; Chris@16: } Chris@16: } else { Chris@16: scanline_iterator tmpitr = previousScanlinePosition; Chris@16: --tmpitr; Chris@16: if((*tmpitr).second == (*previousScanlinePosition).second) { Chris@16: scanline.erase(previousScanlinePosition); Chris@16: //previousScanlinePosition = scanline.end(); Chris@16: //std::cout << "ERASE_B "; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: } else { Chris@16: //count from below is empty, we are starting a new interval of change Chris@16: countFromBelow = currentVertex.second; Chris@16: scanlinePosition = scanline.lower_bound(currentVertex.first.y()); Chris@16: if(scanlinePosition != scanline.end()) { Chris@16: if((*scanlinePosition).first != currentVertex.first.y()) { Chris@16: if(scanlinePosition != scanline.begin()) { Chris@16: //decrement to get the lower position of the first interval this vertex intersects Chris@16: --scanlinePosition; Chris@16: //insert a new element into the scanline for the incoming vertex Chris@16: property_map& countOnLeft = (*scanlinePosition).second; Chris@16: std::pair element(currentVertex.first.y(), countOnLeft); Chris@16: scanlinePosition = scanline.insert(scanlinePosition, element); Chris@16: } else { Chris@16: property_map countOnLeft; Chris@16: std::pair element(currentVertex.first.y(), countOnLeft); Chris@16: scanlinePosition = scanline.insert(scanlinePosition, element); Chris@16: } Chris@16: } Chris@16: } else { Chris@16: property_map countOnLeft; Chris@16: std::pair element(currentVertex.first.y(), countOnLeft); Chris@16: scanlinePosition = scanline.insert(scanlinePosition, element); Chris@16: } Chris@16: } Chris@16: previousY = currentVertex.first.y(); Chris@16: } Chris@16: Chris@16: template Chris@16: inline int assertRedundant(T& t) { Chris@16: if(t.empty()) return 0; Chris@16: int count = 0; Chris@16: typename T::iterator itr = t.begin(); Chris@16: if((*itr).second.empty()) Chris@16: ++count; Chris@16: typename T::iterator itr2 = itr; Chris@16: ++itr2; Chris@16: while(itr2 != t.end()) { Chris@16: if((*itr).second == (*itr2).second) Chris@16: ++count; Chris@16: itr = itr2; Chris@16: ++itr2; Chris@16: } Chris@16: return count; Chris@16: } Chris@16: Chris@16: template Chris@16: inline void performExtract(T& result, property_merge_data& data) { Chris@16: if(data.empty()) return; Chris@16: //sort Chris@16: polygon_sort(data.begin(), data.end(), less_vertex_data()); Chris@16: Chris@16: //scanline Chris@16: bool firstIteration = true; Chris@16: scanlinePosition = scanline.end(); Chris@16: for(std::size_t i = 0; i < data.size(); ++i) { Chris@16: if(firstIteration) { Chris@16: mergeProperty(currentVertex.second, data[i].second); Chris@16: currentVertex.first = data[i].first; Chris@16: firstIteration = false; Chris@16: } else { Chris@16: if(data[i].first != currentVertex.first) { Chris@16: if(data[i].first.x() != currentVertex.first.x()) { Chris@16: processVertex(output); Chris@16: //std::cout << scanline.size() << " "; Chris@16: countFromBelow.clear(); //should already be clear Chris@16: writeGraph(currentVertex.first.x(), result, output, scanline); Chris@16: currentVertex.second.clear(); Chris@16: mergeProperty(currentVertex.second, data[i].second); Chris@16: currentVertex.first = data[i].first; Chris@16: } else { Chris@16: processVertex(output); Chris@16: currentVertex.second.clear(); Chris@16: mergeProperty(currentVertex.second, data[i].second); Chris@16: currentVertex.first = data[i].first; Chris@16: } Chris@16: } else { Chris@16: mergeProperty(currentVertex.second, data[i].second); Chris@16: } Chris@16: } Chris@16: } Chris@16: processVertex(output); Chris@16: writeGraph(currentVertex.first.x(), result, output, scanline); Chris@16: //std::cout << scanline.size() << "\n"; Chris@16: } Chris@16: Chris@16: template Chris@16: inline void insertEdges(T& graph, property_set& p1, property_set& p2) { Chris@16: for(typename property_set::iterator itr = p1.begin(); itr != p1.end(); ++itr) { Chris@16: for(typename property_set::iterator itr2 = p2.begin(); itr2 != p2.end(); ++itr2) { Chris@16: if(*itr != *itr2) { Chris@16: graph[*itr].insert(*itr2); Chris@16: graph[*itr2].insert(*itr); Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: inline void propertySetAbove(coordinate_type y, property_set& ps, T& scanline) { Chris@16: ps.clear(); Chris@16: typename T::iterator itr = scanline.find(y); Chris@16: if(itr != scanline.end()) Chris@16: setProperty(ps, (*itr).second); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void propertySetBelow(coordinate_type y, property_set& ps, T& scanline) { Chris@16: ps.clear(); Chris@16: typename T::iterator itr = scanline.find(y); Chris@16: if(itr != scanline.begin()) { Chris@16: --itr; Chris@16: setProperty(ps, (*itr).second); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: inline void writeGraph(coordinate_type x, T& graph, edge_property_vector& output, T2& scanline) { Chris@16: if(output.empty()) return; Chris@16: edge_property* previousEdgeP = &(output[0]); Chris@16: bool firstIteration = true; Chris@16: property_set ps; Chris@16: for(std::size_t i = 0; i < output.size(); ++i) { Chris@16: edge_property& previousEdge = *previousEdgeP; Chris@16: edge_property& edge = output[i]; Chris@16: if(previousEdge.first.high() == edge.first.low()) { Chris@16: //horizontal edge Chris@16: insertEdges(graph, edge.second.first, previousEdge.second.first); Chris@16: //corner 1 Chris@16: insertEdges(graph, edge.second.first, previousEdge.second.second); Chris@16: //other horizontal edge Chris@16: insertEdges(graph, edge.second.second, previousEdge.second.second); Chris@16: //corner 2 Chris@16: insertEdges(graph, edge.second.second, previousEdge.second.first); Chris@16: } else { Chris@16: if(!firstIteration){ Chris@16: //look up regions above previous edge Chris@16: propertySetAbove(previousEdge.first.high(), ps, scanline); Chris@16: insertEdges(graph, ps, previousEdge.second.first); Chris@16: insertEdges(graph, ps, previousEdge.second.second); Chris@16: } Chris@16: //look up regions below current edge in the scanline Chris@16: propertySetBelow(edge.first.high(), ps, scanline); Chris@16: insertEdges(graph, ps, edge.second.first); Chris@16: insertEdges(graph, ps, edge.second.second); Chris@16: } Chris@16: firstIteration = false; Chris@16: //vertical edge Chris@16: insertEdges(graph, edge.second.second, edge.second.first); Chris@16: //shared region to left Chris@16: insertEdges(graph, edge.second.second, edge.second.second); Chris@16: //shared region to right Chris@16: insertEdges(graph, edge.second.first, edge.second.first); Chris@16: previousEdgeP = &(output[i]); Chris@16: } Chris@16: edge_property& previousEdge = *previousEdgeP; Chris@16: propertySetAbove(previousEdge.first.high(), ps, scanline); Chris@16: insertEdges(graph, ps, previousEdge.second.first); Chris@16: insertEdges(graph, ps, previousEdge.second.second); Chris@16: output.clear(); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void writeOutput(coordinate_type x, Result& result, edge_property_vector& output) { Chris@16: for(std::size_t i = 0; i < output.size(); ++i) { Chris@16: edge_property& edge = output[i]; Chris@16: //edge.second.first is the property set on the left of the edge Chris@16: if(!edge.second.first.empty()) { Chris@16: typename Result::iterator itr = result.find(edge.second.first); Chris@16: if(itr == result.end()) { Chris@16: std::pair element(edge.second.first, polygon_set_type(VERTICAL)); Chris@16: itr = result.insert(result.end(), element); Chris@16: } Chris@16: std::pair, int> element2(interval_data(edge.first.low(), edge.first.high()), -1); //right edge of figure Chris@16: (*itr).second.insert(x, element2); Chris@16: } Chris@16: if(!edge.second.second.empty()) { Chris@16: //edge.second.second is the property set on the right of the edge Chris@16: typename Result::iterator itr = result.find(edge.second.second); Chris@16: if(itr == result.end()) { Chris@16: std::pair element(edge.second.second, polygon_set_type(VERTICAL)); Chris@16: itr = result.insert(result.end(), element); Chris@16: } Chris@16: std::pair, int> element3(interval_data(edge.first.low(), edge.first.high()), 1); //left edge of figure Chris@16: (*itr).second.insert(x, element3); Chris@16: } Chris@16: } Chris@16: output.clear(); Chris@16: } Chris@16: }; Chris@16: Chris@16: } Chris@16: } Chris@16: #endif