mesh_slicer.cpp
Go to the documentation of this file.
2 
3 namespace ram_path_planning
4 {
5 std::string fileExtension(const std::string full_path)
6 {
7  size_t last_index = full_path.find_last_of("/");
8  std::string file_name = full_path.substr(last_index + 1, full_path.size());
9 
10  last_index = file_name.find_last_of("\\");
11  file_name = file_name.substr(last_index + 1, file_name.size());
12 
13  last_index = file_name.find_last_of(".");
14  if (last_index == std::string::npos)
15  return "";
16 
17  return file_name.substr(last_index + 1, file_name.size());
18 }
19 
20 bool readPolygonFile(const std::string file_name,
21  const vtkSmartPointer<vtkPolyData> poly_data)
22 {
23  vtkSmartPointer<ErrorObserver> vtk_observer = vtkSmartPointer<ErrorObserver>::New();
24  std::string file_extension = fileExtension(file_name);
25 
26  vtkSmartPointer<vtkAbstractPolyDataReader> reader;
27 
28  if (!strcasecmp(file_extension.c_str(), "obj"))
29  reader = vtkSmartPointer<vtkOBJReader>::New();
30  else if (!strcasecmp(file_extension.c_str(), "ply"))
31  reader = vtkSmartPointer<vtkPLYReader>::New();
32  else if (!strcasecmp(file_extension.c_str(), "stl"))
33  reader = vtkSmartPointer<vtkSTLReader>::New();
34  else
35  return false;
36 
37  reader->SetFileName(file_name.c_str());
38  reader->AddObserver(vtkCommand::WarningEvent, vtk_observer);
39  reader->AddObserver(vtkCommand::ErrorEvent, vtk_observer);
40  vtk_observer->Clear();
41  reader->Update();
42 
43  if (vtk_observer->GetWarning())
44  {
45  ROS_WARN_STREAM("readPolygonFile: " << file_name << std::endl << vtk_observer->GetWarningMessage());
46  vtk_observer->Clear();
47  return false;
48  }
49  if (vtk_observer->GetError())
50  {
51  ROS_ERROR_STREAM("readPolygonFile: " << file_name << std::endl << vtk_observer->GetErrorMessage());
52  vtk_observer->Clear();
53  return false;
54  }
55 
56  if (!reader->GetOutput()->GetNumberOfCells())
57  {
58  ROS_ERROR_STREAM("readPolygonFile: " << file_name << " has no faces!");
59  return false;
60  }
61 
62  poly_data->DeepCopy(reader->GetOutput());
63  return true;
64 }
65 
66 unsigned sliceMesh(std::vector<Layer> &trajectory,
67  const std::string file_name,
68  const vtkSmartPointer<vtkPolyData> poly_data,
69  vtkSmartPointer<vtkStripper> &stripper,
70  const double height_between_layers,
71  const std::array<double, 3> slicing_direction,
72  const bool use_gui)
73 {
74  if (height_between_layers == 0)
75  return 0;
76 
77  if (!poly_data)
78  return 0;
79 
80  if (!readPolygonFile(file_name, poly_data))
81  return 0;
82 
83  double cutter_normal[3];
84  cutter_normal[0] = slicing_direction[0];
85  cutter_normal[1] = slicing_direction[1];
86  cutter_normal[2] = slicing_direction[2];
87 
88  if (cutter_normal[0] == 0 &&
89  cutter_normal[1] == 0 &&
90  cutter_normal[2] == 0)
91  {
92  cutter_normal[0] = 0;
93  cutter_normal[1] = 0;
94  cutter_normal[2] = 1;
95  }
96 
97  vtkMath::Normalize(cutter_normal);
98 
99  poly_data->ComputeBounds();
100  double min_bound[3];
101  min_bound[0] = poly_data->GetBounds()[0];
102  min_bound[1] = poly_data->GetBounds()[2];
103  min_bound[2] = poly_data->GetBounds()[4];
104  //ROS_INFO_STREAM("Minimum bounds: " << min_bound[0] << " " << min_bound[1] << " " << min_bound[2]);
105 
106  double max_bound[3];
107  max_bound[0] = poly_data->GetBounds()[1];
108  max_bound[1] = poly_data->GetBounds()[3];
109  max_bound[2] = poly_data->GetBounds()[5];
110  //ROS_INFO_STREAM("Maximum bounds: " << max_bound[0] << " " << max_bound[1] << " " << max_bound[2]);
111 
112  trajectory.clear();
113  double min_bound_proj[3];
114  double max_bound_proj[3];
115  vtkMath::ProjectVector(min_bound, cutter_normal, min_bound_proj);
116  vtkMath::ProjectVector(max_bound, cutter_normal, max_bound_proj);
117 
118  double min_offset = cos(vtkMath::AngleBetweenVectors(min_bound_proj, cutter_normal)) * vtkMath::Norm(min_bound_proj);
119  double max_offset = cos(vtkMath::AngleBetweenVectors(max_bound_proj, cutter_normal)) * vtkMath::Norm(max_bound_proj);
120  if (min_offset > max_offset)
121  {
122  double aux_offset = min_offset;
123  min_offset = max_offset;
124  max_offset = aux_offset;
125  }
126 
127  double origin_offset = min_offset;
128  bool first_layer(true);
129  while (origin_offset < max_offset)
130  {
131  // Create a plane to cut mesh
132  vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
133  plane->SetOrigin(poly_data->GetCenter());
134  plane->SetOrigin(0, 0, 0);
135  plane->SetNormal(cutter_normal);
136 
137  // Create a cutter
138  vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();
139  cutter->SetCutFunction(plane);
140  cutter->SetInputData(poly_data);
141 
142  if (first_layer)
143  {
144  cutter->SetValue(0, origin_offset + 1e-5);
145  first_layer = false;
146  }
147  else
148  cutter->SetValue(0, origin_offset);
149 
150  origin_offset += height_between_layers;
151  cutter->Update();
152 
153  vtkSmartPointer<vtkTriangleFilter> triangle_filter = vtkSmartPointer<vtkTriangleFilter>::New();
154  triangle_filter->SetInputConnection(cutter->GetOutputPort());
155  triangle_filter->Update();
156 
157  stripper = vtkSmartPointer<vtkStripper>::New();
158  stripper->SetInputConnection(triangle_filter->GetOutputPort());
159  stripper->Update();
160 
161  Polygon poly = Polygon::New();
162  poly->DeepCopy(stripper->GetOutput());
163  if (poly->GetNumberOfPoints() < 3)
164  ROS_INFO_STREAM("sliceMesh: Contour is empty");
165  else
166  {
167  PolygonVector poly_vector;
168  poly_vector.push_back(poly);
169  Layer layer;
170  layer.push_back(poly_vector);
171 
172  trajectory.push_back(layer);
173  if (use_gui)
174  ROS_INFO_STREAM("sliceMesh: Generated " <<poly->GetNumberOfCells()<<" contours in this layer");
175  }
176  if (use_gui)
177  {
178  ROS_INFO_STREAM("Press enter to slice the next layer");
179  std::string we_dont_care;
180  std::getline(std::cin, we_dont_care);
181  }
182  }
183 
184  if (use_gui)
185  ROS_INFO_STREAM("Generated " << trajectory.size() << " slices");
186 
187  return trajectory.size();
188 }
189 
190 }
191 
bool readPolygonFile(const std::string file_name, const vtkSmartPointer< vtkPolyData > poly_data)
Definition: mesh_slicer.cpp:20
unsigned sliceMesh(std::vector< Layer > &trajectory, const std::string file_name, const vtkSmartPointer< vtkPolyData > poly_data, vtkSmartPointer< vtkStripper > &stripper, const double height_between_layers, const std::array< double, 3 > slicing_direction, const bool use_gui=false)
Definition: mesh_slicer.cpp:66
std::string fileExtension(const std::string full_path)
Definition: mesh_slicer.cpp:5
std::vector< PolygonVector > Layer
Definition: mesh_slicer.hpp:27
vtkSmartPointer< vtkPolyData > Polygon
Definition: mesh_slicer.hpp:25
std::vector< Polygon > PolygonVector
Definition: mesh_slicer.hpp:26
#define ROS_WARN_STREAM(args)
#define ROS_INFO_STREAM(args)
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
#define ROS_ERROR_STREAM(args)
bool use_gui


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