max_cover.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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_MAX_COVER_HPP
  8. #define BOOST_POLYGON_MAX_COVER_HPP
  9. namespace boost { namespace polygon{
  10. template <typename Unit>
  11. struct MaxCover {
  12. typedef interval_data<Unit> Interval;
  13. typedef rectangle_data<Unit> Rectangle;
  14. class Node {
  15. private:
  16. std::vector<Node*> children_;
  17. std::set<Interval> tracedPaths_;
  18. public:
  19. Rectangle rect;
  20. Node() : children_(), tracedPaths_(), rect() {}
  21. Node(const Rectangle rectIn) : children_(), tracedPaths_(), rect(rectIn) {}
  22. typedef typename std::vector<Node*>::iterator iterator;
  23. inline iterator begin() { return children_.begin(); }
  24. inline iterator end() { return children_.end(); }
  25. inline void add(Node* child) { children_.push_back(child); }
  26. inline bool tracedPath(const Interval& ivl) const {
  27. return tracedPaths_.find(ivl) != tracedPaths_.end();
  28. }
  29. inline void addPath(const Interval& ivl) {
  30. tracedPaths_.insert(tracedPaths_.end(), ivl);
  31. }
  32. };
  33. typedef std::pair<std::pair<Unit, Interval>, Node* > EdgeAssociation;
  34. class lessEdgeAssociation : public std::binary_function<const EdgeAssociation&, const EdgeAssociation&, bool> {
  35. public:
  36. inline lessEdgeAssociation() {}
  37. inline bool operator () (const EdgeAssociation& elem1, const EdgeAssociation& elem2) const {
  38. if(elem1.first.first < elem2.first.first) return true;
  39. if(elem1.first.first > elem2.first.first) return false;
  40. return elem1.first.second < elem2.first.second;
  41. }
  42. };
  43. template <class cT>
  44. static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient) {
  45. Interval rectIvl = node->rect.get(orient);
  46. if(node->tracedPath(rectIvl)) {
  47. return;
  48. }
  49. node->addPath(rectIvl);
  50. if(node->begin() == node->end()) {
  51. //std::cout << "WRITE OUT 3: " << node->rect << std::endl;
  52. outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(node->rect));
  53. return;
  54. }
  55. bool writeOut = true;
  56. for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) {
  57. getMaxCover(outputContainer, *itr, orient, node->rect); //get rectangles down path
  58. Interval nodeIvl = (*itr)->rect.get(orient);
  59. if(contains(nodeIvl, rectIvl, true)) writeOut = false;
  60. }
  61. if(writeOut) {
  62. //std::cout << "WRITE OUT 2: " << node->rect << std::endl;
  63. outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(node->rect));
  64. }
  65. }
  66. struct stack_element {
  67. inline stack_element() :
  68. node(), rect(), itr() {}
  69. inline stack_element(Node* n,
  70. const Rectangle& r,
  71. typename Node::iterator i) :
  72. node(n), rect(r), itr(i) {}
  73. Node* node;
  74. Rectangle rect;
  75. typename Node::iterator itr;
  76. };
  77. template <class cT>
  78. static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient,
  79. Rectangle rect) {
  80. //std::cout << "New Root\n";
  81. std::vector<stack_element> stack;
  82. typename Node::iterator itr = node->begin();
  83. do {
  84. //std::cout << "LOOP\n";
  85. //std::cout << node->rect << std::endl;
  86. Interval rectIvl = rect.get(orient);
  87. Interval nodeIvl = node->rect.get(orient);
  88. bool iresult = intersect(rectIvl, nodeIvl, false);
  89. bool tresult = !node->tracedPath(rectIvl);
  90. //std::cout << (itr != node->end()) << " " << iresult << " " << tresult << std::endl;
  91. Rectangle nextRect1 = Rectangle(rectIvl, rectIvl);
  92. Unit low = rect.get(orient.get_perpendicular()).low();
  93. Unit high = node->rect.get(orient.get_perpendicular()).high();
  94. nextRect1.set(orient.get_perpendicular(), Interval(low, high));
  95. if(iresult && tresult) {
  96. node->addPath(rectIvl);
  97. bool writeOut = true;
  98. //check further visibility beyond this node
  99. for(typename Node::iterator itr2 = node->begin(); itr2 != node->end(); ++itr2) {
  100. Interval nodeIvl3 = (*itr2)->rect.get(orient);
  101. //if a child of this node can contain the interval then we can extend through
  102. if(contains(nodeIvl3, rectIvl, true)) writeOut = false;
  103. //std::cout << "child " << (*itr2)->rect << std::endl;
  104. }
  105. Rectangle nextRect2 = Rectangle(rectIvl, rectIvl);
  106. Unit low2 = rect.get(orient.get_perpendicular()).low();
  107. Unit high2 = node->rect.get(orient.get_perpendicular()).high();
  108. nextRect2.set(orient.get_perpendicular(), Interval(low2, high2));
  109. if(writeOut) {
  110. //std::cout << "write out " << nextRect << std::endl;
  111. outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect2));
  112. } else {
  113. //std::cout << "suppress " << nextRect << std::endl;
  114. }
  115. }
  116. if(itr != node->end() && iresult && tresult) {
  117. //std::cout << "recurse into child\n";
  118. stack.push_back(stack_element(node, rect, itr));
  119. rect = nextRect1;
  120. node = *itr;
  121. itr = node->begin();
  122. } else {
  123. if(!stack.empty()) {
  124. //std::cout << "recurse out of child\n";
  125. node = stack.back().node;
  126. rect = stack.back().rect;
  127. itr = stack.back().itr;
  128. stack.pop_back();
  129. } else {
  130. //std::cout << "empty stack\n";
  131. //if there were no children of the root node
  132. // Rectangle nextRect = Rectangle(rectIvl, rectIvl);
  133. // Unit low = rect.get(orient.get_perpendicular()).low();
  134. // Unit high = node->rect.get(orient.get_perpendicular()).high();
  135. // nextRect.set(orient.get_perpendicular(), Interval(low, high));
  136. // outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect));
  137. }
  138. //std::cout << "increment " << (itr != node->end()) << std::endl;
  139. if(itr != node->end()) {
  140. ++itr;
  141. if(itr != node->end()) {
  142. //std::cout << "recurse into next child.\n";
  143. stack.push_back(stack_element(node, rect, itr));
  144. Interval rectIvl2 = rect.get(orient);
  145. Interval nodeIvl2 = node->rect.get(orient);
  146. /*bool iresult =*/ intersect(rectIvl2, nodeIvl2, false);
  147. Rectangle nextRect2 = Rectangle(rectIvl2, rectIvl2);
  148. Unit low2 = rect.get(orient.get_perpendicular()).low();
  149. Unit high2 = node->rect.get(orient.get_perpendicular()).high();
  150. nextRect2.set(orient.get_perpendicular(), Interval(low2, high2));
  151. rect = nextRect2;
  152. //std::cout << "rect for next child" << rect << std::endl;
  153. node = *itr;
  154. itr = node->begin();
  155. }
  156. }
  157. }
  158. } while(!stack.empty() || itr != node->end());
  159. }
  160. /* Function recursive version of getMaxCover
  161. Because the code is so much simpler than the loop algorithm I retain it for clarity
  162. template <class cT>
  163. static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient,
  164. const Rectangle& rect) {
  165. Interval rectIvl = rect.get(orient);
  166. Interval nodeIvl = node->rect.get(orient);
  167. if(!intersect(rectIvl, nodeIvl, false)) {
  168. return;
  169. }
  170. if(node->tracedPath(rectIvl)) {
  171. return;
  172. }
  173. node->addPath(rectIvl);
  174. Rectangle nextRect(rectIvl, rectIvl);
  175. Unit low = rect.get(orient.get_perpendicular()).low();
  176. Unit high = node->rect.get(orient.get_perpendicular()).high();
  177. nextRect.set(orient.get_perpendicular(), Interval(low, high));
  178. bool writeOut = true;
  179. rectIvl = nextRect.get(orient);
  180. for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) {
  181. nodeIvl = (*itr)->rect.get(orient);
  182. if(contains(nodeIvl, rectIvl, true)) writeOut = false;
  183. }
  184. if(writeOut) {
  185. outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect));
  186. }
  187. for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) {
  188. getMaxCover(outputContainer, *itr, orient, nextRect);
  189. }
  190. }
  191. */
  192. //iterator range is assummed to be in topological order meaning all node's trailing
  193. //edges are in sorted order
  194. template <class iT>
  195. static inline void computeDag(iT beginNode, iT endNode, orientation_2d orient,
  196. std::size_t size) {
  197. std::vector<EdgeAssociation> leadingEdges;
  198. leadingEdges.reserve(size);
  199. for(iT iter = beginNode; iter != endNode; ++iter) {
  200. Node* nodep = &(*iter);
  201. Unit leading = nodep->rect.get(orient.get_perpendicular()).low();
  202. Interval rectIvl = nodep->rect.get(orient);
  203. leadingEdges.push_back(EdgeAssociation(std::pair<Unit, Interval>(leading, rectIvl), nodep));
  204. }
  205. polygon_sort(leadingEdges.begin(), leadingEdges.end(), lessEdgeAssociation());
  206. typename std::vector<EdgeAssociation>::iterator leadingBegin = leadingEdges.begin();
  207. iT trailingBegin = beginNode;
  208. while(leadingBegin != leadingEdges.end()) {
  209. EdgeAssociation& leadingSegment = (*leadingBegin);
  210. Unit trailing = (*trailingBegin).rect.get(orient.get_perpendicular()).high();
  211. Interval ivl = (*trailingBegin).rect.get(orient);
  212. std::pair<Unit, Interval> trailingSegment(trailing, ivl);
  213. if(leadingSegment.first.first < trailingSegment.first) {
  214. ++leadingBegin;
  215. continue;
  216. }
  217. if(leadingSegment.first.first > trailingSegment.first) {
  218. ++trailingBegin;
  219. continue;
  220. }
  221. if(leadingSegment.first.second.high() <= trailingSegment.second.low()) {
  222. ++leadingBegin;
  223. continue;
  224. }
  225. if(trailingSegment.second.high() <= leadingSegment.first.second.low()) {
  226. ++trailingBegin;
  227. continue;
  228. }
  229. //leading segment intersects trailing segment
  230. (*trailingBegin).add((*leadingBegin).second);
  231. if(leadingSegment.first.second.high() > trailingSegment.second.high()) {
  232. ++trailingBegin;
  233. continue;
  234. }
  235. if(trailingSegment.second.high() > leadingSegment.first.second.high()) {
  236. ++leadingBegin;
  237. continue;
  238. }
  239. ++leadingBegin;
  240. ++trailingBegin;
  241. }
  242. }
  243. template <class cT>
  244. static inline void getMaxCover(cT& outputContainer,
  245. const std::vector<Rectangle>& rects, orientation_2d orient) {
  246. if(rects.empty()) return;
  247. std::vector<Node> nodes;
  248. {
  249. if(rects.size() == 1) {
  250. outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(rects[0]));
  251. return;
  252. }
  253. nodes.reserve(rects.size());
  254. for(std::size_t i = 0; i < rects.size(); ++i) { nodes.push_back(Node(rects[i])); }
  255. }
  256. computeDag(nodes.begin(), nodes.end(), orient, nodes.size());
  257. for(std::size_t i = 0; i < nodes.size(); ++i) {
  258. getMaxCover(outputContainer, &(nodes[i]), orient);
  259. }
  260. }
  261. };
  262. }
  263. }
  264. #endif