1 /*
2 * Software License Agreement (BSD License)
3 *
4 * Point Cloud Library (PCL) - www.pointclouds.org
5 * Copyright (c) 2012-, Open Perception, Inc.
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 * * Neither the name of the copyright holder(s) nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 *
36 * $Id: test_surface.cpp 6579 2012-07-27 18:57:32Z rusu $
37 *
38 */
39
40 #include <pcl/test/gtest.h>
41
42 #include <pcl/point_types.h>
43 #include <pcl/io/pcd_io.h>
44 #include <pcl/io/vtk_io.h>
45 #include <pcl/features/normal_3d.h>
46 #include <pcl/surface/gp3.h>
47 #include <pcl/common/common.h>
48
49 #include <pcl/io/obj_io.h>
50 #include <pcl/TextureMesh.h>
51 #include <pcl/surface/texture_mapping.h>
52 using namespace pcl;
53 using namespace pcl::io;
54
55 PointCloud<PointXYZ>::Ptr cloud (new PointCloud<PointXYZ>);
56 PointCloud<PointNormal>::Ptr cloud_with_normals (new PointCloud<PointNormal>);
57 search::KdTree<PointXYZ>::Ptr tree;
58 search::KdTree<PointNormal>::Ptr tree2;
59
60 // add by ktran to test update functions
61 PointCloud<PointXYZ>::Ptr cloud1 (new PointCloud<PointXYZ>);
62 PointCloud<PointNormal>::Ptr cloud_with_normals1 (new PointCloud<PointNormal>);
63 search::KdTree<PointXYZ>::Ptr tree3;
64 search::KdTree<PointNormal>::Ptr tree4;
65
66 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST(PCL,GreedyProjectionTriangulation)67 TEST (PCL, GreedyProjectionTriangulation)
68 {
69 // Init objects
70 PolygonMesh triangles;
71 GreedyProjectionTriangulation<PointNormal> gp3;
72
73 // Set parameters
74 gp3.setInputCloud (cloud_with_normals);
75 gp3.setSearchMethod (tree2);
76 gp3.setSearchRadius (0.025);
77 gp3.setMu (2.5);
78 gp3.setMaximumNearestNeighbors (100);
79 gp3.setMaximumSurfaceAngle(M_PI/4); // 45 degrees
80 gp3.setMinimumAngle(M_PI/18); // 10 degrees
81 gp3.setMaximumAngle(2*M_PI/3); // 120 degrees
82 gp3.setNormalConsistency(false);
83
84 // Reconstruct
85 gp3.reconstruct (triangles);
86 //saveVTKFile ("./test/bun0-gp3.vtk", triangles);
87 EXPECT_EQ (triangles.cloud.width, cloud_with_normals->width);
88 EXPECT_EQ (triangles.cloud.height, cloud_with_normals->height);
89 EXPECT_NEAR (int (triangles.polygons.size ()), 685, 5);
90
91 // Check triangles
92 EXPECT_EQ (int (triangles.polygons.at (0).vertices.size ()), 3);
93 EXPECT_EQ (int (triangles.polygons.at (0).vertices.at (0)), 0);
94 EXPECT_EQ (int (triangles.polygons.at (0).vertices.at (1)), 12);
95 EXPECT_EQ (int (triangles.polygons.at (0).vertices.at (2)), 198);
96 EXPECT_EQ (int (triangles.polygons.at (684).vertices.size ()), 3);
97 EXPECT_EQ (int (triangles.polygons.at (684).vertices.at (0)), 393);
98 EXPECT_EQ (int (triangles.polygons.at (684).vertices.at (1)), 394);
99 EXPECT_EQ (int (triangles.polygons.at (684).vertices.at (2)), 395);
100
101 // Additional vertex information
102 std::vector<int> parts = gp3.getPartIDs();
103 std::vector<int> states = gp3.getPointStates();
104 int nr_points = cloud_with_normals->width * cloud_with_normals->height;
105 EXPECT_EQ (int (parts.size ()), nr_points);
106 EXPECT_EQ (int (states.size ()), nr_points);
107 EXPECT_EQ (parts[0], 0);
108 EXPECT_EQ (states[0], gp3.COMPLETED);
109 EXPECT_EQ (parts[393], 5);
110 EXPECT_EQ (states[393], gp3.BOUNDARY);
111 }
112
113 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST(PCL,GreedyProjectionTriangulation_Merge2Meshes)114 TEST (PCL, GreedyProjectionTriangulation_Merge2Meshes)
115 {
116 // check if exist update cloud
117 if(cloud_with_normals1->width * cloud_with_normals1->height > 0){
118 // Init objects
119 PolygonMesh triangles;
120 PolygonMesh triangles1;
121 GreedyProjectionTriangulation<PointNormal> gp3;
122 GreedyProjectionTriangulation<PointNormal> gp31;
123
124 // Set parameters
125 gp3.setInputCloud (cloud_with_normals);
126 gp3.setSearchMethod (tree2);
127 gp3.setSearchRadius (0.025);
128 gp3.setMu (2.5);
129 gp3.setMaximumNearestNeighbors (100);
130 gp3.setMaximumSurfaceAngle(M_PI/4); // 45 degrees
131 gp3.setMinimumAngle(M_PI/18); // 10 degrees
132 gp3.setMaximumAngle(2*M_PI/3); // 120 degrees
133 gp3.setNormalConsistency(false);
134
135 // for mesh 2
136 // Set parameters
137 gp31.setInputCloud (cloud_with_normals1);
138 gp31.setSearchMethod (tree4);
139 gp31.setSearchRadius (0.025);
140 gp31.setMu (2.5);
141 gp31.setMaximumNearestNeighbors (100);
142 gp31.setMaximumSurfaceAngle(M_PI/4); // 45 degrees
143 gp31.setMinimumAngle(M_PI/18); // 10 degrees
144 gp31.setMaximumAngle(2*M_PI/3); // 120 degrees
145 gp31.setNormalConsistency(false);
146
147
148 // Reconstruct
149 //gp3.reconstruct (triangles);
150 //saveVTKFile ("bun01.vtk", triangles);
151
152 //gp31.reconstruct (triangles1);
153 //saveVTKFile ("bun02.vtk", triangles1);
154 }
155 }
156 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST(PCL,UpdateMesh_With_TextureMapping)157 TEST (PCL, UpdateMesh_With_TextureMapping)
158 {
159 if(cloud_with_normals1->width * cloud_with_normals1->height > 0){
160 // Init objects
161 PolygonMesh triangles;
162 PolygonMesh triangles1;
163 GreedyProjectionTriangulation<PointNormal> gp3;
164 GreedyProjectionTriangulation<PointNormal> gp31;
165
166 // Set parameters
167 gp3.setInputCloud (cloud_with_normals);
168 gp3.setSearchMethod (tree2);
169 gp3.setSearchRadius (0.025);
170 gp3.setMu (2.5);
171 gp3.setMaximumNearestNeighbors (100);
172 gp3.setMaximumSurfaceAngle(M_PI/4); // 45 degrees
173 gp3.setMinimumAngle(M_PI/18); // 10 degrees
174 gp3.setMaximumAngle(2*M_PI/3); // 120 degrees
175 gp3.setNormalConsistency(false);
176
177 gp3.reconstruct (triangles);
178
179 EXPECT_EQ (triangles.cloud.width, cloud_with_normals->width);
180 EXPECT_EQ (triangles.cloud.height, cloud_with_normals->height);
181 EXPECT_EQ (int (triangles.polygons.size ()), 685);
182
183 // update with texture mapping
184 // set 2 texture for 2 mesh
185 std::vector<std::string> tex_files;
186 tex_files.emplace_back("tex4.jpg");
187
188 // initialize texture mesh
189 TextureMesh tex_mesh;
190 tex_mesh.cloud = triangles.cloud;
191
192 // add the 1st mesh
193 tex_mesh.tex_polygons.push_back(triangles.polygons);
194
195 // update mesh and texture mesh
196 //gp3.updateMesh(cloud_with_normals1, triangles, tex_mesh);
197 // set texture for added cloud
198 //tex_files.push_back("tex8.jpg");
199 // save updated mesh
200 //saveVTKFile ("update_bunny.vtk", triangles);
201
202 //TextureMapping<PointXYZ> tm;
203
204 //// set mesh scale control
205 //tm.setF(0.01);
206
207 //// set vector field
208 //tm.setVectorField(1, 0, 0);
209
210 //TexMaterial tex_material;
211
212 //// default texture materials parameters
213 //tex_material.tex_Ka.r = 0.2f;
214 //tex_material.tex_Ka.g = 0.2f;
215 //tex_material.tex_Ka.b = 0.2f;
216
217 //tex_material.tex_Kd.r = 0.8f;
218 //tex_material.tex_Kd.g = 0.8f;
219 //tex_material.tex_Kd.b = 0.8f;
220
221 //tex_material.tex_Ks.r = 1.0f;
222 //tex_material.tex_Ks.g = 1.0f;
223 //tex_material.tex_Ks.b = 1.0f;
224 //tex_material.tex_d = 1.0f;
225 //tex_material.tex_Ns = 0.0f;
226 //tex_material.tex_illum = 2;
227
228 //// set texture material parameters
229 //tm.setTextureMaterials(tex_material);
230
231 //// set texture files
232 //tm.setTextureFiles(tex_files);
233
234 //// mapping
235 //tm.mapTexture2Mesh(tex_mesh);
236
237 //saveOBJFile ("update_bunny.obj", tex_mesh);
238 }
239 }
240
241 /* ---[ */
242 int
main(int argc,char ** argv)243 main (int argc, char** argv)
244 {
245 if (argc < 2)
246 {
247 std::cerr << "No test file given. Please download `bun0.pcd` and pass its path to the test." << std::endl;
248 return (-1);
249 }
250
251 // Load file
252 pcl::PCLPointCloud2 cloud_blob;
253 loadPCDFile (argv[1], cloud_blob);
254 fromPCLPointCloud2 (cloud_blob, *cloud);
255
256 // Create search tree
257 tree.reset (new search::KdTree<PointXYZ> (false));
258 tree->setInputCloud (cloud);
259
260 // Normal estimation
261 NormalEstimation<PointXYZ, Normal> n;
262 PointCloud<Normal>::Ptr normals (new PointCloud<Normal> ());
263 n.setInputCloud (cloud);
264 //n.setIndices (indices[B);
265 n.setSearchMethod (tree);
266 n.setKSearch (20);
267 n.compute (*normals);
268
269 // Concatenate XYZ and normal information
270 pcl::concatenateFields (*cloud, *normals, *cloud_with_normals);
271
272 // Create search tree
273 tree2.reset (new search::KdTree<PointNormal>);
274 tree2->setInputCloud (cloud_with_normals);
275
276 // Process for update cloud
277 if(argc == 3){
278 pcl::PCLPointCloud2 cloud_blob1;
279 loadPCDFile (argv[2], cloud_blob1);
280 fromPCLPointCloud2 (cloud_blob1, *cloud1);
281 // Create search tree
282 tree3.reset (new search::KdTree<PointXYZ> (false));
283 tree3->setInputCloud (cloud1);
284
285 // Normal estimation
286 NormalEstimation<PointXYZ, Normal> n1;
287 PointCloud<Normal>::Ptr normals1 (new PointCloud<Normal> ());
288 n1.setInputCloud (cloud1);
289
290 n1.setSearchMethod (tree3);
291 n1.setKSearch (20);
292 n1.compute (*normals1);
293
294 // Concatenate XYZ and normal information
295 pcl::concatenateFields (*cloud1, *normals1, *cloud_with_normals1);
296 // Create search tree
297 tree4.reset (new search::KdTree<PointNormal>);
298 tree4->setInputCloud (cloud_with_normals1);
299 }
300
301 // Testing
302 testing::InitGoogleTest (&argc, argv);
303 return (RUN_ALL_TESTS ());
304 }
305 /* ]--- */
306