43 #ifndef PCL_SURFACE_IMPL_CONVEX_HULL_H_
44 #define PCL_SURFACE_IMPL_CONVEX_HULL_H_
56 template <
typename Po
intInT>
void
57 pcl::ConvexHull<PointInT>::calculateInputDimension ()
59 PCL_WARN (
"[pcl::%s::calculateInputDimension] WARNING: Input dimension not specified. Automatically determining input dimension.\n", getClassName ().c_str ());
61 Eigen::Vector4f xyz_centroid;
67 if (eigen_values[0] / eigen_values[2] < 1.0e-3)
74 template <
typename Po
intInT>
void
75 pcl::ConvexHull<PointInT>::performReconstruction2D (
PointCloud &hull, std::vector<pcl::Vertices> &polygons,
79 bool xy_proj_safe =
true;
80 bool yz_proj_safe =
true;
81 bool xz_proj_safe =
true;
84 PointInT p0 = input_->points[0];
85 PointInT p1 = input_->points[indices_->size () - 1];
86 PointInT p2 = input_->points[indices_->size () / 2];
87 Eigen::Array4f dy1dy2 = (p1.getArray4fMap () - p0.getArray4fMap ()) / (p2.getArray4fMap () - p0.getArray4fMap ());
88 while (!( (dy1dy2[0] != dy1dy2[1]) || (dy1dy2[2] != dy1dy2[1]) ) )
90 p0 = input_->points[rand () % indices_->size ()];
91 p1 = input_->points[rand () % indices_->size ()];
92 p2 = input_->points[rand () % indices_->size ()];
93 dy1dy2 = (p1.getArray4fMap () - p0.getArray4fMap ()) / (p2.getArray4fMap () - p0.getArray4fMap ());
97 normal_calc_cloud.
points.resize (3);
98 normal_calc_cloud.
points[0] = p0;
99 normal_calc_cloud.
points[1] = p1;
100 normal_calc_cloud.
points[2] = p2;
102 Eigen::Vector4f normal_calc_centroid;
103 Eigen::Matrix3f normal_calc_covariance;
106 Eigen::Vector3f::Scalar eigen_value;
107 Eigen::Vector3f plane_params;
108 pcl::eigen33 (normal_calc_covariance, eigen_value, plane_params);
109 float theta_x = fabsf (plane_params.dot (x_axis_));
110 float theta_y = fabsf (plane_params.dot (y_axis_));
111 float theta_z = fabsf (plane_params.dot (z_axis_));
115 if (theta_z > projection_angle_thresh_)
117 xz_proj_safe =
false;
118 yz_proj_safe =
false;
120 if (theta_x > projection_angle_thresh_)
122 xz_proj_safe =
false;
123 xy_proj_safe =
false;
125 if (theta_y > projection_angle_thresh_)
127 xy_proj_safe =
false;
128 yz_proj_safe =
false;
132 boolT ismalloc = True;
134 FILE *outfile = NULL;
140 const char* flags = qhull_flags.c_str ();
142 FILE *errfile = stderr;
145 coordT *points =
reinterpret_cast<coordT*
> (calloc (indices_->size () * dimension,
sizeof (coordT)));
151 for (
size_t i = 0; i < indices_->size (); ++i, j+=dimension)
153 points[j + 0] =
static_cast<coordT
> (input_->points[(*indices_)[i]].x);
154 points[j + 1] =
static_cast<coordT
> (input_->points[(*indices_)[i]].y);
157 else if (yz_proj_safe)
159 for (
size_t i = 0; i < input_->points.size (); ++i, j+=dimension)
161 points[j + 0] =
static_cast<coordT
> (input_->points[(*indices_)[i]].y);
162 points[j + 1] =
static_cast<coordT
> (input_->points[(*indices_)[i]].z);
165 else if (xz_proj_safe)
167 for (
size_t i = 0; i < input_->points.size (); ++i, j+=dimension)
169 points[j + 0] =
static_cast<coordT
> (input_->points[(*indices_)[i]].x);
170 points[j + 1] =
static_cast<coordT
> (input_->points[(*indices_)[i]].z);
176 PCL_ERROR (
"[pcl::%s::performReconstruction2D] Invalid input!\n", getClassName ().c_str ());
180 int exitcode = qh_new_qhull (dimension, static_cast<int> (indices_->size ()), points, ismalloc, const_cast<char*> (flags), outfile, errfile);
185 PCL_ERROR (
"[pcl::%s::performReconstrution2D] ERROR: qhull was unable to compute a convex hull for the given point cloud (%zu)!\n", getClassName ().c_str (), indices_->size ());
191 qh_freeqhull (!qh_ALL);
192 int curlong, totlong;
193 qh_memfreeshort (&curlong, &totlong);
201 total_area_ = qh totvol;
205 int num_vertices = qh num_vertices;
206 hull.
points.resize (num_vertices);
207 memset (&hull.
points[0], static_cast<int> (hull.
points.size ()),
sizeof (PointInT));
212 std::vector<std::pair<int, Eigen::Vector4f>, Eigen::aligned_allocator<std::pair<int, Eigen::Vector4f> > > idx_points (num_vertices);
213 idx_points.resize (hull.
points.size ());
214 memset (&idx_points[0], static_cast<int> (hull.
points.size ()),
sizeof (std::pair<int, Eigen::Vector4f>));
218 hull.
points[i] = input_->points[(*indices_)[qh_pointid (vertex->point)]];
219 idx_points[i].first = qh_pointid (vertex->point);
224 Eigen::Vector4f centroid;
228 for (
size_t j = 0; j < hull.
points.size (); j++)
230 idx_points[j].second[0] = hull.
points[j].x - centroid[0];
231 idx_points[j].second[1] = hull.
points[j].y - centroid[1];
234 else if (yz_proj_safe)
236 for (
size_t j = 0; j < hull.
points.size (); j++)
238 idx_points[j].second[0] = hull.
points[j].y - centroid[1];
239 idx_points[j].second[1] = hull.
points[j].z - centroid[2];
242 else if (xz_proj_safe)
244 for (
size_t j = 0; j < hull.
points.size (); j++)
246 idx_points[j].second[0] = hull.
points[j].x - centroid[0];
247 idx_points[j].second[1] = hull.
points[j].z - centroid[2];
250 std::sort (idx_points.begin (), idx_points.end (), comparePoints2D);
253 polygons[0].vertices.resize (hull.
points.size () + 1);
255 for (
int j = 0; j < static_cast<int> (hull.
points.size ()); j++)
257 hull.
points[j] = input_->points[(*indices_)[idx_points[j].first]];
258 polygons[0].vertices[j] =
static_cast<unsigned int> (j);
260 polygons[0].vertices[hull.
points.size ()] = 0;
262 qh_freeqhull (!qh_ALL);
263 int curlong, totlong;
264 qh_memfreeshort (&curlong, &totlong);
266 hull.
width =
static_cast<uint32_t
> (hull.
points.size ());
273 #pragma GCC diagnostic ignored "-Wold-style-cast"
276 template <
typename Po
intInT>
void
277 pcl::ConvexHull<PointInT>::performReconstruction3D (
278 PointCloud &hull, std::vector<pcl::Vertices> &polygons,
bool fill_polygon_data)
283 boolT ismalloc = True;
285 FILE *outfile = NULL;
291 const char *flags = qhull_flags.c_str ();
293 FILE *errfile = stderr;
296 coordT *points =
reinterpret_cast<coordT*
> (calloc (indices_->size () * dimension,
sizeof (coordT)));
299 for (
size_t i = 0; i < indices_->size (); ++i, j+=dimension)
301 points[j + 0] =
static_cast<coordT
> (input_->points[(*indices_)[i]].x);
302 points[j + 1] =
static_cast<coordT
> (input_->points[(*indices_)[i]].y);
303 points[j + 2] =
static_cast<coordT
> (input_->points[(*indices_)[i]].z);
307 int exitcode = qh_new_qhull (dimension, static_cast<int> (indices_->size ()), points, ismalloc, const_cast<char*> (flags), outfile, errfile);
312 PCL_ERROR (
"[pcl::%s::performReconstrution3D] ERROR: qhull was unable to compute a convex hull for the given point cloud (%zu)!\n", getClassName ().c_str (), input_->points.size ());
318 qh_freeqhull (!qh_ALL);
319 int curlong, totlong;
320 qh_memfreeshort (&curlong, &totlong);
327 int num_facets = qh num_facets;
329 int num_vertices = qh num_vertices;
330 hull.
points.resize (num_vertices);
335 int max_vertex_id = 0;
338 if (vertex->id + 1 > max_vertex_id)
339 max_vertex_id = vertex->id + 1;
343 std::vector<int> qhid_to_pcidx (max_vertex_id);
348 hull.
points[i] = input_->points[(*indices_)[qh_pointid (vertex->point)]];
350 qhid_to_pcidx[vertex->id] = i;
356 total_area_ = qh totarea;
357 total_volume_ = qh totvol;
360 if (fill_polygon_data)
362 polygons.resize (num_facets);
368 polygons[dd].vertices.resize (3);
371 int vertex_n, vertex_i;
372 FOREACHvertex_i_ ((*facet).vertices)
374 polygons[dd].vertices[vertex_i] = qhid_to_pcidx[vertex->
id];
379 qh_freeqhull (!qh_ALL);
380 int curlong, totlong;
381 qh_memfreeshort (&curlong, &totlong);
383 hull.width = static_cast<uint32_t> (hull.points.size ());
385 hull.is_dense = false;
388 #pragma GCC diagnostic warning "-Wold-style-cast"
392 template <
typename Po
intInT>
void
393 pcl::ConvexHull<PointInT>::performReconstruction (
PointCloud &hull, std::vector<pcl::Vertices> &polygons,
394 bool fill_polygon_data)
397 calculateInputDimension ();
399 performReconstruction2D (hull, polygons, fill_polygon_data);
400 else if (dimension_ == 3)
401 performReconstruction3D (hull, polygons, fill_polygon_data);
403 PCL_ERROR (
"[pcl::%s::performReconstruction] Error: invalid input dimension requested: %d\n",getClassName ().c_str (),dimension_);
407 template <
typename Po
intInT>
void
408 pcl::ConvexHull<PointInT>::reconstruct (
PointCloud &output)
410 output.
header = input_->header;
411 if (!initCompute () || input_->points.empty () || indices_->empty ())
418 std::vector<pcl::Vertices> polygons;
419 performReconstruction (output, polygons,
false);
421 output.
width =
static_cast<uint32_t
> (output.
points.size ());
430 template <
typename Po
intInT>
void
431 pcl::ConvexHull<PointInT>::performReconstruction (PolygonMesh &output)
435 performReconstruction (hull_points, output.polygons,
true);
442 template <
typename Po
intInT>
void
443 pcl::ConvexHull<PointInT>::performReconstruction (std::vector<pcl::Vertices> &polygons)
446 performReconstruction (hull_points, polygons,
true);
450 template <
typename Po
intInT>
void
451 pcl::ConvexHull<PointInT>::reconstruct (
PointCloud &points, std::vector<pcl::Vertices> &polygons)
453 points.
header = input_->header;
454 if (!initCompute () || input_->points.empty () || indices_->empty ())
461 performReconstruction (points, polygons,
true);
463 points.
width =
static_cast<uint32_t
> (points.
points.size ());
470 #define PCL_INSTANTIATE_ConvexHull(T) template class PCL_EXPORTS pcl::ConvexHull<T>;
472 #endif // PCL_SURFACE_IMPL_CONVEX_HULL_H_