00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2011, Dirk Holz, University of Bonn. 00006 * Copyright (c) 2010-2011, Willow Garage, Inc. 00007 * 00008 * All rights reserved. 00009 * 00010 * Redistribution and use in source and binary forms, with or without 00011 * modification, are permitted provided that the following conditions 00012 * are met: 00013 * 00014 * * Redistributions of source code must retain the above copyright 00015 * notice, this list of conditions and the following disclaimer. 00016 * * Redistributions in binary form must reproduce the above 00017 * copyright notice, this list of conditions and the following 00018 * disclaimer in the documentation and/or other materials provided 00019 * with the distribution. 00020 * * Neither the name of Willow Garage, Inc. nor the names of its 00021 * contributors may be used to endorse or promote products derived 00022 * from this software without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00025 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00026 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00027 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00028 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00029 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00030 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00031 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00032 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00033 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00034 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00035 * POSSIBILITY OF SUCH DAMAGE. 00036 * 00037 * $Id$ 00038 * 00039 */ 00040 00041 #ifndef PCL_SURFACE_ORGANIZED_FAST_MESH_H_ 00042 #define PCL_SURFACE_ORGANIZED_FAST_MESH_H_ 00043 00044 #include <pcl/common/angles.h> 00045 #include <pcl/surface/reconstruction.h> 00046 00047 namespace pcl 00048 { 00049 00050 /** \brief Simple triangulation/surface reconstruction for organized point 00051 * clouds. Neighboring points (pixels in image space) are connected to 00052 * construct a triangular (or quad) mesh. 00053 * 00054 * \note If you use this code in any academic work, please cite: 00055 * D. Holz and S. Behnke. 00056 * Fast Range Image Segmentation and Smoothing using Approximate Surface Reconstruction and Region Growing. 00057 * In Proceedings of the 12th International Conference on Intelligent Autonomous Systems (IAS), 00058 * Jeju Island, Korea, June 26-29 2012. 00059 * <a href="http://purl.org/holz/papers/holz_2012_ias.pdf">http://purl.org/holz/papers/holz_2012_ias.pdf</a> 00060 * 00061 * \author Dirk Holz, Radu B. Rusu 00062 * \ingroup surface 00063 */ 00064 template <typename PointInT> 00065 class OrganizedFastMesh : public MeshConstruction<PointInT> 00066 { 00067 public: 00068 typedef boost::shared_ptr<OrganizedFastMesh<PointInT> > Ptr; 00069 typedef boost::shared_ptr<const OrganizedFastMesh<PointInT> > ConstPtr; 00070 00071 using MeshConstruction<PointInT>::input_; 00072 using MeshConstruction<PointInT>::check_tree_; 00073 00074 typedef typename pcl::PointCloud<PointInT>::Ptr PointCloudPtr; 00075 00076 typedef std::vector<pcl::Vertices> Polygons; 00077 00078 enum TriangulationType 00079 { 00080 TRIANGLE_RIGHT_CUT, // _always_ "cuts" a quad from top left to bottom right 00081 TRIANGLE_LEFT_CUT, // _always_ "cuts" a quad from top right to bottom left 00082 TRIANGLE_ADAPTIVE_CUT, // "cuts" where possible and prefers larger differences in 'z' direction 00083 QUAD_MESH // create a simple quad mesh 00084 }; 00085 00086 /** \brief Constructor. Triangulation type defaults to \a QUAD_MESH. */ 00087 OrganizedFastMesh () 00088 : max_edge_length_squared_ (0.025f) 00089 , triangle_pixel_size_rows_ (1) 00090 , triangle_pixel_size_columns_ (1) 00091 , triangulation_type_ (QUAD_MESH) 00092 , store_shadowed_faces_ (false) 00093 , cos_angle_tolerance_ (fabsf (cosf (pcl::deg2rad (12.5f)))) 00094 { 00095 check_tree_ = false; 00096 }; 00097 00098 /** \brief Destructor. */ 00099 virtual ~OrganizedFastMesh () {}; 00100 00101 /** \brief Set a maximum edge length. TODO: Implement! 00102 * \param[in] max_edge_length the maximum edge length 00103 */ 00104 inline void 00105 setMaxEdgeLength (float max_edge_length) 00106 { 00107 max_edge_length_squared_ = max_edge_length * max_edge_length; 00108 }; 00109 00110 /** \brief Set the edge length (in pixels) used for constructing the fixed mesh. 00111 * \param[in] triangle_size edge length in pixels 00112 * (Default: 1 = neighboring pixels are connected) 00113 */ 00114 inline void 00115 setTrianglePixelSize (int triangle_size) 00116 { 00117 setTrianglePixelSizeRows (triangle_size); 00118 setTrianglePixelSizeColumns (triangle_size); 00119 } 00120 00121 /** \brief Set the edge length (in pixels) used for iterating over rows when constructing the fixed mesh. 00122 * \param[in] triangle_size edge length in pixels 00123 * (Default: 1 = neighboring pixels are connected) 00124 */ 00125 inline void 00126 setTrianglePixelSizeRows (int triangle_size) 00127 { 00128 triangle_pixel_size_rows_ = std::max (1, (triangle_size - 1)); 00129 } 00130 00131 /** \brief Set the edge length (in pixels) used for iterating over columns when constructing the fixed mesh. 00132 * \param[in] triangle_size edge length in pixels 00133 * (Default: 1 = neighboring pixels are connected) 00134 */ 00135 inline void 00136 setTrianglePixelSizeColumns (int triangle_size) 00137 { 00138 triangle_pixel_size_columns_ = std::max (1, (triangle_size - 1)); 00139 } 00140 00141 /** \brief Set the triangulation type (see \a TriangulationType) 00142 * \param[in] type quad mesh, triangle mesh with fixed left, right cut, 00143 * or adaptive cut (splits a quad w.r.t. the depth (z) of the points) 00144 */ 00145 inline void 00146 setTriangulationType (TriangulationType type) 00147 { 00148 triangulation_type_ = type; 00149 } 00150 00151 /** \brief Store shadowed faces or not. 00152 * \param[in] enable set to true to store shadowed faces 00153 */ 00154 inline void 00155 storeShadowedFaces (bool enable) 00156 { 00157 store_shadowed_faces_ = enable; 00158 } 00159 00160 protected: 00161 /** \brief max (squared) length of edge */ 00162 float max_edge_length_squared_; 00163 00164 /** \brief size of triangle edges (in pixels) for iterating over rows. */ 00165 int triangle_pixel_size_rows_; 00166 00167 /** \brief size of triangle edges (in pixels) for iterating over columns*/ 00168 int triangle_pixel_size_columns_; 00169 00170 /** \brief Type of meshing scheme (quads vs. triangles, left cut vs. right cut ... */ 00171 TriangulationType triangulation_type_; 00172 00173 /** \brief Whether or not shadowed faces are stored, e.g., for exploration */ 00174 bool store_shadowed_faces_; 00175 00176 /** \brief (Cosine of the) angle tolerance used when checking whether or not an edge between two points is shadowed. */ 00177 float cos_angle_tolerance_; 00178 00179 /** \brief Perform the actual polygonal reconstruction. 00180 * \param[out] polygons the resultant polygons 00181 */ 00182 void 00183 reconstructPolygons (std::vector<pcl::Vertices>& polygons); 00184 00185 /** \brief Create the surface. 00186 * \param[out] polygons the resultant polygons, as a set of vertices. The Vertices structure contains an array of point indices. 00187 */ 00188 virtual void 00189 performReconstruction (std::vector<pcl::Vertices> &polygons); 00190 00191 /** \brief Create the surface. 00192 * 00193 * Simply uses image indices to create an initial polygonal mesh for organized point clouds. 00194 * \a indices_ are ignored! 00195 * 00196 * \param[out] output the resultant polygonal mesh 00197 */ 00198 void 00199 performReconstruction (pcl::PolygonMesh &output); 00200 00201 /** \brief Add a new triangle to the current polygon mesh 00202 * \param[in] a index of the first vertex 00203 * \param[in] b index of the second vertex 00204 * \param[in] c index of the third vertex 00205 * \param[in] idx the index in the set of polygon vertices (assumes \a idx is valid in \a polygons) 00206 * \param[out] polygons the polygon mesh to be updated 00207 */ 00208 inline void 00209 addTriangle (int a, int b, int c, int idx, std::vector<pcl::Vertices>& polygons) 00210 { 00211 assert (idx < static_cast<int> (polygons.size ())); 00212 polygons[idx].vertices.resize (3); 00213 polygons[idx].vertices[0] = a; 00214 polygons[idx].vertices[1] = b; 00215 polygons[idx].vertices[2] = c; 00216 } 00217 00218 /** \brief Add a new quad to the current polygon mesh 00219 * \param[in] a index of the first vertex 00220 * \param[in] b index of the second vertex 00221 * \param[in] c index of the third vertex 00222 * \param[in] d index of the fourth vertex 00223 * \param[in] idx the index in the set of polygon vertices (assumes \a idx is valid in \a polygons) 00224 * \param[out] polygons the polygon mesh to be updated 00225 */ 00226 inline void 00227 addQuad (int a, int b, int c, int d, int idx, std::vector<pcl::Vertices>& polygons) 00228 { 00229 assert (idx < static_cast<int> (polygons.size ())); 00230 polygons[idx].vertices.resize (4); 00231 polygons[idx].vertices[0] = a; 00232 polygons[idx].vertices[1] = b; 00233 polygons[idx].vertices[2] = c; 00234 polygons[idx].vertices[3] = d; 00235 } 00236 00237 /** \brief Set (all) coordinates of a particular point to the specified value 00238 * \param[in] point_index index of point 00239 * \param[out] mesh to modify 00240 * \param[in] value value to use when re-setting 00241 * \param[in] field_x_idx the X coordinate of the point 00242 * \param[in] field_y_idx the Y coordinate of the point 00243 * \param[in] field_z_idx the Z coordinate of the point 00244 */ 00245 inline void 00246 resetPointData (const int &point_index, pcl::PolygonMesh &mesh, const float &value = 0.0f, 00247 int field_x_idx = 0, int field_y_idx = 1, int field_z_idx = 2) 00248 { 00249 float new_value = value; 00250 memcpy (&mesh.cloud.data[point_index * mesh.cloud.point_step + mesh.cloud.fields[field_x_idx].offset], &new_value, sizeof (float)); 00251 memcpy (&mesh.cloud.data[point_index * mesh.cloud.point_step + mesh.cloud.fields[field_y_idx].offset], &new_value, sizeof (float)); 00252 memcpy (&mesh.cloud.data[point_index * mesh.cloud.point_step + mesh.cloud.fields[field_z_idx].offset], &new_value, sizeof (float)); 00253 } 00254 00255 /** \brief Check if a point is shadowed by another point 00256 * \param[in] point_a the first point 00257 * \param[in] point_b the second point 00258 */ 00259 inline bool 00260 isShadowed (const PointInT& point_a, const PointInT& point_b) 00261 { 00262 Eigen::Vector3f viewpoint = Eigen::Vector3f::Zero (); // TODO: allow for passing viewpoint information 00263 Eigen::Vector3f dir_a = viewpoint - point_a.getVector3fMap (); 00264 Eigen::Vector3f dir_b = point_b.getVector3fMap () - point_a.getVector3fMap (); 00265 float distance_to_points = dir_a.norm (); 00266 float distance_between_points = dir_b.norm (); 00267 float cos_angle = dir_a.dot (dir_b) / (distance_to_points*distance_between_points); 00268 if (cos_angle != cos_angle) 00269 cos_angle = 1.0f; 00270 return (fabs (cos_angle) >= cos_angle_tolerance_); 00271 // TODO: check for both: angle almost 0/180 _and_ distance between points larger than noise level 00272 } 00273 00274 /** \brief Check if a triangle is valid. 00275 * \param[in] a index of the first vertex 00276 * \param[in] b index of the second vertex 00277 * \param[in] c index of the third vertex 00278 */ 00279 inline bool 00280 isValidTriangle (const int& a, const int& b, const int& c) 00281 { 00282 if (!pcl::isFinite (input_->points[a])) return (false); 00283 if (!pcl::isFinite (input_->points[b])) return (false); 00284 if (!pcl::isFinite (input_->points[c])) return (false); 00285 return (true); 00286 } 00287 00288 /** \brief Check if a triangle is shadowed. 00289 * \param[in] a index of the first vertex 00290 * \param[in] b index of the second vertex 00291 * \param[in] c index of the third vertex 00292 */ 00293 inline bool 00294 isShadowedTriangle (const int& a, const int& b, const int& c) 00295 { 00296 if (isShadowed (input_->points[a], input_->points[b])) return (true); 00297 if (isShadowed (input_->points[b], input_->points[c])) return (true); 00298 if (isShadowed (input_->points[c], input_->points[a])) return (true); 00299 return (false); 00300 } 00301 00302 /** \brief Check if a quad is valid. 00303 * \param[in] a index of the first vertex 00304 * \param[in] b index of the second vertex 00305 * \param[in] c index of the third vertex 00306 * \param[in] d index of the fourth vertex 00307 */ 00308 inline bool 00309 isValidQuad (const int& a, const int& b, const int& c, const int& d) 00310 { 00311 if (!pcl::isFinite (input_->points[a])) return (false); 00312 if (!pcl::isFinite (input_->points[b])) return (false); 00313 if (!pcl::isFinite (input_->points[c])) return (false); 00314 if (!pcl::isFinite (input_->points[d])) return (false); 00315 return (true); 00316 } 00317 00318 /** \brief Check if a triangle is shadowed. 00319 * \param[in] a index of the first vertex 00320 * \param[in] b index of the second vertex 00321 * \param[in] c index of the third vertex 00322 * \param[in] d index of the fourth vertex 00323 */ 00324 inline bool 00325 isShadowedQuad (const int& a, const int& b, const int& c, const int& d) 00326 { 00327 if (isShadowed (input_->points[a], input_->points[b])) return (true); 00328 if (isShadowed (input_->points[b], input_->points[c])) return (true); 00329 if (isShadowed (input_->points[c], input_->points[d])) return (true); 00330 if (isShadowed (input_->points[d], input_->points[a])) return (true); 00331 return (false); 00332 } 00333 00334 /** \brief Create a quad mesh. 00335 * \param[out] polygons the resultant mesh 00336 */ 00337 void 00338 makeQuadMesh (std::vector<pcl::Vertices>& polygons); 00339 00340 /** \brief Create a right cut mesh. 00341 * \param[out] polygons the resultant mesh 00342 */ 00343 void 00344 makeRightCutMesh (std::vector<pcl::Vertices>& polygons); 00345 00346 /** \brief Create a left cut mesh. 00347 * \param[out] polygons the resultant mesh 00348 */ 00349 void 00350 makeLeftCutMesh (std::vector<pcl::Vertices>& polygons); 00351 00352 /** \brief Create an adaptive cut mesh. 00353 * \param[out] polygons the resultant mesh 00354 */ 00355 void 00356 makeAdaptiveCutMesh (std::vector<pcl::Vertices>& polygons); 00357 }; 00358 } 00359 00360 #ifdef PCL_NO_PRECOMPILE 00361 #include <pcl/surface/impl/organized_fast_mesh.hpp> 00362 #endif 00363 00364 #endif // PCL_SURFACE_ORGANIZED_FAST_MESH_H_
Except where otherwise noted, the PointClouds.org web pages are licensed under Creative Commons Attribution 3.0.
Pages generated on Wed Mar 25 00:26:15 2015