00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
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
00115 if (edgeTable[cubeindex] == 0)
00116 return;
00117
00118
00119 Eigen::Vector3f center;
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
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
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
00236 grid_ = std::vector<float> (res_x_*res_y_*res_z_, 0.0f);
00237
00238
00239 tree_->setInputCloud (input_);
00240
00241 getBoundingBox ();
00242
00243
00244
00245 voxelizeData ();
00246
00247
00248
00249
00250
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
00291 grid_ = std::vector<float> (res_x_*res_y_*res_z_, 0.0f);
00292
00293
00294 tree_->setInputCloud (input_);
00295
00296 getBoundingBox ();
00297
00298
00299
00300 voxelizeData ();
00301
00302
00303
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