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 ());
1078 if (HasHalfEdgeData::value)
1080 assert (&half_edge_data >= &half_edge_data_cloud_.
front () && &half_edge_data <= &half_edge_data_cloud_.
back ());
1093 if (HasEdgeData::value)
1095 assert (&edge_data >= &edge_data_cloud_.
front () && &edge_data <= &edge_data_cloud_.
back ());
1108 if (HasFaceData::value)
1110 assert (&face_data >= &face_data_cloud_.
front () && &face_data <= &face_data_cloud_.
back ());
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));
1755 template <
class ElementContainerT,
class DataContainerT,
class IndexContainerT,
class HasDataT> IndexContainerT
1756 remove (ElementContainerT& elements, DataContainerT& data_cloud)
1758 typedef typename IndexContainerT::value_type Index;
1759 typedef typename ElementContainerT::value_type Element;
1761 if (HasDataT::value) assert (elements.size () == data_cloud.size ());
1762 else assert (data_cloud.empty ());
1764 IndexContainerT new_indices (elements.size (),
typename IndexContainerT::value_type ());
1765 Index ind_old (0), ind_new (0);
1767 typename ElementContainerT::const_iterator it_e_old = elements.begin ();
1768 typename ElementContainerT::iterator it_e_new = elements.begin ();
1770 typename DataContainerT::const_iterator it_d_old = data_cloud.begin ();
1771 typename DataContainerT::iterator it_d_new = data_cloud.begin ();
1773 typename IndexContainerT::iterator it_ind_new = new_indices.begin ();
1774 typename IndexContainerT::const_iterator it_ind_new_end = new_indices.end ();
1776 while (it_ind_new!=it_ind_new_end)
1780 *it_ind_new = ind_new++;
1783 *it_e_new++ = *it_e_old;
1784 this->
assignIf (it_d_old, it_d_new, HasDataT ());
1793 elements.resize (ind_new.get (), Element ());
1794 if (HasDataT::value)
1796 data_cloud.resize (ind_new.get ());
1798 else if (it_d_old != data_cloud.begin () || it_d_new != data_cloud.begin ())
1800 std::cerr <<
"TODO: Bug in MeshBase::remove!\n";
1802 exit (EXIT_FAILURE);
1805 return (new_indices);
1809 template <
class IteratorT>
inline void 1816 template <
class IteratorT>
inline void 1822 template <
class ConstIteratorT,
class IteratorT>
inline void 1823 assignIf (
const ConstIteratorT source, IteratorT target, boost::true_type )
const 1829 template <
class ConstIteratorT,
class IteratorT>
inline void 1830 assignIf (
const ConstIteratorT , IteratorT , boost::false_type )
const 1842 assert (this->
isValid (idx_vertex));
1843 this->
getVertex (idx_vertex).idx_outgoing_half_edge_ = idx_outgoing_half_edge;
1850 assert (this->
isValid (idx_half_edge));
1851 this->
getHalfEdge (idx_half_edge).idx_terminating_vertex_ = idx_terminating_vertex;
1858 assert (this->
isValid (idx_half_edge));
1859 this->
getHalfEdge (idx_half_edge).idx_next_half_edge_ = idx_next_half_edge;
1867 assert (this->
isValid (idx_half_edge));
1868 this->
getHalfEdge (idx_half_edge).idx_prev_half_edge_ = idx_prev_half_edge;
1875 assert (this->
isValid (idx_half_edge));
1876 this->
getHalfEdge (idx_half_edge).idx_face_ = idx_face;
1883 assert (this->
isValid (idx_face));
1884 this->
getFace (idx_face).idx_inner_half_edge_ = idx_inner_half_edge;
1904 }
while (++circ!=circ_end);
1922 }
while (++circ!=circ_end);
1941 if (!this->
isBoundary ((circ++).getTargetIndex ()))
return (
true);
1945 }
while (++circ != circ_end);
1963 if (!this->
isManifold (VertexIndex (i)))
return (
false);
1973 template <
class DataCloudT>
inline void 1974 reserveData (DataCloudT& cloud,
const size_t n, boost::true_type )
const 1980 template <
class DataCloudT>
inline void 1986 template <
class DataCloudT>
inline void 1987 resizeData (DataCloudT& ,
const size_t n,
const typename DataCloudT::value_type& data, boost::true_type )
const 1989 data.resize (n, data);
1993 template <
class DataCloudT>
inline void 1994 resizeData (DataCloudT& ,
const size_t ,
const typename DataCloudT::value_type& , boost::false_type )
const 1999 template <
class DataCloudT>
inline void 2006 template <
class DataCloudT>
inline void 2019 assert (this->
isValid (idx_vertex));
2020 return (vertices_ [idx_vertex.
get ()]);
2027 assert (this->
isValid (idx_vertex));
2028 return (vertices_ [idx_vertex.
get ()]);
2035 assert (this->
isValid (idx_vertex));
2036 vertices_ [idx_vertex.
get ()] = vertex;
2047 assert (this->
isValid (idx_he));
2048 return (half_edges_ [idx_he.
get ()]);
2055 assert (this->
isValid (idx_he));
2056 return (half_edges_ [idx_he.
get ()]);
2063 assert (this->
isValid (idx_he));
2064 half_edges_ [idx_he.
get ()] = half_edge;
2075 assert (this->
isValid (idx_face));
2076 return (faces_ [idx_face.
get ()]);
2083 assert (this->
isValid (idx_face));
2084 return (faces_ [idx_face.
get ()]);
2091 assert (this->
isValid (idx_face));
2092 faces_ [idx_face.
get ()] = face;
2131 std::vector <bool> is_new_;
2134 std::vector <bool> make_adjacent_;
2137 std::vector <bool> is_boundary_;
2147 template <
class MeshT>
2150 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
2155 #endif // PCL_GEOMETRY_MESH_BASE_H HalfEdgeIndex getOppositeHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the opposite half-edge index to a given half-edge.
void markDeleted(const VertexIndex &idx_vertex)
Mark the given vertex as deleted.
HalfEdgeIndex getCurrentHalfEdgeIndex() const
Get the half-edge that is currently stored in the circulator.
size_t sizeHalfEdges() const
Get the number of the half-edges.
MeshBase< DerivedT, MeshTraitsT, MeshTagT > Self
std::vector< Vertex > Vertices
void deleteFace(const FaceIndex &idx_face, boost::false_type)
Non-manifold version of deleteFace.
void setPrevHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge, const HalfEdgeIndex &idx_prev_half_edge)
Set the previous half-edge index to a given half-edge.
bool isManifold(boost::true_type) const
Always manifold.
A vertex is a node in the mesh.
bool isBoundary(const FaceIndex &idx_face) const
Check if the given face lies on the boundary.
pcl::geometry::HalfEdgeIndex HalfEdgeIndex
IncomingHalfEdgeAroundVertexCirculator getIncomingHalfEdgeAroundVertexCirculator(const VertexIndex &idx_vertex) const
pcl::geometry::FaceAroundVertexCirculator< const Self > FaceAroundVertexCirculator
std::vector< FaceIndex > FaceIndices
HalfEdgeIndex getIncomingHalfEdgeIndex(const VertexIndex &idx_vertex) const
Get the incoming half-edge index to a given vertex.
VertexIndex getVertexIndex(const VertexData &vertex_data) const
Get the index associated to the given vertex data.
bool isBoundary(const HalfEdgeIndex &idx_he) const
Check if the given half-edge lies on the bounddary.
An edge is a connection between two vertices.
bool isDeleted(const VertexIndex &idx_vertex) const
Check if the given vertex is marked as deleted.
Faces::iterator FaceIterator
void invalidate()
Invalidate the index.
void resizeFaces(const size_t n, const FaceData &data=FaceData())
Resize the faces to n elements.
size_t sizeFaces() const
Get the number of the faces.
bool isValid(const EdgeIndex &idx_edge) const
Check if the given edge index is a valid index into the mesh.
void connectOldNew(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b)
The second half-edge is new.
OutgoingHalfEdgeAroundVertexCirculator getOutgoingHalfEdgeAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
bool isIsolated(const VertexIndex &idx_vertex) const
Check if the given vertex is isolated (not connected to other elements).
VertexIndex getOriginatingVertexIndex(const HalfEdgeIndex &idx_half_edge) const
Get the originating vertex index to a given half-edge.
bool isDeleted(const EdgeIndex &idx_edge) const
Check if the given edge (any of the two half-edges) is marked as deleted.
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.
HalfEdgeIndex getOutgoingHalfEdgeIndex(const VertexIndex &idx_vertex) const
Get the outgoing half-edge index to a given vertex.
Vertices::iterator VertexIterator
FaceDataCloud & getFaceDataCloud()
Get access to the stored face data.
MeshTraitsT::HalfEdgeData HalfEdgeData
boost::shared_ptr< Self > Ptr
pcl::geometry::VertexAroundVertexCirculator< const Self > VertexAroundVertexCirculator
void deleteEdge(const EdgeIndex &idx_edge)
Mark the given edge (both half-edges) and the associated faces as deleted.
void assignIf(const ConstIteratorT source, IteratorT target, boost::true_type) const
Assign the source iterator to the target iterator.
bool setHalfEdgeDataCloud(const HalfEdgeDataCloud &half_edge_data_cloud)
Change the stored half-edge data.
HalfEdgeIndex getNextHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the next half-edge index to a given half-edge.
boost::integral_constant< bool, !boost::is_same< VertexData, pcl::geometry::NoData >::value > HasVertexData
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).
std::vector< HalfEdge > HalfEdges
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.
FaceDataCloud getFaceDataCloud() const
Get the stored face data.
This file defines compatibility wrappers for low level I/O functions.
bool isManifold(boost::false_type) const
Check if all vertices in the mesh are manifold.
bool empty() const
Check if the mesh is empty.
pcl::geometry::VertexIndex VertexIndex
pcl::geometry::EdgeIndex EdgeIndex
Circulates clockwise around a face and returns an index to the face of the outer half-edge (the targe...
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).
void setNextHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge, const HalfEdgeIndex &idx_next_half_edge)
Set the next half_edge index to a given half-edge.
Circulates counter-clockwise around a vertex and returns an index to the incoming half-edge (the targ...
HalfEdgeIndex getOuterHalfEdgeIndex(const FaceIndex &idx_face) const
Get the outer half-edge inex to a given face.
void clearData(DataCloudT &, boost::false_type) const
Does nothing.
FaceAroundFaceCirculator getFaceAroundFaceCirculator(const FaceIndex &idx_face) const
VertexDataCloud getVertexDataCloud() const
Get the stored vertex data.
bool emptyFaces() const
Check if the faces are empty.
void setInnerHalfEdgeIndex(const FaceIndex &idx_face, const HalfEdgeIndex &idx_inner_half_edge)
Set the inner half-edge index to a given face.
bool emptyVertices() const
Check if the vertices are empty.
boost::integral_constant< bool, !boost::is_same< HalfEdgeData, pcl::geometry::NoData >::value > HasHalfEdgeData
void resizeVertices(const size_t n, const VertexData &data=VertexData())
Resize the the vertices to n elements.
void push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
VertexAroundVertexCirculator getVertexAroundVertexCirculator(const VertexIndex &idx_vertex) const
size_t sizeVertices() const
Get the number of the vertices.
void setHalfEdge(const HalfEdgeIndex &idx_he, const HalfEdge &half_edge)
Set the half-edge at the given index.
bool isValid(const VertexIndex &idx_vertex) const
Check if the given vertex index is a valid index into the mesh.
HalfEdgeDataCloud getHalfEdgeDataCloud() const
Get the stored half-edge data.
void deleteEdge(const HalfEdgeIndex &idx_he)
Mark the given half-edge, the opposite half-edge and the associated faces as deleted.
pcl::geometry::VertexAroundFaceCirculator< const Self > VertexAroundFaceCirculator
size_t sizeEdges() const
Get the number of the edges.
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).
VectorType::iterator iterator
void reserveFaces(const size_t n)
Reserve storage space for n faces.
Vertex getVertex(const VertexIndex &idx_vertex) const
Get the vertex for the given index.
HalfEdges::const_iterator HalfEdgeConstIterator
void addData(pcl::PointCloud< DataT > &, const DataT &, boost::false_type)
Does nothing.
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.
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.
EdgeIndex getEdgeIndex(const EdgeData &edge_data) const
Get the index associated to the given edge data.
EdgeDataCloud getEdgeDataCloud() const
Get the stored edge data.
bool isBoundary(const FaceIndex &idx_face) const
Check if the given face lies on the boundary.
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).
pcl::PointCloud< HalfEdgeData > HalfEdgeDataCloud
HalfEdgeIndex getTargetIndex() const
Get the index to the outer half-edge.
pcl::PointCloud< VertexData > VertexDataCloud
HalfEdgeIndex getHalfEdgeIndex(const HalfEdgeData &half_edge_data) const
Get the index associated to the given half-edge data.
VertexIndex getTargetIndex() const
Get the index to the target vertex.
Index used to access elements in the half-edge mesh.
std::vector< Face > Faces
std::vector< HalfEdgeIndex > HalfEdgeIndices
Describes a set of vertices in a polygon mesh, by basically storing an array of indices.
FaceAroundFaceCirculator getFaceAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
bool isBoundary(const FaceIndex &idx_face, boost::false_type) const
Check if any edge of the face lies on the boundary.
Faces::const_iterator FaceConstIterator
MeshTraitsT::IsManifold IsManifold
VertexIndex addVertex(const VertexData &vertex_data=VertexData())
Add a vertex to the mesh.
void markDeleted(const EdgeIndex &idx_edge)
Mark the given edge (both half-edges) as deleted.
pcl::geometry::HalfEdgeIndex toHalfEdgeIndex(const EdgeIndex &index, const bool get_first=true)
Convert the given edge index to a half-edge index.
void invalidate()
Invalidate the index.
bool isDeleted(const HalfEdgeIndex &idx_he) const
Check if the given half-edge is marked as deleted.
MeshTraitsT::EdgeData EdgeData
HalfEdgeIndex getTargetIndex() const
Get the index to the incoming half-edge.
int get() const
Get the index.
InnerHalfEdgeAroundFaceCirculator getInnerHalfEdgeAroundFaceCirculator(const FaceIndex &idx_face) const
HalfEdge & getHalfEdge(const HalfEdgeIndex &idx_he)
Get the half-edge for the given index.
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.
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.
Face & getFace(const FaceIndex &idx_face)
Get the face for the given index.
Circulates counter-clockwise around a vertex and returns an index to the terminating vertex of the ou...
void connectOldOld(const HalfEdgeIndex &, const HalfEdgeIndex &, const VertexIndex &, boost::true_type)
Both half-edges are old (manifold version).
bool isBoundary(const VertexIndex &idx_vertex) const
Check if the given vertex lies on the boundary.
void setFace(const FaceIndex &idx_face, const Face &face)
Set the face at the given index.
void setOutgoingHalfEdgeIndex(const VertexIndex &idx_vertex, const HalfEdgeIndex &idx_outgoing_half_edge)
Set the outgoing half-edge index to a given vertex.
Index used to access elements in the half-edge mesh.
void clear()
Clear all mesh elements and data.
Index used to access elements in the half-edge mesh.
InnerHalfEdgeAroundFaceCirculator getInnerHalfEdgeAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
Circulates clockwise around a face and returns an index to the terminating vertex of the inner half-e...
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).
Vertex & getVertex(const VertexIndex &idx_vertex)
Get the vertex for the given index.
bool isManifold(const VertexIndex &idx_vertex, boost::false_type) const
Check if the given vertex is manifold.
void setTerminatingVertexIndex(const HalfEdgeIndex &idx_half_edge, const VertexIndex &idx_terminating_vertex)
Set the terminating vertex index to a given half-edge.
HalfEdge getHalfEdge(const HalfEdgeIndex &idx_he) const
Get the half-edge for the given index.
Index used to access elements in the half-edge mesh.
void resizeData(DataCloudT &, const size_t n, const typename DataCloudT::value_type &data, boost::true_type) const
Resize the mesh data.
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.
FaceIndex addFaceImplBase(const VertexIndices &vertices, const FaceData &face_data, const EdgeData &edge_data, const HalfEdgeData &half_edge_data)
General implementation of addFace.
FaceIndex connectFace(const HalfEdgeIndices &inner_he, const FaceData &face_data)
Add a face to the mesh and connect it to the half-edges.
const PointT & front() const
VertexAroundFaceCirculator getVertexAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
bool isBoundary(const FaceIndex &idx_face, boost::true_type) const
Check if any vertex of the face lies on the boundary.
float distance(const PointT &p1, const PointT &p2)
HalfEdges::iterator HalfEdgeIterator
void reserveData(DataCloudT &cloud, const size_t n, boost::true_type) const
Reserve storage space for the mesh data.
Read / write the half-edge mesh from / to a file.
Circulates counter-clockwise around a vertex and returns an index to the outgoing half-edge (the targ...
HalfEdgeIndex getTargetIndex() const
Get the index to the outgoing half-edge.
void reserveVertices(const size_t n)
Reserve storage space n vertices.
OutgoingHalfEdgeAroundVertexCirculator getOutgoingHalfEdgeAroundVertexCirculator(const VertexIndex &idx_vertex) const
boost::shared_ptr< const Self > ConstPtr
Face getFace(const FaceIndex &idx_face) const
Get the face for the given index.
FaceAroundVertexCirculator getFaceAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
MeshTraitsT::FaceData FaceData
void deleteFace(const FaceIndex &idx_face, boost::true_type)
Manifold version of deleteFace.
void reserveData(DataCloudT &, const size_t, boost::false_type) const
Does nothing.
FaceIndex getOppositeFaceIndex(const HalfEdgeIndex &idx_half_edge) const
Get the face index to a given half-edge.
boost::integral_constant< bool, !boost::is_same< FaceData, pcl::geometry::NoData >::value > HasFaceData
void invalidate()
Invalidate the index.
std::vector< EdgeIndex > EdgeIndices
pcl::PointCloud< EdgeData > EdgeDataCloud
void clearData(DataCloudT &cloud, boost::true_type) const
Clear the mesh data.
bool setEdgeDataCloud(const EdgeDataCloud &edge_data_cloud)
Change the stored edge data.
OuterHalfEdgeAroundFaceCirculator getOuterHalfEdgeAroundFaceCirculator(const FaceIndex &idx_face) const
HalfEdgeDataCloud & getHalfEdgeDataCloud()
Get access to the stored half-edge data.
VertexIndex getTerminatingVertexIndex(const HalfEdgeIndex &idx_half_edge) const
Get the terminating vertex index to a given half-edge.
void resizeData(DataCloudT &, const size_t, const typename DataCloudT::value_type &, boost::false_type) const
Does nothing.
FaceIndex getFaceIndex(const HalfEdgeIndex &idx_half_edge) const
Get the face index to a given half-edge.
EdgeDataCloud & getEdgeDataCloud()
Get access to the stored edge data.
pcl::geometry::FaceAroundFaceCirculator< const Self > FaceAroundFaceCirculator
void incrementIf(IteratorT &it, boost::true_type) const
Increment the iterator.
pcl::geometry::OutgoingHalfEdgeAroundVertexCirculator< const Self > OutgoingHalfEdgeAroundVertexCirculator
int get() const
Get the index.
void assignIf(const ConstIteratorT, IteratorT, boost::false_type) const
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.
HalfEdgeIndex getTargetIndex() const
Get the index to the inner half-edge.
MeshTraitsT::VertexData VertexData
int get() const
Get the index.
boost::integral_constant< bool, !boost::is_same< EdgeData, pcl::geometry::NoData >::value > HasEdgeData
FaceIndex getFaceIndex(const FaceData &face_data) const
Get the index associated to the given face data.
bool isValid(const FaceIndex &idx_face) const
Check if the given face index is a valid index into the mesh.
HalfEdgeIndex getInnerHalfEdgeIndex(const FaceIndex &idx_face) const
Get the inner half-edge index to a given face.
void cleanUp()
Removes all mesh elements and data that are marked as deleted.
const PointT & back() const
bool isManifold(const VertexIndex &idx_vertex) const
Check if the given vertex is manifold.
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 isManifold() const
Check if the mesh is manifold.
OuterHalfEdgeAroundFaceCirculator getOuterHalfEdgeAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
pcl::geometry::Vertex Vertex
FaceIndex getTargetIndex() const
Get the index to the target face.
void addData(pcl::PointCloud< DataT > &cloud, const DataT &data, boost::true_type)
Add mesh data.
bool isDeleted(const FaceIndex &idx_face) const
Check if the given face is marked as deleted.
bool isManifold(const VertexIndex &, boost::true_type) const
Always manifold.
VertexDataCloud & getVertexDataCloud()
Get access to the stored vertex data.
void setFaceIndex(const HalfEdgeIndex &idx_half_edge, const FaceIndex &idx_face)
Set the face index to a given half-edge.
FaceAroundVertexCirculator getFaceAroundVertexCirculator(const VertexIndex &idx_vertex) const
A face is a closed loop of edges.
bool isEqualTopology(const Self &other) const
Check if the other mesh has the same topology as this mesh.
Circulates clockwise around a face and returns an index to the inner half-edge (the target).
void deleteFace(const FaceIndex &idx_face)
Mark the given face as deleted.
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.
bool isValid(const HalfEdgeIndex &idx_he) const
Check if the given half-edge index is a valid index into the mesh.
pcl::geometry::IncomingHalfEdgeAroundVertexCirculator< const Self > IncomingHalfEdgeAroundVertexCirculator
void markDeleted(const FaceIndex &idx_face)
Mark the given face as deleted.
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.
void connectNewOld(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b)
The first half-edge is new.
void resize(size_t n)
Resize the cloud.
Circulates clockwise around a face and returns an index to the outer half-edge (the target).
Circulates counter-clockwise around a vertex and returns an index to the face of the outgoing half-ed...
pcl::geometry::InnerHalfEdgeAroundFaceCirculator< const Self > InnerHalfEdgeAroundFaceCirculator
void incrementIf(IteratorT &, boost::false_type) const
Does nothing.
Base class for the half-edge mesh.
VertexAroundVertexCirculator getVertexAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
IncomingHalfEdgeAroundVertexCirculator getIncomingHalfEdgeAroundVertexCirculator(const HalfEdgeIndex &idx_incoming_half_edge) const
pcl::geometry::HalfEdge HalfEdge
VertexAroundFaceCirculator getVertexAroundFaceCirculator(const FaceIndex &idx_face) const
Vertices::const_iterator VertexConstIterator
BOOST_CONCEPT_ASSERT((boost::Convertible< IsManifold, bool >))
void deleteVertex(const VertexIndex &idx_vertex)
Mark the given vertex and all connected half-edges and faces as deleted.
pcl::PointCloud< FaceData > FaceDataCloud
void reserveEdges(const size_t n)
Reserve storage space for n edges (2*n storage space is reserved for the half-edges).
void markDeleted(const HalfEdgeIndex &idx_he)
Mark the given half-edge as deleted.
pcl::geometry::OuterHalfEdgeAroundFaceCirculator< const Self > OuterHalfEdgeAroundFaceCirculator
bool setFaceDataCloud(const FaceDataCloud &face_data_cloud)
Change the stored face data.
IndexContainerT remove(ElementContainerT &elements, DataContainerT &data_cloud)
Removes mesh elements and data that are marked as deleted from the container.
pcl::geometry::FaceIndex FaceIndex
std::vector< VertexIndex > VertexIndices
void setVertex(const VertexIndex &idx_vertex, const Vertex &vertex)
Set the vertex at the given index.
bool isValid() const
Returns true if the index is valid.
bool emptyEdges() const
Check if the edges are empty.
VertexIndex getTargetIndex() const
Get the index to the target vertex.
HalfEdgeIndex getPrevHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the previous half-edge index to a given half-edge.
bool setVertexDataCloud(const VertexDataCloud &vertex_data_cloud)
Change the stored vertex data.
VectorType::const_iterator const_iterator