max_cover.hpp 11 KB

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