| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 | /*  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_HPPnamespace 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:      typedef const EdgeAssociation& first_argument_type;      typedef const EdgeAssociation& second_argument_type;      typedef bool result_type;      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 << "suppress " << 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
 |