File indexing completed on 2024-11-16 09:28:40
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_POLYGON_MAX_COVER_HPP
0009 #define BOOST_POLYGON_MAX_COVER_HPP
0010 namespace boost { namespace polygon{
0011
0012 template <typename Unit>
0013 struct MaxCover {
0014 typedef interval_data<Unit> Interval;
0015 typedef rectangle_data<Unit> Rectangle;
0016
0017 class Node {
0018 private:
0019 std::vector<Node*> children_;
0020 std::set<Interval> tracedPaths_;
0021 public:
0022 Rectangle rect;
0023 Node() : children_(), tracedPaths_(), rect() {}
0024 Node(const Rectangle rectIn) : children_(), tracedPaths_(), rect(rectIn) {}
0025 typedef typename std::vector<Node*>::iterator iterator;
0026 inline iterator begin() { return children_.begin(); }
0027 inline iterator end() { return children_.end(); }
0028 inline void add(Node* child) { children_.push_back(child); }
0029 inline bool tracedPath(const Interval& ivl) const {
0030 return tracedPaths_.find(ivl) != tracedPaths_.end();
0031 }
0032 inline void addPath(const Interval& ivl) {
0033 tracedPaths_.insert(tracedPaths_.end(), ivl);
0034 }
0035 };
0036
0037 typedef std::pair<std::pair<Unit, Interval>, Node* > EdgeAssociation;
0038
0039 class lessEdgeAssociation {
0040 public:
0041 typedef const EdgeAssociation& first_argument_type;
0042 typedef const EdgeAssociation& second_argument_type;
0043 typedef bool result_type;
0044 inline lessEdgeAssociation() {}
0045 inline bool operator () (const EdgeAssociation& elem1, const EdgeAssociation& elem2) const {
0046 if(elem1.first.first < elem2.first.first) return true;
0047 if(elem1.first.first > elem2.first.first) return false;
0048 return elem1.first.second < elem2.first.second;
0049 }
0050 };
0051
0052 template <class cT>
0053 static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient) {
0054 Interval rectIvl = node->rect.get(orient);
0055 if(node->tracedPath(rectIvl)) {
0056 return;
0057 }
0058 node->addPath(rectIvl);
0059 if(node->begin() == node->end()) {
0060
0061 outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(node->rect));
0062 return;
0063 }
0064 bool writeOut = true;
0065 for(typename Node::iterator itr = node->begin(); itr != node->end(); ++itr) {
0066 getMaxCover(outputContainer, *itr, orient, node->rect);
0067 Interval nodeIvl = (*itr)->rect.get(orient);
0068 if(contains(nodeIvl, rectIvl, true)) writeOut = false;
0069 }
0070 if(writeOut) {
0071
0072 outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(node->rect));
0073 }
0074 }
0075
0076 struct stack_element {
0077 inline stack_element() :
0078 node(), rect(), itr() {}
0079 inline stack_element(Node* n,
0080 const Rectangle& r,
0081 typename Node::iterator i) :
0082 node(n), rect(r), itr(i) {}
0083 Node* node;
0084 Rectangle rect;
0085 typename Node::iterator itr;
0086 };
0087
0088 template <class cT>
0089 static inline void getMaxCover(cT& outputContainer, Node* node, orientation_2d orient,
0090 Rectangle rect) {
0091
0092 std::vector<stack_element> stack;
0093 typename Node::iterator itr = node->begin();
0094 do {
0095
0096
0097 Interval rectIvl = rect.get(orient);
0098 Interval nodeIvl = node->rect.get(orient);
0099 bool iresult = intersect(rectIvl, nodeIvl, false);
0100 bool tresult = !node->tracedPath(rectIvl);
0101
0102 Rectangle nextRect1 = Rectangle(rectIvl, rectIvl);
0103 Unit low = rect.get(orient.get_perpendicular()).low();
0104 Unit high = node->rect.get(orient.get_perpendicular()).high();
0105 nextRect1.set(orient.get_perpendicular(), Interval(low, high));
0106 if(iresult && tresult) {
0107 node->addPath(rectIvl);
0108 bool writeOut = true;
0109
0110 for(typename Node::iterator itr2 = node->begin(); itr2 != node->end(); ++itr2) {
0111 Interval nodeIvl3 = (*itr2)->rect.get(orient);
0112
0113 if(contains(nodeIvl3, rectIvl, true)) writeOut = false;
0114
0115 }
0116 Rectangle nextRect2 = Rectangle(rectIvl, rectIvl);
0117 Unit low2 = rect.get(orient.get_perpendicular()).low();
0118 Unit high2 = node->rect.get(orient.get_perpendicular()).high();
0119 nextRect2.set(orient.get_perpendicular(), Interval(low2, high2));
0120 if(writeOut) {
0121
0122 outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(nextRect2));
0123 } else {
0124
0125 }
0126 }
0127 if(itr != node->end() && iresult && tresult) {
0128
0129 stack.push_back(stack_element(node, rect, itr));
0130 rect = nextRect1;
0131 node = *itr;
0132 itr = node->begin();
0133 } else {
0134 if(!stack.empty()) {
0135
0136 node = stack.back().node;
0137 rect = stack.back().rect;
0138 itr = stack.back().itr;
0139 stack.pop_back();
0140 } else {
0141
0142
0143
0144
0145
0146
0147
0148 }
0149
0150 if(itr != node->end()) {
0151 ++itr;
0152 if(itr != node->end()) {
0153
0154 stack.push_back(stack_element(node, rect, itr));
0155 Interval rectIvl2 = rect.get(orient);
0156 Interval nodeIvl2 = node->rect.get(orient);
0157 intersect(rectIvl2, nodeIvl2, false);
0158 Rectangle nextRect2 = Rectangle(rectIvl2, rectIvl2);
0159 Unit low2 = rect.get(orient.get_perpendicular()).low();
0160 Unit high2 = node->rect.get(orient.get_perpendicular()).high();
0161 nextRect2.set(orient.get_perpendicular(), Interval(low2, high2));
0162 rect = nextRect2;
0163
0164 node = *itr;
0165 itr = node->begin();
0166 }
0167 }
0168 }
0169 } while(!stack.empty() || itr != node->end());
0170 }
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 template <class iT>
0209 static inline void computeDag(iT beginNode, iT endNode, orientation_2d orient,
0210 std::size_t size) {
0211 std::vector<EdgeAssociation> leadingEdges;
0212 leadingEdges.reserve(size);
0213 for(iT iter = beginNode; iter != endNode; ++iter) {
0214 Node* nodep = &(*iter);
0215 Unit leading = nodep->rect.get(orient.get_perpendicular()).low();
0216 Interval rectIvl = nodep->rect.get(orient);
0217 leadingEdges.push_back(EdgeAssociation(std::pair<Unit, Interval>(leading, rectIvl), nodep));
0218 }
0219 polygon_sort(leadingEdges.begin(), leadingEdges.end(), lessEdgeAssociation());
0220 typename std::vector<EdgeAssociation>::iterator leadingBegin = leadingEdges.begin();
0221 iT trailingBegin = beginNode;
0222 while(leadingBegin != leadingEdges.end()) {
0223 EdgeAssociation& leadingSegment = (*leadingBegin);
0224 Unit trailing = (*trailingBegin).rect.get(orient.get_perpendicular()).high();
0225 Interval ivl = (*trailingBegin).rect.get(orient);
0226 std::pair<Unit, Interval> trailingSegment(trailing, ivl);
0227 if(leadingSegment.first.first < trailingSegment.first) {
0228 ++leadingBegin;
0229 continue;
0230 }
0231 if(leadingSegment.first.first > trailingSegment.first) {
0232 ++trailingBegin;
0233 continue;
0234 }
0235 if(leadingSegment.first.second.high() <= trailingSegment.second.low()) {
0236 ++leadingBegin;
0237 continue;
0238 }
0239 if(trailingSegment.second.high() <= leadingSegment.first.second.low()) {
0240 ++trailingBegin;
0241 continue;
0242 }
0243
0244 (*trailingBegin).add((*leadingBegin).second);
0245 if(leadingSegment.first.second.high() > trailingSegment.second.high()) {
0246 ++trailingBegin;
0247 continue;
0248 }
0249 if(trailingSegment.second.high() > leadingSegment.first.second.high()) {
0250 ++leadingBegin;
0251 continue;
0252 }
0253 ++leadingBegin;
0254 ++trailingBegin;
0255 }
0256 }
0257
0258 template <class cT>
0259 static inline void getMaxCover(cT& outputContainer,
0260 const std::vector<Rectangle>& rects, orientation_2d orient) {
0261 if(rects.empty()) return;
0262 std::vector<Node> nodes;
0263 {
0264 if(rects.size() == 1) {
0265 outputContainer.push_back(copy_construct<typename cT::value_type, Rectangle>(rects[0]));
0266 return;
0267 }
0268 nodes.reserve(rects.size());
0269 for(std::size_t i = 0; i < rects.size(); ++i) { nodes.push_back(Node(rects[i])); }
0270 }
0271 computeDag(nodes.begin(), nodes.end(), orient, nodes.size());
0272 for(std::size_t i = 0; i < nodes.size(); ++i) {
0273 getMaxCover(outputContainer, &(nodes[i]), orient);
0274 }
0275 }
0276
0277 };
0278 }
0279 }
0280
0281 #endif