property_merge.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. /*
  2. Copyright 2008 Intel Corporation
  3. Use, modification and distribution are subject to the Boost Software License,
  4. Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. */
  7. #ifndef BOOST_POLYGON_PROPERTY_MERGE_HPP
  8. #define BOOST_POLYGON_PROPERTY_MERGE_HPP
  9. namespace boost { namespace polygon{
  10. template <typename coordinate_type>
  11. class property_merge_point {
  12. private:
  13. coordinate_type x_, y_;
  14. public:
  15. inline property_merge_point() : x_(), y_() {}
  16. inline property_merge_point(coordinate_type x, coordinate_type y) : x_(x), y_(y) {}
  17. //use builtin assign and copy
  18. inline bool operator==(const property_merge_point& that) const { return x_ == that.x_ && y_ == that.y_; }
  19. inline bool operator!=(const property_merge_point& that) const { return !((*this) == that); }
  20. inline bool operator<(const property_merge_point& that) const {
  21. if(x_ < that.x_) return true;
  22. if(x_ > that.x_) return false;
  23. return y_ < that.y_;
  24. }
  25. inline coordinate_type x() const { return x_; }
  26. inline coordinate_type y() const { return y_; }
  27. inline void x(coordinate_type value) { x_ = value; }
  28. inline void y(coordinate_type value) { y_ = value; }
  29. };
  30. template <typename coordinate_type>
  31. class property_merge_interval {
  32. private:
  33. coordinate_type low_, high_;
  34. public:
  35. inline property_merge_interval() : low_(), high_() {}
  36. inline property_merge_interval(coordinate_type low, coordinate_type high) : low_(low), high_(high) {}
  37. //use builtin assign and copy
  38. inline bool operator==(const property_merge_interval& that) const { return low_ == that.low_ && high_ == that.high_; }
  39. inline bool operator!=(const property_merge_interval& that) const { return !((*this) == that); }
  40. inline bool operator<(const property_merge_interval& that) const {
  41. if(low_ < that.low_) return true;
  42. if(low_ > that.low_) return false;
  43. return high_ < that.high_;
  44. }
  45. inline coordinate_type low() const { return low_; }
  46. inline coordinate_type high() const { return high_; }
  47. inline void low(coordinate_type value) { low_ = value; }
  48. inline void high(coordinate_type value) { high_ = value; }
  49. };
  50. template <typename coordinate_type, typename property_type, typename polygon_set_type, typename keytype = std::set<property_type> >
  51. class merge_scanline {
  52. public:
  53. //definitions
  54. typedef keytype property_set;
  55. typedef std::vector<std::pair<property_type, int> > property_map;
  56. typedef std::pair<property_merge_point<coordinate_type>, std::pair<property_type, int> > vertex_property;
  57. typedef std::pair<property_merge_point<coordinate_type>, property_map> vertex_data;
  58. typedef std::vector<vertex_property> property_merge_data;
  59. //typedef std::map<property_set, polygon_set_type> Result;
  60. typedef std::map<coordinate_type, property_map> scanline_type;
  61. typedef typename scanline_type::iterator scanline_iterator;
  62. typedef std::pair<property_merge_interval<coordinate_type>, std::pair<property_set, property_set> > edge_property;
  63. typedef std::vector<edge_property> edge_property_vector;
  64. //static public member functions
  65. template <typename iT, typename orientation_2d_type>
  66. static inline void
  67. populate_property_merge_data(property_merge_data& pmd, iT input_begin, iT input_end,
  68. const property_type& property, orientation_2d_type orient) {
  69. for( ; input_begin != input_end; ++input_begin) {
  70. std::pair<property_merge_point<coordinate_type>, std::pair<property_type, int> > element;
  71. if(orient == HORIZONTAL)
  72. element.first = property_merge_point<coordinate_type>((*input_begin).second.first, (*input_begin).first);
  73. else
  74. element.first = property_merge_point<coordinate_type>((*input_begin).first, (*input_begin).second.first);
  75. element.second.first = property;
  76. element.second.second = (*input_begin).second.second;
  77. pmd.push_back(element);
  78. }
  79. }
  80. //public member functions
  81. merge_scanline() : output(), scanline(), currentVertex(), tmpVector(), previousY(), countFromBelow(), scanlinePosition() {}
  82. merge_scanline(const merge_scanline& that) :
  83. output(that.output),
  84. scanline(that.scanline),
  85. currentVertex(that.currentVertex),
  86. tmpVector(that.tmpVector),
  87. previousY(that.previousY),
  88. countFromBelow(that.countFromBelow),
  89. scanlinePosition(that.scanlinePosition)
  90. {}
  91. merge_scanline& operator=(const merge_scanline& that) {
  92. output = that.output;
  93. scanline = that.scanline;
  94. currentVertex = that.currentVertex;
  95. tmpVector = that.tmpVector;
  96. previousY = that.previousY;
  97. countFromBelow = that.countFromBelow;
  98. scanlinePosition = that.scanlinePosition;
  99. return *this;
  100. }
  101. template <typename result_type>
  102. inline void perform_merge(result_type& result, property_merge_data& data) {
  103. if(data.empty()) return;
  104. //sort
  105. polygon_sort(data.begin(), data.end(), less_vertex_data<vertex_property>());
  106. //scanline
  107. bool firstIteration = true;
  108. scanlinePosition = scanline.end();
  109. for(std::size_t i = 0; i < data.size(); ++i) {
  110. if(firstIteration) {
  111. mergeProperty(currentVertex.second, data[i].second);
  112. currentVertex.first = data[i].first;
  113. firstIteration = false;
  114. } else {
  115. if(data[i].first != currentVertex.first) {
  116. if(data[i].first.x() != currentVertex.first.x()) {
  117. processVertex(output);
  118. //std::cout << scanline.size() << " ";
  119. countFromBelow.clear(); //should already be clear
  120. writeOutput(currentVertex.first.x(), result, output);
  121. currentVertex.second.clear();
  122. mergeProperty(currentVertex.second, data[i].second);
  123. currentVertex.first = data[i].first;
  124. //std::cout << assertRedundant(scanline) << "/" << scanline.size() << " ";
  125. } else {
  126. processVertex(output);
  127. currentVertex.second.clear();
  128. mergeProperty(currentVertex.second, data[i].second);
  129. currentVertex.first = data[i].first;
  130. }
  131. } else {
  132. mergeProperty(currentVertex.second, data[i].second);
  133. }
  134. }
  135. }
  136. processVertex(output);
  137. writeOutput(currentVertex.first.x(), result, output);
  138. //std::cout << assertRedundant(scanline) << "/" << scanline.size() << "\n";
  139. //std::cout << scanline.size() << "\n";
  140. }
  141. private:
  142. //private supporting types
  143. template <class T>
  144. class less_vertex_data {
  145. public:
  146. less_vertex_data() {}
  147. bool operator()(const T& lvalue, const T& rvalue) const {
  148. if(lvalue.first.x() < rvalue.first.x()) return true;
  149. if(lvalue.first.x() > rvalue.first.x()) return false;
  150. if(lvalue.first.y() < rvalue.first.y()) return true;
  151. return false;
  152. }
  153. };
  154. template <typename T>
  155. struct lessPropertyCount {
  156. lessPropertyCount() {}
  157. bool operator()(const T& a, const T& b) {
  158. return a.first < b.first;
  159. }
  160. };
  161. //private static member functions
  162. static inline void mergeProperty(property_map& lvalue, std::pair<property_type, int>& rvalue) {
  163. typename property_map::iterator itr = std::lower_bound(lvalue.begin(), lvalue.end(), rvalue,
  164. lessPropertyCount<std::pair<property_type, int> >());
  165. if(itr == lvalue.end() ||
  166. (*itr).first != rvalue.first) {
  167. lvalue.insert(itr, rvalue);
  168. } else {
  169. (*itr).second += rvalue.second;
  170. if((*itr).second == 0)
  171. lvalue.erase(itr);
  172. }
  173. // if(assertSorted(lvalue)) {
  174. // std::cout << "in mergeProperty\n";
  175. // exit(0);
  176. // }
  177. }
  178. // static inline bool assertSorted(property_map& pset) {
  179. // bool result = false;
  180. // for(std::size_t i = 1; i < pset.size(); ++i) {
  181. // if(pset[i] < pset[i-1]) {
  182. // std::cout << "Out of Order Error ";
  183. // result = true;
  184. // }
  185. // if(pset[i].first == pset[i-1].first) {
  186. // std::cout << "Duplicate Property Error ";
  187. // result = true;
  188. // }
  189. // if(pset[0].second == 0 || pset[1].second == 0) {
  190. // std::cout << "Empty Property Error ";
  191. // result = true;
  192. // }
  193. // }
  194. // return result;
  195. // }
  196. static inline void setProperty(property_set& pset, property_map& pmap) {
  197. for(typename property_map::iterator itr = pmap.begin(); itr != pmap.end(); ++itr) {
  198. if((*itr).second > 0) {
  199. pset.insert(pset.end(), (*itr).first);
  200. }
  201. }
  202. }
  203. //private data members
  204. edge_property_vector output;
  205. scanline_type scanline;
  206. vertex_data currentVertex;
  207. property_map tmpVector;
  208. coordinate_type previousY;
  209. property_map countFromBelow;
  210. scanline_iterator scanlinePosition;
  211. //private member functions
  212. inline void mergeCount(property_map& lvalue, property_map& rvalue) {
  213. typename property_map::iterator litr = lvalue.begin();
  214. typename property_map::iterator ritr = rvalue.begin();
  215. tmpVector.clear();
  216. while(litr != lvalue.end() && ritr != rvalue.end()) {
  217. if((*litr).first <= (*ritr).first) {
  218. if(!tmpVector.empty() &&
  219. (*litr).first == tmpVector.back().first) {
  220. tmpVector.back().second += (*litr).second;
  221. } else {
  222. tmpVector.push_back(*litr);
  223. }
  224. ++litr;
  225. } else if((*ritr).first <= (*litr).first) {
  226. if(!tmpVector.empty() &&
  227. (*ritr).first == tmpVector.back().first) {
  228. tmpVector.back().second += (*ritr).second;
  229. } else {
  230. tmpVector.push_back(*ritr);
  231. }
  232. ++ritr;
  233. }
  234. }
  235. while(litr != lvalue.end()) {
  236. if(!tmpVector.empty() &&
  237. (*litr).first == tmpVector.back().first) {
  238. tmpVector.back().second += (*litr).second;
  239. } else {
  240. tmpVector.push_back(*litr);
  241. }
  242. ++litr;
  243. }
  244. while(ritr != rvalue.end()) {
  245. if(!tmpVector.empty() &&
  246. (*ritr).first == tmpVector.back().first) {
  247. tmpVector.back().second += (*ritr).second;
  248. } else {
  249. tmpVector.push_back(*ritr);
  250. }
  251. ++ritr;
  252. }
  253. lvalue.clear();
  254. for(std::size_t i = 0; i < tmpVector.size(); ++i) {
  255. if(tmpVector[i].second != 0) {
  256. lvalue.push_back(tmpVector[i]);
  257. }
  258. }
  259. // if(assertSorted(lvalue)) {
  260. // std::cout << "in mergeCount\n";
  261. // exit(0);
  262. // }
  263. }
  264. inline void processVertex(edge_property_vector& output) {
  265. if(!countFromBelow.empty()) {
  266. //we are processing an interval of change in scanline state between
  267. //previous vertex position and current vertex position where
  268. //count from below represents the change on the interval
  269. //foreach scanline element from previous to current we
  270. //write the interval on the scanline that is changing
  271. //the old value and the new value to output
  272. property_merge_interval<coordinate_type> currentInterval(previousY, currentVertex.first.y());
  273. coordinate_type currentY = currentInterval.low();
  274. if(scanlinePosition == scanline.end() ||
  275. (*scanlinePosition).first != previousY) {
  276. scanlinePosition = scanline.lower_bound(previousY);
  277. }
  278. scanline_iterator previousScanlinePosition = scanlinePosition;
  279. ++scanlinePosition;
  280. while(scanlinePosition != scanline.end()) {
  281. coordinate_type elementY = (*scanlinePosition).first;
  282. if(elementY <= currentInterval.high()) {
  283. property_map& countOnLeft = (*previousScanlinePosition).second;
  284. edge_property element;
  285. output.push_back(element);
  286. output.back().first = property_merge_interval<coordinate_type>((*previousScanlinePosition).first, elementY);
  287. setProperty(output.back().second.first, countOnLeft);
  288. mergeCount(countOnLeft, countFromBelow);
  289. setProperty(output.back().second.second, countOnLeft);
  290. if(output.back().second.first == output.back().second.second) {
  291. output.pop_back(); //it was an internal vertical edge, not to be output
  292. }
  293. else if(output.size() > 1) {
  294. edge_property& secondToLast = output[output.size()-2];
  295. if(secondToLast.first.high() == output.back().first.low() &&
  296. secondToLast.second.first == output.back().second.first &&
  297. secondToLast.second.second == output.back().second.second) {
  298. //merge output onto previous output because properties are
  299. //identical on both sides implying an internal horizontal edge
  300. secondToLast.first.high(output.back().first.high());
  301. output.pop_back();
  302. }
  303. }
  304. if(previousScanlinePosition == scanline.begin()) {
  305. if(countOnLeft.empty()) {
  306. scanline.erase(previousScanlinePosition);
  307. }
  308. } else {
  309. scanline_iterator tmpitr = previousScanlinePosition;
  310. --tmpitr;
  311. if((*tmpitr).second == (*previousScanlinePosition).second)
  312. scanline.erase(previousScanlinePosition);
  313. }
  314. } else if(currentY < currentInterval.high()){
  315. //elementY > currentInterval.high()
  316. //split the interval between previous and current scanline elements
  317. std::pair<coordinate_type, property_map> elementScan;
  318. elementScan.first = currentInterval.high();
  319. elementScan.second = (*previousScanlinePosition).second;
  320. scanlinePosition = scanline.insert(scanlinePosition, elementScan);
  321. continue;
  322. } else {
  323. break;
  324. }
  325. previousScanlinePosition = scanlinePosition;
  326. currentY = previousY = elementY;
  327. ++scanlinePosition;
  328. if(scanlinePosition == scanline.end() &&
  329. currentY < currentInterval.high()) {
  330. //insert a new element for top of range
  331. std::pair<coordinate_type, property_map> elementScan;
  332. elementScan.first = currentInterval.high();
  333. scanlinePosition = scanline.insert(scanline.end(), elementScan);
  334. }
  335. }
  336. if(scanlinePosition == scanline.end() &&
  337. currentY < currentInterval.high()) {
  338. //handle case where we iterated to end of the scanline
  339. //we need to insert an element into the scanline at currentY
  340. //with property value coming from below
  341. //and another one at currentInterval.high() with empty property value
  342. mergeCount(scanline[currentY], countFromBelow);
  343. std::pair<coordinate_type, property_map> elementScan;
  344. elementScan.first = currentInterval.high();
  345. scanline.insert(scanline.end(), elementScan);
  346. edge_property element;
  347. output.push_back(element);
  348. output.back().first = property_merge_interval<coordinate_type>(currentY, currentInterval.high());
  349. setProperty(output.back().second.second, countFromBelow);
  350. mergeCount(countFromBelow, currentVertex.second);
  351. } else {
  352. mergeCount(countFromBelow, currentVertex.second);
  353. if(countFromBelow.empty()) {
  354. if(previousScanlinePosition == scanline.begin()) {
  355. if((*previousScanlinePosition).second.empty()) {
  356. scanline.erase(previousScanlinePosition);
  357. //previousScanlinePosition = scanline.end();
  358. //std::cout << "ERASE_A ";
  359. }
  360. } else {
  361. scanline_iterator tmpitr = previousScanlinePosition;
  362. --tmpitr;
  363. if((*tmpitr).second == (*previousScanlinePosition).second) {
  364. scanline.erase(previousScanlinePosition);
  365. //previousScanlinePosition = scanline.end();
  366. //std::cout << "ERASE_B ";
  367. }
  368. }
  369. }
  370. }
  371. } else {
  372. //count from below is empty, we are starting a new interval of change
  373. countFromBelow = currentVertex.second;
  374. scanlinePosition = scanline.lower_bound(currentVertex.first.y());
  375. if(scanlinePosition != scanline.end()) {
  376. if((*scanlinePosition).first != currentVertex.first.y()) {
  377. if(scanlinePosition != scanline.begin()) {
  378. //decrement to get the lower position of the first interval this vertex intersects
  379. --scanlinePosition;
  380. //insert a new element into the scanline for the incoming vertex
  381. property_map& countOnLeft = (*scanlinePosition).second;
  382. std::pair<coordinate_type, property_map> element(currentVertex.first.y(), countOnLeft);
  383. scanlinePosition = scanline.insert(scanlinePosition, element);
  384. } else {
  385. property_map countOnLeft;
  386. std::pair<coordinate_type, property_map> element(currentVertex.first.y(), countOnLeft);
  387. scanlinePosition = scanline.insert(scanlinePosition, element);
  388. }
  389. }
  390. } else {
  391. property_map countOnLeft;
  392. std::pair<coordinate_type, property_map> element(currentVertex.first.y(), countOnLeft);
  393. scanlinePosition = scanline.insert(scanlinePosition, element);
  394. }
  395. }
  396. previousY = currentVertex.first.y();
  397. }
  398. template <typename T>
  399. inline int assertRedundant(T& t) {
  400. if(t.empty()) return 0;
  401. int count = 0;
  402. typename T::iterator itr = t.begin();
  403. if((*itr).second.empty())
  404. ++count;
  405. typename T::iterator itr2 = itr;
  406. ++itr2;
  407. while(itr2 != t.end()) {
  408. if((*itr).second == (*itr2).second)
  409. ++count;
  410. itr = itr2;
  411. ++itr2;
  412. }
  413. return count;
  414. }
  415. template <typename T>
  416. inline void performExtract(T& result, property_merge_data& data) {
  417. if(data.empty()) return;
  418. //sort
  419. polygon_sort(data.begin(), data.end(), less_vertex_data<vertex_property>());
  420. //scanline
  421. bool firstIteration = true;
  422. scanlinePosition = scanline.end();
  423. for(std::size_t i = 0; i < data.size(); ++i) {
  424. if(firstIteration) {
  425. mergeProperty(currentVertex.second, data[i].second);
  426. currentVertex.first = data[i].first;
  427. firstIteration = false;
  428. } else {
  429. if(data[i].first != currentVertex.first) {
  430. if(data[i].first.x() != currentVertex.first.x()) {
  431. processVertex(output);
  432. //std::cout << scanline.size() << " ";
  433. countFromBelow.clear(); //should already be clear
  434. writeGraph(result, output, scanline);
  435. currentVertex.second.clear();
  436. mergeProperty(currentVertex.second, data[i].second);
  437. currentVertex.first = data[i].first;
  438. } else {
  439. processVertex(output);
  440. currentVertex.second.clear();
  441. mergeProperty(currentVertex.second, data[i].second);
  442. currentVertex.first = data[i].first;
  443. }
  444. } else {
  445. mergeProperty(currentVertex.second, data[i].second);
  446. }
  447. }
  448. }
  449. processVertex(output);
  450. writeGraph(result, output, scanline);
  451. //std::cout << scanline.size() << "\n";
  452. }
  453. template <typename T>
  454. inline void insertEdges(T& graph, property_set& p1, property_set& p2) {
  455. for(typename property_set::iterator itr = p1.begin(); itr != p1.end(); ++itr) {
  456. for(typename property_set::iterator itr2 = p2.begin(); itr2 != p2.end(); ++itr2) {
  457. if(*itr != *itr2) {
  458. graph[*itr].insert(*itr2);
  459. graph[*itr2].insert(*itr);
  460. }
  461. }
  462. }
  463. }
  464. template <typename T>
  465. inline void propertySetAbove(coordinate_type y, property_set& ps, T& scanline) {
  466. ps.clear();
  467. typename T::iterator itr = scanline.find(y);
  468. if(itr != scanline.end())
  469. setProperty(ps, (*itr).second);
  470. }
  471. template <typename T>
  472. inline void propertySetBelow(coordinate_type y, property_set& ps, T& scanline) {
  473. ps.clear();
  474. typename T::iterator itr = scanline.find(y);
  475. if(itr != scanline.begin()) {
  476. --itr;
  477. setProperty(ps, (*itr).second);
  478. }
  479. }
  480. template <typename T, typename T2>
  481. inline void writeGraph(T& graph, edge_property_vector& output, T2& scanline) {
  482. if(output.empty()) return;
  483. edge_property* previousEdgeP = &(output[0]);
  484. bool firstIteration = true;
  485. property_set ps;
  486. for(std::size_t i = 0; i < output.size(); ++i) {
  487. edge_property& previousEdge = *previousEdgeP;
  488. edge_property& edge = output[i];
  489. if(previousEdge.first.high() == edge.first.low()) {
  490. //horizontal edge
  491. insertEdges(graph, edge.second.first, previousEdge.second.first);
  492. //corner 1
  493. insertEdges(graph, edge.second.first, previousEdge.second.second);
  494. //other horizontal edge
  495. insertEdges(graph, edge.second.second, previousEdge.second.second);
  496. //corner 2
  497. insertEdges(graph, edge.second.second, previousEdge.second.first);
  498. } else {
  499. if(!firstIteration){
  500. //look up regions above previous edge
  501. propertySetAbove(previousEdge.first.high(), ps, scanline);
  502. insertEdges(graph, ps, previousEdge.second.first);
  503. insertEdges(graph, ps, previousEdge.second.second);
  504. }
  505. //look up regions below current edge in the scanline
  506. propertySetBelow(edge.first.high(), ps, scanline);
  507. insertEdges(graph, ps, edge.second.first);
  508. insertEdges(graph, ps, edge.second.second);
  509. }
  510. firstIteration = false;
  511. //vertical edge
  512. insertEdges(graph, edge.second.second, edge.second.first);
  513. //shared region to left
  514. insertEdges(graph, edge.second.second, edge.second.second);
  515. //shared region to right
  516. insertEdges(graph, edge.second.first, edge.second.first);
  517. previousEdgeP = &(output[i]);
  518. }
  519. edge_property& previousEdge = *previousEdgeP;
  520. propertySetAbove(previousEdge.first.high(), ps, scanline);
  521. insertEdges(graph, ps, previousEdge.second.first);
  522. insertEdges(graph, ps, previousEdge.second.second);
  523. output.clear();
  524. }
  525. template <typename Result>
  526. inline void writeOutput(coordinate_type x, Result& result, edge_property_vector& output) {
  527. for(std::size_t i = 0; i < output.size(); ++i) {
  528. edge_property& edge = output[i];
  529. //edge.second.first is the property set on the left of the edge
  530. if(!edge.second.first.empty()) {
  531. typename Result::iterator itr = result.find(edge.second.first);
  532. if(itr == result.end()) {
  533. std::pair<property_set, polygon_set_type> element(edge.second.first, polygon_set_type(VERTICAL));
  534. itr = result.insert(result.end(), element);
  535. }
  536. std::pair<interval_data<coordinate_type>, int> element2(interval_data<coordinate_type>(edge.first.low(), edge.first.high()), -1); //right edge of figure
  537. (*itr).second.insert(x, element2);
  538. }
  539. if(!edge.second.second.empty()) {
  540. //edge.second.second is the property set on the right of the edge
  541. typename Result::iterator itr = result.find(edge.second.second);
  542. if(itr == result.end()) {
  543. std::pair<property_set, polygon_set_type> element(edge.second.second, polygon_set_type(VERTICAL));
  544. itr = result.insert(result.end(), element);
  545. }
  546. std::pair<interval_data<coordinate_type>, int> element3(interval_data<coordinate_type>(edge.first.low(), edge.first.high()), 1); //left edge of figure
  547. (*itr).second.insert(x, element3);
  548. }
  549. }
  550. output.clear();
  551. }
  552. };
  553. }
  554. }
  555. #endif