# Construct a convex hull polygon for a plane model

In this tutorial we will learn how to calculate a simple 2D convex hull polygon for a set of points supported by a plane.

The following video shows a demonstration of the code given below on the test dataset table_scene_mug_stereo_textured.pcd.

# The code

Then, create a file, let’s say, convex_hull_2d.cpp in your favorite editor, and place the following inside it:

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #include #include #include #include #include #include #include #include #include int main (int argc, char** argv) { pcl::PointCloud::Ptr cloud (new pcl::PointCloud), cloud_filtered (new pcl::PointCloud), cloud_projected (new pcl::PointCloud); pcl::PCDReader reader; reader.read ("table_scene_mug_stereo_textured.pcd", *cloud); // Build a filter to remove spurious NaNs pcl::PassThrough pass; pass.setInputCloud (cloud); pass.setFilterFieldName ("z"); pass.setFilterLimits (0, 1.1); pass.filter (*cloud_filtered); std::cerr << "PointCloud after filtering has: " << cloud_filtered->points.size () << " data points." << std::endl; pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients); pcl::PointIndices::Ptr inliers (new pcl::PointIndices); // Create the segmentation object pcl::SACSegmentation seg; // Optional seg.setOptimizeCoefficients (true); // Mandatory seg.setModelType (pcl::SACMODEL_PLANE); seg.setMethodType (pcl::SAC_RANSAC); seg.setDistanceThreshold (0.01); seg.setInputCloud (cloud_filtered); seg.segment (*inliers, *coefficients); // Project the model inliers pcl::ProjectInliers proj; proj.setModelType (pcl::SACMODEL_PLANE); proj.setInputCloud (cloud_filtered); proj.setIndices (inliers); proj.setModelCoefficients (coefficients); proj.filter (*cloud_projected); // Create a Convex Hull representation of the projected inliers pcl::PointCloud::Ptr cloud_hull (new pcl::PointCloud); pcl::ConvexHull chull; chull.setInputCloud (cloud_projected); chull.reconstruct (*cloud_hull); std::cerr << "Convex hull has: " << cloud_hull->points.size () << " data points." << std::endl; pcl::PCDWriter writer; writer.write ("table_scene_mug_stereo_textured_hull.pcd", *cloud_hull, false); return (0); } 

# The explanation

The only interesting part is in the lines below, where the ConvexHull object gets created and the reconstruction is performed:

  // Create a Convex Hull representation of the projected inliers
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZ>);
pcl::ConvexHull<pcl::PointXYZ> chull;
chull.setInputCloud (cloud_projected);


# Compiling and running the program

  1 2 3 4 5 6 7 8 9 10 11 12 cmake_minimum_required(VERSION 2.8 FATAL_ERROR) project(convex_hull_2d) find_package(PCL 1.2 REQUIRED) include_directories(${PCL_INCLUDE_DIRS}) link_directories(${PCL_LIBRARY_DIRS}) add_definitions(${PCL_DEFINITIONS}) add_executable (convex_hull_2d convex_hull_2d.cpp) target_link_libraries (convex_hull_2d${PCL_LIBRARIES}) 
\$ ./convex_hull_2d

PointCloud after filtering has: 139656 data points.