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 ());
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 ();
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));
279 this->remove <Vertices, VertexDataCloud, VertexIndices, HasVertexData>
280 (vertices_, vertex_data_cloud_);
282 this->remove <HalfEdges, HalfEdgeDataCloud, HalfEdgeIndices, HasHalfEdgeData>
283 (half_edges_, half_edge_data_cloud_);
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));
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));
442 assert (this->
isValid (idx_vertex));
450 assert (this->
isValid (idx_outgoing_half_edge));
458 assert (this->
isValid (idx_vertex));
466 assert (this->
isValid (idx_outgoing_half_edge));
474 assert (this->
isValid (idx_vertex));
482 assert (this->
isValid (idx_incoming_half_edge));
490 assert (this->
isValid (idx_vertex));
498 assert (this->
isValid (idx_outgoing_half_edge));
506 assert (this->
isValid (idx_face));
514 assert (this->
isValid (idx_inner_half_edge));
522 assert (this->
isValid (idx_face));
530 assert (this->
isValid (idx_inner_half_edge));
538 assert (this->
isValid (idx_face));
546 assert (this->
isValid (idx_inner_half_edge));
554 assert (this->
isValid (idx_face));
562 assert (this->
isValid (idx_inner_half_edge));
599 for (
unsigned int i=0; i<this->
sizeFaces (); ++i)
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);
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);
839 half_edges_.reserve (2*n);
860 vertices_.resize (n);
870 half_edges_.resize (2*n);
892 half_edges_.clear ();
911 return (vertex_data_cloud_);
918 return (vertex_data_cloud_);
928 if (vertex_data_cloud.
size () == vertex_data_cloud_.
size ())
930 vertex_data_cloud_ = vertex_data_cloud;
949 return (half_edge_data_cloud_);
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;
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;
1025 return (face_data_cloud_);
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)));
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)));
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)));
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)));
1149 const int n =
static_cast<int> (vertices.size ());
1153 inner_he_.resize (n);
1154 free_he_.resize (n);
1156 make_adjacent_.resize (n);
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 ()))
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]);
1204 return (this->
connectFace (inner_he_, face_data));
1224 half_edges_.push_back (
HalfEdge (idx_v_b));
1225 half_edges_.push_back (
HalfEdge (idx_v_a));
1231 return (
HalfEdgeIndex (static_cast <int> (half_edges_.size () - 2)));
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);
1267 std::vector <bool>::reference is_new_ab,
1268 boost::false_type )
const
1271 if (this->
isIsolated (idx_v_a))
return (
true);
1282 if (!this->
isBoundary (idx_he_ab))
return (
false);
1287 }
while (++circ!=circ_end);
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);
1319 const bool is_new_ab,
1320 const bool is_new_bc,
1322 std::vector <bool>::reference make_adjacent_ab_bc,
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;
1384 faces_.push_back (
Face (inner_he.back ()));
1389 for (HalfEdgeIndices::const_iterator it=inner_he.begin (); it!=inner_he.end (); ++it)
1431 this->
connectNewNew (idx_he_ab, idx_he_bc, idx_v_b, boost::true_type ());
1497 if (idx_he_b_out == idx_he_bc)
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 ();
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]);
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)
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;
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;
1866 assert (this->
isValid (idx_half_edge));
1867 this->
getHalfEdge (idx_half_edge).idx_prev_half_edge_ = idx_prev_half_edge;
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;
1903 }
while (++circ!=circ_end);
1921 }
while (++circ!=circ_end);
1940 if (!this->
isBoundary ((circ++).getTargetIndex ()))
return (
true);
1944 }
while (++circ != circ_end);
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 ()]);
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 ()]);
2090 assert (this->
isValid (idx_face));
2091 faces_ [idx_face.
get ()] = face;
2130 std::vector <bool> is_new_;
2133 std::vector <bool> make_adjacent_;
2136 std::vector <bool> is_boundary_;
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.
VectorType::iterator iterator
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.
const PointT & front() const
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.
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
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.
VectorType::const_iterator const_iterator
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
Describes a set of vertices in a polygon mesh, by basically storing an array of indices.
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
const PointT & back() const
Index used to access elements in the half-edge mesh.
void reserveData(DataCloudT &, const size_t, boost::false_type) const
Does nothing.
void resize(size_t n)
Resize the cloud.
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
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.
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 connectOldNew(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b)
The second half-edge is new.
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.
void push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
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