diff DEPENDENCIES/generic/include/boost/polygon/detail/max_cover.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DEPENDENCIES/generic/include/boost/polygon/detail/max_cover.hpp	Tue Aug 05 11:11:38 2014 +0100
@@ -0,0 +1,278 @@
+/*
+  Copyright 2008 Intel Corporation
+
+  Use, modification and distribution are subject to the Boost Software License,
+  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+  http://www.boost.org/LICENSE_1_0.txt).
+*/
+#ifndef BOOST_POLYGON_MAX_COVER_HPP
+#define BOOST_POLYGON_MAX_COVER_HPP
+namespace boost { namespace polygon{
+
+  template <typename Unit>
+  struct MaxCover {
+    typedef interval_data<Unit> Interval;
+    typedef rectangle_data<Unit> Rectangle;
+
+    class Node {
+    private:
+      std::vector<Node*> children_;
+      std::set<Interval> tracedPaths_;
+    public:
+      Rectangle rect;
+      Node() : children_(), tracedPaths_(), rect() {}
+      Node(const Rectangle rectIn) : children_(), tracedPaths_(), rect(rectIn) {}
+      typedef typename std::vector<Node*>::iterator iterator;
+      inline iterator begin() { return children_.begin(); }
+      inline iterator end() { return children_.end(); }
+      inline void add(Node* child) { children_.push_back(child); }
+      inline bool tracedPath(const Interval& ivl) const {
+        return tracedPaths_.find(ivl) != tracedPaths_.end();
+      }
+      inline void addPath(const Interval& ivl) {
+        tracedPaths_.insert(tracedPaths_.end(), ivl);
+      }
+    };
+
+    typedef std::pair<std::pair<Unit, Interval>, Node* > EdgeAssociation;
+
+    class lessEdgeAssociation : public std::binary_function<const EdgeAssociation&, const EdgeAssociation&, bool> {
+    public:
+      inline lessEdgeAssociation() {}
+      inline bool operator () (const EdgeAssociation& elem1, const EdgeAssociation& elem2) const {
+        if(elem1.first.first < elem2.first.first) return true;
+        if(elem1.first.first > elem2.first.first) return false;
+        return elem1.first.second < elem2.first.second;
+      }
+    };
+
+    template <class cT>
+    static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient) {
+      Interval rectIvl = node->rect.get(orient);
+      if(node->tracedPath(rectIvl)) {
+        return;
+      }
+      node->addPath(rectIvl);
+      if(node->begin() == node->end()) {
+        //std::cout << "WRITE OUT 3: " << node->rect << std::endl;
+        outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(node->rect));
+        return;
+      }
+      bool writeOut = true;
+      for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) {
+        getMaxCover(outputContainer, *itr, orient, node->rect); //get rectangles down path
+        Interval nodeIvl = (*itr)->rect.get(orient);
+        if(contains(nodeIvl, rectIvl, true)) writeOut = false;
+      }
+      if(writeOut) {
+        //std::cout << "WRITE OUT 2: " << node->rect << std::endl;
+        outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(node->rect));
+      }
+    }
+
+    struct stack_element {
+      inline stack_element() :
+        node(), rect(), itr() {}
+      inline stack_element(Node* n,
+                           const Rectangle& r,
+                           typename Node::iterator i) :
+        node(n), rect(r), itr(i) {}
+      Node* node;
+      Rectangle rect;
+      typename Node::iterator itr;
+    };
+
+    template <class cT>
+    static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient,
+                                   Rectangle rect) {
+      //std::cout << "New Root\n";
+      std::vector<stack_element> stack;
+      typename Node::iterator itr = node->begin();
+      do {
+        //std::cout << "LOOP\n";
+        //std::cout << node->rect << std::endl;
+        Interval rectIvl = rect.get(orient);
+        Interval nodeIvl = node->rect.get(orient);
+        bool iresult = intersect(rectIvl, nodeIvl, false);
+        bool tresult = !node->tracedPath(rectIvl);
+        //std::cout << (itr != node->end()) << " " << iresult << " " << tresult << std::endl;
+        Rectangle nextRect1 = Rectangle(rectIvl, rectIvl);
+        Unit low = rect.get(orient.get_perpendicular()).low();
+        Unit high = node->rect.get(orient.get_perpendicular()).high();
+        nextRect1.set(orient.get_perpendicular(), Interval(low, high));
+        if(iresult && tresult) {
+          node->addPath(rectIvl);
+          bool writeOut = true;
+          //check further visibility beyond this node
+          for(typename Node::iterator itr2 = node->begin(); itr2 != node->end(); ++itr2) {
+            Interval nodeIvl3 = (*itr2)->rect.get(orient);
+            //if a child of this node can contain the interval then we can extend through
+            if(contains(nodeIvl3, rectIvl, true)) writeOut = false;
+            //std::cout << "child " << (*itr2)->rect << std::endl;
+          }
+          Rectangle nextRect2 = Rectangle(rectIvl, rectIvl);
+          Unit low2 = rect.get(orient.get_perpendicular()).low();
+          Unit high2 = node->rect.get(orient.get_perpendicular()).high();
+          nextRect2.set(orient.get_perpendicular(), Interval(low2, high2));
+          if(writeOut) {
+            //std::cout << "write out " << nextRect << std::endl;
+            outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect2));
+          } else {
+            //std::cout << "supress " << nextRect << std::endl;
+          }
+        }
+        if(itr != node->end() && iresult && tresult) {
+          //std::cout << "recurse into child\n";
+          stack.push_back(stack_element(node, rect, itr));
+          rect = nextRect1;
+          node = *itr;
+          itr = node->begin();
+        } else {
+          if(!stack.empty()) {
+            //std::cout << "recurse out of child\n";
+            node = stack.back().node;
+            rect = stack.back().rect;
+            itr = stack.back().itr;
+            stack.pop_back();
+          } else {
+            //std::cout << "empty stack\n";
+            //if there were no children of the root node
+//             Rectangle nextRect = Rectangle(rectIvl, rectIvl);
+//             Unit low = rect.get(orient.get_perpendicular()).low();
+//             Unit high = node->rect.get(orient.get_perpendicular()).high();
+//             nextRect.set(orient.get_perpendicular(), Interval(low, high));
+//             outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect));
+          }
+          //std::cout << "increment " << (itr != node->end()) << std::endl;
+          if(itr != node->end()) {
+            ++itr;
+            if(itr != node->end()) {
+              //std::cout << "recurse into next child.\n";
+              stack.push_back(stack_element(node, rect, itr));
+              Interval rectIvl2 = rect.get(orient);
+              Interval nodeIvl2 = node->rect.get(orient);
+              /*bool iresult =*/ intersect(rectIvl2, nodeIvl2, false);
+              Rectangle nextRect2 = Rectangle(rectIvl2, rectIvl2);
+              Unit low2 = rect.get(orient.get_perpendicular()).low();
+              Unit high2 = node->rect.get(orient.get_perpendicular()).high();
+              nextRect2.set(orient.get_perpendicular(), Interval(low2, high2));
+              rect = nextRect2;
+              //std::cout << "rect for next child" << rect << std::endl;
+              node = *itr;
+              itr = node->begin();
+            }
+          }
+        }
+      } while(!stack.empty() || itr != node->end());
+    }
+
+    /*  Function recursive version of getMaxCover
+        Because the code is so much simpler than the loop algorithm I retain it for clarity
+
+    template <class cT>
+    static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient,
+                                   const Rectangle& rect) {
+      Interval rectIvl = rect.get(orient);
+      Interval nodeIvl = node->rect.get(orient);
+      if(!intersect(rectIvl, nodeIvl, false)) {
+        return;
+      }
+      if(node->tracedPath(rectIvl)) {
+        return;
+      }
+      node->addPath(rectIvl);
+      Rectangle nextRect(rectIvl, rectIvl);
+      Unit low = rect.get(orient.get_perpendicular()).low();
+      Unit high = node->rect.get(orient.get_perpendicular()).high();
+      nextRect.set(orient.get_perpendicular(), Interval(low, high));
+      bool writeOut = true;
+      rectIvl = nextRect.get(orient);
+      for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) {
+        nodeIvl = (*itr)->rect.get(orient);
+        if(contains(nodeIvl, rectIvl, true)) writeOut = false;
+      }
+      if(writeOut) {
+        outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect));
+      }
+      for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) {
+        getMaxCover(outputContainer, *itr, orient, nextRect);
+      }
+    }
+    */
+
+    //iterator range is assummed to be in topological order meaning all node's trailing
+    //edges are in sorted order
+    template <class iT>
+    static inline void computeDag(iT beginNode, iT endNode, orientation_2d orient,
+                                  std::size_t size) {
+      std::vector<EdgeAssociation> leadingEdges;
+      leadingEdges.reserve(size);
+      for(iT iter = beginNode; iter != endNode; ++iter) {
+        Node* nodep = &(*iter);
+        Unit leading = nodep->rect.get(orient.get_perpendicular()).low();
+        Interval rectIvl = nodep->rect.get(orient);
+        leadingEdges.push_back(EdgeAssociation(std::pair<Unit, Interval>(leading, rectIvl), nodep));
+      }
+      polygon_sort(leadingEdges.begin(), leadingEdges.end(), lessEdgeAssociation());
+      typename std::vector<EdgeAssociation>::iterator leadingBegin = leadingEdges.begin();
+      iT trailingBegin = beginNode;
+      while(leadingBegin != leadingEdges.end()) {
+        EdgeAssociation& leadingSegment = (*leadingBegin);
+        Unit trailing = (*trailingBegin).rect.get(orient.get_perpendicular()).high();
+        Interval ivl = (*trailingBegin).rect.get(orient);
+        std::pair<Unit, Interval> trailingSegment(trailing, ivl);
+        if(leadingSegment.first.first < trailingSegment.first) {
+          ++leadingBegin;
+          continue;
+        }
+        if(leadingSegment.first.first > trailingSegment.first) {
+          ++trailingBegin;
+          continue;
+        }
+        if(leadingSegment.first.second.high() <= trailingSegment.second.low()) {
+          ++leadingBegin;
+          continue;
+        }
+        if(trailingSegment.second.high() <= leadingSegment.first.second.low()) {
+          ++trailingBegin;
+          continue;
+        }
+        //leading segment intersects trailing segment
+        (*trailingBegin).add((*leadingBegin).second);
+        if(leadingSegment.first.second.high() > trailingSegment.second.high()) {
+          ++trailingBegin;
+          continue;
+        }
+        if(trailingSegment.second.high() > leadingSegment.first.second.high()) {
+          ++leadingBegin;
+          continue;
+        }
+        ++leadingBegin;
+        ++trailingBegin;
+      }
+    }
+
+    template <class cT>
+    static inline void getMaxCover(cT& outputContainer,
+                                   const std::vector<Rectangle>& rects, orientation_2d orient) {
+      if(rects.empty()) return;
+      std::vector<Node> nodes;
+      {
+        if(rects.size() == 1) {
+          outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(rects[0]));
+          return;
+        }
+        nodes.reserve(rects.size());
+        for(std::size_t i = 0; i < rects.size(); ++i) { nodes.push_back(Node(rects[i])); }
+      }
+      computeDag(nodes.begin(), nodes.end(), orient, nodes.size());
+      for(std::size_t i = 0; i < nodes.size(); ++i) {
+        getMaxCover(outputContainer, &(nodes[i]), orient);
+      }
+    }
+
+  };
+}
+}
+
+#endif