/* | |
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 | |