Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:48:00

0001 /*
0002   Copyright 2008 Intel Corporation
0003 
0004   Use, modification and distribution are subject to the Boost Software License,
0005   Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0006   http://www.boost.org/LICENSE_1_0.txt).
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     // default constructor
0037     inline polygon_45_set_data() : error_data_(), data_(), dirty_(false), unsorted_(false), is_manhattan_(true) {}
0038 
0039     // constructor from a geometry object
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     // copy constructor
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     // destructor
0057     inline ~polygon_45_set_data() {}
0058 
0059     // assignement operator
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     // insert iterator range
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     // insert iterator range
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     // equivalence operator
0162     inline bool operator==(const polygon_45_set_data& p) const {
0163       clean();
0164       p.clean();
0165       return data_ == p.data_;
0166     }
0167 
0168     // inequivalence operator
0169     inline bool operator!=(const polygon_45_set_data& p) const {
0170       return !((*this) == p);
0171     }
0172 
0173     // get iterator to begin vertex data
0174     inline iterator_type begin() const {
0175       return data_.begin();
0176     }
0177 
0178     // get iterator to end vertex data
0179     inline iterator_type end() const {
0180       return data_.end();
0181     }
0182 
0183     const value_type& value() const {
0184       return data_;
0185     }
0186 
0187     // clear the contents of the polygon_45_set_data
0188     inline void clear() { data_.clear(); error_data_.clear(); dirty_ = unsorted_ = false; is_manhattan_ = true; }
0189 
0190     // find out if Polygon set is empty
0191     inline bool empty() const { return data_.empty(); }
0192 
0193     // get the Polygon set size in vertices
0194     inline std::size_t size() const { clean(); return data_.size(); }
0195 
0196     // get the current Polygon set capacity in vertices
0197     inline std::size_t capacity() const { return data_.capacity(); }
0198 
0199     // reserve size of polygon set in vertices
0200     inline void reserve(std::size_t size) { return data_.reserve(size); }
0201 
0202     // find out if Polygon set is sorted
0203     inline bool sorted() const { return !unsorted_; }
0204 
0205     // find out if Polygon set is clean
0206     inline bool dirty() const { return dirty_; }
0207 
0208     // find out if Polygon set is clean
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     // append to the container cT with polygons (holes will be fractured vertically)
0242     template <class cT>
0243     void get_polygons(cT& container) const {
0244       get_dispatch(container, polygon_45_concept());
0245     }
0246 
0247     // append to the container cT with PolygonWithHoles objects
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     // append to the container cT with polygons of three or four verticies
0254     // slicing orientation is vertical
0255     template <class cT>
0256     void get_trapezoids(cT& container) const {
0257       clean();
0258       typename polygon_45_formation<Unit>::Polygon45Tiling pf;
0259       //std::cout << "FORMING POLYGONS\n";
0260       pf.scan(container, data_.begin(), data_.end());
0261       //std::cout << "DONE FORMING POLYGONS\n";
0262     }
0263 
0264     // append to the container cT with polygons of three or four verticies
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     // insert vertex sequence
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     // get the external boundary rectangle
0287     template <typename rectangle_type>
0288     bool extents(rectangle_type& rect) const;
0289 
0290     // snap verticies of set to even,even or odd,odd coordinates
0291     void snap() const;
0292 
0293     // |= &= += *= -= ^= binary operators
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     // resizing operations
0302     polygon_45_set_data& operator+=(Unit delta);
0303     polygon_45_set_data& operator-=(Unit delta);
0304 
0305     // shrink the Polygon45Set by shrinking
0306     polygon_45_set_data& resize(coordinate_type resizing, RoundingOption rounding = CLOSEST,
0307                                 CornerOption corner = INTERSECTION);
0308 
0309     // transform set
0310     template <typename transformation_type>
0311     polygon_45_set_data& transform(const transformation_type& tr);
0312 
0313     // scale set
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     // self_intersect
0319     polygon_45_set_data& self_intersect() {
0320       sort();
0321       applyAdaptiveUnary_<1>(); //1 = AND
0322       dirty_ = false;
0323       return *this;
0324     }
0325 
0326     // self_xor
0327     polygon_45_set_data& self_xor() {
0328       sort();
0329       applyAdaptiveUnary_<3>(); //3 = XOR
0330       dirty_ = false;
0331       return *this;
0332     }
0333 
0334     // accumulate the bloated polygon
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     //functions
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       //std::cout << "FORMING POLYGONS\n";
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     // accumulate the bloated polygon with holes
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     //retval.second = pt1.x() < pt2.x() ? -1 : 1;
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     //std::cout << pt1 << " " << pt2 << " " << pt3 << std::endl;
0500     std::pair<int, int> check;
0501     check = characterizeEdge45(pt1, pt2);
0502     //std::cout << "index " << check.first << " " << check.second * -multiplier << std::endl;
0503     vertex.count[check.first] += check.second * -multiplier;
0504     check = characterizeEdge45(pt2, pt3);
0505     //std::cout << "index " << check.first << " " << check.second * multiplier << std::endl;
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     //skip any duplicate points
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       //skip any duplicate points
0540       if(pt == prevPt) {
0541         ++itr;
0542         continue;
0543       }
0544       //operate on the three points
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   // insert polygon set
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   // insert polygon set
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   // get the external boundary rectangle
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   //this function snaps the vertex and two half edges
0662   //to be both even or both odd coordinate values if one of the edges is 45
0663   //and throws an excpetion if an edge is non-manhattan, non-45.
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           //move right
0673           vertex.pt.x(vertex.pt.x() + 1);
0674         } else {
0675           //assert that vertex.count[3] != 0
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   // |= &= += *= -= ^= binary operators
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     //b.sort();
0700     //sort();
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     //b.sort();
0717     //sort();
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     //b.sort();
0726     //sort();
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     //perterb 45 edges to prevent non-integer intersection errors upon boolean op
0754     //snap();
0755     return *this;
0756   }
0757 
0758   //distance is assumed to be positive
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   //distance is assumed to be positive
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 { //UNDERSIZE
0773       return (Unit)distance;
0774     }
0775   }
0776 
0777   // 0 is east, 1 is northeast, 2 is north, 3 is northwest, 4 is west, 5 is southwest, 6 is south
0778   // 7 is southwest
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         //45 degree bloating
0787         double distance = (double)bloating;
0788         distance /= sqrt2;  // multiply by 1/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     //the intention here is to use all integer arithmetic without causing overflow
0838     //turncation error or divide by zero error
0839     //I don't use floating point arithmetic because its precision may not be high enough
0840     //at the extremes of the integer range
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       // y - y1 = (rise1/run1)(x - x1)
0862       // y - y2 = (rise2/run2)(x - x2)
0863       // y = (rise1/run1)(x - x1) + y1 = (rise2/run2)(x - x2) + y2
0864       // (rise1/run1 - rise2/run2)x = y2 - y1 + rise1/run1 x1 - rise2/run2 x2
0865       // x = (y2 - y1 + rise1/run1 x1 - rise2/run2 x2)/(rise1/run1 - rise2/run2)
0866       // x = (y2 - y1 + rise1/run1 x1 - rise2/run2 x2)(rise1 run2 - rise2 run1)/(run1 run2)
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         // y - y1 = (rise1/run1)(x - x1)
0875         // (run1/rise1)(y - y1) = x - x1
0876         // x = (run1/rise1)(y - y1) + x1 = (run2/rise2)(y - y2) + x2
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       //we have to round up
0900       bloating = bloating / 2 + bloating % 2 ; //round up
0901       if(second.x() < first.x()) std::swap(first, second);
0902       if(first.y() < second.y()) { //upward sloping
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 { //downward sloping
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()) { //upward sloping
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 { //downward sloping
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     //edge is 45
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; //accute interior corner
1015       else multiplier *= -1; //make it appear to be an accute exterior angle
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         //ORTHOGONAL of a 45 degree corner
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     //if the change in angle is 135 degrees it is an accute exterior corner
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     //insert minkofski shapes on edges and corners
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; //skip first point if it is duplicate of last point
1127         }
1128       }
1129     } while(second != end);
1130     //sizingSet.snap();
1131     polygon_45_set_data<Unit> tmp;
1132     //insert original shape
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   // accumulate the bloated polygon with holes
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   // transform set
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_); //swapping vectors should be constant time operation
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         //std::cout << "SCAN " << currentX << "\n";
1264         //scan event
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       //std::cout << "get next\n";
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         //std::cout << "case1 next\n";
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         //std::cout << "case2 next\n";
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         //std::cout << "case3 next\n";
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         //std::cout << "SCAN " << currentX << "\n";
1387         //scan event
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       //std::cout << "get next\n";
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; //too few points
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; //too few points
1492         continue;
1493       } else {
1494         const Point& pt = *beginr;
1495         pt3 = pt;
1496         ++beginr;
1497         if(beginr == endr) {
1498           next_to_last = true;
1499           //skip last point equal to first
1500           continue;
1501         }
1502       }
1503       if(local_abs(x(pt2)) % 2) { //y % 2 should also be odd
1504         //is corner concave or convex?
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         //std::cout << pt1 << " " << pt2 << " " << pt3 << " " << ar << std::endl;
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       //convert each into polygon_90_set data and call boolean operations
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; //skip all non vertical edges
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; //skip all non vertical edges
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             //std::cout << "FORMING POLYGONS\n";
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); //OR operation
1646             result_data.swap(new_result_data);
1647           }
1648           scale_down_vertex_45_compact_range_blindly(result_data.begin(), result_data.end(), 2);
1649           //result.data_.reserve(result_data.size());
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       //std::cout << "DONE SCANNING\n";
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       //convert each into polygon_90_set data and call boolean operations
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; //skip all non vertical edges
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             //std::cout << "FORMING POLYGONS\n";
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); //OR operation
1757             result_data.swap(new_result_data);
1758           }
1759           scale_down_vertex_45_compact_range_blindly(result_data.begin(), result_data.end(), 2);
1760           //result.data_.reserve(result_data.size());
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       //std::cout << "DONE SCANNING\n";
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     //merge properties of input geometries and store the resulting geometries of regions
1810     //with unique sets of merged properties to polygons sets in a map keyed by sets of properties
1811     // T = std::map<std::set<property_type>, polygon_45_set_data<coordiante_type> > or
1812     // T = std::map<std::vector<property_type>, polygon_45_set_data<coordiante_type> >
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   //ConnectivityExtraction computes the graph of connectivity between rectangle, polygon and
1838   //polygon set graph nodes where an edge is created whenever the geometry in two nodes overlap
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     //insert a polygon set graph node, the value returned is the id of the graph node
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     //extract connectivity and store the edges in the graph
1870     //graph must be indexable by graph node id and the indexed value must be a std::set of
1871     //graph node id
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