iterator_geometry_to_set.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. Copyright 2008 Intel Corporation
  3. Use, modification and distribution are subject to the Boost Software License,
  4. Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. */
  7. #ifndef BOOST_POLYGON_ITERATOR_GEOMETRY_TO_SET_HPP
  8. #define BOOST_POLYGON_ITERATOR_GEOMETRY_TO_SET_HPP
  9. namespace boost { namespace polygon{
  10. template <typename concept_type, typename geometry_type>
  11. class iterator_geometry_to_set {};
  12. template <typename rectangle_type>
  13. class iterator_geometry_to_set<rectangle_concept, rectangle_type> {
  14. public:
  15. typedef typename rectangle_traits<rectangle_type>::coordinate_type coordinate_type;
  16. typedef std::forward_iterator_tag iterator_category;
  17. typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type;
  18. typedef std::ptrdiff_t difference_type;
  19. typedef const value_type* pointer; //immutable
  20. typedef const value_type& reference; //immutable
  21. private:
  22. rectangle_data<coordinate_type> rectangle_;
  23. mutable value_type vertex_;
  24. unsigned int corner_;
  25. orientation_2d orient_;
  26. bool is_hole_;
  27. public:
  28. iterator_geometry_to_set() : rectangle_(), vertex_(), corner_(4), orient_(), is_hole_() {}
  29. iterator_geometry_to_set(const rectangle_type& rectangle, direction_1d dir,
  30. orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) :
  31. rectangle_(), vertex_(), corner_(0), orient_(orient), is_hole_(is_hole) {
  32. assign(rectangle_, rectangle);
  33. if(dir == HIGH) corner_ = 4;
  34. }
  35. inline iterator_geometry_to_set& operator++() {
  36. ++corner_;
  37. return *this;
  38. }
  39. inline const iterator_geometry_to_set operator++(int) {
  40. iterator_geometry_to_set tmp(*this);
  41. ++(*this);
  42. return tmp;
  43. }
  44. inline bool operator==(const iterator_geometry_to_set& that) const {
  45. return corner_ == that.corner_;
  46. }
  47. inline bool operator!=(const iterator_geometry_to_set& that) const {
  48. return !(*this == that);
  49. }
  50. inline reference operator*() const {
  51. if(corner_ == 0) {
  52. vertex_.first = get(get(rectangle_, orient_.get_perpendicular()), LOW);
  53. vertex_.second.first = get(get(rectangle_, orient_), LOW);
  54. vertex_.second.second = 1;
  55. if(is_hole_) vertex_.second.second *= -1;
  56. } else if(corner_ == 1) {
  57. vertex_.second.first = get(get(rectangle_, orient_), HIGH);
  58. vertex_.second.second = -1;
  59. if(is_hole_) vertex_.second.second *= -1;
  60. } else if(corner_ == 2) {
  61. vertex_.first = get(get(rectangle_, orient_.get_perpendicular()), HIGH);
  62. vertex_.second.first = get(get(rectangle_, orient_), LOW);
  63. } else {
  64. vertex_.second.first = get(get(rectangle_, orient_), HIGH);
  65. vertex_.second.second = 1;
  66. if(is_hole_) vertex_.second.second *= -1;
  67. }
  68. return vertex_;
  69. }
  70. };
  71. template <typename polygon_type>
  72. class iterator_geometry_to_set<polygon_90_concept, polygon_type> {
  73. public:
  74. typedef typename polygon_traits<polygon_type>::coordinate_type coordinate_type;
  75. typedef std::forward_iterator_tag iterator_category;
  76. typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type;
  77. typedef std::ptrdiff_t difference_type;
  78. typedef const value_type* pointer; //immutable
  79. typedef const value_type& reference; //immutable
  80. typedef typename polygon_traits<polygon_type>::iterator_type coord_iterator_type;
  81. private:
  82. value_type vertex_;
  83. typename polygon_traits<polygon_type>::iterator_type itrb, itre;
  84. bool last_vertex_;
  85. bool is_hole_;
  86. int multiplier_;
  87. point_data<coordinate_type> first_pt, second_pt, pts[3];
  88. bool use_wrap;
  89. orientation_2d orient_;
  90. int polygon_index;
  91. public:
  92. iterator_geometry_to_set() : vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) {}
  93. 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) :
  94. vertex_(), itrb(), itre(), last_vertex_(),
  95. is_hole_(is_hole), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(),
  96. orient_(orient), polygon_index(0) {
  97. itrb = begin_points(polygon);
  98. itre = end_points(polygon);
  99. use_wrap = false;
  100. if(itrb == itre || dir == HIGH || ::boost::polygon::size(polygon) < 4) {
  101. polygon_index = -1;
  102. } else {
  103. direction_1d wdir = w;
  104. if(!winding_override)
  105. wdir = winding(polygon);
  106. multiplier_ = wdir == LOW ? -1 : 1;
  107. if(is_hole_) multiplier_ *= -1;
  108. first_pt = pts[0] = *itrb;
  109. ++itrb;
  110. second_pt = pts[1] = *itrb;
  111. ++itrb;
  112. pts[2] = *itrb;
  113. evaluate_();
  114. }
  115. }
  116. iterator_geometry_to_set(const iterator_geometry_to_set& that) :
  117. vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(),
  118. second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) {
  119. vertex_ = that.vertex_;
  120. itrb = that.itrb;
  121. itre = that.itre;
  122. last_vertex_ = that.last_vertex_;
  123. is_hole_ = that.is_hole_;
  124. multiplier_ = that.multiplier_;
  125. first_pt = that.first_pt;
  126. second_pt = that.second_pt;
  127. pts[0] = that.pts[0];
  128. pts[1] = that.pts[1];
  129. pts[2] = that.pts[2];
  130. use_wrap = that.use_wrap;
  131. orient_ = that.orient_;
  132. polygon_index = that.polygon_index;
  133. }
  134. inline iterator_geometry_to_set& operator++() {
  135. ++polygon_index;
  136. if(itrb == itre) {
  137. if(first_pt == pts[1]) polygon_index = -1;
  138. else {
  139. pts[0] = pts[1];
  140. pts[1] = pts[2];
  141. if(first_pt == pts[2]) {
  142. pts[2] = second_pt;
  143. } else {
  144. pts[2] = first_pt;
  145. }
  146. }
  147. } else {
  148. ++itrb;
  149. pts[0] = pts[1];
  150. pts[1] = pts[2];
  151. if(itrb == itre) {
  152. if(first_pt == pts[2]) {
  153. pts[2] = second_pt;
  154. } else {
  155. pts[2] = first_pt;
  156. }
  157. } else {
  158. pts[2] = *itrb;
  159. }
  160. }
  161. evaluate_();
  162. return *this;
  163. }
  164. inline const iterator_geometry_to_set operator++(int) {
  165. iterator_geometry_to_set tmp(*this);
  166. ++(*this);
  167. return tmp;
  168. }
  169. inline bool operator==(const iterator_geometry_to_set& that) const {
  170. return polygon_index == that.polygon_index;
  171. }
  172. inline bool operator!=(const iterator_geometry_to_set& that) const {
  173. return !(*this == that);
  174. }
  175. inline reference operator*() const {
  176. return vertex_;
  177. }
  178. inline void evaluate_() {
  179. vertex_.first = pts[1].get(orient_.get_perpendicular());
  180. vertex_.second.first =pts[1].get(orient_);
  181. if(pts[1] == pts[2]) {
  182. vertex_.second.second = 0;
  183. } else if(pts[0].get(HORIZONTAL) != pts[1].get(HORIZONTAL)) {
  184. vertex_.second.second = -1;
  185. } else if(pts[0].get(VERTICAL) != pts[1].get(VERTICAL)) {
  186. vertex_.second.second = 1;
  187. } else {
  188. vertex_.second.second = 0;
  189. }
  190. vertex_.second.second *= multiplier_;
  191. }
  192. };
  193. template <typename polygon_with_holes_type>
  194. class iterator_geometry_to_set<polygon_90_with_holes_concept, polygon_with_holes_type> {
  195. public:
  196. typedef typename polygon_90_traits<polygon_with_holes_type>::coordinate_type coordinate_type;
  197. typedef std::forward_iterator_tag iterator_category;
  198. typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type;
  199. typedef std::ptrdiff_t difference_type;
  200. typedef const value_type* pointer; //immutable
  201. typedef const value_type& reference; //immutable
  202. private:
  203. iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type> itrb, itre;
  204. iterator_geometry_to_set<polygon_90_concept, typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type> itrhib, itrhie;
  205. typename polygon_with_holes_traits<polygon_with_holes_type>::iterator_holes_type itrhb, itrhe;
  206. orientation_2d orient_;
  207. bool is_hole_;
  208. bool started_holes;
  209. public:
  210. iterator_geometry_to_set() : itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() {}
  211. iterator_geometry_to_set(const polygon_with_holes_type& polygon, direction_1d dir,
  212. orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) :
  213. itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(orient), is_hole_(is_hole), started_holes() {
  214. itre = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, HIGH, orient, is_hole_);
  215. itrhe = end_holes(polygon);
  216. if(dir == HIGH) {
  217. itrb = itre;
  218. itrhb = itrhe;
  219. started_holes = true;
  220. } else {
  221. itrb = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, LOW, orient, is_hole_);
  222. itrhb = begin_holes(polygon);
  223. started_holes = false;
  224. }
  225. }
  226. iterator_geometry_to_set(const iterator_geometry_to_set& that) :
  227. itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() {
  228. itrb = that.itrb;
  229. itre = that.itre;
  230. if(that.itrhib != that.itrhie) {
  231. itrhib = that.itrhib;
  232. itrhie = that.itrhie;
  233. }
  234. itrhb = that.itrhb;
  235. itrhe = that.itrhe;
  236. orient_ = that.orient_;
  237. is_hole_ = that.is_hole_;
  238. started_holes = that.started_holes;
  239. }
  240. inline iterator_geometry_to_set& operator++() {
  241. //this code can be folded with flow control factoring
  242. if(itrb == itre) {
  243. if(itrhib == itrhie) {
  244. if(itrhb != itrhe) {
  245. itrhib = iterator_geometry_to_set<polygon_90_concept,
  246. typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_);
  247. itrhie = iterator_geometry_to_set<polygon_90_concept,
  248. typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_);
  249. ++itrhb;
  250. } else {
  251. //in this case we have no holes so we just need the iterhib == itrhie, which
  252. //is always true if they were default initialized in the initial case or
  253. //both point to end of the previous hole processed
  254. //no need to explicitly reset them, and it causes an stl debug assertion to use
  255. //the default constructed iterator this way
  256. //itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept,
  257. // typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>();
  258. }
  259. } else {
  260. ++itrhib;
  261. if(itrhib == itrhie) {
  262. if(itrhb != itrhe) {
  263. itrhib = iterator_geometry_to_set<polygon_90_concept,
  264. typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_);
  265. itrhie = iterator_geometry_to_set<polygon_90_concept,
  266. typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_);
  267. ++itrhb;
  268. } else {
  269. //this is the same case as above
  270. //itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept,
  271. // typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>();
  272. }
  273. }
  274. }
  275. } else {
  276. ++itrb;
  277. if(itrb == itre) {
  278. if(itrhb != itrhe) {
  279. itrhib = iterator_geometry_to_set<polygon_90_concept,
  280. typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_);
  281. itrhie = iterator_geometry_to_set<polygon_90_concept,
  282. typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_);
  283. ++itrhb;
  284. }
  285. }
  286. }
  287. return *this;
  288. }
  289. inline const iterator_geometry_to_set operator++(int) {
  290. iterator_geometry_to_set tmp(*this);
  291. ++(*this);
  292. return tmp;
  293. }
  294. inline bool operator==(const iterator_geometry_to_set& that) const {
  295. return itrb == that.itrb && itrhb == that.itrhb && itrhib == that.itrhib;
  296. }
  297. inline bool operator!=(const iterator_geometry_to_set& that) const {
  298. return !(*this == that);
  299. }
  300. inline reference operator*() const {
  301. if(itrb != itre) return *itrb;
  302. return *itrhib;
  303. }
  304. };
  305. }
  306. }
  307. #endif