|
Point Cloud Library (PCL)
1.5.1
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2010, Willow Garage, Inc. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of Willow Garage, Inc. nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 * 00034 */ 00035 00036 #ifndef PCL_SURFACE_IMPL_MARCHING_CUBES_H_ 00037 #define PCL_SURFACE_IMPL_MARCHING_CUBES_H_ 00038 00039 #include "pcl/surface/marching_cubes.h" 00040 #include <pcl/common/common.h> 00041 #include <pcl/common/vector_average.h> 00042 #include <pcl/Vertices.h> 00043 #include <pcl/kdtree/kdtree_flann.h> 00044 00046 template <typename PointNT> 00047 pcl::MarchingCubes<PointNT>::MarchingCubes () 00048 { 00049 } 00050 00052 template <typename PointNT> 00053 pcl::MarchingCubes<PointNT>::~MarchingCubes () 00054 { 00055 } 00056 00058 template <typename PointNT> void 00059 pcl::MarchingCubes<PointNT>::getBoundingBox () 00060 { 00061 pcl::getMinMax3D (*input_, min_p_, max_p_); 00062 00063 Eigen::Vector4f bounding_box_size = max_p_ - min_p_; 00064 00065 bounding_box_size = max_p_ - min_p_; 00066 PCL_DEBUG ("[pcl::MarchingCubes::getBoundingBox] Size of Bounding Box is [%f, %f, %f]\n", 00067 bounding_box_size.x (), bounding_box_size.y (), bounding_box_size.z ()); 00068 double max_size = 00069 (std::max) ((std::max)(bounding_box_size.x (), bounding_box_size.y ()), 00070 bounding_box_size.z ()); 00071 00072 data_size_ = max_size / leaf_size_; 00073 PCL_DEBUG ("[pcl::MarchingCubes::getBoundingBox] Lower left point is [%f, %f, %f]\n", 00074 min_p_.x (), min_p_.y (), min_p_.z ()); 00075 PCL_DEBUG ("[pcl::MarchingCubes::getBoundingBox] Upper left point is [%f, %f, %f]\n", 00076 max_p_.x (), max_p_.y (), max_p_.z ()); 00077 PCL_DEBUG ("[pcl::MarchingCubes::getBoundingBox] Padding size: %d\n", padding_size_); 00078 PCL_DEBUG ("[pcl::MarchingCubes::getBoundingBox] Leaf size: %f\n", leaf_size_); 00079 00080 gaussian_scale_ = pow ((padding_size_+1) * leaf_size_ / 2.0, 2.0); 00081 } 00082 00084 template <typename PointNT> void 00085 pcl::MarchingCubes<PointNT>::interpolateEdge (float iso_level, 00086 Eigen::Vector3f &p1, 00087 Eigen::Vector3f &p2, 00088 float val_p1, 00089 float val_p2, 00090 Eigen::Vector3f &output) 00091 { 00092 if (iso_level - val_p1 < 0.00001) 00093 output = p1; 00094 if (iso_level - val_p2 < 0.00001) 00095 output = p2; 00096 if (val_p1 - val_p2 < 0.00001) 00097 output = p1; 00098 00099 float mu = (iso_level - val_p1) / (val_p2-val_p1); 00100 output[0] = p1[0] + mu * (p2[0] - p1[0]); 00101 output[1] = p1[1] + mu * (p2[1] - p1[1]); 00102 output[2] = p1[2] + mu * (p2[2] - p1[2]); 00103 } 00104 00106 template <typename PointNT> void 00107 pcl::MarchingCubes<PointNT>::createSurface (Leaf leaf_node, 00108 Eigen::Vector3i &index_3d, 00109 pcl::PointCloud<PointNT> &cloud, 00110 float iso_level) 00111 { 00112 int cubeindex = 0; 00113 Eigen::Vector3f vertex_list[12]; 00114 if (leaf_node.vertex[0] < iso_level) cubeindex |= 1; 00115 if (leaf_node.vertex[1] < iso_level) cubeindex |= 2; 00116 if (leaf_node.vertex[2] < iso_level) cubeindex |= 4; 00117 if (leaf_node.vertex[3] < iso_level) cubeindex |= 8; 00118 if (leaf_node.vertex[4] < iso_level) cubeindex |= 16; 00119 if (leaf_node.vertex[5] < iso_level) cubeindex |= 32; 00120 if (leaf_node.vertex[6] < iso_level) cubeindex |= 64; 00121 if (leaf_node.vertex[7] < iso_level) cubeindex |= 128; 00122 00123 // Cube is entirely in/out of the surface 00124 if (edgeTable[cubeindex] == 0) 00125 return; 00126 00127 std::vector<Eigen::Vector3f> p; 00128 p.resize (8); 00129 Eigen::Vector4f center; 00130 getCellCenterFromIndex (index_3d, center); 00131 for (int i = 0; i < 8; ++i) 00132 { 00133 Eigen::Vector3f point; 00134 if(i & 0x4) 00135 point[1] = center[1] + leaf_size_/2; 00136 else 00137 point[1] = center[1] - leaf_size_/2; 00138 00139 if(i & 0x2) 00140 point[2] = center[2] + leaf_size_/2; 00141 else 00142 point[2] = center[2] - leaf_size_/2; 00143 00144 if((i & 0x1) ^ ((i >> 1) & 0x1)) 00145 point[0] = center[0] + leaf_size_/2; 00146 else 00147 point[0] = center[0] - leaf_size_/2; 00148 00149 p[i] = point; 00150 } 00151 00152 // Find the vertices where the surface intersects the cube 00153 if (edgeTable[cubeindex] & 1) 00154 interpolateEdge (iso_level,p[0],p[1],leaf_node.vertex[0],leaf_node.vertex[1], vertex_list[0]); 00155 if (edgeTable[cubeindex] & 2) 00156 interpolateEdge (iso_level,p[1],p[2],leaf_node.vertex[1],leaf_node.vertex[2], vertex_list[1]); 00157 if (edgeTable[cubeindex] & 4) 00158 interpolateEdge (iso_level,p[2],p[3],leaf_node.vertex[2],leaf_node.vertex[3], vertex_list[2]); 00159 if (edgeTable[cubeindex] & 8) 00160 interpolateEdge (iso_level,p[3],p[0],leaf_node.vertex[3],leaf_node.vertex[0], vertex_list[3]); 00161 if (edgeTable[cubeindex] & 16) 00162 interpolateEdge (iso_level,p[4],p[5],leaf_node.vertex[4],leaf_node.vertex[5], vertex_list[4]); 00163 if (edgeTable[cubeindex] & 32) 00164 interpolateEdge (iso_level,p[5],p[6],leaf_node.vertex[5],leaf_node.vertex[6], vertex_list[5]); 00165 if (edgeTable[cubeindex] & 64) 00166 interpolateEdge (iso_level,p[6],p[7],leaf_node.vertex[6],leaf_node.vertex[7], vertex_list[6]); 00167 if (edgeTable[cubeindex] & 128) 00168 interpolateEdge (iso_level,p[7],p[4],leaf_node.vertex[7],leaf_node.vertex[4], vertex_list[7]); 00169 if (edgeTable[cubeindex] & 256) 00170 interpolateEdge (iso_level,p[0],p[4],leaf_node.vertex[0],leaf_node.vertex[4], vertex_list[8]); 00171 if (edgeTable[cubeindex] & 512) 00172 interpolateEdge (iso_level,p[1],p[5],leaf_node.vertex[1],leaf_node.vertex[5], vertex_list[9]); 00173 if (edgeTable[cubeindex] & 1024) 00174 interpolateEdge (iso_level,p[2],p[6],leaf_node.vertex[2],leaf_node.vertex[6], vertex_list[10]); 00175 if (edgeTable[cubeindex] & 2048) 00176 interpolateEdge (iso_level,p[3],p[7],leaf_node.vertex[3],leaf_node.vertex[7], vertex_list[11]); 00177 00178 // Create the triangle 00179 for (int i = 0; triTable[cubeindex][i] != -1; i+=3) 00180 { 00181 PointNT p1,p2,p3; 00182 p1.x = vertex_list[triTable[cubeindex][i ]][0]; 00183 p1.y = vertex_list[triTable[cubeindex][i ]][1]; 00184 p1.z = vertex_list[triTable[cubeindex][i ]][2]; 00185 cloud.push_back (p1); 00186 p2.x = vertex_list[triTable[cubeindex][i+1]][0]; 00187 p2.y = vertex_list[triTable[cubeindex][i+1]][1]; 00188 p2.z = vertex_list[triTable[cubeindex][i+1]][2]; 00189 cloud.push_back (p2); 00190 p3.x = vertex_list[triTable[cubeindex][i+2]][0]; 00191 p3.y = vertex_list[triTable[cubeindex][i+2]][1]; 00192 p3.z = vertex_list[triTable[cubeindex][i+2]][2]; 00193 cloud.push_back (p3); 00194 } 00195 } 00196 00198 template <typename PointNT> void 00199 pcl::MarchingCubes<PointNT>::getNeighborList1D (Leaf leaf, 00200 Eigen::Vector3i &index3d, 00201 HashMap &neighbor_list) 00202 { 00203 for (int x = -1; x < 2; ++x) 00204 { 00205 for (int y = -1; y < 2; ++y) 00206 { 00207 for (int z = -1; z < 2; ++z) 00208 { 00209 if (x == 0 && y == 0 && z == 0) 00210 continue; 00211 00212 if (index3d[0] == 0 && x == -1) 00213 continue; 00214 if (index3d[1] == 0 && y == -1) 00215 continue; 00216 if (index3d[2] == 0 && z == -1) 00217 continue; 00218 00219 Eigen::Vector3i neighbor_index; 00220 neighbor_index[0] = index3d[0] + x; 00221 neighbor_index[1] = index3d[1] + y; 00222 neighbor_index[2] = index3d[2] + z; 00223 Leaf neighbor_leaf; 00224 00225 if ((x == 0 || x == 1) && 00226 (y == 0 || y == 1) && 00227 (z == 0 || z == 1)) 00228 neighbor_leaf.vertex[0] = leaf.vertex[0]; 00229 00230 if ((x == 0 || x == -1) && 00231 (y == 0 || y == 1) && 00232 (z == 0 || z == 1)) 00233 neighbor_leaf.vertex[1] = leaf.vertex[1]; 00234 00235 if ((x == 0 || x == -1) && 00236 (y == 0 || y == 1) && 00237 (z == 0 || z == -1)) 00238 neighbor_leaf.vertex[2] = leaf.vertex[2]; 00239 00240 if ((x == 0 || x == 1) && 00241 (y == 0 || y == 1) && 00242 (z == 0 || z == -1)) 00243 neighbor_leaf.vertex[3] = leaf.vertex[3]; 00244 00245 if ((x == 0 || x == 1) && 00246 (y == 0 || y == -1) && 00247 (z == 0 || z == 1)) 00248 neighbor_leaf.vertex[4] = leaf.vertex[4]; 00249 00250 if ((x == 0 || x == -1) && 00251 (y == 0 || y == -1) && 00252 (z == 0 || z == 1)) 00253 neighbor_leaf.vertex[5] = leaf.vertex[5]; 00254 00255 if ((x == 0 || x == -1) && 00256 (y == 0 || y == -1) && 00257 (z == 0 || z == -1)) 00258 neighbor_leaf.vertex[6] = leaf.vertex[6]; 00259 00260 if ((x == 0 || x == 1) && 00261 (y == 0 || y == -1) && 00262 (z == 0 || z == -1)) 00263 neighbor_leaf.vertex[7] = leaf.vertex[7]; 00264 00265 neighbor_list[getIndexIn1D (neighbor_index)] = neighbor_leaf; 00266 } 00267 } 00268 } 00269 } 00270 00272 template <typename PointNT> void 00273 pcl::MarchingCubes<PointNT>::performReconstruction (pcl::PolygonMesh &output) 00274 { 00275 if (!(iso_level_ > 0 && iso_level_ < 1)) 00276 { 00277 PCL_ERROR ("[pcl::%s::performReconstruction] Invalid iso level %f! Please use a number between 0 and 1.\n", getClassName ().c_str (), iso_level_); 00278 output.cloud.width = output.cloud.height = 0; 00279 output.cloud.data.clear (); 00280 output.polygons.clear (); 00281 return; 00282 } 00283 if (leaf_size_ <=0) 00284 { 00285 PCL_ERROR ("[pcl::%s::performReconstruction] Invalid leaf size %f! Please use a number greater than 0.\n", getClassName ().c_str (), leaf_size_); 00286 output.cloud.width = output.cloud.height = 0; 00287 output.cloud.data.clear (); 00288 output.polygons.clear (); 00289 return; 00290 00291 } 00292 00293 getBoundingBox (); 00294 00295 // transform the point cloud into a voxel grid 00296 // this needs to be implemented in a child class 00297 voxelizeData (); 00298 00299 // run the actual marching cubes algorithm, store it into a point cloud, 00300 // and copy the point cloud + connectivity into output 00301 pcl::PointCloud<PointNT> cloud; 00302 BOOST_FOREACH (typename HashMap::value_type entry, cell_hash_map_) 00303 { 00304 Eigen::Vector3i leaf_index; 00305 getIndexIn3D (entry.first, leaf_index); 00306 createSurface (entry.second, leaf_index, cloud, iso_level_); 00307 } 00308 pcl::toROSMsg (cloud, output.cloud); 00309 output.polygons.resize (cloud.size () / 3); 00310 00311 for (size_t i = 0; i < output.polygons.size (); ++i) 00312 { 00313 pcl::Vertices v; 00314 v.vertices.resize (3); 00315 for (int j = 0; j < 3; ++j) 00316 v.vertices[j] = i*3+j; 00317 output.polygons[i] = v; 00318 } 00319 } 00320 00322 template <typename PointNT> void 00323 pcl::MarchingCubes<PointNT>::performReconstruction (pcl::PointCloud<PointNT> &points, 00324 std::vector<pcl::Vertices> &polygons) 00325 { 00327 if (!(iso_level_ > 0 && iso_level_ < 1)) 00328 { 00329 PCL_ERROR ("[pcl::%s::performReconstruction] Invalid iso level %f! Please use a number between 0 and 1.\n", getClassName ().c_str (), iso_level_); 00330 points.width = points.height = 0; 00331 points.clear (); 00332 polygons.clear (); 00333 return; 00334 } 00335 if (leaf_size_ <=0) 00336 { 00337 PCL_ERROR ("[pcl::%s::performReconstruction] Invalid leaf size %f! Please use a number greater than 0.\n", getClassName ().c_str (), leaf_size_); 00338 points.width = points.height = 0; 00339 points.clear (); 00340 polygons.clear (); 00341 return; 00342 00343 } 00344 00345 getBoundingBox (); 00346 00347 // transform the point cloud into a voxel grid 00348 // this needs to be implemented in a child class 00349 voxelizeData (); 00350 00351 // run the actual marching cubes algorithm, store it into a point cloud, 00352 // and copy the point cloud + connectivity into output 00353 BOOST_FOREACH (typename HashMap::value_type entry, cell_hash_map_) 00354 { 00355 Eigen::Vector3i leaf_index; 00356 getIndexIn3D (entry.first, leaf_index); 00357 createSurface (entry.second, leaf_index, points, iso_level_); 00358 } 00359 polygons.resize (points.size () / 3); 00360 00361 for (size_t i = 0; i < polygons.size (); ++i) 00362 { 00363 pcl::Vertices v; 00364 v.vertices.resize (3); 00365 for (int j = 0; j < 3; ++j) 00366 v.vertices[j] = i*3+j; 00367 polygons[i] = v; 00368 } 00369 } 00370 00371 00372 00373 #define PCL_INSTANTIATE_MarchingCubes(T) template class PCL_EXPORTS pcl::MarchingCubes<T>; 00374 00375 #endif // PCL_SURFACE_IMPL_MARCHING_CUBES_H_ 00376
1.8.0