diff --git a/.ci/azure-pipelines/azure-pipelines.yaml b/.ci/azure-pipelines/azure-pipelines.yaml index 69881c08317..5ebe7af4a79 100644 --- a/.ci/azure-pipelines/azure-pipelines.yaml +++ b/.ci/azure-pipelines/azure-pipelines.yaml @@ -52,8 +52,6 @@ stages: CC: gcc CXX: g++ BUILD_GPU: OFF - # surface is not ready for re-entrant QHull - CMAKE_ARGS: '-DBUILD_tests_surface=OFF' container: $[ variables['CONTAINER'] ] timeoutInMinutes: 0 variables: diff --git a/cmake/Modules/FindQhull.cmake b/cmake/Modules/FindQhull.cmake index 7f3cf90dc11..f9f628452b8 100644 --- a/cmake/Modules/FindQhull.cmake +++ b/cmake/Modules/FindQhull.cmake @@ -9,14 +9,12 @@ # If QHULL_USE_STATIC is specified then look for static libraries ONLY else # look for shared ones -set(QHULL_MAJOR_VERSION 6) - if(QHULL_USE_STATIC) - set(QHULL_RELEASE_NAME qhullstatic) - set(QHULL_DEBUG_NAME qhullstatic_d) + set(QHULL_RELEASE_NAME qhullstatic_r) + set(QHULL_DEBUG_NAME qhullstatic_rd) else() - set(QHULL_RELEASE_NAME qhull_p qhull${QHULL_MAJOR_VERSION} qhull) - set(QHULL_DEBUG_NAME qhull_p_d qhull${QHULL_MAJOR_VERSION}_d qhull_d${QHULL_MAJOR_VERSION} qhull_d) + set(QHULL_RELEASE_NAME qhull_r qhull) + set(QHULL_DEBUG_NAME qhull_rd qhull_d) endif() find_file(QHULL_HEADER @@ -30,10 +28,8 @@ set(QHULL_HEADER "${QHULL_HEADER}" CACHE INTERNAL "QHull header" FORCE ) if(QHULL_HEADER) get_filename_component(qhull_header ${QHULL_HEADER} NAME_WE) if("${qhull_header}" STREQUAL "qhull") - set(HAVE_QHULL_2011 OFF) get_filename_component(QHULL_INCLUDE_DIR ${QHULL_HEADER} PATH) elseif("${qhull_header}" STREQUAL "libqhull") - set(HAVE_QHULL_2011 ON) get_filename_component(QHULL_INCLUDE_DIR ${QHULL_HEADER} PATH) get_filename_component(QHULL_INCLUDE_DIR ${QHULL_INCLUDE_DIR} PATH) endif() diff --git a/pcl_config.h.in b/pcl_config.h.in index 3eccb95c975..e41128d2dc5 100644 --- a/pcl_config.h.in +++ b/pcl_config.h.in @@ -42,8 +42,6 @@ #cmakedefine HAVE_QHULL 1 -#cmakedefine HAVE_QHULL_2011 1 - #cmakedefine HAVE_CUDA 1 #cmakedefine HAVE_ENSENSO 1 diff --git a/surface/include/pcl/surface/convex_hull.h b/surface/include/pcl/surface/convex_hull.h index d82bbf0b0ea..917b42c412f 100644 --- a/surface/include/pcl/surface/convex_hull.h +++ b/surface/include/pcl/surface/convex_hull.h @@ -88,11 +88,11 @@ namespace pcl using PointCloudConstPtr = typename PointCloud::ConstPtr; /** \brief Empty constructor. */ - ConvexHull () : compute_area_ (false), total_area_ (0), total_volume_ (0), dimension_ (0), + ConvexHull () : compute_area_ (false), total_area_ (0), total_volume_ (0), dimension_ (0), projection_angle_thresh_ (std::cos (0.174532925) ), qhull_flags ("qhull "), x_axis_ (1.0, 0.0, 0.0), y_axis_ (0.0, 1.0, 0.0), z_axis_ (0.0, 0.0, 1.0) { - }; + } /** \brief Empty destructor */ ~ConvexHull () {} diff --git a/surface/include/pcl/surface/impl/concave_hull.hpp b/surface/include/pcl/surface/impl/concave_hull.hpp index 50216d15512..0019b2d395f 100644 --- a/surface/include/pcl/surface/impl/concave_hull.hpp +++ b/surface/include/pcl/surface/impl/concave_hull.hpp @@ -194,8 +194,13 @@ pcl::ConcaveHull::performReconstruction (PointCloud &alpha_shape, std: points[i * dim_ + 2] = static_cast (cloud_transformed[i].z); } + qhT qh_qh; + qhT* qh = &qh_qh; + QHULL_LIB_CHECK + qh_zero(qh, errfile); + // Compute concave hull - exitcode = qh_new_qhull (dim_, static_cast (cloud_transformed.size ()), points, ismalloc, flags, outfile, errfile); + exitcode = qh_new_qhull (qh, dim_, static_cast (cloud_transformed.size ()), points, ismalloc, flags, outfile, errfile); if (exitcode != 0) { @@ -227,16 +232,16 @@ pcl::ConcaveHull::performReconstruction (PointCloud &alpha_shape, std: alpha_shape.width = alpha_shape.height = 0; polygons.resize (0); - qh_freeqhull (!qh_ALL); + qh_freeqhull (qh, !qh_ALL); int curlong, totlong; - qh_memfreeshort (&curlong, &totlong); + qh_memfreeshort (qh, &curlong, &totlong); return; } - qh_setvoronoi_all (); + qh_setvoronoi_all (qh); - int num_vertices = qh num_vertices; + int num_vertices = qh->num_vertices; alpha_shape.resize (num_vertices); vertexT *vertex; @@ -253,11 +258,11 @@ pcl::ConcaveHull::performReconstruction (PointCloud &alpha_shape, std: ++max_vertex_id; std::vector qhid_to_pcidx (max_vertex_id); - int num_facets = qh num_facets; + int num_facets = qh->num_facets; if (dim_ == 3) { - setT *triangles_set = qh_settemp (4 * num_facets); + setT *triangles_set = qh_settemp (qh, 4 * num_facets); if (voronoi_centers_) voronoi_centers_->points.resize (num_facets); @@ -283,29 +288,29 @@ pcl::ConcaveHull::performReconstruction (PointCloud &alpha_shape, std: if (r <= alpha_) { // all triangles in tetrahedron are good, add them all to the alpha shape (triangles_set) - qh_makeridges (facet); + qh_makeridges (qh, facet); facet->good = true; - facet->visitid = qh visit_id; + facet->visitid = qh->visit_id; ridgeT *ridge, **ridgep; FOREACHridge_ (facet->ridges) { facetT *neighb = otherfacet_ (ridge, facet); - if ((neighb->visitid != qh visit_id)) - qh_setappend (&triangles_set, ridge); + if ((neighb->visitid != qh->visit_id)) + qh_setappend (qh, &triangles_set, ridge); } } else { // consider individual triangles from the tetrahedron... facet->good = false; - facet->visitid = qh visit_id; - qh_makeridges (facet); + facet->visitid = qh->visit_id; + qh_makeridges (qh, facet); ridgeT *ridge, **ridgep; FOREACHridge_ (facet->ridges) { facetT *neighb; neighb = otherfacet_ (ridge, facet); - if ((neighb->visitid != qh visit_id)) + if ((neighb->visitid != qh->visit_id)) { // check if individual triangle is good and add it to triangles_set @@ -322,7 +327,7 @@ pcl::ConcaveHull::performReconstruction (PointCloud &alpha_shape, std: double r = pcl::getCircumcircleRadius (a, b, c); if (r <= alpha_) - qh_setappend (&triangles_set, ridge); + qh_setappend (qh, &triangles_set, ridge); } } } @@ -354,7 +359,7 @@ pcl::ConcaveHull::performReconstruction (PointCloud &alpha_shape, std: { polygons[triangles].vertices.resize (3); int vertex_n, vertex_i; - FOREACHvertex_i_ ((*ridge).vertices) //3 vertices per ridge! + FOREACHvertex_i_ (qh, (*ridge).vertices) //3 vertices per ridge! { if (!added_vertices[vertex->id]) { @@ -383,7 +388,7 @@ pcl::ConcaveHull::performReconstruction (PointCloud &alpha_shape, std: { // Compute the alpha complex for the set of points // Filters the delaunay triangles - setT *edges_set = qh_settemp (3 * num_facets); + setT *edges_set = qh_settemp (qh, 3 * num_facets); if (voronoi_centers_) voronoi_centers_->points.resize (num_facets); @@ -403,12 +408,12 @@ pcl::ConcaveHull::performReconstruction (PointCloud &alpha_shape, std: if (r <= alpha_) { pcl::Vertices facet_vertices; //TODO: is not used!! - qh_makeridges (facet); + qh_makeridges (qh, facet); facet->good = true; ridgeT *ridge, **ridgep; FOREACHridge_ (facet->ridges) - qh_setappend (&edges_set, ridge); + qh_setappend (qh, &edges_set, ridge); if (voronoi_centers_) { @@ -438,7 +443,7 @@ pcl::ConcaveHull::performReconstruction (PointCloud &alpha_shape, std: std::vector pcd_indices; pcd_indices.resize (2); - FOREACHvertex_i_ ((*ridge).vertices) //in 2-dim, 2 vertices per ridge! + FOREACHvertex_i_ (qh, (*ridge).vertices) //in 2-dim, 2 vertices per ridge! { if (!added_vertices[vertex->id]) { @@ -540,9 +545,9 @@ pcl::ConcaveHull::performReconstruction (PointCloud &alpha_shape, std: voronoi_centers_->points.resize (dd); } - qh_freeqhull (!qh_ALL); + qh_freeqhull (qh, !qh_ALL); int curlong, totlong; - qh_memfreeshort (&curlong, &totlong); + qh_memfreeshort (qh, &curlong, &totlong); Eigen::Affine3d transInverse = transform1.inverse (); pcl::transformPointCloud (alpha_shape, alpha_shape, transInverse); diff --git a/surface/include/pcl/surface/impl/convex_hull.hpp b/surface/include/pcl/surface/impl/convex_hull.hpp index b8cbb5f14fd..aa36cdd9efb 100644 --- a/surface/include/pcl/surface/impl/convex_hull.hpp +++ b/surface/include/pcl/surface/impl/convex_hull.hpp @@ -136,10 +136,8 @@ pcl::ConvexHull::performReconstruction2D (PointCloud &hull, std::vecto // output from qh_produce_output(), use NULL to skip qh_produce_output() FILE *outfile = nullptr; -#ifndef HAVE_QHULL_2011 if (compute_area_) outfile = stderr; -#endif // option flags for qhull, see qh_opt.htm const char* flags = qhull_flags.c_str (); @@ -180,18 +178,21 @@ pcl::ConvexHull::performReconstruction2D (PointCloud &hull, std::vecto // This should only happen if we had invalid input PCL_ERROR ("[pcl::%s::performReconstruction2D] Invalid input!\n", getClassName ().c_str ()); } + + qhT qh_qh; + qhT* qh = &qh_qh; + QHULL_LIB_CHECK + qh_zero(qh, errfile); // Compute convex hull - int exitcode = qh_new_qhull (dimension, static_cast (indices_->size ()), points, ismalloc, const_cast (flags), outfile, errfile); -#ifdef HAVE_QHULL_2011 + int exitcode = qh_new_qhull (qh, dimension, static_cast (indices_->size ()), points, ismalloc, const_cast (flags), outfile, errfile); if (compute_area_) { - qh_prepare_output(); + qh_prepare_output(qh); } -#endif // 0 if no error from qhull or it doesn't find any vertices - if (exitcode != 0 || qh num_vertices == 0) + if (exitcode != 0 || qh->num_vertices == 0) { PCL_ERROR ("[pcl::%s::performReconstrution2D] ERROR: qhull was unable to compute a convex hull for the given point cloud (%lu)!\n", getClassName ().c_str (), indices_->size ()); @@ -199,9 +200,9 @@ pcl::ConvexHull::performReconstruction2D (PointCloud &hull, std::vecto hull.width = hull.height = 0; polygons.resize (0); - qh_freeqhull (!qh_ALL); + qh_freeqhull (qh, !qh_ALL); int curlong, totlong; - qh_memfreeshort (&curlong, &totlong); + qh_memfreeshort (qh, &curlong, &totlong); return; } @@ -209,11 +210,11 @@ pcl::ConvexHull::performReconstruction2D (PointCloud &hull, std::vecto // Qhull returns the area in volume for 2D if (compute_area_) { - total_area_ = qh totvol; + total_area_ = qh->totvol; total_volume_ = 0.0; } - int num_vertices = qh num_vertices; + int num_vertices = qh->num_vertices; hull.clear(); hull.resize(num_vertices, PointInT{}); @@ -225,8 +226,8 @@ pcl::ConvexHull::performReconstruction2D (PointCloud &hull, std::vecto FORALLvertices { - hull[i] = (*input_)[(*indices_)[qh_pointid (vertex->point)]]; - idx_points[i].first = qh_pointid (vertex->point); + hull[i] = (*input_)[(*indices_)[qh_pointid (qh, vertex->point)]]; + idx_points[i].first = qh_pointid (qh, vertex->point); ++i; } @@ -273,9 +274,9 @@ pcl::ConvexHull::performReconstruction2D (PointCloud &hull, std::vecto polygons[0].vertices[j] = static_cast (j); } - qh_freeqhull (!qh_ALL); + qh_freeqhull (qh, !qh_ALL); int curlong, totlong; - qh_memfreeshort (&curlong, &totlong); + qh_memfreeshort (qh, &curlong, &totlong); hull.width = hull.size (); hull.height = 1; @@ -298,10 +299,8 @@ pcl::ConvexHull::performReconstruction3D ( // output from qh_produce_output(), use NULL to skip qh_produce_output() FILE *outfile = nullptr; -#ifndef HAVE_QHULL_2011 if (compute_area_) outfile = stderr; -#endif // option flags for qhull, see qh_opt.htm const char *flags = qhull_flags.c_str (); @@ -319,14 +318,17 @@ pcl::ConvexHull::performReconstruction3D ( points[j + 2] = static_cast ((*input_)[(*indices_)[i]].z); } + qhT qh_qh; + qhT* qh = &qh_qh; + QHULL_LIB_CHECK + qh_zero(qh, errfile); + // Compute convex hull - int exitcode = qh_new_qhull (dimension, static_cast (indices_->size ()), points, ismalloc, const_cast (flags), outfile, errfile); -#ifdef HAVE_QHULL_2011 + int exitcode = qh_new_qhull (qh, dimension, static_cast (indices_->size ()), points, ismalloc, const_cast (flags), outfile, errfile); if (compute_area_) { - qh_prepare_output(); + qh_prepare_output(qh); } -#endif // 0 if no error from qhull if (exitcode != 0) @@ -340,18 +342,18 @@ pcl::ConvexHull::performReconstruction3D ( hull.width = hull.height = 0; polygons.resize (0); - qh_freeqhull (!qh_ALL); + qh_freeqhull (qh, !qh_ALL); int curlong, totlong; - qh_memfreeshort (&curlong, &totlong); + qh_memfreeshort (qh, &curlong, &totlong); return; } - qh_triangulate (); + qh_triangulate (qh); - int num_facets = qh num_facets; + int num_facets = qh->num_facets; - int num_vertices = qh num_vertices; + int num_vertices = qh->num_vertices; hull.resize (num_vertices); vertexT * vertex; @@ -374,7 +376,7 @@ pcl::ConvexHull::performReconstruction3D ( FORALLvertices { // Add vertices to hull point_cloud and store index - hull_indices_.indices.push_back ((*indices_)[qh_pointid (vertex->point)]); + hull_indices_.indices.push_back ((*indices_)[qh_pointid (qh, vertex->point)]); hull[i] = (*input_)[hull_indices_.indices.back ()]; qhid_to_pcidx[vertex->id] = i; // map the vertex id of qhull to the point cloud index @@ -383,8 +385,8 @@ pcl::ConvexHull::performReconstruction3D ( if (compute_area_) { - total_area_ = qh totarea; - total_volume_ = qh totvol; + total_area_ = qh->totarea; + total_volume_ = qh->totvol; } if (fill_polygon_data) @@ -399,16 +401,16 @@ pcl::ConvexHull::performReconstruction3D ( // Needed by FOREACHvertex_i_ int vertex_n, vertex_i; - FOREACHvertex_i_ ((*facet).vertices) + FOREACHvertex_i_ (qh, (*facet).vertices) //facet_vertices.vertices.push_back (qhid_to_pcidx[vertex->id]); polygons[dd].vertices[vertex_i] = qhid_to_pcidx[vertex->id]; ++dd; } } // Deallocates memory (also the points) - qh_freeqhull (!qh_ALL); + qh_freeqhull (qh, !qh_ALL); int curlong, totlong; - qh_memfreeshort (&curlong, &totlong); + qh_memfreeshort (qh, &curlong, &totlong); hull.width = hull.size (); hull.height = 1; diff --git a/surface/include/pcl/surface/qhull.h b/surface/include/pcl/surface/qhull.h index 39eee73e401..da370497082 100644 --- a/surface/include/pcl/surface/qhull.h +++ b/surface/include/pcl/surface/qhull.h @@ -48,25 +48,14 @@ extern "C" { -#ifdef HAVE_QHULL_2011 -# include "libqhull/libqhull.h" -# include "libqhull/mem.h" -# include "libqhull/qset.h" -# include "libqhull/geom.h" -# include "libqhull/merge.h" -# include "libqhull/poly.h" -# include "libqhull/io.h" -# include "libqhull/stat.h" -#else -# include "qhull/qhull.h" -# include "qhull/mem.h" -# include "qhull/qset.h" -# include "qhull/geom.h" -# include "qhull/merge.h" -# include "qhull/poly.h" -# include "qhull/io.h" -# include "qhull/stat.h" -#endif +#include "libqhull_r/libqhull_r.h" +#include "libqhull_r/mem_r.h" +#include "libqhull_r/qset_r.h" +#include "libqhull_r/geom_r.h" +#include "libqhull_r/merge_r.h" +#include "libqhull_r/poly_r.h" +#include "libqhull_r/io_r.h" +#include "libqhull_r/stat_r.h" } #endif