annotate DEPENDENCIES/generic/include/boost/polygon/detail/max_cover.hpp @ 125:34e428693f5d vext

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