PageRenderTime 54ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/CGAL/Minkowski_sum_2/Exact_offset_base_2.h

https://gitlab.com/aksr/MeshSimplification
C Header | 297 lines | 168 code | 54 blank | 75 comment | 13 complexity | 3ed34acfb55d6f3e07fc1f469284f56e MD5 | raw file
  1. // Copyright (c) 2006 Tel-Aviv University (Israel).
  2. // All rights reserved.
  3. //
  4. // This file is part of CGAL (www.cgal.org).
  5. // You can redistribute it and/or modify it under the terms of the GNU
  6. // General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. //
  9. // Licensees holding a valid commercial license may use this file in
  10. // accordance with the commercial license agreement provided with the software.
  11. //
  12. // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
  13. // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  14. //
  15. // $URL$
  16. // $Id$
  17. //
  18. // Author(s) : Ron Wein <wein@post.tau.ac.il>
  19. #ifndef CGAL_EXACT_OFFSET_BASE_H
  20. #define CGAL_EXACT_OFFSET_BASE_H
  21. #include <CGAL/Polygon_2.h>
  22. #include <CGAL/Polygon_with_holes_2.h>
  23. #include <CGAL/Gps_traits_2.h>
  24. #include <CGAL/Minkowski_sum_2/Labels.h>
  25. #include <CGAL/Minkowski_sum_2/Arr_labeled_traits_2.h>
  26. #include <CGAL/use.h>
  27. namespace CGAL {
  28. /*! \class
  29. * A base class for computing the offset of a given polygon by a given
  30. * radius in an exact manner.
  31. */
  32. template <class Traits_, class Container_>
  33. class Exact_offset_base_2
  34. {
  35. private:
  36. typedef Traits_ Traits_2;
  37. // Rational kernel types:
  38. typedef typename Traits_2::Rat_kernel Rat_kernel;
  39. typedef typename Rat_kernel::FT Rational;
  40. typedef typename Rat_kernel::Point_2 Rat_point_2;
  41. typedef typename Rat_kernel::Line_2 Rat_line_2;
  42. typedef typename Rat_kernel::Circle_2 Rat_circle_2;
  43. protected:
  44. typedef Rat_kernel Basic_kernel;
  45. typedef Rational Basic_NT;
  46. private:
  47. // Algebraic kernel types:
  48. typedef typename Traits_2::Alg_kernel Alg_kernel;
  49. typedef typename Alg_kernel::FT Algebraic;
  50. typedef typename Alg_kernel::Point_2 Alg_point_2;
  51. typedef typename Traits_2::Nt_traits Nt_traits;
  52. // Traits-class types:
  53. typedef typename Traits_2::Curve_2 Curve_2;
  54. typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2;
  55. typedef CGAL::Gps_traits_2<Traits_2> Gps_traits_2;
  56. protected:
  57. typedef CGAL::Polygon_2<Rat_kernel, Container_> Polygon_2;
  58. typedef CGAL::Polygon_with_holes_2<Rat_kernel,
  59. Container_> Polygon_with_holes_2;
  60. typedef typename Gps_traits_2::Polygon_2 Offset_polygon_2;
  61. private:
  62. // Polygon-related types:
  63. typedef typename Polygon_2::Vertex_circulator Vertex_circulator;
  64. protected:
  65. typedef Arr_labeled_traits_2<Traits_2> Labeled_traits_2;
  66. typedef typename Labeled_traits_2::X_monotone_curve_2 Labeled_curve_2;
  67. public:
  68. /*! Default constructor. */
  69. Exact_offset_base_2 ()
  70. {}
  71. protected:
  72. /*!
  73. * Compute the curves that constitute the offset of a simple polygon by a
  74. * given radius.
  75. * \param pgn The polygon.
  76. * \param orient The orientation to traverse the vertices.
  77. * \param r The offset radius.
  78. * \param cycle_id The index of the cycle.
  79. * \param oi An output iterator for the offset curves.
  80. * \pre The value type of the output iterator is Labeled_curve_2.
  81. * \return A past-the-end iterator for the holes container.
  82. */
  83. template <class OutputIterator>
  84. OutputIterator _offset_polygon (const Polygon_2& pgn,
  85. CGAL::Orientation orient,
  86. const Rational& r,
  87. unsigned int cycle_id,
  88. OutputIterator oi) const
  89. {
  90. // Prepare circulators over the polygon vertices.
  91. const bool forward = (pgn.orientation() == orient);
  92. Vertex_circulator first, curr, next;
  93. first = pgn.vertices_circulator();
  94. curr = first;
  95. next = first;
  96. // Traverse the polygon vertices and edges and construct the arcs that
  97. // constitute the single convolution cycle.
  98. Alg_kernel alg_ker;
  99. typename Alg_kernel::Equal_2 f_equal = alg_ker.equal_2_object();
  100. Nt_traits nt_traits;
  101. const Rational sqr_r = CGAL::square (r);
  102. const Algebraic alg_r = nt_traits.convert (r);
  103. Rational x1, y1; // The source of the current edge.
  104. Rational x2, y2; // The target of the current edge.
  105. Rational delta_x, delta_y; // (x2 - x1) and (y2 - y1), resp.
  106. Algebraic len; // The length of the current edge.
  107. Algebraic trans_x, trans_y; // The translation vector.
  108. Alg_point_2 op1, op2; // The edge points of the offset edge.
  109. Alg_point_2 first_op; // The first offset point.
  110. Algebraic a, b, c;
  111. unsigned int curve_index = 0;
  112. Traits_2 traits;
  113. std::list<Object> xobjs;
  114. std::list<Object>::iterator xobj_it;
  115. typename Traits_2::Make_x_monotone_2
  116. f_make_x_monotone = traits.make_x_monotone_2_object();
  117. Curve_2 arc;
  118. X_monotone_curve_2 xarc;
  119. bool assign_success;
  120. do
  121. {
  122. // Get a circulator for the next vertex (in the proper orientation).
  123. if (forward)
  124. ++next;
  125. else
  126. --next;
  127. // Compute the vector v = (delta_x, delta_y) of the current edge,
  128. // and compute the edge length ||v||.
  129. x1 = curr->x();
  130. y1 = curr->y();
  131. x2 = next->x();
  132. y2 = next->y();
  133. delta_x = x2 - x1;
  134. delta_y = y2 - y1;
  135. len = nt_traits.sqrt (nt_traits.convert (CGAL::square (delta_x) +
  136. CGAL::square (delta_y)));
  137. // The angle theta between the vector v and the x-axis is given by:
  138. //
  139. // y2 - y1 x2 - x1
  140. // sin(alpha) = --------- cos(alpha) = ---------
  141. // ||v|| ||v||
  142. //
  143. // To offset the endpoints of the current edge we compute a vector
  144. // (trans_x, trans_y) perpendicular to v. Since we traverse the polygon
  145. // in a counterclockwise manner, the angle this vector forms with the
  146. // x-axis is (alpha - PI/2), and we have:
  147. //
  148. // trans_x = r*cos(alpha - PI/2) = r*sin(alpha)
  149. // trans_y = r*sin(alpha - PI/2) = -r*cos(alpha)
  150. trans_x = nt_traits.convert (r * delta_y) / len;
  151. trans_y = nt_traits.convert (-r * delta_x) / len;
  152. // Construct the first offset vertex, which corresponds to the
  153. // source vertex of the current polygon edge.
  154. op1 = Alg_point_2 (nt_traits.convert (x1) + trans_x,
  155. nt_traits.convert (y1) + trans_y);
  156. if (curr == first)
  157. {
  158. // This is the first edge we visit -- store op1 for future use.
  159. first_op = op1;
  160. }
  161. else
  162. {
  163. if (! f_equal (op2, op1))
  164. {
  165. // Connect op2 (from the previous iteration) and op1 with a circular
  166. // arc, whose supporting circle is (x1, x2) with radius r.
  167. arc = Curve_2 (Rat_circle_2 (*curr, sqr_r),
  168. CGAL::COUNTERCLOCKWISE,
  169. op2, op1);
  170. // Subdivide the arc into x-monotone subarcs and append them to the
  171. // convolution cycle.
  172. xobjs.clear();
  173. f_make_x_monotone (arc, std::back_inserter(xobjs));
  174. for (xobj_it = xobjs.begin(); xobj_it != xobjs.end(); ++xobj_it)
  175. {
  176. assign_success = CGAL::assign (xarc, *xobj_it);
  177. CGAL_assertion (assign_success);
  178. CGAL_USE(assign_success);
  179. *oi = Labeled_curve_2 (xarc,
  180. X_curve_label (xarc.is_directed_right(),
  181. cycle_id,
  182. curve_index));
  183. ++oi;
  184. curve_index++;
  185. }
  186. }
  187. }
  188. // Construct the second offset vertex, which corresponds to the
  189. // target vertex of the current polygon edge.
  190. op2 = Alg_point_2 (nt_traits.convert (x2) + trans_x,
  191. nt_traits.convert (y2) + trans_y);
  192. // The equation of the line connecting op1 and op2 is given by:
  193. //
  194. // (y1 - y2)*x + (x2 - x1)*y + (r*len - y1*x2 - x1*y2) = 0
  195. //
  196. a = nt_traits.convert (-delta_y);
  197. b = nt_traits.convert (delta_x);
  198. c = alg_r*len - nt_traits.convert (y1*x2 - x1*y2);
  199. xarc = X_monotone_curve_2 (a, b, c,
  200. op1, op2);
  201. *oi = Labeled_curve_2 (xarc,
  202. X_curve_label (xarc.is_directed_right(),
  203. cycle_id,
  204. curve_index));
  205. ++oi;
  206. curve_index++;
  207. // Proceed to the next polygon vertex.
  208. curr = next;
  209. } while (curr != first);
  210. if (! f_equal (op2, first_op))
  211. {
  212. // Close the convolution cycle by creating the final circular arc,
  213. // centered at the first vertex.
  214. arc = Curve_2 (Rat_circle_2 (*first, sqr_r),
  215. CGAL::COUNTERCLOCKWISE,
  216. op2, first_op);
  217. // Subdivide the arc into x-monotone subarcs and append them to the
  218. // convolution cycle.
  219. bool is_last;
  220. xobjs.clear();
  221. f_make_x_monotone (arc, std::back_inserter(xobjs));
  222. xobj_it = xobjs.begin();
  223. while (xobj_it != xobjs.end())
  224. {
  225. assign_success = CGAL::assign (xarc, *xobj_it);
  226. CGAL_assertion (assign_success);
  227. CGAL_USE(assign_success);
  228. ++xobj_it;
  229. is_last = (xobj_it == xobjs.end());
  230. *oi = Labeled_curve_2 (xarc,
  231. X_curve_label (xarc.is_directed_right(),
  232. cycle_id,
  233. curve_index,
  234. is_last));
  235. ++oi;
  236. curve_index++;
  237. }
  238. }
  239. return (oi);
  240. }
  241. };
  242. } //namespace CGAL
  243. #endif