| /* |
| Copyright 2008 Intel Corporation |
| |
| Use, modification and distribution are subject to the Boost Software License, |
| Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| http://www.boost.org/LICENSE_1_0.txt). |
| */ |
| #ifndef BOOST_POLYGON_ITERATOR_GEOMETRY_TO_SET_HPP |
| #define BOOST_POLYGON_ITERATOR_GEOMETRY_TO_SET_HPP |
| namespace boost { namespace polygon{ |
| template <typename concept_type, typename geometry_type> |
| class iterator_geometry_to_set {}; |
| |
| template <typename rectangle_type> |
| class iterator_geometry_to_set<rectangle_concept, rectangle_type> { |
| public: |
| typedef typename rectangle_traits<rectangle_type>::coordinate_type coordinate_type; |
| typedef std::forward_iterator_tag iterator_category; |
| typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type; |
| typedef std::ptrdiff_t difference_type; |
| typedef const value_type* pointer; //immutable |
| typedef const value_type& reference; //immutable |
| private: |
| rectangle_data<coordinate_type> rectangle_; |
| mutable value_type vertex_; |
| unsigned int corner_; |
| orientation_2d orient_; |
| bool is_hole_; |
| public: |
| iterator_geometry_to_set() : rectangle_(), vertex_(), corner_(4), orient_(), is_hole_() {} |
| iterator_geometry_to_set(const rectangle_type& rectangle, direction_1d dir, |
| orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) : |
| rectangle_(), vertex_(), corner_(0), orient_(orient), is_hole_(is_hole) { |
| assign(rectangle_, rectangle); |
| if(dir == HIGH) corner_ = 4; |
| } |
| inline iterator_geometry_to_set& operator++() { |
| ++corner_; |
| return *this; |
| } |
| inline const iterator_geometry_to_set operator++(int) { |
| iterator_geometry_to_set tmp(*this); |
| ++(*this); |
| return tmp; |
| } |
| inline bool operator==(const iterator_geometry_to_set& that) const { |
| return corner_ == that.corner_; |
| } |
| inline bool operator!=(const iterator_geometry_to_set& that) const { |
| return !(*this == that); |
| } |
| inline reference operator*() const { |
| if(corner_ == 0) { |
| vertex_.first = get(get(rectangle_, orient_.get_perpendicular()), LOW); |
| vertex_.second.first = get(get(rectangle_, orient_), LOW); |
| vertex_.second.second = 1; |
| if(is_hole_) vertex_.second.second *= -1; |
| } else if(corner_ == 1) { |
| vertex_.second.first = get(get(rectangle_, orient_), HIGH); |
| vertex_.second.second = -1; |
| if(is_hole_) vertex_.second.second *= -1; |
| } else if(corner_ == 2) { |
| vertex_.first = get(get(rectangle_, orient_.get_perpendicular()), HIGH); |
| vertex_.second.first = get(get(rectangle_, orient_), LOW); |
| } else { |
| vertex_.second.first = get(get(rectangle_, orient_), HIGH); |
| vertex_.second.second = 1; |
| if(is_hole_) vertex_.second.second *= -1; |
| } |
| return vertex_; |
| } |
| }; |
| |
| template <typename polygon_type> |
| class iterator_geometry_to_set<polygon_90_concept, polygon_type> { |
| public: |
| typedef typename polygon_traits<polygon_type>::coordinate_type coordinate_type; |
| typedef std::forward_iterator_tag iterator_category; |
| typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type; |
| typedef std::ptrdiff_t difference_type; |
| typedef const value_type* pointer; //immutable |
| typedef const value_type& reference; //immutable |
| typedef typename polygon_traits<polygon_type>::iterator_type coord_iterator_type; |
| private: |
| value_type vertex_; |
| typename polygon_traits<polygon_type>::iterator_type itrb, itre; |
| bool last_vertex_; |
| bool is_hole_; |
| int multiplier_; |
| point_data<coordinate_type> first_pt, second_pt, pts[3]; |
| bool use_wrap; |
| orientation_2d orient_; |
| int polygon_index; |
| public: |
| iterator_geometry_to_set() : vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) {} |
| iterator_geometry_to_set(const polygon_type& polygon, direction_1d dir, orientation_2d orient = HORIZONTAL, bool is_hole = false, bool winding_override = false, direction_1d w = CLOCKWISE) : |
| vertex_(), itrb(), itre(), last_vertex_(), |
| is_hole_(is_hole), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), |
| orient_(orient), polygon_index(0) { |
| itrb = begin_points(polygon); |
| itre = end_points(polygon); |
| use_wrap = false; |
| if(itrb == itre || dir == HIGH || size(polygon) < 4) { |
| polygon_index = -1; |
| } else { |
| direction_1d wdir = w; |
| if(!winding_override) |
| wdir = winding(polygon); |
| multiplier_ = wdir == LOW ? -1 : 1; |
| if(is_hole_) multiplier_ *= -1; |
| first_pt = pts[0] = *itrb; |
| ++itrb; |
| second_pt = pts[1] = *itrb; |
| ++itrb; |
| pts[2] = *itrb; |
| evaluate_(); |
| } |
| } |
| iterator_geometry_to_set(const iterator_geometry_to_set& that) : |
| vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(), |
| second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) { |
| vertex_ = that.vertex_; |
| itrb = that.itrb; |
| itre = that.itre; |
| last_vertex_ = that.last_vertex_; |
| is_hole_ = that.is_hole_; |
| multiplier_ = that.multiplier_; |
| first_pt = that.first_pt; |
| second_pt = that.second_pt; |
| pts[0] = that.pts[0]; |
| pts[1] = that.pts[1]; |
| pts[2] = that.pts[2]; |
| use_wrap = that.use_wrap; |
| orient_ = that.orient_; |
| polygon_index = that.polygon_index; |
| } |
| inline iterator_geometry_to_set& operator++() { |
| ++polygon_index; |
| if(itrb == itre) { |
| if(first_pt == pts[1]) polygon_index = -1; |
| else { |
| pts[0] = pts[1]; |
| pts[1] = pts[2]; |
| if(first_pt == pts[2]) { |
| pts[2] = second_pt; |
| } else { |
| pts[2] = first_pt; |
| } |
| } |
| } else { |
| ++itrb; |
| pts[0] = pts[1]; |
| pts[1] = pts[2]; |
| if(itrb == itre) { |
| if(first_pt == pts[2]) { |
| pts[2] = second_pt; |
| } else { |
| pts[2] = first_pt; |
| } |
| } else { |
| pts[2] = *itrb; |
| } |
| } |
| evaluate_(); |
| return *this; |
| } |
| inline const iterator_geometry_to_set operator++(int) { |
| iterator_geometry_to_set tmp(*this); |
| ++(*this); |
| return tmp; |
| } |
| inline bool operator==(const iterator_geometry_to_set& that) const { |
| return polygon_index == that.polygon_index; |
| } |
| inline bool operator!=(const iterator_geometry_to_set& that) const { |
| return !(*this == that); |
| } |
| inline reference operator*() const { |
| return vertex_; |
| } |
| |
| inline void evaluate_() { |
| vertex_.first = pts[1].get(orient_.get_perpendicular()); |
| vertex_.second.first =pts[1].get(orient_); |
| if(pts[1] == pts[2]) { |
| vertex_.second.second = 0; |
| } else if(pts[0].get(HORIZONTAL) != pts[1].get(HORIZONTAL)) { |
| vertex_.second.second = -1; |
| } else if(pts[0].get(VERTICAL) != pts[1].get(VERTICAL)) { |
| vertex_.second.second = 1; |
| } else { |
| vertex_.second.second = 0; |
| } |
| vertex_.second.second *= multiplier_; |
| } |
| }; |
| |
| template <typename polygon_with_holes_type> |
| class iterator_geometry_to_set<polygon_90_with_holes_concept, polygon_with_holes_type> { |
| public: |
| typedef typename polygon_90_traits<polygon_with_holes_type>::coordinate_type coordinate_type; |
| typedef std::forward_iterator_tag iterator_category; |
| typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type; |
| typedef std::ptrdiff_t difference_type; |
| typedef const value_type* pointer; //immutable |
| typedef const value_type& reference; //immutable |
| private: |
| iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type> itrb, itre; |
| iterator_geometry_to_set<polygon_90_concept, typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type> itrhib, itrhie; |
| typename polygon_with_holes_traits<polygon_with_holes_type>::iterator_holes_type itrhb, itrhe; |
| orientation_2d orient_; |
| bool is_hole_; |
| bool started_holes; |
| public: |
| iterator_geometry_to_set() : itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() {} |
| iterator_geometry_to_set(const polygon_with_holes_type& polygon, direction_1d dir, |
| orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) : |
| itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(orient), is_hole_(is_hole), started_holes() { |
| itre = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, HIGH, orient, is_hole_); |
| itrhe = end_holes(polygon); |
| if(dir == HIGH) { |
| itrb = itre; |
| itrhb = itrhe; |
| started_holes = true; |
| } else { |
| itrb = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, LOW, orient, is_hole_); |
| itrhb = begin_holes(polygon); |
| started_holes = false; |
| } |
| } |
| iterator_geometry_to_set(const iterator_geometry_to_set& that) : |
| itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() { |
| itrb = that.itrb; |
| itre = that.itre; |
| if(that.itrhib != that.itrhie) { |
| itrhib = that.itrhib; |
| itrhie = that.itrhie; |
| } |
| itrhb = that.itrhb; |
| itrhe = that.itrhe; |
| orient_ = that.orient_; |
| is_hole_ = that.is_hole_; |
| started_holes = that.started_holes; |
| } |
| inline iterator_geometry_to_set& operator++() { |
| //this code can be folded with flow control factoring |
| if(itrb == itre) { |
| if(itrhib == itrhie) { |
| if(itrhb != itrhe) { |
| itrhib = iterator_geometry_to_set<polygon_90_concept, |
| typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_); |
| itrhie = iterator_geometry_to_set<polygon_90_concept, |
| typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_); |
| ++itrhb; |
| } else { |
| //in this case we have no holes so we just need the iterhib == itrhie, which |
| //is always true if they were default initialized in the initial case or |
| //both point to end of the previous hole processed |
| //no need to explicitly reset them, and it causes an stl debug assertion to use |
| //the default constructed iterator this way |
| //itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept, |
| // typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(); |
| } |
| } else { |
| ++itrhib; |
| if(itrhib == itrhie) { |
| if(itrhb != itrhe) { |
| itrhib = iterator_geometry_to_set<polygon_90_concept, |
| typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_); |
| itrhie = iterator_geometry_to_set<polygon_90_concept, |
| typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_); |
| ++itrhb; |
| } else { |
| //this is the same case as above |
| //itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept, |
| // typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(); |
| } |
| } |
| } |
| } else { |
| ++itrb; |
| if(itrb == itre) { |
| if(itrhb != itrhe) { |
| itrhib = iterator_geometry_to_set<polygon_90_concept, |
| typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_); |
| itrhie = iterator_geometry_to_set<polygon_90_concept, |
| typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_); |
| ++itrhb; |
| } |
| } |
| } |
| return *this; |
| } |
| inline const iterator_geometry_to_set operator++(int) { |
| iterator_geometry_to_set tmp(*this); |
| ++(*this); |
| return tmp; |
| } |
| inline bool operator==(const iterator_geometry_to_set& that) const { |
| return itrb == that.itrb && itrhb == that.itrhb && itrhib == that.itrhib; |
| } |
| inline bool operator!=(const iterator_geometry_to_set& that) const { |
| return !(*this == that); |
| } |
| inline reference operator*() const { |
| if(itrb != itre) return *itrb; |
| return *itrhib; |
| } |
| }; |
| |
| |
| } |
| } |
| #endif |
| |