donghong_ding_imp.hpp
Go to the documentation of this file.
1 #ifndef RAM_PATH_PLANNING_DONGHONG_DING_IMP_HPP
2 #define RAM_PATH_PLANNING_DONGHONG_DING_IMP_HPP
3 
4 namespace ram_path_planning
5 {
6 // Allow 4 concurrent threads, tweak depending on the machine you use
7 
8 template<class ActionSpec>
10  DonghongDingBase<ActionSpec>("DonghongDing", "Fill volume",
11  "ram/path_planning/generate_trajectory/donghong_ding"),
12  semaphore_(4)
13  {
14  this->deposited_material_width_ = 0.002; // 2 millimeters
15 
16  contours_filtering_tolerance_ = 0.0025; // 2.5 millimeters
17  polygon_division_tolerance_ = M_PI / 6; // 30 degrees
18  closest_to_bisector_ = false;
19  }
20 
21 template<class ActionSpec>
23  const int current_progrress_value,
24  const int next_progress_value,
25  const Polygon poly_data,
26  Layer &layer,
27  const double deposited_material_width,
28  const double contours_filtering_tolerance,
29  const std::array<double, 3> normal_vector,
30  const double polygon_division_tolerance,
31  const bool closest_to_bisector,
32  const bool use_gui)
33  {
34  // Publish feedback with a percentage between current_progrress_value and next_progress_value :
35  // progress_value = current_progrress_value + v * (next_progress_value - current_progrress_value )
36  // v is a parameter between 0 and 1
37 
38  float v = 0.0;
39  int progress_value = current_progrress_value;
40 
41  if (!poly_data)
42  return "Polydata is not initialized";
43 
44  if (poly_data->GetNumberOfPoints() == 0)
45  return "Polydata is empty";
46 
47  this->normal_vector_[0] = normal_vector[0];
48  this->normal_vector_[1] = normal_vector[1];
49  this->normal_vector_[2] = normal_vector[2];
50 
51  vtkMath::Normalize(this->normal_vector_);
52 
53  if (normal_vector[0] == 0 && normal_vector[1] == 0 && normal_vector[2] == 0)
54  {
55  this->normal_vector_[0] = 0;
56  this->normal_vector_[1] = 0;
57  this->normal_vector_[2] = 1;
58  }
59 
60  this->deposited_material_width_ = deposited_material_width;
61  polygon_division_tolerance_ = polygon_division_tolerance;
62  contours_filtering_tolerance_ = contours_filtering_tolerance;
63  closest_to_bisector_ = closest_to_bisector;
64 
65  if (!this->removeDuplicatePoints(poly_data, this->deposited_material_width_ / 2)) // tolerance default
66  return "Failed to remove duplicate points";
67 
69  return "Failed to merge colinear edges";
70 
71  if (this->intersectionBetweenContours(poly_data))
72  return "Contours intersects";
73 
74  std::vector<int> level;
75  std::vector<int> father;
76  this->identifyRelationships(poly_data, level, father);
77  if (!this->organizePolygonContoursInLayer(poly_data, level, father, layer))
78  return "Failed to organize polygon contours in layer";
79 
80  // Divide in convex polygons
81  vtkSmartPointer<vtkPoints> split_points = vtkSmartPointer<vtkPoints>::New();
82  for (unsigned i(0); i < layer.size(); ++i)
83  {
84  unsigned j = 0;
85  while (j < layer[i].size())
86  {
87 
88  if (use_gui)
89  {
90  std::string s;
91  std::getline(std::cin, s);
92  ROS_INFO_STREAM("Dividing in convex polygons");
93  }
94 
95  if (this->divideInConvexPolygons(layer[i], j, split_points))
96  {
97  vtkIdType n_cells = layer[i][j]->GetNumberOfCells();
98  if (n_cells == 1 && vtkPolygon::IsConvex(layer[i][j]->GetPoints()))
99  j++;
100  }
101  else
102  return "Error dividing the polygons";
103  }
104  // Action feedback
105  v = 0.5 * (i + 1) / layer.size();
106  progress_value = (int)(current_progrress_value + v * (next_progress_value - current_progrress_value));
107  if (!this->publishStatusPercentageDone("Dividing concave polygon " + std::to_string(i) + " in convex polygons",
108  progress_value,
109  gh))
110  return "GoalHandle is not active";
111  }
112 
113  if (use_gui)
114  {
115  std::string s;
116  std::getline(std::cin, s);
117  ROS_INFO_STREAM("Enter was pressed: zigzag in convex polygons");
118  }
119 
120  // Path generation in convex polygons
121  std::vector<std::future<bool> > futures;
122  for (auto polygons : layer)
123  for (auto poly_data : polygons)
124  futures.push_back(std::async(&DonghongDing::generateTrajectoryInConvexPolygon, this, poly_data));
125 
126  bool global_return = true;
127  for (auto &t : futures)
128  global_return &= t.get();
129  if (!global_return)
130  return "Failed to generate trajectory in one of the convex polygons";
131 
132  // Merge convex polygons. First method
133  vtkIdType n_lines = split_points->GetNumberOfPoints() / 2;
134  int current_line = 0;
135  unsigned polygon_id = layer.size() - 1;
136  for (int line_id(n_lines - 1); line_id >= 0; --line_id) // LIFO
137  {
138 
139  if (use_gui)
140  {
141  std::string s;
142  std::getline(std::cin, s);
143  ROS_INFO_STREAM("Enter was pressed: Merging polygons. Line " << line_id);
144  }
145 
146  // Action feedback
147  current_line++;
148  v = 0.5 + 0.5 * (current_line) / (n_lines);
149  progress_value = (int)(current_progrress_value + v * (next_progress_value - current_progrress_value));
150  if (!this->publishStatusPercentageDone("Merging polygons. Line " + std::to_string(line_id), progress_value, gh))
151  return "GoalHandle is not active";
152 
153  if (layer[polygon_id].size() == 1)
154  polygon_id--;
155  if (!mergeConvexPolygons(layer[polygon_id], split_points, line_id))
156  return "Failed to merge convex polygons";
157  }
158 
159  for (auto polygons : layer)
160  for (auto poly_data : polygons)
161  {
162  if (!this->removeDuplicatePoints(poly_data))
163  return "Failed to remove duplicate points";
164  if (!this->mergeColinearEdges(poly_data))
165  return "Failed to merge colinear edges";
166  }
167 
168  if (use_gui)
169  {
170  std::string s;
171  ROS_INFO_STREAM("Path generated on one layer");
172  std::getline(std::cin, s);
173  }
174  return "";
175  }
176 
177 template<class ActionSpec>
179  const int current_progrress_value,
180  const int next_progress_value,
181  const std::string yaml_file,
182  Layer &layer,
183  const double deposited_material_width,
184  const double contours_filtering_tolerance,
185  const double polygon_division_tolerance,
186  const bool closest_to_bisector,
187  const bool use_gui)
188  {
189  // Prepare contours
190  const Polygon poly_data = Polygon::New();
191  std::vector<unsigned> layer_count;
192  if (!ram_utils::yamlFileToPolydata2(yaml_file, poly_data, layer_count))
193  if (!ram_utils::yamlFileToPolydata(yaml_file, poly_data))
194  return "Could not parse the YAML file";
195 
196  std::array<double, 3> normal_vector = {0, 0, 1};
197  layer.clear();
198  return generateOneLayerTrajectory(gh, current_progrress_value, next_progress_value, poly_data, layer,
199  deposited_material_width,
200  contours_filtering_tolerance, normal_vector,
201  polygon_division_tolerance,
202  closest_to_bisector, use_gui);
203  }
204 
205 template<class ActionSpec>
207  vtkIdType &cell_id,
208  vtkIdType &pos,
209  double &angle)
210  {
211  vtkIdType n_cells = poly_data->GetNumberOfCells();
212 
213  for (vtkIdType i(0); i < n_cells; ++i)
214  {
215  // Points in the cell i
216  vtkIdType n_points = poly_data->GetCell(i)->GetNumberOfPoints();
217  for (vtkIdType j(0); j < n_points; ++j)
218  {
219  double p0[3];
220  double p1[3]; // Central point
221  double p2[3];
222 
223  if (j == 0)
224  poly_data->GetCell(i)->GetPoints()->GetPoint((n_points - 1), p0);
225  else
226  poly_data->GetCell(i)->GetPoints()->GetPoint((j - 1), p0);
227 
228  poly_data->GetCell(i)->GetPoints()->GetPoint(j, p1);
229  poly_data->GetCell(i)->GetPoints()->GetPoint((j + 1) % n_points, p2);
230 
231  double v1[3]; // Vector between p1 and p0
232  double v2[3]; // Vector between p1 and p2
233 
234  vtkMath::Subtract(p0, p1, v1);
235  vtkMath::Subtract(p2, p1, v2);
236 
237  angle = this->angleBetweenVectors(v1, v2);
238  if (angle < 0) // Found notch
239  {
240  cell_id = i;
241  pos = j;
242  return true;
243  }
244  }
245  }
246 
247  ROS_ERROR_STREAM("findNotch: Zero notch found");
248  return false;
249  }
250 
251 template<class ActionSpec>
253  const vtkIdType notch_cell_id,
254  const vtkIdType notch_pos,
255  const vtkIdType vertex_cell_id,
256  const vtkIdType vertex_pos)
257  {
258  vtkIdType n_points_cell;
259  double notch_prev[3];
260  double notch[3];
261  double notch_next[3]; // notch next point int the polygon
262  n_points_cell = poly_data->GetCell(notch_cell_id)->GetNumberOfPoints();
263 
264  if (notch_pos == 0)
265  poly_data->GetCell(notch_cell_id)->GetPoints()->GetPoint((n_points_cell - 1), notch_prev);
266  else
267  poly_data->GetCell(notch_cell_id)->GetPoints()->GetPoint((notch_pos - 1), notch_prev);
268  poly_data->GetCell(notch_cell_id)->GetPoints()->GetPoint(notch_pos, notch);
269  poly_data->GetCell(notch_cell_id)->GetPoints()->GetPoint((notch_pos + 1) % n_points_cell, notch_next);
270 
271  double vertex_prev[3];
272  double vertex[3];
273  double vertex_next[3]; // vertex next point int the polygon
274  n_points_cell = poly_data->GetCell(vertex_cell_id)->GetNumberOfPoints();
275 
276  if (vertex_pos == 0)
277  poly_data->GetCell(vertex_cell_id)->GetPoints()->GetPoint((n_points_cell - 1), vertex_prev);
278  else
279  poly_data->GetCell(vertex_cell_id)->GetPoints()->GetPoint((vertex_pos - 1), vertex_prev);
280  poly_data->GetCell(vertex_cell_id)->GetPoints()->GetPoint(vertex_pos, vertex);
281  poly_data->GetCell(vertex_cell_id)->GetPoints()->GetPoint((vertex_pos + 1) % n_points_cell, vertex_next);
282 
283  // angles
284  double v_1[3];
285  double v_2[3];
286  //angle 1: between the lines notch - notch_prev and notch - vertex
287  vtkMath::Subtract(vertex, notch, v_2);
288  vtkMath::Subtract(notch_prev, notch, v_1);
289  if (vtkMath::AngleBetweenVectors(v_1, v_2) < polygon_division_tolerance_)
290  return false;
291  //angle 2: between the lines notch - notch_next and notch - vertex
292  vtkMath::Subtract(notch_next, notch, v_1);
293  if (vtkMath::AngleBetweenVectors(v_1, v_2) < polygon_division_tolerance_)
294  return false;
295  //angle 3: between the lines vertex - vertex_prev and notch - vertex
296  vtkMath::Subtract(notch, vertex, v_2);
297  vtkMath::Subtract(vertex_prev, vertex, v_1);
298  if (vtkMath::AngleBetweenVectors(v_1, v_2) < polygon_division_tolerance_)
299  return false;
300  //angle 4: between the lines vertex - vertex_next and notch - vertex
301  vtkMath::Subtract(vertex_next, vertex, v_1);
302  if (vtkMath::AngleBetweenVectors(v_1, v_2) < polygon_division_tolerance_)
303  return false;
304  return true;
305  }
306 
307 template<class ActionSpec>
309  double point_1[3],
310  double point_2[3])
311  {
312  vtkIdType n_cells = poly_data->GetNumberOfCells();
313  for (vtkIdType cell_id(0); cell_id < n_cells; ++cell_id) //verify intersections with the geometries
314  {
315  vtkIdType n_edges = poly_data->GetCell(cell_id)->GetNumberOfEdges();
316  for (vtkIdType edge_id(0); edge_id < n_edges; ++edge_id)
317  {
318  double e_p1[3];
319  double e_p2[3];
320  poly_data->GetCell(cell_id)->GetEdge(edge_id)->GetPoints()->GetPoint(0, e_p1);
321  poly_data->GetCell(cell_id)->GetEdge(edge_id)->GetPoints()->GetPoint(1, e_p2);
322  double u;
323  double v;
324  int intersection = 0;
325  //intersect the line "notch p_1" with the edge(line e_p1 e_p2)
326  intersection = vtkLine::Intersection3D(point_1, point_2, e_p1, e_p2, u, v);
327  if (intersection == 2 && std::abs(u) > this->calculation_tol_ && std::abs(u - 1) > this->calculation_tol_) // u!= 0 &&0u!=1
328  return true;
329  }
330  }
331  return false;
332  }
333 
334 template<class ActionSpec>
336  const vtkIdType notch_cell_id,
337  const vtkIdType notch_pos,
338  vtkIdType &vertex_cell_id,
339  vtkIdType &vertex_pos,
340  const double notch_angle)
341  {
342  double ref_angle = notch_angle * (-1);
343  vtkIdType n_cells = poly_data->GetNumberOfCells();
344  bool is_vertex = false;
345 
346  //2.1. reference vectors
347  double v_ref[3];
348 
349  double notch[3];
350  double notch_next[3]; // notch next point int the polygon
351  vtkIdType n_points_cell = poly_data->GetCell(notch_cell_id)->GetNumberOfPoints();
352  poly_data->GetCell(notch_cell_id)->GetPoints()->GetPoint(notch_pos, notch);
353  poly_data->GetCell(notch_cell_id)->GetPoints()->GetPoint((notch_pos + 1) % n_points_cell, notch_next);
354  vtkMath::Subtract(notch, notch_next, v_ref); //vector between p2 and p1. reference vector
355 
356  //2.2. Determine whether the points are inside the zone
357  bool is_notch = false; //Flag. change if the the possible second point is a notch
358  float vertex_d = FLT_MAX;
359  for (vtkIdType cell_id(0); cell_id < n_cells; ++cell_id)
360  {
361  vtkIdType n_points = poly_data->GetCell(cell_id)->GetNumberOfPoints();
362  for (vtkIdType point_id(0); point_id < n_points; ++point_id)
363  {
364  double p0[3];
365  double p[3]; // Central point
366  double p2[3];
367  if (point_id == 0)
368  poly_data->GetCell(cell_id)->GetPoints()->GetPoint((n_points - 1), p0);
369  else
370  poly_data->GetCell(cell_id)->GetPoints()->GetPoint((point_id - 1), p0);
371  poly_data->GetCell(cell_id)->GetPoints()->GetPoint(point_id, p);
372  poly_data->GetCell(cell_id)->GetPoints()->GetPoint((point_id + 1) % n_points, p2);
373 
374  double vector[3]; // Vector between the notch and the possible second point of the line
375  vtkMath::Subtract(p, notch, vector);
376  double angle = this->angleBetweenVectors(v_ref, vector); // Calculate angle
377 
378  if (!(angle >= 0 && angle <= ref_angle)) // Point is not inside the reference area
379  continue;
380  // Measure and verify intersections with the geometries
381  if (intersectLineWithContours(poly_data, notch, p))
382  continue;
383 
384  // Verify if the point is a notch
385  double p1_p0[3]; // Vector between p1 and p0
386  double p2_p0[3]; // Vector between p1 and p2
387  vtkMath::Subtract(p0, p, p1_p0);
388  vtkMath::Subtract(p2, p, p2_p0);
389  double point_angle = this->angleBetweenVectors(p1_p0, p2_p0);
390 
391  // Verify the flag
392  if (point_angle < 0)
393  if (!is_notch)
394  {
395  vertex_d = FLT_MAX;
396  is_notch = true;
397  }
398  if (!((point_angle > 0 && !is_notch) || point_angle < 0))
399  continue;
400 
401  double point_d; // Distance between the notch and p
402 
403  // Compute distance between the notch and p1
405  point_d = sqrt(vtkMath::Distance2BetweenPoints(notch, p)) * std::abs(sin(angle - ref_angle / 2));
406  else
407  point_d = sqrt(vtkMath::Distance2BetweenPoints(notch, p));
408 
409  if (point_d < vertex_d)
410  {
411  // Save point
412  vertex_d = point_d;
413  is_vertex = true;
414  vertex_pos = point_id;
415  vertex_cell_id = cell_id;
416 
417  }
418  }
419  }
420 
421  return is_vertex;
422  }
423 
424 template<class ActionSpec>
426  const vtkIdType notch_cell_id,
427  const vtkIdType notch_pos,
428  vtkIdType &vertex_cell_id,
429  vtkIdType &vertex_pos,
430  double vertex[3])
431  {
432  double notch_prev[3];
433  double notch[3]; // Central point
434  double notch_next[3];
435 
436  vtkIdType n_points_cell = poly_data->GetCell(notch_cell_id)->GetNumberOfPoints();
437 
438  if (notch_pos == 0)
439  poly_data->GetCell(notch_cell_id)->GetPoints()->GetPoint((n_points_cell - 1), notch_prev);
440  else
441  poly_data->GetCell(notch_cell_id)->GetPoints()->GetPoint((notch_pos - 1), notch_prev);
442  poly_data->GetCell(notch_cell_id)->GetPoints()->GetPoint(notch_pos, notch);
443  poly_data->GetCell(notch_cell_id)->GetPoints()->GetPoint((notch_pos + 1) % n_points_cell, notch_next);
444 
445  // Vector between p0 and p1
446  double v1[3] = {notch[0] - notch_prev[0], notch[1] - notch_prev[1], notch[2] - notch_prev[2]};
447  // Vector between p2 and p1. Vector reference
448  double v2[3] = {notch[0] - notch_next[0], notch[1] - notch_next[1], notch[2] - notch_next[2]};
449  vtkMath::Normalize(v1);
450  vtkMath::Normalize(v2);
451  double bisector[3] = {v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]}; // Vector in the bisector direction
452  vtkMath::Normalize(bisector);
453  double bounds[6];
454  poly_data->GetPoints()->GetBounds(bounds);
455  double bound_min[3] = {bounds[0], bounds[2], bounds[4]};
456  double bound_max[3] = {bounds[1], bounds[3], bounds[5]};
457 
458  // Maximum distance between all points in a polyData
459  double d_max = sqrt(vtkMath::Distance2BetweenPoints(bound_min, bound_max));
460 
461  // Bisector: between notch and bisector_p. bisector_p = notch + d_max*bisector
462  double bisector_p[3];
463  for (unsigned i(0); i < 3; ++i)
464  bisector_p[i] = notch[i] + d_max * bisector[i];
465 
466  // find the intersection point
467  double vertex_coordinate = DBL_MAX;
468  bool find_intersection = false; // flag
469  vtkIdType n_cells = poly_data->GetNumberOfCells();
470 
471  for (vtkIdType cell_id(0); cell_id < n_cells; ++cell_id) // Verify intersections with the geometries
472  {
473  vtkIdType n_edges = poly_data->GetCell(cell_id)->GetNumberOfEdges();
474  for (vtkIdType edge_id(0); edge_id < n_edges; ++edge_id)
475  {
476  double e_p1[3];
477  double e_p2[3];
478  poly_data->GetCell(cell_id)->GetEdge(edge_id)->GetPoints()->GetPoint(0, e_p1);
479  poly_data->GetCell(cell_id)->GetEdge(edge_id)->GetPoints()->GetPoint(1, e_p2);
480  double u;
481  double v;
482  int intersection = 0;
483  intersection = vtkLine::Intersection3D(notch, bisector_p, e_p1, e_p2, u, v);
484  if (u < vertex_coordinate && intersection == 2 && std::abs(u) > this->calculation_tol_
485  && std::abs(u - 1) > this->calculation_tol_) // u!= 0 &&0u!=1
486  {
487  //save point
488  find_intersection = true;
489  vertex_coordinate = u;
490  vertex_cell_id = cell_id;
491  vertex_pos = edge_id;
492  }
493  }
494  }
495 
496  if (find_intersection == false)
497  {
498  ROS_ERROR_STREAM("findIntersectWithBisector: Intersection not found");
499  return false;
500  }
501 
502  for (unsigned i = 0; i < 3; i++)
503  vertex[i] = notch[i] + vertex_coordinate * d_max * bisector[i];
504 
505  return true;
506  }
507 
508 template<class ActionSpec>
510  const int polygon_position,
511  const vtkSmartPointer<vtkPoints> split_points)
512  {
513  this->removeDuplicatePoints(polygon_source[polygon_position]);
514  this->mergeColinearEdges(polygon_source[polygon_position]);
515 
516  vtkSmartPointer<vtkPolyData> poly_data = vtkSmartPointer<vtkPolyData>::New();
517  poly_data->DeepCopy(polygon_source[polygon_position]);
518  vtkIdType n_cells = poly_data->GetNumberOfCells();
519  if (n_cells == 0)
520  {
521  ROS_WARN_STREAM("divideInConvexPolygons: poly_data is empty");
522  return true;
523  }
524  if (n_cells == 1 && vtkPolygon::IsConvex(poly_data->GetPoints()))
525  {
526  return true;
527  }
528 
529  //1. find first notch
530  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
531  points = poly_data->GetPoints();
532 
533  vtkIdType notch_cell_id;
534  vtkIdType notch_id;
535  double angle;
536  if (!findNotch(poly_data, notch_cell_id, notch_id, angle))
537  return false;
538  double notch[3];
539  poly_data->GetCell(notch_cell_id)->GetPoints()->GetPoint(notch_id, notch);
540 
541  vtkIdType vertex_cell_id;
542  vtkIdType vertex_pos; //position in the polygon
543  vtkIdType vertex_edge_id; //edge id if this point is not a vertex --
544  double vertex[3];
545 
546  //2. find second point of the dividing line (vertex)
547  bool is_vertex(findVertex(poly_data, notch_cell_id, notch_id, vertex_cell_id, vertex_pos, angle));
548 
549  if (is_vertex)
550  is_vertex = verifyAngles(poly_data, notch_cell_id, notch_id, vertex_cell_id, vertex_pos);
551  //2.3. Eliminate notch
552  if (is_vertex == false)
553  {
554  if (!findIntersectWithBisector(poly_data, notch_cell_id, notch_id, vertex_cell_id, vertex_edge_id, vertex))
555  return false;
556  }
557  else
558  poly_data->GetCell(vertex_cell_id)->GetPoints()->GetPoint(vertex_pos, vertex);
559  //3. make the news polydatas (poly_data_a, poly_data_b)
560 
561  // 4 cases:
562  // case 1: notch and vertex are inside the same contour (polygon 0)
563  // case 2: notch is in the external contour and vertex is in a contour child
564  // case 3: notch is in a contour child and vertex is in the external contour
565  // case 4: notch and vertex are in different contour children
566  // poly_data_a and poly_data_b
567  vtkSmartPointer<vtkCellArray> polygon_array_a = vtkSmartPointer<vtkCellArray>::New();
568  vtkSmartPointer<vtkPoints> points_a = vtkSmartPointer<vtkPoints>::New();
569 
570  vtkSmartPointer<vtkCellArray> polygon_array_b = vtkSmartPointer<vtkCellArray>::New();
571  vtkSmartPointer<vtkPoints> points_b = vtkSmartPointer<vtkPoints>::New();
572 
573  vtkSmartPointer<vtkPoints> point_list = vtkSmartPointer<vtkPoints>::New();
574  vtkSmartPointer<vtkPolygon> polygon_a = vtkSmartPointer<vtkPolygon>::New();
575  vtkSmartPointer<vtkPolygon> polygon_b = vtkSmartPointer<vtkPolygon>::New();
576 
577  double p[3];
578  // CASE 1,
579  // -vertex_pos > notch_id (case 1.1)
580  // -vertex_pos < notch_id (case 1.2)
581 
582  // save the external contours
583  point_list = poly_data->GetCell(0)->GetPoints();
584  vtkIdType last_point_a;
585  vtkIdType first_point_b;
586  if (notch_cell_id == 0 && vertex_cell_id == 0)
587  {
588  if (is_vertex == true)
589  {
590  split_points->InsertNextPoint(notch);
591  split_points->InsertNextPoint(vertex);
592  last_point_a = vertex_pos;
593  first_point_b = vertex_pos;
594  }
595  else
596  {
597  split_points->InsertNextPoint(vertex);
598  split_points->InsertNextPoint(notch);
599  last_point_a = vertex_edge_id;
600  first_point_b = (vertex_edge_id + 1) % point_list->GetNumberOfPoints(); // if Vertex is between the last point and the first point
601  // Save Vertex in poly_data_a
602  polygon_a->GetPointIds()->InsertNextId(points_a->GetNumberOfPoints());
603  polygon_a->GetPoints()->InsertNextPoint(vertex);
604  points_a->InsertNextPoint(vertex);
605  // Save Vertex in poly_data_b
606  polygon_b->GetPointIds()->InsertNextId(points_b->GetNumberOfPoints());
607  polygon_b->GetPoints()->InsertNextPoint(vertex);
608  points_b->InsertNextPoint(vertex);
609  }
610  vtkIdType n_points = point_list->GetNumberOfPoints();
611  for (vtkIdType i(0); i < n_points; ++i)
612  {
613  int id = (i + notch_id) % n_points;
614  point_list->GetPoint(id, p);
615  if (first_point_b > notch_id)
616  {
617  if (id >= notch_id && id <= last_point_a)
618  {
619  polygon_a->GetPointIds()->InsertNextId(points_a->GetNumberOfPoints());
620  polygon_a->GetPoints()->InsertNextPoint(p);
621  points_a->InsertNextPoint(p);
622  }
623  if (id >= first_point_b || id < notch_id)
624  {
625  polygon_b->GetPointIds()->InsertNextId(points_b->GetNumberOfPoints());
626  polygon_b->GetPoints()->InsertNextPoint(p);
627  points_b->InsertNextPoint(p);
628  }
629  }
630  else if (first_point_b < notch_id)
631  {
632  if (id >= notch_id || (last_point_a < notch_id && id <= last_point_a))
633  {
634  polygon_a->GetPointIds()->InsertNextId(points_a->GetNumberOfPoints());
635  polygon_a->GetPoints()->InsertNextPoint(p);
636  points_a->InsertNextPoint(p);
637  }
638 
639  if (id >= first_point_b && id < notch_id)
640  {
641  polygon_b->GetPointIds()->InsertNextId(points_b->GetNumberOfPoints());
642  polygon_b->GetPoints()->InsertNextPoint(p);
643  points_b->InsertNextPoint(p);
644  }
645  }
646  }
647  point_list->GetPoint(notch_id, p);
648  polygon_b->GetPointIds()->InsertNextId(points_b->GetNumberOfPoints());
649  polygon_b->GetPoints()->InsertNextPoint(p);
650  points_b->InsertNextPoint(p);
651 
652  polygon_array_a->InsertNextCell(polygon_a);
653  polygon_array_b->InsertNextCell(polygon_b);
654  //save the others polygons in the polydata
655  vtkSmartPointer<vtkPolygon> external_contour_a = vtkSmartPointer<vtkPolygon>::New();
656  external_contour_a->DeepCopy(polygon_a);
657  for (vtkIdType i = 1; i < n_cells; i++)
658  {
659  polygon_a = vtkSmartPointer<vtkPolygon>::New();
660  polygon_b = vtkSmartPointer<vtkPolygon>::New();
661  point_list = poly_data->GetCell(i)->GetPoints();
662  point_list->GetPoint(0, p);
663  double n[3];
664  this->computeNormal(external_contour_a->GetPoints(), n);
665  double bounds[6];
666  external_contour_a->GetPoints()->GetBounds(bounds);
667 
668  int in_polygon_a = external_contour_a->PointInPolygon(
669  p, external_contour_a->GetPoints()->GetNumberOfPoints(),
670  static_cast<double*>(external_contour_a->GetPoints()->GetData()->GetVoidPointer(0)),
671  bounds, n);
672 
673  if (in_polygon_a == 1) // Save the contour in poly_data_a
674  {
675  for (vtkIdType j = 0; j < point_list->GetNumberOfPoints(); ++j)
676  {
677  point_list->GetPoint(j, p);
678  polygon_a->GetPointIds()->InsertNextId(points_a->GetNumberOfPoints());
679  polygon_a->GetPoints()->InsertNextPoint(p);
680  points_a->InsertNextPoint(p);
681  }
682  polygon_array_a->InsertNextCell(polygon_a);
683  }
684  if (in_polygon_a == 0) // Save the contour in poly_data_b
685  {
686  for (vtkIdType j = 0; j < point_list->GetNumberOfPoints(); ++j)
687  {
688  point_list->GetPoint(j, p);
689  polygon_b->GetPointIds()->InsertNextId(points_b->GetNumberOfPoints());
690  polygon_b->GetPoints()->InsertNextPoint(p);
691  points_b->InsertNextPoint(p);
692  }
693  polygon_array_b->InsertNextCell(polygon_b);
694  }
695  }
696  }
697  // cases 2,3 and 4
698  vtkIdType n_points;
699  if (notch_cell_id != vertex_cell_id) // 1 polydata (polydata_a)
700  {
701  vtkIdType first_point_vertex_contour;
702  if (notch_cell_id != 0 && vertex_cell_id != 0) //CASE 4
703  {
704  //External contour in case 4
705  polygon_a = vtkSmartPointer<vtkPolygon>::New();
706  point_list = poly_data->GetCell(0)->GetPoints();
707  for (vtkIdType j = 0; j < point_list->GetNumberOfPoints(); ++j)
708  {
709  point_list->GetPoint(j, p);
710  polygon_a->GetPointIds()->InsertNextId(points_a->GetNumberOfPoints());
711  points_a->InsertNextPoint(p);
712  }
713  polygon_array_a->InsertNextCell(polygon_a);
714  polygon_a = vtkSmartPointer<vtkPolygon>::New();
715  }
716  // notch contour
717  point_list = poly_data->GetCell(notch_cell_id)->GetPoints();
718  n_points = point_list->GetNumberOfPoints();
719  double delta[3];
720 
721  for (vtkIdType i = 0; i <= n_points; i++)
722  {
723  vtkIdType pos = (i + notch_id) % n_points;
724  point_list->GetPoint(pos, p);
725  //modify the notch point
726  if (i == 0)
727  {
728  double next_point[3];
729  point_list->GetPoint((i + 1 + notch_id) % n_points, next_point);
730  vtkMath::Subtract(next_point, p, delta);
731  vtkMath::Normalize(delta);
732  vtkMath::MultiplyScalar(delta, 1e-7);
733  vtkMath::Add(p, delta, p);
734  }
735  polygon_a->GetPointIds()->InsertNextId(points_a->GetNumberOfPoints());
736  polygon_a->GetPoints()->InsertNextPoint(p);
737  points_a->InsertNextPoint(p);
738  }
739  //vertex contour
740  point_list = poly_data->GetCell(vertex_cell_id)->GetPoints();
741  n_points = point_list->GetNumberOfPoints();
742  if (is_vertex == true)
743  first_point_vertex_contour = vertex_pos;
744  else
745  {
746  first_point_vertex_contour = (vertex_edge_id + 1) % n_points;
747  polygon_a->GetPointIds()->InsertNextId(points_a->GetNumberOfPoints());
748  points_a->InsertNextPoint(vertex);
749  }
750 
751  for (vtkIdType i = 0; i < n_points; i++)
752  {
753  vtkIdType pos = (i + first_point_vertex_contour) % n_points;
754  point_list->GetPoint(pos, p);
755  polygon_a->GetPointIds()->InsertNextId(points_a->GetNumberOfPoints());
756  points_a->InsertNextPoint(p);
757  }
758  polygon_a->GetPointIds()->InsertNextId(points_a->GetNumberOfPoints());
759  vtkMath::Add(vertex, delta, vertex);
760  points_a->InsertNextPoint(vertex);
761 
762  polygon_array_a->InsertNextCell(polygon_a);
763  //save the others polygons in the polydata
764  for (vtkIdType i = 1; i < n_cells; i++)
765  {
766  if (i != vertex_cell_id && i != notch_cell_id)
767  {
768  polygon_a = vtkSmartPointer<vtkPolygon>::New();
769  point_list = poly_data->GetCell(i)->GetPoints();
770  for (vtkIdType j = 0; j < point_list->GetNumberOfPoints(); ++j)
771  {
772  point_list->GetPoint(j, p);
773  polygon_a->GetPointIds()->InsertNextId(points_a->GetNumberOfPoints());
774  points_a->InsertNextPoint(p);
775  }
776  polygon_array_a->InsertNextCell(polygon_a);
777  }
778  }
779  }
780 // end cases
781  vtkSmartPointer<vtkPolyData> poly_data_a = vtkSmartPointer<vtkPolyData>::New();
782  poly_data_a->SetPolys(polygon_array_a);
783  poly_data_a->SetPoints(points_a);
784  polygon_source.erase(polygon_source.begin() + polygon_position);
785  polygon_source.push_back(poly_data_a);
786 
787  if (polygon_array_b->GetNumberOfCells() > 0)
788  {
789  vtkSmartPointer<vtkPolyData> poly_data_b = vtkSmartPointer<vtkPolyData>::New();
790  poly_data_b->SetPolys(polygon_array_b);
791  poly_data_b->SetPoints(points_b);
792  polygon_source.push_back(poly_data_b);
793  }
794  return true;
795  }
796 
797 template<class ActionSpec>
799  vtkIdType &edge,
800  vtkIdType &opposite_point_id)
801  {
802  if (poly_data->GetNumberOfCells() != 1)
803  {
804  ROS_ERROR_STREAM("identifyZigzagDirection: multiple or zero cells in the polydata");
805  return -1;
806  }
807 
808  vtkIdType n_points = poly_data->GetCell(0)->GetNumberOfPoints(); // number of points is equal to number of edges
809  double min_global_h = DBL_MAX;
810 
811  for (vtkIdType edge_id(0); edge_id < n_points; ++edge_id)
812  {
813  double e_p1[3];
814  double e_p2[3];
815  poly_data->GetCell(0)->GetEdge(edge_id)->GetPoints()->GetPoint(0, e_p1);
816  poly_data->GetCell(0)->GetEdge(edge_id)->GetPoints()->GetPoint(1, e_p2);
817 
818  double max_local_h = 0;
819  vtkIdType local_opposite_point = 0; // opposite point to the edge (edge_id)
820  for (vtkIdType point_id(0); point_id < n_points; ++point_id)
821  {
822  if (point_id != edge_id && point_id != (edge_id + 1) % n_points)
823  {
824  double point[3];
825  poly_data->GetCell(0)->GetPoints()->GetPoint(point_id, point);
826  double h = sqrt(vtkLine::DistanceToLine(point, e_p1, e_p2));
827 
828  double delta_h = h - max_local_h;
829  if (delta_h > this->calculation_tol_) // h > max_local_h
830  {
831  max_local_h = h;
832  local_opposite_point = point_id;
833  }
834  else if (std::abs(delta_h) < this->calculation_tol_) // two points at the same distance. Find the closest point to e_p2
835  {
836  double max_point[3];
837  poly_data->GetCell(0)->GetPoints()->GetPoint(local_opposite_point, max_point);
838 
839  if (vtkMath::Distance2BetweenPoints(point, e_p2) < vtkMath::Distance2BetweenPoints(max_point, e_p2))
840  local_opposite_point = point_id;
841  }
842  }
843  }
844  if (max_local_h < min_global_h)
845  {
846  min_global_h = max_local_h;
847  edge = edge_id;
848  opposite_point_id = local_opposite_point;
849  }
850  }
851  return min_global_h;
852  }
853 
854 template<class ActionSpec>
856  const vtkIdType edge_id,
857  const vtkIdType opposite_point_id,
858  const vtkSmartPointer<vtkPoints> left_chain,
859  const vtkSmartPointer<vtkPoints> right_chain)
860  {
861  vtkIdType n_points = poly_data->GetCell(0)->GetNumberOfPoints();
862  // edge points :
863  double e_p1[3];
864  double e_p2[3];
865  poly_data->GetCell(0)->GetEdge(edge_id)->GetPoints()->GetPoint(0, e_p1);
866  poly_data->GetCell(0)->GetEdge(edge_id)->GetPoints()->GetPoint(1, e_p2);
867 
868  double p[3];
869  poly_data->GetCell(0)->GetPoints()->GetPoint(opposite_point_id, p);
870  vtkIdType last_point_id = opposite_point_id;
871  vtkIdType first_point_id = (edge_id + 1) % n_points;
872 
873  poly_data->GetCell(0)->GetPoints()->GetPoint(last_point_id, p);
874  right_chain->InsertNextPoint(p);
875 
876  for (vtkIdType i(0); i < n_points; ++i)
877  {
878  int id = (i + first_point_id) % n_points;
879 
880  poly_data->GetCell(0)->GetPoints()->GetPoint(id, p);
881 
882  if (last_point_id > first_point_id)
883  {
884  if (id >= first_point_id && id <= last_point_id)
885  left_chain->InsertNextPoint(p);
886  else
887  right_chain->InsertNextPoint(p);
888  }
889  else
890  {
891  if (id < first_point_id && id > last_point_id)
892  right_chain->InsertNextPoint(p);
893  else
894  left_chain->InsertNextPoint(p);
895  }
896  }
897  }
898 
899 template<class ActionSpec>
901  const vtkIdType edge_id,
902  const vtkIdType opposite_point_id,
903  const vtkSmartPointer<vtkPoints> left_chain,
904  const vtkSmartPointer<vtkPoints> right_chain)
905  {
906  if (poly_data->GetNumberOfCells() != 1)
907  {
908  ROS_ERROR_STREAM("offsetLeftChain: multiple or zero cells in the polydata");
909  return false;
910  }
911  vtkIdType n_points = poly_data->GetCell(0)->GetNumberOfPoints();
912  double e_p1[3];
913  double e_p2[3];
914  poly_data->GetCell(0)->GetEdge(edge_id)->GetPoints()->GetPoint(0, e_p1);
915  poly_data->GetCell(0)->GetEdge(edge_id)->GetPoints()->GetPoint(1, e_p2);
916 
917  vtkIdType first_point_id = (edge_id + 1) % n_points;
918  // 1. offset the polygon
919  // 1.1. identify the new points
920  double angle_first_point = M_PI / 2; // Because sin(angle_first_point) = 1
921  vtkSmartPointer<vtkPoints> new_points = vtkSmartPointer<vtkPoints>::New();
922  for (vtkIdType i(0); i < left_chain->GetNumberOfPoints(); ++i)
923  {
924  vtkIdType id = (first_point_id + i) % n_points;
925  double p0[3];
926  double p1[3]; //point
927  double p2[3];
928 
929  double v1[3];
930  double v2[3];
931  double angle;
932  double bisector[3];
933  double new_point[3];
934 
935  if (id == 0)
936  poly_data->GetCell(0)->GetPoints()->GetPoint((n_points - 1), p0);
937  else
938  poly_data->GetCell(0)->GetPoints()->GetPoint((id - 1), p0);
939  poly_data->GetCell(0)->GetPoints()->GetPoint(id, p1);
940  poly_data->GetCell(0)->GetPoints()->GetPoint((id + 1) % n_points, p2);
941 
942  vtkMath::Subtract(p0, p1, v1);
943  vtkMath::Subtract(p2, p1, v2);
944  vtkMath::Normalize(v1);
945  vtkMath::Normalize(v2);
946  angle = vtkMath::AngleBetweenVectors(v1, v2);
947  if (i == 0)
948  {
949  angle_first_point = angle; // Save the value to modify the last point in the first hull
950  for (int k = 0; k < 3; ++k)
951  new_point[k] = p1[k] + this->deposited_material_width_ / sin(angle) * v1[k];
952  if (sqrt(vtkMath::Distance2BetweenPoints(p1, new_point)) > sqrt(vtkMath::Distance2BetweenPoints(p1, p0)))
953  {
954  ROS_ERROR_STREAM("offsetLeftChain: error modifying the first point in the left chain");
955  return false;
956  }
957  }
958  else if (i == (left_chain->GetNumberOfPoints() - 1))
959  {
960  for (int k = 0; k < 3; ++k)
961  new_point[k] = p1[k] + this->deposited_material_width_ / sin(angle) * v2[k];
962  if (sqrt(vtkMath::Distance2BetweenPoints(p1, new_point)) > sqrt(vtkMath::Distance2BetweenPoints(p1, p2)))
963  {
964  ROS_ERROR_STREAM("offsetLeftChain: error modifying the last point in the left chain");
965  return false;
966  }
967  }
968  else
969  {
970  vtkMath::Add(v1, v2, bisector);
971  vtkMath::Normalize(bisector);
972  for (int k = 0; k < 3; ++k)
973  new_point[k] = p1[k] + this->deposited_material_width_ / sin(angle / 2) * bisector[k];
974  }
975  new_points->InsertNextPoint(new_point);
976  }
977 
978  // 1.2. verification, intersection among the lines
979  for (vtkIdType i(0); i < left_chain->GetNumberOfPoints(); ++i)
980  {
981  double p_i[3];
982  double new_p_i[3];
983  left_chain->GetPoint(i, p_i);
984  new_points->GetPoint(i, new_p_i);
985 
986  for (vtkIdType j(0); j < left_chain->GetNumberOfPoints(); ++j)
987  {
988  double p_j[3];
989  double new_p_j[3];
990  left_chain->GetPoint(i, p_j);
991  new_points->GetPoint(i, new_p_j);
992 
993  double u; // Parametric coordinate of the line 1
994  double v; // Parametric coordinate of the line 2
995  int intersection = vtkLine::Intersection3D(p_i, new_p_i, p_j, new_p_j, u, v);
996 
997  if (intersection == 2)
998  {
999  ROS_ERROR_STREAM("offsetLeftChain: edge is too short");
1000  return false;
1001  }
1002  }
1003  }
1004 
1005  // 1.3. replace the points in the poly_data
1006  for (vtkIdType i(0); i < left_chain->GetNumberOfPoints(); ++i)
1007  {
1008  vtkIdType id = (first_point_id + i) % n_points;
1009  double new_point[3];
1010  new_points->GetPoint(i, new_point);
1011  poly_data->GetPoints()->SetPoint(poly_data->GetCell(0)->GetPointId(id), new_point);
1012  poly_data->Modified();
1013  }
1014 
1015  // 2. modify first point in the second hull
1016  double p0[3]; // first point in the second hull
1017  double p1[3]; // opposite point in the polygon after offset
1018  double p2[3]; // next point to p1
1019  double v[3];
1020  right_chain->GetPoint(0, p0);
1021  poly_data->GetCell(0)->GetPoints()->GetPoint(opposite_point_id, p1);
1022  poly_data->GetCell(0)->GetPoints()->GetPoint((opposite_point_id + 1) % n_points, p2);
1023 
1024  if (vtkMath::Distance2BetweenPoints(p0, p1) >= vtkMath::Distance2BetweenPoints(p1, p2))
1025  {
1026  ROS_ERROR_STREAM("offsetLeftChain: Error modifying the point between the zigzag path and the right chain");
1027  return false;
1028  }
1029 
1030  vtkMath::Subtract(p1, p0, v);
1031  for (int k = 0; k < 3; ++k)
1032  p0[k] += 2 * v[k];
1033  right_chain->SetPoint(0, p0);
1034 
1035  // 3. add modified points in the first hull
1036  for (vtkIdType i(left_chain->GetNumberOfPoints() - 1); i >= 0; --i)
1037  {
1038  vtkIdType id = (first_point_id + i) % n_points;
1039  double p[3];
1040  poly_data->GetCell(0)->GetPoints()->GetPoint(id, p);
1041  left_chain->InsertNextPoint(p);
1042  }
1043 
1044  // 4. modify last point in the first hull
1045  left_chain->GetPoint((left_chain->GetNumberOfPoints() - 1), p0);
1046  left_chain->GetPoint((left_chain->GetNumberOfPoints() - 2), p1);
1047  vtkMath::Subtract(p1, p0, v);
1048  vtkMath::Normalize(v);
1049  if (sqrt(vtkMath::Distance2BetweenPoints(p0, p1)) < this->deposited_material_width_ / (sin(angle_first_point)))
1050  {
1051  ROS_ERROR_STREAM("offsetLeftChain: Error modifying the point between the left chain and the zigzag path");
1052  return false;
1053  }
1054  for (int k = 0; k < 3; ++k)
1055  p0[k] += this->deposited_material_width_ / (sin(angle_first_point)) * v[k];
1056  left_chain->SetPoint((left_chain->GetNumberOfPoints() - 1), p0);
1057 
1058  return true;
1059  }
1060 
1061 template<class ActionSpec>
1063  const vtkIdType edge_id,
1064  const vtkIdType opposite_point_id,
1065  const vtkSmartPointer<vtkPoints> zigzag_points,
1066  const double deposited_material_width)
1067  {
1068  if (poly_data->GetNumberOfCells() != 1)
1069  {
1070  ROS_ERROR_STREAM("zigzagGeneration: multiple or zero cells in the polydata");
1071  return false;
1072  }
1073  vtkIdType n_edges = poly_data->GetCell(0)->GetNumberOfEdges();
1074  double e_p1[3];
1075  double e_p2[3];
1076  double last_p[3];
1077  double next_p[3];
1078  poly_data->GetCell(0)->GetEdge(edge_id)->GetPoints()->GetPoint(0, e_p1);
1079  poly_data->GetCell(0)->GetEdge(edge_id)->GetPoints()->GetPoint(1, e_p2);
1080  poly_data->GetPoints()->GetPoint(opposite_point_id, last_p);
1081  poly_data->GetPoints()->GetPoint((opposite_point_id + 1) % n_edges, next_p);
1082  double zigzag_dir[3]; // zigzag direction vector
1083 
1084  vtkMath::Subtract(e_p1, e_p2, zigzag_dir);
1085  vtkMath::Normalize(zigzag_dir);
1086 
1087  double u[3]; //vector between the first point in the edge with the zigzag direction and the opposite point
1088  vtkMath::Subtract(last_p, e_p2, u);
1089  double proj_u[3];
1090  vtkMath::ProjectVector(u, zigzag_dir, proj_u);
1091  double step_dir[3]; // step direction vector. Is perpendicular to zigzag_dir
1092  vtkMath::Subtract(u, proj_u, step_dir);
1093  double h = vtkMath::Norm(step_dir);
1094  vtkMath::Normalize(step_dir);
1095 
1096  double l = deposited_material_width;
1097  zigzag_points->InsertNextPoint(e_p2);
1098  zigzag_points->InsertNextPoint(e_p1);
1099 
1100  while (l <= h) // intersect the polygon with a perpendicular plane
1101  {
1102 
1103  vtkSmartPointer<vtkPoints> intersection_points = vtkSmartPointer<vtkPoints>::New();
1104  for (vtkIdType edge_id(0); edge_id < n_edges; ++edge_id)
1105  {
1106  double p1[3];
1107  double p2[3];
1108  poly_data->GetCell(0)->GetEdge(edge_id)->GetPoints()->GetPoint(0, p1);
1109  poly_data->GetCell(0)->GetEdge(edge_id)->GetPoints()->GetPoint(1, p2);
1110  double p0[3];
1111  for (unsigned k(0); k < 3; ++k)
1112  p0[k] = e_p2[k] + l * step_dir[k];
1113  double t;
1114  double x[3];
1115  int intersection = vtkPlane::IntersectWithLine(p1, p2, step_dir, p0, t, x);
1116  if (intersection == 1)
1117  intersection_points->InsertNextPoint(x);
1118  }
1119 
1120  if (intersection_points->GetNumberOfPoints() != 2)
1121  {
1123  "zigzagGeneration: " << intersection_points->GetNumberOfPoints()
1124  << " intersections. 2 expected intersections.");
1125  return false;
1126  }
1127 
1128  double final_point[3];
1129  double x_1[3];
1130  double x_2[3];
1131  zigzag_points->GetPoint((zigzag_points->GetNumberOfPoints() - 1), final_point);
1132  intersection_points->GetPoint(0, x_1);
1133  intersection_points->GetPoint(1, x_2);
1134 
1135  if (vtkMath::Distance2BetweenPoints(final_point, x_1) < vtkMath::Distance2BetweenPoints(final_point, x_2))
1136  {
1137  zigzag_points->InsertNextPoint(x_1);
1138  zigzag_points->InsertNextPoint(x_2);
1139  }
1140  else
1141  {
1142  zigzag_points->InsertNextPoint(x_2);
1143  zigzag_points->InsertNextPoint(x_1);
1144  }
1145  l += deposited_material_width;
1146  }
1147 
1148  // Opposite edges are parallel
1149  double v1[3] = {e_p1[0] - e_p2[0], e_p1[1] - e_p2[1], e_p1[2] - e_p2[2]};
1150  double v2[3] = {next_p[0] - last_p[0], next_p[1] - last_p[1], next_p[2] - last_p[2]};
1151  if (vtkMath::AngleBetweenVectors(v1, v2) < 1e-3) // Almost parallel
1152  zigzag_points->InsertNextPoint(next_p);
1153  zigzag_points->InsertNextPoint(last_p);
1154  return true;
1155  }
1156 
1157 template<class ActionSpec>
1159  const vtkSmartPointer<vtkPoints> left_chain,
1160  const vtkSmartPointer<vtkPoints> right_chain,
1161  const vtkSmartPointer<vtkPoints> zigzag_points)
1162  {
1163  vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New();
1164  vtkSmartPointer<vtkCellArray> polygon_array = vtkSmartPointer<vtkCellArray>::New();
1165  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
1166  vtkSmartPointer<vtkPolyData> new_poly_data = vtkSmartPointer<vtkPolyData>::New();
1167  double p[3];
1168  for (vtkIdType i = 0; i < right_chain->GetNumberOfPoints(); ++i)
1169  {
1170 
1171  right_chain->GetPoint(i, p);
1172  polygon->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
1173  points->InsertNextPoint(p);
1174  }
1175  for (vtkIdType i = 0; i < left_chain->GetNumberOfPoints(); ++i)
1176  {
1177 
1178  left_chain->GetPoint(i, p);
1179  polygon->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
1180  points->InsertNextPoint(p);
1181  }
1182  for (vtkIdType i = 0; i < zigzag_points->GetNumberOfPoints(); ++i)
1183  {
1184 
1185  zigzag_points->GetPoint(i, p);
1186  polygon->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
1187  points->InsertNextPoint(p);
1188  }
1189 
1190  polygon_array->InsertNextCell(polygon);
1191  new_poly_data->SetPolys(polygon_array);
1192  new_poly_data->SetPoints(points);
1193 
1194  poly_data->ShallowCopy(new_poly_data);
1195  }
1196 
1197 template<class ActionSpec>
1199  const vtkSmartPointer<vtkPoints> split_points,
1200  const vtkIdType split_line)
1201  {
1202  unsigned n_polygons = polygon_source.size();
1203 
1204  double l0[3];
1205  double l1[3];
1206  split_points->GetPoint((2 * split_line), l0);
1207  split_points->GetPoint((2 * split_line + 1), l1);
1208 
1209 // Find the two closest polygons to the split line. the distance between the split line
1210  unsigned polygon_1 = -1;
1211  vtkIdType edge_1 = -1;
1212  double l0_to_edge_1 = DBL_MAX;
1213 
1214  unsigned polygon_2 = -1;
1215  vtkIdType edge_2 = -1;
1216  double l0_to_edge_2 = DBL_MAX;
1217 
1218  for (unsigned polygon_id(0); polygon_id < n_polygons; ++polygon_id)
1219  {
1220  bool find_parallel = false;
1221  double min_distance_to_l0 = DBL_MAX;
1222  vtkIdType closest_edge = -1;
1223  vtkIdType n_edges = polygon_source[polygon_id]->GetCell(0)->GetNumberOfEdges();
1224  for (int edge_id(0); edge_id < n_edges; ++edge_id)
1225  {
1226  double distance_to_l0;
1227  double e_p1[3];
1228  double e_p0[3];
1229  polygon_source[polygon_id]->GetCell(0)->GetEdge(edge_id)->GetPoints()->GetPoint(0, e_p0);
1230  polygon_source[polygon_id]->GetCell(0)->GetEdge(edge_id)->GetPoints()->GetPoint(1, e_p1);
1231  double t;
1232 
1233  double v[3] = {e_p1[0] - e_p0[0], e_p1[1] - e_p0[1], e_p1[2] - e_p0[2]};
1234  double u[3] = {l1[0] - l0[0], l1[1] - l0[1], l1[2] - l0[2]};
1235  if (sin(vtkMath::AngleBetweenVectors(u, v)) < 1e-3) // the lines are almost parallel
1236  {
1237  distance_to_l0 = sqrt(vtkLine::DistanceToLine(l0, e_p0, e_p1, t));
1238  if (distance_to_l0 < min_distance_to_l0)
1239  {
1240  find_parallel = true;
1241  min_distance_to_l0 = distance_to_l0;
1242  closest_edge = edge_id;
1243  }
1244  }
1245  }
1246  if (find_parallel)
1247  {
1248  if (min_distance_to_l0 < l0_to_edge_1)
1249  {
1250  polygon_2 = polygon_1;
1251  edge_2 = edge_1;
1252  l0_to_edge_2 = l0_to_edge_1;
1253 
1254  polygon_1 = polygon_id;
1255  edge_1 = closest_edge;
1256  l0_to_edge_1 = min_distance_to_l0;
1257  }
1258  else if (min_distance_to_l0 < l0_to_edge_2)
1259  {
1260  polygon_2 = polygon_id;
1261  edge_2 = closest_edge;
1262  l0_to_edge_2 = min_distance_to_l0;
1263  }
1264  }
1265  }
1266  if (edge_1 == -1 || edge_2 == -1)
1267  {
1268  ROS_ERROR_STREAM("mergeConvexPolygons: Error finding parallels edges to the split line");
1269  return false;
1270  }
1271 
1272  // Find the new points
1273  double e1_p1[3];
1274  double e1_p0[3];
1275 
1276  double e2_p1[3];
1277  double e2_p0[3];
1278 
1279  double e1_v[3];
1280  double e2_v[3];
1281 
1282  double connection_point_1[3];
1283  double connection_point_2[3];
1284 
1285  double connection_point_3[3];
1286  double connection_point_4[3];
1287 
1288  double t1 = -1;
1289  double t2 = -1;
1290  polygon_source[polygon_1]->GetCell(0)->GetEdge(edge_1)->GetPoints()->GetPoint(0, e1_p0);
1291  polygon_source[polygon_1]->GetCell(0)->GetEdge(edge_1)->GetPoints()->GetPoint(1, e1_p1);
1292 
1293  polygon_source[polygon_2]->GetCell(0)->GetEdge(edge_2)->GetPoints()->GetPoint(0, e2_p0);
1294  polygon_source[polygon_2]->GetCell(0)->GetEdge(edge_2)->GetPoints()->GetPoint(1, e2_p1);
1295 
1296  vtkMath::Subtract(e1_p1, e1_p0, e1_v);
1297  vtkMath::Normalize(e1_v);
1298  vtkMath::Subtract(e2_p1, e2_p0, e2_v);
1299  vtkMath::Normalize(e2_v);
1300 
1301  vtkLine::DistanceToLine(l0, e2_p0, e2_p1, t2, connection_point_2);
1302  t2 = (t2 > 1) ? 1 : (t2 < 0) ? 0 : t2;
1303  vtkLine::DistanceToLine(l0, e1_p0, e1_p1, t1, connection_point_1);
1304  t1 = (t1 > 1) ? 1 : (t1 < 0) ? 0 : t1;
1305 
1306  // Find the connection points. two points in each edge
1307  double l; // Distance between the connection lines
1308  double connection_v[3];
1309 
1310  vtkMath::Subtract(connection_point_2, connection_point_1, connection_v);
1311  vtkMath::Normalize(connection_v);
1312  l = this->deposited_material_width_ / sin(vtkMath::AngleBetweenVectors(e1_v, connection_v));
1313  double e1_l = sqrt(vtkMath::Distance2BetweenPoints(e1_p0, e1_p1));
1314  double e2_l = sqrt(vtkMath::Distance2BetweenPoints(e2_p0, e2_p1));
1315 
1316  if ((t2 - l / e2_l) > 0 && t1 < 1)
1317  {
1318  for (int k = 0; k < 3; ++k)
1319  {
1320  connection_point_4[k] = connection_point_1[k] + l * e1_v[k];
1321  connection_point_3[k] = connection_point_2[k] - l * e2_v[k];
1322 
1323  if (t1 == 0 && (l - e1_l) < 0.25 * this->deposited_material_width_ && (l - e1_l) > 0) // Arbitrary value 0.25 * d
1324  connection_point_4[k] = e1_p1[k];
1325  }
1326  }
1327  else if ((t1 - l / e1_l) > 0 && t2 < 1)
1328  {
1329  for (int k = 0; k < 3; ++k)
1330  {
1331  connection_point_4[k] = connection_point_1[k];
1332  connection_point_3[k] = connection_point_2[k];
1333 
1334  connection_point_1[k] -= l * e1_v[k];
1335  connection_point_2[k] += l * e2_v[k];
1336 
1337  if (t2 == 0 && (l - e2_l) < 0.25 * this->deposited_material_width_ && (l - e2_l) > 0) // Arbitrary value
1338  connection_point_2[k] = e2_p1[k];
1339  }
1340  }
1341  else
1342  {
1343  ROS_ERROR_STREAM("mergeConvexPolygons: edge is too short");
1344  return false;
1345  }
1346 
1347  // Merge polygons
1348  vtkSmartPointer<vtkCellArray> polygon_array = vtkSmartPointer<vtkCellArray>::New();
1349  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
1350  vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New();
1351  double p[3];
1352 
1353  for (vtkIdType i(0); i <= edge_1; ++i) // First polygon, part 1
1354  {
1355  polygon_source[polygon_1]->GetCell(0)->GetPoints()->GetPoint(i, p);
1356  polygon->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
1357  points->InsertNextPoint(p);
1358  }
1359 
1360  polygon->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
1361  points->InsertNextPoint(connection_point_1);
1362 
1363  polygon->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
1364  points->InsertNextPoint(connection_point_2);
1365 
1366  for (vtkIdType i(0); i < polygon_source[polygon_2]->GetNumberOfPoints(); ++i) // Second polygon,
1367  {
1368  vtkIdType id = (i + edge_2 + 1) % polygon_source[polygon_2]->GetNumberOfPoints();
1369  polygon_source[polygon_2]->GetCell(0)->GetPoints()->GetPoint(id, p);
1370  polygon->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
1371  points->InsertNextPoint(p);
1372  }
1373 
1374  polygon->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
1375  points->InsertNextPoint(connection_point_3);
1376 
1377  polygon->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
1378  points->InsertNextPoint(connection_point_4);
1379 
1380  for (vtkIdType i(edge_1 + 1); i < polygon_source[polygon_1]->GetNumberOfPoints(); ++i) // first polygon, part 2
1381  {
1382  polygon_source[polygon_1]->GetCell(0)->GetPoints()->GetPoint(i, p);
1383  polygon->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
1384  points->InsertNextPoint(p);
1385  }
1386 
1387  polygon_array->InsertNextCell(polygon);
1388  vtkSmartPointer<vtkPolyData> poly_data = vtkSmartPointer<vtkPolyData>::New();
1389  poly_data->SetPolys(polygon_array);
1390  poly_data->SetPoints(points);
1391 
1392  if (polygon_2 > polygon_1)
1393  {
1394  polygon_source.erase(polygon_source.begin() + polygon_2);
1395  polygon_source.erase(polygon_source.begin() + polygon_1);
1396  }
1397  else
1398  {
1399  polygon_source.erase(polygon_source.begin() + polygon_1);
1400  polygon_source.erase(polygon_source.begin() + polygon_2);
1401  }
1402 
1403  polygon_source.push_back(poly_data);
1404  return true;
1405  }
1406 
1407 template<class ActionSpec>
1409  {
1410  semaphore_.wait(); //Semaphore
1411 
1412  this->removeDuplicatePoints(poly_data);
1413  this->mergeColinearEdges(poly_data);
1414 
1415  if (!this->offsetPolygonContour(poly_data, this->deposited_material_width_ / 2.0))
1416  {
1417  semaphore_.signal();
1418  return false;
1419  };
1420 
1421  vtkIdType edge_id;
1422  vtkIdType opposite_point_id;
1423  double h;
1424 
1425  h = identifyZigzagDirection(poly_data, edge_id, opposite_point_id);
1426  if (h / this->deposited_material_width_ <= 4)
1427  ROS_WARN_STREAM("warning: h/d <= 4 | h/d = " << h / this->deposited_material_width_);
1428 
1429  vtkSmartPointer<vtkPoints> left_chain = vtkSmartPointer<vtkPoints>::New();
1430  vtkSmartPointer<vtkPoints> right_chain = vtkSmartPointer<vtkPoints>::New();
1431  vtkSmartPointer<vtkPoints> zigzag_points = vtkSmartPointer<vtkPoints>::New();
1432 
1433  identifyLeftChain(poly_data, edge_id, opposite_point_id, left_chain, right_chain);
1434  if (!offsetLeftChain(poly_data, edge_id, opposite_point_id, left_chain, right_chain))
1435  {
1436  semaphore_.signal();
1437  return false;
1438  }
1439 
1440  if (!this->offsetPolygonContour(poly_data, this->deposited_material_width_))
1441  {
1442  semaphore_.signal();
1443  return false;
1444  }
1445 
1446  if (!zigzagGeneration(poly_data, edge_id, opposite_point_id, zigzag_points, this->deposited_material_width_))
1447  {
1448  semaphore_.signal();
1449  return false;
1450  }
1451 
1452  mergeListOfPoints(poly_data, left_chain, right_chain, zigzag_points);
1453  this->removeDuplicatePoints(poly_data);
1454  this->mergeColinearEdges(poly_data);
1455  semaphore_.signal();
1456  return true;
1457  }
1458 
1459 }
1460 
1461 #endif
bool findIntersectWithBisector(const Polygon poly_data, const vtkIdType notch_cell_id, const vtkIdType notch_pos, vtkIdType &vertex_cell_id, vtkIdType &vertex_pos, double vertex[3])
double angleBetweenVectors(const double v1[3], const double v2[3])
void identifyRelationships(const Polygon poly_data, std::vector< int > &level, std::vector< int > &father)
bool mergeColinearEdges(const Polygon poly_data, const double tolerance=1e-6)
bool divideInConvexPolygons(PolygonVector &polygon_source, const int polygon_position, const vtkSmartPointer< vtkPoints > split_points)
vtkSmartPointer< vtkPolyData > Polygon
bool yamlFileToPolydata(const std::string yaml_file, Polygon poly_data)
XmlRpcServer s
bool offsetLeftChain(const Polygon poly_data, const vtkIdType edge_id, const vtkIdType opposite_point_id, const vtkSmartPointer< vtkPoints > left_chain, const vtkSmartPointer< vtkPoints > right_chain)
bool intersectLineWithContours(const Polygon poly_data, double point_1[3], double point_2[3])
std::vector< PolygonVector > Layer
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
void computeNormal(vtkPoints *p, double *n)
double identifyZigzagDirection(const Polygon poly_data, vtkIdType &edge, vtkIdType &futhest_point)
bool zigzagGeneration(const Polygon poly_data, const vtkIdType edge_id, const vtkIdType opposite_point_id, const vtkSmartPointer< vtkPoints > zigzag_points, const double deposited_material_width)
bool organizePolygonContoursInLayer(const Polygon poly_data, const std::vector< int > level, const std::vector< int > father, Layer &layer)
bool publishStatusPercentageDone(const std::string progress_msg, const unsigned percentage, actionlib::ServerGoalHandle< ActionSpec > &gh)
bool removeDuplicatePoints(const Polygon poly_data, const double tolerance=1e-6)
bool verifyAngles(const Polygon poly_data, const vtkIdType notch_cell_id, const vtkIdType notch_pos, const vtkIdType vertex_cell_id, const vtkIdType vertex_pos)
bool yamlFileToPolydata2(const std::string yaml_file, Polygon poly_data, std::vector< unsigned > &layer_count)
TFSIMD_FORCE_INLINE const tfScalar & x() const
std::vector< Polygon > PolygonVector
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
bool generateTrajectoryInConvexPolygon(const Polygon poly_data)
#define ROS_WARN_STREAM(args)
void mergeListOfPoints(const Polygon poly_data, const vtkSmartPointer< vtkPoints > left_chain, const vtkSmartPointer< vtkPoints > right_chain, const vtkSmartPointer< vtkPoints > zigzag_points)
#define ROS_INFO_STREAM(args)
bool intersectionBetweenContours(const Polygon poly_data)
bool offsetPolygonContour(const Polygon poly_data, const double deposited_material_width)
bool mergeConvexPolygons(PolygonVector &polygon_source, const vtkSmartPointer< vtkPoints > split_points, const vtkIdType split_line)
void identifyLeftChain(const Polygon poly_data, const vtkIdType edge_id, const vtkIdType opposite_point_id, const vtkSmartPointer< vtkPoints > left_chain, const vtkSmartPointer< vtkPoints > right_chain)
#define ROS_ERROR_STREAM(args)
bool findNotch(const Polygon poly_data, vtkIdType &cell_id, vtkIdType &pos, double &angle)
bool use_gui
std::string generateOneLayerTrajectory(actionlib::ServerGoalHandle< ActionSpec > &gh, const int current_progrress_value, const int next_progress_value, const Polygon poly_data, Layer &layer, const double deposited_material_width, const double contours_filtering_tolerance, const std::array< double, 3 > normal_vector={0, 0, 1}, const double polygon_division_tolerance=M_PI/6, const bool closest_to_bisector=false, const bool use_gui=false)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
bool findVertex(const Polygon poly_data, const vtkIdType notch_cell_id, const vtkIdType notch_pos, vtkIdType &vertex_cell_id, vtkIdType &vertex_pos, const double notch_angle)


ram_path_planning
Author(s): Andres Campos - Institut Maupertuis
autogenerated on Mon Jun 10 2019 14:50:03