43 #include <pcl/geometry/boost.h> 44 #include <pcl/geometry/eigen.h> 45 #include <pcl/geometry/mesh_circulators.h> 46 #include <pcl/geometry/mesh_indices.h> 47 #include <pcl/geometry/mesh_elements.h> 48 #include <pcl/geometry/mesh_traits.h> 51 #include <pcl/point_cloud.h> 54 #include <type_traits> 60 #ifdef PCL_GEOMETRY_MESH_BASE_TEST_DELETE_FACE_MANIFOLD_2 65 bool g_pcl_geometry_mesh_base_test_delete_face_manifold_2_success;
78 template <
class MeshT>
99 template <
class DerivedT,
class MeshTraitsT,
class MeshTagT>
105 using Ptr = shared_ptr<Self>;
118 static_assert (std::is_convertible<IsManifold, bool>::value,
"MeshTraitsT::IsManifold is not convertible to bool");
123 using HasVertexData = std::integral_constant <bool, !std::is_same <VertexData , pcl::geometry::NoData>::value>;
124 using HasHalfEdgeData = std::integral_constant <bool, !std::is_same <HalfEdgeData, pcl::geometry::NoData>::value>;
125 using HasEdgeData = std::integral_constant <bool, !std::is_same <EdgeData , pcl::geometry::NoData>::value>;
126 using HasFaceData = std::integral_constant <bool, !std::is_same <FaceData , pcl::geometry::NoData>::value>;
156 : vertex_data_cloud_ (),
157 half_edge_data_cloud_ (),
174 vertices_.push_back (
Vertex ());
194 return (static_cast <Derived*> (
this)->addFaceImpl (vertices, face_data, edge_data, half_edge_data));
203 assert (this->
isValid (idx_vertex));
204 if (this->
isDeleted (idx_vertex))
return;
206 delete_faces_vertex_.clear ();
215 }
while (++circ!=circ_end);
217 for (FaceIndices::const_iterator it = delete_faces_vertex_.begin (); it!=delete_faces_vertex_.end (); ++it)
229 assert (this->
isValid (idx_he));
246 assert (this->
isValid (idx_edge));
257 assert (this->
isValid (idx_face));
271 this->remove <Vertices, VertexDataCloud, VertexIndices, HasVertexData>
272 (vertices_, vertex_data_cloud_);
274 this->remove <HalfEdges, HalfEdgeDataCloud, HalfEdgeIndices, HasHalfEdgeData>
275 (half_edges_, half_edge_data_cloud_);
277 this->remove <Faces, FaceDataCloud, FaceIndices, HasFaceData>
278 (faces_, face_data_cloud_);
281 if (HasEdgeData::value)
283 auto it_ed_old = edge_data_cloud_.
begin ();
284 auto it_ed_new = edge_data_cloud_.
begin ();
286 for (
auto it_ind = new_half_edge_indices.cbegin (), it_ind_end = new_half_edge_indices.cend (); it_ind!=it_ind_end; it_ind+=2, ++it_ed_old)
288 if (it_ind->isValid ())
290 *it_ed_new++ = *it_ed_old;
297 for (
VertexIterator it = vertices_.begin (); it!=vertices_.end (); ++it)
299 if (it->idx_outgoing_half_edge_.isValid ())
301 it->idx_outgoing_half_edge_ = new_half_edge_indices [it->idx_outgoing_half_edge_.get ()];
305 for (
HalfEdgeIterator it = half_edges_.begin (); it!=half_edges_.end (); ++it)
307 it->idx_terminating_vertex_ = new_vertex_indices [it->idx_terminating_vertex_.get ()];
308 it->idx_next_half_edge_ = new_half_edge_indices [it->idx_next_half_edge_.get ()];
309 it->idx_prev_half_edge_ = new_half_edge_indices [it->idx_prev_half_edge_.get ()];
310 if (it->idx_face_.isValid ())
312 it->idx_face_ = new_face_indices [it->idx_face_.get ()];
316 for (
FaceIterator it = faces_.begin (); it!=faces_.end (); ++it)
318 it->idx_inner_half_edge_ = new_half_edge_indices [it->idx_inner_half_edge_.get ()];
330 assert (this->
isValid (idx_vertex));
331 return (this->
getVertex (idx_vertex).idx_outgoing_half_edge_);
338 assert (this->
isValid (idx_vertex));
350 assert (this->
isValid (idx_half_edge));
351 return (this->
getHalfEdge (idx_half_edge).idx_terminating_vertex_);
358 assert (this->
isValid (idx_half_edge));
366 assert (this->
isValid (idx_half_edge));
375 assert (this->
isValid (idx_half_edge));
376 return (this->
getHalfEdge (idx_half_edge).idx_next_half_edge_);
383 assert (this->
isValid (idx_half_edge));
384 return (this->
getHalfEdge (idx_half_edge).idx_prev_half_edge_);
391 assert (this->
isValid (idx_half_edge));
392 return (this->
getHalfEdge (idx_half_edge).idx_face_);
399 assert (this->
isValid (idx_half_edge));
411 assert (this->
isValid (idx_face));
412 return (this->
getFace (idx_face).idx_inner_half_edge_);
419 assert (this->
isValid (idx_face));
431 assert (this->
isValid (idx_vertex));
439 assert (this->
isValid (idx_outgoing_half_edge));
447 assert (this->
isValid (idx_vertex));
455 assert (this->
isValid (idx_outgoing_half_edge));
463 assert (this->
isValid (idx_vertex));
471 assert (this->
isValid (idx_incoming_half_edge));
479 assert (this->
isValid (idx_vertex));
487 assert (this->
isValid (idx_outgoing_half_edge));
495 assert (this->
isValid (idx_face));
503 assert (this->
isValid (idx_inner_half_edge));
511 assert (this->
isValid (idx_face));
519 assert (this->
isValid (idx_inner_half_edge));
527 assert (this->
isValid (idx_face));
535 assert (this->
isValid (idx_inner_half_edge));
543 assert (this->
isValid (idx_face));
551 assert (this->
isValid (idx_inner_half_edge));
588 for (std::size_t i=0; i<this->
sizeFaces (); ++i)
637 assert (this->
isValid (idx_vertex));
645 assert (this->
isValid (idx_he));
653 assert (this->
isValid (idx_edge));
662 assert (this->
isValid (idx_face));
674 assert (this->
isValid (idx_vertex));
686 assert (this->
isValid (idx_vertex));
687 if (this->
isIsolated (idx_vertex))
return (
true);
695 assert (this->
isValid (idx_he));
703 assert (this->
isValid (idx_edge));
711 template <
bool CheckVerticesT>
inline bool 714 assert (this->
isValid (idx_face));
715 return (this->
isBoundary (idx_face, std::integral_constant <bool, CheckVerticesT> ()));
722 assert (this->
isValid (idx_face));
723 return (this->
isBoundary (idx_face, std::true_type ()));
734 assert (this->
isValid (idx_vertex));
735 if (this->
isIsolated (idx_vertex))
return (
true);
754 return (vertices_.size ());
761 assert (half_edges_.size () % 2 == 0);
762 return (half_edges_.size ());
769 assert (half_edges_.size () % 2 == 0);
770 return (half_edges_.size () / 2);
777 return (faces_.size ());
795 return (vertices_.empty ());
802 return (half_edges_.empty ());
809 return (faces_.empty ());
820 vertices_.reserve (n);
828 half_edges_.reserve (2*n);
849 vertices_.resize (n);
859 half_edges_.resize (2*n);
881 half_edges_.clear ();
900 return (vertex_data_cloud_);
907 return (vertex_data_cloud_);
917 if (vertex_data_cloud.
size () == vertex_data_cloud_.
size ())
919 vertex_data_cloud_ = vertex_data_cloud;
935 return (half_edge_data_cloud_);
942 return (half_edge_data_cloud_);
952 if (half_edge_data_cloud.
size () == half_edge_data_cloud_.
size ())
954 half_edge_data_cloud_ = half_edge_data_cloud;
970 return (edge_data_cloud_);
977 return (edge_data_cloud_);
987 if (edge_data_cloud.
size () == edge_data_cloud_.
size ())
989 edge_data_cloud_ = edge_data_cloud;
1005 return (face_data_cloud_);
1012 return (face_data_cloud_);
1022 if (face_data_cloud.
size () == face_data_cloud_.
size ())
1024 face_data_cloud_ = face_data_cloud;
1040 if (HasVertexData::value)
1042 assert (&vertex_data >= &vertex_data_cloud_.
front () && &vertex_data <= &vertex_data_cloud_.
back ());
1052 if (HasHalfEdgeData::value)
1054 assert (&half_edge_data >= &half_edge_data_cloud_.
front () && &half_edge_data <= &half_edge_data_cloud_.
back ());
1064 if (HasEdgeData::value)
1066 assert (&edge_data >= &edge_data_cloud_.
front () && &edge_data <= &edge_data_cloud_.
back ());
1076 if (HasFaceData::value)
1078 assert (&face_data >= &face_data_cloud_.
front () && &face_data <= &face_data_cloud_.
back ());
1114 const int n =
static_cast<int> (vertices.size ());
1118 inner_he_.resize (n);
1119 free_he_.resize (n);
1121 make_adjacent_.resize (n);
1122 for (
int i=0; i<n; ++i)
1129 for (
int i=0; i<n; ++i)
1132 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 ()))
1139 if (!IsManifold::value)
1141 for (
int i=0; i<n; ++i)
1143 if (make_adjacent_ [i])
1145 this->
makeAdjacent (inner_he_ [i], inner_he_ [(i+1)%n], free_he_ [i]);
1151 for (
int i=0; i<n; ++i)
1155 inner_he_ [i] = this->
addEdge (vertices [i], vertices [(i+1)%n], half_edge_data, edge_data);
1160 for (
int i=0; i<n; ++i)
1163 if ( is_new_ [i] && is_new_ [j]) this->
connectNewNew (inner_he_ [i], inner_he_ [j], vertices [j],
IsManifold ());
1164 else if ( is_new_ [i] && !is_new_ [j]) this->
connectNewOld (inner_he_ [i], inner_he_ [j], vertices [j]);
1165 else if (!is_new_ [i] && is_new_ [j]) this->
connectOldNew (inner_he_ [i], inner_he_ [j], vertices [j]);
1168 return (this->
connectFace (inner_he_, face_data));
1188 half_edges_.push_back (
HalfEdge (idx_v_b));
1189 half_edges_.push_back (
HalfEdge (idx_v_a));
1195 return (
HalfEdgeIndex (static_cast <int> (half_edges_.size () - 2)));
1213 std::vector <bool>::reference is_new_ab,
1214 std::true_type )
const 1217 if (this->
isIsolated (idx_v_a))
return (
true);
1221 if (!this->
isBoundary (idx_he_ab))
return (
false);
1231 std::vector <bool>::reference is_new_ab,
1232 std::false_type )
const 1235 if (this->
isIsolated (idx_v_a))
return (
true);
1246 if (!this->
isBoundary (idx_he_ab))
return (
false);
1251 }
while (++circ!=circ_end);
1260 const bool is_new_ab,
1261 const bool is_new_bc,
1262 const bool is_isolated_b,
1263 std::vector <bool>::reference ,
1265 std::true_type )
const 1267 return !(is_new_ab && is_new_bc && !is_isolated_b);
1282 const bool is_new_ab,
1283 const bool is_new_bc,
1285 std::vector <bool>::reference make_adjacent_ab_bc,
1287 std::false_type )
const 1289 if (is_new_ab || is_new_bc)
1291 make_adjacent_ab_bc =
false;
1297 make_adjacent_ab_bc =
false;
1301 make_adjacent_ab_bc =
true;
1346 faces_.push_back (
Face (inner_he.back ()));
1351 for (
const auto &idx_half_edge : inner_he)
1393 this->
connectNewNew (idx_he_ab, idx_he_bc, idx_v_b, std::true_type ());
1459 if (idx_he_b_out == idx_he_bc)
1464 while (++circ!=circ_end)
1480 template <
class DataT>
1488 template <
class DataT>
1503 assert (this->
isValid (idx_face));
1504 delete_faces_face_.clear ();
1505 delete_faces_face_.push_back (idx_face);
1507 while (!delete_faces_face_.empty ())
1509 const FaceIndex idx_face_cur = delete_faces_face_.back ();
1510 delete_faces_face_.pop_back ();
1513 this->
deleteFace (idx_face_cur, std::false_type ());
1522 assert (this->
isValid (idx_face));
1527 is_boundary_.clear ();
1534 }
while (++circ != circ_end);
1535 assert (inner_he_.size () >= 3);
1537 const int n = static_cast <
int> (inner_he_.size ());
1540 if (IsManifold::value)
1542 for (
int i=0; i<n; ++i)
1545 this->
reconnect (inner_he_ [i], inner_he_ [j], is_boundary_ [i], is_boundary_ [j]);
1547 for (
int i=0; i<n; ++i)
1554 for (
int i=0; i<n; ++i)
1557 this->
reconnect (inner_he_ [i], inner_he_ [j], is_boundary_ [i], is_boundary_ [j]);
1573 const bool is_boundary_ba,
1574 const bool is_boundary_cb)
1580 if (is_boundary_ba && is_boundary_cb)
1584 if (idx_he_cb_next == idx_he_ba)
1597 else if (is_boundary_ba && !is_boundary_cb)
1605 else if (!is_boundary_ba && is_boundary_cb)
1632 delete_faces_face_.push_back (this->
getFaceIndex ((circ++).getTargetIndex ()));
1634 #ifdef PCL_GEOMETRY_MESH_BASE_TEST_DELETE_FACE_MANIFOLD_2 1641 pcl::geometry::g_pcl_geometry_mesh_base_test_delete_face_manifold_2_success =
false;
1674 assert (this->
isValid (idx_vertex));
1682 assert (this->
isValid (idx_he));
1690 assert (this->
isValid (idx_edge));
1699 assert (this->
isValid (idx_face));
1717 template <
class ElementContainerT,
class DataContainerT,
class IndexContainerT,
class HasDataT> IndexContainerT
1718 remove (ElementContainerT& elements, DataContainerT& data_cloud)
1720 using Index =
typename IndexContainerT::value_type;
1721 using Element =
typename ElementContainerT::value_type;
1723 if (HasDataT::value) assert (elements.size () == data_cloud.size ());
1724 else assert (data_cloud.empty ());
1726 IndexContainerT new_indices (elements.size (),
typename IndexContainerT::value_type ());
1727 Index ind_old (0), ind_new (0);
1729 typename ElementContainerT::const_iterator it_e_old = elements.begin ();
1730 typename ElementContainerT::iterator it_e_new = elements.begin ();
1732 typename DataContainerT::const_iterator it_d_old = data_cloud.begin ();
1733 typename DataContainerT::iterator it_d_new = data_cloud.begin ();
1735 typename IndexContainerT::iterator it_ind_new = new_indices.begin ();
1736 typename IndexContainerT::const_iterator it_ind_new_end = new_indices.end ();
1738 while (it_ind_new!=it_ind_new_end)
1742 *it_ind_new = ind_new++;
1745 *it_e_new++ = *it_e_old;
1746 this->
assignIf (it_d_old, it_d_new, HasDataT ());
1755 elements.resize (ind_new.get (), Element ());
1756 if (HasDataT::value)
1758 data_cloud.resize (ind_new.get ());
1760 else if (it_d_old != data_cloud.begin () || it_d_new != data_cloud.begin ())
1762 std::cerr <<
"TODO: Bug in MeshBase::remove!\n";
1764 exit (EXIT_FAILURE);
1767 return (new_indices);
1771 template <
class IteratorT>
inline void 1778 template <
class IteratorT>
inline void 1784 template <
class ConstIteratorT,
class IteratorT>
inline void 1785 assignIf (
const ConstIteratorT source, IteratorT target, std::true_type )
const 1791 template <
class ConstIteratorT,
class IteratorT>
inline void 1792 assignIf (
const ConstIteratorT , IteratorT , std::false_type )
const 1804 assert (this->
isValid (idx_vertex));
1805 this->
getVertex (idx_vertex).idx_outgoing_half_edge_ = idx_outgoing_half_edge;
1812 assert (this->
isValid (idx_half_edge));
1813 this->
getHalfEdge (idx_half_edge).idx_terminating_vertex_ = idx_terminating_vertex;
1820 assert (this->
isValid (idx_half_edge));
1821 this->
getHalfEdge (idx_half_edge).idx_next_half_edge_ = idx_next_half_edge;
1829 assert (this->
isValid (idx_half_edge));
1830 this->
getHalfEdge (idx_half_edge).idx_prev_half_edge_ = idx_prev_half_edge;
1837 assert (this->
isValid (idx_half_edge));
1838 this->
getHalfEdge (idx_half_edge).idx_face_ = idx_face;
1845 assert (this->
isValid (idx_face));
1846 this->
getFace (idx_face).idx_inner_half_edge_ = idx_inner_half_edge;
1866 }
while (++circ!=circ_end);
1884 }
while (++circ!=circ_end);
1903 if (!this->
isBoundary ((circ++).getTargetIndex ()))
return (
true);
1907 }
while (++circ != circ_end);
1935 template <
class DataCloudT>
inline void 1936 reserveData (DataCloudT& cloud,
const std::size_t n, std::true_type )
const 1942 template <
class DataCloudT>
inline void 1943 reserveData (DataCloudT& ,
const std::size_t , std::false_type )
const 1948 template <
class DataCloudT>
inline void 1949 resizeData (DataCloudT& ,
const std::size_t n,
const typename DataCloudT::value_type& data, std::true_type )
const 1951 data.resize (n, data);
1955 template <
class DataCloudT>
inline void 1956 resizeData (DataCloudT& ,
const std::size_t ,
const typename DataCloudT::value_type& , std::false_type )
const 1961 template <
class DataCloudT>
inline void 1968 template <
class DataCloudT>
inline void 1981 assert (this->
isValid (idx_vertex));
1982 return (vertices_ [idx_vertex.
get ()]);
1989 assert (this->
isValid (idx_vertex));
1990 return (vertices_ [idx_vertex.
get ()]);
1997 assert (this->
isValid (idx_vertex));
1998 vertices_ [idx_vertex.
get ()] = vertex;
2009 assert (this->
isValid (idx_he));
2010 return (half_edges_ [idx_he.
get ()]);
2017 assert (this->
isValid (idx_he));
2018 return (half_edges_ [idx_he.
get ()]);
2025 assert (this->
isValid (idx_he));
2026 half_edges_ [idx_he.
get ()] = half_edge;
2037 assert (this->
isValid (idx_face));
2038 return (faces_ [idx_face.
get ()]);
2045 assert (this->
isValid (idx_face));
2046 return (faces_ [idx_face.
get ()]);
2053 assert (this->
isValid (idx_face));
2054 faces_ [idx_face.
get ()] = face;
2093 std::vector <bool> is_new_;
2096 std::vector <bool> make_adjacent_;
2099 std::vector <bool> is_boundary_;
2109 template <
class MeshT>
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.
std::vector< Face > Faces
void setPrevHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge, const HalfEdgeIndex &idx_prev_half_edge)
Set the previous half-edge index to a given half-edge.
A vertex is a node in the mesh.
bool isBoundary(const FaceIndex &idx_face) const
Check if the given face lies on the boundary.
typename HalfEdges::iterator HalfEdgeIterator
IncomingHalfEdgeAroundVertexCirculator getIncomingHalfEdgeAroundVertexCirculator(const VertexIndex &idx_vertex) const
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.
Defines functions, macros and traits for allocating and using memory.
std::vector< EdgeIndex > EdgeIndices
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.
void invalidate()
Invalidate the index.
bool isValid(const EdgeIndex &idx_edge) const
Check if the given edge index is a valid index into the mesh.
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 &, std::true_type) const
Check if the face may be added (mesh does not become non-manifold).
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).
bool isManifold(std::false_type) const
Check if all vertices in the mesh are manifold.
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.
HalfEdgeIndex getOutgoingHalfEdgeIndex(const VertexIndex &idx_vertex) const
Get the outgoing half-edge index to a given vertex.
FaceDataCloud & getFaceDataCloud()
Get access to the stored face data.
bool checkTopology1(const VertexIndex &idx_v_a, const VertexIndex &idx_v_b, HalfEdgeIndex &idx_he_ab, std::vector< bool >::reference is_new_ab, std::false_type) const
Non manifold version of checkTopology1.
pcl::PointCloud< VertexData > VertexDataCloud
typename MeshTraitsT::VertexData VertexData
void deleteEdge(const EdgeIndex &idx_edge)
Mark the given edge (both half-edges) and the associated faces as deleted.
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.
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.
typename Faces::iterator FaceIterator
iterator begin() noexcept
bool empty() const
Check if the mesh is empty.
void resizeVertices(const std::size_t n, const VertexData &data=VertexData())
Resize the the vertices to n elements.
Circulates clockwise around a face and returns an index to the face of the outer half-edge (the targe...
void reconnectNBNB(const HalfEdgeIndex &idx_he_bc, const HalfEdgeIndex &idx_he_cb, const VertexIndex &idx_v_b, std::true_type)
Both edges are not on the boundary.
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...
typename MeshTraitsT::IsManifold IsManifold
HalfEdgeIndex getOuterHalfEdgeIndex(const FaceIndex &idx_face) const
Get the outer half-edge inex to a given face.
void clearData(DataCloudT &cloud, std::true_type) const
Clear the mesh data.
FaceAroundFaceCirculator getFaceAroundFaceCirculator(const FaceIndex &idx_face) const
VertexDataCloud getVertexDataCloud() const
Get the stored vertex data.
void addData(pcl::PointCloud< DataT > &cloud, const DataT &data, std::true_type)
Add mesh 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.
void resizeData(DataCloudT &, const std::size_t, const typename DataCloudT::value_type &, std::false_type) const
Does nothing.
void push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
bool isManifold(std::true_type) const
Always manifold.
VertexAroundVertexCirculator getVertexAroundVertexCirculator(const VertexIndex &idx_vertex) const
std::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 connectNewNew(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b, std::false_type)
Both half-edges are new (non-manifold version).
void deleteEdge(const HalfEdgeIndex &idx_he)
Mark the given half-edge, the opposite half-edge and the associated faces as deleted.
void connectOldOld(const HalfEdgeIndex &, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b, std::false_type)
Both half-edges are old (non-manifold version).
Vertex getVertex(const VertexIndex &idx_vertex) const
Get the vertex for the given index.
void resizeEdges(const std::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).
#define PCL_MAKE_ALIGNED_OPERATOR_NEW
Macro to signal a class requires a custom allocator.
EdgeIndex getEdgeIndex(const EdgeData &edge_data) const
Get the index associated to the given edge data.
Tag describing the type of the mesh.
EdgeDataCloud getEdgeDataCloud() const
Get the stored edge data.
bool isBoundary(const FaceIndex &idx_face) const
Check if the given face lies on the boundary.
std::vector< HalfEdge > HalfEdges
HalfEdgeIndex getTargetIndex() const
Get the index to the outer half-edge.
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.
typename MeshTraitsT::HalfEdgeData HalfEdgeData
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
typename MeshTraitsT::FaceData FaceData
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.
HalfEdgeIndex getTargetIndex() const
Get the index to the incoming half-edge.
int get() const
Get the index.
InnerHalfEdgeAroundFaceCirculator getInnerHalfEdgeAroundFaceCirculator(const FaceIndex &idx_face) const
std::size_t sizeEdges() const
Get the number of the edges.
HalfEdge & getHalfEdge(const HalfEdgeIndex &idx_he)
Get the half-edge for the given index.
void resizeFaces(const std::size_t n, const FaceData &data=FaceData())
Resize the faces to n elements.
Half-edge mesh that can only store quads.
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.
void reserveFaces(const std::size_t n)
Reserve storage space for n faces.
Circulates counter-clockwise around a vertex and returns an index to the terminating vertex of the ou...
void reserveData(DataCloudT &cloud, const std::size_t n, std::true_type) const
Reserve storage space for the mesh data.
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 deleteFace(const FaceIndex &idx_face, std::false_type)
Non-manifold version of deleteFace.
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.
void incrementIf(IteratorT &, std::false_type) const
Does nothing.
Index used to access elements in the half-edge mesh.
void clearData(DataCloudT &, std::false_type) const
Does nothing.
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...
Vertex & getVertex(const VertexIndex &idx_vertex)
Get the vertex for the given index.
std::vector< HalfEdgeIndex > HalfEdgeIndices
void assignIf(const ConstIteratorT source, IteratorT target, std::true_type) const
Assign the source iterator to the target iterator.
pcl::PointCloud< FaceData > FaceDataCloud
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 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
float distance(const PointT &p1, const PointT &p2)
typename Vertices::iterator VertexIterator
void reserveEdges(const std::size_t n)
Reserve storage space for n edges (2*n storage space is reserved for the half-edges).
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.
OutgoingHalfEdgeAroundVertexCirculator getOutgoingHalfEdgeAroundVertexCirculator(const VertexIndex &idx_vertex) const
bool isManifold(const VertexIndex &, std::true_type) const
Always manifold.
Face getFace(const FaceIndex &idx_face) const
Get the face for the given index.
FaceAroundVertexCirculator getFaceAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
void resize(std::size_t count)
Resizes the container to contain count elements.
FaceIndex getOppositeFaceIndex(const HalfEdgeIndex &idx_half_edge) const
Get the face index to a given half-edge.
void invalidate()
Invalidate the index.
pcl::PointCloud< HalfEdgeData > HalfEdgeDataCloud
void deleteFace(const FaceIndex &idx_face, std::true_type)
Manifold version of deleteFace.
std::integral_constant< bool, !std::is_same< FaceData, pcl::geometry::NoData >::value > HasFaceData
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.
std::integral_constant< bool, !std::is_same< VertexData, pcl::geometry::NoData >::value > HasVertexData
void reconnectNBNB(const HalfEdgeIndex &idx_he_bc, const HalfEdgeIndex &, const VertexIndex &idx_v_b, std::false_type)
Both edges are not on the boundary.
bool isManifold(const VertexIndex &idx_vertex, std::false_type) const
Check if the given vertex is manifold.
VertexIndex getTerminatingVertexIndex(const HalfEdgeIndex &idx_half_edge) const
Get the terminating vertex index to a given half-edge.
FaceIndex getFaceIndex(const HalfEdgeIndex &idx_half_edge) const
Get the face index to a given half-edge.
bool isBoundary(const FaceIndex &idx_face, std::false_type) const
Check if any edge of the face lies on the boundary.
std::vector< Vertex > Vertices
EdgeDataCloud & getEdgeDataCloud()
Get access to the stored edge data.
int get() const
Get the index.
void resizeData(DataCloudT &, const std::size_t n, const typename DataCloudT::value_type &data, std::true_type) const
Resize the mesh data.
HalfEdgeIndex getTargetIndex() const
Get the index to the inner half-edge.
int get() const
Get the index.
FaceIndex getFaceIndex(const FaceData &face_data) const
Get the index associated to the given face data.
std::integral_constant< bool, !std::is_same< HalfEdgeData, pcl::geometry::NoData >::value > HasHalfEdgeData
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.
typename MeshTraitsT::EdgeData EdgeData
typename Vertices::const_iterator VertexConstIterator
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.
std::size_t sizeHalfEdges() const
Get the number of the half-edges.
std::integral_constant< bool, !std::is_same< EdgeData, pcl::geometry::NoData >::value > HasEdgeData
std::vector< FaceIndex > FaceIndices
bool isManifold() const
Check if the mesh is manifold.
OuterHalfEdgeAroundFaceCirculator getOuterHalfEdgeAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
FaceIndex getTargetIndex() const
Get the index to the target face.
bool isDeleted(const FaceIndex &idx_face) const
Check if the given face is marked as deleted.
void addData(pcl::PointCloud< DataT > &, const DataT &, std::false_type)
Does nothing.
VertexDataCloud & getVertexDataCloud()
Get access to the stored vertex data.
typename HalfEdges::const_iterator HalfEdgeConstIterator
shared_ptr< const Self > ConstPtr
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)...
pcl::PointCloud< EdgeData > EdgeDataCloud
void deleteFace(const FaceIndex &idx_face)
Mark the given face as deleted.
void connectOldOld(const HalfEdgeIndex &, const HalfEdgeIndex &, const VertexIndex &, std::true_type)
Both half-edges are old (manifold version).
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.
void markDeleted(const FaceIndex &idx_face)
Mark the given face as deleted.
void connectNewOld(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b)
The first half-edge is new.
std::size_t sizeFaces() const
Get the number of the faces.
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...
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
VertexAroundFaceCirculator getVertexAroundFaceCirculator(const FaceIndex &idx_face) const
void reserveVertices(const std::size_t n)
Reserve storage space n vertices.
typename Faces::const_iterator FaceConstIterator
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, std::false_type) const
Check if the half-edge bc is the next half-edge of ab.
bool checkTopology1(const VertexIndex &idx_v_a, const VertexIndex &idx_v_b, HalfEdgeIndex &idx_he_ab, std::vector< bool >::reference is_new_ab, std::true_type) const
Check if the edge between the two vertices can be added.
void deleteVertex(const VertexIndex &idx_vertex)
Mark the given vertex and all connected half-edges and faces as deleted.
void reserveData(DataCloudT &, const std::size_t, std::false_type) const
Does nothing.
void markDeleted(const HalfEdgeIndex &idx_he)
Mark the given half-edge as deleted.
void connectNewNew(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b, std::true_type)
Both half-edges are new (manifold version).
bool setFaceDataCloud(const FaceDataCloud &face_data_cloud)
Change the stored face data.
std::vector< VertexIndex > VertexIndices
bool isBoundary(const FaceIndex &idx_face, std::true_type) const
Check if any vertex of the face lies on the boundary.
void incrementIf(IteratorT &it, std::true_type) const
Increment the iterator.
Defines all the PCL and non-PCL macros used.
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.
void assignIf(const ConstIteratorT, IteratorT, std::false_type) const
Does nothing.
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.