test_mesh.cpp
Go to the documentation of this file.
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 #include <vector>
00042 
00043 #include <gtest/gtest.h>
00044 
00045 // Needed for one test. Must be defined before including the mesh.
00046 #define PCL_GEOMETRY_MESH_BASE_TEST_DELETE_FACE_MANIFOLD_2
00047 
00048 #include <pcl/geometry/triangle_mesh.h>
00049 
00050 #include "test_mesh_common_functions.h"
00051 
00053 
00054 typedef pcl::geometry::VertexIndex   VertexIndex;
00055 typedef pcl::geometry::HalfEdgeIndex HalfEdgeIndex;
00056 typedef pcl::geometry::EdgeIndex     EdgeIndex;
00057 typedef pcl::geometry::FaceIndex     FaceIndex;
00058 
00059 typedef std::vector <VertexIndex>   VertexIndices;
00060 typedef std::vector <HalfEdgeIndex> HalfEdgeIndices;
00061 typedef std::vector <FaceIndex>     FaceIndices;
00062 
00063 template <bool IsManifoldT>
00064 struct MeshTraits
00065 {
00066     typedef int                                          VertexData;
00067     typedef pcl::geometry::NoData                        HalfEdgeData;
00068     typedef pcl::geometry::NoData                        EdgeData;
00069     typedef pcl::geometry::NoData                        FaceData;
00070     typedef boost::integral_constant <bool, IsManifoldT> IsManifold;
00071 };
00072 
00073 typedef pcl::geometry::TriangleMesh <MeshTraits <true > > ManifoldTriangleMesh;
00074 typedef pcl::geometry::TriangleMesh <MeshTraits <false> > NonManifoldTriangleMesh;
00075 
00077 
00078 TEST (TestAddDeleteFace, NonManifold1)
00079 {
00080   // The triangle 0-1-2 is added last //
00081   //     5                            //
00082   //    / \                           //
00083   //   0 - 2                          //
00084   //  / \ / \                         //
00085   // 3 - 1 - 4                        //
00086   NonManifoldTriangleMesh mesh;
00087   for (unsigned int i=0; i<6; ++i) mesh.addVertex (i);
00088 
00089   typedef VertexIndex VI;
00090   VertexIndices vi;
00091   std::vector <VertexIndices> faces;
00092   vi.push_back (VI (0)); vi.push_back (VI (3)); vi.push_back (VI (1)); faces.push_back (vi); vi.clear (); // 0
00093   vi.push_back (VI (2)); vi.push_back (VI (1)); vi.push_back (VI (4)); faces.push_back (vi); vi.clear (); // 1
00094   vi.push_back (VI (0)); vi.push_back (VI (2)); vi.push_back (VI (5)); faces.push_back (vi); vi.clear (); // 2
00095   for (unsigned int i=0; i<faces.size (); ++i)
00096   {
00097     ASSERT_TRUE (mesh.addFace (faces [i]).isValid ());
00098   }
00099   EXPECT_TRUE (hasFaces (mesh, faces));
00100 
00101   // Check if the whole boundary is reached.
00102   VertexIndices boundary_expected;
00103   boundary_expected.push_back (VI (0));
00104   boundary_expected.push_back (VI (5));
00105   boundary_expected.push_back (VI (2));
00106   boundary_expected.push_back (VI (4));
00107   boundary_expected.push_back (VI (1));
00108   boundary_expected.push_back (VI (3));
00109 
00110   VertexIndices boundary_vertices = getBoundaryVertices (mesh, VI (3));
00111   EXPECT_EQ (boundary_expected, boundary_vertices);
00112 
00113   // Close the gaps.
00114   vi.push_back (VI (0)); vi.push_back (VI (1)); vi.push_back (VI (2)); faces.push_back (vi); vi.clear (); // 3
00115   ASSERT_TRUE (mesh.addFace (faces [3]).isValid ());
00116   EXPECT_TRUE (hasFaces (mesh, faces));
00117 
00118   // Delete faces
00119   mesh.deleteFace (FaceIndex (3));
00120   mesh.deleteFace (FaceIndex (1));
00121   mesh.cleanUp ();
00122 
00123   std::vector <std::vector <int> > expected_data;
00124   std::vector <int> data;
00125   data.push_back (0); data.push_back (3); data.push_back (1); expected_data.push_back (data); data.clear ();
00126   data.push_back (0); data.push_back (2); data.push_back (5); expected_data.push_back (data); data.clear ();
00127 
00128   std::vector <int> boundary_data_expected;
00129   boundary_data_expected.push_back (3);
00130   boundary_data_expected.push_back (0);
00131   boundary_data_expected.push_back (5);
00132   boundary_data_expected.push_back (2);
00133   boundary_data_expected.push_back (0);
00134   boundary_data_expected.push_back (1);
00135 
00136   ASSERT_TRUE (hasFaces (mesh, expected_data));
00137   ASSERT_EQ (boundary_data_expected, getBoundaryVertices (mesh, 1));
00138 }
00139 
00141 
00142 TEST (TestAddDeleteFace, NonManifold2)
00143 {
00144   NonManifoldTriangleMesh mesh;
00145   for (unsigned int i=0; i<9; ++i) mesh.addVertex (i);
00146   typedef VertexIndex VI;
00147   VertexIndices vi;
00148   std::vector <VertexIndices> faces;
00149 
00150   // 2 - 1 //
00151   //  \ /  //
00152   //   0   //
00153   //  / \  //
00154   // 3 - 4 //
00155   vi.push_back (VI (0)); vi.push_back (VI (1)); vi.push_back (VI (2)); faces.push_back (vi); vi.clear ();
00156   vi.push_back (VI (0)); vi.push_back (VI (3)); vi.push_back (VI (4)); faces.push_back (vi); vi.clear ();
00157   for (unsigned int i=0; i<faces.size (); ++i)
00158   {
00159     ASSERT_TRUE (mesh.addFace (faces [i]).isValid ());
00160   }
00161   EXPECT_TRUE (hasFaces (mesh, faces));
00162 
00163   // (*) Adding the next two faces would destroy the connectivity around vertex 0. E.g. a VertexAroundVertexCirculator would not be able to access all the vertices (1, 2, 3, 4) anymore.
00164   vi.push_back (VI (3)); vi.push_back (VI (0)); vi.push_back (VI (4));
00165   EXPECT_FALSE (mesh.addFace (vi).isValid ());
00166   vi.clear ();
00167 
00168   vi.push_back (VI (1)); vi.push_back (VI (0)); vi.push_back (VI (2));
00169   EXPECT_FALSE (mesh.addFace (vi).isValid ());
00170   vi.clear ();
00171 
00172   {
00173     // Check if the whole boundary is reached.
00174     VertexIndices boundary_expected;
00175     boundary_expected.push_back (VI (0));
00176     boundary_expected.push_back (VI (0));
00177     boundary_expected.push_back (VI (1));
00178     boundary_expected.push_back (VI (2));
00179     boundary_expected.push_back (VI (3));
00180     boundary_expected.push_back (VI (4));
00181 
00182     VertexIndices boundary_vertices = getBoundaryVertices (mesh, VI (2));
00183     std::sort (boundary_vertices.begin (), boundary_vertices.end ());
00184     EXPECT_EQ (boundary_expected, boundary_vertices);
00185   }
00186 
00187   // New config //
00188   //   2 - 1    //
00189   //    \ /     //
00190   // 3 - 0 - 6  //
00191   //  \ / \ /   //
00192   //   4   5    //
00193   vi.push_back (VI (0)); vi.push_back (VI (5)); vi.push_back (VI (6)); faces.push_back (vi); vi.clear ();
00194   EXPECT_TRUE (mesh.addFace (faces [2]).isValid ());
00195   EXPECT_TRUE (hasFaces (mesh, faces));
00196 
00197   // Same as (*)
00198   vi.push_back (VI (1)); vi.push_back (VI (0)); vi.push_back (VI (2));
00199   EXPECT_FALSE (mesh.addFace (vi).isValid ());
00200   vi.clear ();
00201 
00202   vi.push_back (VI (3)); vi.push_back (VI (0)); vi.push_back (VI (4));
00203   EXPECT_FALSE (mesh.addFace (vi).isValid ());
00204   vi.clear ();
00205 
00206   vi.push_back (VI (5)); vi.push_back (VI (0)); vi.push_back (VI (6));
00207   EXPECT_FALSE (mesh.addFace (vi).isValid ());
00208   vi.clear ();
00209 
00210   {
00211     // Check if the whole boundary is reached.
00212     VertexIndices boundary_expected;
00213     boundary_expected.push_back (VI (0));
00214     boundary_expected.push_back (VI (0));
00215     boundary_expected.push_back (VI (0));
00216     boundary_expected.push_back (VI (1));
00217     boundary_expected.push_back (VI (2));
00218     boundary_expected.push_back (VI (3));
00219     boundary_expected.push_back (VI (4));
00220     boundary_expected.push_back (VI (5));
00221     boundary_expected.push_back (VI (6));
00222 
00223     VertexIndices boundary_vertices = getBoundaryVertices (mesh, VI (2));
00224     std::sort (boundary_vertices.begin (), boundary_vertices.end ());
00225     EXPECT_EQ (boundary_expected, boundary_vertices);
00226   }
00227 
00228   // New config //
00229   // 2---1   8  //
00230   //  \  |  /|  //
00231   //   \ | / |  //
00232   //    \|/  |  //
00233   // 3---0---7  //
00234   // |  /|\     //
00235   // | / | \    //
00236   // |/  |  \   //
00237   // 4   5---6  //
00238   vi.push_back (VI (0)); vi.push_back (VI (7)); vi.push_back (VI (8)); faces.push_back (vi); vi.clear ();
00239   EXPECT_TRUE (mesh.addFace (faces [3]).isValid ());
00240   EXPECT_TRUE (hasFaces (mesh, faces));
00241 
00242   // Same as (*)
00243   vi.push_back (VI (1)); vi.push_back (VI (0)); vi.push_back (VI (2));
00244   EXPECT_FALSE (mesh.addFace (vi).isValid ());
00245   vi.clear ();
00246 
00247   vi.push_back (VI (3)); vi.push_back (VI (0)); vi.push_back (VI (4));
00248   EXPECT_FALSE (mesh.addFace (vi).isValid ());
00249   vi.clear ();
00250 
00251   vi.push_back (VI (5)); vi.push_back (VI (0)); vi.push_back (VI (6));
00252   EXPECT_FALSE (mesh.addFace (vi).isValid ());
00253   vi.clear ();
00254 
00255   vi.push_back (VI (7)); vi.push_back (VI (0)); vi.push_back (VI (8));
00256   EXPECT_FALSE (mesh.addFace (vi).isValid ());
00257   vi.clear ();
00258 
00259   // Check if the whole boundary is reached.
00260   {
00261     VertexIndices boundary_expected;
00262     boundary_expected.push_back (VI (0));
00263     boundary_expected.push_back (VI (0));
00264     boundary_expected.push_back (VI (0));
00265     boundary_expected.push_back (VI (0));
00266     boundary_expected.push_back (VI (1));
00267     boundary_expected.push_back (VI (2));
00268     boundary_expected.push_back (VI (3));
00269     boundary_expected.push_back (VI (4));
00270     boundary_expected.push_back (VI (5));
00271     boundary_expected.push_back (VI (6));
00272     boundary_expected.push_back (VI (7));
00273     boundary_expected.push_back (VI (8));
00274 
00275     VertexIndices boundary_vertices = getBoundaryVertices (mesh, VI (2));
00276     std::sort (boundary_vertices.begin (), boundary_vertices.end ());
00277     EXPECT_EQ (boundary_expected, boundary_vertices);
00278   }
00279 
00280   // Close the gaps //
00281   // 2---1---8      //
00282   // |\  |  /|      //
00283   // | \0|5/ |      //
00284   // | 6\|/3 |      //
00285   // 3---0---7      //
00286   // | 1/|\7 |      //
00287   // | /4|2\ |      //
00288   // |/  |  \|      //
00289   // 4---5---6      //
00290   vi.push_back (VI (0)); vi.push_back (VI (4)); vi.push_back (VI (5)); faces.push_back (vi); vi.clear ();
00291   vi.push_back (VI (0)); vi.push_back (VI (8)); vi.push_back (VI (1)); faces.push_back (vi); vi.clear ();
00292   vi.push_back (VI (0)); vi.push_back (VI (2)); vi.push_back (VI (3)); faces.push_back (vi); vi.clear ();
00293   vi.push_back (VI (0)); vi.push_back (VI (6)); vi.push_back (VI (7)); faces.push_back (vi); vi.clear ();
00294   for (unsigned int i=4; i<faces.size (); ++i)
00295   {
00296     EXPECT_TRUE (mesh.addFace (faces [i]).isValid ());
00297   }
00298   EXPECT_TRUE (hasFaces (mesh, faces));
00299 
00300   VertexIndices boundary_expected;
00301   for (unsigned int i=8; i>0; --i)
00302   {
00303     boundary_expected.push_back (VI (i));
00304   }
00305   VertexIndices boundary_vertices = getBoundaryVertices (mesh, VI (1));
00306   EXPECT_EQ (boundary_expected, boundary_vertices);
00307 
00308   // Copy vertex indices to data
00309   std::vector <std::vector <int> > expected (faces.size ());
00310   for (unsigned int i=0; i<faces.size (); ++i)
00311   {
00312     std::vector <int> tmp (faces [i].size ());
00313     for (unsigned int j=0; j<faces [i].size (); ++j)
00314     {
00315       tmp [j] = faces [i][j].get ();
00316     }
00317     expected [i] = tmp;
00318   }
00319 
00320   // Delete all faces
00321   while (expected.size ())
00322   {
00323     mesh.deleteFace (FaceIndex (0));
00324     mesh.cleanUp ();
00325     expected.erase (expected.begin ());
00326     ASSERT_TRUE (hasFaces (mesh, expected));
00327   }
00328 
00329   ASSERT_TRUE (mesh.empty ());
00330 }
00331 
00333 
00334 TEST (TestAddDeleteFace, Manifold1)
00335 {
00336   typedef ManifoldTriangleMesh Mesh;
00337   typedef VertexIndex          VI;
00338   Mesh mesh;
00339   for (unsigned int i=0; i<7; ++i) mesh.addVertex (i);
00340 
00341   //   2 - 1   //
00342   //  / \ / \  //
00343   // 3 - 0 - 6 //
00344   //  \ / \ /  //
00345   //   4 - 5   //
00346   std::vector <VertexIndices> faces;
00347   std::vector <std::vector <int> > expected;
00348   VertexIndices vi;
00349   vi.push_back (VI (0)); vi.push_back (VI (1)); vi.push_back (VI (2)); faces.push_back (vi); vi.clear ();
00350   vi.push_back (VI (0)); vi.push_back (VI (2)); vi.push_back (VI (3)); faces.push_back (vi); vi.clear ();
00351   vi.push_back (VI (0)); vi.push_back (VI (3)); vi.push_back (VI (4)); faces.push_back (vi); vi.clear ();
00352   vi.push_back (VI (0)); vi.push_back (VI (4)); vi.push_back (VI (5)); faces.push_back (vi); vi.clear ();
00353   vi.push_back (VI (0)); vi.push_back (VI (5)); vi.push_back (VI (6)); faces.push_back (vi); vi.clear ();
00354   vi.push_back (VI (0)); vi.push_back (VI (6)); vi.push_back (VI (1)); faces.push_back (vi); vi.clear ();
00355 
00356   for (unsigned int i=0; i<faces.size (); ++i)
00357   {
00358     std::vector <int> tmp (faces [i].size ());
00359     for (unsigned int j=0; j<faces [i].size (); ++j)
00360     {
00361       tmp [j] = faces [i][j].get ();
00362     }
00363     expected.push_back (tmp);
00364     ASSERT_TRUE (mesh.addFace (faces [i]).isValid ()) << "Face " << i;
00365   }
00366   ASSERT_TRUE (hasFaces (mesh, faces));
00367   ASSERT_TRUE (hasFaces (mesh, expected));
00368 
00369   mesh.deleteFace (FaceIndex (0)); // 012
00370   mesh.deleteFace (FaceIndex (3)); // 045 -> makes mesh non-manifold -> delete additional faces.
00371   mesh.cleanUp ();
00372 
00373   EXPECT_TRUE (mesh.isManifold ());
00374 
00375   // Only the faces 0-5-6 and 0-6-1 remain after deletion.
00376   // NOTE: It would be also valid if the faces 0-2-3 and 0-3-4 remain.
00377   ASSERT_TRUE (hasFaces (mesh, std::vector <std::vector <int> > (expected.begin ()+4, expected.end ())));
00378 
00379   //   9 - 10    //
00380   //  / \ / \    //
00381   // 8 - 2 - 1   //
00382   //  \ / \ / \  //
00383   //   3 - 0 - 6 //
00384   //  / \ / \ /  //
00385   // 7 - 4 - 5   //
00386   mesh.clear ();
00387   expected.clear ();
00388   for (unsigned int i=0; i<11; ++i) mesh.addVertex (i);
00389   vi.push_back (VI ( 3)); vi.push_back (VI (7)); vi.push_back (VI (4)); faces.push_back (vi); vi.clear ();
00390   vi.push_back (VI ( 3)); vi.push_back (VI (2)); vi.push_back (VI (8)); faces.push_back (vi); vi.clear ();
00391   vi.push_back (VI ( 8)); vi.push_back (VI (2)); vi.push_back (VI (9)); faces.push_back (vi); vi.clear ();
00392   vi.push_back (VI (10)); vi.push_back (VI (9)); vi.push_back (VI (2)); faces.push_back (vi); vi.clear ();
00393   vi.push_back (VI (10)); vi.push_back (VI (2)); vi.push_back (VI (1)); faces.push_back (vi); vi.clear ();
00394   for (unsigned int i=0; i<faces.size (); ++i)
00395   {
00396     ASSERT_TRUE (mesh.addFace (faces [i]).isValid ()) << "Face " << i;
00397   }
00398   ASSERT_TRUE (hasFaces (mesh, faces));
00399 
00400   mesh.deleteFace (FaceIndex (0)); // 0-1-2 -> deletes 10-2-1
00401   mesh.deleteFace (FaceIndex (3)); // 0-4-5 -> deletes  0-3-4, 3-7-4 and 0-2-3
00402   mesh.cleanUp ();
00403 
00404   std::vector <int> tmp;
00405   tmp.push_back ( 0); tmp.push_back (5); tmp.push_back (6); expected.push_back (tmp); tmp.clear ();
00406   tmp.push_back ( 0); tmp.push_back (6); tmp.push_back (1); expected.push_back (tmp); tmp.clear ();
00407   tmp.push_back ( 3); tmp.push_back (2); tmp.push_back (8); expected.push_back (tmp); tmp.clear ();
00408   tmp.push_back ( 8); tmp.push_back (2); tmp.push_back (9); expected.push_back (tmp); tmp.clear ();
00409   tmp.push_back (10); tmp.push_back (9); tmp.push_back (2); expected.push_back (tmp); tmp.clear ();
00410   EXPECT_TRUE (mesh.isManifold ());
00411   ASSERT_TRUE (hasFaces (mesh, expected));
00412 
00413   std::vector <int> expected_boundary;
00414   expected_boundary.push_back (6);
00415   expected_boundary.push_back (5);
00416   expected_boundary.push_back (0);
00417   expected_boundary.push_back (1);
00418   EXPECT_EQ (expected_boundary, getBoundaryVertices (mesh, 1));
00419 
00420   expected_boundary.clear ();
00421   expected_boundary.push_back ( 2);
00422   expected_boundary.push_back ( 3);
00423   expected_boundary.push_back ( 8);
00424   expected_boundary.push_back ( 9);
00425   expected_boundary.push_back (10);
00426   EXPECT_EQ (expected_boundary, getBoundaryVertices (mesh, 8));
00427 }
00428 
00430 
00431 #ifdef PCL_GEOMETRY_MESH_BASE_TEST_DELETE_FACE_MANIFOLD_2
00432 
00433 TEST (TestAddDeleteFace, Manifold2)
00434 {
00435   typedef ManifoldTriangleMesh Mesh;
00436   typedef VertexIndex          VI;
00437 
00438   //  1 ----- 3  //
00439   //  \ \   / /  //
00440   //   \  0  /   //
00441   //    \ | /    //
00442   //      2      //
00443   std::vector <VertexIndices> faces;
00444   VertexIndices vi;
00445   vi.push_back (VI (0)); vi.push_back (VI (1)); vi.push_back (VI (2)); faces.push_back (vi); vi.clear ();
00446   vi.push_back (VI (0)); vi.push_back (VI (2)); vi.push_back (VI (3)); faces.push_back (vi); vi.clear ();
00447   vi.push_back (VI (0)); vi.push_back (VI (3)); vi.push_back (VI (1)); faces.push_back (vi); vi.clear ();
00448 
00449   // Try all possible combinations of adding the faces and deleting a vertex.
00450   // NOTE: Some cases are redundant.
00451   std::vector <int>                p;
00452   std::vector <std::vector <int> > permutations;
00453 
00454   p.push_back (0); p.push_back (1); p.push_back (2); permutations.push_back (p); p.clear ();
00455   p.push_back (1); p.push_back (2); p.push_back (0); permutations.push_back (p); p.clear ();
00456   p.push_back (2); p.push_back (0); p.push_back (1); permutations.push_back (p); p.clear ();
00457 
00458   Mesh mesh_tmp;
00459   vi.clear ();
00460   for (int i=0; i<4; ++i)
00461   {
00462     vi.push_back (mesh_tmp.addVertex ());
00463   }
00464 
00465   for (size_t i=0; i<permutations.size (); ++i) // first face
00466   {
00467     for (size_t j=0; j<permutations.size (); ++j) // second face
00468     {
00469       for (size_t k=0; k<permutations.size (); ++k) // third face
00470       {
00471         for (VI l (0); l < VI (3); ++l) // deleted vertex
00472         {
00473           pcl::geometry::g_pcl_geometry_mesh_base_test_delete_face_manifold_2_success = true;
00474 
00475           std::stringstream errormsg;
00476           errormsg << "\n";
00477           errormsg << faces [0] [permutations [i][0]] << faces [0] [permutations [i][1]] << faces [0] [permutations [i][2]] << " ";
00478           errormsg << faces [1] [permutations [j][0]] << faces [1] [permutations [j][1]] << faces [1] [permutations [j][2]] << " ";
00479           errormsg << faces [2] [permutations [k][0]] << faces [2] [permutations [k][1]] << faces [2] [permutations [k][2]] << " ";
00480           errormsg << "v: " << l << "\n";
00481 
00482           Mesh mesh = mesh_tmp;
00483 
00484           mesh.addFace (faces [0] [permutations [i][0]], faces [0] [permutations [i][1]], faces [0] [permutations [i][2]]);
00485           mesh.addFace (faces [1] [permutations [j][0]], faces [1] [permutations [j][1]], faces [1] [permutations [j][2]]);
00486           mesh.addFace (faces [2] [permutations [k][0]], faces [2] [permutations [k][1]], faces [2] [permutations [k][2]]);
00487 
00488           mesh.deleteVertex (VI (l));
00489           ASSERT_TRUE (pcl::geometry::g_pcl_geometry_mesh_base_test_delete_face_manifold_2_success) << errormsg.str ();
00490         }
00491       }
00492     }
00493   }
00494 }
00495 #endif // PCL_GEOMETRY_MESH_BASE_TEST_DELETE_FACE_MANIFOLD_2
00496 
00498 
00499 TEST (TestDelete, VertexAndEdge)
00500 {
00501   typedef NonManifoldTriangleMesh Mesh;
00502   typedef VertexIndex             VI;
00503   Mesh mesh;
00504   for (unsigned int i=0; i<7; ++i) mesh.addVertex (i);
00505 
00506   //   2 - 1          2 - 1  //
00507   //  / \ / \        / \ /   //
00508   // 3 - 0 - 6  ->  3 - 0    //
00509   //  \ / \ /        \ / \   //
00510   //   4 - 5          4 - 5  //
00511   std::vector <VertexIndices> faces;
00512   std::vector <std::vector <int> > expected;
00513   VertexIndices vi;
00514   vi.push_back (VI (0)); vi.push_back (VI (1)); vi.push_back (VI (2)); faces.push_back (vi); vi.clear ();
00515   vi.push_back (VI (0)); vi.push_back (VI (2)); vi.push_back (VI (3)); faces.push_back (vi); vi.clear ();
00516   vi.push_back (VI (0)); vi.push_back (VI (3)); vi.push_back (VI (4)); faces.push_back (vi); vi.clear ();
00517   vi.push_back (VI (0)); vi.push_back (VI (4)); vi.push_back (VI (5)); faces.push_back (vi); vi.clear ();
00518   vi.push_back (VI (0)); vi.push_back (VI (5)); vi.push_back (VI (6)); faces.push_back (vi); vi.clear ();
00519   vi.push_back (VI (0)); vi.push_back (VI (6)); vi.push_back (VI (1)); faces.push_back (vi); vi.clear ();
00520 
00521   for (unsigned int i=0; i<faces.size (); ++i)
00522   {
00523     std::vector <int> tmp (faces [i].size ());
00524     for (unsigned int j=0; j<faces [i].size (); ++j)
00525     {
00526       tmp [j] = faces [i][j].get ();
00527     }
00528     expected.push_back (tmp);
00529     ASSERT_TRUE (mesh.addFace (faces [i]).isValid ()) << "Face " << i;
00530   }
00531   ASSERT_TRUE (hasFaces (mesh, faces));
00532   ASSERT_TRUE (hasFaces (mesh, expected));
00533 
00534   // Search edge 0-6
00535   Mesh::VertexAroundVertexCirculator       circ     = mesh.getVertexAroundVertexCirculator (VI (0));
00536   const Mesh::VertexAroundVertexCirculator circ_end = circ;
00537   HalfEdgeIndex idx_he_06;
00538   do
00539   {
00540     if (circ.getTargetIndex () == VI (6))
00541     {
00542       idx_he_06 = circ.getCurrentHalfEdgeIndex ();
00543       break;
00544     }
00545   } while (++circ != circ_end);
00546 
00547   // Delete
00548   Mesh mesh_deleted_vertex    = mesh;
00549   Mesh mesh_deleted_half_edge = mesh;
00550   Mesh mesh_deleted_edge      = mesh;
00551   expected.pop_back ();
00552   expected.pop_back ();
00553 
00554   mesh_deleted_vertex.deleteVertex (VI (6));
00555   mesh_deleted_vertex.cleanUp ();
00556 
00557   mesh_deleted_half_edge.deleteEdge (idx_he_06);
00558   mesh_deleted_half_edge.cleanUp ();
00559 
00560   mesh_deleted_edge.deleteEdge (pcl::geometry::toEdgeIndex (idx_he_06));
00561   mesh_deleted_edge.cleanUp ();
00562 
00563   EXPECT_TRUE (hasFaces (mesh_deleted_vertex,    expected));
00564   EXPECT_TRUE (hasFaces (mesh_deleted_half_edge, expected));
00565   EXPECT_TRUE (hasFaces (mesh_deleted_edge,      expected));
00566 }
00567 
00569 
00570 TEST (TestMesh, IsBoundaryIsManifold)
00571 {
00572   // The triangle 0-1-2 is added last //
00573   //     5                            //
00574   //    / \                           //
00575   //   0 - 2                          //
00576   //  / \ / \                         //
00577   // 3 - 1 - 4                        //
00578   NonManifoldTriangleMesh mesh;
00579   for (unsigned int i=0; i<6; ++i) mesh.addVertex (i);
00580 
00581   typedef VertexIndex VI;
00582   VertexIndices vi;
00583   std::vector <VertexIndices> faces;
00584   vi.push_back (VI (0)); vi.push_back (VI (3)); vi.push_back (VI (1)); faces.push_back (vi); vi.clear (); // 0
00585   vi.push_back (VI (2)); vi.push_back (VI (1)); vi.push_back (VI (4)); faces.push_back (vi); vi.clear (); // 1
00586   vi.push_back (VI (0)); vi.push_back (VI (2)); vi.push_back (VI (5)); faces.push_back (vi); vi.clear (); // 2
00587   for (unsigned int i=0; i<faces.size (); ++i)
00588   {
00589     ASSERT_TRUE (mesh.addFace (faces [i]).isValid ());
00590   }
00591   EXPECT_TRUE (hasFaces (mesh, faces));
00592 
00593   // Check if the whole boundary is reached.
00594   VertexIndices boundary_expected;
00595   boundary_expected.push_back (VI (0));
00596   boundary_expected.push_back (VI (5));
00597   boundary_expected.push_back (VI (2));
00598   boundary_expected.push_back (VI (4));
00599   boundary_expected.push_back (VI (1));
00600   boundary_expected.push_back (VI (3));
00601 
00602   VertexIndices boundary_vertices = getBoundaryVertices (mesh, VI (3));
00603   EXPECT_EQ (boundary_expected, boundary_vertices);
00604   EXPECT_FALSE (mesh.isManifold (VI (0)));
00605   EXPECT_FALSE (mesh.isManifold (VI (1)));
00606   EXPECT_FALSE (mesh.isManifold (VI (2)));
00607   EXPECT_TRUE  (mesh.isManifold (VI (3)));
00608   EXPECT_TRUE  (mesh.isManifold (VI (4)));
00609   EXPECT_TRUE  (mesh.isManifold (VI (5)));
00610   ASSERT_FALSE (mesh.isManifold ());
00611 
00612   for (unsigned int i=0; i<mesh.sizeEdges (); ++i)
00613   {
00614     ASSERT_TRUE (mesh.isBoundary (EdgeIndex (i)));
00615   }
00616 
00617   // Make manifold
00618   vi.push_back (VI (0)); vi.push_back (VI (1)); vi.push_back (VI (2)); faces.push_back (vi); vi.clear (); // 3
00619   ASSERT_TRUE  (mesh.addFace (faces [3]).isValid ());
00620   EXPECT_TRUE  (hasFaces (mesh, faces));
00621 
00622   EXPECT_TRUE  (mesh.isManifold ());
00623   EXPECT_TRUE  (mesh.isBoundary (FaceIndex (3)));         // This version checks the vertices
00624   EXPECT_FALSE (mesh.isBoundary <false> (FaceIndex (3))); // This version checks the edges
00625 
00626   const HalfEdgeIndex idx_he_01 = findHalfEdge (mesh, VI (0), VI (1));
00627   const HalfEdgeIndex idx_he_12 = findHalfEdge (mesh, VI (1), VI (2));
00628   const HalfEdgeIndex idx_he_20 = findHalfEdge (mesh, VI (2), VI (0));
00629 
00630   ASSERT_TRUE (idx_he_01.isValid ());
00631   ASSERT_TRUE (idx_he_12.isValid ());
00632   ASSERT_TRUE (idx_he_20.isValid ());
00633 
00634   EXPECT_FALSE (mesh.isBoundary (pcl::geometry::toEdgeIndex (idx_he_01)));
00635   EXPECT_FALSE (mesh.isBoundary (pcl::geometry::toEdgeIndex (idx_he_12)));
00636   EXPECT_FALSE (mesh.isBoundary (pcl::geometry::toEdgeIndex (idx_he_20)));
00637 
00638   // Isolated vertex
00639   mesh.addVertex (6);
00640   ASSERT_TRUE (mesh.isManifold (VI (6)));
00641   ASSERT_TRUE (mesh.isBoundary (VI (6)));
00642 }
00643 
00645 
00646 int
00647 main (int argc, char** argv)
00648 {
00649   testing::InitGoogleTest (&argc, argv);
00650   return (RUN_ALL_TESTS ());
00651 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:35:08