annotate DEPENDENCIES/generic/include/boost/polygon/polygon_90_set_data.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +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_POLYGON_90_SET_DATA_HPP
Chris@16 9 #define BOOST_POLYGON_POLYGON_90_SET_DATA_HPP
Chris@16 10 #include "isotropy.hpp"
Chris@16 11 #include "point_concept.hpp"
Chris@16 12 #include "transform.hpp"
Chris@16 13 #include "interval_concept.hpp"
Chris@16 14 #include "rectangle_concept.hpp"
Chris@16 15 #include "segment_concept.hpp"
Chris@16 16 #include "detail/iterator_points_to_compact.hpp"
Chris@16 17 #include "detail/iterator_compact_to_points.hpp"
Chris@16 18 #include "polygon_traits.hpp"
Chris@16 19
Chris@16 20 //manhattan boolean algorithms
Chris@16 21 #include "detail/boolean_op.hpp"
Chris@16 22 #include "detail/polygon_formation.hpp"
Chris@16 23 #include "detail/rectangle_formation.hpp"
Chris@16 24 #include "detail/max_cover.hpp"
Chris@16 25 #include "detail/property_merge.hpp"
Chris@16 26 #include "detail/polygon_90_touch.hpp"
Chris@16 27 #include "detail/iterator_geometry_to_set.hpp"
Chris@16 28
Chris@16 29 namespace boost { namespace polygon{
Chris@16 30 template <typename ltype, typename rtype, typename op_type>
Chris@16 31 class polygon_90_set_view;
Chris@16 32
Chris@16 33 template <typename T>
Chris@16 34 class polygon_90_set_data {
Chris@16 35 public:
Chris@16 36 typedef T coordinate_type;
Chris@16 37 typedef std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > > value_type;
Chris@16 38 typedef typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::const_iterator iterator_type;
Chris@16 39 typedef polygon_90_set_data operator_arg_type;
Chris@16 40
Chris@16 41 // default constructor
Chris@16 42 inline polygon_90_set_data() : orient_(HORIZONTAL), data_(), dirty_(false), unsorted_(false) {}
Chris@16 43
Chris@16 44 // constructor
Chris@16 45 inline polygon_90_set_data(orientation_2d orient) : orient_(orient), data_(), dirty_(false), unsorted_(false) {}
Chris@16 46
Chris@16 47 // constructor from an iterator pair over vertex data
Chris@16 48 template <typename iT>
Chris@16 49 inline polygon_90_set_data(orientation_2d orient, iT input_begin, iT input_end) :
Chris@16 50 orient_(HORIZONTAL), data_(), dirty_(false), unsorted_(false) {
Chris@16 51 dirty_ = true;
Chris@16 52 unsorted_ = true;
Chris@16 53 for( ; input_begin != input_end; ++input_begin) { insert(*input_begin); }
Chris@16 54 }
Chris@16 55
Chris@16 56 // copy constructor
Chris@16 57 inline polygon_90_set_data(const polygon_90_set_data& that) :
Chris@16 58 orient_(that.orient_), data_(that.data_), dirty_(that.dirty_), unsorted_(that.unsorted_) {}
Chris@16 59
Chris@16 60 template <typename ltype, typename rtype, typename op_type>
Chris@16 61 inline polygon_90_set_data(const polygon_90_set_view<ltype, rtype, op_type>& that);
Chris@16 62
Chris@16 63 // copy with orientation change constructor
Chris@16 64 inline polygon_90_set_data(orientation_2d orient, const polygon_90_set_data& that) :
Chris@16 65 orient_(orient), data_(), dirty_(false), unsorted_(false) {
Chris@16 66 insert(that, false, that.orient_);
Chris@16 67 }
Chris@16 68
Chris@16 69 // destructor
Chris@16 70 inline ~polygon_90_set_data() {}
Chris@16 71
Chris@16 72 // assignement operator
Chris@16 73 inline polygon_90_set_data& operator=(const polygon_90_set_data& that) {
Chris@16 74 if(this == &that) return *this;
Chris@16 75 orient_ = that.orient_;
Chris@16 76 data_ = that.data_;
Chris@16 77 dirty_ = that.dirty_;
Chris@16 78 unsorted_ = that.unsorted_;
Chris@16 79 return *this;
Chris@16 80 }
Chris@16 81
Chris@16 82 template <typename ltype, typename rtype, typename op_type>
Chris@16 83 inline polygon_90_set_data& operator=(const polygon_90_set_view<ltype, rtype, op_type>& that);
Chris@16 84
Chris@16 85 template <typename geometry_object>
Chris@16 86 inline polygon_90_set_data& operator=(const geometry_object& geometry) {
Chris@16 87 data_.clear();
Chris@16 88 insert(geometry);
Chris@16 89 return *this;
Chris@16 90 }
Chris@16 91
Chris@16 92 // insert iterator range
Chris@16 93 inline void insert(iterator_type input_begin, iterator_type input_end, orientation_2d orient = HORIZONTAL) {
Chris@16 94 if(input_begin == input_end || (!data_.empty() && &(*input_begin) == &(*(data_.begin())))) return;
Chris@16 95 dirty_ = true;
Chris@16 96 unsorted_ = true;
Chris@16 97 if(orient == orient_)
Chris@16 98 data_.insert(data_.end(), input_begin, input_end);
Chris@16 99 else {
Chris@16 100 for( ; input_begin != input_end; ++input_begin) {
Chris@16 101 insert(*input_begin, false, orient);
Chris@16 102 }
Chris@16 103 }
Chris@16 104 }
Chris@16 105
Chris@16 106 // insert iterator range
Chris@16 107 template <typename iT>
Chris@16 108 inline void insert(iT input_begin, iT input_end, orientation_2d orient = HORIZONTAL) {
Chris@16 109 if(input_begin == input_end) return;
Chris@16 110 dirty_ = true;
Chris@16 111 unsorted_ = true;
Chris@16 112 for( ; input_begin != input_end; ++input_begin) {
Chris@16 113 insert(*input_begin, false, orient);
Chris@16 114 }
Chris@16 115 }
Chris@16 116
Chris@16 117 inline void insert(const polygon_90_set_data& polygon_set) {
Chris@16 118 insert(polygon_set.begin(), polygon_set.end(), polygon_set.orient());
Chris@16 119 }
Chris@16 120
Chris@16 121 inline void insert(const std::pair<std::pair<point_data<coordinate_type>, point_data<coordinate_type> >, int>& edge, bool is_hole = false,
Chris@16 122 orientation_2d orient = HORIZONTAL) {
Chris@16 123 std::pair<coordinate_type, std::pair<coordinate_type, int> > vertex;
Chris@16 124 vertex.first = edge.first.first.x();
Chris@16 125 vertex.second.first = edge.first.first.y();
Chris@16 126 vertex.second.second = edge.second * (is_hole ? -1 : 1);
Chris@16 127 insert(vertex, false, VERTICAL);
Chris@16 128 vertex.first = edge.first.second.x();
Chris@16 129 vertex.second.first = edge.first.second.y();
Chris@16 130 vertex.second.second *= -1;
Chris@16 131 insert(vertex, false, VERTICAL);
Chris@16 132 }
Chris@16 133
Chris@16 134 template <typename geometry_type>
Chris@16 135 inline void insert(const geometry_type& geometry_object, bool is_hole = false, orientation_2d = HORIZONTAL) {
Chris@16 136 iterator_geometry_to_set<typename geometry_concept<geometry_type>::type, geometry_type>
Chris@16 137 begin_input(geometry_object, LOW, orient_, is_hole), end_input(geometry_object, HIGH, orient_, is_hole);
Chris@16 138 insert(begin_input, end_input, orient_);
Chris@16 139 }
Chris@16 140
Chris@16 141 inline void insert(const std::pair<coordinate_type, std::pair<coordinate_type, int> >& vertex, bool is_hole = false,
Chris@16 142 orientation_2d orient = HORIZONTAL) {
Chris@16 143 data_.push_back(vertex);
Chris@16 144 if(orient != orient_) std::swap(data_.back().first, data_.back().second.first);
Chris@16 145 if(is_hole) data_.back().second.second *= -1;
Chris@16 146 dirty_ = true;
Chris@16 147 unsorted_ = true;
Chris@16 148 }
Chris@16 149
Chris@16 150 inline void insert(coordinate_type major_coordinate, const std::pair<interval_data<coordinate_type>, int>& edge) {
Chris@16 151 std::pair<coordinate_type, std::pair<coordinate_type, int> > vertex;
Chris@16 152 vertex.first = major_coordinate;
Chris@16 153 vertex.second.first = edge.first.get(LOW);
Chris@16 154 vertex.second.second = edge.second;
Chris@16 155 insert(vertex, false, orient_);
Chris@16 156 vertex.second.first = edge.first.get(HIGH);
Chris@16 157 vertex.second.second *= -1;
Chris@16 158 insert(vertex, false, orient_);
Chris@16 159 }
Chris@16 160
Chris@16 161 template <typename output_container>
Chris@16 162 inline void get(output_container& output) const {
Chris@16 163 get_dispatch(output, typename geometry_concept<typename output_container::value_type>::type());
Chris@16 164 }
Chris@16 165
Chris@16 166 template <typename output_container>
Chris@16 167 inline void get(output_container& output, size_t vthreshold) const {
Chris@16 168 get_dispatch(output, typename geometry_concept<typename output_container::value_type>::type(), vthreshold);
Chris@16 169 }
Chris@16 170
Chris@16 171
Chris@16 172 template <typename output_container>
Chris@16 173 inline void get_polygons(output_container& output) const {
Chris@16 174 get_dispatch(output, polygon_90_concept());
Chris@16 175 }
Chris@16 176
Chris@16 177 template <typename output_container>
Chris@16 178 inline void get_rectangles(output_container& output) const {
Chris@16 179 clean();
Chris@16 180 form_rectangles(output, data_.begin(), data_.end(), orient_, rectangle_concept());
Chris@16 181 }
Chris@16 182
Chris@16 183 template <typename output_container>
Chris@16 184 inline void get_rectangles(output_container& output, orientation_2d slicing_orientation) const {
Chris@16 185 if(slicing_orientation == orient_) {
Chris@16 186 get_rectangles(output);
Chris@16 187 } else {
Chris@16 188 polygon_90_set_data<coordinate_type> ps(*this);
Chris@16 189 ps.transform(axis_transformation(axis_transformation::SWAP_XY));
Chris@16 190 output_container result;
Chris@16 191 ps.get_rectangles(result);
Chris@16 192 for(typename output_container::iterator itr = result.begin(); itr != result.end(); ++itr) {
Chris@16 193 ::boost::polygon::transform(*itr, axis_transformation(axis_transformation::SWAP_XY));
Chris@16 194 }
Chris@16 195 output.insert(output.end(), result.begin(), result.end());
Chris@16 196 }
Chris@16 197 }
Chris@16 198
Chris@16 199 // equivalence operator
Chris@16 200 inline bool operator==(const polygon_90_set_data& p) const {
Chris@16 201 if(orient_ == p.orient()) {
Chris@16 202 clean();
Chris@16 203 p.clean();
Chris@16 204 return data_ == p.data_;
Chris@16 205 } else {
Chris@16 206 return false;
Chris@16 207 }
Chris@16 208 }
Chris@16 209
Chris@16 210 // inequivalence operator
Chris@16 211 inline bool operator!=(const polygon_90_set_data& p) const {
Chris@16 212 return !((*this) == p);
Chris@16 213 }
Chris@16 214
Chris@16 215 // get iterator to begin vertex data
Chris@16 216 inline iterator_type begin() const {
Chris@16 217 return data_.begin();
Chris@16 218 }
Chris@16 219
Chris@16 220 // get iterator to end vertex data
Chris@16 221 inline iterator_type end() const {
Chris@16 222 return data_.end();
Chris@16 223 }
Chris@16 224
Chris@16 225 const value_type& value() const {
Chris@16 226 return data_;
Chris@16 227 }
Chris@16 228
Chris@16 229 // clear the contents of the polygon_90_set_data
Chris@16 230 inline void clear() { data_.clear(); dirty_ = unsorted_ = false; }
Chris@16 231
Chris@16 232 // find out if Polygon set is empty
Chris@16 233 inline bool empty() const { clean(); return data_.empty(); }
Chris@16 234
Chris@16 235 // get the Polygon set size in vertices
Chris@16 236 inline std::size_t size() const { clean(); return data_.size(); }
Chris@16 237
Chris@16 238 // get the current Polygon set capacity in vertices
Chris@16 239 inline std::size_t capacity() const { return data_.capacity(); }
Chris@16 240
Chris@16 241 // reserve size of polygon set in vertices
Chris@16 242 inline void reserve(std::size_t size) { return data_.reserve(size); }
Chris@16 243
Chris@16 244 // find out if Polygon set is sorted
Chris@16 245 inline bool sorted() const { return !unsorted_; }
Chris@16 246
Chris@16 247 // find out if Polygon set is clean
Chris@16 248 inline bool dirty() const { return dirty_; }
Chris@16 249
Chris@16 250 // get the scanline orientation of the polygon set
Chris@16 251 inline orientation_2d orient() const { return orient_; }
Chris@16 252
Chris@16 253 // Start BM
Chris@16 254 // The problem: If we have two polygon sets with two different scanline orientations:
Chris@16 255 // I tried changing the orientation of one to coincide with other (If not, resulting boolean operation
Chris@16 256 // produces spurious results).
Chris@16 257 // First I tried copying polygon data from one of the sets into another set with corrected orientation
Chris@16 258 // using one of the copy constructor that takes in orientation (see somewhere above in this file) --> copy constructor throws error
Chris@16 259 // Then I tried another approach:(see below). This approach also fails to produce the desired results when test case is run.
Chris@16 260 // Here is the part that beats me: If I comment out the whole section, I can do all the operations (^=, -=, &= )these commented out
Chris@16 261 // operations perform. So then why do we need them?. Hence, I commented out this whole section.
Chris@16 262 // End BM
Chris@16 263 // polygon_90_set_data<coordinate_type>& operator-=(const polygon_90_set_data& that) {
Chris@16 264 // sort();
Chris@16 265 // that.sort();
Chris@16 266 // value_type data;
Chris@16 267 // std::swap(data, data_);
Chris@16 268 // applyBooleanBinaryOp(data.begin(), data.end(),
Chris@16 269 // that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryNot>());
Chris@16 270 // return *this;
Chris@16 271 // }
Chris@16 272 // polygon_90_set_data<coordinate_type>& operator^=(const polygon_90_set_data& that) {
Chris@16 273 // sort();
Chris@16 274 // that.sort();
Chris@16 275 // value_type data;
Chris@16 276 // std::swap(data, data_);
Chris@16 277 // applyBooleanBinaryOp(data.begin(), data.end(),
Chris@16 278 // that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryXor>());
Chris@16 279 // return *this;
Chris@16 280 // }
Chris@16 281 // polygon_90_set_data<coordinate_type>& operator&=(const polygon_90_set_data& that) {
Chris@16 282 // sort();
Chris@16 283 // that.sort();
Chris@16 284 // value_type data;
Chris@16 285 // std::swap(data, data_);
Chris@16 286 // applyBooleanBinaryOp(data.begin(), data.end(),
Chris@16 287 // that.begin(), that.end(), boolean_op::BinaryCount<boolean_op::BinaryAnd>());
Chris@16 288 // return *this;
Chris@16 289 // }
Chris@16 290 // polygon_90_set_data<coordinate_type>& operator|=(const polygon_90_set_data& that) {
Chris@16 291 // insert(that);
Chris@16 292 // return *this;
Chris@16 293 // }
Chris@16 294
Chris@16 295 void clean() const {
Chris@16 296 sort();
Chris@16 297 if(dirty_) {
Chris@16 298 boolean_op::default_arg_workaround<int>::applyBooleanOr(data_);
Chris@16 299 dirty_ = false;
Chris@16 300 }
Chris@16 301 }
Chris@16 302
Chris@16 303 void sort() const{
Chris@16 304 if(unsorted_) {
Chris@16 305 polygon_sort(data_.begin(), data_.end());
Chris@16 306 unsorted_ = false;
Chris@16 307 }
Chris@16 308 }
Chris@16 309
Chris@16 310 template <typename input_iterator_type>
Chris@16 311 void set(input_iterator_type input_begin, input_iterator_type input_end, orientation_2d orient) {
Chris@16 312 data_.clear();
Chris@16 313 reserve(std::distance(input_begin, input_end));
Chris@16 314 data_.insert(data_.end(), input_begin, input_end);
Chris@16 315 orient_ = orient;
Chris@16 316 dirty_ = true;
Chris@16 317 unsorted_ = true;
Chris@16 318 }
Chris@16 319
Chris@16 320 void set(const value_type& value, orientation_2d orient) {
Chris@16 321 data_ = value;
Chris@16 322 orient_ = orient;
Chris@16 323 dirty_ = true;
Chris@16 324 unsorted_ = true;
Chris@16 325 }
Chris@16 326
Chris@16 327 //extents
Chris@16 328 template <typename rectangle_type>
Chris@16 329 bool
Chris@16 330 extents(rectangle_type& extents_rectangle) const {
Chris@16 331 clean();
Chris@16 332 if(data_.empty()) return false;
Chris@16 333 if(orient_ == HORIZONTAL)
Chris@16 334 set_points(extents_rectangle, point_data<coordinate_type>(data_[0].second.first, data_[0].first),
Chris@16 335 point_data<coordinate_type>(data_[data_.size() - 1].second.first, data_[data_.size() - 1].first));
Chris@16 336 else
Chris@16 337 set_points(extents_rectangle, point_data<coordinate_type>(data_[0].first, data_[0].second.first),
Chris@16 338 point_data<coordinate_type>(data_[data_.size() - 1].first, data_[data_.size() - 1].second.first));
Chris@16 339 for(std::size_t i = 1; i < data_.size() - 1; ++i) {
Chris@16 340 if(orient_ == HORIZONTAL)
Chris@16 341 encompass(extents_rectangle, point_data<coordinate_type>(data_[i].second.first, data_[i].first));
Chris@16 342 else
Chris@16 343 encompass(extents_rectangle, point_data<coordinate_type>(data_[i].first, data_[i].second.first));
Chris@16 344 }
Chris@16 345 return true;
Chris@16 346 }
Chris@16 347
Chris@16 348 polygon_90_set_data&
Chris@16 349 bloat2(typename coordinate_traits<coordinate_type>::unsigned_area_type west_bloating,
Chris@16 350 typename coordinate_traits<coordinate_type>::unsigned_area_type east_bloating,
Chris@16 351 typename coordinate_traits<coordinate_type>::unsigned_area_type south_bloating,
Chris@16 352 typename coordinate_traits<coordinate_type>::unsigned_area_type north_bloating) {
Chris@16 353 std::vector<rectangle_data<coordinate_type> > rects;
Chris@16 354 clean();
Chris@16 355 rects.reserve(data_.size() / 2);
Chris@16 356 get(rects);
Chris@16 357 rectangle_data<coordinate_type> convolutionRectangle(interval_data<coordinate_type>(-((coordinate_type)west_bloating),
Chris@16 358 (coordinate_type)east_bloating),
Chris@16 359 interval_data<coordinate_type>(-((coordinate_type)south_bloating),
Chris@16 360 (coordinate_type)north_bloating));
Chris@16 361 for(typename std::vector<rectangle_data<coordinate_type> >::iterator itr = rects.begin();
Chris@16 362 itr != rects.end(); ++itr) {
Chris@16 363 convolve(*itr, convolutionRectangle);
Chris@16 364 }
Chris@16 365 clear();
Chris@16 366 insert(rects.begin(), rects.end());
Chris@16 367 return *this;
Chris@16 368 }
Chris@16 369
Chris@16 370 static void modify_pt(point_data<coordinate_type>& pt, const point_data<coordinate_type>& prev_pt,
Chris@16 371 const point_data<coordinate_type>& current_pt, const point_data<coordinate_type>& next_pt,
Chris@16 372 coordinate_type west_bloating,
Chris@16 373 coordinate_type east_bloating,
Chris@16 374 coordinate_type south_bloating,
Chris@16 375 coordinate_type north_bloating) {
Chris@16 376 bool pxl = prev_pt.x() < current_pt.x();
Chris@16 377 bool pyl = prev_pt.y() < current_pt.y();
Chris@16 378 bool nxl = next_pt.x() < current_pt.x();
Chris@16 379 bool nyl = next_pt.y() < current_pt.y();
Chris@16 380 bool pxg = prev_pt.x() > current_pt.x();
Chris@16 381 bool pyg = prev_pt.y() > current_pt.y();
Chris@16 382 bool nxg = next_pt.x() > current_pt.x();
Chris@16 383 bool nyg = next_pt.y() > current_pt.y();
Chris@16 384 //two of the four if statements will execute
Chris@16 385 if(pxl)
Chris@16 386 pt.y(current_pt.y() - south_bloating);
Chris@16 387 if(pxg)
Chris@16 388 pt.y(current_pt.y() + north_bloating);
Chris@16 389 if(nxl)
Chris@16 390 pt.y(current_pt.y() + north_bloating);
Chris@16 391 if(nxg)
Chris@16 392 pt.y(current_pt.y() - south_bloating);
Chris@16 393 if(pyl)
Chris@16 394 pt.x(current_pt.x() + east_bloating);
Chris@16 395 if(pyg)
Chris@16 396 pt.x(current_pt.x() - west_bloating);
Chris@16 397 if(nyl)
Chris@16 398 pt.x(current_pt.x() - west_bloating);
Chris@16 399 if(nyg)
Chris@16 400 pt.x(current_pt.x() + east_bloating);
Chris@16 401 }
Chris@16 402 static void resize_poly_up(std::vector<point_data<coordinate_type> >& poly,
Chris@16 403 coordinate_type west_bloating,
Chris@16 404 coordinate_type east_bloating,
Chris@16 405 coordinate_type south_bloating,
Chris@16 406 coordinate_type north_bloating) {
Chris@16 407 point_data<coordinate_type> first_pt = poly[0];
Chris@16 408 point_data<coordinate_type> second_pt = poly[1];
Chris@16 409 point_data<coordinate_type> prev_pt = poly[0];
Chris@16 410 point_data<coordinate_type> current_pt = poly[1];
Chris@16 411 for(std::size_t i = 2; i < poly.size(); ++i) {
Chris@16 412 point_data<coordinate_type> next_pt = poly[i];
Chris@16 413 modify_pt(poly[i-1], prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating);
Chris@16 414 prev_pt = current_pt;
Chris@16 415 current_pt = next_pt;
Chris@16 416 }
Chris@16 417 point_data<coordinate_type> next_pt = first_pt;
Chris@16 418 modify_pt(poly.back(), prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating);
Chris@16 419 prev_pt = current_pt;
Chris@16 420 current_pt = next_pt;
Chris@16 421 next_pt = second_pt;
Chris@16 422 modify_pt(poly[0], prev_pt, current_pt, next_pt, west_bloating, east_bloating, south_bloating, north_bloating);
Chris@16 423 remove_colinear_pts(poly);
Chris@16 424 }
Chris@16 425 static bool resize_poly_down(std::vector<point_data<coordinate_type> >& poly,
Chris@16 426 coordinate_type west_shrinking,
Chris@16 427 coordinate_type east_shrinking,
Chris@16 428 coordinate_type south_shrinking,
Chris@16 429 coordinate_type north_shrinking) {
Chris@16 430 rectangle_data<coordinate_type> extents_rectangle;
Chris@16 431 set_points(extents_rectangle, poly[0], poly[0]);
Chris@16 432 point_data<coordinate_type> first_pt = poly[0];
Chris@16 433 point_data<coordinate_type> second_pt = poly[1];
Chris@16 434 point_data<coordinate_type> prev_pt = poly[0];
Chris@16 435 point_data<coordinate_type> current_pt = poly[1];
Chris@16 436 encompass(extents_rectangle, current_pt);
Chris@16 437 for(std::size_t i = 2; i < poly.size(); ++i) {
Chris@16 438 point_data<coordinate_type> next_pt = poly[i];
Chris@16 439 encompass(extents_rectangle, next_pt);
Chris@16 440 modify_pt(poly[i-1], prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking);
Chris@16 441 prev_pt = current_pt;
Chris@16 442 current_pt = next_pt;
Chris@16 443 }
Chris@16 444 if(delta(extents_rectangle, HORIZONTAL) < std::abs(west_shrinking + east_shrinking))
Chris@16 445 return false;
Chris@16 446 if(delta(extents_rectangle, VERTICAL) < std::abs(north_shrinking + south_shrinking))
Chris@16 447 return false;
Chris@16 448 point_data<coordinate_type> next_pt = first_pt;
Chris@16 449 modify_pt(poly.back(), prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking);
Chris@16 450 prev_pt = current_pt;
Chris@16 451 current_pt = next_pt;
Chris@16 452 next_pt = second_pt;
Chris@16 453 modify_pt(poly[0], prev_pt, current_pt, next_pt, west_shrinking, east_shrinking, south_shrinking, north_shrinking);
Chris@16 454 return remove_colinear_pts(poly);
Chris@16 455 }
Chris@16 456
Chris@16 457 static bool remove_colinear_pts(std::vector<point_data<coordinate_type> >& poly) {
Chris@16 458 bool found_colinear = true;
Chris@16 459 while(found_colinear && poly.size() >= 4) {
Chris@16 460 found_colinear = false;
Chris@16 461 typename std::vector<point_data<coordinate_type> >::iterator itr = poly.begin();
Chris@16 462 itr += poly.size() - 1; //get last element position
Chris@16 463 typename std::vector<point_data<coordinate_type> >::iterator itr2 = poly.begin();
Chris@16 464 typename std::vector<point_data<coordinate_type> >::iterator itr3 = itr2;
Chris@16 465 ++itr3;
Chris@16 466 std::size_t count = 0;
Chris@16 467 for( ; itr3 < poly.end(); ++itr3) {
Chris@16 468 if(((*itr).x() == (*itr2).x() && (*itr).x() == (*itr3).x()) ||
Chris@16 469 ((*itr).y() == (*itr2).y() && (*itr).y() == (*itr3).y()) ) {
Chris@16 470 ++count;
Chris@16 471 found_colinear = true;
Chris@16 472 } else {
Chris@16 473 itr = itr2;
Chris@16 474 ++itr2;
Chris@16 475 }
Chris@16 476 *itr2 = *itr3;
Chris@16 477 }
Chris@16 478 itr3 = poly.begin();
Chris@16 479 if(((*itr).x() == (*itr2).x() && (*itr).x() == (*itr3).x()) ||
Chris@16 480 ((*itr).y() == (*itr2).y() && (*itr).y() == (*itr3).y()) ) {
Chris@16 481 ++count;
Chris@16 482 found_colinear = true;
Chris@16 483 }
Chris@16 484 poly.erase(poly.end() - count, poly.end());
Chris@16 485 }
Chris@16 486 return poly.size() >= 4;
Chris@16 487 }
Chris@16 488
Chris@16 489 polygon_90_set_data&
Chris@16 490 bloat(typename coordinate_traits<coordinate_type>::unsigned_area_type west_bloating,
Chris@16 491 typename coordinate_traits<coordinate_type>::unsigned_area_type east_bloating,
Chris@16 492 typename coordinate_traits<coordinate_type>::unsigned_area_type south_bloating,
Chris@16 493 typename coordinate_traits<coordinate_type>::unsigned_area_type north_bloating) {
Chris@16 494 std::list<polygon_45_with_holes_data<coordinate_type> > polys;
Chris@16 495 get(polys);
Chris@16 496 clear();
Chris@16 497 for(typename std::list<polygon_45_with_holes_data<coordinate_type> >::iterator itr = polys.begin();
Chris@16 498 itr != polys.end(); ++itr) {
Chris@16 499 //polygon_90_set_data<coordinate_type> psref;
Chris@16 500 //psref.insert(view_as<polygon_90_concept>((*itr).self_));
Chris@16 501 //rectangle_data<coordinate_type> prerect;
Chris@16 502 //psref.extents(prerect);
Chris@16 503 resize_poly_up((*itr).self_.coords_, (coordinate_type)west_bloating, (coordinate_type)east_bloating,
Chris@16 504 (coordinate_type)south_bloating, (coordinate_type)north_bloating);
Chris@16 505 iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
Chris@16 506 begin_input(view_as<polygon_90_concept>((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE),
Chris@16 507 end_input(view_as<polygon_90_concept>((*itr).self_), HIGH, orient_, false, true, COUNTERCLOCKWISE);
Chris@16 508 insert(begin_input, end_input, orient_);
Chris@16 509 //polygon_90_set_data<coordinate_type> pstest;
Chris@16 510 //pstest.insert(view_as<polygon_90_concept>((*itr).self_));
Chris@16 511 //psref.bloat2(west_bloating, east_bloating, south_bloating, north_bloating);
Chris@16 512 //if(!equivalence(psref, pstest)) {
Chris@16 513 // std::cout << "test failed\n";
Chris@16 514 //}
Chris@16 515 for(typename std::list<polygon_45_data<coordinate_type> >::iterator itrh = (*itr).holes_.begin();
Chris@16 516 itrh != (*itr).holes_.end(); ++itrh) {
Chris@16 517 //rectangle_data<coordinate_type> rect;
Chris@16 518 //psref.extents(rect);
Chris@16 519 //polygon_90_set_data<coordinate_type> psrefhole;
Chris@16 520 //psrefhole.insert(prerect);
Chris@16 521 //psrefhole.insert(view_as<polygon_90_concept>(*itrh), true);
Chris@16 522 //polygon_45_data<coordinate_type> testpoly(*itrh);
Chris@16 523 if(resize_poly_down((*itrh).coords_,(coordinate_type)west_bloating, (coordinate_type)east_bloating,
Chris@16 524 (coordinate_type)south_bloating, (coordinate_type)north_bloating)) {
Chris@16 525 iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
Chris@16 526 begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true),
Chris@16 527 end_input2(view_as<polygon_90_concept>(*itrh), HIGH, orient_, true, true);
Chris@16 528 insert(begin_input2, end_input2, orient_);
Chris@16 529 //polygon_90_set_data<coordinate_type> pstesthole;
Chris@16 530 //pstesthole.insert(rect);
Chris@16 531 //iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
Chris@16 532 // begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true);
Chris@16 533 //pstesthole.insert(begin_input2, end_input, orient_);
Chris@16 534 //psrefhole.bloat2(west_bloating, east_bloating, south_bloating, north_bloating);
Chris@16 535 //if(!equivalence(psrefhole, pstesthole)) {
Chris@16 536 // std::cout << (winding(testpoly) == CLOCKWISE) << std::endl;
Chris@16 537 // std::cout << (winding(*itrh) == CLOCKWISE) << std::endl;
Chris@16 538 // polygon_90_set_data<coordinate_type> c(psrefhole);
Chris@16 539 // c.clean();
Chris@16 540 // polygon_90_set_data<coordinate_type> a(pstesthole);
Chris@16 541 // polygon_90_set_data<coordinate_type> b(pstesthole);
Chris@16 542 // a.sort();
Chris@16 543 // b.clean();
Chris@16 544 // std::cout << "test hole failed\n";
Chris@16 545 // //std::cout << testpoly << std::endl;
Chris@16 546 //}
Chris@16 547 }
Chris@16 548 }
Chris@16 549 }
Chris@16 550 return *this;
Chris@16 551 }
Chris@16 552
Chris@16 553 polygon_90_set_data&
Chris@16 554 shrink(typename coordinate_traits<coordinate_type>::unsigned_area_type west_shrinking,
Chris@16 555 typename coordinate_traits<coordinate_type>::unsigned_area_type east_shrinking,
Chris@16 556 typename coordinate_traits<coordinate_type>::unsigned_area_type south_shrinking,
Chris@16 557 typename coordinate_traits<coordinate_type>::unsigned_area_type north_shrinking) {
Chris@16 558 std::list<polygon_45_with_holes_data<coordinate_type> > polys;
Chris@16 559 get(polys);
Chris@16 560 clear();
Chris@16 561 for(typename std::list<polygon_45_with_holes_data<coordinate_type> >::iterator itr = polys.begin();
Chris@16 562 itr != polys.end(); ++itr) {
Chris@16 563 //polygon_90_set_data<coordinate_type> psref;
Chris@16 564 //psref.insert(view_as<polygon_90_concept>((*itr).self_));
Chris@16 565 //rectangle_data<coordinate_type> prerect;
Chris@16 566 //psref.extents(prerect);
Chris@16 567 //polygon_45_data<coordinate_type> testpoly((*itr).self_);
Chris@16 568 if(resize_poly_down((*itr).self_.coords_, -(coordinate_type)west_shrinking, -(coordinate_type)east_shrinking,
Chris@16 569 -(coordinate_type)south_shrinking, -(coordinate_type)north_shrinking)) {
Chris@16 570 iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
Chris@16 571 begin_input(view_as<polygon_90_concept>((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE),
Chris@16 572 end_input(view_as<polygon_90_concept>((*itr).self_), HIGH, orient_, false, true, COUNTERCLOCKWISE);
Chris@16 573 insert(begin_input, end_input, orient_);
Chris@16 574 //iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
Chris@16 575 // begin_input2(view_as<polygon_90_concept>((*itr).self_), LOW, orient_, false, true, COUNTERCLOCKWISE);
Chris@16 576 //polygon_90_set_data<coordinate_type> pstest;
Chris@16 577 //pstest.insert(begin_input2, end_input, orient_);
Chris@16 578 //psref.shrink2(west_shrinking, east_shrinking, south_shrinking, north_shrinking);
Chris@16 579 //if(!equivalence(psref, pstest)) {
Chris@16 580 // std::cout << "test failed\n";
Chris@16 581 //}
Chris@16 582 for(typename std::list<polygon_45_data<coordinate_type> >::iterator itrh = (*itr).holes_.begin();
Chris@16 583 itrh != (*itr).holes_.end(); ++itrh) {
Chris@16 584 //rectangle_data<coordinate_type> rect;
Chris@16 585 //psref.extents(rect);
Chris@16 586 //polygon_90_set_data<coordinate_type> psrefhole;
Chris@16 587 //psrefhole.insert(prerect);
Chris@16 588 //psrefhole.insert(view_as<polygon_90_concept>(*itrh), true);
Chris@16 589 //polygon_45_data<coordinate_type> testpoly(*itrh);
Chris@16 590 resize_poly_up((*itrh).coords_, -(coordinate_type)west_shrinking, -(coordinate_type)east_shrinking,
Chris@16 591 -(coordinate_type)south_shrinking, -(coordinate_type)north_shrinking);
Chris@16 592 iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
Chris@16 593 begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true),
Chris@16 594 end_input2(view_as<polygon_90_concept>(*itrh), HIGH, orient_, true, true);
Chris@16 595 insert(begin_input2, end_input2, orient_);
Chris@16 596 //polygon_90_set_data<coordinate_type> pstesthole;
Chris@16 597 //pstesthole.insert(rect);
Chris@16 598 //iterator_geometry_to_set<polygon_90_concept, view_of<polygon_90_concept, polygon_45_data<coordinate_type> > >
Chris@16 599 // begin_input2(view_as<polygon_90_concept>(*itrh), LOW, orient_, true, true);
Chris@16 600 //pstesthole.insert(begin_input2, end_input, orient_);
Chris@16 601 //psrefhole.shrink2(west_shrinking, east_shrinking, south_shrinking, north_shrinking);
Chris@16 602 //if(!equivalence(psrefhole, pstesthole)) {
Chris@16 603 // std::cout << (winding(testpoly) == CLOCKWISE) << std::endl;
Chris@16 604 // std::cout << (winding(*itrh) == CLOCKWISE) << std::endl;
Chris@16 605 // polygon_90_set_data<coordinate_type> c(psrefhole);
Chris@16 606 // c.clean();
Chris@16 607 // polygon_90_set_data<coordinate_type> a(pstesthole);
Chris@16 608 // polygon_90_set_data<coordinate_type> b(pstesthole);
Chris@16 609 // a.sort();
Chris@16 610 // b.clean();
Chris@16 611 // std::cout << "test hole failed\n";
Chris@16 612 // //std::cout << testpoly << std::endl;
Chris@16 613 //}
Chris@16 614 }
Chris@16 615 }
Chris@16 616 }
Chris@16 617 return *this;
Chris@16 618 }
Chris@16 619
Chris@16 620 polygon_90_set_data&
Chris@16 621 shrink2(typename coordinate_traits<coordinate_type>::unsigned_area_type west_shrinking,
Chris@16 622 typename coordinate_traits<coordinate_type>::unsigned_area_type east_shrinking,
Chris@16 623 typename coordinate_traits<coordinate_type>::unsigned_area_type south_shrinking,
Chris@16 624 typename coordinate_traits<coordinate_type>::unsigned_area_type north_shrinking) {
Chris@16 625 rectangle_data<coordinate_type> externalBoundary;
Chris@16 626 if(!extents(externalBoundary)) return *this;
Chris@16 627 ::boost::polygon::bloat(externalBoundary, 10); //bloat by diferential ammount
Chris@16 628 //insert a hole that encompasses the data
Chris@16 629 insert(externalBoundary, true); //note that the set is in a dirty state now
Chris@16 630 sort(); //does not apply implicit OR operation
Chris@16 631 std::vector<rectangle_data<coordinate_type> > rects;
Chris@16 632 rects.reserve(data_.size() / 2);
Chris@16 633 //begin does not apply implicit or operation, this is a dirty range
Chris@16 634 form_rectangles(rects, data_.begin(), data_.end(), orient_, rectangle_concept());
Chris@16 635 clear();
Chris@16 636 rectangle_data<coordinate_type> convolutionRectangle(interval_data<coordinate_type>(-((coordinate_type)east_shrinking),
Chris@16 637 (coordinate_type)west_shrinking),
Chris@16 638 interval_data<coordinate_type>(-((coordinate_type)north_shrinking),
Chris@16 639 (coordinate_type)south_shrinking));
Chris@16 640 for(typename std::vector<rectangle_data<coordinate_type> >::iterator itr = rects.begin();
Chris@16 641 itr != rects.end(); ++itr) {
Chris@16 642 rectangle_data<coordinate_type>& rect = *itr;
Chris@16 643 convolve(rect, convolutionRectangle);
Chris@16 644 //insert rectangle as a hole
Chris@16 645 insert(rect, true);
Chris@16 646 }
Chris@16 647 convolve(externalBoundary, convolutionRectangle);
Chris@16 648 //insert duplicate of external boundary as solid to cancel out the external hole boundaries
Chris@16 649 insert(externalBoundary);
Chris@16 650 clean(); //we have negative values in the set, so we need to apply an OR operation to make it valid input to a boolean
Chris@16 651 return *this;
Chris@16 652 }
Chris@16 653
Chris@16 654 polygon_90_set_data&
Chris@16 655 shrink(direction_2d dir, typename coordinate_traits<coordinate_type>::unsigned_area_type shrinking) {
Chris@16 656 if(dir == WEST)
Chris@16 657 return shrink(shrinking, 0, 0, 0);
Chris@16 658 if(dir == EAST)
Chris@16 659 return shrink(0, shrinking, 0, 0);
Chris@16 660 if(dir == SOUTH)
Chris@16 661 return shrink(0, 0, shrinking, 0);
Chris@16 662 return shrink(0, 0, 0, shrinking);
Chris@16 663 }
Chris@16 664
Chris@16 665 polygon_90_set_data&
Chris@16 666 bloat(direction_2d dir, typename coordinate_traits<coordinate_type>::unsigned_area_type shrinking) {
Chris@16 667 if(dir == WEST)
Chris@16 668 return bloat(shrinking, 0, 0, 0);
Chris@16 669 if(dir == EAST)
Chris@16 670 return bloat(0, shrinking, 0, 0);
Chris@16 671 if(dir == SOUTH)
Chris@16 672 return bloat(0, 0, shrinking, 0);
Chris@16 673 return bloat(0, 0, 0, shrinking);
Chris@16 674 }
Chris@16 675
Chris@16 676 polygon_90_set_data&
Chris@16 677 resize(coordinate_type west, coordinate_type east, coordinate_type south, coordinate_type north);
Chris@16 678
Chris@16 679 polygon_90_set_data& move(coordinate_type x_delta, coordinate_type y_delta) {
Chris@16 680 for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
Chris@16 681 itr = data_.begin(); itr != data_.end(); ++itr) {
Chris@16 682 if(orient_ == orientation_2d(VERTICAL)) {
Chris@16 683 (*itr).first += x_delta;
Chris@16 684 (*itr).second.first += y_delta;
Chris@16 685 } else {
Chris@16 686 (*itr).second.first += x_delta;
Chris@16 687 (*itr).first += y_delta;
Chris@16 688 }
Chris@16 689 }
Chris@16 690 return *this;
Chris@16 691 }
Chris@16 692
Chris@16 693 // transform set
Chris@16 694 template <typename transformation_type>
Chris@16 695 polygon_90_set_data& transform(const transformation_type& transformation) {
Chris@16 696 direction_2d dir1, dir2;
Chris@16 697 transformation.get_directions(dir1, dir2);
Chris@16 698 int sign = dir1.get_sign() * dir2.get_sign();
Chris@16 699 for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
Chris@16 700 itr = data_.begin(); itr != data_.end(); ++itr) {
Chris@16 701 if(orient_ == orientation_2d(VERTICAL)) {
Chris@16 702 transformation.transform((*itr).first, (*itr).second.first);
Chris@16 703 } else {
Chris@16 704 transformation.transform((*itr).second.first, (*itr).first);
Chris@16 705 }
Chris@16 706 (*itr).second.second *= sign;
Chris@16 707 }
Chris@16 708 if(dir1 != EAST || dir2 != NORTH)
Chris@16 709 unsorted_ = true; //some mirroring or rotation must have happened
Chris@16 710 return *this;
Chris@16 711 }
Chris@16 712
Chris@16 713 // scale set
Chris@16 714 polygon_90_set_data& scale_up(typename coordinate_traits<coordinate_type>::unsigned_area_type factor) {
Chris@16 715 for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
Chris@16 716 itr = data_.begin(); itr != data_.end(); ++itr) {
Chris@16 717 (*itr).first *= (coordinate_type)factor;
Chris@16 718 (*itr).second.first *= (coordinate_type)factor;
Chris@16 719 }
Chris@16 720 return *this;
Chris@16 721 }
Chris@16 722 polygon_90_set_data& scale_down(typename coordinate_traits<coordinate_type>::unsigned_area_type factor) {
Chris@16 723 typedef typename coordinate_traits<coordinate_type>::coordinate_distance dt;
Chris@16 724 for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
Chris@16 725 itr = data_.begin(); itr != data_.end(); ++itr) {
Chris@16 726 (*itr).first = scaling_policy<coordinate_type>::round((dt)((*itr).first) / (dt)factor);
Chris@16 727 (*itr).second.first = scaling_policy<coordinate_type>::round((dt)((*itr).second.first) / (dt)factor);
Chris@16 728 }
Chris@16 729 unsorted_ = true; //scaling down can make coordinates equal that were not previously equal
Chris@16 730 return *this;
Chris@16 731 }
Chris@16 732 template <typename scaling_type>
Chris@16 733 polygon_90_set_data& scale(const anisotropic_scale_factor<scaling_type>& scaling) {
Chris@16 734 for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
Chris@16 735 itr = data_.begin(); itr != data_.end(); ++itr) {
Chris@16 736 if(orient_ == orientation_2d(VERTICAL)) {
Chris@16 737 scaling.scale((*itr).first, (*itr).second.first);
Chris@16 738 } else {
Chris@16 739 scaling.scale((*itr).second.first, (*itr).first);
Chris@16 740 }
Chris@16 741 }
Chris@16 742 unsorted_ = true;
Chris@16 743 return *this;
Chris@16 744 }
Chris@16 745 template <typename scaling_type>
Chris@16 746 polygon_90_set_data& scale_with(const scaling_type& scaling) {
Chris@16 747 for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
Chris@16 748 itr = data_.begin(); itr != data_.end(); ++itr) {
Chris@16 749 if(orient_ == orientation_2d(VERTICAL)) {
Chris@16 750 scaling.scale((*itr).first, (*itr).second.first);
Chris@16 751 } else {
Chris@16 752 scaling.scale((*itr).second.first, (*itr).first);
Chris@16 753 }
Chris@16 754 }
Chris@16 755 unsorted_ = true;
Chris@16 756 return *this;
Chris@16 757 }
Chris@16 758 polygon_90_set_data& scale(double factor) {
Chris@16 759 typedef typename coordinate_traits<coordinate_type>::coordinate_distance dt;
Chris@16 760 for(typename std::vector<std::pair<coordinate_type, std::pair<coordinate_type, int> > >::iterator
Chris@16 761 itr = data_.begin(); itr != data_.end(); ++itr) {
Chris@16 762 (*itr).first = scaling_policy<coordinate_type>::round((dt)((*itr).first) * (dt)factor);
Chris@16 763 (*itr).second.first = scaling_policy<coordinate_type>::round((dt)((*itr).second.first) * (dt)factor);
Chris@16 764 }
Chris@16 765 unsorted_ = true; //scaling make coordinates equal that were not previously equal
Chris@16 766 return *this;
Chris@16 767 }
Chris@16 768
Chris@16 769 polygon_90_set_data& self_xor() {
Chris@16 770 sort();
Chris@16 771 if(dirty_) { //if it is clean it is a no-op
Chris@16 772 boolean_op::default_arg_workaround<boolean_op::UnaryCount>::applyBooleanOr(data_);
Chris@16 773 dirty_ = false;
Chris@16 774 }
Chris@16 775 return *this;
Chris@16 776 }
Chris@16 777
Chris@16 778 polygon_90_set_data& self_intersect() {
Chris@16 779 sort();
Chris@16 780 if(dirty_) { //if it is clean it is a no-op
Chris@16 781 interval_data<coordinate_type> ivl((std::numeric_limits<coordinate_type>::min)(), (std::numeric_limits<coordinate_type>::max)());
Chris@16 782 rectangle_data<coordinate_type> rect(ivl, ivl);
Chris@16 783 insert(rect, true);
Chris@16 784 clean();
Chris@16 785 }
Chris@16 786 return *this;
Chris@16 787 }
Chris@16 788
Chris@16 789 inline polygon_90_set_data& interact(const polygon_90_set_data& that) {
Chris@16 790 typedef coordinate_type Unit;
Chris@16 791 if(that.dirty_) that.clean();
Chris@16 792 typename touch_90_operation<Unit>::TouchSetData tsd;
Chris@16 793 touch_90_operation<Unit>::populateTouchSetData(tsd, that.data_, 0);
Chris@16 794 std::vector<polygon_90_data<Unit> > polys;
Chris@16 795 get(polys);
Chris@16 796 std::vector<std::set<int> > graph(polys.size()+1, std::set<int>());
Chris@16 797 for(std::size_t i = 0; i < polys.size(); ++i){
Chris@16 798 polygon_90_set_data<Unit> psTmp(that.orient_);
Chris@16 799 psTmp.insert(polys[i]);
Chris@16 800 psTmp.clean();
Chris@16 801 touch_90_operation<Unit>::populateTouchSetData(tsd, psTmp.data_, i+1);
Chris@16 802 }
Chris@16 803 touch_90_operation<Unit>::performTouch(graph, tsd);
Chris@16 804 clear();
Chris@16 805 for(std::set<int>::iterator itr = graph[0].begin(); itr != graph[0].end(); ++itr){
Chris@16 806 insert(polys[(*itr)-1]);
Chris@16 807 }
Chris@16 808 dirty_ = false;
Chris@16 809 return *this;
Chris@16 810 }
Chris@16 811
Chris@16 812
Chris@16 813 template <class T2, typename iterator_type_1, typename iterator_type_2>
Chris@16 814 void applyBooleanBinaryOp(iterator_type_1 itr1, iterator_type_1 itr1_end,
Chris@16 815 iterator_type_2 itr2, iterator_type_2 itr2_end,
Chris@16 816 T2 defaultCount) {
Chris@16 817 data_.clear();
Chris@16 818 boolean_op::applyBooleanBinaryOp(data_, itr1, itr1_end, itr2, itr2_end, defaultCount);
Chris@16 819 }
Chris@16 820
Chris@16 821 private:
Chris@16 822 orientation_2d orient_;
Chris@16 823 mutable value_type data_;
Chris@16 824 mutable bool dirty_;
Chris@16 825 mutable bool unsorted_;
Chris@16 826
Chris@16 827 private:
Chris@16 828 //functions
Chris@16 829 template <typename output_container>
Chris@16 830 void get_dispatch(output_container& output, rectangle_concept ) const {
Chris@16 831 clean();
Chris@16 832 form_rectangles(output, data_.begin(), data_.end(), orient_, rectangle_concept());
Chris@16 833 }
Chris@16 834 template <typename output_container>
Chris@16 835 void get_dispatch(output_container& output, polygon_90_concept tag) const {
Chris@16 836 get_fracture(output, true, tag);
Chris@16 837 }
Chris@16 838
Chris@16 839 template <typename output_container>
Chris@16 840 void get_dispatch(output_container& output, polygon_90_concept tag,
Chris@16 841 size_t vthreshold) const {
Chris@16 842 get_fracture(output, true, tag, vthreshold);
Chris@16 843 }
Chris@16 844
Chris@16 845 template <typename output_container>
Chris@16 846 void get_dispatch(output_container& output, polygon_90_with_holes_concept tag) const {
Chris@16 847 get_fracture(output, false, tag);
Chris@16 848 }
Chris@16 849
Chris@16 850 template <typename output_container>
Chris@16 851 void get_dispatch(output_container& output, polygon_90_with_holes_concept tag,
Chris@16 852 size_t vthreshold) const {
Chris@16 853 get_fracture(output, false, tag, vthreshold);
Chris@16 854 }
Chris@16 855
Chris@16 856
Chris@16 857 template <typename output_container>
Chris@16 858 void get_dispatch(output_container& output, polygon_45_concept tag) const {
Chris@16 859 get_fracture(output, true, tag);
Chris@16 860 }
Chris@16 861 template <typename output_container>
Chris@16 862 void get_dispatch(output_container& output, polygon_45_with_holes_concept tag) const {
Chris@16 863 get_fracture(output, false, tag);
Chris@16 864 }
Chris@16 865 template <typename output_container>
Chris@16 866 void get_dispatch(output_container& output, polygon_concept tag) const {
Chris@16 867 get_fracture(output, true, tag);
Chris@16 868 }
Chris@16 869 template <typename output_container>
Chris@16 870 void get_dispatch(output_container& output, polygon_with_holes_concept tag) const {
Chris@16 871 get_fracture(output, false, tag);
Chris@16 872 }
Chris@16 873 template <typename output_container, typename concept_type>
Chris@16 874 void get_fracture(output_container& container, bool fracture_holes, concept_type tag) const {
Chris@16 875 clean();
Chris@16 876 ::boost::polygon::get_polygons(container, data_.begin(), data_.end(), orient_, fracture_holes, tag);
Chris@16 877 }
Chris@16 878
Chris@16 879 template <typename output_container, typename concept_type>
Chris@16 880 void get_fracture(output_container& container, bool fracture_holes, concept_type tag,
Chris@16 881 size_t vthreshold) const {
Chris@16 882 clean();
Chris@16 883 ::boost::polygon::get_polygons(container, data_.begin(), data_.end(), orient_, fracture_holes, tag, vthreshold);
Chris@16 884 }
Chris@16 885 };
Chris@16 886
Chris@16 887 template <typename coordinate_type>
Chris@16 888 polygon_90_set_data<coordinate_type>&
Chris@16 889 polygon_90_set_data<coordinate_type>::resize(coordinate_type west,
Chris@16 890 coordinate_type east,
Chris@16 891 coordinate_type south,
Chris@16 892 coordinate_type north) {
Chris@16 893 move(-west, -south);
Chris@16 894 coordinate_type e_total = west + east;
Chris@16 895 coordinate_type n_total = south + north;
Chris@16 896 if((e_total < 0) ^ (n_total < 0)) {
Chris@16 897 //different signs
Chris@16 898 if(e_total < 0) {
Chris@16 899 shrink(0, -e_total, 0, 0);
Chris@16 900 if(n_total != 0)
Chris@16 901 return bloat(0, 0, 0, n_total);
Chris@16 902 else
Chris@16 903 return (*this);
Chris@16 904 } else {
Chris@16 905 shrink(0, 0, 0, -n_total); //shrink first
Chris@16 906 if(e_total != 0)
Chris@16 907 return bloat(0, e_total, 0, 0);
Chris@16 908 else
Chris@16 909 return (*this);
Chris@16 910 }
Chris@16 911 } else {
Chris@16 912 if(e_total < 0) {
Chris@16 913 return shrink(0, -e_total, 0, -n_total);
Chris@16 914 }
Chris@16 915 return bloat(0, e_total, 0, n_total);
Chris@16 916 }
Chris@16 917 }
Chris@16 918
Chris@16 919 template <typename coordinate_type, typename property_type>
Chris@16 920 class property_merge_90 {
Chris@16 921 private:
Chris@16 922 std::vector<std::pair<property_merge_point<coordinate_type>, std::pair<property_type, int> > > pmd_;
Chris@16 923 public:
Chris@16 924 inline property_merge_90() : pmd_() {}
Chris@16 925 inline property_merge_90(const property_merge_90& that) : pmd_(that.pmd_) {}
Chris@16 926 inline property_merge_90& operator=(const property_merge_90& that) { pmd_ = that.pmd_; return *this; }
Chris@16 927 inline void insert(const polygon_90_set_data<coordinate_type>& ps, const property_type& property) {
Chris@16 928 merge_scanline<coordinate_type, property_type, polygon_90_set_data<coordinate_type> >::
Chris@16 929 populate_property_merge_data(pmd_, ps.begin(), ps.end(), property, ps.orient());
Chris@16 930 }
Chris@16 931 template <class GeoObjT>
Chris@16 932 inline void insert(const GeoObjT& geoObj, const property_type& property) {
Chris@16 933 polygon_90_set_data<coordinate_type> ps;
Chris@16 934 ps.insert(geoObj);
Chris@16 935 insert(ps, property);
Chris@16 936 }
Chris@16 937 //merge properties of input geometries and store the resulting geometries of regions
Chris@16 938 //with unique sets of merged properties to polygons sets in a map keyed by sets of properties
Chris@16 939 // T = std::map<std::set<property_type>, polygon_90_set_data<coordiante_type> > or
Chris@16 940 // T = std::map<std::vector<property_type>, polygon_90_set_data<coordiante_type> >
Chris@16 941 template <typename ResultType>
Chris@16 942 inline void merge(ResultType& result) {
Chris@16 943 merge_scanline<coordinate_type, property_type, polygon_90_set_data<coordinate_type>, typename ResultType::key_type> ms;
Chris@16 944 ms.perform_merge(result, pmd_);
Chris@16 945 }
Chris@16 946 };
Chris@16 947
Chris@16 948 //ConnectivityExtraction computes the graph of connectivity between rectangle, polygon and
Chris@16 949 //polygon set graph nodes where an edge is created whenever the geometry in two nodes overlap
Chris@16 950 template <typename coordinate_type>
Chris@16 951 class connectivity_extraction_90 {
Chris@16 952 private:
Chris@16 953 typedef typename touch_90_operation<coordinate_type>::TouchSetData tsd;
Chris@16 954 tsd tsd_;
Chris@16 955 unsigned int nodeCount_;
Chris@16 956 public:
Chris@16 957 inline connectivity_extraction_90() : tsd_(), nodeCount_(0) {}
Chris@16 958 inline connectivity_extraction_90(const connectivity_extraction_90& that) : tsd_(that.tsd_),
Chris@16 959 nodeCount_(that.nodeCount_) {}
Chris@16 960 inline connectivity_extraction_90& operator=(const connectivity_extraction_90& that) {
Chris@16 961 tsd_ = that.tsd_;
Chris@16 962 nodeCount_ = that.nodeCount_; {}
Chris@16 963 return *this;
Chris@16 964 }
Chris@16 965
Chris@16 966 //insert a polygon set graph node, the value returned is the id of the graph node
Chris@16 967 inline unsigned int insert(const polygon_90_set_data<coordinate_type>& ps) {
Chris@16 968 ps.clean();
Chris@16 969 touch_90_operation<coordinate_type>::populateTouchSetData(tsd_, ps.begin(), ps.end(), nodeCount_);
Chris@16 970 return nodeCount_++;
Chris@16 971 }
Chris@16 972 template <class GeoObjT>
Chris@16 973 inline unsigned int insert(const GeoObjT& geoObj) {
Chris@16 974 polygon_90_set_data<coordinate_type> ps;
Chris@16 975 ps.insert(geoObj);
Chris@16 976 return insert(ps);
Chris@16 977 }
Chris@16 978
Chris@16 979 //extract connectivity and store the edges in the graph
Chris@16 980 //graph must be indexable by graph node id and the indexed value must be a std::set of
Chris@16 981 //graph node id
Chris@16 982 template <class GraphT>
Chris@16 983 inline void extract(GraphT& graph) {
Chris@16 984 touch_90_operation<coordinate_type>::performTouch(graph, tsd_);
Chris@16 985 }
Chris@16 986 };
Chris@16 987 }
Chris@16 988 }
Chris@16 989 #endif