41 #ifndef PCL_GEOMETRY_MESH_BASE_H
42 #define PCL_GEOMETRY_MESH_BASE_H
46 #include <pcl/geometry/boost.h>
47 #include <pcl/geometry/eigen.h>
48 #include <pcl/geometry/mesh_circulators.h>
49 #include <pcl/geometry/mesh_indices.h>
50 #include <pcl/geometry/mesh_elements.h>
51 #include <pcl/geometry/mesh_traits.h>
52 #include <pcl/point_cloud.h>
58 #ifdef PCL_GEOMETRY_MESH_BASE_TEST_DELETE_FACE_MANIFOLD_2
63 bool g_pcl_geometry_mesh_base_test_delete_face_manifold_2_success;
76 template <
class MeshT>
97 template <
class DerivedT,
class MeshTraitsT,
class MeshTagT>
103 typedef boost::shared_ptr <Self>
Ptr;
121 typedef boost::integral_constant <bool, !boost::is_same <VertexData , pcl::geometry::NoData>::value>
HasVertexData;
122 typedef boost::integral_constant <bool, !boost::is_same <HalfEdgeData, pcl::geometry::NoData>::value>
HasHalfEdgeData;
123 typedef boost::integral_constant <bool, !boost::is_same <EdgeData , pcl::geometry::NoData>::value>
HasEdgeData;
124 typedef boost::integral_constant <bool, !boost::is_same <FaceData , pcl::geometry::NoData>::value>
HasFaceData;
154 : vertex_data_cloud_ (),
155 half_edge_data_cloud_ (),
166 delete_faces_vertex_ (),
167 delete_faces_face_ ()
182 vertices_.push_back (
Vertex ());
183 this->
addData (vertex_data_cloud_, vertex_data, HasVertexData ());
184 return (VertexIndex (static_cast <int> (this->
sizeVertices () - 1)));
197 const FaceData& face_data = FaceData (),
198 const EdgeData& edge_data = EdgeData (),
199 const HalfEdgeData& half_edge_data = HalfEdgeData ())
202 return (static_cast <Derived*> (
this)->addFaceImpl (vertices, face_data, edge_data, half_edge_data));
211 assert (this->
isValid (idx_vertex));
212 if (this->
isDeleted (idx_vertex))
return;
214 delete_faces_vertex_.clear ();
216 const FaceAroundVertexCirculator circ_end = circ;
223 }
while (++circ!=circ_end);
225 for (FaceIndices::const_iterator it = delete_faces_vertex_.begin (); it!=delete_faces_vertex_.end (); ++it)
237 assert (this->
isValid (idx_he));
254 assert (this->
isValid (idx_edge));
265 assert (this->
isValid (idx_face));
278 const VertexIndices new_vertex_indices =
279 this->remove <Vertices, VertexDataCloud, VertexIndices, HasVertexData>
280 (vertices_, vertex_data_cloud_);
281 const HalfEdgeIndices new_half_edge_indices =
282 this->remove <HalfEdges, HalfEdgeDataCloud, HalfEdgeIndices, HasHalfEdgeData>
283 (half_edges_, half_edge_data_cloud_);
284 const FaceIndices new_face_indices =
285 this->remove <Faces, FaceDataCloud, FaceIndices, HasFaceData>
286 (faces_, face_data_cloud_);
289 if (HasEdgeData::value)
294 HalfEdgeIndices::const_iterator it_ind = new_half_edge_indices.begin ();
295 HalfEdgeIndices::const_iterator it_ind_end = new_half_edge_indices.end ();
297 for (; it_ind!=it_ind_end; it_ind+=2, ++it_ed_old)
299 if (it_ind->isValid ())
301 *it_ed_new++ = *it_ed_old;
308 for (
VertexIterator it = vertices_.begin (); it!=vertices_.end (); ++it)
310 if (it->idx_outgoing_half_edge_.isValid ())
312 it->idx_outgoing_half_edge_ = new_half_edge_indices [it->idx_outgoing_half_edge_.get ()];
316 for (
HalfEdgeIterator it = half_edges_.begin (); it!=half_edges_.end (); ++it)
318 it->idx_terminating_vertex_ = new_vertex_indices [it->idx_terminating_vertex_.get ()];
319 it->idx_next_half_edge_ = new_half_edge_indices [it->idx_next_half_edge_.get ()];
320 it->idx_prev_half_edge_ = new_half_edge_indices [it->idx_prev_half_edge_.get ()];
321 if (it->idx_face_.isValid ())
323 it->idx_face_ = new_face_indices [it->idx_face_.get ()];
327 for (
FaceIterator it = faces_.begin (); it!=faces_.end (); ++it)
329 it->idx_inner_half_edge_ = new_half_edge_indices [it->idx_inner_half_edge_.get ()];
341 assert (this->
isValid (idx_vertex));
342 return (this->
getVertex (idx_vertex).idx_outgoing_half_edge_);
349 assert (this->
isValid (idx_vertex));
361 assert (this->
isValid (idx_half_edge));
362 return (this->
getHalfEdge (idx_half_edge).idx_terminating_vertex_);
369 assert (this->
isValid (idx_half_edge));
377 assert (this->
isValid (idx_half_edge));
379 return (HalfEdgeIndex (idx_half_edge.
get () & 1 ? idx_half_edge.
get () - 1 : idx_half_edge.
get () + 1));
386 assert (this->
isValid (idx_half_edge));
387 return (this->
getHalfEdge (idx_half_edge).idx_next_half_edge_);
394 assert (this->
isValid (idx_half_edge));
395 return (this->
getHalfEdge (idx_half_edge).idx_prev_half_edge_);
402 assert (this->
isValid (idx_half_edge));
403 return (this->
getHalfEdge (idx_half_edge).idx_face_);
410 assert (this->
isValid (idx_half_edge));
422 assert (this->
isValid (idx_face));
423 return (this->
getFace (idx_face).idx_inner_half_edge_);
430 assert (this->
isValid (idx_face));
439 inline VertexAroundVertexCirculator
442 assert (this->
isValid (idx_vertex));
443 return (VertexAroundVertexCirculator (idx_vertex,
this));
447 inline VertexAroundVertexCirculator
450 assert (this->
isValid (idx_outgoing_half_edge));
451 return (VertexAroundVertexCirculator (idx_outgoing_half_edge,
this));
455 inline OutgoingHalfEdgeAroundVertexCirculator
458 assert (this->
isValid (idx_vertex));
459 return (OutgoingHalfEdgeAroundVertexCirculator (idx_vertex,
this));
463 inline OutgoingHalfEdgeAroundVertexCirculator
466 assert (this->
isValid (idx_outgoing_half_edge));
467 return (OutgoingHalfEdgeAroundVertexCirculator (idx_outgoing_half_edge,
this));
471 inline IncomingHalfEdgeAroundVertexCirculator
474 assert (this->
isValid (idx_vertex));
475 return (IncomingHalfEdgeAroundVertexCirculator (idx_vertex,
this));
479 inline IncomingHalfEdgeAroundVertexCirculator
482 assert (this->
isValid (idx_incoming_half_edge));
483 return (IncomingHalfEdgeAroundVertexCirculator (idx_incoming_half_edge,
this));
487 inline FaceAroundVertexCirculator
490 assert (this->
isValid (idx_vertex));
491 return (FaceAroundVertexCirculator (idx_vertex,
this));
495 inline FaceAroundVertexCirculator
498 assert (this->
isValid (idx_outgoing_half_edge));
499 return (FaceAroundVertexCirculator (idx_outgoing_half_edge,
this));
503 inline VertexAroundFaceCirculator
506 assert (this->
isValid (idx_face));
507 return (VertexAroundFaceCirculator (idx_face,
this));
511 inline VertexAroundFaceCirculator
514 assert (this->
isValid (idx_inner_half_edge));
515 return (VertexAroundFaceCirculator (idx_inner_half_edge,
this));
519 inline InnerHalfEdgeAroundFaceCirculator
522 assert (this->
isValid (idx_face));
523 return (InnerHalfEdgeAroundFaceCirculator (idx_face,
this));
527 inline InnerHalfEdgeAroundFaceCirculator
530 assert (this->
isValid (idx_inner_half_edge));
531 return (InnerHalfEdgeAroundFaceCirculator (idx_inner_half_edge,
this));
535 inline OuterHalfEdgeAroundFaceCirculator
538 assert (this->
isValid (idx_face));
539 return (OuterHalfEdgeAroundFaceCirculator (idx_face,
this));
543 inline OuterHalfEdgeAroundFaceCirculator
546 assert (this->
isValid (idx_inner_half_edge));
547 return (OuterHalfEdgeAroundFaceCirculator (idx_inner_half_edge,
this));
551 inline FaceAroundFaceCirculator
554 assert (this->
isValid (idx_face));
555 return (FaceAroundFaceCirculator (idx_face,
this));
559 inline FaceAroundFaceCirculator
562 assert (this->
isValid (idx_inner_half_edge));
563 return (FaceAroundFaceCirculator (idx_inner_half_edge,
this));
599 for (
unsigned int i=0; i<this->
sizeFaces (); ++i)
616 return (idx_vertex >= VertexIndex (0) && idx_vertex < VertexIndex (
int (vertices_.size ())));
623 return (idx_he >= HalfEdgeIndex (0) && idx_he < HalfEdgeIndex (half_edges_.size ()));
630 return (idx_edge >= EdgeIndex (0) && idx_edge < EdgeIndex (half_edges_.size () / 2));
637 return (idx_face >= FaceIndex (0) && idx_face < FaceIndex (faces_.size ()));
648 assert (this->
isValid (idx_vertex));
656 assert (this->
isValid (idx_he));
664 assert (this->
isValid (idx_edge));
673 assert (this->
isValid (idx_face));
685 assert (this->
isValid (idx_vertex));
697 assert (this->
isValid (idx_vertex));
698 if (this->
isIsolated (idx_vertex))
return (
true);
706 assert (this->
isValid (idx_he));
714 assert (this->
isValid (idx_edge));
722 template <
bool CheckVerticesT>
inline bool
725 assert (this->
isValid (idx_face));
726 return (this->
isBoundary (idx_face, boost::integral_constant <bool, CheckVerticesT> ()));
733 assert (this->
isValid (idx_face));
734 return (this->
isBoundary (idx_face, boost::true_type ()));
745 assert (this->
isValid (idx_vertex));
746 if (this->
isIsolated (idx_vertex))
return (
true);
747 return (this->
isManifold (idx_vertex, IsManifold ()));
765 return (vertices_.size ());
772 assert (half_edges_.size () % 2 == 0);
773 return (half_edges_.size ());
780 assert (half_edges_.size () % 2 == 0);
781 return (half_edges_.size () / 2);
788 return (faces_.size ());
806 return (vertices_.empty ());
813 return (half_edges_.empty ());
820 return (faces_.empty ());
831 vertices_.reserve (n);
832 this->
reserveData (vertex_data_cloud_, n, HasVertexData ());
839 half_edges_.reserve (2*n);
840 this->
reserveData (half_edge_data_cloud_, 2*n, HasHalfEdgeData ());
841 this->
reserveData (edge_data_cloud_ , n, HasEdgeData ());
849 this->
reserveData (face_data_cloud_, n, HasFaceData ());
860 vertices_.resize (n);
861 this->
resizeData (vertex_data_cloud_, n, data, HasVertexData ());
867 const EdgeData& edge_data = EdgeData (),
868 const HalfEdgeData he_data = HalfEdgeData ())
870 half_edges_.resize (2*n);
871 this->
resizeData (half_edge_data_cloud_, 2*n, he_data , HasHalfEdgeData ());
872 this->
resizeData (edge_data_cloud_ , n, edge_data, HasEdgeData ());
880 this->
resizeData (face_data_cloud_, n, data, HasFaceData ());
892 half_edges_.clear ();
895 this->
clearData (vertex_data_cloud_ , HasVertexData ());
896 this->
clearData (half_edge_data_cloud_, HasHalfEdgeData ());
897 this->
clearData (edge_data_cloud_ , HasEdgeData ());
898 this->
clearData (face_data_cloud_ , HasFaceData ());
908 inline VertexDataCloud&
911 return (vertex_data_cloud_);
915 inline VertexDataCloud
918 return (vertex_data_cloud_);
928 if (vertex_data_cloud.
size () == vertex_data_cloud_.
size ())
930 vertex_data_cloud_ = vertex_data_cloud;
946 inline HalfEdgeDataCloud&
949 return (half_edge_data_cloud_);
953 inline HalfEdgeDataCloud
956 return (half_edge_data_cloud_);
966 if (half_edge_data_cloud.
size () == half_edge_data_cloud_.
size ())
968 half_edge_data_cloud_ = half_edge_data_cloud;
984 inline EdgeDataCloud&
987 return (edge_data_cloud_);
994 return (edge_data_cloud_);
1004 if (edge_data_cloud.
size () == edge_data_cloud_.
size ())
1006 edge_data_cloud_ = edge_data_cloud;
1022 inline FaceDataCloud&
1025 return (face_data_cloud_);
1029 inline FaceDataCloud
1032 return (face_data_cloud_);
1042 if (face_data_cloud.
size () == face_data_cloud_.
size ())
1044 face_data_cloud_ = face_data_cloud;
1063 if (HasVertexData::value)
1065 assert (&vertex_data >= &vertex_data_cloud_.
front () && &vertex_data <= &vertex_data_cloud_.
back ());
1066 return (VertexIndex (std::distance (&vertex_data_cloud_.
front (), &vertex_data)));
1070 return (VertexIndex ());
1075 inline HalfEdgeIndex
1078 if (HasHalfEdgeData::value)
1080 assert (&half_edge_data >= &half_edge_data_cloud_.
front () && &half_edge_data <= &half_edge_data_cloud_.
back ());
1081 return (HalfEdgeIndex (std::distance (&half_edge_data_cloud_.
front (), &half_edge_data)));
1085 return (HalfEdgeIndex ());
1093 if (HasEdgeData::value)
1095 assert (&edge_data >= &edge_data_cloud_.
front () && &edge_data <= &edge_data_cloud_.
back ());
1096 return (EdgeIndex (std::distance (&edge_data_cloud_.
front (), &edge_data)));
1100 return (EdgeIndex ());
1108 if (HasFaceData::value)
1110 assert (&face_data >= &face_data_cloud_.
front () && &face_data <= &face_data_cloud_.
back ());
1111 return (FaceIndex (std::distance (&face_data_cloud_.
front (), &face_data)));
1115 return (FaceIndex ());
1145 const FaceData& face_data,
1146 const EdgeData& edge_data,
1147 const HalfEdgeData& half_edge_data)
1149 const int n =
static_cast<int> (vertices.size ());
1150 if (n < 3)
return (FaceIndex ());
1153 inner_he_.resize (n);
1154 free_he_.resize (n);
1156 make_adjacent_.resize (n);
1160 if (!this->
checkTopology1 (vertices [i], vertices [(i+1)%n], inner_he_ [i], is_new_ [i], IsManifold ()))
1162 return (FaceIndex ());
1168 if (!this->
checkTopology2 (inner_he_ [i], inner_he_ [j], is_new_ [i], is_new_ [j], this->
isIsolated (vertices [j]), make_adjacent_ [i], free_he_ [i], IsManifold ()))
1170 return (FaceIndex ());
1175 if (!IsManifold::value)
1179 if (make_adjacent_ [i])
1181 this->
makeAdjacent (inner_he_ [i], inner_he_ [(i+1)%n], free_he_ [i]);
1191 inner_he_ [i] = this->
addEdge (vertices [i], vertices [(i+1)%n], half_edge_data, edge_data);
1199 if ( is_new_ [i] && is_new_ [j]) this->
connectNewNew (inner_he_ [i], inner_he_ [j], vertices [j], IsManifold ());
1200 else if ( is_new_ [i] && !is_new_ [j]) this->
connectNewOld (inner_he_ [i], inner_he_ [j], vertices [j]);
1201 else if (!is_new_ [i] && is_new_ [j]) this->
connectOldNew (inner_he_ [i], inner_he_ [j], vertices [j]);
1202 else this->
connectOldOld (inner_he_ [i], inner_he_ [j], vertices [j], IsManifold ());
1204 return (this->
connectFace (inner_he_, face_data));
1220 const VertexIndex& idx_v_b,
1221 const HalfEdgeData& he_data,
1222 const EdgeData& edge_data)
1224 half_edges_.push_back (HalfEdge (idx_v_b));
1225 half_edges_.push_back (HalfEdge (idx_v_a));
1227 this->
addData (half_edge_data_cloud_, he_data , HasHalfEdgeData ());
1228 this->
addData (half_edge_data_cloud_, he_data , HasHalfEdgeData ());
1229 this->
addData (edge_data_cloud_ , edge_data, HasEdgeData ());
1231 return (HalfEdgeIndex (static_cast <int> (half_edges_.size () - 2)));
1247 const VertexIndex& idx_v_b,
1248 HalfEdgeIndex& idx_he_ab,
1249 std::vector <bool>::reference is_new_ab,
1250 boost::true_type )
const
1253 if (this->
isIsolated (idx_v_a))
return (
true);
1257 if (!this->
isBoundary (idx_he_ab))
return (
false);
1265 const VertexIndex& idx_v_b,
1266 HalfEdgeIndex& idx_he_ab,
1267 std::vector <bool>::reference is_new_ab,
1268 boost::false_type )
const
1271 if (this->
isIsolated (idx_v_a))
return (
true);
1275 const VertexAroundVertexCirculator circ_end = circ;
1282 if (!this->
isBoundary (idx_he_ab))
return (
false);
1287 }
while (++circ!=circ_end);
1295 const HalfEdgeIndex& ,
1296 const bool is_new_ab,
1297 const bool is_new_bc,
1298 const bool is_isolated_b,
1299 std::vector <bool>::reference ,
1301 boost::true_type )
const
1303 if (is_new_ab && is_new_bc && !is_isolated_b)
return (
false);
1318 const HalfEdgeIndex& idx_he_bc,
1319 const bool is_new_ab,
1320 const bool is_new_bc,
1322 std::vector <bool>::reference make_adjacent_ab_bc,
1323 HalfEdgeIndex& idx_free_half_edge,
1324 boost::false_type )
const
1326 if (is_new_ab || is_new_bc)
1328 make_adjacent_ab_bc =
false;
1334 make_adjacent_ab_bc =
false;
1338 make_adjacent_ab_bc =
true;
1358 const HalfEdgeIndex& idx_he_bc,
1359 HalfEdgeIndex& idx_free_half_edge)
1382 const FaceData& face_data)
1384 faces_.push_back (Face (inner_he.back ()));
1385 this->
addData (face_data_cloud_, face_data, HasFaceData ());
1387 const FaceIndex idx_face (static_cast <int> (this->
sizeFaces () - 1));
1389 for (HalfEdgeIndices::const_iterator it=inner_he.begin (); it!=inner_he.end (); ++it)
1400 const HalfEdgeIndex& idx_he_bc)
1409 const HalfEdgeIndex& idx_he_bc,
1410 const VertexIndex& idx_v_b,
1425 const HalfEdgeIndex& idx_he_bc,
1426 const VertexIndex& idx_v_b,
1431 this->
connectNewNew (idx_he_ab, idx_he_bc, idx_v_b, boost::true_type ());
1451 const HalfEdgeIndex& idx_he_bc,
1452 const VertexIndex& idx_v_b)
1466 const HalfEdgeIndex& idx_he_bc,
1467 const VertexIndex& idx_v_b)
1481 const HalfEdgeIndex& ,
1482 const VertexIndex& ,
1490 const HalfEdgeIndex& idx_he_bc,
1491 const VertexIndex& idx_v_b,
1497 if (idx_he_b_out == idx_he_bc)
1500 const OutgoingHalfEdgeAroundVertexCirculator circ_end = circ;
1502 while (++circ!=circ_end)
1518 template <
class DataT>
1526 template <
class DataT>
1541 assert (this->
isValid (idx_face));
1542 delete_faces_face_.clear ();
1543 delete_faces_face_.push_back (idx_face);
1545 while (!delete_faces_face_.empty ())
1547 const FaceIndex idx_face_cur = delete_faces_face_.back ();
1548 delete_faces_face_.pop_back ();
1551 this->
deleteFace (idx_face_cur, boost::false_type ());
1560 assert (this->
isValid (idx_face));
1565 is_boundary_.clear ();
1567 const InnerHalfEdgeAroundFaceCirculator circ_end = circ;
1572 }
while (++circ != circ_end);
1573 assert (inner_he_.size () >= 3);
1575 const int n = static_cast <
int> (inner_he_.size ());
1578 if (IsManifold::value)
1580 for (
int i=0; i<n; ++i)
1583 this->
reconnect (inner_he_ [i], inner_he_ [j], is_boundary_ [i], is_boundary_ [j]);
1585 for (
int i=0; i<n; ++i)
1592 for (
int i=0; i<n; ++i)
1595 this->
reconnect (inner_he_ [i], inner_he_ [j], is_boundary_ [i], is_boundary_ [j]);
1610 const HalfEdgeIndex& idx_he_bc,
1611 const bool is_boundary_ba,
1612 const bool is_boundary_cb)
1618 if (is_boundary_ba && is_boundary_cb)
1622 if (idx_he_cb_next == idx_he_ba)
1635 else if (is_boundary_ba && !is_boundary_cb)
1643 else if (!is_boundary_ba && is_boundary_cb)
1651 this->
reconnectNBNB (idx_he_bc, idx_he_cb, idx_v_b, IsManifold ());
1658 const HalfEdgeIndex& idx_he_cb,
1659 const VertexIndex& idx_v_b,
1670 delete_faces_face_.push_back (this->
getFaceIndex ((circ++).getTargetIndex ()));
1672 #ifdef PCL_GEOMETRY_MESH_BASE_TEST_DELETE_FACE_MANIFOLD_2
1679 pcl::geometry::g_pcl_geometry_mesh_base_test_delete_face_manifold_2_success =
false;
1694 const HalfEdgeIndex& ,
1695 const VertexIndex& idx_v_b,
1712 assert (this->
isValid (idx_vertex));
1720 assert (this->
isValid (idx_he));
1728 assert (this->
isValid (idx_edge));
1737 assert (this->
isValid (idx_face));
1754 template <
class ElementContainerT,
class DataContainerT,
class IndexContainerT,
class HasDataT> IndexContainerT
1755 remove (ElementContainerT& elements, DataContainerT& data_cloud)
1757 typedef typename IndexContainerT::value_type Index;
1758 typedef typename ElementContainerT::value_type Element;
1760 if (HasDataT::value) assert (elements.size () == data_cloud.size ());
1761 else assert (data_cloud.empty ());
1763 IndexContainerT new_indices (elements.size (),
typename IndexContainerT::value_type ());
1764 Index ind_old (0), ind_new (0);
1766 typename ElementContainerT::const_iterator it_e_old = elements.begin ();
1767 typename ElementContainerT::iterator it_e_new = elements.begin ();
1769 typename DataContainerT::const_iterator it_d_old = data_cloud.begin ();
1770 typename DataContainerT::iterator it_d_new = data_cloud.begin ();
1772 typename IndexContainerT::iterator it_ind_new = new_indices.begin ();
1773 typename IndexContainerT::const_iterator it_ind_new_end = new_indices.end ();
1775 while (it_ind_new!=it_ind_new_end)
1779 *it_ind_new = ind_new++;
1782 *it_e_new++ = *it_e_old;
1783 this->
assignIf (it_d_old, it_d_new, HasDataT ());
1792 elements.resize (ind_new.get (), Element ());
1793 if (HasDataT::value)
1795 data_cloud.resize (ind_new.get ());
1797 else if (it_d_old != data_cloud.begin () || it_d_new != data_cloud.begin ())
1799 std::cerr <<
"TODO: Bug in MeshBase::remove!\n";
1801 exit (EXIT_FAILURE);
1804 return (new_indices);
1808 template <
class IteratorT>
inline void
1815 template <
class IteratorT>
inline void
1821 template <
class ConstIteratorT,
class IteratorT>
inline void
1822 assignIf (
const ConstIteratorT source, IteratorT target, boost::true_type )
const
1828 template <
class ConstIteratorT,
class IteratorT>
inline void
1829 assignIf (
const ConstIteratorT , IteratorT , boost::false_type )
const
1841 assert (this->
isValid (idx_vertex));
1842 this->
getVertex (idx_vertex).idx_outgoing_half_edge_ = idx_outgoing_half_edge;
1849 assert (this->
isValid (idx_half_edge));
1850 this->
getHalfEdge (idx_half_edge).idx_terminating_vertex_ = idx_terminating_vertex;
1857 assert (this->
isValid (idx_half_edge));
1858 this->
getHalfEdge (idx_half_edge).idx_next_half_edge_ = idx_next_half_edge;
1864 const HalfEdgeIndex& idx_prev_half_edge)
1866 assert (this->
isValid (idx_half_edge));
1867 this->
getHalfEdge (idx_half_edge).idx_prev_half_edge_ = idx_prev_half_edge;
1872 setFaceIndex (
const HalfEdgeIndex& idx_half_edge,
const FaceIndex& idx_face)
1874 assert (this->
isValid (idx_half_edge));
1875 this->
getHalfEdge (idx_half_edge).idx_face_ = idx_face;
1882 assert (this->
isValid (idx_face));
1883 this->
getFace (idx_face).idx_inner_half_edge_ = idx_inner_half_edge;
1895 const VertexAroundFaceCirculator circ_end = circ;
1903 }
while (++circ!=circ_end);
1913 const OuterHalfEdgeAroundFaceCirculator circ_end = circ;
1921 }
while (++circ!=circ_end);
1935 isManifold (
const VertexIndex& idx_vertex, boost::false_type )
const
1938 const OutgoingHalfEdgeAroundVertexCirculator circ_end = circ;
1940 if (!this->
isBoundary ((circ++).getTargetIndex ()))
return (
true);
1944 }
while (++circ != circ_end);
1962 if (!this->
isManifold (VertexIndex (i)))
return (
false);
1972 template <
class DataCloudT>
inline void
1973 reserveData (DataCloudT& cloud,
const size_t n, boost::true_type )
const
1979 template <
class DataCloudT>
inline void
1985 template <
class DataCloudT>
inline void
1986 resizeData (DataCloudT& data_cloud,
const size_t n,
const typename DataCloudT::value_type& data, boost::true_type )
const
1988 data.resize (n, data);
1992 template <
class DataCloudT>
inline void
1993 resizeData (DataCloudT& ,
const size_t ,
const typename DataCloudT::value_type& , boost::false_type )
const
1998 template <
class DataCloudT>
inline void
2005 template <
class DataCloudT>
inline void
2018 assert (this->
isValid (idx_vertex));
2019 return (vertices_ [idx_vertex.
get ()]);
2026 assert (this->
isValid (idx_vertex));
2027 return (vertices_ [idx_vertex.
get ()]);
2032 setVertex (
const VertexIndex& idx_vertex,
const Vertex& vertex)
2034 assert (this->
isValid (idx_vertex));
2035 vertices_ [idx_vertex.
get ()] = vertex;
2046 assert (this->
isValid (idx_he));
2047 return (half_edges_ [idx_he.
get ()]);
2054 assert (this->
isValid (idx_he));
2055 return (half_edges_ [idx_he.
get ()]);
2062 assert (this->
isValid (idx_he));
2063 half_edges_ [idx_he.
get ()] = half_edge;
2074 assert (this->
isValid (idx_face));
2075 return (faces_ [idx_face.
get ()]);
2082 assert (this->
isValid (idx_face));
2083 return (faces_ [idx_face.
get ()]);
2088 setFace (
const FaceIndex& idx_face,
const Face& face)
2090 assert (this->
isValid (idx_face));
2091 faces_ [idx_face.
get ()] = face;
2101 VertexDataCloud vertex_data_cloud_;
2104 HalfEdgeDataCloud half_edge_data_cloud_;
2107 EdgeDataCloud edge_data_cloud_;
2110 FaceDataCloud face_data_cloud_;
2116 HalfEdges half_edges_;
2124 HalfEdgeIndices inner_he_;
2127 HalfEdgeIndices free_he_;
2130 std::vector <bool> is_new_;
2133 std::vector <bool> make_adjacent_;
2136 std::vector <bool> is_boundary_;
2139 FaceIndices delete_faces_vertex_;
2142 FaceIndices delete_faces_face_;
2146 template <
class MeshT>
2149 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
2154 #endif // PCL_GEOMETRY_MESH_BASE_H
Vertices::const_iterator VertexConstIterator
bool isValid(const HalfEdgeIndex &idx_he) const
Check if the given half-edge index is a valid index into the mesh.
size_t sizeFaces() const
Get the number of the faces.
HalfEdgeDataCloud getHalfEdgeDataCloud() const
Get the stored half-edge data.
void connectNewNew(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b, boost::true_type)
Both half-edges are new (manifold version).
HalfEdgeIndex getHalfEdgeIndex(const HalfEdgeData &half_edge_data) const
Get the index associated to the given half-edge data.
boost::shared_ptr< const Self > ConstPtr
void reconnect(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const bool is_boundary_ba, const bool is_boundary_cb)
Deconnect the input half-edges from the mesh and adjust the indices of the connected half-edges...
An edge is a connection between two vertices.
void reserveEdges(const size_t n)
Reserve storage space for n edges (2*n storage space is reserved for the half-edges).
VertexIndex getVertexIndex(const VertexData &vertex_data) const
Get the index associated to the given vertex data.
bool checkTopology2(const HalfEdgeIndex &, const HalfEdgeIndex &, const bool is_new_ab, const bool is_new_bc, const bool is_isolated_b, std::vector< bool >::reference, HalfEdgeIndex &, boost::true_type) const
Check if the face may be added (mesh does not become non-manifold).
void setOutgoingHalfEdgeIndex(const VertexIndex &idx_vertex, const HalfEdgeIndex &idx_outgoing_half_edge)
Set the outgoing half-edge index to a given vertex.
pcl::geometry::FaceIndex FaceIndex
bool checkTopology1(const VertexIndex &idx_v_a, const VertexIndex &idx_v_b, HalfEdgeIndex &idx_he_ab, std::vector< bool >::reference is_new_ab, boost::true_type) const
Check if the edge between the two vertices can be added.
void connectNewNew(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b, boost::false_type)
Both half-edges are new (non-manifold version).
void resizeData(DataCloudT &, const size_t, const typename DataCloudT::value_type &, boost::false_type) const
Does nothing.
Base class for the half-edge mesh.
pcl::geometry::EdgeIndex EdgeIndex
void makeAdjacent(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, HalfEdgeIndex &idx_free_half_edge)
Make the half-edges bc the next half-edge of ab.
FaceAroundVertexCirculator getFaceAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
bool isEqualTopology(const Self &other) const
Check if the other mesh has the same topology as this mesh.
Index used to access elements in the half-edge mesh.
BOOST_CONCEPT_ASSERT((boost::Convertible< IsManifold, bool >))
void markDeleted(const FaceIndex &idx_face)
Mark the given face as deleted.
InnerHalfEdgeAroundFaceCirculator getInnerHalfEdgeAroundFaceCirculator(const FaceIndex &idx_face) const
std::vector< Face > Faces
void addData(pcl::PointCloud< DataT > &, const DataT &, boost::false_type)
Does nothing.
void reconnectNBNB(const HalfEdgeIndex &idx_he_bc, const HalfEdgeIndex &, const VertexIndex &idx_v_b, boost::false_type)
Both edges are not on the boundary.
pcl::PointCloud< EdgeData > EdgeDataCloud
std::vector< Vertex > Vertices
void invalidate()
Invalidate the index.
bool setVertexDataCloud(const VertexDataCloud &vertex_data_cloud)
Change the stored vertex data.
Circulates clockwise around a face and returns an index to the terminating vertex of the inner half-e...
bool setFaceDataCloud(const FaceDataCloud &face_data_cloud)
Change the stored face data.
void incrementIf(IteratorT &, boost::false_type) const
Does nothing.
VertexAroundFaceCirculator getVertexAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
MeshBase< DerivedT, MeshTraitsT, MeshTagT > Self
void connectPrevNext(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc)
Connect the next and prev indices of the two half-edges with each other.
void invalidate()
Invalidate the index.
pcl::geometry::HalfEdge HalfEdge
MeshTraitsT::EdgeData EdgeData
void deleteVertex(const VertexIndex &idx_vertex)
Mark the given vertex and all connected half-edges and faces as deleted.
HalfEdgeIndex getPrevHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the previous half-edge index to a given half-edge.
bool isValid(const FaceIndex &idx_face) const
Check if the given face index is a valid index into the mesh.
FaceAroundVertexCirculator getFaceAroundVertexCirculator(const VertexIndex &idx_vertex) const
void connectNewOld(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b)
The first half-edge is new.
bool isBoundary(const FaceIndex &idx_face) const
Check if the given face lies on the boundary.
HalfEdgeIndex getOppositeHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the opposite half-edge index to a given half-edge.
Face getFace(const FaceIndex &idx_face) const
Get the face for the given index.
bool isBoundary(const FaceIndex &idx_face, boost::false_type) const
Check if any edge of the face lies on the boundary.
bool empty() const
Check if the mesh is empty.
void assignIf(const ConstIteratorT source, IteratorT target, boost::true_type) const
Assign the source iterator to the target iterator.
bool isValid() const
Returns true if the index is valid.
Index used to access elements in the half-edge mesh.
EdgeIndex getEdgeIndex(const EdgeData &edge_data) const
Get the index associated to the given edge data.
FaceIndex addFaceImplBase(const VertexIndices &vertices, const FaceData &face_data, const EdgeData &edge_data, const HalfEdgeData &half_edge_data)
General implementation of addFace.
void resize(size_t n)
Resize the cloud.
int get() const
Get the index.
Index used to access elements in the half-edge mesh.
void resizeVertices(const size_t n, const VertexData &data=VertexData())
Resize the the vertices to n elements.
void setFaceIndex(const HalfEdgeIndex &idx_half_edge, const FaceIndex &idx_face)
Set the face index to a given half-edge.
std::vector< HalfEdgeIndex > HalfEdgeIndices
HalfEdgeIndex getTargetIndex() const
Get the index to the outgoing half-edge.
pcl::geometry::InnerHalfEdgeAroundFaceCirculator< const Self > InnerHalfEdgeAroundFaceCirculator
pcl::geometry::OutgoingHalfEdgeAroundVertexCirculator< const Self > OutgoingHalfEdgeAroundVertexCirculator
IncomingHalfEdgeAroundVertexCirculator getIncomingHalfEdgeAroundVertexCirculator(const HalfEdgeIndex &idx_incoming_half_edge) const
bool isDeleted(const HalfEdgeIndex &idx_he) const
Check if the given half-edge is marked as deleted.
void markDeleted(const VertexIndex &idx_vertex)
Mark the given vertex as deleted.
InnerHalfEdgeAroundFaceCirculator getInnerHalfEdgeAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
pcl::geometry::FaceAroundFaceCirculator< const Self > FaceAroundFaceCirculator
OutgoingHalfEdgeAroundVertexCirculator getOutgoingHalfEdgeAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
HalfEdgeIndex getOutgoingHalfEdgeIndex(const VertexIndex &idx_vertex) const
Get the outgoing half-edge index to a given vertex.
OuterHalfEdgeAroundFaceCirculator getOuterHalfEdgeAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
void deleteFace(const FaceIndex &idx_face, boost::false_type)
Non-manifold version of deleteFace.
std::vector< HalfEdge > HalfEdges
Circulates clockwise around a face and returns an index to the outer half-edge (the target)...
bool isIsolated(const VertexIndex &idx_vertex) const
Check if the given vertex is isolated (not connected to other elements).
void resizeEdges(const size_t n, const EdgeData &edge_data=EdgeData(), const HalfEdgeData he_data=HalfEdgeData())
Resize the edges to n elements (half-edges will hold 2*n elements).
bool isBoundary(const VertexIndex &idx_vertex) const
Check if the given vertex lies on the boundary.
IncomingHalfEdgeAroundVertexCirculator getIncomingHalfEdgeAroundVertexCirculator(const VertexIndex &idx_vertex) const
Read / write the half-edge mesh from / to a file.
VertexAroundVertexCirculator getVertexAroundVertexCirculator(const VertexIndex &idx_vertex) const
bool isManifold(const VertexIndex &idx_vertex) const
Check if the given vertex is manifold.
Vertices::iterator VertexIterator
size_t sizeVertices() const
Get the number of the vertices.
void clear()
Clear all mesh elements and data.
pcl::geometry::VertexAroundVertexCirculator< const Self > VertexAroundVertexCirculator
FaceIndex connectFace(const HalfEdgeIndices &inner_he, const FaceData &face_data)
Add a face to the mesh and connect it to the half-edges.
A vertex is a node in the mesh.
bool isBoundary(const EdgeIndex &idx_edge) const
Check if the given edge lies on the boundary (any of the two half-edges lies on the boundary...
HalfEdges::const_iterator HalfEdgeConstIterator
HalfEdgeIndex getTargetIndex() const
Get the index to the inner half-edge.
bool isManifold(boost::false_type) const
Check if all vertices in the mesh are manifold.
pcl::geometry::HalfEdgeIndex toHalfEdgeIndex(const EdgeIndex &index, const bool get_first=true)
Convert the given edge index to a half-edge index.
void setPrevHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge, const HalfEdgeIndex &idx_prev_half_edge)
Set the previous half-edge index to a given half-edge.
pcl::geometry::VertexIndex VertexIndex
HalfEdgeIndex getCurrentHalfEdgeIndex() const
Get the half-edge that is currently stored in the circulator.
bool emptyFaces() const
Check if the faces are empty.
boost::integral_constant< bool,!boost::is_same< EdgeData, pcl::geometry::NoData >::value > HasEdgeData
VectorType::iterator iterator
size_t sizeHalfEdges() const
Get the number of the half-edges.
VertexIndex getOriginatingVertexIndex(const HalfEdgeIndex &idx_half_edge) const
Get the originating vertex index to a given half-edge.
Circulates clockwise around a face and returns an index to the inner half-edge (the target)...
void deleteEdge(const EdgeIndex &idx_edge)
Mark the given edge (both half-edges) and the associated faces as deleted.
void deleteFace(const FaceIndex &idx_face)
Mark the given face as deleted.
void addData(pcl::PointCloud< DataT > &cloud, const DataT &data, boost::true_type)
Add mesh data.
MeshTraitsT::HalfEdgeData HalfEdgeData
pcl::PointCloud< HalfEdgeData > HalfEdgeDataCloud
FaceAroundFaceCirculator getFaceAroundFaceCirculator(const FaceIndex &idx_face) const
VertexIndex getTargetIndex() const
Get the index to the target vertex.
void setVertex(const VertexIndex &idx_vertex, const Vertex &vertex)
Set the vertex at the given index.
Vertex & getVertex(const VertexIndex &idx_vertex)
Get the vertex for the given index.
void clearData(DataCloudT &cloud, boost::true_type) const
Clear the mesh data.
bool checkTopology1(const VertexIndex &idx_v_a, const VertexIndex &idx_v_b, HalfEdgeIndex &idx_he_ab, std::vector< bool >::reference is_new_ab, boost::false_type) const
Non manifold version of checkTopology1.
boost::integral_constant< bool,!boost::is_same< VertexData, pcl::geometry::NoData >::value > HasVertexData
void resizeFaces(const size_t n, const FaceData &data=FaceData())
Resize the faces to n elements.
bool isValid(const VertexIndex &idx_vertex) const
Check if the given vertex index is a valid index into the mesh.
Vertex getVertex(const VertexIndex &idx_vertex) const
Get the vertex for the given index.
HalfEdges::iterator HalfEdgeIterator
VertexIndex getTerminatingVertexIndex(const HalfEdgeIndex &idx_half_edge) const
Get the terminating vertex index to a given half-edge.
pcl::PointCloud< FaceData > FaceDataCloud
void incrementIf(IteratorT &it, boost::true_type) const
Increment the iterator.
EdgeDataCloud & getEdgeDataCloud()
Get access to the stored edge data.
int get() const
Get the index.
pcl::geometry::FaceAroundVertexCirculator< const Self > FaceAroundVertexCirculator
void setTerminatingVertexIndex(const HalfEdgeIndex &idx_half_edge, const VertexIndex &idx_terminating_vertex)
Set the terminating vertex index to a given half-edge.
boost::integral_constant< bool,!boost::is_same< HalfEdgeData, pcl::geometry::NoData >::value > HasHalfEdgeData
void markDeleted(const HalfEdgeIndex &idx_he)
Mark the given half-edge as deleted.
FaceIndex addFace(const VertexIndices &vertices, const FaceData &face_data=FaceData(), const EdgeData &edge_data=EdgeData(), const HalfEdgeData &half_edge_data=HalfEdgeData())
Add a face to the mesh.
bool setHalfEdgeDataCloud(const HalfEdgeDataCloud &half_edge_data_cloud)
Change the stored half-edge data.
HalfEdgeIndex getTargetIndex() const
Get the index to the outer half-edge.
void setFace(const FaceIndex &idx_face, const Face &face)
Set the face at the given index.
HalfEdgeIndex getTargetIndex() const
Get the index to the incoming half-edge.
pcl::geometry::OuterHalfEdgeAroundFaceCirculator< const Self > OuterHalfEdgeAroundFaceCirculator
bool isBoundary(const FaceIndex &idx_face, boost::true_type) const
Check if any vertex of the face lies on the boundary.
void clearData(DataCloudT &, boost::false_type) const
Does nothing.
bool isManifold(const VertexIndex &, boost::true_type) const
Always manifold.
bool isManifold() const
Check if the mesh is manifold.
bool isDeleted(const VertexIndex &idx_vertex) const
Check if the given vertex is marked as deleted.
void reconnectNBNB(const HalfEdgeIndex &idx_he_bc, const HalfEdgeIndex &idx_he_cb, const VertexIndex &idx_v_b, boost::true_type)
Both edges are not on the boundary.
void cleanUp()
Removes all mesh elements and data that are marked as deleted.
Faces::const_iterator FaceConstIterator
VertexIndex addVertex(const VertexData &vertex_data=VertexData())
Add a vertex to the mesh.
FaceIndex getFaceIndex(const FaceData &face_data) const
Get the index associated to the given face data.
std::vector< EdgeIndex > EdgeIndices
Index used to access elements in the half-edge mesh.
void reserveData(DataCloudT &, const size_t, boost::false_type) const
Does nothing.
OuterHalfEdgeAroundFaceCirculator getOuterHalfEdgeAroundFaceCirculator(const FaceIndex &idx_face) const
pcl::geometry::VertexAroundFaceCirculator< const Self > VertexAroundFaceCirculator
bool checkTopology2(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const bool is_new_ab, const bool is_new_bc, const bool, std::vector< bool >::reference make_adjacent_ab_bc, HalfEdgeIndex &idx_free_half_edge, boost::false_type) const
Check if the half-edge bc is the next half-edge of ab.
Circulates clockwise around a face and returns an index to the face of the outer half-edge (the targe...
void assignIf(const ConstIteratorT, IteratorT, boost::false_type) const
Does nothing.
void deleteEdge(const HalfEdgeIndex &idx_he)
Mark the given half-edge, the opposite half-edge and the associated faces as deleted.
void setHalfEdge(const HalfEdgeIndex &idx_he, const HalfEdge &half_edge)
Set the half-edge at the given index.
HalfEdgeIndex getInnerHalfEdgeIndex(const FaceIndex &idx_face) const
Get the inner half-edge index to a given face.
void reserveData(DataCloudT &cloud, const size_t n, boost::true_type) const
Reserve storage space for the mesh data.
MeshTraitsT::VertexData VertexData
HalfEdgeIndex addEdge(const VertexIndex &idx_v_a, const VertexIndex &idx_v_b, const HalfEdgeData &he_data, const EdgeData &edge_data)
Add an edge between the two given vertices and connect them with the vertices.
FaceIndex getOppositeFaceIndex(const HalfEdgeIndex &idx_half_edge) const
Get the face index to a given half-edge.
VertexAroundFaceCirculator getVertexAroundFaceCirculator(const FaceIndex &idx_face) const
void deleteFace(const FaceIndex &idx_face, boost::true_type)
Manifold version of deleteFace.
HalfEdge & getHalfEdge(const HalfEdgeIndex &idx_he)
Get the half-edge for the given index.
Circulates counter-clockwise around a vertex and returns an index to the terminating vertex of the ou...
VertexAroundVertexCirculator getVertexAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
OutgoingHalfEdgeAroundVertexCirculator getOutgoingHalfEdgeAroundVertexCirculator(const VertexIndex &idx_vertex) const
const PointT & front() const
HalfEdge getHalfEdge(const HalfEdgeIndex &idx_he) const
Get the half-edge for the given index.
FaceDataCloud & getFaceDataCloud()
Get access to the stored face data.
bool isDeleted(const EdgeIndex &idx_edge) const
Check if the given edge (any of the two half-edges) is marked as deleted.
bool emptyVertices() const
Check if the vertices are empty.
Circulates counter-clockwise around a vertex and returns an index to the incoming half-edge (the targ...
EdgeDataCloud getEdgeDataCloud() const
Get the stored edge data.
bool emptyEdges() const
Check if the edges are empty.
void resizeData(DataCloudT &data_cloud, const size_t n, const typename DataCloudT::value_type &data, boost::true_type) const
Resize the mesh data.
void connectOldOld(const HalfEdgeIndex &, const HalfEdgeIndex &, const VertexIndex &, boost::true_type)
Both half-edges are old (manifold version).
pcl::PointCloud< VertexData > VertexDataCloud
void reserveFaces(const size_t n)
Reserve storage space for n faces.
void setInnerHalfEdgeIndex(const FaceIndex &idx_face, const HalfEdgeIndex &idx_inner_half_edge)
Set the inner half-edge index to a given face.
std::vector< VertexIndex > VertexIndices
int get() const
Get the index.
boost::shared_ptr< Self > Ptr
bool isDeleted(const FaceIndex &idx_face) const
Check if the given face is marked as deleted.
FaceIndex getFaceIndex(const HalfEdgeIndex &idx_half_edge) const
Get the face index to a given half-edge.
size_t sizeEdges() const
Get the number of the edges.
const PointT & back() const
pcl::geometry::IncomingHalfEdgeAroundVertexCirculator< const Self > IncomingHalfEdgeAroundVertexCirculator
Face & getFace(const FaceIndex &idx_face)
Get the face for the given index.
bool isValid(const EdgeIndex &idx_edge) const
Check if the given edge index is a valid index into the mesh.
Circulates counter-clockwise around a vertex and returns an index to the face of the outgoing half-ed...
pcl::geometry::HalfEdgeIndex HalfEdgeIndex
VertexDataCloud & getVertexDataCloud()
Get access to the stored vertex data.
void connectOldOld(const HalfEdgeIndex &, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b, boost::false_type)
Both half-edges are old (non-manifold version).
A face is a closed loop of edges.
bool setEdgeDataCloud(const EdgeDataCloud &edge_data_cloud)
Change the stored edge data.
HalfEdgeDataCloud & getHalfEdgeDataCloud()
Get access to the stored half-edge data.
void invalidate()
Invalidate the index.
bool isBoundary(const HalfEdgeIndex &idx_he) const
Check if the given half-edge lies on the bounddary.
FaceIndex getTargetIndex() const
Get the index to the target face.
boost::integral_constant< bool,!boost::is_same< FaceData, pcl::geometry::NoData >::value > HasFaceData
void setNextHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge, const HalfEdgeIndex &idx_next_half_edge)
Set the next half_edge index to a given half-edge.
void markDeleted(const EdgeIndex &idx_edge)
Mark the given edge (both half-edges) as deleted.
bool isManifold(const VertexIndex &idx_vertex, boost::false_type) const
Check if the given vertex is manifold.
Circulates counter-clockwise around a vertex and returns an index to the outgoing half-edge (the targ...
HalfEdgeIndex getNextHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the next half-edge index to a given half-edge.
HalfEdgeIndex getIncomingHalfEdgeIndex(const VertexIndex &idx_vertex) const
Get the incoming half-edge index to a given vertex.
pcl::geometry::Vertex Vertex
FaceAroundFaceCirculator getFaceAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
void push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
void connectOldNew(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b)
The second half-edge is new.
VectorType::const_iterator const_iterator
std::vector< FaceIndex > FaceIndices
Faces::iterator FaceIterator
HalfEdgeIndex getOuterHalfEdgeIndex(const FaceIndex &idx_face) const
Get the outer half-edge inex to a given face.
bool isBoundary(const FaceIndex &idx_face) const
Check if the given face lies on the boundary.
VertexIndex getTargetIndex() const
Get the index to the target vertex.
FaceDataCloud getFaceDataCloud() const
Get the stored face data.
VertexDataCloud getVertexDataCloud() const
Get the stored vertex data.
MeshTraitsT::IsManifold IsManifold
bool isManifold(boost::true_type) const
Always manifold.
void reserveVertices(const size_t n)
Reserve storage space n vertices.
MeshTraitsT::FaceData FaceData