Point Cloud Library (PCL)
1.7.0
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2009-2012, Willow Garage, Inc. 00006 * Copyright (c) 2012-, Open Perception, 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 the copyright holder(s) 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_GEOMETRY_TRIANGLE_MESH_H 00042 #define PCL_GEOMETRY_TRIANGLE_MESH_H 00043 00044 #include <utility> 00045 00046 #include <pcl/geometry/mesh_base.h> 00047 00048 namespace pcl 00049 { 00050 namespace geometry 00051 { 00052 /** \brief Tag describing the type of the mesh. */ 00053 struct TriangleMeshTag {}; 00054 00055 /** \brief Half-edge mesh that can only store triangles. 00056 * \tparam MeshTraitsT Please have a look at pcl::geometry::DefaultMeshTraits. 00057 * \author Martin Saelzle 00058 * \ingroup geometry 00059 */ 00060 template <class MeshTraitsT> 00061 class TriangleMesh : public pcl::geometry::MeshBase <TriangleMesh <MeshTraitsT>, MeshTraitsT, TriangleMeshTag> 00062 { 00063 public: 00064 00065 typedef pcl::geometry::MeshBase <TriangleMesh <MeshTraitsT>, MeshTraitsT, TriangleMeshTag> Base; 00066 00067 typedef TriangleMesh <MeshTraitsT> Self; 00068 typedef boost::shared_ptr <Self> Ptr; 00069 typedef boost::shared_ptr <const Self> ConstPtr; 00070 00071 typedef typename Base::VertexData VertexData; 00072 typedef typename Base::HalfEdgeData HalfEdgeData; 00073 typedef typename Base::EdgeData EdgeData; 00074 typedef typename Base::FaceData FaceData; 00075 typedef typename Base::IsManifold IsManifold; 00076 typedef typename Base::MeshTag MeshTag; 00077 00078 typedef typename Base::HasVertexData HasVertexData; 00079 typedef typename Base::HasHalfEdgeData HasHalfEdgeData; 00080 typedef typename Base::HasEdgeData HasEdgeData; 00081 typedef typename Base::HasFaceData HasFaceData; 00082 00083 typedef typename Base::VertexDataCloud VertexDataCloud; 00084 typedef typename Base::HalfEdgeDataCloud HalfEdgeDataCloud; 00085 typedef typename Base::EdgeDataCloud EdgeDataCloud; 00086 typedef typename Base::FaceDataCloud FaceDataCloud; 00087 00088 // Indices 00089 typedef typename Base::VertexIndex VertexIndex; 00090 typedef typename Base::HalfEdgeIndex HalfEdgeIndex; 00091 typedef typename Base::EdgeIndex EdgeIndex; 00092 typedef typename Base::FaceIndex FaceIndex; 00093 typedef std::pair <FaceIndex, FaceIndex> FaceIndexPair; 00094 00095 typedef typename Base::VertexIndices VertexIndices; 00096 typedef typename Base::HalfEdgeIndices HalfEdgeIndices; 00097 typedef typename Base::EdgeIndices EdgeIndices; 00098 typedef typename Base::FaceIndices FaceIndices; 00099 00100 // Circulators 00101 typedef typename Base::VertexAroundVertexCirculator VertexAroundVertexCirculator; 00102 typedef typename Base::OutgoingHalfEdgeAroundVertexCirculator OutgoingHalfEdgeAroundVertexCirculator; 00103 typedef typename Base::IncomingHalfEdgeAroundVertexCirculator IncomingHalfEdgeAroundVertexCirculator; 00104 typedef typename Base::FaceAroundVertexCirculator FaceAroundVertexCirculator; 00105 typedef typename Base::VertexAroundFaceCirculator VertexAroundFaceCirculator; 00106 typedef typename Base::InnerHalfEdgeAroundFaceCirculator InnerHalfEdgeAroundFaceCirculator; 00107 typedef typename Base::OuterHalfEdgeAroundFaceCirculator OuterHalfEdgeAroundFaceCirculator; 00108 typedef typename Base::FaceAroundFaceCirculator FaceAroundFaceCirculator; 00109 00110 /** \brief Constructor. */ 00111 TriangleMesh () 00112 : Base (), 00113 add_triangle_ (3), 00114 inner_he_atp_ (4), 00115 is_new_atp_ (4) 00116 { 00117 } 00118 00119 /** \brief The base method of addFace is hidden because of the overloads in this class. */ 00120 using Base::addFace; 00121 00122 /** \brief Add a triangle to the mesh. Data is only added if it is associated with the elements. The last vertex is connected with the first one. 00123 * \param[in] idx_v_0 Index to the first vertex. 00124 * \param[in] idx_v_1 Index to the second vertex. 00125 * \param[in] idx_v_2 Index to the third vertex. 00126 * \param[in] face_data Data that is set for the face. 00127 * \param[in] half_edge_data Data that is set for all added half-edges. 00128 * \param[in] edge_data Data that is set for all added edges. 00129 * \return Index to the new face. Failure is signaled by returning an invalid face index. 00130 * \warning The vertices must be valid and unique (each vertex may be contained only once). Not complying with this requirement results in undefined behavior! 00131 */ 00132 inline FaceIndex 00133 addFace (const VertexIndex& idx_v_0, 00134 const VertexIndex& idx_v_1, 00135 const VertexIndex& idx_v_2, 00136 const FaceData& face_data = FaceData (), 00137 const EdgeData& edge_data = EdgeData (), 00138 const HalfEdgeData& half_edge_data = HalfEdgeData ()) 00139 { 00140 add_triangle_ [0] = idx_v_0; 00141 add_triangle_ [1] = idx_v_1; 00142 add_triangle_ [2] = idx_v_2; 00143 00144 return (this->addFaceImplBase (add_triangle_, face_data, edge_data, half_edge_data)); 00145 } 00146 00147 /** \brief Add two triangles for the four given input vertices. When using a manifold triangle mesh it is not possible to connect two bounded regions without going through a non-manifold intermediate step. This method first tries to add the triangles individually and if this fails connects the whole configuration at once (if possible). 00148 * \param[in] vertices Indices to the vertices of the new face. (The size must be equal to four). 00149 * \param[in] face_data Data that is set for the face. 00150 * \param[in] half_edge_data Data that is set for all added half-edges. 00151 * \param[in] edge_data Data that is set for all added edges. 00152 * \return Pair of face indices. The first index is valid if one triangle was added. Both indices are valid if two triangles were added. 00153 * \warning The vertices must be valid and unique (each vertex may be contained only once). Not complying with this requirement results in undefined behavior! 00154 */ 00155 FaceIndexPair 00156 addTrianglePair (const VertexIndices& vertices, 00157 const FaceData& face_data = FaceData (), 00158 const EdgeData& edge_data = EdgeData (), 00159 const HalfEdgeData& half_edge_data = HalfEdgeData ()) 00160 { 00161 if (vertices.size () != 4) 00162 { 00163 return (std::make_pair (FaceIndex (), FaceIndex ())); 00164 } 00165 else 00166 { 00167 return (this->addTrianglePair (vertices [0], vertices [1], vertices [2], vertices [3], face_data, edge_data, half_edge_data)); 00168 } 00169 } 00170 00171 /** \brief Add two triangles for the four given input vertices. When using a manifold triangle mesh it is not possible to connect two bounded regions without going through a non-manifold intermediate step. This method first tries to add the triangles individually and if this fails connects the whole configuration at once (if possible). 00172 * \param[in] idx_v_0 Index to the first vertex. 00173 * \param[in] idx_v_1 Index to the second vertex. 00174 * \param[in] idx_v_2 Index to the third vertex. 00175 * \param[in] idx_v_3 Index to the fourth vertex. 00176 * \param[in] face_data Data that is set for the face. 00177 * \param[in] half_edge_data Data that is set for all added half-edges. 00178 * \param[in] edge_data Data that is set for all added edges. 00179 * \return Pair of face indices. The first index is valid if one triangle was added. Both indices are valid if two triangles were added. 00180 * \warning The vertices must be valid and unique (each vertex may be contained only once). Not complying with this requirement results in undefined behavior! 00181 */ 00182 inline FaceIndexPair 00183 addTrianglePair (const VertexIndex& idx_v_0, 00184 const VertexIndex& idx_v_1, 00185 const VertexIndex& idx_v_2, 00186 const VertexIndex& idx_v_3, 00187 const FaceData& face_data = FaceData (), 00188 const EdgeData& edge_data = EdgeData (), 00189 const HalfEdgeData& half_edge_data = HalfEdgeData ()) 00190 { 00191 // Try to add two faces 00192 // 3 - 2 00193 // | / | 00194 // 0 - 1 00195 FaceIndex idx_face_0 = this->addFace (idx_v_0, idx_v_1, idx_v_2, face_data); 00196 FaceIndex idx_face_1 = this->addFace (idx_v_0, idx_v_2, idx_v_3, face_data); 00197 00198 if (idx_face_0.isValid ()) 00199 { 00200 return (std::make_pair (idx_face_0, idx_face_1)); 00201 } 00202 else if (idx_face_1.isValid ()) 00203 { 00204 idx_face_0 = this->addFace (idx_v_0, idx_v_1, idx_v_2, face_data); // might be possible to add now 00205 return (std::make_pair (idx_face_1, idx_face_0)); 00206 } 00207 00208 // Try to add two faces 00209 // 3 - 2 00210 // | \ | 00211 // 0 - 1 00212 idx_face_0 = this->addFace (idx_v_1, idx_v_2, idx_v_3, face_data); 00213 idx_face_1 = this->addFace (idx_v_0, idx_v_1, idx_v_3, face_data); 00214 00215 if (idx_face_0.isValid ()) 00216 { 00217 return (std::make_pair (idx_face_0, idx_face_1)); 00218 } 00219 else if (idx_face_1.isValid ()) 00220 { 00221 idx_face_0 = this->addFace (idx_v_1, idx_v_2, idx_v_3, face_data); // might be possible to add now 00222 return (std::make_pair (idx_face_1, idx_face_0)); 00223 } 00224 00225 if (!IsManifold::value) 00226 { 00227 return (std::make_pair (FaceIndex (), FaceIndex ())); 00228 } 00229 00230 // Check manifoldness 00231 if (!Base::checkTopology1 (idx_v_0,idx_v_1, inner_he_atp_ [0], is_new_atp_ [0], IsManifold ()) || 00232 !Base::checkTopology1 (idx_v_1,idx_v_2, inner_he_atp_ [1], is_new_atp_ [1], IsManifold ()) || 00233 !Base::checkTopology1 (idx_v_2,idx_v_3, inner_he_atp_ [2], is_new_atp_ [2], IsManifold ()) || 00234 !Base::checkTopology1 (idx_v_3,idx_v_0, inner_he_atp_ [3], is_new_atp_ [3], IsManifold ())) 00235 { 00236 return (std::make_pair (FaceIndex (), FaceIndex ())); 00237 } 00238 00239 // Connect the triangle pair 00240 if (!is_new_atp_ [0] && is_new_atp_ [1] && !is_new_atp_ [2] && is_new_atp_ [3]) 00241 { 00242 return (this->connectTrianglePair (inner_he_atp_ [0], inner_he_atp_ [2], idx_v_0, idx_v_1, idx_v_2, idx_v_3, face_data, edge_data, half_edge_data)); 00243 } 00244 else if (is_new_atp_ [0] && !is_new_atp_ [1] && is_new_atp_ [2] && !is_new_atp_ [3]) 00245 { 00246 return (this->connectTrianglePair (inner_he_atp_ [1], inner_he_atp_ [3], idx_v_1, idx_v_2, idx_v_3, idx_v_0, face_data, edge_data, half_edge_data)); 00247 } 00248 else 00249 { 00250 return (std::make_pair (FaceIndex (), FaceIndex ())); 00251 } 00252 } 00253 00254 private: 00255 00256 // NOTE: Can't use the typedef of Base as a friend. 00257 friend class pcl::geometry::MeshBase <TriangleMesh <MeshTraitsT>, MeshTraitsT, pcl::geometry::TriangleMeshTag>; 00258 00259 /** \brief addFace for the triangular mesh. */ 00260 inline FaceIndex 00261 addFaceImpl (const VertexIndices& vertices, 00262 const FaceData& face_data, 00263 const EdgeData& edge_data, 00264 const HalfEdgeData& half_edge_data) 00265 { 00266 if (vertices.size () == 3) 00267 return (this->addFaceImplBase (vertices, face_data, edge_data, half_edge_data)); 00268 else 00269 return (FaceIndex ()); 00270 } 00271 00272 /** \brief Connect the triangles a-b-c and a-c-d. The edges a-b and c-d must be old and the edges b-c and d-a must be new. */ 00273 // d - c 00274 // | / | 00275 // a - b 00276 FaceIndexPair 00277 connectTrianglePair (const HalfEdgeIndex& idx_he_ab, 00278 const HalfEdgeIndex& idx_he_cd, 00279 const VertexIndex& idx_v_a, 00280 const VertexIndex& idx_v_b, 00281 const VertexIndex& idx_v_c, 00282 const VertexIndex& idx_v_d, 00283 const FaceData& face_data, 00284 const EdgeData& edge_data, 00285 const HalfEdgeData& he_data) 00286 { 00287 // Add new half-edges 00288 const HalfEdgeIndex idx_he_bc = Base::addEdge (idx_v_b, idx_v_c, he_data, edge_data); 00289 const HalfEdgeIndex idx_he_da = Base::addEdge (idx_v_d, idx_v_a, he_data, edge_data); 00290 const HalfEdgeIndex idx_he_ca = Base::addEdge (idx_v_c, idx_v_a, he_data, edge_data); 00291 00292 const HalfEdgeIndex idx_he_cb = Base::getOppositeHalfEdgeIndex (idx_he_bc); 00293 const HalfEdgeIndex idx_he_ad = Base::getOppositeHalfEdgeIndex (idx_he_da); 00294 const HalfEdgeIndex idx_he_ac = Base::getOppositeHalfEdgeIndex (idx_he_ca); 00295 00296 // Get the existing half-edges 00297 const HalfEdgeIndex idx_he_ab_prev = Base::getPrevHalfEdgeIndex (idx_he_ab); // No reference! 00298 const HalfEdgeIndex idx_he_ab_next = Base::getNextHalfEdgeIndex (idx_he_ab); // No reference! 00299 00300 const HalfEdgeIndex idx_he_cd_prev = Base::getPrevHalfEdgeIndex (idx_he_cd); // No reference! 00301 const HalfEdgeIndex idx_he_cd_next = Base::getNextHalfEdgeIndex (idx_he_cd); // No reference! 00302 00303 // Connect the outer half-edges 00304 Base::connectPrevNext (idx_he_ab_prev, idx_he_ad ); 00305 Base::connectPrevNext (idx_he_ad , idx_he_cd_next); 00306 Base::connectPrevNext (idx_he_cd_prev, idx_he_cb ); 00307 Base::connectPrevNext (idx_he_cb , idx_he_ab_next); 00308 00309 // Connect the inner half-edges 00310 Base::connectPrevNext (idx_he_ab, idx_he_bc); 00311 Base::connectPrevNext (idx_he_bc, idx_he_ca); 00312 Base::connectPrevNext (idx_he_ca, idx_he_ab); 00313 00314 Base::connectPrevNext (idx_he_ac, idx_he_cd); 00315 Base::connectPrevNext (idx_he_cd, idx_he_da); 00316 Base::connectPrevNext (idx_he_da, idx_he_ac); 00317 00318 // Connect the vertices to the boundary half-edges 00319 Base::setOutgoingHalfEdgeIndex (idx_v_a, idx_he_ad ); 00320 Base::setOutgoingHalfEdgeIndex (idx_v_b, idx_he_ab_next); 00321 Base::setOutgoingHalfEdgeIndex (idx_v_c, idx_he_cb ); 00322 Base::setOutgoingHalfEdgeIndex (idx_v_d, idx_he_cd_next); 00323 00324 // Add and connect the faces 00325 HalfEdgeIndices inner_he_abc; inner_he_abc.reserve (3); 00326 inner_he_abc.push_back (idx_he_ab); 00327 inner_he_abc.push_back (idx_he_bc); 00328 inner_he_abc.push_back (idx_he_ca); 00329 00330 HalfEdgeIndices inner_he_acd; inner_he_acd.reserve (3); 00331 inner_he_acd.push_back (idx_he_ac); 00332 inner_he_acd.push_back (idx_he_cd); 00333 inner_he_acd.push_back (idx_he_da); 00334 00335 const FaceIndex idx_f_abc = Base::connectFace (inner_he_abc, face_data); 00336 const FaceIndex idx_f_acd = Base::connectFace (inner_he_acd, face_data); 00337 00338 return (std::make_pair (idx_f_abc, idx_f_acd)); 00339 } 00340 00341 //////////////////////////////////////////////////////////////////////// 00342 // Members 00343 //////////////////////////////////////////////////////////////////////// 00344 00345 /** \brief Storage for adding a triangle. */ 00346 VertexIndices add_triangle_; 00347 00348 /** \brief Storage for addTrianglePair. */ 00349 HalfEdgeIndices inner_he_atp_; 00350 00351 /** \brief Storage for addTrianglePair. */ 00352 std::vector <bool> is_new_atp_; 00353 00354 public: 00355 00356 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 00357 }; 00358 } // End namespace geom 00359 } // End namespace pcl 00360 00361 #endif // PCL_GEOMETRY_TRIANGLE_MESH_H