Collision Checker
triangulate.cc
Go to the documentation of this file.
2 #include <math.h>
3 
4 #define ENABLE_CGAL 0
5 #if ENABLE_TRIANGULATION
6 #if ENABLE_CGAL
7 
8 #include <CGAL/Constrained_Delaunay_triangulation_2.h>
9 #include <CGAL/Delaunay_mesh_face_base_2.h>
10 #include <CGAL/Delaunay_mesh_size_criteria_2.h>
11 #include <CGAL/Delaunay_mesher_2.h>
12 #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
13 #include <CGAL/Polygon_2.h>
14 #endif
15 
16 #if ENABLE_TRIANGLE
17 
18 #define REAL double
19 #define VOID int
20 
21 extern "C" {
22 
23 #include "triangle.h"
24 }
25 
26 #include "string.h"
27 
28 #endif
29 #if ENABLE_GPC
30 
31 extern "C" {
32 
33 #include "gpc.h"
34 }
35 
36 #endif
37 
38 namespace collision {
39 namespace triangulation {
40 
41 int do_triangulate_aabb(
42  std::vector<Eigen::Vector2d> vertices,
43  std::vector<collision::TriangleConstPtr> &triangles_out) {
44  double min_x = std::numeric_limits<double>::max();
45  double max_x = std::numeric_limits<double>::min();
46  double min_y = std::numeric_limits<double>::max();
47  double max_y = std::numeric_limits<double>::min();
48  for (auto vert : vertices) {
49  min_x = std::min(min_x, vert(0));
50  min_y = std::min(min_y, vert(1));
51  max_x = std::max(max_x, vert(0));
52  max_y = std::max(max_y, vert(1));
53  }
54 
55  if (!isinf(min_x) && !isinf(max_x) && !isinf(min_y) && !isinf(max_y)) {
56  auto v1 = Eigen::Vector2d(min_x, min_y);
57  auto v2 = Eigen::Vector2d(max_x, min_y);
58  auto v3 = Eigen::Vector2d(max_x, max_y);
59  auto v4 = Eigen::Vector2d(min_x, max_y);
60  triangles_out.emplace_back(new collision::Triangle(v1, v2, v3));
61  triangles_out.emplace_back(new collision::Triangle(v3, v4, v1));
62  }
63 
64  return 0;
65 }
66 
67 #if ENABLE_CGAL
68 
69 int do_triangulate_cgal(std::vector<Eigen::Vector2d> vertices,
70  std::vector<collision::TriangleConstPtr> &triangles_out) {
71  typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
72  typedef CGAL::Exact_predicates_tag Itag;
73  typedef CGAL::Constrained_Delaunay_triangulation_2<K, CGAL::Default, Itag>
74  CDT;
75  typedef CDT::Point Point;
76  typedef CGAL::Polygon_2<K> Polygon_2;
77 
78  CDT cdt;
79 
80  Polygon_2 polygon1;
81  for (auto &el : vertices) {
82  polygon1.push_back(Point(el[0], el[1]));
83  }
84  cdt.insert_constraint(polygon1.vertices_begin(), polygon1.vertices_end(),
85  true);
86 
87  for (CDT::Finite_faces_iterator fit = cdt.finite_faces_begin();
88  fit != cdt.finite_faces_end(); ++fit) {
89  Eigen::Vector2d vert1(cdt.triangle(fit)[0].x(), cdt.triangle(fit)[0].y());
90  Eigen::Vector2d vert2(cdt.triangle(fit)[1].x(), cdt.triangle(fit)[1].y());
91  Eigen::Vector2d vert3(cdt.triangle(fit)[2].x(), cdt.triangle(fit)[2].y());
92  triangles_out.emplace_back(new collision::Triangle(vert1, vert2, vert3));
93  }
94  return 0;
95 }
96 
97 int do_triangulateQuality_cgal(
98  std::vector<Eigen::Vector2d> vertices,
99  std::vector<collision::TriangleConstPtr> &triangles_out,
100  TriangulationQuality qual) {
101  typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
102  typedef CGAL::Triangulation_vertex_base_2<K> Vb;
103  typedef CGAL::Delaunay_mesh_face_base_2<K> Fb;
104  typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds;
105  typedef CGAL::Constrained_Delaunay_triangulation_2<K, Tds> CDT;
106  typedef CGAL::Delaunay_mesh_size_criteria_2<CDT> Criteria;
107  typedef CDT::Vertex_handle Vertex_handle;
108  typedef CDT::Point Point;
109  typedef CGAL::Polygon_2<K> Polygon_2;
110 
111  Polygon_2 polygon1;
112  for (auto &el : vertices) {
113  polygon1.push_back(Point(el[0], el[1]));
114  }
115  CDT cdt;
116  cdt.insert_constraint(polygon1.vertices_begin(), polygon1.vertices_end(),
117  true);
118 
119  CGAL::refine_Delaunay_mesh_2(cdt, Criteria(qual.mesh_quality, 0));
120 
121  for (CDT::Finite_faces_iterator fit = cdt.finite_faces_begin();
122  fit != cdt.finite_faces_end(); ++fit) {
123  Eigen::Vector2d vert1(cdt.triangle(fit)[0].x(), cdt.triangle(fit)[0].y());
124  Eigen::Vector2d vert2(cdt.triangle(fit)[1].x(), cdt.triangle(fit)[1].y());
125  Eigen::Vector2d vert3(cdt.triangle(fit)[2].x(), cdt.triangle(fit)[2].y());
126  triangles_out.emplace_back(new collision::Triangle(vert1, vert2, vert3));
127  }
128 
129  return 0;
130 }
131 #endif
132 
133 #if ENABLE_TRIANGLE
134 
135 #define FREE_IF_NONZERO(x) \
136  { \
137  if (x) free(x); \
138  }
139 
140 int triangulate_helper(std::vector<Eigen::Vector2d> vertices,
141  std::vector<collision::TriangleConstPtr> &triangles_out,
142  char *mode) {
143  struct triangulateio in, mid, out, vorout;
144 
145  /* Make necessary initializations so that Triangle can return a */
146  /* triangulation in `mid' and a voronoi diagram in `vorout'. */
147 
148  memset(&in, 0, sizeof(triangulateio));
149  memset(&mid, 0, sizeof(triangulateio));
150  memset(&out, 0, sizeof(triangulateio));
151  memset(&vorout, 0, sizeof(triangulateio));
152 
153  in.numberofpoints = vertices.size();
154  in.numberofpointattributes = 0;
155  in.pointlist = (REAL *)malloc(in.numberofpoints * 2 * sizeof(REAL));
156  for (int i = 0; i < in.numberofpoints; i++) {
157  in.pointlist[i * 2] = vertices[i][0];
158  in.pointlist[i * 2 + 1] = vertices[i][1];
159  }
160 
161  in.pointattributelist = 0;
162 
163  in.pointmarkerlist = 0;
164 
165  in.numberofsegments = in.numberofpoints;
166  in.segmentlist = (int *)malloc(in.numberofsegments * 2 * sizeof(int));
167  for (int cc1 = 0; cc1 < in.numberofpoints - 1; cc1++) {
168  in.segmentlist[cc1 * 2] = cc1;
169  in.segmentlist[cc1 * 2 + 1] = cc1 + 1;
170  }
171  in.segmentlist[(in.numberofpoints - 1) * 2] = in.numberofpoints - 1;
172  in.segmentlist[(in.numberofpoints - 1) * 2 + 1] = 0;
173 
174  in.numberofholes = 0;
175  in.numberofregions = 0;
176 
177  /* Triangulate the points. Switches are chosen to read and write a */
178  /* PSLG (p), preserve the convex hull (c), number everything from */
179  /* zero (z), assign a regional attribute to each element (A), and */
180  /* produce an edge list (e), a Voronoi diagram (v), and a triangle */
181  /* neighbor list (n). */
182 
183  triangulate(mode, &in, &mid, &vorout);
184 
185  for (int cc1 = 0; cc1 < mid.numberoftriangles; cc1++) {
186  double x_1 = mid.pointlist[mid.trianglelist[cc1 * 3] * 2];
187  double y_1 = mid.pointlist[mid.trianglelist[cc1 * 3] * 2 + 1];
188  double x_2 = mid.pointlist[mid.trianglelist[cc1 * 3 + 1] * 2];
189  double y_2 = mid.pointlist[mid.trianglelist[cc1 * 3 + 1] * 2 + 1];
190  double x_3 = mid.pointlist[mid.trianglelist[cc1 * 3 + 2] * 2];
191  double y_3 = mid.pointlist[mid.trianglelist[cc1 * 3 + 2] * 2 + 1];
192  triangles_out.push_back(std::make_shared<const collision::Triangle>(
193  Eigen::Vector2d(x_1, y_1), Eigen::Vector2d(x_2, y_2),
194  Eigen::Vector2d(x_3, y_3)));
195  }
196 
197  FREE_IF_NONZERO(in.pointlist);
198  FREE_IF_NONZERO(in.segmentlist);
199  FREE_IF_NONZERO(mid.pointlist);
200  FREE_IF_NONZERO(mid.pointattributelist);
201  FREE_IF_NONZERO(mid.pointmarkerlist);
202  FREE_IF_NONZERO(mid.trianglelist);
203  FREE_IF_NONZERO(mid.triangleattributelist);
204  FREE_IF_NONZERO(mid.trianglearealist);
205  FREE_IF_NONZERO(mid.neighborlist);
206  FREE_IF_NONZERO(mid.segmentlist);
207  FREE_IF_NONZERO(mid.segmentmarkerlist);
208  FREE_IF_NONZERO(mid.edgelist);
209  FREE_IF_NONZERO(mid.edgemarkerlist);
210  FREE_IF_NONZERO(vorout.pointlist);
211  FREE_IF_NONZERO(vorout.pointattributelist);
212  FREE_IF_NONZERO(vorout.edgelist);
213  FREE_IF_NONZERO(vorout.normlist);
214  FREE_IF_NONZERO(out.pointlist);
215  FREE_IF_NONZERO(out.pointattributelist);
216  FREE_IF_NONZERO(out.trianglelist);
217  FREE_IF_NONZERO(out.triangleattributelist);
218 
219  return 0;
220 }
221 
222 int do_triangulate_triangle(std::vector<Eigen::Vector2d> vertices,
223  std::vector<collision::TriangleConstPtr> &triangles_out) {
224  triangulate_helper(vertices, triangles_out, (char *)("pzQ"));
225  return 0;
226 }
227 
228 int do_triangulateQuality_triangle(
229  std::vector<Eigen::Vector2d> vertices,
230  std::vector<collision::TriangleConstPtr> &triangles_out,
231  TriangulationQuality qual) {
232  // preconditions: qual.quality_b_cgal is positive
233  if (qual.use_quality) {
234  char buffer[64];
235  int ret =
236  snprintf(buffer, sizeof buffer, "pzQq%.0f", qual.mesh_quality);
237  buffer[63] = 0;
238  triangulate_helper(vertices, triangles_out, buffer);
239  } else {
240  do_triangulate_triangle(vertices, triangles_out);
241  }
242  return 0;
243 }
244 #endif
245 #if ENABLE_GPC
246 
247 
248 gpc_polygon * gpc_poly_new() {
249  gpc_polygon *poly = (gpc_polygon *)malloc(sizeof(gpc_polygon));
250  if (poly) {
251  poly->num_contours = 0;
252  poly->contour = NULL;
253  poly->hole = NULL;
254  }
255  return poly;
256 }
257 
258 
259 int do_triangulate_gpc(std::vector<Eigen::Vector2d> vertices,
260  std::vector<collision::TriangleConstPtr> &triangles_out) {
261 
262 
263  gpc_polygon* gpc_p=gpc_poly_new();
264 
265  if(!gpc_p)
266  throw;
267 
268  gpc_vertex_list vl;
269 
270  auto gpc_vertices=new gpc_vertex[vertices.size()];
271 
272  if(!gpc_vertices)
273  throw;
274 
275  vl.num_vertices=vertices.size();
276  vl.vertex=gpc_vertices;
277 
278  int cc1=0;
279 
280  for(auto el:vertices)
281  {
282  vl.vertex[cc1].x=el[0];
283  vl.vertex[cc1].y=el[1];
284 
285  cc1++;
286  }
287 
288  gpc_add_contour(gpc_p, &vl, 0);
289 
290 
291  gpc_tristrip *t = (gpc_tristrip *)alloca(sizeof(gpc_tristrip));
292 
293  if(!t)
294  throw;
295 
296  t->num_strips = 0;
297  t->strip = NULL;
298 
299 
300 
301  gpc_polygon_to_tristrip(gpc_p, t);
302 
303  Eigen::Matrix<double, 2, 3> verts;
304 
305  for(int cc1=0; cc1<t->num_strips; cc1++)
306  {
307  for(int cc2=0; cc2<t->strip[cc1].num_vertices-2; cc2++)
308  {
309  auto vert=t->strip[cc1].vertex[cc2];
310  verts.col(0) = Eigen::Vector2d(vert.x,vert.y);
311 
312  vert=t->strip[cc1].vertex[cc2+1];
313  verts.col(1) = Eigen::Vector2d(vert.x,vert.y);
314 
315  vert=t->strip[cc1].vertex[cc2+2];
316  verts.col(2) = Eigen::Vector2d(vert.x,vert.y);
317 
318  triangles_out.push_back(std::make_shared<const collision::Triangle>(
319  verts.col(0), verts.col(1), verts.col(2)));
320 
321  }
322  }
323 
324  gpc_free_tristrip(t);
325 
326 
327  delete gpc_vertices;
328  gpc_free_polygon(gpc_p);
329  free(gpc_p);
330 
331  return 0;
332 }
333 
334 int do_triangulateQuality_gpc(
335  std::vector<Eigen::Vector2d> vertices,
336  std::vector<collision::TriangleConstPtr> &triangles_out,
337  TriangulationQuality qual)
338 {
339  return do_triangulate_gpc(vertices, triangles_out);
340 }
341 
342 
343 #endif
344 
345 int do_triangulate(std::vector<Eigen::Vector2d> vertices,
346  std::vector<collision::TriangleConstPtr> &triangles_out, int method) {
347 
348  switch(method)
349  {
350  case TRIANGULATION_GPC:
351  #if ENABLE_GPC
352  return do_triangulate_gpc(vertices,triangles_out);
353  #else
354  throw std::runtime_error("The drivability checker library was compiled without General Polygon Clipper support.");
355  #endif
356  break;
357 
358  case TRIANGULATION_TRIANGLE:
359  #if ENABLE_TRIANGLE
360  return do_triangulate_triangle(vertices,triangles_out);
361  #else
362  throw std::runtime_error("The drivability checker library was compiled without Triangle support.");
363  #endif
364  break;
365 
366  case TRIANGULATION_CGAL:
367  #if ENABLE_CGAL
368  return do_triangulate_cgal(vertices,triangles_out);
369  #else
370  throw std::runtime_error("The drivability checker library was compiled without CGAL support.");
371  #endif
372  break;
373  }
374  return 0;
375 }
376 
377 int do_triangulateQuality(
378  std::vector<Eigen::Vector2d> vertices,
379  std::vector<collision::TriangleConstPtr> &triangles_out, int method,
380  TriangulationQuality qual)
381 {
382  switch(method)
383  {
384  case TRIANGULATION_GPC:
385  #if ENABLE_GPC
386  return do_triangulateQuality_gpc(vertices,triangles_out, qual);
387  #else
388  throw std::runtime_error("The drivability checker library was compiled without General Polygon Clipper support.");
389  #endif
390  break;
391 
392  case TRIANGULATION_TRIANGLE:
393  #if ENABLE_TRIANGLE
394  return do_triangulateQuality_triangle(vertices,triangles_out, qual);
395  #else
396  throw std::runtime_error("The drivability checker library was compiled without Triangle support.");
397  #endif
398  break;
399 
400  case TRIANGULATION_CGAL:
401  #if ENABLE_CGAL
402  return do_triangulateQuality_cgal(vertices,triangles_out, qual);
403  #else
404  throw std::runtime_error("The drivability checker library was compiled without CGAL support.");
405  #endif
406  break;
407  }
408  return 0;
409 }
410 
411 } // namespace triangulation
412 } // namespace collision
413 #endif
Triangle.
Definition: triangle.h:17