|
Point Cloud Library (PCL)
1.6.0
|
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 : min_p_ (), max_p_ (), percentage_extend_grid_ (), iso_level_ () 00049 { 00050 } 00051 00053 template <typename PointNT> 00054 pcl::MarchingCubes<PointNT>::~MarchingCubes () 00055 { 00056 } 00057 00059 template <typename PointNT> void 00060 pcl::MarchingCubes<PointNT>::getBoundingBox () 00061 { 00062 pcl::getMinMax3D (*input_, min_p_, max_p_); 00063 00064 min_p_ -= (max_p_ - min_p_) * percentage_extend_grid_/2; 00065 max_p_ += (max_p_ - min_p_) * percentage_extend_grid_/2; 00066 00067 Eigen::Vector4f bounding_box_size = max_p_ - min_p_; 00068 00069 bounding_box_size = max_p_ - min_p_; 00070 PCL_DEBUG ("[pcl::MarchingCubesHoppe::getBoundingBox] Size of Bounding Box is [%f, %f, %f]\n", 00071 bounding_box_size.x (), bounding_box_size.y (), bounding_box_size.z ()); 00072 double max_size = 00073 (std::max) ((std::max)(bounding_box_size.x (), bounding_box_size.y ()), 00074 bounding_box_size.z ()); 00075 00076 // data_size_ = static_cast<uint64_t> (max_size / leaf_size_); 00077 PCL_DEBUG ("[pcl::MarchingCubesHoppe::getBoundingBox] Lower left point is [%f, %f, %f]\n", 00078 min_p_.x (), min_p_.y (), min_p_.z ()); 00079 PCL_DEBUG ("[pcl::MarchingCubesHoppe::getBoundingBox] Upper left point is [%f, %f, %f]\n", 00080 max_p_.x (), max_p_.y (), max_p_.z ()); 00081 } 00082 00083 00085 template <typename PointNT> void 00086 pcl::MarchingCubes<PointNT>::interpolateEdge (Eigen::Vector3f &p1, 00087 Eigen::Vector3f &p2, 00088 float val_p1, 00089 float val_p2, 00090 Eigen::Vector3f &output) 00091 { 00092 float mu = (iso_level_ - val_p1) / (val_p2-val_p1); 00093 output = p1 + mu * (p2 - p1); 00094 } 00095 00096 00098 template <typename PointNT> void 00099 pcl::MarchingCubes<PointNT>::createSurface (std::vector<float> &leaf_node, 00100 Eigen::Vector3i &index_3d, 00101 pcl::PointCloud<PointNT> &cloud) 00102 { 00103 int cubeindex = 0; 00104 Eigen::Vector3f vertex_list[12]; 00105 if (leaf_node[0] < iso_level_) cubeindex |= 1; 00106 if (leaf_node[1] < iso_level_) cubeindex |= 2; 00107 if (leaf_node[2] < iso_level_) cubeindex |= 4; 00108 if (leaf_node[3] < iso_level_) cubeindex |= 8; 00109 if (leaf_node[4] < iso_level_) cubeindex |= 16; 00110 if (leaf_node[5] < iso_level_) cubeindex |= 32; 00111 if (leaf_node[6] < iso_level_) cubeindex |= 64; 00112 if (leaf_node[7] < iso_level_) cubeindex |= 128; 00113 00114 // Cube is entirely in/out of the surface 00115 if (edgeTable[cubeindex] == 0) 00116 return; 00117 00118 //Eigen::Vector4f index_3df (index_3d[0], index_3d[1], index_3d[2], 0.0f); 00119 Eigen::Vector3f center;// TODO coeff wise product = min_p_ + Eigen::Vector4f (1.0f/res_x_, 1.0f/res_y_, 1.0f/res_z_) * index_3df * (max_p_ - min_p_); 00120 center[0] = min_p_[0] + (max_p_[0] - min_p_[0]) * index_3d[0] / res_x_; 00121 center[1] = min_p_[1] + (max_p_[1] - min_p_[1]) * index_3d[1] / res_y_; 00122 center[2] = min_p_[2] + (max_p_[2] - min_p_[2]) * index_3d[2] / res_z_; 00123 00124 std::vector<Eigen::Vector3f> p; 00125 p.resize (8); 00126 for (int i = 0; i < 8; ++i) 00127 { 00128 Eigen::Vector3f point = center; 00129 if(i & 0x4) 00130 point[1] = static_cast<float> (center[1] + (max_p_[1] - min_p_[1]) / float (res_y_)); 00131 00132 if(i & 0x2) 00133 point[2] = static_cast<float> (center[2] + (max_p_[2] - min_p_[2]) / float (res_z_)); 00134 00135 if((i & 0x1) ^ ((i >> 1) & 0x1)) 00136 point[0] = static_cast<float> (center[0] + (max_p_[0] - min_p_[0]) / float (res_x_)); 00137 00138 p[i] = point; 00139 } 00140 00141 00142 // Find the vertices where the surface intersects the cube 00143 if (edgeTable[cubeindex] & 1) 00144 interpolateEdge (p[0], p[1], leaf_node[0], leaf_node[1], vertex_list[0]); 00145 if (edgeTable[cubeindex] & 2) 00146 interpolateEdge (p[1], p[2], leaf_node[1], leaf_node[2], vertex_list[1]); 00147 if (edgeTable[cubeindex] & 4) 00148 interpolateEdge (p[2], p[3], leaf_node[2], leaf_node[3], vertex_list[2]); 00149 if (edgeTable[cubeindex] & 8) 00150 interpolateEdge (p[3], p[0], leaf_node[3], leaf_node[0], vertex_list[3]); 00151 if (edgeTable[cubeindex] & 16) 00152 interpolateEdge (p[4], p[5], leaf_node[4], leaf_node[5], vertex_list[4]); 00153 if (edgeTable[cubeindex] & 32) 00154 interpolateEdge (p[5], p[6], leaf_node[5], leaf_node[6], vertex_list[5]); 00155 if (edgeTable[cubeindex] & 64) 00156 interpolateEdge (p[6], p[7], leaf_node[6], leaf_node[7], vertex_list[6]); 00157 if (edgeTable[cubeindex] & 128) 00158 interpolateEdge (p[7], p[4], leaf_node[7], leaf_node[4], vertex_list[7]); 00159 if (edgeTable[cubeindex] & 256) 00160 interpolateEdge (p[0], p[4], leaf_node[0], leaf_node[4], vertex_list[8]); 00161 if (edgeTable[cubeindex] & 512) 00162 interpolateEdge (p[1], p[5], leaf_node[1], leaf_node[5], vertex_list[9]); 00163 if (edgeTable[cubeindex] & 1024) 00164 interpolateEdge (p[2], p[6], leaf_node[2], leaf_node[6], vertex_list[10]); 00165 if (edgeTable[cubeindex] & 2048) 00166 interpolateEdge (p[3], p[7], leaf_node[3], leaf_node[7], vertex_list[11]); 00167 00168 // Create the triangle 00169 for (int i = 0; triTable[cubeindex][i] != -1; i+=3) 00170 { 00171 PointNT p1,p2,p3; 00172 p1.x = vertex_list[triTable[cubeindex][i ]][0]; 00173 p1.y = vertex_list[triTable[cubeindex][i ]][1]; 00174 p1.z = vertex_list[triTable[cubeindex][i ]][2]; 00175 cloud.push_back (p1); 00176 p2.x = vertex_list[triTable[cubeindex][i+1]][0]; 00177 p2.y = vertex_list[triTable[cubeindex][i+1]][1]; 00178 p2.z = vertex_list[triTable[cubeindex][i+1]][2]; 00179 cloud.push_back (p2); 00180 p3.x = vertex_list[triTable[cubeindex][i+2]][0]; 00181 p3.y = vertex_list[triTable[cubeindex][i+2]][1]; 00182 p3.z = vertex_list[triTable[cubeindex][i+2]][2]; 00183 cloud.push_back (p3); 00184 } 00185 } 00186 00187 00189 template <typename PointNT> void 00190 pcl::MarchingCubes<PointNT>::getNeighborList1D (std::vector<float> &leaf, 00191 Eigen::Vector3i &index3d) 00192 { 00193 leaf = std::vector<float> (8, 0.0f); 00194 00195 leaf[0] = getGridValue (index3d); 00196 leaf[1] = getGridValue (index3d + Eigen::Vector3i (1, 0, 0)); 00197 leaf[2] = getGridValue (index3d + Eigen::Vector3i (1, 0, 1)); 00198 leaf[3] = getGridValue (index3d + Eigen::Vector3i (0, 0, 1)); 00199 leaf[4] = getGridValue (index3d + Eigen::Vector3i (0, 1, 0)); 00200 leaf[5] = getGridValue (index3d + Eigen::Vector3i (1, 1, 0)); 00201 leaf[6] = getGridValue (index3d + Eigen::Vector3i (1, 1, 1)); 00202 leaf[7] = getGridValue (index3d + Eigen::Vector3i (0, 1, 1)); 00203 } 00204 00205 00207 template <typename PointNT> float 00208 pcl::MarchingCubes<PointNT>::getGridValue (Eigen::Vector3i pos) 00209 { 00211 if (pos[0] < 0 || pos[0] >= res_x_) 00212 return -1.0f; 00213 if (pos[1] < 0 || pos[1] >= res_y_) 00214 return -1.0f; 00215 if (pos[2] < 0 || pos[2] >= res_z_) 00216 return -1.0f; 00217 00218 return grid_[pos[0]*res_y_*res_z_ + pos[1]*res_z_ + pos[2]]; 00219 } 00220 00221 00223 template <typename PointNT> void 00224 pcl::MarchingCubes<PointNT>::performReconstruction (pcl::PolygonMesh &output) 00225 { 00226 if (!(iso_level_ >= 0 && iso_level_ < 1)) 00227 { 00228 PCL_ERROR ("[pcl::%s::performReconstruction] Invalid iso level %f! Please use a number between 0 and 1.\n", getClassName ().c_str (), iso_level_); 00229 output.cloud.width = output.cloud.height = 0; 00230 output.cloud.data.clear (); 00231 output.polygons.clear (); 00232 return; 00233 } 00234 00235 // Create grid 00236 grid_ = std::vector<float> (res_x_*res_y_*res_z_, 0.0f); 00237 00238 // Populate tree 00239 tree_->setInputCloud (input_); 00240 00241 getBoundingBox (); 00242 00243 // Transform the point cloud into a voxel grid 00244 // This needs to be implemented in a child class 00245 voxelizeData (); 00246 00247 00248 00249 // Run the actual marching cubes algorithm, store it into a point cloud, 00250 // and copy the point cloud + connectivity into output 00251 pcl::PointCloud<PointNT> cloud; 00252 00253 for (int x = 1; x < res_x_-1; ++x) 00254 for (int y = 1; y < res_y_-1; ++y) 00255 for (int z = 1; z < res_z_-1; ++z) 00256 { 00257 Eigen::Vector3i index_3d (x, y, z); 00258 std::vector<float> leaf_node; 00259 getNeighborList1D (leaf_node, index_3d); 00260 createSurface (leaf_node, index_3d, cloud); 00261 } 00262 pcl::toROSMsg (cloud, output.cloud); 00263 00264 output.polygons.resize (cloud.size () / 3); 00265 for (size_t i = 0; i < output.polygons.size (); ++i) 00266 { 00267 pcl::Vertices v; 00268 v.vertices.resize (3); 00269 for (int j = 0; j < 3; ++j) 00270 v.vertices[j] = static_cast<int> (i) * 3 + j; 00271 output.polygons[i] = v; 00272 } 00273 } 00274 00275 00277 template <typename PointNT> void 00278 pcl::MarchingCubes<PointNT>::performReconstruction (pcl::PointCloud<PointNT> &points, 00279 std::vector<pcl::Vertices> &polygons) 00280 { 00281 if (!(iso_level_ >= 0 && iso_level_ < 1)) 00282 { 00283 PCL_ERROR ("[pcl::%s::performReconstruction] Invalid iso level %f! Please use a number between 0 and 1.\n", getClassName ().c_str (), iso_level_); 00284 points.width = points.height = 0; 00285 points.points.clear (); 00286 polygons.clear (); 00287 return; 00288 } 00289 00290 // Create grid 00291 grid_ = std::vector<float> (res_x_*res_y_*res_z_, 0.0f); 00292 00293 // Populate tree 00294 tree_->setInputCloud (input_); 00295 00296 getBoundingBox (); 00297 00298 // Transform the point cloud into a voxel grid 00299 // This needs to be implemented in a child class 00300 voxelizeData (); 00301 00302 // Run the actual marching cubes algorithm, store it into a point cloud, 00303 // and copy the point cloud + connectivity into output 00304 points.clear (); 00305 for (int x = 1; x < res_x_-1; ++x) 00306 for (int y = 1; y < res_y_-1; ++y) 00307 for (int z = 1; z < res_z_-1; ++z) 00308 { 00309 Eigen::Vector3i index_3d (x, y, z); 00310 std::vector<float> leaf_node; 00311 getNeighborList1D (leaf_node, index_3d); 00312 createSurface (leaf_node, index_3d, points); 00313 } 00314 00315 polygons.resize (points.size () / 3); 00316 for (size_t i = 0; i < polygons.size (); ++i) 00317 { 00318 pcl::Vertices v; 00319 v.vertices.resize (3); 00320 for (int j = 0; j < 3; ++j) 00321 v.vertices[j] = static_cast<int> (i) * 3 + j; 00322 polygons[i] = v; 00323 } 00324 } 00325 00326 00327 00328 #define PCL_INSTANTIATE_MarchingCubes(T) template class PCL_EXPORTS pcl::MarchingCubes<T>; 00329 00330 #endif // PCL_SURFACE_IMPL_MARCHING_CUBES_H_ 00331
1.7.6.1