00001 #include <pcl/point_cloud.h>
00002 #include <pcl/point_types.h>
00003 #include <pcl/io/pcd_io.h>
00004
00005 #include <pcl/visualization/pcl_visualizer.h>
00006 #include <pcl/surface/on_nurbs/fitting_surface_tdm.h>
00007 #include <pcl/surface/on_nurbs/fitting_curve_2d_asdm.h>
00008 #include <pcl/surface/on_nurbs/triangulation.h>
00009
00010 typedef pcl::PointXYZ Point;
00011
00012 void
00013 PointCloud2Vector3d (pcl::PointCloud<Point>::Ptr cloud, pcl::on_nurbs::vector_vec3d &data)
00014 {
00015 for (unsigned i = 0; i < cloud->size (); i++)
00016 {
00017 Point &p = cloud->at (i);
00018 if (!pcl_isnan (p.x) && !pcl_isnan (p.y) && !pcl_isnan (p.z))
00019 data.push_back (Eigen::Vector3d (p.x, p.y, p.z));
00020 }
00021 }
00022
00023 void
00024 visualizeCurve (ON_NurbsCurve &curve, ON_NurbsSurface &surface, pcl::visualization::PCLVisualizer &viewer)
00025 {
00026 pcl::PointCloud<pcl::PointXYZRGB>::Ptr curve_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
00027
00028 pcl::on_nurbs::Triangulation::convertCurve2PointCloud (curve, surface, curve_cloud, 4);
00029 for (std::size_t i = 0; i < curve_cloud->size () - 1; i++)
00030 {
00031 pcl::PointXYZRGB &p1 = curve_cloud->at (i);
00032 pcl::PointXYZRGB &p2 = curve_cloud->at (i + 1);
00033 std::ostringstream os;
00034 os << "line" << i;
00035 viewer.removeShape (os.str ());
00036 viewer.addLine<pcl::PointXYZRGB> (p1, p2, 1.0, 0.0, 0.0, os.str ());
00037 }
00038
00039 pcl::PointCloud<pcl::PointXYZRGB>::Ptr curve_cps (new pcl::PointCloud<pcl::PointXYZRGB>);
00040 for (int i = 0; i < curve.CVCount (); i++)
00041 {
00042 ON_3dPoint p1;
00043 curve.GetCV (i, p1);
00044
00045 double pnt[3];
00046 surface.Evaluate (p1.x, p1.y, 0, 3, pnt);
00047 pcl::PointXYZRGB p2;
00048 p2.x = float (pnt[0]);
00049 p2.y = float (pnt[1]);
00050 p2.z = float (pnt[2]);
00051
00052 p2.r = 255;
00053 p2.g = 0;
00054 p2.b = 0;
00055
00056 curve_cps->push_back (p2);
00057 }
00058 viewer.removePointCloud ("cloud_cps");
00059 viewer.addPointCloud (curve_cps, "cloud_cps");
00060 }
00061
00062 int
00063 main (int argc, char *argv[])
00064 {
00065 std::string pcd_file;
00066
00067 if (argc < 2)
00068 {
00069 printf ("\nUsage: pcl_example_nurbs_fitting_surface pcd<PointXYZ>-file\n\n");
00070 exit (0);
00071 }
00072
00073 pcd_file = argv[1];
00074
00075 unsigned order (3);
00076 unsigned refinement (6);
00077 unsigned iterations (10);
00078 unsigned mesh_resolution (256);
00079
00080 pcl::visualization::PCLVisualizer viewer ("Test: NURBS surface fitting");
00081 viewer.setSize (800, 600);
00082
00083
00084
00085 printf (" loading %s\n", pcd_file.c_str ());
00086 pcl::PointCloud<Point>::Ptr cloud (new pcl::PointCloud<Point>);
00087 pcl::PCLPointCloud2 cloud2;
00088 pcl::on_nurbs::NurbsDataSurface data;
00089
00090 if (pcl::io::loadPCDFile (pcd_file, cloud2) == -1)
00091 throw std::runtime_error (" PCD file not found.");
00092
00093 fromPCLPointCloud2 (cloud2, *cloud);
00094 PointCloud2Vector3d (cloud, data.interior);
00095 pcl::visualization::PointCloudColorHandlerCustom<Point> handler (cloud, 0, 255, 0);
00096 viewer.addPointCloud<Point> (cloud, handler, "cloud_cylinder");
00097 printf (" %zu points in data set\n", cloud->size ());
00098
00099
00100
00101 printf (" surface fitting ...\n");
00102 ON_NurbsSurface nurbs = pcl::on_nurbs::FittingSurface::initNurbsPCABoundingBox (order, &data);
00103 pcl::on_nurbs::FittingSurface fit (&data, nurbs);
00104
00105
00106 pcl::PolygonMesh mesh;
00107 pcl::PointCloud<pcl::PointXYZ>::Ptr mesh_cloud (new pcl::PointCloud<pcl::PointXYZ>);
00108 std::vector<pcl::Vertices> mesh_vertices;
00109
00110 std::string mesh_id = "mesh_nurbs";
00111 pcl::on_nurbs::Triangulation::convertSurface2PolygonMesh (fit.m_nurbs, mesh, mesh_resolution);
00112 viewer.addPolygonMesh (mesh, mesh_id);
00113
00114 pcl::on_nurbs::FittingSurface::Parameter params;
00115 params.interior_smoothness = 0.15;
00116 params.interior_weight = 1.0;
00117 params.boundary_smoothness = 0.15;
00118 params.boundary_weight = 0.0;
00119
00120
00121 for (unsigned i = 0; i < refinement; i++)
00122 {
00123 fit.refine (0);
00124 fit.refine (1);
00125 fit.assemble (params);
00126 fit.solve ();
00127 pcl::on_nurbs::Triangulation::convertSurface2Vertices (fit.m_nurbs, mesh_cloud, mesh_vertices, mesh_resolution);
00128 viewer.updatePolygonMesh<pcl::PointXYZ> (mesh_cloud, mesh_vertices, mesh_id);
00129 viewer.spinOnce ();
00130 }
00131
00132
00133 for (unsigned i = 0; i < iterations; i++)
00134 {
00135 fit.assemble (params);
00136 fit.solve ();
00137 pcl::on_nurbs::Triangulation::convertSurface2Vertices (fit.m_nurbs, mesh_cloud, mesh_vertices, mesh_resolution);
00138 viewer.updatePolygonMesh<pcl::PointXYZ> (mesh_cloud, mesh_vertices, mesh_id);
00139 viewer.spinOnce ();
00140 }
00141
00142
00143
00144 pcl::on_nurbs::FittingCurve2dAPDM::FitParameter curve_params;
00145 curve_params.addCPsAccuracy = 3e-2;
00146 curve_params.addCPsIteration = 3;
00147 curve_params.maxCPs = 200;
00148 curve_params.accuracy = 1e-3;
00149 curve_params.iterations = 10000;
00150
00151 curve_params.param.closest_point_resolution = 0;
00152 curve_params.param.closest_point_weight = 1.0;
00153 curve_params.param.closest_point_sigma2 = 0.1;
00154 curve_params.param.interior_sigma2 = 0.0001;
00155 curve_params.param.smooth_concavity = 1.0;
00156 curve_params.param.smoothness = 1.0;
00157
00158 pcl::on_nurbs::NurbsDataCurve2d curve_data;
00159 curve_data.interior = data.interior_param;
00160 curve_data.interior_weight_function.push_back (true);
00161
00162 ON_NurbsCurve curve_nurbs = pcl::on_nurbs::FittingCurve2dAPDM::initNurbsCurve2D (order, curve_data.interior);
00163
00164 pcl::on_nurbs::FittingCurve2dASDM curve_fit (&curve_data, curve_nurbs);
00165
00166
00167
00168 curve_fit.fitting (curve_params);
00169 visualizeCurve (curve_fit.m_nurbs, fit.m_nurbs, viewer);
00170
00171
00172
00173 printf (" triangulate trimmed surface ...\n");
00174 viewer.removePolygonMesh (mesh_id);
00175 pcl::on_nurbs::Triangulation::convertTrimmedSurface2PolygonMesh (fit.m_nurbs, curve_fit.m_nurbs, mesh,
00176 mesh_resolution);
00177 viewer.addPolygonMesh (mesh, mesh_id);
00178
00179 printf (" ... done.\n");
00180
00181 viewer.spin ();
00182 return 0;
00183 }