diff --git a/test/surface/CMakeLists.txt b/test/surface/CMakeLists.txt index 7c01b28a663..94574096ffb 100644 --- a/test/surface/CMakeLists.txt +++ b/test/surface/CMakeLists.txt @@ -39,6 +39,13 @@ PCL_ADD_TEST(surface_poisson test_poisson LINK_WITH pcl_gtest pcl_io pcl_kdtree pcl_surface pcl_features ARGUMENTS "${PCL_SOURCE_DIR}/test/bun0.pcd") +if(BUILD_surface_on_nurbs) + PCL_ADD_TEST(surface_on_nurbs test_on_nurbs + FILES test_on_nurbs.cpp + LINK_WITH pcl_gtest pcl_io pcl_kdtree pcl_surface pcl_features pcl_search + ARGUMENTS "${PCL_SOURCE_DIR}/test/bun0.pcd") +endif() + if(QHULL_FOUND) PCL_ADD_TEST(surface_convex_hull test_convex_hull FILES test_convex_hull.cpp diff --git a/test/surface/test_on_nurbs.cpp b/test/surface/test_on_nurbs.cpp new file mode 100644 index 00000000000..18700d329ee --- /dev/null +++ b/test/surface/test_on_nurbs.cpp @@ -0,0 +1,123 @@ +/* +* SPDX-License-Identifier: BSD-3-Clause +* +* Point Cloud Library (PCL) - www.pointclouds.org +* Copyright (c) 2025-, Open Perception Inc. +* +* All rights reserved +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace pcl; +using namespace pcl::io; + +using Point = pcl::PointXYZ; + +PointCloud::Ptr cloud (new PointCloud); + +void +PointCloud2Vector3d (pcl::PointCloud::Ptr cloud, pcl::on_nurbs::vector_vec3d &data) +{ + for (const auto &p : *cloud) + { + if (!std::isnan (p.x) && !std::isnan (p.y) && !std::isnan (p.z)) + data.emplace_back (p.x, p.y, p.z); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +TEST (PCL, on_nurbs_fitting_surface_pdm) +{ + // ############################################################################ + // fit B-spline surface + pcl::on_nurbs::NurbsDataSurface data; + PointCloud2Vector3d (cloud, data.interior); + // parameters + unsigned order (3); + unsigned refinement (5); + unsigned iterations (10); + unsigned mesh_resolution (256); + + pcl::on_nurbs::FittingSurface::Parameter params; + params.interior_smoothness = 0.2; + params.interior_weight = 1.0; + params.boundary_smoothness = 0.2; + params.boundary_weight = 0.0; + + // initialize + ON_NurbsSurface nurbs = pcl::on_nurbs::FittingSurface::initNurbsPCABoundingBox (order, &data); + pcl::on_nurbs::FittingSurface fit (&data, nurbs); + // fit.setQuiet (false); // enable/disable debug output + + // mesh for visualization + pcl::PolygonMesh mesh; + pcl::PointCloud::Ptr mesh_cloud (new pcl::PointCloud); + std::vector mesh_vertices; + std::string mesh_id = "mesh_nurbs"; + pcl::on_nurbs::Triangulation::convertSurface2PolygonMesh (fit.m_nurbs, mesh, mesh_resolution); + + // surface refinement + for (unsigned i = 0; i < refinement; i++) + { + fit.refine (0); + fit.refine (1); + fit.assemble (params); + fit.solve (); + pcl::on_nurbs::Triangulation::convertSurface2Vertices (fit.m_nurbs, mesh_cloud, mesh_vertices, mesh_resolution); + } + + // surface fitting with final refinement level + for (unsigned i = 0; i < iterations; i++) + { + fit.assemble (params); + fit.solve (); + pcl::on_nurbs::Triangulation::convertSurface2Vertices (fit.m_nurbs, mesh_cloud, mesh_vertices, mesh_resolution); + } + + ASSERT_EQ (mesh.polygons.size (), 131072); + // All polygons should be triangles + for (const auto & polygon : mesh.polygons) + EXPECT_EQ (polygon.vertices.size (), 3); + + EXPECT_EQ (mesh.polygons[10].vertices[0], 5); + EXPECT_EQ (mesh.polygons[10].vertices[1], 6); + EXPECT_EQ (mesh.polygons[10].vertices[2], 263); + + EXPECT_EQ (mesh.polygons[200].vertices[0], 100); + EXPECT_EQ (mesh.polygons[200].vertices[1], 101); + EXPECT_EQ (mesh.polygons[200].vertices[2], 358); + + EXPECT_EQ (mesh.polygons[1000].vertices[0], 501); + EXPECT_EQ (mesh.polygons[1000].vertices[1], 502); + EXPECT_EQ (mesh.polygons[1000].vertices[2], 759); +} + +/* ---[ */ +int +main (int argc, char** argv) +{ + if (argc < 2) + { + std::cerr << "No test file given. Please download `bun0.pcd` and pass its path to the test." << std::endl; + return (-1); + } + + // Load file + loadPCDFile (argv[1], *cloud); + + // Testing + testing::InitGoogleTest (&argc, argv); + return (RUN_ALL_TESTS ()); +} +/* ]--- */