annotate DEPENDENCIES/generic/include/boost/polygon/polygon_45_set_data.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_POLYGON_45_SET_DATA_HPP
Chris@16 9 #define BOOST_POLYGON_POLYGON_45_SET_DATA_HPP
Chris@16 10 #include "polygon_90_set_data.hpp"
Chris@16 11 #include "detail/boolean_op_45.hpp"
Chris@16 12 #include "detail/polygon_45_formation.hpp"
Chris@16 13 #include "detail/polygon_45_touch.hpp"
Chris@16 14 #include "detail/property_merge_45.hpp"
Chris@16 15 namespace boost { namespace polygon{
Chris@16 16
Chris@16 17 enum RoundingOption { CLOSEST = 0, OVERSIZE = 1, UNDERSIZE = 2, SQRT2 = 3, SQRT1OVER2 = 4 };
Chris@16 18 enum CornerOption { INTERSECTION = 0, ORTHOGONAL = 1, UNFILLED = 2 };
Chris@16 19
Chris@16 20 template <typename ltype, typename rtype, int op_type>
Chris@16 21 class polygon_45_set_view;
Chris@16 22
Chris@16 23 struct polygon_45_set_concept {};
Chris@16 24
Chris@16 25 template <typename Unit>
Chris@16 26 class polygon_45_set_data {
Chris@16 27 public:
Chris@16 28 typedef typename polygon_45_formation<Unit>::Vertex45Compact Vertex45Compact;
Chris@16 29 typedef std::vector<Vertex45Compact> Polygon45VertexData;
Chris@16 30
Chris@16 31 typedef Unit coordinate_type;
Chris@16 32 typedef Polygon45VertexData value_type;
Chris@16 33 typedef typename value_type::const_iterator iterator_type;
Chris@16 34 typedef polygon_45_set_data operator_arg_type;
Chris@16 35
Chris@16 36 // default constructor
Chris@16 37 inline polygon_45_set_data() : error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) {}
Chris@16 38
Chris@16 39 // constructor from a geometry object
Chris@16 40 template <typename geometry_type>
Chris@16 41 inline polygon_45_set_data(const geometry_type& that) : error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) {
Chris@16 42 insert(that);
Chris@16 43 }
Chris@16 44
Chris@16 45 // copy constructor
Chris@16 46 inline polygon_45_set_data(const polygon_45_set_data& that) :
Chris@16 47 error_data_(that.error_data_), data_(that.data_), dirty_(that.dirty_),
Chris@16 48 unsorted_(that.unsorted_), is_manhattan_(that.is_manhattan_) {}
Chris@16 49
Chris@16 50 template <typename ltype, typename rtype, int op_type>
Chris@16 51 inline polygon_45_set_data(const polygon_45_set_view<ltype, rtype, op_type>& that) :
Chris@16 52 error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) {
Chris@16 53 (*this) = that.value();
Chris@16 54 }
Chris@16 55
Chris@16 56 // destructor
Chris@16 57 inline ~polygon_45_set_data() {}
Chris@16 58
Chris@16 59 // assignement operator
Chris@16 60 inline polygon_45_set_data& operator=(const polygon_45_set_data& that) {
Chris@16 61 if(this == &that) return *this;
Chris@16 62 error_data_ = that.error_data_;
Chris@16 63 data_ = that.data_;
Chris@16 64 dirty_ = that.dirty_;
Chris@16 65 unsorted_ = that.unsorted_;
Chris@16 66 is_manhattan_ = that.is_manhattan_;
Chris@16 67 return *this;
Chris@16 68 }
Chris@16 69
Chris@16 70 template <typename ltype, typename rtype, int op_type>
Chris@16 71 inline polygon_45_set_data& operator=(const polygon_45_set_view<ltype, rtype, op_type>& that) {
Chris@16 72 (*this) = that.value();
Chris@16 73 return *this;
Chris@16 74 }
Chris@16 75
Chris@16 76 template <typename geometry_object>
Chris@16 77 inline polygon_45_set_data& operator=(const geometry_object& geometry) {
Chris@16 78 data_.clear();
Chris@16 79 insert(geometry);
Chris@16 80 return *this;
Chris@16 81 }
Chris@16 82
Chris@16 83 // insert iterator range
Chris@16 84 inline void insert(iterator_type input_begin, iterator_type input_end, bool is_hole = false) {
Chris@16 85 if(input_begin == input_end || (!data_.empty() && &(*input_begin) == &(*(data_.begin())))) return;
Chris@16 86 dirty_ = true;
Chris@16 87 unsorted_ = true;
Chris@16 88 while(input_begin != input_end) {
Chris@16 89 insert(*input_begin, is_hole);
Chris@16 90 ++input_begin;
Chris@16 91 }
Chris@16 92 }
Chris@16 93
Chris@16 94 // insert iterator range
Chris@16 95 template <typename iT>
Chris@16 96 inline void insert(iT input_begin, iT input_end, bool is_hole = false) {
Chris@16 97 if(input_begin == input_end) return;
Chris@16 98 dirty_ = true;
Chris@16 99 unsorted_ = true;
Chris@16 100 while(input_begin != input_end) {
Chris@16 101 insert(*input_begin, is_hole);
Chris@16 102 ++input_begin;
Chris@16 103 }
Chris@16 104 }
Chris@16 105
Chris@16 106 inline void insert(const polygon_45_set_data& polygon_set, bool is_hole = false);
Chris@16 107 template <typename coord_type>
Chris@16 108 inline void insert(const polygon_45_set_data<coord_type>& polygon_set, bool is_hole = false);
Chris@16 109
Chris@16 110 template <typename geometry_type>
Chris@16 111 inline void insert(const geometry_type& geometry_object, bool is_hole = false) {
Chris@16 112 insert_dispatch(geometry_object, is_hole, typename geometry_concept<geometry_type>::type());
Chris@16 113 }
Chris@16 114
Chris@16 115 inline void insert_clean(const Vertex45Compact& vertex_45, bool is_hole = false) {
Chris@16 116 if(vertex_45.count.is_45()) is_manhattan_ = false;
Chris@16 117 data_.push_back(vertex_45);
Chris@16 118 if(is_hole) data_.back().count.invert();
Chris@16 119 }
Chris@16 120
Chris@16 121 inline void insert(const Vertex45Compact& vertex_45, bool is_hole = false) {
Chris@16 122 dirty_ = true;
Chris@16 123 unsorted_ = true;
Chris@16 124 insert_clean(vertex_45, is_hole);
Chris@16 125 }
Chris@16 126
Chris@16 127 template <typename coordinate_type_2>
Chris@16 128 inline void insert(const polygon_90_set_data<coordinate_type_2>& polygon_set, bool is_hole = false) {
Chris@16 129 if(polygon_set.orient() == VERTICAL) {
Chris@16 130 for(typename polygon_90_set_data<coordinate_type_2>::iterator_type itr = polygon_set.begin();
Chris@16 131 itr != polygon_set.end(); ++itr) {
Chris@16 132 Vertex45Compact vertex_45(point_data<Unit>((*itr).first, (*itr).second.first), 2, (*itr).second.second);
Chris@16 133 vertex_45.count[1] = (*itr).second.second;
Chris@16 134 if(is_hole) vertex_45.count[1] *= - 1;
Chris@16 135 insert_clean(vertex_45, is_hole);
Chris@16 136 }
Chris@16 137 } else {
Chris@16 138 for(typename polygon_90_set_data<coordinate_type_2>::iterator_type itr = polygon_set.begin();
Chris@16 139 itr != polygon_set.end(); ++itr) {
Chris@16 140 Vertex45Compact vertex_45(point_data<Unit>((*itr).second.first, (*itr).first), 2, (*itr).second.second);
Chris@16 141 vertex_45.count[1] = (*itr).second.second;
Chris@16 142 if(is_hole) vertex_45.count[1] *= - 1;
Chris@16 143 insert_clean(vertex_45, is_hole);
Chris@16 144 }
Chris@16 145 }
Chris@16 146 dirty_ = true;
Chris@16 147 unsorted_ = true;
Chris@16 148 }
Chris@16 149
Chris@16 150 template <typename output_container>
Chris@16 151 inline void get(output_container& output) const {
Chris@16 152 get_dispatch(output, typename geometry_concept<typename output_container::value_type>::type());
Chris@16 153 }
Chris@16 154
Chris@16 155 inline bool has_error_data() const { return !error_data_.empty(); }
Chris@16 156 inline std::size_t error_count() const { return error_data_.size() / 4; }
Chris@16 157 inline void get_error_data(polygon_45_set_data& p) const {
Chris@16 158 p.data_.insert(p.data_.end(), error_data_.begin(), error_data_.end());
Chris@16 159 }
Chris@16 160
Chris@16 161 // equivalence operator
Chris@16 162 inline bool operator==(const polygon_45_set_data& p) const {
Chris@16 163 clean();
Chris@16 164 p.clean();
Chris@16 165 return data_ == p.data_;
Chris@16 166 }
Chris@16 167
Chris@16 168 // inequivalence operator
Chris@16 169 inline bool operator!=(const polygon_45_set_data& p) const {
Chris@16 170 return !((*this) == p);
Chris@16 171 }
Chris@16 172
Chris@16 173 // get iterator to begin vertex data
Chris@16 174 inline iterator_type begin() const {
Chris@16 175 return data_.begin();
Chris@16 176 }
Chris@16 177
Chris@16 178 // get iterator to end vertex data
Chris@16 179 inline iterator_type end() const {
Chris@16 180 return data_.end();
Chris@16 181 }
Chris@16 182
Chris@16 183 const value_type& value() const {
Chris@16 184 return data_;
Chris@16 185 }
Chris@16 186
Chris@16 187 // clear the contents of the polygon_45_set_data
Chris@16 188 inline void clear() { data_.clear(); error_data_.clear(); dirty_ = unsorted_ = false; is_manhattan_ = true; }
Chris@16 189
Chris@16 190 // find out if Polygon set is empty
Chris@16 191 inline bool empty() const { return data_.empty(); }
Chris@16 192
Chris@16 193 // get the Polygon set size in vertices
Chris@16 194 inline std::size_t size() const { clean(); return data_.size(); }
Chris@16 195
Chris@16 196 // get the current Polygon set capacity in vertices
Chris@16 197 inline std::size_t capacity() const { return data_.capacity(); }
Chris@16 198
Chris@16 199 // reserve size of polygon set in vertices
Chris@16 200 inline void reserve(std::size_t size) { return data_.reserve(size); }
Chris@16 201
Chris@16 202 // find out if Polygon set is sorted
Chris@16 203 inline bool sorted() const { return !unsorted_; }
Chris@16 204
Chris@16 205 // find out if Polygon set is clean
Chris@16 206 inline bool dirty() const { return dirty_; }
Chris@16 207
Chris@16 208 // find out if Polygon set is clean
Chris@16 209 inline bool is_manhattan() const { return is_manhattan_; }
Chris@16 210
Chris@16 211 bool clean() const;
Chris@16 212
Chris@16 213 void sort() const{
Chris@16 214 if(unsorted_) {
Chris@16 215 polygon_sort(data_.begin(), data_.end());
Chris@16 216 unsorted_ = false;
Chris@16 217 }
Chris@16 218 }
Chris@16 219
Chris@16 220 template <typename input_iterator_type>
Chris@16 221 void set(input_iterator_type input_begin, input_iterator_type input_end) {
Chris@16 222 data_.clear();
Chris@16 223 reserve(std::distance(input_begin, input_end));
Chris@16 224 insert(input_begin, input_end);
Chris@16 225 dirty_ = true;
Chris@16 226 unsorted_ = true;
Chris@16 227 }
Chris@16 228
Chris@16 229 void set_clean(const value_type& value) {
Chris@16 230 data_ = value;
Chris@16 231 dirty_ = false;
Chris@16 232 unsorted_ = false;
Chris@16 233 }
Chris@16 234
Chris@16 235 void set(const value_type& value) {
Chris@16 236 data_ = value;
Chris@16 237 dirty_ = true;
Chris@16 238 unsorted_ = true;
Chris@16 239 }
Chris@16 240
Chris@16 241 // append to the container cT with polygons (holes will be fractured vertically)
Chris@16 242 template <class cT>
Chris@16 243 void get_polygons(cT& container) const {
Chris@16 244 get_dispatch(container, polygon_45_concept());
Chris@16 245 }
Chris@16 246
Chris@16 247 // append to the container cT with PolygonWithHoles objects
Chris@16 248 template <class cT>
Chris@16 249 void get_polygons_with_holes(cT& container) const {
Chris@16 250 get_dispatch(container, polygon_45_with_holes_concept());
Chris@16 251 }
Chris@16 252
Chris@16 253 // append to the container cT with polygons of three or four verticies
Chris@16 254 // slicing orientation is vertical
Chris@16 255 template <class cT>
Chris@16 256 void get_trapezoids(cT& container) const {
Chris@16 257 clean();
Chris@16 258 typename polygon_45_formation<Unit>::Polygon45Tiling pf;
Chris@16 259 //std::cout << "FORMING POLYGONS\n";
Chris@16 260 pf.scan(container, data_.begin(), data_.end());
Chris@16 261 //std::cout << "DONE FORMING POLYGONS\n";
Chris@16 262 }
Chris@16 263
Chris@16 264 // append to the container cT with polygons of three or four verticies
Chris@16 265 template <class cT>
Chris@16 266 void get_trapezoids(cT& container, orientation_2d slicing_orientation) const {
Chris@16 267 if(slicing_orientation == VERTICAL) {
Chris@16 268 get_trapezoids(container);
Chris@16 269 } else {
Chris@16 270 polygon_45_set_data<Unit> ps(*this);
Chris@16 271 ps.transform(axis_transformation(axis_transformation::SWAP_XY));
Chris@16 272 cT result;
Chris@16 273 ps.get_trapezoids(result);
Chris@16 274 for(typename cT::iterator itr = result.begin(); itr != result.end(); ++itr) {
Chris@16 275 ::boost::polygon::transform(*itr, axis_transformation(axis_transformation::SWAP_XY));
Chris@16 276 }
Chris@16 277 container.insert(container.end(), result.begin(), result.end());
Chris@16 278 }
Chris@16 279 }
Chris@16 280
Chris@16 281 // insert vertex sequence
Chris@16 282 template <class iT>
Chris@16 283 void insert_vertex_sequence(iT begin_vertex, iT end_vertex,
Chris@16 284 direction_1d winding, bool is_hole = false);
Chris@16 285
Chris@16 286 // get the external boundary rectangle
Chris@16 287 template <typename rectangle_type>
Chris@16 288 bool extents(rectangle_type& rect) const;
Chris@16 289
Chris@16 290 // snap verticies of set to even,even or odd,odd coordinates
Chris@16 291 void snap() const;
Chris@16 292
Chris@16 293 // |= &= += *= -= ^= binary operators
Chris@16 294 polygon_45_set_data& operator|=(const polygon_45_set_data& b);
Chris@16 295 polygon_45_set_data& operator&=(const polygon_45_set_data& b);
Chris@16 296 polygon_45_set_data& operator+=(const polygon_45_set_data& b);
Chris@16 297 polygon_45_set_data& operator*=(const polygon_45_set_data& b);
Chris@16 298 polygon_45_set_data& operator-=(const polygon_45_set_data& b);
Chris@16 299 polygon_45_set_data& operator^=(const polygon_45_set_data& b);
Chris@16 300
Chris@16 301 // resizing operations
Chris@16 302 polygon_45_set_data& operator+=(Unit delta);
Chris@16 303 polygon_45_set_data& operator-=(Unit delta);
Chris@16 304
Chris@16 305 // shrink the Polygon45Set by shrinking
Chris@16 306 polygon_45_set_data& resize(coordinate_type resizing, RoundingOption rounding = CLOSEST,
Chris@16 307 CornerOption corner = INTERSECTION);
Chris@16 308
Chris@16 309 // transform set
Chris@16 310 template <typename transformation_type>
Chris@16 311 polygon_45_set_data& transform(const transformation_type& tr);
Chris@16 312
Chris@16 313 // scale set
Chris@16 314 polygon_45_set_data& scale_up(typename coordinate_traits<Unit>::unsigned_area_type factor);
Chris@16 315 polygon_45_set_data& scale_down(typename coordinate_traits<Unit>::unsigned_area_type factor);
Chris@16 316 polygon_45_set_data& scale(double scaling);
Chris@16 317
Chris@16 318 // self_intersect
Chris@16 319 polygon_45_set_data& self_intersect() {
Chris@16 320 sort();
Chris@16 321 applyAdaptiveUnary_<1>(); //1 = AND
Chris@16 322 dirty_ = false;
Chris@16 323 return *this;
Chris@16 324 }
Chris@16 325
Chris@16 326 // self_xor
Chris@16 327 polygon_45_set_data& self_xor() {
Chris@16 328 sort();
Chris@16 329 applyAdaptiveUnary_<3>(); //3 = XOR
Chris@16 330 dirty_ = false;
Chris@16 331 return *this;
Chris@16 332 }
Chris@16 333
Chris@16 334 // accumulate the bloated polygon
Chris@16 335 template <typename geometry_type>
Chris@16 336 polygon_45_set_data& insert_with_resize(const geometry_type& poly,
Chris@16 337 coordinate_type resizing, RoundingOption rounding = CLOSEST,
Chris@16 338 CornerOption corner = INTERSECTION,
Chris@16 339 bool hole = false) {
Chris@16 340 return insert_with_resize_dispatch(poly, resizing, rounding, corner, hole, typename geometry_concept<geometry_type>::type());
Chris@16 341 }
Chris@16 342
Chris@16 343 private:
Chris@16 344 mutable value_type error_data_;
Chris@16 345 mutable value_type data_;
Chris@16 346 mutable bool dirty_;
Chris@16 347 mutable bool unsorted_;
Chris@16 348 mutable bool is_manhattan_;
Chris@16 349
Chris@16 350 private:
Chris@16 351 //functions
Chris@16 352 template <typename output_container>
Chris@16 353 void get_dispatch(output_container& output, polygon_45_concept tag) const {
Chris@16 354 get_fracture(output, true, tag);
Chris@16 355 }
Chris@16 356 template <typename output_container>
Chris@16 357 void get_dispatch(output_container& output, polygon_45_with_holes_concept tag) const {
Chris@16 358 get_fracture(output, false, tag);
Chris@16 359 }
Chris@16 360 template <typename output_container>
Chris@16 361 void get_dispatch(output_container& output, polygon_concept tag) const {
Chris@16 362 get_fracture(output, true, tag);
Chris@16 363 }
Chris@16 364 template <typename output_container>
Chris@16 365 void get_dispatch(output_container& output, polygon_with_holes_concept tag) const {
Chris@16 366 get_fracture(output, false, tag);
Chris@16 367 }
Chris@16 368 template <typename output_container, typename concept_type>
Chris@16 369 void get_fracture(output_container& container, bool fracture_holes, concept_type ) const {
Chris@16 370 clean();
Chris@16 371 typename polygon_45_formation<Unit>::Polygon45Formation pf(fracture_holes);
Chris@16 372 //std::cout << "FORMING POLYGONS\n";
Chris@16 373 pf.scan(container, data_.begin(), data_.end());
Chris@16 374 }
Chris@16 375
Chris@16 376 template <typename geometry_type>
Chris@16 377 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, undefined_concept) {
Chris@16 378 insert(geometry_object.begin(), geometry_object.end(), is_hole);
Chris@16 379 }
Chris@16 380 template <typename geometry_type>
Chris@16 381 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, rectangle_concept tag);
Chris@16 382 template <typename geometry_type>
Chris@16 383 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_90_concept ) {
Chris@16 384 insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole);
Chris@16 385 }
Chris@16 386 template <typename geometry_type>
Chris@16 387 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_90_with_holes_concept ) {
Chris@16 388 insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole);
Chris@16 389 for(typename polygon_with_holes_traits<geometry_type>::iterator_holes_type itr =
Chris@16 390 begin_holes(geometry_object); itr != end_holes(geometry_object);
Chris@16 391 ++itr) {
Chris@16 392 insert_vertex_sequence(begin_points(*itr), end_points(*itr), winding(*itr), !is_hole);
Chris@16 393 }
Chris@16 394 }
Chris@16 395 template <typename geometry_type>
Chris@16 396 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_45_concept ) {
Chris@16 397 insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole);
Chris@16 398 }
Chris@16 399 template <typename geometry_type>
Chris@16 400 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_45_with_holes_concept ) {
Chris@16 401 insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole);
Chris@16 402 for(typename polygon_with_holes_traits<geometry_type>::iterator_holes_type itr =
Chris@16 403 begin_holes(geometry_object); itr != end_holes(geometry_object);
Chris@16 404 ++itr) {
Chris@16 405 insert_vertex_sequence(begin_points(*itr), end_points(*itr), winding(*itr), !is_hole);
Chris@16 406 }
Chris@16 407 }
Chris@16 408 template <typename geometry_type>
Chris@16 409 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_45_set_concept ) {
Chris@16 410 polygon_45_set_data ps;
Chris@16 411 assign(ps, geometry_object);
Chris@16 412 insert(ps, is_hole);
Chris@16 413 }
Chris@16 414 template <typename geometry_type>
Chris@16 415 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_90_set_concept ) {
Chris@16 416 std::list<polygon_90_data<coordinate_type> > pl;
Chris@16 417 assign(pl, geometry_object);
Chris@16 418 insert(pl.begin(), pl.end(), is_hole);
Chris@16 419 }
Chris@16 420
Chris@16 421 void insert_vertex_half_edge_45_pair(const point_data<Unit>& pt1, point_data<Unit>& pt2,
Chris@16 422 const point_data<Unit>& pt3, direction_1d wdir);
Chris@16 423
Chris@16 424 template <typename geometry_type>
Chris@16 425 polygon_45_set_data& insert_with_resize_dispatch(const geometry_type& poly,
Chris@16 426 coordinate_type resizing, RoundingOption rounding,
Chris@16 427 CornerOption corner, bool hole, polygon_45_concept tag);
Chris@16 428
Chris@16 429 // accumulate the bloated polygon with holes
Chris@16 430 template <typename geometry_type>
Chris@16 431 polygon_45_set_data& insert_with_resize_dispatch(const geometry_type& poly,
Chris@16 432 coordinate_type resizing, RoundingOption rounding,
Chris@16 433 CornerOption corner, bool hole, polygon_45_with_holes_concept tag);
Chris@16 434
Chris@16 435 static void snap_vertex_45(Vertex45Compact& vertex);
Chris@16 436
Chris@16 437 public:
Chris@16 438 template <int op>
Chris@16 439 void applyAdaptiveBoolean_(const polygon_45_set_data& rvalue) const;
Chris@16 440 template <int op>
Chris@16 441 void applyAdaptiveBoolean_(polygon_45_set_data& result, const polygon_45_set_data& rvalue) const;
Chris@16 442 template <int op>
Chris@16 443 void applyAdaptiveUnary_() const;
Chris@16 444 };
Chris@16 445
Chris@16 446 template <typename T>
Chris@16 447 struct geometry_concept<polygon_45_set_data<T> > {
Chris@16 448 typedef polygon_45_set_concept type;
Chris@16 449 };
Chris@16 450
Chris@16 451 template <typename iT, typename T>
Chris@16 452 void scale_up_vertex_45_compact_range(iT beginr, iT endr, T factor) {
Chris@16 453 for( ; beginr != endr; ++beginr) {
Chris@16 454 scale_up((*beginr).pt, factor);
Chris@16 455 }
Chris@16 456 }
Chris@16 457 template <typename iT, typename T>
Chris@16 458 void scale_down_vertex_45_compact_range_blindly(iT beginr, iT endr, T factor) {
Chris@16 459 for( ; beginr != endr; ++beginr) {
Chris@16 460 scale_down((*beginr).pt, factor);
Chris@16 461 }
Chris@16 462 }
Chris@16 463
Chris@16 464 template <typename Unit>
Chris@16 465 inline std::pair<int, int> characterizeEdge45(const point_data<Unit>& pt1, const point_data<Unit>& pt2) {
Chris@16 466 std::pair<int, int> retval(0, 1);
Chris@16 467 if(pt1.x() == pt2.x()) {
Chris@16 468 retval.first = 3;
Chris@16 469 retval.second = -1;
Chris@16 470 return retval;
Chris@16 471 }
Chris@16 472 //retval.second = pt1.x() < pt2.x() ? -1 : 1;
Chris@16 473 retval.second = 1;
Chris@16 474 if(pt1.y() == pt2.y()) {
Chris@16 475 retval.first = 1;
Chris@16 476 } else if(pt1.x() < pt2.x()) {
Chris@16 477 if(pt1.y() < pt2.y()) {
Chris@16 478 retval.first = 2;
Chris@16 479 } else {
Chris@16 480 retval.first = 0;
Chris@16 481 }
Chris@16 482 } else {
Chris@16 483 if(pt1.y() < pt2.y()) {
Chris@16 484 retval.first = 0;
Chris@16 485 } else {
Chris@16 486 retval.first = 2;
Chris@16 487 }
Chris@16 488 }
Chris@16 489 return retval;
Chris@16 490 }
Chris@16 491
Chris@16 492 template <typename cT, typename pT>
Chris@16 493 bool insert_vertex_half_edge_45_pair_into_vector(cT& output,
Chris@16 494 const pT& pt1, pT& pt2,
Chris@16 495 const pT& pt3,
Chris@16 496 direction_1d wdir) {
Chris@16 497 int multiplier = wdir == LOW ? -1 : 1;
Chris@16 498 typename cT::value_type vertex(pt2, 0, 0);
Chris@16 499 //std::cout << pt1 << " " << pt2 << " " << pt3 << std::endl;
Chris@16 500 std::pair<int, int> check;
Chris@16 501 check = characterizeEdge45(pt1, pt2);
Chris@16 502 //std::cout << "index " << check.first << " " << check.second * -multiplier << std::endl;
Chris@16 503 vertex.count[check.first] += check.second * -multiplier;
Chris@16 504 check = characterizeEdge45(pt2, pt3);
Chris@16 505 //std::cout << "index " << check.first << " " << check.second * multiplier << std::endl;
Chris@16 506 vertex.count[check.first] += check.second * multiplier;
Chris@16 507 output.push_back(vertex);
Chris@16 508 return vertex.count.is_45();
Chris@16 509 }
Chris@16 510
Chris@16 511 template <typename Unit>
Chris@16 512 inline void polygon_45_set_data<Unit>::insert_vertex_half_edge_45_pair(const point_data<Unit>& pt1, point_data<Unit>& pt2,
Chris@16 513 const point_data<Unit>& pt3,
Chris@16 514 direction_1d wdir) {
Chris@16 515 if(insert_vertex_half_edge_45_pair_into_vector(data_, pt1, pt2, pt3, wdir)) is_manhattan_ = false;
Chris@16 516 }
Chris@16 517
Chris@16 518 template <typename Unit>
Chris@16 519 template <class iT>
Chris@16 520 inline void polygon_45_set_data<Unit>::insert_vertex_sequence(iT begin_vertex, iT end_vertex,
Chris@16 521 direction_1d winding, bool is_hole) {
Chris@16 522 if(begin_vertex == end_vertex) return;
Chris@16 523 if(is_hole) winding = winding.backward();
Chris@16 524 iT itr = begin_vertex;
Chris@16 525 if(itr == end_vertex) return;
Chris@16 526 point_data<Unit> firstPt = *itr;
Chris@16 527 ++itr;
Chris@16 528 point_data<Unit> secondPt(firstPt);
Chris@16 529 //skip any duplicate points
Chris@16 530 do {
Chris@16 531 if(itr == end_vertex) return;
Chris@16 532 secondPt = *itr;
Chris@16 533 ++itr;
Chris@16 534 } while(secondPt == firstPt);
Chris@16 535 point_data<Unit> prevPt = secondPt;
Chris@16 536 point_data<Unit> prevPrevPt = firstPt;
Chris@16 537 while(itr != end_vertex) {
Chris@16 538 point_data<Unit> pt = *itr;
Chris@16 539 //skip any duplicate points
Chris@16 540 if(pt == prevPt) {
Chris@16 541 ++itr;
Chris@16 542 continue;
Chris@16 543 }
Chris@16 544 //operate on the three points
Chris@16 545 insert_vertex_half_edge_45_pair(prevPrevPt, prevPt, pt, winding);
Chris@16 546 prevPrevPt = prevPt;
Chris@16 547 prevPt = pt;
Chris@16 548 ++itr;
Chris@16 549 }
Chris@16 550 if(prevPt != firstPt) {
Chris@16 551 insert_vertex_half_edge_45_pair(prevPrevPt, prevPt, firstPt, winding);
Chris@16 552 insert_vertex_half_edge_45_pair(prevPt, firstPt, secondPt, winding);
Chris@16 553 } else {
Chris@16 554 insert_vertex_half_edge_45_pair(prevPrevPt, firstPt, secondPt, winding);
Chris@16 555 }
Chris@16 556 dirty_ = true;
Chris@16 557 unsorted_ = true;
Chris@16 558 }
Chris@16 559
Chris@16 560 // insert polygon set
Chris@16 561 template <typename Unit>
Chris@16 562 inline void polygon_45_set_data<Unit>::insert(const polygon_45_set_data<Unit>& polygon_set, bool is_hole) {
Chris@16 563 std::size_t count = data_.size();
Chris@16 564 data_.insert(data_.end(), polygon_set.data_.begin(), polygon_set.data_.end());
Chris@16 565 error_data_.insert(error_data_.end(), polygon_set.error_data_.begin(),
Chris@16 566 polygon_set.error_data_.end());
Chris@16 567 if(is_hole) {
Chris@16 568 for(std::size_t i = count; i < data_.size(); ++i) {
Chris@16 569 data_[i].count = data_[i].count.invert();
Chris@16 570 }
Chris@16 571 }
Chris@16 572 dirty_ = true;
Chris@16 573 unsorted_ = true;
Chris@16 574 if(polygon_set.is_manhattan_ == false) is_manhattan_ = false;
Chris@16 575 return;
Chris@16 576 }
Chris@16 577 // insert polygon set
Chris@16 578 template <typename Unit>
Chris@16 579 template <typename coord_type>
Chris@16 580 inline void polygon_45_set_data<Unit>::insert(const polygon_45_set_data<coord_type>& polygon_set, bool is_hole) {
Chris@16 581 std::size_t count = data_.size();
Chris@16 582 for(typename polygon_45_set_data<coord_type>::iterator_type itr = polygon_set.begin();
Chris@16 583 itr != polygon_set.end(); ++itr) {
Chris@16 584 const typename polygon_45_set_data<coord_type>::Vertex45Compact& v = *itr;
Chris@16 585 typename polygon_45_set_data<Unit>::Vertex45Compact v2;
Chris@16 586 v2.pt.x(static_cast<Unit>(v.pt.x()));
Chris@16 587 v2.pt.y(static_cast<Unit>(v.pt.y()));
Chris@16 588 v2.count = typename polygon_45_formation<Unit>::Vertex45Count(v.count[0], v.count[1], v.count[2], v.count[3]);
Chris@16 589 data_.push_back(v2);
Chris@16 590 }
Chris@16 591 polygon_45_set_data<coord_type> tmp;
Chris@16 592 polygon_set.get_error_data(tmp);
Chris@16 593 for(typename polygon_45_set_data<coord_type>::iterator_type itr = tmp.begin();
Chris@16 594 itr != tmp.end(); ++itr) {
Chris@16 595 const typename polygon_45_set_data<coord_type>::Vertex45Compact& v = *itr;
Chris@16 596 typename polygon_45_set_data<Unit>::Vertex45Compact v2;
Chris@16 597 v2.pt.x(static_cast<Unit>(v.pt.x()));
Chris@16 598 v2.pt.y(static_cast<Unit>(v.pt.y()));
Chris@16 599 v2.count = typename polygon_45_formation<Unit>::Vertex45Count(v.count[0], v.count[1], v.count[2], v.count[3]);
Chris@16 600 error_data_.push_back(v2);
Chris@16 601 }
Chris@16 602 if(is_hole) {
Chris@16 603 for(std::size_t i = count; i < data_.size(); ++i) {
Chris@16 604 data_[i].count = data_[i].count.invert();
Chris@16 605 }
Chris@16 606 }
Chris@16 607 dirty_ = true;
Chris@16 608 unsorted_ = true;
Chris@16 609 if(polygon_set.is_manhattan() == false) is_manhattan_ = false;
Chris@16 610 return;
Chris@16 611 }
Chris@16 612
Chris@16 613 template <typename cT, typename rT>
Chris@16 614 void insert_rectangle_into_vector_45(cT& output, const rT& rect, bool is_hole) {
Chris@16 615 point_data<typename rectangle_traits<rT>::coordinate_type>
Chris@16 616 llpt = ll(rect), lrpt = lr(rect), ulpt = ul(rect), urpt = ur(rect);
Chris@16 617 direction_1d dir = COUNTERCLOCKWISE;
Chris@16 618 if(is_hole) dir = CLOCKWISE;
Chris@16 619 insert_vertex_half_edge_45_pair_into_vector(output, llpt, lrpt, urpt, dir);
Chris@16 620 insert_vertex_half_edge_45_pair_into_vector(output, lrpt, urpt, ulpt, dir);
Chris@16 621 insert_vertex_half_edge_45_pair_into_vector(output, urpt, ulpt, llpt, dir);
Chris@16 622 insert_vertex_half_edge_45_pair_into_vector(output, ulpt, llpt, lrpt, dir);
Chris@16 623 }
Chris@16 624
Chris@16 625 template <typename Unit>
Chris@16 626 template <typename geometry_type>
Chris@16 627 inline void polygon_45_set_data<Unit>::insert_dispatch(const geometry_type& geometry_object,
Chris@16 628 bool is_hole, rectangle_concept ) {
Chris@16 629 dirty_ = true;
Chris@16 630 unsorted_ = true;
Chris@16 631 insert_rectangle_into_vector_45(data_, geometry_object, is_hole);
Chris@16 632 }
Chris@16 633
Chris@16 634 // get the external boundary rectangle
Chris@16 635 template <typename Unit>
Chris@16 636 template <typename rectangle_type>
Chris@16 637 inline bool polygon_45_set_data<Unit>::extents(rectangle_type& rect) const{
Chris@16 638 clean();
Chris@16 639 if(empty()) {
Chris@16 640 return false;
Chris@16 641 }
Chris@16 642 Unit low = (std::numeric_limits<Unit>::max)();
Chris@16 643 Unit high = (std::numeric_limits<Unit>::min)();
Chris@16 644 interval_data<Unit> xivl(low, high);
Chris@16 645 interval_data<Unit> yivl(low, high);
Chris@16 646 for(typename value_type::const_iterator itr = data_.begin();
Chris@16 647 itr != data_.end(); ++ itr) {
Chris@16 648 if((*itr).pt.x() > xivl.get(HIGH))
Chris@16 649 xivl.set(HIGH, (*itr).pt.x());
Chris@16 650 if((*itr).pt.x() < xivl.get(LOW))
Chris@16 651 xivl.set(LOW, (*itr).pt.x());
Chris@16 652 if((*itr).pt.y() > yivl.get(HIGH))
Chris@16 653 yivl.set(HIGH, (*itr).pt.y());
Chris@16 654 if((*itr).pt.y() < yivl.get(LOW))
Chris@16 655 yivl.set(LOW, (*itr).pt.y());
Chris@16 656 }
Chris@16 657 rect = construct<rectangle_type>(xivl, yivl);
Chris@16 658 return true;
Chris@16 659 }
Chris@16 660
Chris@16 661 //this function snaps the vertex and two half edges
Chris@16 662 //to be both even or both odd coordinate values if one of the edges is 45
Chris@16 663 //and throws an excpetion if an edge is non-manhattan, non-45.
Chris@16 664 template <typename Unit>
Chris@16 665 inline void polygon_45_set_data<Unit>::snap_vertex_45(typename polygon_45_set_data<Unit>::Vertex45Compact& vertex) {
Chris@16 666 bool plus45 = vertex.count[2] != 0;
Chris@16 667 bool minus45 = vertex.count[0] != 0;
Chris@16 668 if(plus45 || minus45) {
Chris@16 669 if(abs(vertex.pt.x()) % 2 != abs(vertex.pt.y()) % 2) {
Chris@16 670 if(vertex.count[1] != 0 ||
Chris@16 671 (plus45 && minus45)) {
Chris@16 672 //move right
Chris@16 673 vertex.pt.x(vertex.pt.x() + 1);
Chris@16 674 } else {
Chris@16 675 //assert that vertex.count[3] != 0
Chris@16 676 Unit modifier = plus45 ? -1 : 1;
Chris@16 677 vertex.pt.y(vertex.pt.y() + modifier);
Chris@16 678 }
Chris@16 679 }
Chris@16 680 }
Chris@16 681 }
Chris@16 682
Chris@16 683 template <typename Unit>
Chris@16 684 inline void polygon_45_set_data<Unit>::snap() const {
Chris@16 685 for(typename value_type::iterator itr = data_.begin();
Chris@16 686 itr != data_.end(); ++itr) {
Chris@16 687 snap_vertex_45(*itr);
Chris@16 688 }
Chris@16 689 }
Chris@16 690
Chris@16 691 // |= &= += *= -= ^= binary operators
Chris@16 692 template <typename Unit>
Chris@16 693 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator|=(const polygon_45_set_data<Unit>& b) {
Chris@16 694 insert(b);
Chris@16 695 return *this;
Chris@16 696 }
Chris@16 697 template <typename Unit>
Chris@16 698 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator&=(const polygon_45_set_data<Unit>& b) {
Chris@16 699 //b.sort();
Chris@16 700 //sort();
Chris@16 701 applyAdaptiveBoolean_<1>(b);
Chris@16 702 dirty_ = false;
Chris@16 703 unsorted_ = false;
Chris@16 704 return *this;
Chris@16 705 }
Chris@16 706 template <typename Unit>
Chris@16 707 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator+=(const polygon_45_set_data<Unit>& b) {
Chris@16 708 return (*this) |= b;
Chris@16 709 }
Chris@16 710 template <typename Unit>
Chris@16 711 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator*=(const polygon_45_set_data<Unit>& b) {
Chris@16 712 return (*this) &= b;
Chris@16 713 }
Chris@16 714 template <typename Unit>
Chris@16 715 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator-=(const polygon_45_set_data<Unit>& b) {
Chris@16 716 //b.sort();
Chris@16 717 //sort();
Chris@16 718 applyAdaptiveBoolean_<2>(b);
Chris@16 719 dirty_ = false;
Chris@16 720 unsorted_ = false;
Chris@16 721 return *this;
Chris@16 722 }
Chris@16 723 template <typename Unit>
Chris@16 724 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator^=(const polygon_45_set_data<Unit>& b) {
Chris@16 725 //b.sort();
Chris@16 726 //sort();
Chris@16 727 applyAdaptiveBoolean_<3>(b);
Chris@16 728 dirty_ = false;
Chris@16 729 unsorted_ = false;
Chris@16 730 return *this;
Chris@16 731 }
Chris@16 732
Chris@16 733 template <typename Unit>
Chris@16 734 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator+=(Unit delta) {
Chris@16 735 return resize(delta);
Chris@16 736 }
Chris@16 737 template <typename Unit>
Chris@16 738 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator-=(Unit delta) {
Chris@16 739 return (*this) += -delta;
Chris@16 740 }
Chris@16 741
Chris@16 742 template <typename Unit>
Chris@16 743 inline polygon_45_set_data<Unit>&
Chris@16 744 polygon_45_set_data<Unit>::resize(Unit resizing, RoundingOption rounding, CornerOption corner) {
Chris@16 745 if(resizing == 0) return *this;
Chris@16 746 std::list<polygon_45_with_holes_data<Unit> > pl;
Chris@16 747 get_polygons_with_holes(pl);
Chris@16 748 clear();
Chris@16 749 for(typename std::list<polygon_45_with_holes_data<Unit> >::iterator itr = pl.begin(); itr != pl.end(); ++itr) {
Chris@16 750 insert_with_resize(*itr, resizing, rounding, corner);
Chris@16 751 }
Chris@16 752 clean();
Chris@16 753 //perterb 45 edges to prevent non-integer intersection errors upon boolean op
Chris@16 754 //snap();
Chris@16 755 return *this;
Chris@16 756 }
Chris@16 757
Chris@16 758 //distance is assumed to be positive
Chris@16 759 inline int roundClosest(double distance) {
Chris@16 760 int f = (int)distance;
Chris@16 761 if(distance - (double)f < 0.5) return f;
Chris@16 762 return f+1;
Chris@16 763 }
Chris@16 764
Chris@16 765 //distance is assumed to be positive
Chris@16 766 template <typename Unit>
Chris@16 767 inline Unit roundWithOptions(double distance, RoundingOption rounding) {
Chris@16 768 if(rounding == CLOSEST) {
Chris@16 769 return roundClosest(distance);
Chris@16 770 } else if(rounding == OVERSIZE) {
Chris@16 771 return (Unit)distance + 1;
Chris@16 772 } else { //UNDERSIZE
Chris@16 773 return (Unit)distance;
Chris@16 774 }
Chris@16 775 }
Chris@16 776
Chris@16 777 // 0 is east, 1 is northeast, 2 is north, 3 is northwest, 4 is west, 5 is southwest, 6 is south
Chris@16 778 // 7 is southwest
Chris@16 779 template <typename Unit>
Chris@16 780 inline point_data<Unit> bloatVertexInDirWithOptions(const point_data<Unit>& point, unsigned int dir,
Chris@16 781 Unit bloating, RoundingOption rounding) {
Chris@16 782 const double sqrt2 = 1.4142135623730950488016887242097;
Chris@16 783 if(dir & 1) {
Chris@16 784 Unit unitDistance = (Unit)bloating;
Chris@16 785 if(rounding != SQRT2) {
Chris@16 786 //45 degree bloating
Chris@16 787 double distance = (double)bloating;
Chris@16 788 distance /= sqrt2; // multiply by 1/sqrt2
Chris@16 789 unitDistance = roundWithOptions<Unit>(distance, rounding);
Chris@16 790 }
Chris@16 791 int xMultiplier = 1;
Chris@16 792 int yMultiplier = 1;
Chris@16 793 if(dir == 3 || dir == 5) xMultiplier = -1;
Chris@16 794 if(dir == 5 || dir == 7) yMultiplier = -1;
Chris@16 795 return point_data<Unit>(point.x()+xMultiplier*unitDistance,
Chris@16 796 point.y()+yMultiplier*unitDistance);
Chris@16 797 } else {
Chris@16 798 if(dir == 0)
Chris@16 799 return point_data<Unit>(point.x()+bloating, point.y());
Chris@16 800 if(dir == 2)
Chris@16 801 return point_data<Unit>(point.x(), point.y()+bloating);
Chris@16 802 if(dir == 4)
Chris@16 803 return point_data<Unit>(point.x()-bloating, point.y());
Chris@16 804 if(dir == 6)
Chris@16 805 return point_data<Unit>(point.x(), point.y()-bloating);
Chris@16 806 return point_data<Unit>();
Chris@16 807 }
Chris@16 808 }
Chris@16 809
Chris@16 810 template <typename Unit>
Chris@16 811 inline unsigned int getEdge45Direction(const point_data<Unit>& pt1, const point_data<Unit>& pt2) {
Chris@16 812 if(pt1.x() == pt2.x()) {
Chris@16 813 if(pt1.y() < pt2.y()) return 2;
Chris@16 814 return 6;
Chris@16 815 }
Chris@16 816 if(pt1.y() == pt2.y()) {
Chris@16 817 if(pt1.x() < pt2.x()) return 0;
Chris@16 818 return 4;
Chris@16 819 }
Chris@16 820 if(pt2.y() > pt1.y()) {
Chris@16 821 if(pt2.x() > pt1.x()) return 1;
Chris@16 822 return 3;
Chris@16 823 }
Chris@16 824 if(pt2.x() > pt1.x()) return 7;
Chris@16 825 return 5;
Chris@16 826 }
Chris@16 827
Chris@16 828 inline unsigned int getEdge45NormalDirection(unsigned int dir, int multiplier) {
Chris@16 829 if(multiplier < 0)
Chris@16 830 return (dir + 2) % 8;
Chris@16 831 return (dir + 4 + 2) % 8;
Chris@16 832 }
Chris@16 833
Chris@16 834 template <typename Unit>
Chris@16 835 inline point_data<Unit> getIntersectionPoint(const point_data<Unit>& pt1, unsigned int slope1,
Chris@16 836 const point_data<Unit>& pt2, unsigned int slope2) {
Chris@16 837 //the intention here is to use all integer arithmetic without causing overflow
Chris@16 838 //turncation error or divide by zero error
Chris@16 839 //I don't use floating point arithmetic because its precision may not be high enough
Chris@16 840 //at the extremes of the integer range
Chris@16 841 typedef typename coordinate_traits<Unit>::area_type LongUnit;
Chris@16 842 const Unit rises[8] = {0, 1, 1, 1, 0, -1, -1, -1};
Chris@16 843 const Unit runs[8] = {1, 1, 0, -1, -1, -1, 0, 1};
Chris@16 844 LongUnit rise1 = rises[slope1];
Chris@16 845 LongUnit rise2 = rises[slope2];
Chris@16 846 LongUnit run1 = runs[slope1];
Chris@16 847 LongUnit run2 = runs[slope2];
Chris@16 848 LongUnit x1 = (LongUnit)pt1.x();
Chris@16 849 LongUnit x2 = (LongUnit)pt2.x();
Chris@16 850 LongUnit y1 = (LongUnit)pt1.y();
Chris@16 851 LongUnit y2 = (LongUnit)pt2.y();
Chris@16 852 Unit x = 0;
Chris@16 853 Unit y = 0;
Chris@16 854 if(run1 == 0) {
Chris@16 855 x = pt1.x();
Chris@16 856 y = (Unit)(((x1 - x2) * rise2) / run2) + pt2.y();
Chris@16 857 } else if(run2 == 0) {
Chris@16 858 x = pt2.x();
Chris@16 859 y = (Unit)(((x2 - x1) * rise1) / run1) + pt1.y();
Chris@16 860 } else {
Chris@16 861 // y - y1 = (rise1/run1)(x - x1)
Chris@16 862 // y - y2 = (rise2/run2)(x - x2)
Chris@16 863 // y = (rise1/run1)(x - x1) + y1 = (rise2/run2)(x - x2) + y2
Chris@16 864 // (rise1/run1 - rise2/run2)x = y2 - y1 + rise1/run1 x1 - rise2/run2 x2
Chris@16 865 // x = (y2 - y1 + rise1/run1 x1 - rise2/run2 x2)/(rise1/run1 - rise2/run2)
Chris@16 866 // x = (y2 - y1 + rise1/run1 x1 - rise2/run2 x2)(rise1 run2 - rise2 run1)/(run1 run2)
Chris@16 867 x = (Unit)((y2 - y1 + ((rise1 * x1) / run1) - ((rise2 * x2) / run2)) *
Chris@16 868 (run1 * run2) / (rise1 * run2 - rise2 * run1));
Chris@16 869 if(rise1 == 0) {
Chris@16 870 y = pt1.y();
Chris@16 871 } else if(rise2 == 0) {
Chris@16 872 y = pt2.y();
Chris@16 873 } else {
Chris@16 874 // y - y1 = (rise1/run1)(x - x1)
Chris@16 875 // (run1/rise1)(y - y1) = x - x1
Chris@16 876 // x = (run1/rise1)(y - y1) + x1 = (run2/rise2)(y - y2) + x2
Chris@16 877 y = (Unit)((x2 - x1 + ((run1 * y1) / rise1) - ((run2 * y2) / rise2)) *
Chris@16 878 (rise1 * rise2) / (run1 * rise2 - run2 * rise1));
Chris@16 879 }
Chris@16 880 }
Chris@16 881 return point_data<Unit>(x, y);
Chris@16 882 }
Chris@16 883
Chris@16 884 template <typename Unit>
Chris@16 885 inline
Chris@16 886 void handleResizingEdge45_SQRT1OVER2(polygon_45_set_data<Unit>& sizingSet, point_data<Unit> first,
Chris@16 887 point_data<Unit> second, Unit resizing, CornerOption corner) {
Chris@16 888 if(first.x() == second.x()) {
Chris@16 889 sizingSet.insert(rectangle_data<Unit>(first.x() - resizing, first.y(), first.x() + resizing, second.y()));
Chris@16 890 return;
Chris@16 891 }
Chris@16 892 if(first.y() == second.y()) {
Chris@16 893 sizingSet.insert(rectangle_data<Unit>(first.x(), first.y() - resizing, second.x(), first.y() + resizing));
Chris@16 894 return;
Chris@16 895 }
Chris@16 896 std::vector<point_data<Unit> > pts;
Chris@16 897 Unit bloating = resizing < 0 ? -resizing : resizing;
Chris@16 898 if(corner == UNFILLED) {
Chris@16 899 //we have to round up
Chris@16 900 bloating = bloating / 2 + bloating % 2 ; //round up
Chris@16 901 if(second.x() < first.x()) std::swap(first, second);
Chris@16 902 if(first.y() < second.y()) { //upward sloping
Chris@16 903 pts.push_back(point_data<Unit>(first.x() + bloating, first.y() - bloating));
Chris@16 904 pts.push_back(point_data<Unit>(first.x() - bloating, first.y() + bloating));
Chris@16 905 pts.push_back(point_data<Unit>(second.x() - bloating, second.y() + bloating));
Chris@16 906 pts.push_back(point_data<Unit>(second.x() + bloating, second.y() - bloating));
Chris@16 907 sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), CLOCKWISE, false);
Chris@16 908 } else { //downward sloping
Chris@16 909 pts.push_back(point_data<Unit>(first.x() + bloating, first.y() + bloating));
Chris@16 910 pts.push_back(point_data<Unit>(first.x() - bloating, first.y() - bloating));
Chris@16 911 pts.push_back(point_data<Unit>(second.x() - bloating, second.y() - bloating));
Chris@16 912 pts.push_back(point_data<Unit>(second.x() + bloating, second.y() + bloating));
Chris@16 913 sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), COUNTERCLOCKWISE, false);
Chris@16 914 }
Chris@16 915 return;
Chris@16 916 }
Chris@16 917 if(second.x() < first.x()) std::swap(first, second);
Chris@16 918 if(first.y() < second.y()) { //upward sloping
Chris@16 919 pts.push_back(point_data<Unit>(first.x(), first.y() - bloating));
Chris@16 920 pts.push_back(point_data<Unit>(first.x() - bloating, first.y()));
Chris@16 921 pts.push_back(point_data<Unit>(second.x(), second.y() + bloating));
Chris@16 922 pts.push_back(point_data<Unit>(second.x() + bloating, second.y()));
Chris@16 923 sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), CLOCKWISE, false);
Chris@16 924 } else { //downward sloping
Chris@16 925 pts.push_back(point_data<Unit>(first.x() - bloating, first.y()));
Chris@16 926 pts.push_back(point_data<Unit>(first.x(), first.y() + bloating));
Chris@16 927 pts.push_back(point_data<Unit>(second.x() + bloating, second.y()));
Chris@16 928 pts.push_back(point_data<Unit>(second.x(), second.y() - bloating));
Chris@16 929 sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), CLOCKWISE, false);
Chris@16 930 }
Chris@16 931 }
Chris@16 932
Chris@16 933
Chris@16 934 template <typename Unit>
Chris@16 935 inline
Chris@16 936 void handleResizingEdge45(polygon_45_set_data<Unit>& sizingSet, point_data<Unit> first,
Chris@16 937 point_data<Unit> second, Unit resizing, RoundingOption rounding) {
Chris@16 938 if(first.x() == second.x()) {
Chris@16 939 sizingSet.insert(rectangle_data<int>(first.x() - resizing, first.y(), first.x() + resizing, second.y()));
Chris@16 940 return;
Chris@16 941 }
Chris@16 942 if(first.y() == second.y()) {
Chris@16 943 sizingSet.insert(rectangle_data<int>(first.x(), first.y() - resizing, second.x(), first.y() + resizing));
Chris@16 944 return;
Chris@16 945 }
Chris@16 946 //edge is 45
Chris@16 947 std::vector<point_data<Unit> > pts;
Chris@16 948 Unit bloating = resizing < 0 ? -resizing : resizing;
Chris@16 949 if(second.x() < first.x()) std::swap(first, second);
Chris@16 950 if(first.y() < second.y()) {
Chris@16 951 pts.push_back(bloatVertexInDirWithOptions(first, 3, bloating, rounding));
Chris@16 952 pts.push_back(bloatVertexInDirWithOptions(first, 7, bloating, rounding));
Chris@16 953 pts.push_back(bloatVertexInDirWithOptions(second, 7, bloating, rounding));
Chris@16 954 pts.push_back(bloatVertexInDirWithOptions(second, 3, bloating, rounding));
Chris@16 955 sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), HIGH, false);
Chris@16 956 } else {
Chris@16 957 pts.push_back(bloatVertexInDirWithOptions(first, 1, bloating, rounding));
Chris@16 958 pts.push_back(bloatVertexInDirWithOptions(first, 5, bloating, rounding));
Chris@16 959 pts.push_back(bloatVertexInDirWithOptions(second, 5, bloating, rounding));
Chris@16 960 pts.push_back(bloatVertexInDirWithOptions(second, 1, bloating, rounding));
Chris@16 961 sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), HIGH, false);
Chris@16 962 }
Chris@16 963 }
Chris@16 964
Chris@16 965 template <typename Unit>
Chris@16 966 inline point_data<Unit> bloatVertexInDirWithSQRT1OVER2(int edge1, int normal1, const point_data<Unit>& second, Unit bloating,
Chris@16 967 bool first) {
Chris@16 968 orientation_2d orient = first ? HORIZONTAL : VERTICAL;
Chris@16 969 orientation_2d orientp = orient.get_perpendicular();
Chris@16 970 int multiplier = first ? 1 : -1;
Chris@16 971 point_data<Unit> pt1(second);
Chris@16 972 if(edge1 == 1) {
Chris@16 973 if(normal1 == 3) {
Chris@16 974 move(pt1, orient, -multiplier * bloating);
Chris@16 975 } else {
Chris@16 976 move(pt1, orientp, -multiplier * bloating);
Chris@16 977 }
Chris@16 978 } else if(edge1 == 3) {
Chris@16 979 if(normal1 == 1) {
Chris@16 980 move(pt1, orient, multiplier * bloating);
Chris@16 981 } else {
Chris@16 982 move(pt1, orientp, -multiplier * bloating);
Chris@16 983 }
Chris@16 984 } else if(edge1 == 5) {
Chris@16 985 if(normal1 == 3) {
Chris@16 986 move(pt1, orientp, multiplier * bloating);
Chris@16 987 } else {
Chris@16 988 move(pt1, orient, multiplier * bloating);
Chris@16 989 }
Chris@16 990 } else {
Chris@16 991 if(normal1 == 5) {
Chris@16 992 move(pt1, orient, -multiplier * bloating);
Chris@16 993 } else {
Chris@16 994 move(pt1, orientp, multiplier * bloating);
Chris@16 995 }
Chris@16 996 }
Chris@16 997 return pt1;
Chris@16 998 }
Chris@16 999
Chris@16 1000 template <typename Unit>
Chris@16 1001 inline
Chris@16 1002 void handleResizingVertex45(polygon_45_set_data<Unit>& sizingSet, const point_data<Unit>& first,
Chris@16 1003 const point_data<Unit>& second, const point_data<Unit>& third, Unit resizing,
Chris@16 1004 RoundingOption rounding, CornerOption corner,
Chris@16 1005 int multiplier) {
Chris@16 1006 unsigned int edge1 = getEdge45Direction(first, second);
Chris@16 1007 unsigned int edge2 = getEdge45Direction(second, third);
Chris@16 1008 unsigned int diffAngle;
Chris@16 1009 if(multiplier < 0)
Chris@16 1010 diffAngle = (edge2 + 8 - edge1) % 8;
Chris@16 1011 else
Chris@16 1012 diffAngle = (edge1 + 8 - edge2) % 8;
Chris@16 1013 if(diffAngle < 4) {
Chris@16 1014 if(resizing > 0) return; //accute interior corner
Chris@16 1015 else multiplier *= -1; //make it appear to be an accute exterior angle
Chris@16 1016 }
Chris@16 1017 Unit bloating = abs(resizing);
Chris@16 1018 if(rounding == SQRT1OVER2) {
Chris@16 1019 if(edge1 % 2 && edge2 % 2) return;
Chris@16 1020 if(corner == ORTHOGONAL && edge1 % 2 == 0 && edge2 % 2 == 0) {
Chris@16 1021 rectangle_data<Unit> insertion_rect;
Chris@16 1022 set_points(insertion_rect, second, second);
Chris@16 1023 bloat(insertion_rect, bloating);
Chris@16 1024 sizingSet.insert(insertion_rect);
Chris@16 1025 } else if(corner != ORTHOGONAL) {
Chris@16 1026 point_data<Unit> pt1(0, 0);
Chris@16 1027 point_data<Unit> pt2(0, 0);
Chris@16 1028 unsigned int normal1 = getEdge45NormalDirection(edge1, multiplier);
Chris@16 1029 unsigned int normal2 = getEdge45NormalDirection(edge2, multiplier);
Chris@16 1030 if(edge1 % 2) {
Chris@16 1031 pt1 = bloatVertexInDirWithSQRT1OVER2(edge1, normal1, second, bloating, true);
Chris@16 1032 } else {
Chris@16 1033 pt1 = bloatVertexInDirWithOptions(second, normal1, bloating, UNDERSIZE);
Chris@16 1034 }
Chris@16 1035 if(edge2 % 2) {
Chris@16 1036 pt2 = bloatVertexInDirWithSQRT1OVER2(edge2, normal2, second, bloating, false);
Chris@16 1037 } else {
Chris@16 1038 pt2 = bloatVertexInDirWithOptions(second, normal2, bloating, UNDERSIZE);
Chris@16 1039 }
Chris@16 1040 std::vector<point_data<Unit> > pts;
Chris@16 1041 pts.push_back(pt1);
Chris@16 1042 pts.push_back(second);
Chris@16 1043 pts.push_back(pt2);
Chris@16 1044 pts.push_back(getIntersectionPoint(pt1, edge1, pt2, edge2));
Chris@16 1045 polygon_45_data<Unit> poly(pts.begin(), pts.end());
Chris@16 1046 sizingSet.insert(poly);
Chris@16 1047 } else {
Chris@16 1048 //ORTHOGONAL of a 45 degree corner
Chris@16 1049 int normal = 0;
Chris@16 1050 if(edge1 % 2) {
Chris@16 1051 normal = getEdge45NormalDirection(edge2, multiplier);
Chris@16 1052 } else {
Chris@16 1053 normal = getEdge45NormalDirection(edge1, multiplier);
Chris@16 1054 }
Chris@16 1055 rectangle_data<Unit> insertion_rect;
Chris@16 1056 point_data<Unit> edgePoint = bloatVertexInDirWithOptions(second, normal, bloating, UNDERSIZE);
Chris@16 1057 set_points(insertion_rect, second, edgePoint);
Chris@16 1058 if(normal == 0 || normal == 4)
Chris@16 1059 bloat(insertion_rect, VERTICAL, bloating);
Chris@16 1060 else
Chris@16 1061 bloat(insertion_rect, HORIZONTAL, bloating);
Chris@16 1062 sizingSet.insert(insertion_rect);
Chris@16 1063 }
Chris@16 1064 return;
Chris@16 1065 }
Chris@16 1066 unsigned int normal1 = getEdge45NormalDirection(edge1, multiplier);
Chris@16 1067 unsigned int normal2 = getEdge45NormalDirection(edge2, multiplier);
Chris@16 1068 point_data<Unit> edgePoint1 = bloatVertexInDirWithOptions(second, normal1, bloating, rounding);
Chris@16 1069 point_data<Unit> edgePoint2 = bloatVertexInDirWithOptions(second, normal2, bloating, rounding);
Chris@16 1070 //if the change in angle is 135 degrees it is an accute exterior corner
Chris@16 1071 if((edge1+ multiplier * 3) % 8 == edge2) {
Chris@16 1072 if(corner == ORTHOGONAL) {
Chris@16 1073 rectangle_data<Unit> insertion_rect;
Chris@16 1074 set_points(insertion_rect, edgePoint1, edgePoint2);
Chris@16 1075 sizingSet.insert(insertion_rect);
Chris@16 1076 return;
Chris@16 1077 }
Chris@16 1078 }
Chris@16 1079 std::vector<point_data<Unit> > pts;
Chris@16 1080 pts.push_back(edgePoint1);
Chris@16 1081 pts.push_back(second);
Chris@16 1082 pts.push_back(edgePoint2);
Chris@16 1083 pts.push_back(getIntersectionPoint(edgePoint1, edge1, edgePoint2, edge2));
Chris@16 1084 polygon_45_data<Unit> poly(pts.begin(), pts.end());
Chris@16 1085 sizingSet.insert(poly);
Chris@16 1086 }
Chris@16 1087
Chris@16 1088 template <typename Unit>
Chris@16 1089 template <typename geometry_type>
Chris@16 1090 inline polygon_45_set_data<Unit>&
Chris@16 1091 polygon_45_set_data<Unit>::insert_with_resize_dispatch(const geometry_type& poly,
Chris@16 1092 coordinate_type resizing,
Chris@16 1093 RoundingOption rounding,
Chris@16 1094 CornerOption corner,
Chris@16 1095 bool hole, polygon_45_concept ) {
Chris@16 1096 direction_1d wdir = winding(poly);
Chris@16 1097 int multiplier = wdir == LOW ? -1 : 1;
Chris@16 1098 if(hole) resizing *= -1;
Chris@16 1099 typedef typename polygon_45_data<Unit>::iterator_type piterator;
Chris@16 1100 piterator first, second, third, end, real_end;
Chris@16 1101 real_end = end_points(poly);
Chris@16 1102 third = begin_points(poly);
Chris@16 1103 first = third;
Chris@16 1104 if(first == real_end) return *this;
Chris@16 1105 ++third;
Chris@16 1106 if(third == real_end) return *this;
Chris@16 1107 second = end = third;
Chris@16 1108 ++third;
Chris@16 1109 if(third == real_end) return *this;
Chris@16 1110 polygon_45_set_data<Unit> sizingSet;
Chris@16 1111 //insert minkofski shapes on edges and corners
Chris@16 1112 do {
Chris@16 1113 if(rounding != SQRT1OVER2) {
Chris@16 1114 handleResizingEdge45(sizingSet, *first, *second, resizing, rounding);
Chris@16 1115 } else {
Chris@16 1116 handleResizingEdge45_SQRT1OVER2(sizingSet, *first, *second, resizing, corner);
Chris@16 1117 }
Chris@16 1118 if(corner != UNFILLED)
Chris@16 1119 handleResizingVertex45(sizingSet, *first, *second, *third, resizing, rounding, corner, multiplier);
Chris@16 1120 first = second;
Chris@16 1121 second = third;
Chris@16 1122 ++third;
Chris@16 1123 if(third == real_end) {
Chris@16 1124 third = begin_points(poly);
Chris@16 1125 if(*second == *third) {
Chris@16 1126 ++third; //skip first point if it is duplicate of last point
Chris@16 1127 }
Chris@16 1128 }
Chris@16 1129 } while(second != end);
Chris@16 1130 //sizingSet.snap();
Chris@16 1131 polygon_45_set_data<Unit> tmp;
Chris@16 1132 //insert original shape
Chris@16 1133 tmp.insert_dispatch(poly, false, polygon_45_concept());
Chris@16 1134 if(resizing < 0) tmp -= sizingSet;
Chris@16 1135 else tmp += sizingSet;
Chris@16 1136 tmp.clean();
Chris@16 1137 insert(tmp, hole);
Chris@16 1138 dirty_ = true;
Chris@16 1139 unsorted_ = true;
Chris@16 1140 return (*this);
Chris@16 1141 }
Chris@16 1142
Chris@16 1143 // accumulate the bloated polygon with holes
Chris@16 1144 template <typename Unit>
Chris@16 1145 template <typename geometry_type>
Chris@16 1146 inline polygon_45_set_data<Unit>&
Chris@16 1147 polygon_45_set_data<Unit>::insert_with_resize_dispatch(const geometry_type& poly,
Chris@16 1148 coordinate_type resizing,
Chris@16 1149 RoundingOption rounding,
Chris@16 1150 CornerOption corner,
Chris@16 1151 bool hole, polygon_45_with_holes_concept ) {
Chris@16 1152 insert_with_resize_dispatch(poly, resizing, rounding, corner, hole, polygon_45_concept());
Chris@16 1153 for(typename polygon_with_holes_traits<geometry_type>::iterator_holes_type itr =
Chris@16 1154 begin_holes(poly); itr != end_holes(poly);
Chris@16 1155 ++itr) {
Chris@16 1156 insert_with_resize_dispatch(*itr, resizing, rounding, corner, !hole, polygon_45_concept());
Chris@16 1157 }
Chris@16 1158 return *this;
Chris@16 1159 }
Chris@16 1160
Chris@16 1161 // transform set
Chris@16 1162 template <typename Unit>
Chris@16 1163 template <typename transformation_type>
Chris@16 1164 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::transform(const transformation_type& tr){
Chris@16 1165 clean();
Chris@16 1166 std::vector<polygon_45_with_holes_data<Unit> > polys;
Chris@16 1167 get(polys);
Chris@16 1168 for(typename std::vector<polygon_45_with_holes_data<Unit> >::iterator itr = polys.begin();
Chris@16 1169 itr != polys.end(); ++itr) {
Chris@16 1170 ::boost::polygon::transform(*itr, tr);
Chris@16 1171 }
Chris@16 1172 clear();
Chris@16 1173 insert(polys.begin(), polys.end());
Chris@16 1174 dirty_ = true;
Chris@16 1175 unsorted_ = true;
Chris@16 1176 return *this;
Chris@16 1177 }
Chris@16 1178
Chris@16 1179 template <typename Unit>
Chris@16 1180 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::scale_up(typename coordinate_traits<Unit>::unsigned_area_type factor) {
Chris@16 1181 scale_up_vertex_45_compact_range(data_.begin(), data_.end(), factor);
Chris@16 1182 return *this;
Chris@16 1183 }
Chris@16 1184
Chris@16 1185 template <typename Unit>
Chris@16 1186 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::scale_down(typename coordinate_traits<Unit>::unsigned_area_type factor) {
Chris@16 1187 clean();
Chris@16 1188 std::vector<polygon_45_with_holes_data<Unit> > polys;
Chris@16 1189 get_polygons_with_holes(polys);
Chris@16 1190 for(typename std::vector<polygon_45_with_holes_data<Unit> >::iterator itr = polys.begin();
Chris@16 1191 itr != polys.end(); ++itr) {
Chris@16 1192 ::boost::polygon::scale_down(*itr, factor);
Chris@16 1193 }
Chris@16 1194 clear();
Chris@16 1195 insert(polys.begin(), polys.end());
Chris@16 1196 dirty_ = true;
Chris@16 1197 unsorted_ = true;
Chris@16 1198 return *this;
Chris@16 1199 }
Chris@16 1200
Chris@16 1201 template <typename Unit>
Chris@16 1202 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::scale(double factor) {
Chris@16 1203 clean();
Chris@16 1204 std::vector<polygon_45_with_holes_data<Unit> > polys;
Chris@16 1205 get_polygons_with_holes(polys);
Chris@16 1206 for(typename std::vector<polygon_45_with_holes_data<Unit> >::iterator itr = polys.begin();
Chris@16 1207 itr != polys.end(); ++itr) {
Chris@16 1208 ::boost::polygon::scale(*itr, factor);
Chris@16 1209 }
Chris@16 1210 clear();
Chris@16 1211 insert(polys.begin(), polys.end());
Chris@16 1212 dirty_ = true;
Chris@16 1213 unsorted_ = true;
Chris@16 1214 return *this;
Chris@16 1215 }
Chris@16 1216
Chris@16 1217 template <typename Unit>
Chris@16 1218 inline bool polygon_45_set_data<Unit>::clean() const {
Chris@16 1219 if(unsorted_) sort();
Chris@16 1220 if(dirty_) {
Chris@16 1221 applyAdaptiveUnary_<0>();
Chris@16 1222 dirty_ = false;
Chris@16 1223 }
Chris@16 1224 return true;
Chris@16 1225 }
Chris@16 1226
Chris@16 1227 template <typename Unit>
Chris@16 1228 template <int op>
Chris@16 1229 inline void polygon_45_set_data<Unit>::applyAdaptiveBoolean_(const polygon_45_set_data<Unit>& rvalue) const {
Chris@16 1230 polygon_45_set_data<Unit> tmp;
Chris@16 1231 applyAdaptiveBoolean_<op>(tmp, rvalue);
Chris@16 1232 data_.swap(tmp.data_); //swapping vectors should be constant time operation
Chris@16 1233 error_data_.swap(tmp.error_data_);
Chris@16 1234 is_manhattan_ = tmp.is_manhattan_;
Chris@16 1235 unsorted_ = false;
Chris@16 1236 dirty_ = false;
Chris@16 1237 }
Chris@16 1238
Chris@16 1239 template <typename Unit2, int op>
Chris@16 1240 bool applyBoolean45OpOnVectors(std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& result_data,
Chris@16 1241 std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& lvalue_data,
Chris@16 1242 std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& rvalue_data
Chris@16 1243 ) {
Chris@16 1244 bool result_is_manhattan_ = true;
Chris@16 1245 typename boolean_op_45<Unit2>::template Scan45<typename boolean_op_45<Unit2>::Count2,
Chris@16 1246 typename boolean_op_45<Unit2>::template boolean_op_45_output_functor<op> > scan45;
Chris@16 1247 std::vector<typename boolean_op_45<Unit2>::Vertex45> eventOut;
Chris@16 1248 typedef std::pair<typename boolean_op_45<Unit2>::Point,
Chris@16 1249 typename boolean_op_45<Unit2>::template Scan45CountT<typename boolean_op_45<Unit2>::Count2> > Scan45Vertex;
Chris@16 1250 std::vector<Scan45Vertex> eventIn;
Chris@16 1251 typedef std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact> value_type;
Chris@16 1252 typename value_type::const_iterator iter1 = lvalue_data.begin();
Chris@16 1253 typename value_type::const_iterator iter2 = rvalue_data.begin();
Chris@16 1254 typename value_type::const_iterator end1 = lvalue_data.end();
Chris@16 1255 typename value_type::const_iterator end2 = rvalue_data.end();
Chris@16 1256 const Unit2 UnitMax = (std::numeric_limits<Unit2>::max)();
Chris@16 1257 Unit2 x = UnitMax;
Chris@16 1258 while(iter1 != end1 || iter2 != end2) {
Chris@16 1259 Unit2 currentX = UnitMax;
Chris@16 1260 if(iter1 != end1) currentX = iter1->pt.x();
Chris@16 1261 if(iter2 != end2) currentX = (std::min)(currentX, iter2->pt.x());
Chris@16 1262 if(currentX != x) {
Chris@16 1263 //std::cout << "SCAN " << currentX << "\n";
Chris@16 1264 //scan event
Chris@16 1265 scan45.scan(eventOut, eventIn.begin(), eventIn.end());
Chris@16 1266 polygon_sort(eventOut.begin(), eventOut.end());
Chris@16 1267 std::size_t ptCount = 0;
Chris@16 1268 for(std::size_t i = 0; i < eventOut.size(); ++i) {
Chris@16 1269 if(!result_data.empty() &&
Chris@16 1270 result_data.back().pt == eventOut[i].pt) {
Chris@16 1271 result_data.back().count += eventOut[i];
Chris@16 1272 ++ptCount;
Chris@16 1273 } else {
Chris@16 1274 if(!result_data.empty()) {
Chris@16 1275 if(result_data.back().count.is_45()) {
Chris@16 1276 result_is_manhattan_ = false;
Chris@16 1277 }
Chris@16 1278 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
Chris@16 1279 result_data.pop_back();
Chris@16 1280 }
Chris@16 1281 }
Chris@16 1282 result_data.push_back(eventOut[i]);
Chris@16 1283 ptCount = 1;
Chris@16 1284 }
Chris@16 1285 }
Chris@16 1286 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
Chris@16 1287 result_data.pop_back();
Chris@16 1288 }
Chris@16 1289 eventOut.clear();
Chris@16 1290 eventIn.clear();
Chris@16 1291 x = currentX;
Chris@16 1292 }
Chris@16 1293 //std::cout << "get next\n";
Chris@16 1294 if(iter2 != end2 && (iter1 == end1 || iter2->pt.x() < iter1->pt.x() ||
Chris@16 1295 (iter2->pt.x() == iter1->pt.x() &&
Chris@16 1296 iter2->pt.y() < iter1->pt.y()) )) {
Chris@16 1297 //std::cout << "case1 next\n";
Chris@16 1298 eventIn.push_back(Scan45Vertex
Chris@16 1299 (iter2->pt,
Chris@16 1300 typename polygon_45_formation<Unit2>::
Chris@16 1301 Scan45Count(typename polygon_45_formation<Unit2>::Count2(0, iter2->count[0]),
Chris@16 1302 typename polygon_45_formation<Unit2>::Count2(0, iter2->count[1]),
Chris@16 1303 typename polygon_45_formation<Unit2>::Count2(0, iter2->count[2]),
Chris@16 1304 typename polygon_45_formation<Unit2>::Count2(0, iter2->count[3]))));
Chris@16 1305 ++iter2;
Chris@16 1306 } else if(iter1 != end1 && (iter2 == end2 || iter1->pt.x() < iter2->pt.x() ||
Chris@16 1307 (iter1->pt.x() == iter2->pt.x() &&
Chris@16 1308 iter1->pt.y() < iter2->pt.y()) )) {
Chris@16 1309 //std::cout << "case2 next\n";
Chris@16 1310 eventIn.push_back(Scan45Vertex
Chris@16 1311 (iter1->pt,
Chris@16 1312 typename polygon_45_formation<Unit2>::
Chris@16 1313 Scan45Count(
Chris@16 1314 typename polygon_45_formation<Unit2>::Count2(iter1->count[0], 0),
Chris@16 1315 typename polygon_45_formation<Unit2>::Count2(iter1->count[1], 0),
Chris@16 1316 typename polygon_45_formation<Unit2>::Count2(iter1->count[2], 0),
Chris@16 1317 typename polygon_45_formation<Unit2>::Count2(iter1->count[3], 0))));
Chris@16 1318 ++iter1;
Chris@16 1319 } else {
Chris@16 1320 //std::cout << "case3 next\n";
Chris@16 1321 eventIn.push_back(Scan45Vertex
Chris@16 1322 (iter2->pt,
Chris@16 1323 typename polygon_45_formation<Unit2>::
Chris@16 1324 Scan45Count(typename polygon_45_formation<Unit2>::Count2(iter1->count[0],
Chris@16 1325 iter2->count[0]),
Chris@16 1326 typename polygon_45_formation<Unit2>::Count2(iter1->count[1],
Chris@16 1327 iter2->count[1]),
Chris@16 1328 typename polygon_45_formation<Unit2>::Count2(iter1->count[2],
Chris@16 1329 iter2->count[2]),
Chris@16 1330 typename polygon_45_formation<Unit2>::Count2(iter1->count[3],
Chris@16 1331 iter2->count[3]))));
Chris@16 1332 ++iter1;
Chris@16 1333 ++iter2;
Chris@16 1334 }
Chris@16 1335 }
Chris@16 1336 scan45.scan(eventOut, eventIn.begin(), eventIn.end());
Chris@16 1337 polygon_sort(eventOut.begin(), eventOut.end());
Chris@16 1338
Chris@16 1339 std::size_t ptCount = 0;
Chris@16 1340 for(std::size_t i = 0; i < eventOut.size(); ++i) {
Chris@16 1341 if(!result_data.empty() &&
Chris@16 1342 result_data.back().pt == eventOut[i].pt) {
Chris@16 1343 result_data.back().count += eventOut[i];
Chris@16 1344 ++ptCount;
Chris@16 1345 } else {
Chris@16 1346 if(!result_data.empty()) {
Chris@16 1347 if(result_data.back().count.is_45()) {
Chris@16 1348 result_is_manhattan_ = false;
Chris@16 1349 }
Chris@16 1350 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
Chris@16 1351 result_data.pop_back();
Chris@16 1352 }
Chris@16 1353 }
Chris@16 1354 result_data.push_back(eventOut[i]);
Chris@16 1355 ptCount = 1;
Chris@16 1356 }
Chris@16 1357 }
Chris@16 1358 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
Chris@16 1359 result_data.pop_back();
Chris@16 1360 }
Chris@16 1361 if(!result_data.empty() &&
Chris@16 1362 result_data.back().count.is_45()) {
Chris@16 1363 result_is_manhattan_ = false;
Chris@16 1364 }
Chris@16 1365 return result_is_manhattan_;
Chris@16 1366 }
Chris@16 1367
Chris@16 1368 template <typename Unit2, int op>
Chris@16 1369 bool applyUnary45OpOnVectors(std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& result_data,
Chris@16 1370 std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& lvalue_data ) {
Chris@16 1371 bool result_is_manhattan_ = true;
Chris@16 1372 typename boolean_op_45<Unit2>::template Scan45<typename boolean_op_45<Unit2>::Count1,
Chris@16 1373 typename boolean_op_45<Unit2>::template unary_op_45_output_functor<op> > scan45;
Chris@16 1374 std::vector<typename boolean_op_45<Unit2>::Vertex45> eventOut;
Chris@16 1375 typedef typename boolean_op_45<Unit2>::template Scan45CountT<typename boolean_op_45<Unit2>::Count1> Scan45Count;
Chris@16 1376 typedef std::pair<typename boolean_op_45<Unit2>::Point, Scan45Count> Scan45Vertex;
Chris@16 1377 std::vector<Scan45Vertex> eventIn;
Chris@16 1378 typedef std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact> value_type;
Chris@16 1379 typename value_type::const_iterator iter1 = lvalue_data.begin();
Chris@16 1380 typename value_type::const_iterator end1 = lvalue_data.end();
Chris@16 1381 const Unit2 UnitMax = (std::numeric_limits<Unit2>::max)();
Chris@16 1382 Unit2 x = UnitMax;
Chris@16 1383 while(iter1 != end1) {
Chris@16 1384 Unit2 currentX = iter1->pt.x();
Chris@16 1385 if(currentX != x) {
Chris@16 1386 //std::cout << "SCAN " << currentX << "\n";
Chris@16 1387 //scan event
Chris@16 1388 scan45.scan(eventOut, eventIn.begin(), eventIn.end());
Chris@16 1389 polygon_sort(eventOut.begin(), eventOut.end());
Chris@16 1390 std::size_t ptCount = 0;
Chris@16 1391 for(std::size_t i = 0; i < eventOut.size(); ++i) {
Chris@16 1392 if(!result_data.empty() &&
Chris@16 1393 result_data.back().pt == eventOut[i].pt) {
Chris@16 1394 result_data.back().count += eventOut[i];
Chris@16 1395 ++ptCount;
Chris@16 1396 } else {
Chris@16 1397 if(!result_data.empty()) {
Chris@16 1398 if(result_data.back().count.is_45()) {
Chris@16 1399 result_is_manhattan_ = false;
Chris@16 1400 }
Chris@16 1401 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
Chris@16 1402 result_data.pop_back();
Chris@16 1403 }
Chris@16 1404 }
Chris@16 1405 result_data.push_back(eventOut[i]);
Chris@16 1406 ptCount = 1;
Chris@16 1407 }
Chris@16 1408 }
Chris@16 1409 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
Chris@16 1410 result_data.pop_back();
Chris@16 1411 }
Chris@16 1412 eventOut.clear();
Chris@16 1413 eventIn.clear();
Chris@16 1414 x = currentX;
Chris@16 1415 }
Chris@16 1416 //std::cout << "get next\n";
Chris@16 1417 eventIn.push_back(Scan45Vertex
Chris@16 1418 (iter1->pt,
Chris@16 1419 Scan45Count( typename boolean_op_45<Unit2>::Count1(iter1->count[0]),
Chris@16 1420 typename boolean_op_45<Unit2>::Count1(iter1->count[1]),
Chris@16 1421 typename boolean_op_45<Unit2>::Count1(iter1->count[2]),
Chris@16 1422 typename boolean_op_45<Unit2>::Count1(iter1->count[3]))));
Chris@16 1423 ++iter1;
Chris@16 1424 }
Chris@16 1425 scan45.scan(eventOut, eventIn.begin(), eventIn.end());
Chris@16 1426 polygon_sort(eventOut.begin(), eventOut.end());
Chris@16 1427
Chris@16 1428 std::size_t ptCount = 0;
Chris@16 1429 for(std::size_t i = 0; i < eventOut.size(); ++i) {
Chris@16 1430 if(!result_data.empty() &&
Chris@16 1431 result_data.back().pt == eventOut[i].pt) {
Chris@16 1432 result_data.back().count += eventOut[i];
Chris@16 1433 ++ptCount;
Chris@16 1434 } else {
Chris@16 1435 if(!result_data.empty()) {
Chris@16 1436 if(result_data.back().count.is_45()) {
Chris@16 1437 result_is_manhattan_ = false;
Chris@16 1438 }
Chris@16 1439 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
Chris@16 1440 result_data.pop_back();
Chris@16 1441 }
Chris@16 1442 }
Chris@16 1443 result_data.push_back(eventOut[i]);
Chris@16 1444 ptCount = 1;
Chris@16 1445 }
Chris@16 1446 }
Chris@16 1447 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
Chris@16 1448 result_data.pop_back();
Chris@16 1449 }
Chris@16 1450 if(!result_data.empty() &&
Chris@16 1451 result_data.back().count.is_45()) {
Chris@16 1452 result_is_manhattan_ = false;
Chris@16 1453 }
Chris@16 1454 return result_is_manhattan_;
Chris@16 1455 }
Chris@16 1456
Chris@16 1457 template <typename cT, typename iT>
Chris@16 1458 void get_error_rects_shell(cT& posE, cT& negE, iT beginr, iT endr) {
Chris@16 1459 typedef typename std::iterator_traits<iT>::value_type Point;
Chris@16 1460 typedef typename point_traits<Point>::coordinate_type Unit;
Chris@16 1461 typedef typename coordinate_traits<Unit>::area_type area_type;
Chris@16 1462 Point pt1, pt2, pt3;
Chris@16 1463 bool i1 = true;
Chris@16 1464 bool i2 = true;
Chris@16 1465 bool not_done = beginr != endr;
Chris@16 1466 bool next_to_last = false;
Chris@16 1467 bool last = false;
Chris@16 1468 Point first, second;
Chris@16 1469 while(not_done) {
Chris@16 1470 if(last) {
Chris@16 1471 last = false;
Chris@16 1472 not_done = false;
Chris@16 1473 pt3 = second;
Chris@16 1474 } else if(next_to_last) {
Chris@16 1475 next_to_last = false;
Chris@16 1476 last = true;
Chris@16 1477 pt3 = first;
Chris@16 1478 } else if(i1) {
Chris@16 1479 const Point& pt = *beginr;
Chris@16 1480 first = pt1 = pt;
Chris@16 1481 i1 = false;
Chris@16 1482 i2 = true;
Chris@16 1483 ++beginr;
Chris@16 1484 if(beginr == endr) return; //too few points
Chris@16 1485 continue;
Chris@16 1486 } else if (i2) {
Chris@16 1487 const Point& pt = *beginr;
Chris@16 1488 second = pt2 = pt;
Chris@16 1489 i2 = false;
Chris@16 1490 ++beginr;
Chris@16 1491 if(beginr == endr) return; //too few points
Chris@16 1492 continue;
Chris@16 1493 } else {
Chris@16 1494 const Point& pt = *beginr;
Chris@16 1495 pt3 = pt;
Chris@16 1496 ++beginr;
Chris@16 1497 if(beginr == endr) {
Chris@16 1498 next_to_last = true;
Chris@16 1499 //skip last point equal to first
Chris@16 1500 continue;
Chris@16 1501 }
Chris@16 1502 }
Chris@16 1503 if(local_abs(x(pt2)) % 2) { //y % 2 should also be odd
Chris@16 1504 //is corner concave or convex?
Chris@16 1505 Point pts[] = {pt1, pt2, pt3};
Chris@16 1506 area_type ar = point_sequence_area<Point*, area_type>(pts, pts+3);
Chris@16 1507 direction_1d dir = ar < 0 ? COUNTERCLOCKWISE : CLOCKWISE;
Chris@16 1508 //std::cout << pt1 << " " << pt2 << " " << pt3 << " " << ar << std::endl;
Chris@16 1509 if(dir == CLOCKWISE) {
Chris@16 1510 posE.push_back(rectangle_data<typename Point::coordinate_type>
Chris@16 1511 (x(pt2) - 1, y(pt2) - 1, x(pt2) + 1, y(pt2) + 1));
Chris@16 1512
Chris@16 1513 } else {
Chris@16 1514 negE.push_back(rectangle_data<typename Point::coordinate_type>
Chris@16 1515 (x(pt2) - 1, y(pt2) - 1, x(pt2) + 1, y(pt2) + 1));
Chris@16 1516 }
Chris@16 1517 }
Chris@16 1518 pt1 = pt2;
Chris@16 1519 pt2 = pt3;
Chris@16 1520 }
Chris@16 1521 }
Chris@16 1522
Chris@16 1523 template <typename cT, typename pT>
Chris@16 1524 void get_error_rects(cT& posE, cT& negE, const pT& p) {
Chris@16 1525 get_error_rects_shell(posE, negE, p.begin(), p.end());
Chris@16 1526 for(typename pT::iterator_holes_type iHb = p.begin_holes();
Chris@16 1527 iHb != p.end_holes(); ++iHb) {
Chris@16 1528 get_error_rects_shell(posE, negE, iHb->begin(), iHb->end());
Chris@16 1529 }
Chris@16 1530 }
Chris@16 1531
Chris@16 1532 template <typename Unit>
Chris@16 1533 template <int op>
Chris@16 1534 inline void polygon_45_set_data<Unit>::applyAdaptiveBoolean_(polygon_45_set_data<Unit>& result,
Chris@16 1535 const polygon_45_set_data<Unit>& rvalue) const {
Chris@16 1536 result.clear();
Chris@16 1537 result.error_data_ = error_data_;
Chris@16 1538 result.error_data_.insert(result.error_data_.end(), rvalue.error_data_.begin(),
Chris@16 1539 rvalue.error_data_.end());
Chris@16 1540 if(is_manhattan() && rvalue.is_manhattan()) {
Chris@16 1541 //convert each into polygon_90_set data and call boolean operations
Chris@16 1542 polygon_90_set_data<Unit> l90sd(VERTICAL), r90sd(VERTICAL), output(VERTICAL);
Chris@16 1543 for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) {
Chris@16 1544 if((*itr).count[3] == 0) continue; //skip all non vertical edges
Chris@16 1545 l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL);
Chris@16 1546 }
Chris@16 1547 for(typename value_type::const_iterator itr = rvalue.data_.begin(); itr != rvalue.data_.end(); ++itr) {
Chris@16 1548 if((*itr).count[3] == 0) continue; //skip all non vertical edges
Chris@16 1549 r90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL);
Chris@16 1550 }
Chris@16 1551 l90sd.sort();
Chris@16 1552 r90sd.sort();
Chris@16 1553 #ifdef BOOST_POLYGON_MSVC
Chris@16 1554 #pragma warning (push)
Chris@16 1555 #pragma warning (disable: 4127)
Chris@16 1556 #endif
Chris@16 1557 if(op == 0) {
Chris@16 1558 output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(),
Chris@16 1559 r90sd.begin(), r90sd.end(), boolean_op::BinaryCount<boolean_op::BinaryOr>());
Chris@16 1560 } else if (op == 1) {
Chris@16 1561 output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(),
Chris@16 1562 r90sd.begin(), r90sd.end(), boolean_op::BinaryCount<boolean_op::BinaryAnd>());
Chris@16 1563 } else if (op == 2) {
Chris@16 1564 output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(),
Chris@16 1565 r90sd.begin(), r90sd.end(), boolean_op::BinaryCount<boolean_op::BinaryNot>());
Chris@16 1566 } else if (op == 3) {
Chris@16 1567 output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(),
Chris@16 1568 r90sd.begin(), r90sd.end(), boolean_op::BinaryCount<boolean_op::BinaryXor>());
Chris@16 1569 }
Chris@16 1570 #ifdef BOOST_POLYGON_MSVC
Chris@16 1571 #pragma warning (pop)
Chris@16 1572 #endif
Chris@16 1573 result.data_.clear();
Chris@16 1574 result.insert(output);
Chris@16 1575 result.is_manhattan_ = true;
Chris@16 1576 result.dirty_ = false;
Chris@16 1577 result.unsorted_ = false;
Chris@16 1578 } else {
Chris@16 1579 sort();
Chris@16 1580 rvalue.sort();
Chris@16 1581 try {
Chris@16 1582 result.is_manhattan_ = applyBoolean45OpOnVectors<Unit, op>(result.data_, data_, rvalue.data_);
Chris@16 1583 } catch (std::string str) {
Chris@16 1584 std::string msg = "GTL 45 Boolean error, precision insufficient to represent edge intersection coordinate value.";
Chris@16 1585 if(str == msg) {
Chris@16 1586 result.clear();
Chris@16 1587 typedef typename coordinate_traits<Unit>::manhattan_area_type Unit2;
Chris@16 1588 typedef typename polygon_45_formation<Unit2>::Vertex45Compact Vertex45Compact2;
Chris@16 1589 typedef std::vector<Vertex45Compact2> Data2;
Chris@16 1590 Data2 rvalue_data, lvalue_data, result_data;
Chris@16 1591 rvalue_data.reserve(rvalue.data_.size());
Chris@16 1592 lvalue_data.reserve(data_.size());
Chris@16 1593 for(std::size_t i = 0 ; i < data_.size(); ++i) {
Chris@16 1594 const Vertex45Compact& vi = data_[i];
Chris@16 1595 Vertex45Compact2 ci;
Chris@16 1596 ci.pt = point_data<Unit2>(x(vi.pt), y(vi.pt));
Chris@16 1597 ci.count = typename polygon_45_formation<Unit2>::Vertex45Count
Chris@16 1598 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
Chris@16 1599 lvalue_data.push_back(ci);
Chris@16 1600 }
Chris@16 1601 for(std::size_t i = 0 ; i < rvalue.data_.size(); ++i) {
Chris@16 1602 const Vertex45Compact& vi = rvalue.data_[i];
Chris@16 1603 Vertex45Compact2 ci;
Chris@16 1604 ci.pt = (point_data<Unit2>(x(vi.pt), y(vi.pt)));
Chris@16 1605 ci.count = typename polygon_45_formation<Unit2>::Vertex45Count
Chris@16 1606 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
Chris@16 1607 rvalue_data.push_back(ci);
Chris@16 1608 }
Chris@16 1609 scale_up_vertex_45_compact_range(lvalue_data.begin(), lvalue_data.end(), 2);
Chris@16 1610 scale_up_vertex_45_compact_range(rvalue_data.begin(), rvalue_data.end(), 2);
Chris@16 1611 bool result_is_manhattan = applyBoolean45OpOnVectors<Unit2, op>(result_data,
Chris@16 1612 lvalue_data,
Chris@16 1613 rvalue_data );
Chris@16 1614 if(!result_is_manhattan) {
Chris@16 1615 typename polygon_45_formation<Unit2>::Polygon45Formation pf(false);
Chris@16 1616 //std::cout << "FORMING POLYGONS\n";
Chris@16 1617 std::vector<polygon_45_with_holes_data<Unit2> > container;
Chris@16 1618 pf.scan(container, result_data.begin(), result_data.end());
Chris@16 1619 Data2 error_data_out;
Chris@16 1620 std::vector<rectangle_data<Unit2> > pos_error_rects;
Chris@16 1621 std::vector<rectangle_data<Unit2> > neg_error_rects;
Chris@16 1622 for(std::size_t i = 0; i < container.size(); ++i) {
Chris@16 1623 get_error_rects(pos_error_rects, neg_error_rects, container[i]);
Chris@16 1624 }
Chris@16 1625 for(std::size_t i = 0; i < pos_error_rects.size(); ++i) {
Chris@16 1626 insert_rectangle_into_vector_45(result_data, pos_error_rects[i], false);
Chris@16 1627 insert_rectangle_into_vector_45(error_data_out, pos_error_rects[i], false);
Chris@16 1628 }
Chris@16 1629 for(std::size_t i = 0; i < neg_error_rects.size(); ++i) {
Chris@16 1630 insert_rectangle_into_vector_45(result_data, neg_error_rects[i], true);
Chris@16 1631 insert_rectangle_into_vector_45(error_data_out, neg_error_rects[i], false);
Chris@16 1632 }
Chris@16 1633 scale_down_vertex_45_compact_range_blindly(error_data_out.begin(), error_data_out.end(), 2);
Chris@16 1634 for(std::size_t i = 0 ; i < error_data_out.size(); ++i) {
Chris@16 1635 const Vertex45Compact2& vi = error_data_out[i];
Chris@16 1636 Vertex45Compact ci;
Chris@16 1637 ci.pt.x(static_cast<Unit>(x(vi.pt)));
Chris@16 1638 ci.pt.y(static_cast<Unit>(y(vi.pt)));
Chris@16 1639 ci.count = typename polygon_45_formation<Unit>::Vertex45Count
Chris@16 1640 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
Chris@16 1641 result.error_data_.push_back(ci);
Chris@16 1642 }
Chris@16 1643 Data2 new_result_data;
Chris@16 1644 polygon_sort(result_data.begin(), result_data.end());
Chris@16 1645 applyUnary45OpOnVectors<Unit2, 0>(new_result_data, result_data); //OR operation
Chris@16 1646 result_data.swap(new_result_data);
Chris@16 1647 }
Chris@16 1648 scale_down_vertex_45_compact_range_blindly(result_data.begin(), result_data.end(), 2);
Chris@16 1649 //result.data_.reserve(result_data.size());
Chris@16 1650 for(std::size_t i = 0 ; i < result_data.size(); ++i) {
Chris@16 1651 const Vertex45Compact2& vi = result_data[i];
Chris@16 1652 Vertex45Compact ci;
Chris@16 1653 ci.pt.x(static_cast<Unit>(x(vi.pt)));
Chris@16 1654 ci.pt.y(static_cast<Unit>(y(vi.pt)));
Chris@16 1655 ci.count = typename polygon_45_formation<Unit>::Vertex45Count
Chris@16 1656 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
Chris@16 1657 result.data_.push_back(ci);
Chris@16 1658 }
Chris@16 1659 result.is_manhattan_ = result_is_manhattan;
Chris@16 1660 result.dirty_ = false;
Chris@16 1661 result.unsorted_ = false;
Chris@16 1662 } else { throw str; }
Chris@16 1663 }
Chris@16 1664 //std::cout << "DONE SCANNING\n";
Chris@16 1665 }
Chris@16 1666 }
Chris@16 1667
Chris@16 1668 template <typename Unit>
Chris@16 1669 template <int op>
Chris@16 1670 inline void polygon_45_set_data<Unit>::applyAdaptiveUnary_() const {
Chris@16 1671 polygon_45_set_data<Unit> result;
Chris@16 1672 result.error_data_ = error_data_;
Chris@16 1673 if(is_manhattan()) {
Chris@16 1674 //convert each into polygon_90_set data and call boolean operations
Chris@16 1675 polygon_90_set_data<Unit> l90sd(VERTICAL);
Chris@16 1676 for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) {
Chris@16 1677 if((*itr).count[3] == 0) continue; //skip all non vertical edges
Chris@16 1678 l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL);
Chris@16 1679 }
Chris@16 1680 l90sd.sort();
Chris@16 1681 #ifdef BOOST_POLYGON_MSVC
Chris@16 1682 #pragma warning (push)
Chris@16 1683 #pragma warning (disable: 4127)
Chris@16 1684 #endif
Chris@16 1685 if(op == 0) {
Chris@16 1686 l90sd.clean();
Chris@16 1687 } else if (op == 1) {
Chris@16 1688 l90sd.self_intersect();
Chris@16 1689 } else if (op == 3) {
Chris@16 1690 l90sd.self_xor();
Chris@16 1691 }
Chris@16 1692 #ifdef BOOST_POLYGON_MSVC
Chris@16 1693 #pragma warning (pop)
Chris@16 1694 #endif
Chris@16 1695 result.data_.clear();
Chris@16 1696 result.insert(l90sd);
Chris@16 1697 result.is_manhattan_ = true;
Chris@16 1698 result.dirty_ = false;
Chris@16 1699 result.unsorted_ = false;
Chris@16 1700 } else {
Chris@16 1701 sort();
Chris@16 1702 try {
Chris@16 1703 result.is_manhattan_ = applyUnary45OpOnVectors<Unit, op>(result.data_, data_);
Chris@16 1704 } catch (std::string str) {
Chris@16 1705 std::string msg = "GTL 45 Boolean error, precision insufficient to represent edge intersection coordinate value.";
Chris@16 1706 if(str == msg) {
Chris@16 1707 result.clear();
Chris@16 1708 typedef typename coordinate_traits<Unit>::manhattan_area_type Unit2;
Chris@16 1709 typedef typename polygon_45_formation<Unit2>::Vertex45Compact Vertex45Compact2;
Chris@16 1710 typedef std::vector<Vertex45Compact2> Data2;
Chris@16 1711 Data2 lvalue_data, result_data;
Chris@16 1712 lvalue_data.reserve(data_.size());
Chris@16 1713 for(std::size_t i = 0 ; i < data_.size(); ++i) {
Chris@16 1714 const Vertex45Compact& vi = data_[i];
Chris@16 1715 Vertex45Compact2 ci;
Chris@16 1716 ci.pt.x(static_cast<Unit>(x(vi.pt)));
Chris@16 1717 ci.pt.y(static_cast<Unit>(y(vi.pt)));
Chris@16 1718 ci.count = typename polygon_45_formation<Unit2>::Vertex45Count
Chris@16 1719 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
Chris@16 1720 lvalue_data.push_back(ci);
Chris@16 1721 }
Chris@16 1722 scale_up_vertex_45_compact_range(lvalue_data.begin(), lvalue_data.end(), 2);
Chris@16 1723 bool result_is_manhattan = applyUnary45OpOnVectors<Unit2, op>(result_data,
Chris@16 1724 lvalue_data );
Chris@16 1725 if(!result_is_manhattan) {
Chris@16 1726 typename polygon_45_formation<Unit2>::Polygon45Formation pf(false);
Chris@16 1727 //std::cout << "FORMING POLYGONS\n";
Chris@16 1728 std::vector<polygon_45_with_holes_data<Unit2> > container;
Chris@16 1729 pf.scan(container, result_data.begin(), result_data.end());
Chris@16 1730 Data2 error_data_out;
Chris@16 1731 std::vector<rectangle_data<Unit2> > pos_error_rects;
Chris@16 1732 std::vector<rectangle_data<Unit2> > neg_error_rects;
Chris@16 1733 for(std::size_t i = 0; i < container.size(); ++i) {
Chris@16 1734 get_error_rects(pos_error_rects, neg_error_rects, container[i]);
Chris@16 1735 }
Chris@16 1736 for(std::size_t i = 0; i < pos_error_rects.size(); ++i) {
Chris@16 1737 insert_rectangle_into_vector_45(result_data, pos_error_rects[i], false);
Chris@16 1738 insert_rectangle_into_vector_45(error_data_out, pos_error_rects[i], false);
Chris@16 1739 }
Chris@16 1740 for(std::size_t i = 0; i < neg_error_rects.size(); ++i) {
Chris@16 1741 insert_rectangle_into_vector_45(result_data, neg_error_rects[i], true);
Chris@16 1742 insert_rectangle_into_vector_45(error_data_out, neg_error_rects[i], false);
Chris@16 1743 }
Chris@16 1744 scale_down_vertex_45_compact_range_blindly(error_data_out.begin(), error_data_out.end(), 2);
Chris@16 1745 for(std::size_t i = 0 ; i < error_data_out.size(); ++i) {
Chris@16 1746 const Vertex45Compact2& vi = error_data_out[i];
Chris@16 1747 Vertex45Compact ci;
Chris@16 1748 ci.pt.x(static_cast<Unit>(x(vi.pt)));
Chris@16 1749 ci.pt.y(static_cast<Unit>(y(vi.pt)));
Chris@16 1750 ci.count = typename polygon_45_formation<Unit>::Vertex45Count
Chris@16 1751 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
Chris@16 1752 result.error_data_.push_back(ci);
Chris@16 1753 }
Chris@16 1754 Data2 new_result_data;
Chris@16 1755 polygon_sort(result_data.begin(), result_data.end());
Chris@16 1756 applyUnary45OpOnVectors<Unit2, 0>(new_result_data, result_data); //OR operation
Chris@16 1757 result_data.swap(new_result_data);
Chris@16 1758 }
Chris@16 1759 scale_down_vertex_45_compact_range_blindly(result_data.begin(), result_data.end(), 2);
Chris@16 1760 //result.data_.reserve(result_data.size());
Chris@16 1761 for(std::size_t i = 0 ; i < result_data.size(); ++i) {
Chris@16 1762 const Vertex45Compact2& vi = result_data[i];
Chris@16 1763 Vertex45Compact ci;
Chris@16 1764 ci.pt.x(static_cast<Unit>(x(vi.pt)));
Chris@16 1765 ci.pt.y(static_cast<Unit>(y(vi.pt)));
Chris@16 1766 ci.count = typename polygon_45_formation<Unit>::Vertex45Count
Chris@16 1767 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
Chris@16 1768 result.data_.push_back(ci);
Chris@16 1769 }
Chris@16 1770 result.is_manhattan_ = result_is_manhattan;
Chris@16 1771 result.dirty_ = false;
Chris@16 1772 result.unsorted_ = false;
Chris@16 1773 } else { throw str; }
Chris@16 1774 }
Chris@16 1775 //std::cout << "DONE SCANNING\n";
Chris@16 1776 }
Chris@16 1777 data_.swap(result.data_);
Chris@16 1778 error_data_.swap(result.error_data_);
Chris@16 1779 dirty_ = result.dirty_;
Chris@16 1780 unsorted_ = result.unsorted_;
Chris@16 1781 is_manhattan_ = result.is_manhattan_;
Chris@16 1782 }
Chris@16 1783
Chris@16 1784 template <typename coordinate_type, typename property_type>
Chris@16 1785 class property_merge_45 {
Chris@16 1786 private:
Chris@16 1787 typedef typename coordinate_traits<coordinate_type>::manhattan_area_type big_coord;
Chris@16 1788 typedef typename polygon_45_property_merge<big_coord, property_type>::MergeSetData tsd;
Chris@16 1789 tsd tsd_;
Chris@16 1790 public:
Chris@16 1791 inline property_merge_45() : tsd_() {}
Chris@16 1792 inline property_merge_45(const property_merge_45& that) : tsd_(that.tsd_) {}
Chris@16 1793 inline property_merge_45& operator=(const property_merge_45& that) {
Chris@16 1794 tsd_ = that.tsd_;
Chris@16 1795 return *this;
Chris@16 1796 }
Chris@16 1797
Chris@16 1798 inline void insert(const polygon_45_set_data<coordinate_type>& ps, property_type property) {
Chris@16 1799 ps.clean();
Chris@16 1800 polygon_45_property_merge<big_coord, property_type>::populateMergeSetData(tsd_, ps.begin(), ps.end(), property);
Chris@16 1801 }
Chris@16 1802 template <class GeoObjT>
Chris@16 1803 inline void insert(const GeoObjT& geoObj, property_type property) {
Chris@16 1804 polygon_45_set_data<coordinate_type> ps;
Chris@16 1805 ps.insert(geoObj);
Chris@16 1806 insert(ps, property);
Chris@16 1807 }
Chris@16 1808
Chris@16 1809 //merge properties of input geometries and store the resulting geometries of regions
Chris@16 1810 //with unique sets of merged properties to polygons sets in a map keyed by sets of properties
Chris@16 1811 // T = std::map<std::set<property_type>, polygon_45_set_data<coordiante_type> > or
Chris@16 1812 // T = std::map<std::vector<property_type>, polygon_45_set_data<coordiante_type> >
Chris@16 1813 template <class result_type>
Chris@16 1814 inline void merge(result_type& result) {
Chris@16 1815 typedef typename result_type::key_type keytype;
Chris@16 1816 typedef std::map<keytype, polygon_45_set_data<big_coord> > bigtype;
Chris@16 1817 bigtype result_big;
Chris@16 1818 polygon_45_property_merge<big_coord, property_type>::performMerge(result_big, tsd_);
Chris@16 1819 std::vector<polygon_45_with_holes_data<big_coord> > polys;
Chris@16 1820 std::vector<rectangle_data<big_coord> > pos_error_rects;
Chris@16 1821 std::vector<rectangle_data<big_coord> > neg_error_rects;
Chris@16 1822 for(typename std::map<keytype, polygon_45_set_data<big_coord> >::iterator itr = result_big.begin();
Chris@16 1823 itr != result_big.end(); ++itr) {
Chris@16 1824 polys.clear();
Chris@16 1825 (*itr).second.get(polys);
Chris@16 1826 for(std::size_t i = 0; i < polys.size(); ++i) {
Chris@16 1827 get_error_rects(pos_error_rects, neg_error_rects, polys[i]);
Chris@16 1828 }
Chris@16 1829 (*itr).second += pos_error_rects;
Chris@16 1830 (*itr).second -= neg_error_rects;
Chris@16 1831 (*itr).second.scale_down(2);
Chris@16 1832 result[(*itr).first].insert((*itr).second);
Chris@16 1833 }
Chris@16 1834 }
Chris@16 1835 };
Chris@16 1836
Chris@16 1837 //ConnectivityExtraction computes the graph of connectivity between rectangle, polygon and
Chris@16 1838 //polygon set graph nodes where an edge is created whenever the geometry in two nodes overlap
Chris@16 1839 template <typename coordinate_type>
Chris@16 1840 class connectivity_extraction_45 {
Chris@16 1841 private:
Chris@16 1842 typedef typename coordinate_traits<coordinate_type>::manhattan_area_type big_coord;
Chris@16 1843 typedef typename polygon_45_touch<big_coord>::TouchSetData tsd;
Chris@16 1844 tsd tsd_;
Chris@16 1845 unsigned int nodeCount_;
Chris@16 1846 public:
Chris@16 1847 inline connectivity_extraction_45() : tsd_(), nodeCount_(0) {}
Chris@16 1848 inline connectivity_extraction_45(const connectivity_extraction_45& that) : tsd_(that.tsd_),
Chris@16 1849 nodeCount_(that.nodeCount_) {}
Chris@16 1850 inline connectivity_extraction_45& operator=(const connectivity_extraction_45& that) {
Chris@16 1851 tsd_ = that.tsd_;
Chris@16 1852 nodeCount_ = that.nodeCount_; {}
Chris@16 1853 return *this;
Chris@16 1854 }
Chris@16 1855
Chris@16 1856 //insert a polygon set graph node, the value returned is the id of the graph node
Chris@16 1857 inline unsigned int insert(const polygon_45_set_data<coordinate_type>& ps) {
Chris@16 1858 ps.clean();
Chris@16 1859 polygon_45_touch<big_coord>::populateTouchSetData(tsd_, ps.begin(), ps.end(), nodeCount_);
Chris@16 1860 return nodeCount_++;
Chris@16 1861 }
Chris@16 1862 template <class GeoObjT>
Chris@16 1863 inline unsigned int insert(const GeoObjT& geoObj) {
Chris@16 1864 polygon_45_set_data<coordinate_type> ps;
Chris@16 1865 ps.insert(geoObj);
Chris@16 1866 return insert(ps);
Chris@16 1867 }
Chris@16 1868
Chris@16 1869 //extract connectivity and store the edges in the graph
Chris@16 1870 //graph must be indexable by graph node id and the indexed value must be a std::set of
Chris@16 1871 //graph node id
Chris@16 1872 template <class GraphT>
Chris@16 1873 inline void extract(GraphT& graph) {
Chris@16 1874 polygon_45_touch<big_coord>::performTouch(graph, tsd_);
Chris@16 1875 }
Chris@16 1876 };
Chris@16 1877 }
Chris@16 1878 }
Chris@16 1879 #endif
Chris@16 1880