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

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
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_PROPERTY_MERGE_HPP
Chris@16 9 #define BOOST_POLYGON_PROPERTY_MERGE_HPP
Chris@16 10 namespace boost { namespace polygon{
Chris@16 11
Chris@16 12 template <typename coordinate_type>
Chris@16 13 class property_merge_point {
Chris@16 14 private:
Chris@16 15 coordinate_type x_, y_;
Chris@16 16 public:
Chris@16 17 inline property_merge_point() : x_(), y_() {}
Chris@16 18 inline property_merge_point(coordinate_type x, coordinate_type y) : x_(x), y_(y) {}
Chris@16 19 //use builtin assign and copy
Chris@16 20 inline bool operator==(const property_merge_point& that) const { return x_ == that.x_ && y_ == that.y_; }
Chris@16 21 inline bool operator!=(const property_merge_point& that) const { return !((*this) == that); }
Chris@16 22 inline bool operator<(const property_merge_point& that) const {
Chris@16 23 if(x_ < that.x_) return true;
Chris@16 24 if(x_ > that.x_) return false;
Chris@16 25 return y_ < that.y_;
Chris@16 26 }
Chris@16 27 inline coordinate_type x() const { return x_; }
Chris@16 28 inline coordinate_type y() const { return y_; }
Chris@16 29 inline void x(coordinate_type value) { x_ = value; }
Chris@16 30 inline void y(coordinate_type value) { y_ = value; }
Chris@16 31 };
Chris@16 32
Chris@16 33 template <typename coordinate_type>
Chris@16 34 class property_merge_interval {
Chris@16 35 private:
Chris@16 36 coordinate_type low_, high_;
Chris@16 37 public:
Chris@16 38 inline property_merge_interval() : low_(), high_() {}
Chris@16 39 inline property_merge_interval(coordinate_type low, coordinate_type high) : low_(low), high_(high) {}
Chris@16 40 //use builtin assign and copy
Chris@16 41 inline bool operator==(const property_merge_interval& that) const { return low_ == that.low_ && high_ == that.high_; }
Chris@16 42 inline bool operator!=(const property_merge_interval& that) const { return !((*this) == that); }
Chris@16 43 inline bool operator<(const property_merge_interval& that) const {
Chris@16 44 if(low_ < that.low_) return true;
Chris@16 45 if(low_ > that.low_) return false;
Chris@16 46 return high_ < that.high_;
Chris@16 47 }
Chris@16 48 inline coordinate_type low() const { return low_; }
Chris@16 49 inline coordinate_type high() const { return high_; }
Chris@16 50 inline void low(coordinate_type value) { low_ = value; }
Chris@16 51 inline void high(coordinate_type value) { high_ = value; }
Chris@16 52 };
Chris@16 53
Chris@16 54 template <typename coordinate_type, typename property_type, typename polygon_set_type, typename keytype = std::set<property_type> >
Chris@16 55 class merge_scanline {
Chris@16 56 public:
Chris@16 57 //definitions
Chris@16 58
Chris@16 59 typedef keytype property_set;
Chris@16 60 typedef std::vector<std::pair<property_type, int> > property_map;
Chris@16 61 typedef std::pair<property_merge_point<coordinate_type>, std::pair<property_type, int> > vertex_property;
Chris@16 62 typedef std::pair<property_merge_point<coordinate_type>, property_map> vertex_data;
Chris@16 63 typedef std::vector<vertex_property> property_merge_data;
Chris@16 64 //typedef std::map<property_set, polygon_set_type> Result;
Chris@16 65 typedef std::map<coordinate_type, property_map> scanline_type;
Chris@16 66 typedef typename scanline_type::iterator scanline_iterator;
Chris@16 67 typedef std::pair<property_merge_interval<coordinate_type>, std::pair<property_set, property_set> > edge_property;
Chris@16 68 typedef std::vector<edge_property> edge_property_vector;
Chris@16 69
Chris@16 70 //static public member functions
Chris@16 71
Chris@16 72 template <typename iT, typename orientation_2d_type>
Chris@16 73 static inline void
Chris@16 74 populate_property_merge_data(property_merge_data& pmd, iT input_begin, iT input_end,
Chris@16 75 const property_type& property, orientation_2d_type orient) {
Chris@16 76 for( ; input_begin != input_end; ++input_begin) {
Chris@16 77 std::pair<property_merge_point<coordinate_type>, std::pair<property_type, int> > element;
Chris@16 78 if(orient == HORIZONTAL)
Chris@16 79 element.first = property_merge_point<coordinate_type>((*input_begin).second.first, (*input_begin).first);
Chris@16 80 else
Chris@16 81 element.first = property_merge_point<coordinate_type>((*input_begin).first, (*input_begin).second.first);
Chris@16 82 element.second.first = property;
Chris@16 83 element.second.second = (*input_begin).second.second;
Chris@16 84 pmd.push_back(element);
Chris@16 85 }
Chris@16 86 }
Chris@16 87
Chris@16 88 //public member functions
Chris@16 89
Chris@16 90 merge_scanline() : output(), scanline(), currentVertex(), tmpVector(), previousY(), countFromBelow(), scanlinePosition() {}
Chris@16 91 merge_scanline(const merge_scanline& that) :
Chris@16 92 output(that.output),
Chris@16 93 scanline(that.scanline),
Chris@16 94 currentVertex(that.currentVertex),
Chris@16 95 tmpVector(that.tmpVector),
Chris@16 96 previousY(that.previousY),
Chris@16 97 countFromBelow(that.countFromBelow),
Chris@16 98 scanlinePosition(that.scanlinePosition)
Chris@16 99 {}
Chris@16 100 merge_scanline& operator=(const merge_scanline& that) {
Chris@16 101 output = that.output;
Chris@16 102 scanline = that.scanline;
Chris@16 103 currentVertex = that.currentVertex;
Chris@16 104 tmpVector = that.tmpVector;
Chris@16 105 previousY = that.previousY;
Chris@16 106 countFromBelow = that.countFromBelow;
Chris@16 107 scanlinePosition = that.scanlinePosition;
Chris@16 108 return *this;
Chris@16 109 }
Chris@16 110
Chris@16 111 template <typename result_type>
Chris@16 112 inline void perform_merge(result_type& result, property_merge_data& data) {
Chris@16 113 if(data.empty()) return;
Chris@16 114 //sort
Chris@16 115 polygon_sort(data.begin(), data.end(), less_vertex_data<vertex_property>());
Chris@16 116 //scanline
Chris@16 117 bool firstIteration = true;
Chris@16 118 scanlinePosition = scanline.end();
Chris@16 119 for(std::size_t i = 0; i < data.size(); ++i) {
Chris@16 120 if(firstIteration) {
Chris@16 121 mergeProperty(currentVertex.second, data[i].second);
Chris@16 122 currentVertex.first = data[i].first;
Chris@16 123 firstIteration = false;
Chris@16 124 } else {
Chris@16 125 if(data[i].first != currentVertex.first) {
Chris@16 126 if(data[i].first.x() != currentVertex.first.x()) {
Chris@16 127 processVertex(output);
Chris@16 128 //std::cout << scanline.size() << " ";
Chris@16 129 countFromBelow.clear(); //should already be clear
Chris@16 130 writeOutput(currentVertex.first.x(), result, output);
Chris@16 131 currentVertex.second.clear();
Chris@16 132 mergeProperty(currentVertex.second, data[i].second);
Chris@16 133 currentVertex.first = data[i].first;
Chris@16 134 //std::cout << assertRedundant(scanline) << "/" << scanline.size() << " ";
Chris@16 135 } else {
Chris@16 136 processVertex(output);
Chris@16 137 currentVertex.second.clear();
Chris@16 138 mergeProperty(currentVertex.second, data[i].second);
Chris@16 139 currentVertex.first = data[i].first;
Chris@16 140 }
Chris@16 141 } else {
Chris@16 142 mergeProperty(currentVertex.second, data[i].second);
Chris@16 143 }
Chris@16 144 }
Chris@16 145 }
Chris@16 146 processVertex(output);
Chris@16 147 writeOutput(currentVertex.first.x(), result, output);
Chris@16 148 //std::cout << assertRedundant(scanline) << "/" << scanline.size() << "\n";
Chris@16 149 //std::cout << scanline.size() << "\n";
Chris@16 150 }
Chris@16 151
Chris@16 152 private:
Chris@16 153 //private supporting types
Chris@16 154
Chris@16 155 template <class T>
Chris@16 156 class less_vertex_data {
Chris@16 157 public:
Chris@16 158 less_vertex_data() {}
Chris@16 159 bool operator()(const T& lvalue, const T& rvalue) const {
Chris@16 160 if(lvalue.first.x() < rvalue.first.x()) return true;
Chris@16 161 if(lvalue.first.x() > rvalue.first.x()) return false;
Chris@16 162 if(lvalue.first.y() < rvalue.first.y()) return true;
Chris@16 163 return false;
Chris@16 164 }
Chris@16 165 };
Chris@16 166
Chris@16 167 template <typename T>
Chris@16 168 struct lessPropertyCount {
Chris@16 169 lessPropertyCount() {}
Chris@16 170 bool operator()(const T& a, const T& b) {
Chris@16 171 return a.first < b.first;
Chris@16 172 }
Chris@16 173 };
Chris@16 174
Chris@16 175 //private static member functions
Chris@16 176
Chris@16 177 static inline void mergeProperty(property_map& lvalue, std::pair<property_type, int>& rvalue) {
Chris@16 178 typename property_map::iterator itr = std::lower_bound(lvalue.begin(), lvalue.end(), rvalue,
Chris@16 179 lessPropertyCount<std::pair<property_type, int> >());
Chris@16 180 if(itr == lvalue.end() ||
Chris@16 181 (*itr).first != rvalue.first) {
Chris@16 182 lvalue.insert(itr, rvalue);
Chris@16 183 } else {
Chris@16 184 (*itr).second += rvalue.second;
Chris@16 185 if((*itr).second == 0)
Chris@16 186 lvalue.erase(itr);
Chris@16 187 }
Chris@16 188 // if(assertSorted(lvalue)) {
Chris@16 189 // std::cout << "in mergeProperty\n";
Chris@16 190 // exit(0);
Chris@16 191 // }
Chris@16 192 }
Chris@16 193
Chris@16 194 // static inline bool assertSorted(property_map& pset) {
Chris@16 195 // bool result = false;
Chris@16 196 // for(std::size_t i = 1; i < pset.size(); ++i) {
Chris@16 197 // if(pset[i] < pset[i-1]) {
Chris@16 198 // std::cout << "Out of Order Error ";
Chris@16 199 // result = true;
Chris@16 200 // }
Chris@16 201 // if(pset[i].first == pset[i-1].first) {
Chris@16 202 // std::cout << "Duplicate Property Error ";
Chris@16 203 // result = true;
Chris@16 204 // }
Chris@16 205 // if(pset[0].second == 0 || pset[1].second == 0) {
Chris@16 206 // std::cout << "Empty Property Error ";
Chris@16 207 // result = true;
Chris@16 208 // }
Chris@16 209 // }
Chris@16 210 // return result;
Chris@16 211 // }
Chris@16 212
Chris@16 213 static inline void setProperty(property_set& pset, property_map& pmap) {
Chris@16 214 for(typename property_map::iterator itr = pmap.begin(); itr != pmap.end(); ++itr) {
Chris@16 215 if((*itr).second > 0) {
Chris@16 216 pset.insert(pset.end(), (*itr).first);
Chris@16 217 }
Chris@16 218 }
Chris@16 219 }
Chris@16 220
Chris@16 221 //private data members
Chris@16 222
Chris@16 223 edge_property_vector output;
Chris@16 224 scanline_type scanline;
Chris@16 225 vertex_data currentVertex;
Chris@16 226 property_map tmpVector;
Chris@16 227 coordinate_type previousY;
Chris@16 228 property_map countFromBelow;
Chris@16 229 scanline_iterator scanlinePosition;
Chris@16 230
Chris@16 231 //private member functions
Chris@16 232
Chris@16 233 inline void mergeCount(property_map& lvalue, property_map& rvalue) {
Chris@16 234 typename property_map::iterator litr = lvalue.begin();
Chris@16 235 typename property_map::iterator ritr = rvalue.begin();
Chris@16 236 tmpVector.clear();
Chris@16 237 while(litr != lvalue.end() && ritr != rvalue.end()) {
Chris@16 238 if((*litr).first <= (*ritr).first) {
Chris@16 239 if(!tmpVector.empty() &&
Chris@16 240 (*litr).first == tmpVector.back().first) {
Chris@16 241 tmpVector.back().second += (*litr).second;
Chris@16 242 } else {
Chris@16 243 tmpVector.push_back(*litr);
Chris@16 244 }
Chris@16 245 ++litr;
Chris@16 246 } else if((*ritr).first <= (*litr).first) {
Chris@16 247 if(!tmpVector.empty() &&
Chris@16 248 (*ritr).first == tmpVector.back().first) {
Chris@16 249 tmpVector.back().second += (*ritr).second;
Chris@16 250 } else {
Chris@16 251 tmpVector.push_back(*ritr);
Chris@16 252 }
Chris@16 253 ++ritr;
Chris@16 254 }
Chris@16 255 }
Chris@16 256 while(litr != lvalue.end()) {
Chris@16 257 if(!tmpVector.empty() &&
Chris@16 258 (*litr).first == tmpVector.back().first) {
Chris@16 259 tmpVector.back().second += (*litr).second;
Chris@16 260 } else {
Chris@16 261 tmpVector.push_back(*litr);
Chris@16 262 }
Chris@16 263 ++litr;
Chris@16 264 }
Chris@16 265 while(ritr != rvalue.end()) {
Chris@16 266 if(!tmpVector.empty() &&
Chris@16 267 (*ritr).first == tmpVector.back().first) {
Chris@16 268 tmpVector.back().second += (*ritr).second;
Chris@16 269 } else {
Chris@16 270 tmpVector.push_back(*ritr);
Chris@16 271 }
Chris@16 272 ++ritr;
Chris@16 273 }
Chris@16 274 lvalue.clear();
Chris@16 275 for(std::size_t i = 0; i < tmpVector.size(); ++i) {
Chris@16 276 if(tmpVector[i].second != 0) {
Chris@16 277 lvalue.push_back(tmpVector[i]);
Chris@16 278 }
Chris@16 279 }
Chris@16 280 // if(assertSorted(lvalue)) {
Chris@16 281 // std::cout << "in mergeCount\n";
Chris@16 282 // exit(0);
Chris@16 283 // }
Chris@16 284 }
Chris@16 285
Chris@16 286 inline void processVertex(edge_property_vector& output) {
Chris@16 287 if(!countFromBelow.empty()) {
Chris@16 288 //we are processing an interval of change in scanline state between
Chris@16 289 //previous vertex position and current vertex position where
Chris@16 290 //count from below represents the change on the interval
Chris@16 291 //foreach scanline element from previous to current we
Chris@16 292 //write the interval on the scanline that is changing
Chris@16 293 //the old value and the new value to output
Chris@16 294 property_merge_interval<coordinate_type> currentInterval(previousY, currentVertex.first.y());
Chris@16 295 coordinate_type currentY = currentInterval.low();
Chris@16 296 if(scanlinePosition == scanline.end() ||
Chris@16 297 (*scanlinePosition).first != previousY) {
Chris@16 298 scanlinePosition = scanline.lower_bound(previousY);
Chris@16 299 }
Chris@16 300 scanline_iterator previousScanlinePosition = scanlinePosition;
Chris@16 301 ++scanlinePosition;
Chris@16 302 while(scanlinePosition != scanline.end()) {
Chris@16 303 coordinate_type elementY = (*scanlinePosition).first;
Chris@16 304 if(elementY <= currentInterval.high()) {
Chris@16 305 property_map& countOnLeft = (*previousScanlinePosition).second;
Chris@16 306 edge_property element;
Chris@16 307 output.push_back(element);
Chris@16 308 output.back().first = property_merge_interval<coordinate_type>((*previousScanlinePosition).first, elementY);
Chris@16 309 setProperty(output.back().second.first, countOnLeft);
Chris@16 310 mergeCount(countOnLeft, countFromBelow);
Chris@16 311 setProperty(output.back().second.second, countOnLeft);
Chris@16 312 if(output.back().second.first == output.back().second.second) {
Chris@16 313 output.pop_back(); //it was an internal vertical edge, not to be output
Chris@16 314 }
Chris@16 315 else if(output.size() > 1) {
Chris@16 316 edge_property& secondToLast = output[output.size()-2];
Chris@16 317 if(secondToLast.first.high() == output.back().first.low() &&
Chris@16 318 secondToLast.second.first == output.back().second.first &&
Chris@16 319 secondToLast.second.second == output.back().second.second) {
Chris@16 320 //merge output onto previous output because properties are
Chris@16 321 //identical on both sides implying an internal horizontal edge
Chris@16 322 secondToLast.first.high(output.back().first.high());
Chris@16 323 output.pop_back();
Chris@16 324 }
Chris@16 325 }
Chris@16 326 if(previousScanlinePosition == scanline.begin()) {
Chris@16 327 if(countOnLeft.empty()) {
Chris@16 328 scanline.erase(previousScanlinePosition);
Chris@16 329 }
Chris@16 330 } else {
Chris@16 331 scanline_iterator tmpitr = previousScanlinePosition;
Chris@16 332 --tmpitr;
Chris@16 333 if((*tmpitr).second == (*previousScanlinePosition).second)
Chris@16 334 scanline.erase(previousScanlinePosition);
Chris@16 335 }
Chris@16 336
Chris@16 337 } else if(currentY < currentInterval.high()){
Chris@16 338 //elementY > currentInterval.high()
Chris@16 339 //split the interval between previous and current scanline elements
Chris@16 340 std::pair<coordinate_type, property_map> elementScan;
Chris@16 341 elementScan.first = currentInterval.high();
Chris@16 342 elementScan.second = (*previousScanlinePosition).second;
Chris@16 343 scanlinePosition = scanline.insert(scanlinePosition, elementScan);
Chris@16 344 continue;
Chris@16 345 } else {
Chris@16 346 break;
Chris@16 347 }
Chris@16 348 previousScanlinePosition = scanlinePosition;
Chris@16 349 currentY = previousY = elementY;
Chris@16 350 ++scanlinePosition;
Chris@16 351 if(scanlinePosition == scanline.end() &&
Chris@16 352 currentY < currentInterval.high()) {
Chris@16 353 //insert a new element for top of range
Chris@16 354 std::pair<coordinate_type, property_map> elementScan;
Chris@16 355 elementScan.first = currentInterval.high();
Chris@16 356 scanlinePosition = scanline.insert(scanline.end(), elementScan);
Chris@16 357 }
Chris@16 358 }
Chris@16 359 if(scanlinePosition == scanline.end() &&
Chris@16 360 currentY < currentInterval.high()) {
Chris@16 361 //handle case where we iterated to end of the scanline
Chris@16 362 //we need to insert an element into the scanline at currentY
Chris@16 363 //with property value coming from below
Chris@16 364 //and another one at currentInterval.high() with empty property value
Chris@16 365 mergeCount(scanline[currentY], countFromBelow);
Chris@16 366 std::pair<coordinate_type, property_map> elementScan;
Chris@16 367 elementScan.first = currentInterval.high();
Chris@16 368 scanline.insert(scanline.end(), elementScan);
Chris@16 369
Chris@16 370 edge_property element;
Chris@16 371 output.push_back(element);
Chris@16 372 output.back().first = property_merge_interval<coordinate_type>(currentY, currentInterval.high());
Chris@16 373 setProperty(output.back().second.second, countFromBelow);
Chris@16 374 mergeCount(countFromBelow, currentVertex.second);
Chris@16 375 } else {
Chris@16 376 mergeCount(countFromBelow, currentVertex.second);
Chris@16 377 if(countFromBelow.empty()) {
Chris@16 378 if(previousScanlinePosition == scanline.begin()) {
Chris@16 379 if((*previousScanlinePosition).second.empty()) {
Chris@16 380 scanline.erase(previousScanlinePosition);
Chris@16 381 //previousScanlinePosition = scanline.end();
Chris@16 382 //std::cout << "ERASE_A ";
Chris@16 383 }
Chris@16 384 } else {
Chris@16 385 scanline_iterator tmpitr = previousScanlinePosition;
Chris@16 386 --tmpitr;
Chris@16 387 if((*tmpitr).second == (*previousScanlinePosition).second) {
Chris@16 388 scanline.erase(previousScanlinePosition);
Chris@16 389 //previousScanlinePosition = scanline.end();
Chris@16 390 //std::cout << "ERASE_B ";
Chris@16 391 }
Chris@16 392 }
Chris@16 393 }
Chris@16 394 }
Chris@16 395 } else {
Chris@16 396 //count from below is empty, we are starting a new interval of change
Chris@16 397 countFromBelow = currentVertex.second;
Chris@16 398 scanlinePosition = scanline.lower_bound(currentVertex.first.y());
Chris@16 399 if(scanlinePosition != scanline.end()) {
Chris@16 400 if((*scanlinePosition).first != currentVertex.first.y()) {
Chris@16 401 if(scanlinePosition != scanline.begin()) {
Chris@16 402 //decrement to get the lower position of the first interval this vertex intersects
Chris@16 403 --scanlinePosition;
Chris@16 404 //insert a new element into the scanline for the incoming vertex
Chris@16 405 property_map& countOnLeft = (*scanlinePosition).second;
Chris@16 406 std::pair<coordinate_type, property_map> element(currentVertex.first.y(), countOnLeft);
Chris@16 407 scanlinePosition = scanline.insert(scanlinePosition, element);
Chris@16 408 } else {
Chris@16 409 property_map countOnLeft;
Chris@16 410 std::pair<coordinate_type, property_map> element(currentVertex.first.y(), countOnLeft);
Chris@16 411 scanlinePosition = scanline.insert(scanlinePosition, element);
Chris@16 412 }
Chris@16 413 }
Chris@16 414 } else {
Chris@16 415 property_map countOnLeft;
Chris@16 416 std::pair<coordinate_type, property_map> element(currentVertex.first.y(), countOnLeft);
Chris@16 417 scanlinePosition = scanline.insert(scanlinePosition, element);
Chris@16 418 }
Chris@16 419 }
Chris@16 420 previousY = currentVertex.first.y();
Chris@16 421 }
Chris@16 422
Chris@16 423 template <typename T>
Chris@16 424 inline int assertRedundant(T& t) {
Chris@16 425 if(t.empty()) return 0;
Chris@16 426 int count = 0;
Chris@16 427 typename T::iterator itr = t.begin();
Chris@16 428 if((*itr).second.empty())
Chris@16 429 ++count;
Chris@16 430 typename T::iterator itr2 = itr;
Chris@16 431 ++itr2;
Chris@16 432 while(itr2 != t.end()) {
Chris@16 433 if((*itr).second == (*itr2).second)
Chris@16 434 ++count;
Chris@16 435 itr = itr2;
Chris@16 436 ++itr2;
Chris@16 437 }
Chris@16 438 return count;
Chris@16 439 }
Chris@16 440
Chris@16 441 template <typename T>
Chris@16 442 inline void performExtract(T& result, property_merge_data& data) {
Chris@16 443 if(data.empty()) return;
Chris@16 444 //sort
Chris@16 445 polygon_sort(data.begin(), data.end(), less_vertex_data<vertex_property>());
Chris@16 446
Chris@16 447 //scanline
Chris@16 448 bool firstIteration = true;
Chris@16 449 scanlinePosition = scanline.end();
Chris@16 450 for(std::size_t i = 0; i < data.size(); ++i) {
Chris@16 451 if(firstIteration) {
Chris@16 452 mergeProperty(currentVertex.second, data[i].second);
Chris@16 453 currentVertex.first = data[i].first;
Chris@16 454 firstIteration = false;
Chris@16 455 } else {
Chris@16 456 if(data[i].first != currentVertex.first) {
Chris@16 457 if(data[i].first.x() != currentVertex.first.x()) {
Chris@16 458 processVertex(output);
Chris@16 459 //std::cout << scanline.size() << " ";
Chris@16 460 countFromBelow.clear(); //should already be clear
Chris@16 461 writeGraph(currentVertex.first.x(), result, output, scanline);
Chris@16 462 currentVertex.second.clear();
Chris@16 463 mergeProperty(currentVertex.second, data[i].second);
Chris@16 464 currentVertex.first = data[i].first;
Chris@16 465 } else {
Chris@16 466 processVertex(output);
Chris@16 467 currentVertex.second.clear();
Chris@16 468 mergeProperty(currentVertex.second, data[i].second);
Chris@16 469 currentVertex.first = data[i].first;
Chris@16 470 }
Chris@16 471 } else {
Chris@16 472 mergeProperty(currentVertex.second, data[i].second);
Chris@16 473 }
Chris@16 474 }
Chris@16 475 }
Chris@16 476 processVertex(output);
Chris@16 477 writeGraph(currentVertex.first.x(), result, output, scanline);
Chris@16 478 //std::cout << scanline.size() << "\n";
Chris@16 479 }
Chris@16 480
Chris@16 481 template <typename T>
Chris@16 482 inline void insertEdges(T& graph, property_set& p1, property_set& p2) {
Chris@16 483 for(typename property_set::iterator itr = p1.begin(); itr != p1.end(); ++itr) {
Chris@16 484 for(typename property_set::iterator itr2 = p2.begin(); itr2 != p2.end(); ++itr2) {
Chris@16 485 if(*itr != *itr2) {
Chris@16 486 graph[*itr].insert(*itr2);
Chris@16 487 graph[*itr2].insert(*itr);
Chris@16 488 }
Chris@16 489 }
Chris@16 490 }
Chris@16 491 }
Chris@16 492
Chris@16 493 template <typename T>
Chris@16 494 inline void propertySetAbove(coordinate_type y, property_set& ps, T& scanline) {
Chris@16 495 ps.clear();
Chris@16 496 typename T::iterator itr = scanline.find(y);
Chris@16 497 if(itr != scanline.end())
Chris@16 498 setProperty(ps, (*itr).second);
Chris@16 499 }
Chris@16 500
Chris@16 501 template <typename T>
Chris@16 502 inline void propertySetBelow(coordinate_type y, property_set& ps, T& scanline) {
Chris@16 503 ps.clear();
Chris@16 504 typename T::iterator itr = scanline.find(y);
Chris@16 505 if(itr != scanline.begin()) {
Chris@16 506 --itr;
Chris@16 507 setProperty(ps, (*itr).second);
Chris@16 508 }
Chris@16 509 }
Chris@16 510
Chris@16 511 template <typename T, typename T2>
Chris@16 512 inline void writeGraph(coordinate_type x, T& graph, edge_property_vector& output, T2& scanline) {
Chris@16 513 if(output.empty()) return;
Chris@16 514 edge_property* previousEdgeP = &(output[0]);
Chris@16 515 bool firstIteration = true;
Chris@16 516 property_set ps;
Chris@16 517 for(std::size_t i = 0; i < output.size(); ++i) {
Chris@16 518 edge_property& previousEdge = *previousEdgeP;
Chris@16 519 edge_property& edge = output[i];
Chris@16 520 if(previousEdge.first.high() == edge.first.low()) {
Chris@16 521 //horizontal edge
Chris@16 522 insertEdges(graph, edge.second.first, previousEdge.second.first);
Chris@16 523 //corner 1
Chris@16 524 insertEdges(graph, edge.second.first, previousEdge.second.second);
Chris@16 525 //other horizontal edge
Chris@16 526 insertEdges(graph, edge.second.second, previousEdge.second.second);
Chris@16 527 //corner 2
Chris@16 528 insertEdges(graph, edge.second.second, previousEdge.second.first);
Chris@16 529 } else {
Chris@16 530 if(!firstIteration){
Chris@16 531 //look up regions above previous edge
Chris@16 532 propertySetAbove(previousEdge.first.high(), ps, scanline);
Chris@16 533 insertEdges(graph, ps, previousEdge.second.first);
Chris@16 534 insertEdges(graph, ps, previousEdge.second.second);
Chris@16 535 }
Chris@16 536 //look up regions below current edge in the scanline
Chris@16 537 propertySetBelow(edge.first.high(), ps, scanline);
Chris@16 538 insertEdges(graph, ps, edge.second.first);
Chris@16 539 insertEdges(graph, ps, edge.second.second);
Chris@16 540 }
Chris@16 541 firstIteration = false;
Chris@16 542 //vertical edge
Chris@16 543 insertEdges(graph, edge.second.second, edge.second.first);
Chris@16 544 //shared region to left
Chris@16 545 insertEdges(graph, edge.second.second, edge.second.second);
Chris@16 546 //shared region to right
Chris@16 547 insertEdges(graph, edge.second.first, edge.second.first);
Chris@16 548 previousEdgeP = &(output[i]);
Chris@16 549 }
Chris@16 550 edge_property& previousEdge = *previousEdgeP;
Chris@16 551 propertySetAbove(previousEdge.first.high(), ps, scanline);
Chris@16 552 insertEdges(graph, ps, previousEdge.second.first);
Chris@16 553 insertEdges(graph, ps, previousEdge.second.second);
Chris@16 554 output.clear();
Chris@16 555 }
Chris@16 556
Chris@16 557 template <typename Result>
Chris@16 558 inline void writeOutput(coordinate_type x, Result& result, edge_property_vector& output) {
Chris@16 559 for(std::size_t i = 0; i < output.size(); ++i) {
Chris@16 560 edge_property& edge = output[i];
Chris@16 561 //edge.second.first is the property set on the left of the edge
Chris@16 562 if(!edge.second.first.empty()) {
Chris@16 563 typename Result::iterator itr = result.find(edge.second.first);
Chris@16 564 if(itr == result.end()) {
Chris@16 565 std::pair<property_set, polygon_set_type> element(edge.second.first, polygon_set_type(VERTICAL));
Chris@16 566 itr = result.insert(result.end(), element);
Chris@16 567 }
Chris@16 568 std::pair<interval_data<coordinate_type>, int> element2(interval_data<coordinate_type>(edge.first.low(), edge.first.high()), -1); //right edge of figure
Chris@16 569 (*itr).second.insert(x, element2);
Chris@16 570 }
Chris@16 571 if(!edge.second.second.empty()) {
Chris@16 572 //edge.second.second is the property set on the right of the edge
Chris@16 573 typename Result::iterator itr = result.find(edge.second.second);
Chris@16 574 if(itr == result.end()) {
Chris@16 575 std::pair<property_set, polygon_set_type> element(edge.second.second, polygon_set_type(VERTICAL));
Chris@16 576 itr = result.insert(result.end(), element);
Chris@16 577 }
Chris@16 578 std::pair<interval_data<coordinate_type>, int> element3(interval_data<coordinate_type>(edge.first.low(), edge.first.high()), 1); //left edge of figure
Chris@16 579 (*itr).second.insert(x, element3);
Chris@16 580 }
Chris@16 581 }
Chris@16 582 output.clear();
Chris@16 583 }
Chris@16 584 };
Chris@16 585
Chris@16 586 }
Chris@16 587 }
Chris@16 588 #endif