File indexing completed on 2025-01-18 09:48:00
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_POLYGON_POLYGON_45_SET_DATA_HPP
0009 #define BOOST_POLYGON_POLYGON_45_SET_DATA_HPP
0010 #include "polygon_90_set_data.hpp"
0011 #include "detail/boolean_op_45.hpp"
0012 #include "detail/polygon_45_formation.hpp"
0013 #include "detail/polygon_45_touch.hpp"
0014 #include "detail/property_merge_45.hpp"
0015 namespace boost { namespace polygon{
0016
0017 enum RoundingOption { CLOSEST = 0, OVERSIZE = 1, UNDERSIZE = 2, SQRT2 = 3, SQRT1OVER2 = 4 };
0018 enum CornerOption { INTERSECTION = 0, ORTHOGONAL = 1, UNFILLED = 2 };
0019
0020 template <typename ltype, typename rtype, int op_type>
0021 class polygon_45_set_view;
0022
0023 struct polygon_45_set_concept {};
0024
0025 template <typename Unit>
0026 class polygon_45_set_data {
0027 public:
0028 typedef typename polygon_45_formation<Unit>::Vertex45Compact Vertex45Compact;
0029 typedef std::vector<Vertex45Compact> Polygon45VertexData;
0030
0031 typedef Unit coordinate_type;
0032 typedef Polygon45VertexData value_type;
0033 typedef typename value_type::const_iterator iterator_type;
0034 typedef polygon_45_set_data operator_arg_type;
0035
0036
0037 inline polygon_45_set_data() : error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) {}
0038
0039
0040 template <typename geometry_type>
0041 inline polygon_45_set_data(const geometry_type& that) : error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) {
0042 insert(that);
0043 }
0044
0045
0046 inline polygon_45_set_data(const polygon_45_set_data& that) :
0047 error_data_(that.error_data_), data_(that.data_), dirty_(that.dirty_),
0048 unsorted_(that.unsorted_), is_manhattan_(that.is_manhattan_) {}
0049
0050 template <typename ltype, typename rtype, int op_type>
0051 inline polygon_45_set_data(const polygon_45_set_view<ltype, rtype, op_type>& that) :
0052 error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) {
0053 (*this) = that.value();
0054 }
0055
0056
0057 inline ~polygon_45_set_data() {}
0058
0059
0060 inline polygon_45_set_data& operator=(const polygon_45_set_data& that) {
0061 if(this == &that) return *this;
0062 error_data_ = that.error_data_;
0063 data_ = that.data_;
0064 dirty_ = that.dirty_;
0065 unsorted_ = that.unsorted_;
0066 is_manhattan_ = that.is_manhattan_;
0067 return *this;
0068 }
0069
0070 template <typename ltype, typename rtype, int op_type>
0071 inline polygon_45_set_data& operator=(const polygon_45_set_view<ltype, rtype, op_type>& that) {
0072 (*this) = that.value();
0073 return *this;
0074 }
0075
0076 template <typename geometry_object>
0077 inline polygon_45_set_data& operator=(const geometry_object& geometry) {
0078 data_.clear();
0079 insert(geometry);
0080 return *this;
0081 }
0082
0083
0084 inline void insert(iterator_type input_begin, iterator_type input_end, bool is_hole = false) {
0085 if(input_begin == input_end || (!data_.empty() && &(*input_begin) == &(*(data_.begin())))) return;
0086 dirty_ = true;
0087 unsorted_ = true;
0088 while(input_begin != input_end) {
0089 insert(*input_begin, is_hole);
0090 ++input_begin;
0091 }
0092 }
0093
0094
0095 template <typename iT>
0096 inline void insert(iT input_begin, iT input_end, bool is_hole = false) {
0097 if(input_begin == input_end) return;
0098 dirty_ = true;
0099 unsorted_ = true;
0100 while(input_begin != input_end) {
0101 insert(*input_begin, is_hole);
0102 ++input_begin;
0103 }
0104 }
0105
0106 inline void insert(const polygon_45_set_data& polygon_set, bool is_hole = false);
0107 template <typename coord_type>
0108 inline void insert(const polygon_45_set_data<coord_type>& polygon_set, bool is_hole = false);
0109
0110 template <typename geometry_type>
0111 inline void insert(const geometry_type& geometry_object, bool is_hole = false) {
0112 insert_dispatch(geometry_object, is_hole, typename geometry_concept<geometry_type>::type());
0113 }
0114
0115 inline void insert_clean(const Vertex45Compact& vertex_45, bool is_hole = false) {
0116 if(vertex_45.count.is_45()) is_manhattan_ = false;
0117 data_.push_back(vertex_45);
0118 if(is_hole) data_.back().count.invert();
0119 }
0120
0121 inline void insert(const Vertex45Compact& vertex_45, bool is_hole = false) {
0122 dirty_ = true;
0123 unsorted_ = true;
0124 insert_clean(vertex_45, is_hole);
0125 }
0126
0127 template <typename coordinate_type_2>
0128 inline void insert(const polygon_90_set_data<coordinate_type_2>& polygon_set, bool is_hole = false) {
0129 if(polygon_set.orient() == VERTICAL) {
0130 for(typename polygon_90_set_data<coordinate_type_2>::iterator_type itr = polygon_set.begin();
0131 itr != polygon_set.end(); ++itr) {
0132 Vertex45Compact vertex_45(point_data<Unit>((*itr).first, (*itr).second.first), 2, (*itr).second.second);
0133 vertex_45.count[1] = (*itr).second.second;
0134 if(is_hole) vertex_45.count[1] *= - 1;
0135 insert_clean(vertex_45, is_hole);
0136 }
0137 } else {
0138 for(typename polygon_90_set_data<coordinate_type_2>::iterator_type itr = polygon_set.begin();
0139 itr != polygon_set.end(); ++itr) {
0140 Vertex45Compact vertex_45(point_data<Unit>((*itr).second.first, (*itr).first), 2, (*itr).second.second);
0141 vertex_45.count[1] = (*itr).second.second;
0142 if(is_hole) vertex_45.count[1] *= - 1;
0143 insert_clean(vertex_45, is_hole);
0144 }
0145 }
0146 dirty_ = true;
0147 unsorted_ = true;
0148 }
0149
0150 template <typename output_container>
0151 inline void get(output_container& output) const {
0152 get_dispatch(output, typename geometry_concept<typename output_container::value_type>::type());
0153 }
0154
0155 inline bool has_error_data() const { return !error_data_.empty(); }
0156 inline std::size_t error_count() const { return error_data_.size() / 4; }
0157 inline void get_error_data(polygon_45_set_data& p) const {
0158 p.data_.insert(p.data_.end(), error_data_.begin(), error_data_.end());
0159 }
0160
0161
0162 inline bool operator==(const polygon_45_set_data& p) const {
0163 clean();
0164 p.clean();
0165 return data_ == p.data_;
0166 }
0167
0168
0169 inline bool operator!=(const polygon_45_set_data& p) const {
0170 return !((*this) == p);
0171 }
0172
0173
0174 inline iterator_type begin() const {
0175 return data_.begin();
0176 }
0177
0178
0179 inline iterator_type end() const {
0180 return data_.end();
0181 }
0182
0183 const value_type& value() const {
0184 return data_;
0185 }
0186
0187
0188 inline void clear() { data_.clear(); error_data_.clear(); dirty_ = unsorted_ = false; is_manhattan_ = true; }
0189
0190
0191 inline bool empty() const { return data_.empty(); }
0192
0193
0194 inline std::size_t size() const { clean(); return data_.size(); }
0195
0196
0197 inline std::size_t capacity() const { return data_.capacity(); }
0198
0199
0200 inline void reserve(std::size_t size) { return data_.reserve(size); }
0201
0202
0203 inline bool sorted() const { return !unsorted_; }
0204
0205
0206 inline bool dirty() const { return dirty_; }
0207
0208
0209 inline bool is_manhattan() const { return is_manhattan_; }
0210
0211 bool clean() const;
0212
0213 void sort() const{
0214 if(unsorted_) {
0215 polygon_sort(data_.begin(), data_.end());
0216 unsorted_ = false;
0217 }
0218 }
0219
0220 template <typename input_iterator_type>
0221 void set(input_iterator_type input_begin, input_iterator_type input_end) {
0222 data_.clear();
0223 reserve(std::distance(input_begin, input_end));
0224 insert(input_begin, input_end);
0225 dirty_ = true;
0226 unsorted_ = true;
0227 }
0228
0229 void set_clean(const value_type& value) {
0230 data_ = value;
0231 dirty_ = false;
0232 unsorted_ = false;
0233 }
0234
0235 void set(const value_type& value) {
0236 data_ = value;
0237 dirty_ = true;
0238 unsorted_ = true;
0239 }
0240
0241
0242 template <class cT>
0243 void get_polygons(cT& container) const {
0244 get_dispatch(container, polygon_45_concept());
0245 }
0246
0247
0248 template <class cT>
0249 void get_polygons_with_holes(cT& container) const {
0250 get_dispatch(container, polygon_45_with_holes_concept());
0251 }
0252
0253
0254
0255 template <class cT>
0256 void get_trapezoids(cT& container) const {
0257 clean();
0258 typename polygon_45_formation<Unit>::Polygon45Tiling pf;
0259
0260 pf.scan(container, data_.begin(), data_.end());
0261
0262 }
0263
0264
0265 template <class cT>
0266 void get_trapezoids(cT& container, orientation_2d slicing_orientation) const {
0267 if(slicing_orientation == VERTICAL) {
0268 get_trapezoids(container);
0269 } else {
0270 polygon_45_set_data<Unit> ps(*this);
0271 ps.transform(axis_transformation(axis_transformation::SWAP_XY));
0272 cT result;
0273 ps.get_trapezoids(result);
0274 for(typename cT::iterator itr = result.begin(); itr != result.end(); ++itr) {
0275 ::boost::polygon::transform(*itr, axis_transformation(axis_transformation::SWAP_XY));
0276 }
0277 container.insert(container.end(), result.begin(), result.end());
0278 }
0279 }
0280
0281
0282 template <class iT>
0283 void insert_vertex_sequence(iT begin_vertex, iT end_vertex,
0284 direction_1d winding, bool is_hole = false);
0285
0286
0287 template <typename rectangle_type>
0288 bool extents(rectangle_type& rect) const;
0289
0290
0291 void snap() const;
0292
0293
0294 polygon_45_set_data& operator|=(const polygon_45_set_data& b);
0295 polygon_45_set_data& operator&=(const polygon_45_set_data& b);
0296 polygon_45_set_data& operator+=(const polygon_45_set_data& b);
0297 polygon_45_set_data& operator*=(const polygon_45_set_data& b);
0298 polygon_45_set_data& operator-=(const polygon_45_set_data& b);
0299 polygon_45_set_data& operator^=(const polygon_45_set_data& b);
0300
0301
0302 polygon_45_set_data& operator+=(Unit delta);
0303 polygon_45_set_data& operator-=(Unit delta);
0304
0305
0306 polygon_45_set_data& resize(coordinate_type resizing, RoundingOption rounding = CLOSEST,
0307 CornerOption corner = INTERSECTION);
0308
0309
0310 template <typename transformation_type>
0311 polygon_45_set_data& transform(const transformation_type& tr);
0312
0313
0314 polygon_45_set_data& scale_up(typename coordinate_traits<Unit>::unsigned_area_type factor);
0315 polygon_45_set_data& scale_down(typename coordinate_traits<Unit>::unsigned_area_type factor);
0316 polygon_45_set_data& scale(double scaling);
0317
0318
0319 polygon_45_set_data& self_intersect() {
0320 sort();
0321 applyAdaptiveUnary_<1>();
0322 dirty_ = false;
0323 return *this;
0324 }
0325
0326
0327 polygon_45_set_data& self_xor() {
0328 sort();
0329 applyAdaptiveUnary_<3>();
0330 dirty_ = false;
0331 return *this;
0332 }
0333
0334
0335 template <typename geometry_type>
0336 polygon_45_set_data& insert_with_resize(const geometry_type& poly,
0337 coordinate_type resizing, RoundingOption rounding = CLOSEST,
0338 CornerOption corner = INTERSECTION,
0339 bool hole = false) {
0340 return insert_with_resize_dispatch(poly, resizing, rounding, corner, hole, typename geometry_concept<geometry_type>::type());
0341 }
0342
0343 private:
0344 mutable value_type error_data_;
0345 mutable value_type data_;
0346 mutable bool dirty_;
0347 mutable bool unsorted_;
0348 mutable bool is_manhattan_;
0349
0350 private:
0351
0352 template <typename output_container>
0353 void get_dispatch(output_container& output, polygon_45_concept tag) const {
0354 get_fracture(output, true, tag);
0355 }
0356 template <typename output_container>
0357 void get_dispatch(output_container& output, polygon_45_with_holes_concept tag) const {
0358 get_fracture(output, false, tag);
0359 }
0360 template <typename output_container>
0361 void get_dispatch(output_container& output, polygon_concept tag) const {
0362 get_fracture(output, true, tag);
0363 }
0364 template <typename output_container>
0365 void get_dispatch(output_container& output, polygon_with_holes_concept tag) const {
0366 get_fracture(output, false, tag);
0367 }
0368 template <typename output_container, typename concept_type>
0369 void get_fracture(output_container& container, bool fracture_holes, concept_type ) const {
0370 clean();
0371 typename polygon_45_formation<Unit>::Polygon45Formation pf(fracture_holes);
0372
0373 pf.scan(container, data_.begin(), data_.end());
0374 }
0375
0376 template <typename geometry_type>
0377 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, undefined_concept) {
0378 insert(geometry_object.begin(), geometry_object.end(), is_hole);
0379 }
0380 template <typename geometry_type>
0381 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, rectangle_concept tag);
0382 template <typename geometry_type>
0383 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_90_concept ) {
0384 insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole);
0385 }
0386 template <typename geometry_type>
0387 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_90_with_holes_concept ) {
0388 insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole);
0389 for(typename polygon_with_holes_traits<geometry_type>::iterator_holes_type itr =
0390 begin_holes(geometry_object); itr != end_holes(geometry_object);
0391 ++itr) {
0392 insert_vertex_sequence(begin_points(*itr), end_points(*itr), winding(*itr), !is_hole);
0393 }
0394 }
0395 template <typename geometry_type>
0396 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_45_concept ) {
0397 insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole);
0398 }
0399 template <typename geometry_type>
0400 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_45_with_holes_concept ) {
0401 insert_vertex_sequence(begin_points(geometry_object), end_points(geometry_object), winding(geometry_object), is_hole);
0402 for(typename polygon_with_holes_traits<geometry_type>::iterator_holes_type itr =
0403 begin_holes(geometry_object); itr != end_holes(geometry_object);
0404 ++itr) {
0405 insert_vertex_sequence(begin_points(*itr), end_points(*itr), winding(*itr), !is_hole);
0406 }
0407 }
0408 template <typename geometry_type>
0409 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_45_set_concept ) {
0410 polygon_45_set_data ps;
0411 assign(ps, geometry_object);
0412 insert(ps, is_hole);
0413 }
0414 template <typename geometry_type>
0415 void insert_dispatch(const geometry_type& geometry_object, bool is_hole, polygon_90_set_concept ) {
0416 std::list<polygon_90_data<coordinate_type> > pl;
0417 assign(pl, geometry_object);
0418 insert(pl.begin(), pl.end(), is_hole);
0419 }
0420
0421 void insert_vertex_half_edge_45_pair(const point_data<Unit>& pt1, point_data<Unit>& pt2,
0422 const point_data<Unit>& pt3, direction_1d wdir);
0423
0424 template <typename geometry_type>
0425 polygon_45_set_data& insert_with_resize_dispatch(const geometry_type& poly,
0426 coordinate_type resizing, RoundingOption rounding,
0427 CornerOption corner, bool hole, polygon_45_concept tag);
0428
0429
0430 template <typename geometry_type>
0431 polygon_45_set_data& insert_with_resize_dispatch(const geometry_type& poly,
0432 coordinate_type resizing, RoundingOption rounding,
0433 CornerOption corner, bool hole, polygon_45_with_holes_concept tag);
0434
0435 static void snap_vertex_45(Vertex45Compact& vertex);
0436
0437 public:
0438 template <int op>
0439 void applyAdaptiveBoolean_(const polygon_45_set_data& rvalue) const;
0440 template <int op>
0441 void applyAdaptiveBoolean_(polygon_45_set_data& result, const polygon_45_set_data& rvalue) const;
0442 template <int op>
0443 void applyAdaptiveUnary_() const;
0444 };
0445
0446 template <typename T>
0447 struct geometry_concept<polygon_45_set_data<T> > {
0448 typedef polygon_45_set_concept type;
0449 };
0450
0451 template <typename iT, typename T>
0452 void scale_up_vertex_45_compact_range(iT beginr, iT endr, T factor) {
0453 for( ; beginr != endr; ++beginr) {
0454 scale_up((*beginr).pt, factor);
0455 }
0456 }
0457 template <typename iT, typename T>
0458 void scale_down_vertex_45_compact_range_blindly(iT beginr, iT endr, T factor) {
0459 for( ; beginr != endr; ++beginr) {
0460 scale_down((*beginr).pt, factor);
0461 }
0462 }
0463
0464 template <typename Unit>
0465 inline std::pair<int, int> characterizeEdge45(const point_data<Unit>& pt1, const point_data<Unit>& pt2) {
0466 std::pair<int, int> retval(0, 1);
0467 if(pt1.x() == pt2.x()) {
0468 retval.first = 3;
0469 retval.second = -1;
0470 return retval;
0471 }
0472
0473 retval.second = 1;
0474 if(pt1.y() == pt2.y()) {
0475 retval.first = 1;
0476 } else if(pt1.x() < pt2.x()) {
0477 if(pt1.y() < pt2.y()) {
0478 retval.first = 2;
0479 } else {
0480 retval.first = 0;
0481 }
0482 } else {
0483 if(pt1.y() < pt2.y()) {
0484 retval.first = 0;
0485 } else {
0486 retval.first = 2;
0487 }
0488 }
0489 return retval;
0490 }
0491
0492 template <typename cT, typename pT>
0493 bool insert_vertex_half_edge_45_pair_into_vector(cT& output,
0494 const pT& pt1, pT& pt2,
0495 const pT& pt3,
0496 direction_1d wdir) {
0497 int multiplier = wdir == LOW ? -1 : 1;
0498 typename cT::value_type vertex(pt2, 0, 0);
0499
0500 std::pair<int, int> check;
0501 check = characterizeEdge45(pt1, pt2);
0502
0503 vertex.count[check.first] += check.second * -multiplier;
0504 check = characterizeEdge45(pt2, pt3);
0505
0506 vertex.count[check.first] += check.second * multiplier;
0507 output.push_back(vertex);
0508 return vertex.count.is_45();
0509 }
0510
0511 template <typename Unit>
0512 inline void polygon_45_set_data<Unit>::insert_vertex_half_edge_45_pair(const point_data<Unit>& pt1, point_data<Unit>& pt2,
0513 const point_data<Unit>& pt3,
0514 direction_1d wdir) {
0515 if(insert_vertex_half_edge_45_pair_into_vector(data_, pt1, pt2, pt3, wdir)) is_manhattan_ = false;
0516 }
0517
0518 template <typename Unit>
0519 template <class iT>
0520 inline void polygon_45_set_data<Unit>::insert_vertex_sequence(iT begin_vertex, iT end_vertex,
0521 direction_1d winding, bool is_hole) {
0522 if(begin_vertex == end_vertex) return;
0523 if(is_hole) winding = winding.backward();
0524 iT itr = begin_vertex;
0525 if(itr == end_vertex) return;
0526 point_data<Unit> firstPt = *itr;
0527 ++itr;
0528 point_data<Unit> secondPt(firstPt);
0529
0530 do {
0531 if(itr == end_vertex) return;
0532 secondPt = *itr;
0533 ++itr;
0534 } while(secondPt == firstPt);
0535 point_data<Unit> prevPt = secondPt;
0536 point_data<Unit> prevPrevPt = firstPt;
0537 while(itr != end_vertex) {
0538 point_data<Unit> pt = *itr;
0539
0540 if(pt == prevPt) {
0541 ++itr;
0542 continue;
0543 }
0544
0545 insert_vertex_half_edge_45_pair(prevPrevPt, prevPt, pt, winding);
0546 prevPrevPt = prevPt;
0547 prevPt = pt;
0548 ++itr;
0549 }
0550 if(prevPt != firstPt) {
0551 insert_vertex_half_edge_45_pair(prevPrevPt, prevPt, firstPt, winding);
0552 insert_vertex_half_edge_45_pair(prevPt, firstPt, secondPt, winding);
0553 } else {
0554 insert_vertex_half_edge_45_pair(prevPrevPt, firstPt, secondPt, winding);
0555 }
0556 dirty_ = true;
0557 unsorted_ = true;
0558 }
0559
0560
0561 template <typename Unit>
0562 inline void polygon_45_set_data<Unit>::insert(const polygon_45_set_data<Unit>& polygon_set, bool is_hole) {
0563 std::size_t count = data_.size();
0564 data_.insert(data_.end(), polygon_set.data_.begin(), polygon_set.data_.end());
0565 error_data_.insert(error_data_.end(), polygon_set.error_data_.begin(),
0566 polygon_set.error_data_.end());
0567 if(is_hole) {
0568 for(std::size_t i = count; i < data_.size(); ++i) {
0569 data_[i].count = data_[i].count.invert();
0570 }
0571 }
0572 dirty_ = true;
0573 unsorted_ = true;
0574 if(polygon_set.is_manhattan_ == false) is_manhattan_ = false;
0575 return;
0576 }
0577
0578 template <typename Unit>
0579 template <typename coord_type>
0580 inline void polygon_45_set_data<Unit>::insert(const polygon_45_set_data<coord_type>& polygon_set, bool is_hole) {
0581 std::size_t count = data_.size();
0582 for(typename polygon_45_set_data<coord_type>::iterator_type itr = polygon_set.begin();
0583 itr != polygon_set.end(); ++itr) {
0584 const typename polygon_45_set_data<coord_type>::Vertex45Compact& v = *itr;
0585 typename polygon_45_set_data<Unit>::Vertex45Compact v2;
0586 v2.pt.x(static_cast<Unit>(v.pt.x()));
0587 v2.pt.y(static_cast<Unit>(v.pt.y()));
0588 v2.count = typename polygon_45_formation<Unit>::Vertex45Count(v.count[0], v.count[1], v.count[2], v.count[3]);
0589 data_.push_back(v2);
0590 }
0591 polygon_45_set_data<coord_type> tmp;
0592 polygon_set.get_error_data(tmp);
0593 for(typename polygon_45_set_data<coord_type>::iterator_type itr = tmp.begin();
0594 itr != tmp.end(); ++itr) {
0595 const typename polygon_45_set_data<coord_type>::Vertex45Compact& v = *itr;
0596 typename polygon_45_set_data<Unit>::Vertex45Compact v2;
0597 v2.pt.x(static_cast<Unit>(v.pt.x()));
0598 v2.pt.y(static_cast<Unit>(v.pt.y()));
0599 v2.count = typename polygon_45_formation<Unit>::Vertex45Count(v.count[0], v.count[1], v.count[2], v.count[3]);
0600 error_data_.push_back(v2);
0601 }
0602 if(is_hole) {
0603 for(std::size_t i = count; i < data_.size(); ++i) {
0604 data_[i].count = data_[i].count.invert();
0605 }
0606 }
0607 dirty_ = true;
0608 unsorted_ = true;
0609 if(polygon_set.is_manhattan() == false) is_manhattan_ = false;
0610 return;
0611 }
0612
0613 template <typename cT, typename rT>
0614 void insert_rectangle_into_vector_45(cT& output, const rT& rect, bool is_hole) {
0615 point_data<typename rectangle_traits<rT>::coordinate_type>
0616 llpt = ll(rect), lrpt = lr(rect), ulpt = ul(rect), urpt = ur(rect);
0617 direction_1d dir = COUNTERCLOCKWISE;
0618 if(is_hole) dir = CLOCKWISE;
0619 insert_vertex_half_edge_45_pair_into_vector(output, llpt, lrpt, urpt, dir);
0620 insert_vertex_half_edge_45_pair_into_vector(output, lrpt, urpt, ulpt, dir);
0621 insert_vertex_half_edge_45_pair_into_vector(output, urpt, ulpt, llpt, dir);
0622 insert_vertex_half_edge_45_pair_into_vector(output, ulpt, llpt, lrpt, dir);
0623 }
0624
0625 template <typename Unit>
0626 template <typename geometry_type>
0627 inline void polygon_45_set_data<Unit>::insert_dispatch(const geometry_type& geometry_object,
0628 bool is_hole, rectangle_concept ) {
0629 dirty_ = true;
0630 unsorted_ = true;
0631 insert_rectangle_into_vector_45(data_, geometry_object, is_hole);
0632 }
0633
0634
0635 template <typename Unit>
0636 template <typename rectangle_type>
0637 inline bool polygon_45_set_data<Unit>::extents(rectangle_type& rect) const{
0638 clean();
0639 if(empty()) {
0640 return false;
0641 }
0642 Unit low = (std::numeric_limits<Unit>::max)();
0643 Unit high = (std::numeric_limits<Unit>::min)();
0644 interval_data<Unit> xivl(low, high);
0645 interval_data<Unit> yivl(low, high);
0646 for(typename value_type::const_iterator itr = data_.begin();
0647 itr != data_.end(); ++ itr) {
0648 if((*itr).pt.x() > xivl.get(HIGH))
0649 xivl.set(HIGH, (*itr).pt.x());
0650 if((*itr).pt.x() < xivl.get(LOW))
0651 xivl.set(LOW, (*itr).pt.x());
0652 if((*itr).pt.y() > yivl.get(HIGH))
0653 yivl.set(HIGH, (*itr).pt.y());
0654 if((*itr).pt.y() < yivl.get(LOW))
0655 yivl.set(LOW, (*itr).pt.y());
0656 }
0657 rect = construct<rectangle_type>(xivl, yivl);
0658 return true;
0659 }
0660
0661
0662
0663
0664 template <typename Unit>
0665 inline void polygon_45_set_data<Unit>::snap_vertex_45(typename polygon_45_set_data<Unit>::Vertex45Compact& vertex) {
0666 bool plus45 = vertex.count[2] != 0;
0667 bool minus45 = vertex.count[0] != 0;
0668 if(plus45 || minus45) {
0669 if(local_abs(vertex.pt.x()) % 2 != local_abs(vertex.pt.y()) % 2) {
0670 if(vertex.count[1] != 0 ||
0671 (plus45 && minus45)) {
0672
0673 vertex.pt.x(vertex.pt.x() + 1);
0674 } else {
0675
0676 Unit modifier = plus45 ? -1 : 1;
0677 vertex.pt.y(vertex.pt.y() + modifier);
0678 }
0679 }
0680 }
0681 }
0682
0683 template <typename Unit>
0684 inline void polygon_45_set_data<Unit>::snap() const {
0685 for(typename value_type::iterator itr = data_.begin();
0686 itr != data_.end(); ++itr) {
0687 snap_vertex_45(*itr);
0688 }
0689 }
0690
0691
0692 template <typename Unit>
0693 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator|=(const polygon_45_set_data<Unit>& b) {
0694 insert(b);
0695 return *this;
0696 }
0697 template <typename Unit>
0698 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator&=(const polygon_45_set_data<Unit>& b) {
0699
0700
0701 applyAdaptiveBoolean_<1>(b);
0702 dirty_ = false;
0703 unsorted_ = false;
0704 return *this;
0705 }
0706 template <typename Unit>
0707 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator+=(const polygon_45_set_data<Unit>& b) {
0708 return (*this) |= b;
0709 }
0710 template <typename Unit>
0711 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator*=(const polygon_45_set_data<Unit>& b) {
0712 return (*this) &= b;
0713 }
0714 template <typename Unit>
0715 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator-=(const polygon_45_set_data<Unit>& b) {
0716
0717
0718 applyAdaptiveBoolean_<2>(b);
0719 dirty_ = false;
0720 unsorted_ = false;
0721 return *this;
0722 }
0723 template <typename Unit>
0724 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator^=(const polygon_45_set_data<Unit>& b) {
0725
0726
0727 applyAdaptiveBoolean_<3>(b);
0728 dirty_ = false;
0729 unsorted_ = false;
0730 return *this;
0731 }
0732
0733 template <typename Unit>
0734 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator+=(Unit delta) {
0735 return resize(delta);
0736 }
0737 template <typename Unit>
0738 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::operator-=(Unit delta) {
0739 return (*this) += -delta;
0740 }
0741
0742 template <typename Unit>
0743 inline polygon_45_set_data<Unit>&
0744 polygon_45_set_data<Unit>::resize(Unit resizing, RoundingOption rounding, CornerOption corner) {
0745 if(resizing == 0) return *this;
0746 std::list<polygon_45_with_holes_data<Unit> > pl;
0747 get_polygons_with_holes(pl);
0748 clear();
0749 for(typename std::list<polygon_45_with_holes_data<Unit> >::iterator itr = pl.begin(); itr != pl.end(); ++itr) {
0750 insert_with_resize(*itr, resizing, rounding, corner);
0751 }
0752 clean();
0753
0754
0755 return *this;
0756 }
0757
0758
0759 inline int roundClosest(double distance) {
0760 int f = (int)distance;
0761 if(distance - (double)f < 0.5) return f;
0762 return f+1;
0763 }
0764
0765
0766 template <typename Unit>
0767 inline Unit roundWithOptions(double distance, RoundingOption rounding) {
0768 if(rounding == CLOSEST) {
0769 return roundClosest(distance);
0770 } else if(rounding == OVERSIZE) {
0771 return (Unit)distance + 1;
0772 } else {
0773 return (Unit)distance;
0774 }
0775 }
0776
0777
0778
0779 template <typename Unit>
0780 inline point_data<Unit> bloatVertexInDirWithOptions(const point_data<Unit>& point, unsigned int dir,
0781 Unit bloating, RoundingOption rounding) {
0782 const double sqrt2 = 1.4142135623730950488016887242097;
0783 if(dir & 1) {
0784 Unit unitDistance = (Unit)bloating;
0785 if(rounding != SQRT2) {
0786
0787 double distance = (double)bloating;
0788 distance /= sqrt2;
0789 unitDistance = roundWithOptions<Unit>(distance, rounding);
0790 }
0791 int xMultiplier = 1;
0792 int yMultiplier = 1;
0793 if(dir == 3 || dir == 5) xMultiplier = -1;
0794 if(dir == 5 || dir == 7) yMultiplier = -1;
0795 return point_data<Unit>(point.x()+xMultiplier*unitDistance,
0796 point.y()+yMultiplier*unitDistance);
0797 } else {
0798 if(dir == 0)
0799 return point_data<Unit>(point.x()+bloating, point.y());
0800 if(dir == 2)
0801 return point_data<Unit>(point.x(), point.y()+bloating);
0802 if(dir == 4)
0803 return point_data<Unit>(point.x()-bloating, point.y());
0804 if(dir == 6)
0805 return point_data<Unit>(point.x(), point.y()-bloating);
0806 return point_data<Unit>();
0807 }
0808 }
0809
0810 template <typename Unit>
0811 inline unsigned int getEdge45Direction(const point_data<Unit>& pt1, const point_data<Unit>& pt2) {
0812 if(pt1.x() == pt2.x()) {
0813 if(pt1.y() < pt2.y()) return 2;
0814 return 6;
0815 }
0816 if(pt1.y() == pt2.y()) {
0817 if(pt1.x() < pt2.x()) return 0;
0818 return 4;
0819 }
0820 if(pt2.y() > pt1.y()) {
0821 if(pt2.x() > pt1.x()) return 1;
0822 return 3;
0823 }
0824 if(pt2.x() > pt1.x()) return 7;
0825 return 5;
0826 }
0827
0828 inline unsigned int getEdge45NormalDirection(unsigned int dir, int multiplier) {
0829 if(multiplier < 0)
0830 return (dir + 2) % 8;
0831 return (dir + 4 + 2) % 8;
0832 }
0833
0834 template <typename Unit>
0835 inline point_data<Unit> getIntersectionPoint(const point_data<Unit>& pt1, unsigned int slope1,
0836 const point_data<Unit>& pt2, unsigned int slope2) {
0837
0838
0839
0840
0841 typedef typename coordinate_traits<Unit>::area_type LongUnit;
0842 const Unit rises[8] = {0, 1, 1, 1, 0, -1, -1, -1};
0843 const Unit runs[8] = {1, 1, 0, -1, -1, -1, 0, 1};
0844 LongUnit rise1 = rises[slope1];
0845 LongUnit rise2 = rises[slope2];
0846 LongUnit run1 = runs[slope1];
0847 LongUnit run2 = runs[slope2];
0848 LongUnit x1 = (LongUnit)pt1.x();
0849 LongUnit x2 = (LongUnit)pt2.x();
0850 LongUnit y1 = (LongUnit)pt1.y();
0851 LongUnit y2 = (LongUnit)pt2.y();
0852 Unit x = 0;
0853 Unit y = 0;
0854 if(run1 == 0) {
0855 x = pt1.x();
0856 y = (Unit)(((x1 - x2) * rise2) / run2) + pt2.y();
0857 } else if(run2 == 0) {
0858 x = pt2.x();
0859 y = (Unit)(((x2 - x1) * rise1) / run1) + pt1.y();
0860 } else {
0861
0862
0863
0864
0865
0866
0867 x = (Unit)((y2 - y1 + ((rise1 * x1) / run1) - ((rise2 * x2) / run2)) *
0868 (run1 * run2) / (rise1 * run2 - rise2 * run1));
0869 if(rise1 == 0) {
0870 y = pt1.y();
0871 } else if(rise2 == 0) {
0872 y = pt2.y();
0873 } else {
0874
0875
0876
0877 y = (Unit)((x2 - x1 + ((run1 * y1) / rise1) - ((run2 * y2) / rise2)) *
0878 (rise1 * rise2) / (run1 * rise2 - run2 * rise1));
0879 }
0880 }
0881 return point_data<Unit>(x, y);
0882 }
0883
0884 template <typename Unit>
0885 inline
0886 void handleResizingEdge45_SQRT1OVER2(polygon_45_set_data<Unit>& sizingSet, point_data<Unit> first,
0887 point_data<Unit> second, Unit resizing, CornerOption corner) {
0888 if(first.x() == second.x()) {
0889 sizingSet.insert(rectangle_data<Unit>(first.x() - resizing, first.y(), first.x() + resizing, second.y()));
0890 return;
0891 }
0892 if(first.y() == second.y()) {
0893 sizingSet.insert(rectangle_data<Unit>(first.x(), first.y() - resizing, second.x(), first.y() + resizing));
0894 return;
0895 }
0896 std::vector<point_data<Unit> > pts;
0897 Unit bloating = resizing < 0 ? -resizing : resizing;
0898 if(corner == UNFILLED) {
0899
0900 bloating = bloating / 2 + bloating % 2 ;
0901 if(second.x() < first.x()) std::swap(first, second);
0902 if(first.y() < second.y()) {
0903 pts.push_back(point_data<Unit>(first.x() + bloating, first.y() - bloating));
0904 pts.push_back(point_data<Unit>(first.x() - bloating, first.y() + bloating));
0905 pts.push_back(point_data<Unit>(second.x() - bloating, second.y() + bloating));
0906 pts.push_back(point_data<Unit>(second.x() + bloating, second.y() - bloating));
0907 sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), CLOCKWISE, false);
0908 } else {
0909 pts.push_back(point_data<Unit>(first.x() + bloating, first.y() + bloating));
0910 pts.push_back(point_data<Unit>(first.x() - bloating, first.y() - bloating));
0911 pts.push_back(point_data<Unit>(second.x() - bloating, second.y() - bloating));
0912 pts.push_back(point_data<Unit>(second.x() + bloating, second.y() + bloating));
0913 sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), COUNTERCLOCKWISE, false);
0914 }
0915 return;
0916 }
0917 if(second.x() < first.x()) std::swap(first, second);
0918 if(first.y() < second.y()) {
0919 pts.push_back(point_data<Unit>(first.x(), first.y() - bloating));
0920 pts.push_back(point_data<Unit>(first.x() - bloating, first.y()));
0921 pts.push_back(point_data<Unit>(second.x(), second.y() + bloating));
0922 pts.push_back(point_data<Unit>(second.x() + bloating, second.y()));
0923 sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), CLOCKWISE, false);
0924 } else {
0925 pts.push_back(point_data<Unit>(first.x() - bloating, first.y()));
0926 pts.push_back(point_data<Unit>(first.x(), first.y() + bloating));
0927 pts.push_back(point_data<Unit>(second.x() + bloating, second.y()));
0928 pts.push_back(point_data<Unit>(second.x(), second.y() - bloating));
0929 sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), CLOCKWISE, false);
0930 }
0931 }
0932
0933
0934 template <typename Unit>
0935 inline
0936 void handleResizingEdge45(polygon_45_set_data<Unit>& sizingSet, point_data<Unit> first,
0937 point_data<Unit> second, Unit resizing, RoundingOption rounding) {
0938 if(first.x() == second.x()) {
0939 sizingSet.insert(rectangle_data<int>(first.x() - resizing, first.y(), first.x() + resizing, second.y()));
0940 return;
0941 }
0942 if(first.y() == second.y()) {
0943 sizingSet.insert(rectangle_data<int>(first.x(), first.y() - resizing, second.x(), first.y() + resizing));
0944 return;
0945 }
0946
0947 std::vector<point_data<Unit> > pts;
0948 Unit bloating = resizing < 0 ? -resizing : resizing;
0949 if(second.x() < first.x()) std::swap(first, second);
0950 if(first.y() < second.y()) {
0951 pts.push_back(bloatVertexInDirWithOptions(first, 3, bloating, rounding));
0952 pts.push_back(bloatVertexInDirWithOptions(first, 7, bloating, rounding));
0953 pts.push_back(bloatVertexInDirWithOptions(second, 7, bloating, rounding));
0954 pts.push_back(bloatVertexInDirWithOptions(second, 3, bloating, rounding));
0955 sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), HIGH, false);
0956 } else {
0957 pts.push_back(bloatVertexInDirWithOptions(first, 1, bloating, rounding));
0958 pts.push_back(bloatVertexInDirWithOptions(first, 5, bloating, rounding));
0959 pts.push_back(bloatVertexInDirWithOptions(second, 5, bloating, rounding));
0960 pts.push_back(bloatVertexInDirWithOptions(second, 1, bloating, rounding));
0961 sizingSet.insert_vertex_sequence(pts.begin(), pts.end(), HIGH, false);
0962 }
0963 }
0964
0965 template <typename Unit>
0966 inline point_data<Unit> bloatVertexInDirWithSQRT1OVER2(int edge1, int normal1, const point_data<Unit>& second, Unit bloating,
0967 bool first) {
0968 orientation_2d orient = first ? HORIZONTAL : VERTICAL;
0969 orientation_2d orientp = orient.get_perpendicular();
0970 int multiplier = first ? 1 : -1;
0971 point_data<Unit> pt1(second);
0972 if(edge1 == 1) {
0973 if(normal1 == 3) {
0974 move(pt1, orient, -multiplier * bloating);
0975 } else {
0976 move(pt1, orientp, -multiplier * bloating);
0977 }
0978 } else if(edge1 == 3) {
0979 if(normal1 == 1) {
0980 move(pt1, orient, multiplier * bloating);
0981 } else {
0982 move(pt1, orientp, -multiplier * bloating);
0983 }
0984 } else if(edge1 == 5) {
0985 if(normal1 == 3) {
0986 move(pt1, orientp, multiplier * bloating);
0987 } else {
0988 move(pt1, orient, multiplier * bloating);
0989 }
0990 } else {
0991 if(normal1 == 5) {
0992 move(pt1, orient, -multiplier * bloating);
0993 } else {
0994 move(pt1, orientp, multiplier * bloating);
0995 }
0996 }
0997 return pt1;
0998 }
0999
1000 template <typename Unit>
1001 inline
1002 void handleResizingVertex45(polygon_45_set_data<Unit>& sizingSet, const point_data<Unit>& first,
1003 const point_data<Unit>& second, const point_data<Unit>& third, Unit resizing,
1004 RoundingOption rounding, CornerOption corner,
1005 int multiplier) {
1006 unsigned int edge1 = getEdge45Direction(first, second);
1007 unsigned int edge2 = getEdge45Direction(second, third);
1008 unsigned int diffAngle;
1009 if(multiplier < 0)
1010 diffAngle = (edge2 + 8 - edge1) % 8;
1011 else
1012 diffAngle = (edge1 + 8 - edge2) % 8;
1013 if(diffAngle < 4) {
1014 if(resizing > 0) return;
1015 else multiplier *= -1;
1016 }
1017 Unit bloating = local_abs(resizing);
1018 if(rounding == SQRT1OVER2) {
1019 if(edge1 % 2 && edge2 % 2) return;
1020 if(corner == ORTHOGONAL && edge1 % 2 == 0 && edge2 % 2 == 0) {
1021 rectangle_data<Unit> insertion_rect;
1022 set_points(insertion_rect, second, second);
1023 bloat(insertion_rect, bloating);
1024 sizingSet.insert(insertion_rect);
1025 } else if(corner != ORTHOGONAL) {
1026 point_data<Unit> pt1(0, 0);
1027 point_data<Unit> pt2(0, 0);
1028 unsigned int normal1 = getEdge45NormalDirection(edge1, multiplier);
1029 unsigned int normal2 = getEdge45NormalDirection(edge2, multiplier);
1030 if(edge1 % 2) {
1031 pt1 = bloatVertexInDirWithSQRT1OVER2(edge1, normal1, second, bloating, true);
1032 } else {
1033 pt1 = bloatVertexInDirWithOptions(second, normal1, bloating, UNDERSIZE);
1034 }
1035 if(edge2 % 2) {
1036 pt2 = bloatVertexInDirWithSQRT1OVER2(edge2, normal2, second, bloating, false);
1037 } else {
1038 pt2 = bloatVertexInDirWithOptions(second, normal2, bloating, UNDERSIZE);
1039 }
1040 std::vector<point_data<Unit> > pts;
1041 pts.push_back(pt1);
1042 pts.push_back(second);
1043 pts.push_back(pt2);
1044 pts.push_back(getIntersectionPoint(pt1, edge1, pt2, edge2));
1045 polygon_45_data<Unit> poly(pts.begin(), pts.end());
1046 sizingSet.insert(poly);
1047 } else {
1048
1049 int normal = 0;
1050 if(edge1 % 2) {
1051 normal = getEdge45NormalDirection(edge2, multiplier);
1052 } else {
1053 normal = getEdge45NormalDirection(edge1, multiplier);
1054 }
1055 rectangle_data<Unit> insertion_rect;
1056 point_data<Unit> edgePoint = bloatVertexInDirWithOptions(second, normal, bloating, UNDERSIZE);
1057 set_points(insertion_rect, second, edgePoint);
1058 if(normal == 0 || normal == 4)
1059 bloat(insertion_rect, VERTICAL, bloating);
1060 else
1061 bloat(insertion_rect, HORIZONTAL, bloating);
1062 sizingSet.insert(insertion_rect);
1063 }
1064 return;
1065 }
1066 unsigned int normal1 = getEdge45NormalDirection(edge1, multiplier);
1067 unsigned int normal2 = getEdge45NormalDirection(edge2, multiplier);
1068 point_data<Unit> edgePoint1 = bloatVertexInDirWithOptions(second, normal1, bloating, rounding);
1069 point_data<Unit> edgePoint2 = bloatVertexInDirWithOptions(second, normal2, bloating, rounding);
1070
1071 if((edge1+ multiplier * 3) % 8 == edge2) {
1072 if(corner == ORTHOGONAL) {
1073 rectangle_data<Unit> insertion_rect;
1074 set_points(insertion_rect, edgePoint1, edgePoint2);
1075 sizingSet.insert(insertion_rect);
1076 return;
1077 }
1078 }
1079 std::vector<point_data<Unit> > pts;
1080 pts.push_back(edgePoint1);
1081 pts.push_back(second);
1082 pts.push_back(edgePoint2);
1083 pts.push_back(getIntersectionPoint(edgePoint1, edge1, edgePoint2, edge2));
1084 polygon_45_data<Unit> poly(pts.begin(), pts.end());
1085 sizingSet.insert(poly);
1086 }
1087
1088 template <typename Unit>
1089 template <typename geometry_type>
1090 inline polygon_45_set_data<Unit>&
1091 polygon_45_set_data<Unit>::insert_with_resize_dispatch(const geometry_type& poly,
1092 coordinate_type resizing,
1093 RoundingOption rounding,
1094 CornerOption corner,
1095 bool hole, polygon_45_concept ) {
1096 direction_1d wdir = winding(poly);
1097 int multiplier = wdir == LOW ? -1 : 1;
1098 if(hole) resizing *= -1;
1099 typedef typename polygon_45_data<Unit>::iterator_type piterator;
1100 piterator first, second, third, end, real_end;
1101 real_end = end_points(poly);
1102 third = begin_points(poly);
1103 first = third;
1104 if(first == real_end) return *this;
1105 ++third;
1106 if(third == real_end) return *this;
1107 second = end = third;
1108 ++third;
1109 if(third == real_end) return *this;
1110 polygon_45_set_data<Unit> sizingSet;
1111
1112 do {
1113 if(rounding != SQRT1OVER2) {
1114 handleResizingEdge45(sizingSet, *first, *second, resizing, rounding);
1115 } else {
1116 handleResizingEdge45_SQRT1OVER2(sizingSet, *first, *second, resizing, corner);
1117 }
1118 if(corner != UNFILLED)
1119 handleResizingVertex45(sizingSet, *first, *second, *third, resizing, rounding, corner, multiplier);
1120 first = second;
1121 second = third;
1122 ++third;
1123 if(third == real_end) {
1124 third = begin_points(poly);
1125 if(*second == *third) {
1126 ++third;
1127 }
1128 }
1129 } while(second != end);
1130
1131 polygon_45_set_data<Unit> tmp;
1132
1133 tmp.insert_dispatch(poly, false, polygon_45_concept());
1134 if(resizing < 0) tmp -= sizingSet;
1135 else tmp += sizingSet;
1136 tmp.clean();
1137 insert(tmp, hole);
1138 dirty_ = true;
1139 unsorted_ = true;
1140 return (*this);
1141 }
1142
1143
1144 template <typename Unit>
1145 template <typename geometry_type>
1146 inline polygon_45_set_data<Unit>&
1147 polygon_45_set_data<Unit>::insert_with_resize_dispatch(const geometry_type& poly,
1148 coordinate_type resizing,
1149 RoundingOption rounding,
1150 CornerOption corner,
1151 bool hole, polygon_45_with_holes_concept ) {
1152 insert_with_resize_dispatch(poly, resizing, rounding, corner, hole, polygon_45_concept());
1153 for(typename polygon_with_holes_traits<geometry_type>::iterator_holes_type itr =
1154 begin_holes(poly); itr != end_holes(poly);
1155 ++itr) {
1156 insert_with_resize_dispatch(*itr, resizing, rounding, corner, !hole, polygon_45_concept());
1157 }
1158 return *this;
1159 }
1160
1161
1162 template <typename Unit>
1163 template <typename transformation_type>
1164 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::transform(const transformation_type& tr){
1165 clean();
1166 std::vector<polygon_45_with_holes_data<Unit> > polys;
1167 get(polys);
1168 for(typename std::vector<polygon_45_with_holes_data<Unit> >::iterator itr = polys.begin();
1169 itr != polys.end(); ++itr) {
1170 ::boost::polygon::transform(*itr, tr);
1171 }
1172 clear();
1173 insert(polys.begin(), polys.end());
1174 dirty_ = true;
1175 unsorted_ = true;
1176 return *this;
1177 }
1178
1179 template <typename Unit>
1180 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::scale_up(typename coordinate_traits<Unit>::unsigned_area_type factor) {
1181 scale_up_vertex_45_compact_range(data_.begin(), data_.end(), factor);
1182 return *this;
1183 }
1184
1185 template <typename Unit>
1186 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::scale_down(typename coordinate_traits<Unit>::unsigned_area_type factor) {
1187 clean();
1188 std::vector<polygon_45_with_holes_data<Unit> > polys;
1189 get_polygons_with_holes(polys);
1190 for(typename std::vector<polygon_45_with_holes_data<Unit> >::iterator itr = polys.begin();
1191 itr != polys.end(); ++itr) {
1192 ::boost::polygon::scale_down(*itr, factor);
1193 }
1194 clear();
1195 insert(polys.begin(), polys.end());
1196 dirty_ = true;
1197 unsorted_ = true;
1198 return *this;
1199 }
1200
1201 template <typename Unit>
1202 inline polygon_45_set_data<Unit>& polygon_45_set_data<Unit>::scale(double factor) {
1203 clean();
1204 std::vector<polygon_45_with_holes_data<Unit> > polys;
1205 get_polygons_with_holes(polys);
1206 for(typename std::vector<polygon_45_with_holes_data<Unit> >::iterator itr = polys.begin();
1207 itr != polys.end(); ++itr) {
1208 ::boost::polygon::scale(*itr, factor);
1209 }
1210 clear();
1211 insert(polys.begin(), polys.end());
1212 dirty_ = true;
1213 unsorted_ = true;
1214 return *this;
1215 }
1216
1217 template <typename Unit>
1218 inline bool polygon_45_set_data<Unit>::clean() const {
1219 if(unsorted_) sort();
1220 if(dirty_) {
1221 applyAdaptiveUnary_<0>();
1222 dirty_ = false;
1223 }
1224 return true;
1225 }
1226
1227 template <typename Unit>
1228 template <int op>
1229 inline void polygon_45_set_data<Unit>::applyAdaptiveBoolean_(const polygon_45_set_data<Unit>& rvalue) const {
1230 polygon_45_set_data<Unit> tmp;
1231 applyAdaptiveBoolean_<op>(tmp, rvalue);
1232 data_.swap(tmp.data_);
1233 error_data_.swap(tmp.error_data_);
1234 is_manhattan_ = tmp.is_manhattan_;
1235 unsorted_ = false;
1236 dirty_ = false;
1237 }
1238
1239 template <typename Unit2, int op>
1240 bool applyBoolean45OpOnVectors(std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& result_data,
1241 std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& lvalue_data,
1242 std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& rvalue_data
1243 ) {
1244 bool result_is_manhattan_ = true;
1245 typename boolean_op_45<Unit2>::template Scan45<typename boolean_op_45<Unit2>::Count2,
1246 typename boolean_op_45<Unit2>::template boolean_op_45_output_functor<op> > scan45;
1247 std::vector<typename boolean_op_45<Unit2>::Vertex45> eventOut;
1248 typedef std::pair<typename boolean_op_45<Unit2>::Point,
1249 typename boolean_op_45<Unit2>::template Scan45CountT<typename boolean_op_45<Unit2>::Count2> > Scan45Vertex;
1250 std::vector<Scan45Vertex> eventIn;
1251 typedef std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact> value_type;
1252 typename value_type::const_iterator iter1 = lvalue_data.begin();
1253 typename value_type::const_iterator iter2 = rvalue_data.begin();
1254 typename value_type::const_iterator end1 = lvalue_data.end();
1255 typename value_type::const_iterator end2 = rvalue_data.end();
1256 const Unit2 UnitMax = (std::numeric_limits<Unit2>::max)();
1257 Unit2 x = UnitMax;
1258 while(iter1 != end1 || iter2 != end2) {
1259 Unit2 currentX = UnitMax;
1260 if(iter1 != end1) currentX = iter1->pt.x();
1261 if(iter2 != end2) currentX = (std::min)(currentX, iter2->pt.x());
1262 if(currentX != x) {
1263
1264
1265 scan45.scan(eventOut, eventIn.begin(), eventIn.end());
1266 polygon_sort(eventOut.begin(), eventOut.end());
1267 std::size_t ptCount = 0;
1268 for(std::size_t i = 0; i < eventOut.size(); ++i) {
1269 if(!result_data.empty() &&
1270 result_data.back().pt == eventOut[i].pt) {
1271 result_data.back().count += eventOut[i];
1272 ++ptCount;
1273 } else {
1274 if(!result_data.empty()) {
1275 if(result_data.back().count.is_45()) {
1276 result_is_manhattan_ = false;
1277 }
1278 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
1279 result_data.pop_back();
1280 }
1281 }
1282 result_data.push_back(eventOut[i]);
1283 ptCount = 1;
1284 }
1285 }
1286 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
1287 result_data.pop_back();
1288 }
1289 eventOut.clear();
1290 eventIn.clear();
1291 x = currentX;
1292 }
1293
1294 if(iter2 != end2 && (iter1 == end1 || iter2->pt.x() < iter1->pt.x() ||
1295 (iter2->pt.x() == iter1->pt.x() &&
1296 iter2->pt.y() < iter1->pt.y()) )) {
1297
1298 eventIn.push_back(Scan45Vertex
1299 (iter2->pt,
1300 typename polygon_45_formation<Unit2>::
1301 Scan45Count(typename polygon_45_formation<Unit2>::Count2(0, iter2->count[0]),
1302 typename polygon_45_formation<Unit2>::Count2(0, iter2->count[1]),
1303 typename polygon_45_formation<Unit2>::Count2(0, iter2->count[2]),
1304 typename polygon_45_formation<Unit2>::Count2(0, iter2->count[3]))));
1305 ++iter2;
1306 } else if(iter1 != end1 && (iter2 == end2 || iter1->pt.x() < iter2->pt.x() ||
1307 (iter1->pt.x() == iter2->pt.x() &&
1308 iter1->pt.y() < iter2->pt.y()) )) {
1309
1310 eventIn.push_back(Scan45Vertex
1311 (iter1->pt,
1312 typename polygon_45_formation<Unit2>::
1313 Scan45Count(
1314 typename polygon_45_formation<Unit2>::Count2(iter1->count[0], 0),
1315 typename polygon_45_formation<Unit2>::Count2(iter1->count[1], 0),
1316 typename polygon_45_formation<Unit2>::Count2(iter1->count[2], 0),
1317 typename polygon_45_formation<Unit2>::Count2(iter1->count[3], 0))));
1318 ++iter1;
1319 } else {
1320
1321 eventIn.push_back(Scan45Vertex
1322 (iter2->pt,
1323 typename polygon_45_formation<Unit2>::
1324 Scan45Count(typename polygon_45_formation<Unit2>::Count2(iter1->count[0],
1325 iter2->count[0]),
1326 typename polygon_45_formation<Unit2>::Count2(iter1->count[1],
1327 iter2->count[1]),
1328 typename polygon_45_formation<Unit2>::Count2(iter1->count[2],
1329 iter2->count[2]),
1330 typename polygon_45_formation<Unit2>::Count2(iter1->count[3],
1331 iter2->count[3]))));
1332 ++iter1;
1333 ++iter2;
1334 }
1335 }
1336 scan45.scan(eventOut, eventIn.begin(), eventIn.end());
1337 polygon_sort(eventOut.begin(), eventOut.end());
1338
1339 std::size_t ptCount = 0;
1340 for(std::size_t i = 0; i < eventOut.size(); ++i) {
1341 if(!result_data.empty() &&
1342 result_data.back().pt == eventOut[i].pt) {
1343 result_data.back().count += eventOut[i];
1344 ++ptCount;
1345 } else {
1346 if(!result_data.empty()) {
1347 if(result_data.back().count.is_45()) {
1348 result_is_manhattan_ = false;
1349 }
1350 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
1351 result_data.pop_back();
1352 }
1353 }
1354 result_data.push_back(eventOut[i]);
1355 ptCount = 1;
1356 }
1357 }
1358 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
1359 result_data.pop_back();
1360 }
1361 if(!result_data.empty() &&
1362 result_data.back().count.is_45()) {
1363 result_is_manhattan_ = false;
1364 }
1365 return result_is_manhattan_;
1366 }
1367
1368 template <typename Unit2, int op>
1369 bool applyUnary45OpOnVectors(std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& result_data,
1370 std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact>& lvalue_data ) {
1371 bool result_is_manhattan_ = true;
1372 typename boolean_op_45<Unit2>::template Scan45<typename boolean_op_45<Unit2>::Count1,
1373 typename boolean_op_45<Unit2>::template unary_op_45_output_functor<op> > scan45;
1374 std::vector<typename boolean_op_45<Unit2>::Vertex45> eventOut;
1375 typedef typename boolean_op_45<Unit2>::template Scan45CountT<typename boolean_op_45<Unit2>::Count1> Scan45Count;
1376 typedef std::pair<typename boolean_op_45<Unit2>::Point, Scan45Count> Scan45Vertex;
1377 std::vector<Scan45Vertex> eventIn;
1378 typedef std::vector<typename polygon_45_formation<Unit2>::Vertex45Compact> value_type;
1379 typename value_type::const_iterator iter1 = lvalue_data.begin();
1380 typename value_type::const_iterator end1 = lvalue_data.end();
1381 const Unit2 UnitMax = (std::numeric_limits<Unit2>::max)();
1382 Unit2 x = UnitMax;
1383 while(iter1 != end1) {
1384 Unit2 currentX = iter1->pt.x();
1385 if(currentX != x) {
1386
1387
1388 scan45.scan(eventOut, eventIn.begin(), eventIn.end());
1389 polygon_sort(eventOut.begin(), eventOut.end());
1390 std::size_t ptCount = 0;
1391 for(std::size_t i = 0; i < eventOut.size(); ++i) {
1392 if(!result_data.empty() &&
1393 result_data.back().pt == eventOut[i].pt) {
1394 result_data.back().count += eventOut[i];
1395 ++ptCount;
1396 } else {
1397 if(!result_data.empty()) {
1398 if(result_data.back().count.is_45()) {
1399 result_is_manhattan_ = false;
1400 }
1401 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
1402 result_data.pop_back();
1403 }
1404 }
1405 result_data.push_back(eventOut[i]);
1406 ptCount = 1;
1407 }
1408 }
1409 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
1410 result_data.pop_back();
1411 }
1412 eventOut.clear();
1413 eventIn.clear();
1414 x = currentX;
1415 }
1416
1417 eventIn.push_back(Scan45Vertex
1418 (iter1->pt,
1419 Scan45Count( typename boolean_op_45<Unit2>::Count1(iter1->count[0]),
1420 typename boolean_op_45<Unit2>::Count1(iter1->count[1]),
1421 typename boolean_op_45<Unit2>::Count1(iter1->count[2]),
1422 typename boolean_op_45<Unit2>::Count1(iter1->count[3]))));
1423 ++iter1;
1424 }
1425 scan45.scan(eventOut, eventIn.begin(), eventIn.end());
1426 polygon_sort(eventOut.begin(), eventOut.end());
1427
1428 std::size_t ptCount = 0;
1429 for(std::size_t i = 0; i < eventOut.size(); ++i) {
1430 if(!result_data.empty() &&
1431 result_data.back().pt == eventOut[i].pt) {
1432 result_data.back().count += eventOut[i];
1433 ++ptCount;
1434 } else {
1435 if(!result_data.empty()) {
1436 if(result_data.back().count.is_45()) {
1437 result_is_manhattan_ = false;
1438 }
1439 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
1440 result_data.pop_back();
1441 }
1442 }
1443 result_data.push_back(eventOut[i]);
1444 ptCount = 1;
1445 }
1446 }
1447 if(ptCount == 2 && result_data.back().count == (typename polygon_45_formation<Unit2>::Vertex45Count(0, 0, 0, 0))) {
1448 result_data.pop_back();
1449 }
1450 if(!result_data.empty() &&
1451 result_data.back().count.is_45()) {
1452 result_is_manhattan_ = false;
1453 }
1454 return result_is_manhattan_;
1455 }
1456
1457 template <typename cT, typename iT>
1458 void get_error_rects_shell(cT& posE, cT& negE, iT beginr, iT endr) {
1459 typedef typename std::iterator_traits<iT>::value_type Point;
1460 typedef typename point_traits<Point>::coordinate_type Unit;
1461 typedef typename coordinate_traits<Unit>::area_type area_type;
1462 Point pt1, pt2, pt3;
1463 bool i1 = true;
1464 bool i2 = true;
1465 bool not_done = beginr != endr;
1466 bool next_to_last = false;
1467 bool last = false;
1468 Point first, second;
1469 while(not_done) {
1470 if(last) {
1471 last = false;
1472 not_done = false;
1473 pt3 = second;
1474 } else if(next_to_last) {
1475 next_to_last = false;
1476 last = true;
1477 pt3 = first;
1478 } else if(i1) {
1479 const Point& pt = *beginr;
1480 first = pt1 = pt;
1481 i1 = false;
1482 i2 = true;
1483 ++beginr;
1484 if(beginr == endr) return;
1485 continue;
1486 } else if (i2) {
1487 const Point& pt = *beginr;
1488 second = pt2 = pt;
1489 i2 = false;
1490 ++beginr;
1491 if(beginr == endr) return;
1492 continue;
1493 } else {
1494 const Point& pt = *beginr;
1495 pt3 = pt;
1496 ++beginr;
1497 if(beginr == endr) {
1498 next_to_last = true;
1499
1500 continue;
1501 }
1502 }
1503 if(local_abs(x(pt2)) % 2) {
1504
1505 Point pts[] = {pt1, pt2, pt3};
1506 area_type ar = point_sequence_area<Point*, area_type>(pts, pts+3);
1507 direction_1d dir = ar < 0 ? COUNTERCLOCKWISE : CLOCKWISE;
1508
1509 if(dir == CLOCKWISE) {
1510 posE.push_back(rectangle_data<typename Point::coordinate_type>
1511 (x(pt2) - 1, y(pt2) - 1, x(pt2) + 1, y(pt2) + 1));
1512
1513 } else {
1514 negE.push_back(rectangle_data<typename Point::coordinate_type>
1515 (x(pt2) - 1, y(pt2) - 1, x(pt2) + 1, y(pt2) + 1));
1516 }
1517 }
1518 pt1 = pt2;
1519 pt2 = pt3;
1520 }
1521 }
1522
1523 template <typename cT, typename pT>
1524 void get_error_rects(cT& posE, cT& negE, const pT& p) {
1525 get_error_rects_shell(posE, negE, p.begin(), p.end());
1526 for(typename pT::iterator_holes_type iHb = p.begin_holes();
1527 iHb != p.end_holes(); ++iHb) {
1528 get_error_rects_shell(posE, negE, iHb->begin(), iHb->end());
1529 }
1530 }
1531
1532 template <typename Unit>
1533 template <int op>
1534 inline void polygon_45_set_data<Unit>::applyAdaptiveBoolean_(polygon_45_set_data<Unit>& result,
1535 const polygon_45_set_data<Unit>& rvalue) const {
1536 result.clear();
1537 result.error_data_ = error_data_;
1538 result.error_data_.insert(result.error_data_.end(), rvalue.error_data_.begin(),
1539 rvalue.error_data_.end());
1540 if(is_manhattan() && rvalue.is_manhattan()) {
1541
1542 polygon_90_set_data<Unit> l90sd(VERTICAL), r90sd(VERTICAL), output(VERTICAL);
1543 for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) {
1544 if((*itr).count[3] == 0) continue;
1545 l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL);
1546 }
1547 for(typename value_type::const_iterator itr = rvalue.data_.begin(); itr != rvalue.data_.end(); ++itr) {
1548 if((*itr).count[3] == 0) continue;
1549 r90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL);
1550 }
1551 l90sd.sort();
1552 r90sd.sort();
1553 #ifdef BOOST_POLYGON_MSVC
1554 #pragma warning (push)
1555 #pragma warning (disable: 4127)
1556 #endif
1557 if(op == 0) {
1558 output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(),
1559 r90sd.begin(), r90sd.end(), boolean_op::BinaryCount<boolean_op::BinaryOr>());
1560 } else if (op == 1) {
1561 output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(),
1562 r90sd.begin(), r90sd.end(), boolean_op::BinaryCount<boolean_op::BinaryAnd>());
1563 } else if (op == 2) {
1564 output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(),
1565 r90sd.begin(), r90sd.end(), boolean_op::BinaryCount<boolean_op::BinaryNot>());
1566 } else if (op == 3) {
1567 output.applyBooleanBinaryOp(l90sd.begin(), l90sd.end(),
1568 r90sd.begin(), r90sd.end(), boolean_op::BinaryCount<boolean_op::BinaryXor>());
1569 }
1570 #ifdef BOOST_POLYGON_MSVC
1571 #pragma warning (pop)
1572 #endif
1573 result.data_.clear();
1574 result.insert(output);
1575 result.is_manhattan_ = true;
1576 result.dirty_ = false;
1577 result.unsorted_ = false;
1578 } else {
1579 sort();
1580 rvalue.sort();
1581 try {
1582 result.is_manhattan_ = applyBoolean45OpOnVectors<Unit, op>(result.data_, data_, rvalue.data_);
1583 } catch (std::string str) {
1584 std::string msg = "GTL 45 Boolean error, precision insufficient to represent edge intersection coordinate value.";
1585 if(str == msg) {
1586 result.clear();
1587 typedef typename coordinate_traits<Unit>::manhattan_area_type Unit2;
1588 typedef typename polygon_45_formation<Unit2>::Vertex45Compact Vertex45Compact2;
1589 typedef std::vector<Vertex45Compact2> Data2;
1590 Data2 rvalue_data, lvalue_data, result_data;
1591 rvalue_data.reserve(rvalue.data_.size());
1592 lvalue_data.reserve(data_.size());
1593 for(std::size_t i = 0 ; i < data_.size(); ++i) {
1594 const Vertex45Compact& vi = data_[i];
1595 Vertex45Compact2 ci;
1596 ci.pt = point_data<Unit2>(x(vi.pt), y(vi.pt));
1597 ci.count = typename polygon_45_formation<Unit2>::Vertex45Count
1598 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
1599 lvalue_data.push_back(ci);
1600 }
1601 for(std::size_t i = 0 ; i < rvalue.data_.size(); ++i) {
1602 const Vertex45Compact& vi = rvalue.data_[i];
1603 Vertex45Compact2 ci;
1604 ci.pt = (point_data<Unit2>(x(vi.pt), y(vi.pt)));
1605 ci.count = typename polygon_45_formation<Unit2>::Vertex45Count
1606 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
1607 rvalue_data.push_back(ci);
1608 }
1609 scale_up_vertex_45_compact_range(lvalue_data.begin(), lvalue_data.end(), 2);
1610 scale_up_vertex_45_compact_range(rvalue_data.begin(), rvalue_data.end(), 2);
1611 bool result_is_manhattan = applyBoolean45OpOnVectors<Unit2, op>(result_data,
1612 lvalue_data,
1613 rvalue_data );
1614 if(!result_is_manhattan) {
1615 typename polygon_45_formation<Unit2>::Polygon45Formation pf(false);
1616
1617 std::vector<polygon_45_with_holes_data<Unit2> > container;
1618 pf.scan(container, result_data.begin(), result_data.end());
1619 Data2 error_data_out;
1620 std::vector<rectangle_data<Unit2> > pos_error_rects;
1621 std::vector<rectangle_data<Unit2> > neg_error_rects;
1622 for(std::size_t i = 0; i < container.size(); ++i) {
1623 get_error_rects(pos_error_rects, neg_error_rects, container[i]);
1624 }
1625 for(std::size_t i = 0; i < pos_error_rects.size(); ++i) {
1626 insert_rectangle_into_vector_45(result_data, pos_error_rects[i], false);
1627 insert_rectangle_into_vector_45(error_data_out, pos_error_rects[i], false);
1628 }
1629 for(std::size_t i = 0; i < neg_error_rects.size(); ++i) {
1630 insert_rectangle_into_vector_45(result_data, neg_error_rects[i], true);
1631 insert_rectangle_into_vector_45(error_data_out, neg_error_rects[i], false);
1632 }
1633 scale_down_vertex_45_compact_range_blindly(error_data_out.begin(), error_data_out.end(), 2);
1634 for(std::size_t i = 0 ; i < error_data_out.size(); ++i) {
1635 const Vertex45Compact2& vi = error_data_out[i];
1636 Vertex45Compact ci;
1637 ci.pt.x(static_cast<Unit>(x(vi.pt)));
1638 ci.pt.y(static_cast<Unit>(y(vi.pt)));
1639 ci.count = typename polygon_45_formation<Unit>::Vertex45Count
1640 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
1641 result.error_data_.push_back(ci);
1642 }
1643 Data2 new_result_data;
1644 polygon_sort(result_data.begin(), result_data.end());
1645 applyUnary45OpOnVectors<Unit2, 0>(new_result_data, result_data);
1646 result_data.swap(new_result_data);
1647 }
1648 scale_down_vertex_45_compact_range_blindly(result_data.begin(), result_data.end(), 2);
1649
1650 for(std::size_t i = 0 ; i < result_data.size(); ++i) {
1651 const Vertex45Compact2& vi = result_data[i];
1652 Vertex45Compact ci;
1653 ci.pt.x(static_cast<Unit>(x(vi.pt)));
1654 ci.pt.y(static_cast<Unit>(y(vi.pt)));
1655 ci.count = typename polygon_45_formation<Unit>::Vertex45Count
1656 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
1657 result.data_.push_back(ci);
1658 }
1659 result.is_manhattan_ = result_is_manhattan;
1660 result.dirty_ = false;
1661 result.unsorted_ = false;
1662 } else { throw str; }
1663 }
1664
1665 }
1666 }
1667
1668 template <typename Unit>
1669 template <int op>
1670 inline void polygon_45_set_data<Unit>::applyAdaptiveUnary_() const {
1671 polygon_45_set_data<Unit> result;
1672 result.error_data_ = error_data_;
1673 if(is_manhattan()) {
1674
1675 polygon_90_set_data<Unit> l90sd(VERTICAL);
1676 for(typename value_type::const_iterator itr = data_.begin(); itr != data_.end(); ++itr) {
1677 if((*itr).count[3] == 0) continue;
1678 l90sd.insert(std::make_pair((*itr).pt.x(), std::make_pair<Unit, int>((*itr).pt.y(), (*itr).count[3])), false, VERTICAL);
1679 }
1680 l90sd.sort();
1681 #ifdef BOOST_POLYGON_MSVC
1682 #pragma warning (push)
1683 #pragma warning (disable: 4127)
1684 #endif
1685 if(op == 0) {
1686 l90sd.clean();
1687 } else if (op == 1) {
1688 l90sd.self_intersect();
1689 } else if (op == 3) {
1690 l90sd.self_xor();
1691 }
1692 #ifdef BOOST_POLYGON_MSVC
1693 #pragma warning (pop)
1694 #endif
1695 result.data_.clear();
1696 result.insert(l90sd);
1697 result.is_manhattan_ = true;
1698 result.dirty_ = false;
1699 result.unsorted_ = false;
1700 } else {
1701 sort();
1702 try {
1703 result.is_manhattan_ = applyUnary45OpOnVectors<Unit, op>(result.data_, data_);
1704 } catch (std::string str) {
1705 std::string msg = "GTL 45 Boolean error, precision insufficient to represent edge intersection coordinate value.";
1706 if(str == msg) {
1707 result.clear();
1708 typedef typename coordinate_traits<Unit>::manhattan_area_type Unit2;
1709 typedef typename polygon_45_formation<Unit2>::Vertex45Compact Vertex45Compact2;
1710 typedef std::vector<Vertex45Compact2> Data2;
1711 Data2 lvalue_data, result_data;
1712 lvalue_data.reserve(data_.size());
1713 for(std::size_t i = 0 ; i < data_.size(); ++i) {
1714 const Vertex45Compact& vi = data_[i];
1715 Vertex45Compact2 ci;
1716 ci.pt.x(static_cast<Unit>(x(vi.pt)));
1717 ci.pt.y(static_cast<Unit>(y(vi.pt)));
1718 ci.count = typename polygon_45_formation<Unit2>::Vertex45Count
1719 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
1720 lvalue_data.push_back(ci);
1721 }
1722 scale_up_vertex_45_compact_range(lvalue_data.begin(), lvalue_data.end(), 2);
1723 bool result_is_manhattan = applyUnary45OpOnVectors<Unit2, op>(result_data,
1724 lvalue_data );
1725 if(!result_is_manhattan) {
1726 typename polygon_45_formation<Unit2>::Polygon45Formation pf(false);
1727
1728 std::vector<polygon_45_with_holes_data<Unit2> > container;
1729 pf.scan(container, result_data.begin(), result_data.end());
1730 Data2 error_data_out;
1731 std::vector<rectangle_data<Unit2> > pos_error_rects;
1732 std::vector<rectangle_data<Unit2> > neg_error_rects;
1733 for(std::size_t i = 0; i < container.size(); ++i) {
1734 get_error_rects(pos_error_rects, neg_error_rects, container[i]);
1735 }
1736 for(std::size_t i = 0; i < pos_error_rects.size(); ++i) {
1737 insert_rectangle_into_vector_45(result_data, pos_error_rects[i], false);
1738 insert_rectangle_into_vector_45(error_data_out, pos_error_rects[i], false);
1739 }
1740 for(std::size_t i = 0; i < neg_error_rects.size(); ++i) {
1741 insert_rectangle_into_vector_45(result_data, neg_error_rects[i], true);
1742 insert_rectangle_into_vector_45(error_data_out, neg_error_rects[i], false);
1743 }
1744 scale_down_vertex_45_compact_range_blindly(error_data_out.begin(), error_data_out.end(), 2);
1745 for(std::size_t i = 0 ; i < error_data_out.size(); ++i) {
1746 const Vertex45Compact2& vi = error_data_out[i];
1747 Vertex45Compact ci;
1748 ci.pt.x(static_cast<Unit>(x(vi.pt)));
1749 ci.pt.y(static_cast<Unit>(y(vi.pt)));
1750 ci.count = typename polygon_45_formation<Unit>::Vertex45Count
1751 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
1752 result.error_data_.push_back(ci);
1753 }
1754 Data2 new_result_data;
1755 polygon_sort(result_data.begin(), result_data.end());
1756 applyUnary45OpOnVectors<Unit2, 0>(new_result_data, result_data);
1757 result_data.swap(new_result_data);
1758 }
1759 scale_down_vertex_45_compact_range_blindly(result_data.begin(), result_data.end(), 2);
1760
1761 for(std::size_t i = 0 ; i < result_data.size(); ++i) {
1762 const Vertex45Compact2& vi = result_data[i];
1763 Vertex45Compact ci;
1764 ci.pt.x(static_cast<Unit>(x(vi.pt)));
1765 ci.pt.y(static_cast<Unit>(y(vi.pt)));
1766 ci.count = typename polygon_45_formation<Unit>::Vertex45Count
1767 ( vi.count[0], vi.count[1], vi.count[2], vi.count[3]);
1768 result.data_.push_back(ci);
1769 }
1770 result.is_manhattan_ = result_is_manhattan;
1771 result.dirty_ = false;
1772 result.unsorted_ = false;
1773 } else { throw str; }
1774 }
1775
1776 }
1777 data_.swap(result.data_);
1778 error_data_.swap(result.error_data_);
1779 dirty_ = result.dirty_;
1780 unsorted_ = result.unsorted_;
1781 is_manhattan_ = result.is_manhattan_;
1782 }
1783
1784 template <typename coordinate_type, typename property_type>
1785 class property_merge_45 {
1786 private:
1787 typedef typename coordinate_traits<coordinate_type>::manhattan_area_type big_coord;
1788 typedef typename polygon_45_property_merge<big_coord, property_type>::MergeSetData tsd;
1789 tsd tsd_;
1790 public:
1791 inline property_merge_45() : tsd_() {}
1792 inline property_merge_45(const property_merge_45& that) : tsd_(that.tsd_) {}
1793 inline property_merge_45& operator=(const property_merge_45& that) {
1794 tsd_ = that.tsd_;
1795 return *this;
1796 }
1797
1798 inline void insert(const polygon_45_set_data<coordinate_type>& ps, property_type property) {
1799 ps.clean();
1800 polygon_45_property_merge<big_coord, property_type>::populateMergeSetData(tsd_, ps.begin(), ps.end(), property);
1801 }
1802 template <class GeoObjT>
1803 inline void insert(const GeoObjT& geoObj, property_type property) {
1804 polygon_45_set_data<coordinate_type> ps;
1805 ps.insert(geoObj);
1806 insert(ps, property);
1807 }
1808
1809
1810
1811
1812
1813 template <class result_type>
1814 inline void merge(result_type& result) {
1815 typedef typename result_type::key_type keytype;
1816 typedef std::map<keytype, polygon_45_set_data<big_coord> > bigtype;
1817 bigtype result_big;
1818 polygon_45_property_merge<big_coord, property_type>::performMerge(result_big, tsd_);
1819 std::vector<polygon_45_with_holes_data<big_coord> > polys;
1820 std::vector<rectangle_data<big_coord> > pos_error_rects;
1821 std::vector<rectangle_data<big_coord> > neg_error_rects;
1822 for(typename std::map<keytype, polygon_45_set_data<big_coord> >::iterator itr = result_big.begin();
1823 itr != result_big.end(); ++itr) {
1824 polys.clear();
1825 (*itr).second.get(polys);
1826 for(std::size_t i = 0; i < polys.size(); ++i) {
1827 get_error_rects(pos_error_rects, neg_error_rects, polys[i]);
1828 }
1829 (*itr).second += pos_error_rects;
1830 (*itr).second -= neg_error_rects;
1831 (*itr).second.scale_down(2);
1832 result[(*itr).first].insert((*itr).second);
1833 }
1834 }
1835 };
1836
1837
1838
1839 template <typename coordinate_type>
1840 class connectivity_extraction_45 {
1841 private:
1842 typedef typename coordinate_traits<coordinate_type>::manhattan_area_type big_coord;
1843 typedef typename polygon_45_touch<big_coord>::TouchSetData tsd;
1844 tsd tsd_;
1845 unsigned int nodeCount_;
1846 public:
1847 inline connectivity_extraction_45() : tsd_(), nodeCount_(0) {}
1848 inline connectivity_extraction_45(const connectivity_extraction_45& that) : tsd_(that.tsd_),
1849 nodeCount_(that.nodeCount_) {}
1850 inline connectivity_extraction_45& operator=(const connectivity_extraction_45& that) {
1851 tsd_ = that.tsd_;
1852 nodeCount_ = that.nodeCount_; {}
1853 return *this;
1854 }
1855
1856
1857 inline unsigned int insert(const polygon_45_set_data<coordinate_type>& ps) {
1858 ps.clean();
1859 polygon_45_touch<big_coord>::populateTouchSetData(tsd_, ps.begin(), ps.end(), nodeCount_);
1860 return nodeCount_++;
1861 }
1862 template <class GeoObjT>
1863 inline unsigned int insert(const GeoObjT& geoObj) {
1864 polygon_45_set_data<coordinate_type> ps;
1865 ps.insert(geoObj);
1866 return insert(ps);
1867 }
1868
1869
1870
1871
1872 template <class GraphT>
1873 inline void extract(GraphT& graph) {
1874 polygon_45_touch<big_coord>::performTouch(graph, tsd_);
1875 }
1876 };
1877 }
1878 }
1879 #endif
1880