Point Cloud Library (PCL)
1.10.0
|
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>
50 #include <pcl/point_cloud.h>
53 #include <type_traits>
59 #ifdef PCL_GEOMETRY_MESH_BASE_TEST_DELETE_FACE_MANIFOLD_2
64 bool g_pcl_geometry_mesh_base_test_delete_face_manifold_2_success;
77 template <
class MeshT>
98 template <
class DerivedT,
class MeshTraitsT,
class MeshTagT>
117 static_assert (std::is_convertible<IsManifold, bool>::value,
"MeshTraitsT::IsManifold is not convertible to bool");
122 using HasVertexData = std::integral_constant <bool, !std::is_same <VertexData , pcl::geometry::NoData>::value>;
123 using HasHalfEdgeData = std::integral_constant <bool, !std::is_same <HalfEdgeData, pcl::geometry::NoData>::value>;
124 using HasEdgeData = std::integral_constant <bool, !std::is_same <EdgeData , pcl::geometry::NoData>::value>;
125 using HasFaceData = std::integral_constant <bool, !std::is_same <FaceData , pcl::geometry::NoData>::value>;
155 : vertex_data_cloud_ (),
156 half_edge_data_cloud_ (),
173 vertices_.push_back (
Vertex ());
193 return (static_cast <Derived*> (
this)->addFaceImpl (vertices, face_data, edge_data, half_edge_data));
202 assert (this->
isValid (idx_vertex));
203 if (this->
isDeleted (idx_vertex))
return;
205 delete_faces_vertex_.clear ();
214 }
while (++circ!=circ_end);
216 for (FaceIndices::const_iterator it = delete_faces_vertex_.begin (); it!=delete_faces_vertex_.end (); ++it)
228 assert (this->
isValid (idx_he));
245 assert (this->
isValid (idx_edge));
256 assert (this->
isValid (idx_face));
270 this->remove <Vertices, VertexDataCloud, VertexIndices, HasVertexData>
271 (vertices_, vertex_data_cloud_);
273 this->remove <HalfEdges, HalfEdgeDataCloud, HalfEdgeIndices, HasHalfEdgeData>
274 (half_edges_, half_edge_data_cloud_);
276 this->remove <Faces, FaceDataCloud, FaceIndices, HasFaceData>
277 (faces_, face_data_cloud_);
280 if (HasEdgeData::value)
282 auto it_ed_old = edge_data_cloud_.
begin ();
283 auto it_ed_new = edge_data_cloud_.
begin ();
285 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)
287 if (it_ind->isValid ())
289 *it_ed_new++ = *it_ed_old;
296 for (
VertexIterator it = vertices_.begin (); it!=vertices_.end (); ++it)
298 if (it->idx_outgoing_half_edge_.isValid ())
300 it->idx_outgoing_half_edge_ = new_half_edge_indices [it->idx_outgoing_half_edge_.get ()];
304 for (
HalfEdgeIterator it = half_edges_.begin (); it!=half_edges_.end (); ++it)
306 it->idx_terminating_vertex_ = new_vertex_indices [it->idx_terminating_vertex_.get ()];
307 it->idx_next_half_edge_ = new_half_edge_indices [it->idx_next_half_edge_.get ()];
308 it->idx_prev_half_edge_ = new_half_edge_indices [it->idx_prev_half_edge_.get ()];
309 if (it->idx_face_.isValid ())
311 it->idx_face_ = new_face_indices [it->idx_face_.get ()];
315 for (
FaceIterator it = faces_.begin (); it!=faces_.end (); ++it)
317 it->idx_inner_half_edge_ = new_half_edge_indices [it->idx_inner_half_edge_.get ()];
329 assert (this->
isValid (idx_vertex));
330 return (this->
getVertex (idx_vertex).idx_outgoing_half_edge_);
337 assert (this->
isValid (idx_vertex));
349 assert (this->
isValid (idx_half_edge));
350 return (this->
getHalfEdge (idx_half_edge).idx_terminating_vertex_);
357 assert (this->
isValid (idx_half_edge));
365 assert (this->
isValid (idx_half_edge));
374 assert (this->
isValid (idx_half_edge));
375 return (this->
getHalfEdge (idx_half_edge).idx_next_half_edge_);
382 assert (this->
isValid (idx_half_edge));
383 return (this->
getHalfEdge (idx_half_edge).idx_prev_half_edge_);
390 assert (this->
isValid (idx_half_edge));
391 return (this->
getHalfEdge (idx_half_edge).idx_face_);
398 assert (this->
isValid (idx_half_edge));
410 assert (this->
isValid (idx_face));
411 return (this->
getFace (idx_face).idx_inner_half_edge_);
418 assert (this->
isValid (idx_face));
430 assert (this->
isValid (idx_vertex));
438 assert (this->
isValid (idx_outgoing_half_edge));
446 assert (this->
isValid (idx_vertex));
454 assert (this->
isValid (idx_outgoing_half_edge));
462 assert (this->
isValid (idx_vertex));
470 assert (this->
isValid (idx_incoming_half_edge));
478 assert (this->
isValid (idx_vertex));
486 assert (this->
isValid (idx_outgoing_half_edge));
494 assert (this->
isValid (idx_face));
502 assert (this->
isValid (idx_inner_half_edge));
510 assert (this->
isValid (idx_face));
518 assert (this->
isValid (idx_inner_half_edge));
526 assert (this->
isValid (idx_face));
534 assert (this->
isValid (idx_inner_half_edge));
542 assert (this->
isValid (idx_face));
550 assert (this->
isValid (idx_inner_half_edge));
587 for (std::size_t i=0; i<this->
sizeFaces (); ++i)
636 assert (this->
isValid (idx_vertex));
644 assert (this->
isValid (idx_he));
652 assert (this->
isValid (idx_edge));
661 assert (this->
isValid (idx_face));
673 assert (this->
isValid (idx_vertex));
685 assert (this->
isValid (idx_vertex));
686 if (this->
isIsolated (idx_vertex))
return (
true);
694 assert (this->
isValid (idx_he));
702 assert (this->
isValid (idx_edge));
710 template <
bool CheckVerticesT>
inline bool
713 assert (this->
isValid (idx_face));
714 return (this->
isBoundary (idx_face, std::integral_constant <bool, CheckVerticesT> ()));
721 assert (this->
isValid (idx_face));
722 return (this->
isBoundary (idx_face, std::true_type ()));
733 assert (this->
isValid (idx_vertex));
734 if (this->
isIsolated (idx_vertex))
return (
true);
753 return (vertices_.size ());
760 assert (half_edges_.size () % 2 == 0);
761 return (half_edges_.size ());
768 assert (half_edges_.size () % 2 == 0);
769 return (half_edges_.size () / 2);
776 return (faces_.size ());
794 return (vertices_.empty ());
801 return (half_edges_.empty ());
808 return (faces_.empty ());
819 vertices_.reserve (n);
827 half_edges_.reserve (2*n);
848 vertices_.resize (n);
858 half_edges_.resize (2*n);
880 half_edges_.clear ();
899 return (vertex_data_cloud_);
906 return (vertex_data_cloud_);
916 if (vertex_data_cloud.
size () == vertex_data_cloud_.
size ())
918 vertex_data_cloud_ = vertex_data_cloud;
934 return (half_edge_data_cloud_);
941 return (half_edge_data_cloud_);
951 if (half_edge_data_cloud.
size () == half_edge_data_cloud_.
size ())
953 half_edge_data_cloud_ = half_edge_data_cloud;
969 return (edge_data_cloud_);
976 return (edge_data_cloud_);
986 if (edge_data_cloud.
size () == edge_data_cloud_.
size ())
988 edge_data_cloud_ = edge_data_cloud;
1004 return (face_data_cloud_);
1011 return (face_data_cloud_);
1021 if (face_data_cloud.
size () == face_data_cloud_.
size ())
1023 face_data_cloud_ = face_data_cloud;
1039 if (HasVertexData::value)
1041 assert (&vertex_data >= &vertex_data_cloud_.
front () && &vertex_data <= &vertex_data_cloud_.
back ());
1051 if (HasHalfEdgeData::value)
1053 assert (&half_edge_data >= &half_edge_data_cloud_.
front () && &half_edge_data <= &half_edge_data_cloud_.
back ());
1063 if (HasEdgeData::value)
1065 assert (&edge_data >= &edge_data_cloud_.
front () && &edge_data <= &edge_data_cloud_.
back ());
1075 if (HasFaceData::value)
1077 assert (&face_data >= &face_data_cloud_.
front () && &face_data <= &face_data_cloud_.
back ());
1113 const int n = static_cast<int> (vertices.size ());
1117 inner_he_.resize (n);
1118 free_he_.resize (n);
1120 make_adjacent_.resize (n);
1121 for (
int i=0; i<n; ++i)
1128 for (
int i=0; i<n; ++i)
1131 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 ()))
1138 if (!IsManifold::value)
1140 for (
int i=0; i<n; ++i)
1142 if (make_adjacent_ [i])
1144 this->
makeAdjacent (inner_he_ [i], inner_he_ [(i+1)%n], free_he_ [i]);
1150 for (
int i=0; i<n; ++i)
1154 inner_he_ [i] = this->
addEdge (vertices [i], vertices [(i+1)%n], half_edge_data, edge_data);
1159 for (
int i=0; i<n; ++i)
1162 if ( is_new_ [i] && is_new_ [j]) this->
connectNewNew (inner_he_ [i], inner_he_ [j], vertices [j],
IsManifold ());
1163 else if ( is_new_ [i] && !is_new_ [j]) this->
connectNewOld (inner_he_ [i], inner_he_ [j], vertices [j]);
1164 else if (!is_new_ [i] && is_new_ [j]) this->
connectOldNew (inner_he_ [i], inner_he_ [j], vertices [j]);
1167 return (this->
connectFace (inner_he_, face_data));
1187 half_edges_.push_back (
HalfEdge (idx_v_b));
1188 half_edges_.push_back (
HalfEdge (idx_v_a));
1194 return (
HalfEdgeIndex (static_cast <int> (half_edges_.size () - 2)));
1212 std::vector <bool>::reference is_new_ab,
1213 std::true_type )
const
1216 if (this->
isIsolated (idx_v_a))
return (
true);
1220 if (!this->
isBoundary (idx_he_ab))
return (
false);
1230 std::vector <bool>::reference is_new_ab,
1231 std::false_type )
const
1234 if (this->
isIsolated (idx_v_a))
return (
true);
1245 if (!this->
isBoundary (idx_he_ab))
return (
false);
1250 }
while (++circ!=circ_end);
1259 const bool is_new_ab,
1260 const bool is_new_bc,
1261 const bool is_isolated_b,
1262 std::vector <bool>::reference ,
1264 std::true_type )
const
1266 return !(is_new_ab && is_new_bc && !is_isolated_b);
1281 const bool is_new_ab,
1282 const bool is_new_bc,
1284 std::vector <bool>::reference make_adjacent_ab_bc,
1286 std::false_type )
const
1288 if (is_new_ab || is_new_bc)
1290 make_adjacent_ab_bc =
false;
1296 make_adjacent_ab_bc =
false;
1300 make_adjacent_ab_bc =
true;
1345 faces_.push_back (
Face (inner_he.back ()));
1350 for (
const auto &idx_half_edge : inner_he)
1392 this->
connectNewNew (idx_he_ab, idx_he_bc, idx_v_b, std::true_type ());
1458 if (idx_he_b_out == idx_he_bc)
1463 while (++circ!=circ_end)
1479 template <
class DataT>
1487 template <
class DataT>
1502 assert (this->
isValid (idx_face));
1503 delete_faces_face_.clear ();
1504 delete_faces_face_.push_back (idx_face);
1506 while (!delete_faces_face_.empty ())
1508 const FaceIndex idx_face_cur = delete_faces_face_.back ();
1509 delete_faces_face_.pop_back ();
1512 this->
deleteFace (idx_face_cur, std::false_type ());
1521 assert (this->
isValid (idx_face));
1526 is_boundary_.clear ();
1533 }
while (++circ != circ_end);
1534 assert (inner_he_.size () >= 3);
1536 const int n = static_cast <int> (inner_he_.size ());
1539 if (IsManifold::value)
1541 for (
int i=0; i<n; ++i)
1544 this->
reconnect (inner_he_ [i], inner_he_ [j], is_boundary_ [i], is_boundary_ [j]);
1546 for (
int i=0; i<n; ++i)
1553 for (
int i=0; i<n; ++i)
1556 this->
reconnect (inner_he_ [i], inner_he_ [j], is_boundary_ [i], is_boundary_ [j]);
1572 const bool is_boundary_ba,
1573 const bool is_boundary_cb)
1579 if (is_boundary_ba && is_boundary_cb)
1583 if (idx_he_cb_next == idx_he_ba)
1596 else if (is_boundary_ba && !is_boundary_cb)
1604 else if (!is_boundary_ba && is_boundary_cb)
1631 delete_faces_face_.push_back (this->
getFaceIndex ((circ++).getTargetIndex ()));
1633 #ifdef PCL_GEOMETRY_MESH_BASE_TEST_DELETE_FACE_MANIFOLD_2
1640 pcl::geometry::g_pcl_geometry_mesh_base_test_delete_face_manifold_2_success =
false;
1673 assert (this->
isValid (idx_vertex));
1681 assert (this->
isValid (idx_he));
1689 assert (this->
isValid (idx_edge));
1698 assert (this->
isValid (idx_face));
1716 template <
class ElementContainerT,
class DataContainerT,
class IndexContainerT,
class HasDataT> IndexContainerT
1717 remove (ElementContainerT& elements, DataContainerT& data_cloud)
1719 using Index =
typename IndexContainerT::value_type;
1720 using Element =
typename ElementContainerT::value_type;
1722 if (HasDataT::value) assert (elements.size () == data_cloud.size ());
1723 else assert (data_cloud.empty ());
1725 IndexContainerT new_indices (elements.size (),
typename IndexContainerT::value_type ());
1726 Index ind_old (0), ind_new (0);
1728 typename ElementContainerT::const_iterator it_e_old = elements.begin ();
1729 typename ElementContainerT::iterator it_e_new = elements.begin ();
1731 typename DataContainerT::const_iterator it_d_old = data_cloud.begin ();
1732 typename DataContainerT::iterator it_d_new = data_cloud.begin ();
1734 typename IndexContainerT::iterator it_ind_new = new_indices.begin ();
1735 typename IndexContainerT::const_iterator it_ind_new_end = new_indices.end ();
1737 while (it_ind_new!=it_ind_new_end)
1741 *it_ind_new = ind_new++;
1744 *it_e_new++ = *it_e_old;
1745 this->
assignIf (it_d_old, it_d_new, HasDataT ());
1754 elements.resize (ind_new.get (), Element ());
1755 if (HasDataT::value)
1757 data_cloud.resize (ind_new.get ());
1759 else if (it_d_old != data_cloud.begin () || it_d_new != data_cloud.begin ())
1761 std::cerr <<
"TODO: Bug in MeshBase::remove!\n";
1763 exit (EXIT_FAILURE);
1766 return (new_indices);
1770 template <
class IteratorT>
inline void
1777 template <
class IteratorT>
inline void
1783 template <
class ConstIteratorT,
class IteratorT>
inline void
1784 assignIf (
const ConstIteratorT source, IteratorT target, std::true_type )
const
1790 template <
class ConstIteratorT,
class IteratorT>
inline void
1791 assignIf (
const ConstIteratorT , IteratorT , std::false_type )
const
1803 assert (this->
isValid (idx_vertex));
1804 this->
getVertex (idx_vertex).idx_outgoing_half_edge_ = idx_outgoing_half_edge;
1811 assert (this->
isValid (idx_half_edge));
1812 this->
getHalfEdge (idx_half_edge).idx_terminating_vertex_ = idx_terminating_vertex;
1819 assert (this->
isValid (idx_half_edge));
1820 this->
getHalfEdge (idx_half_edge).idx_next_half_edge_ = idx_next_half_edge;
1828 assert (this->
isValid (idx_half_edge));
1829 this->
getHalfEdge (idx_half_edge).idx_prev_half_edge_ = idx_prev_half_edge;
1836 assert (this->
isValid (idx_half_edge));
1837 this->
getHalfEdge (idx_half_edge).idx_face_ = idx_face;
1844 assert (this->
isValid (idx_face));
1845 this->
getFace (idx_face).idx_inner_half_edge_ = idx_inner_half_edge;
1865 }
while (++circ!=circ_end);
1883 }
while (++circ!=circ_end);
1902 if (!this->
isBoundary ((circ++).getTargetIndex ()))
return (
true);
1906 }
while (++circ != circ_end);
1934 template <
class DataCloudT>
inline void
1935 reserveData (DataCloudT& cloud,
const std::size_t n, std::true_type )
const
1941 template <
class DataCloudT>
inline void
1942 reserveData (DataCloudT& ,
const std::size_t , std::false_type )
const
1947 template <
class DataCloudT>
inline void
1948 resizeData (DataCloudT& ,
const std::size_t n,
const typename DataCloudT::value_type& data, std::true_type )
const
1950 data.resize (n, data);
1954 template <
class DataCloudT>
inline void
1955 resizeData (DataCloudT& ,
const std::size_t ,
const typename DataCloudT::value_type& , std::false_type )
const
1960 template <
class DataCloudT>
inline void
1967 template <
class DataCloudT>
inline void
1980 assert (this->
isValid (idx_vertex));
1981 return (vertices_ [idx_vertex.
get ()]);
1988 assert (this->
isValid (idx_vertex));
1989 return (vertices_ [idx_vertex.
get ()]);
1996 assert (this->
isValid (idx_vertex));
1997 vertices_ [idx_vertex.
get ()] = vertex;
2008 assert (this->
isValid (idx_he));
2009 return (half_edges_ [idx_he.
get ()]);
2016 assert (this->
isValid (idx_he));
2017 return (half_edges_ [idx_he.
get ()]);
2024 assert (this->
isValid (idx_he));
2025 half_edges_ [idx_he.
get ()] = half_edge;
2036 assert (this->
isValid (idx_face));
2037 return (faces_ [idx_face.
get ()]);
2044 assert (this->
isValid (idx_face));
2045 return (faces_ [idx_face.
get ()]);
2052 assert (this->
isValid (idx_face));
2053 faces_ [idx_face.
get ()] = face;
2092 std::vector <bool> is_new_;
2095 std::vector <bool> make_adjacent_;
2098 std::vector <bool> is_boundary_;
2108 template <
class MeshT>
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 emptyEdges() const
Check if the edges are empty.
void setVertex(const VertexIndex &idx_vertex, const Vertex &vertex)
Set the vertex at the given index.
Defines all the PCL and non-PCL macros used.
bool isBoundary(const HalfEdgeIndex &idx_he) const
Check if the given half-edge lies on the bounddary.
This file defines compatibility wrappers for low level I/O functions.
void connectOldNew(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b)
The second half-edge is new.
An edge is a connection between two vertices.
HalfEdgeIndex getPrevHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the previous half-edge index to a given half-edge.
bool isDeleted(const VertexIndex &idx_vertex) const
Check if the given vertex is marked as deleted.
bool setVertexDataCloud(const VertexDataCloud &vertex_data_cloud)
Change the stored vertex data.
HalfEdgeIndex getOppositeHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the opposite half-edge index to a given half-edge.
float distance(const PointT &p1, const PointT &p2)
HalfEdgeIndex getOutgoingHalfEdgeIndex(const VertexIndex &idx_vertex) const
Get the outgoing half-edge index to a given vertex.
typename HalfEdges::iterator HalfEdgeIterator
void setPrevHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge, const HalfEdgeIndex &idx_prev_half_edge)
Set the previous half-edge index to a given half-edge.
IncomingHalfEdgeAroundVertexCirculator getIncomingHalfEdgeAroundVertexCirculator(const VertexIndex &idx_vertex) const
FaceDataCloud getFaceDataCloud() const
Get the stored face data.
void deleteEdge(const EdgeIndex &idx_edge)
Mark the given edge (both half-edges) and the associated faces as deleted.
bool empty() const
Check if the mesh is empty.
std::vector< EdgeIndex > EdgeIndices
bool isValid(const EdgeIndex &idx_edge) const
Check if the given edge index is a valid index into the mesh.
void resizeVertices(const std::size_t n, const VertexData &data=VertexData())
Resize the the vertices to n elements.
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).
OutgoingHalfEdgeAroundVertexCirculator getOutgoingHalfEdgeAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
HalfEdgeIndex getTargetIndex() const
Get the index to the outgoing half-edge.
bool isIsolated(const VertexIndex &idx_vertex) const
Check if the given vertex is isolated (not connected to other elements).
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.
void addData(pcl::PointCloud< DataT > &cloud, const DataT &data, std::true_type)
Add mesh data.
bool isManifold(std::false_type) const
Check if all vertices in the mesh are manifold.
FaceAroundFaceCirculator getFaceAroundFaceCirculator(const FaceIndex &idx_face) const
void resize(std::size_t n)
Resize the cloud.
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.
VertexDataCloud getVertexDataCloud() const
Get the stored vertex data.
FaceDataCloud & getFaceDataCloud()
Get access to the stored face data.
void clearData(DataCloudT &cloud, std::true_type) const
Clear the mesh data.
bool emptyVertices() const
Check if the vertices are empty.
Circulates clockwise around a face and returns an index to the inner half-edge (the target).
pcl::PointCloud< VertexData > VertexDataCloud
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.
HalfEdgeIndex getNextHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the next half-edge index to a given half-edge.
bool setHalfEdgeDataCloud(const HalfEdgeDataCloud &half_edge_data_cloud)
Change the stored half-edge data.
A vertex is a node in the mesh.
VertexAroundVertexCirculator getVertexAroundVertexCirculator(const VertexIndex &idx_vertex) const
typename MeshTraitsT::VertexData VertexData
void setHalfEdge(const HalfEdgeIndex &idx_he, const HalfEdge &half_edge)
Set the half-edge at the given index.
void resizeData(DataCloudT &, const std::size_t, const typename DataCloudT::value_type &, std::false_type) const
Does nothing.
std::size_t sizeVertices() const
Get the number of the vertices.
Circulates clockwise around a face and returns an index to the outer half-edge (the target).
void deleteEdge(const HalfEdgeIndex &idx_he)
Mark the given half-edge, the opposite half-edge and the associated faces as deleted.
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 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.
typename Faces::iterator FaceIterator
typename MeshTraitsT::IsManifold IsManifold
Circulates counter-clockwise around a vertex and returns an index to the incoming half-edge (the targ...
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 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.
HalfEdgeIndex getOuterHalfEdgeIndex(const FaceIndex &idx_face) const
Get the outer half-edge inex to a given face.
EdgeIndex getEdgeIndex(const EdgeData &edge_data) const
Get the index associated to the given edge data.
EdgeDataCloud getEdgeDataCloud() const
Get the stored edge data.
std::vector< HalfEdge > HalfEdges
typename MeshTraitsT::FaceData FaceData
bool isManifold(std::true_type) const
Always manifold.
bool isValid(const VertexIndex &idx_vertex) const
Check if the given vertex index is a valid index into the mesh.
FaceAroundFaceCirculator getFaceAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
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).
HalfEdgeDataCloud getHalfEdgeDataCloud() const
Get the stored half-edge data.
bool isDeleted(const HalfEdgeIndex &idx_he) const
Check if the given half-edge is marked as deleted.
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).
void resizeFaces(const std::size_t n, const FaceData &data=FaceData())
Resize the faces to n elements.
Circulates clockwise around a face and returns an index to the terminating vertex of the inner half-e...
HalfEdge & getHalfEdge(const HalfEdgeIndex &idx_he)
Get the half-edge for the given index.
bool isBoundary(const FaceIndex &idx_face) const
Check if the given face lies on the boundary.
void reserveFaces(const std::size_t n)
Reserve storage space for n faces.
HalfEdgeIndex getHalfEdgeIndex(const HalfEdgeData &half_edge_data) const
Get the index associated to the given half-edge data.
Index used to access elements in the half-edge mesh.
Circulates clockwise around a face and returns an index to the face of the outer half-edge (the targe...
void deleteFace(const FaceIndex &idx_face, std::false_type)
Non-manifold version of deleteFace.
Index used to access elements in the half-edge mesh.
void setOutgoingHalfEdgeIndex(const VertexIndex &idx_vertex, const HalfEdgeIndex &idx_outgoing_half_edge)
Set the outgoing half-edge index to a given vertex.
typename MeshTraitsT::HalfEdgeData HalfEdgeData
Circulates counter-clockwise around a vertex and returns an index to the outgoing half-edge (the targ...
VertexIndex addVertex(const VertexData &vertex_data=VertexData())
Add a vertex to the mesh.
void incrementIf(IteratorT &, std::false_type) const
Does nothing.
void markDeleted(const EdgeIndex &idx_edge)
Mark the given edge (both half-edges) as deleted.
InnerHalfEdgeAroundFaceCirculator getInnerHalfEdgeAroundFaceCirculator(const FaceIndex &idx_face) const
std::vector< HalfEdgeIndex > HalfEdgeIndices
std::size_t sizeEdges() const
Get the number of the edges.
void setTerminatingVertexIndex(const HalfEdgeIndex &idx_half_edge, const VertexIndex &idx_terminating_vertex)
Set the terminating vertex index to a given half-edge.
HalfEdgeIndex getTargetIndex() const
Get the index to the outer half-edge.
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.
VertexIndex getTargetIndex() const
Get the index to the target vertex.
Face & getFace(const FaceIndex &idx_face)
Get the face for the given index.
bool isBoundary(const VertexIndex &idx_vertex) const
Check if the given vertex lies on the boundary.
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.
A face is a closed loop of edges.
FaceIndex connectFace(const HalfEdgeIndices &inner_he, const FaceData &face_data)
Add a face to the mesh and connect it to the half-edges.
void reserveData(DataCloudT &cloud, const std::size_t n, std::true_type) const
Reserve storage space for the mesh data.
void setFace(const FaceIndex &idx_face, const Face &face)
Set the face at the given index.
void clear()
Clear all mesh elements and data.
void clearData(DataCloudT &, std::false_type) const
Does nothing.
InnerHalfEdgeAroundFaceCirculator getInnerHalfEdgeAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
bool isManifold(const VertexIndex &, std::true_type) const
Always manifold.
const PointT & back() const
Vertex & getVertex(const VertexIndex &idx_vertex)
Get the vertex for the given index.
Face getFace(const FaceIndex &idx_face) const
Get the face for the given index.
pcl::PointCloud< FaceData > FaceDataCloud
void assignIf(const ConstIteratorT source, IteratorT target, std::true_type) const
Assign the source iterator to the target iterator.
#define PCL_MAKE_ALIGNED_OPERATOR_NEW
Macro to signal a class requires a custom allocator.
HalfEdge getHalfEdge(const HalfEdgeIndex &idx_he) const
Get the half-edge for the given index.
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
VertexAroundFaceCirculator getVertexAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
Index used to access elements in the half-edge mesh.
void reserveEdges(const std::size_t n)
Reserve storage space for n edges (2*n storage space is reserved for the half-edges).
typename Vertices::iterator VertexIterator
Tag describing the type of the mesh.
bool isBoundary(const FaceIndex &idx_face, std::false_type) const
Check if any edge of the face lies on the boundary.
FaceIndex getFaceIndex(const HalfEdgeIndex &idx_half_edge) const
Get the face index to a given half-edge.
void reconnectNBNB(const HalfEdgeIndex &idx_he_bc, const HalfEdgeIndex &, const VertexIndex &idx_v_b, std::false_type)
Both edges are not on the boundary.
VertexIndex getTargetIndex() const
Get the index to the target vertex.
OutgoingHalfEdgeAroundVertexCirculator getOutgoingHalfEdgeAroundVertexCirculator(const VertexIndex &idx_vertex) const
EdgeDataCloud & getEdgeDataCloud()
Get access to the stored edge data.
FaceAroundVertexCirculator getFaceAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
FaceIndex getOppositeFaceIndex(const HalfEdgeIndex &idx_half_edge) const
Get the face index to a given half-edge.
void invalidate()
Invalidate the index.
HalfEdgeIndex getTargetIndex() const
Get the index to the incoming half-edge.
int get() const
Get the index.
pcl::PointCloud< HalfEdgeData > HalfEdgeDataCloud
Circulates counter-clockwise around a vertex and returns an index to the face of the outgoing half-ed...
FaceIndex getFaceIndex(const FaceData &face_data) const
Get the index associated to the given face data.
typename MeshTraitsT::EdgeData EdgeData
void invalidate()
Invalidate the index.
HalfEdgeIndex getTargetIndex() const
Get the index to the inner half-edge.
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.
bool setEdgeDataCloud(const EdgeDataCloud &edge_data_cloud)
Change the stored edge data.
OuterHalfEdgeAroundFaceCirculator getOuterHalfEdgeAroundFaceCirculator(const FaceIndex &idx_face) const
bool isManifold() const
Check if the mesh is manifold.
void addData(pcl::PointCloud< DataT > &, const DataT &, std::false_type)
Does nothing.
HalfEdgeDataCloud & getHalfEdgeDataCloud()
Get access to the stored half-edge data.
bool isManifold(const VertexIndex &idx_vertex, std::false_type) const
Check if the given vertex is manifold.
Half-edge mesh that can only store quads.
std::integral_constant< bool, !std::is_same< VertexData, pcl::geometry::NoData >::value > HasVertexData
typename HalfEdges::const_iterator HalfEdgeConstIterator
VertexDataCloud & getVertexDataCloud()
Get access to the stored vertex data.
Read / write the half-edge mesh from / to a file.
void setFaceIndex(const HalfEdgeIndex &idx_half_edge, const FaceIndex &idx_face)
Set the face index to a given half-edge.
VertexIndex getTerminatingVertexIndex(const HalfEdgeIndex &idx_half_edge) const
Get the terminating vertex index to a given half-edge.
std::vector< Vertex > Vertices
Index used to access elements in the half-edge mesh.
bool isEqualTopology(const Self &other) const
Check if the other mesh has the same topology as this mesh.
pcl::PointCloud< EdgeData > EdgeDataCloud
const PointT & front() const
void resizeData(DataCloudT &, const std::size_t n, const typename DataCloudT::value_type &data, std::true_type) const
Resize the mesh data.
pcl::geometry::HalfEdgeIndex toHalfEdgeIndex(const EdgeIndex &index, const bool get_first=true)
Convert the given edge index to a half-edge index.
typename Vertices::const_iterator VertexConstIterator
Describes a set of vertices in a polygon mesh, by basically storing an array of indices.
VertexAroundVertexCirculator getVertexAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
std::integral_constant< bool, !std::is_same< HalfEdgeData, pcl::geometry::NoData >::value > HasHalfEdgeData
bool isValid() const
Returns true if the index is valid.
std::vector< FaceIndex > FaceIndices
void reserveVertices(const std::size_t n)
Reserve storage space n vertices.
void invalidate()
Invalidate the index.
std::integral_constant< bool, !std::is_same< EdgeData, pcl::geometry::NoData >::value > HasEdgeData
void cleanUp()
Removes all mesh elements and data that are marked 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 isManifold(const VertexIndex &idx_vertex) const
Check if the given vertex is manifold.
std::size_t sizeHalfEdges() const
Get the number of the half-edges.
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.
bool isDeleted(const FaceIndex &idx_face) const
Check if the given face is marked as deleted.
HalfEdgeIndex getCurrentHalfEdgeIndex() const
Get the half-edge that is currently stored in the circulator.
OuterHalfEdgeAroundFaceCirculator getOuterHalfEdgeAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
shared_ptr< const Self > ConstPtr
void deleteVertex(const VertexIndex &idx_vertex)
Mark the given vertex and all connected half-edges and faces as deleted.
bool isValid(const HalfEdgeIndex &idx_he) const
Check if the given half-edge index is a valid index into the mesh.
void connectOldOld(const HalfEdgeIndex &, const HalfEdgeIndex &, const VertexIndex &, std::true_type)
Both half-edges are old (manifold version).
FaceAroundVertexCirculator getFaceAroundVertexCirculator(const VertexIndex &idx_vertex) const
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.
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.
void reserveData(DataCloudT &, const std::size_t, std::false_type) const
Does nothing.
IndexContainerT remove(ElementContainerT &elements, DataContainerT &data_cloud)
Removes mesh elements and data that are marked as deleted from the container.
bool isBoundary(const FaceIndex &idx_face, std::true_type) const
Check if any vertex of the face lies on the boundary.
std::size_t sizeFaces() const
Get the number of the faces.
bool setFaceDataCloud(const FaceDataCloud &face_data_cloud)
Change the stored face data.
IncomingHalfEdgeAroundVertexCirculator getIncomingHalfEdgeAroundVertexCirculator(const HalfEdgeIndex &idx_incoming_half_edge) const
int get() const
Get the index.
void push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
VertexAroundFaceCirculator getVertexAroundFaceCirculator(const FaceIndex &idx_face) const
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.
void assignIf(const ConstIteratorT, IteratorT, std::false_type) const
Does nothing.
FaceIndex getTargetIndex() const
Get the index to the target face.
void markDeleted(const VertexIndex &idx_vertex)
Mark the given vertex as deleted.
std::vector< Face > Faces
int get() const
Get the index.
boost::shared_ptr< T > shared_ptr
Alias for boost::shared_ptr.
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).
void markDeleted(const HalfEdgeIndex &idx_he)
Mark the given half-edge as deleted.
bool isBoundary(const FaceIndex &idx_face) const
Check if the given face lies on the boundary.
void incrementIf(IteratorT &it, std::true_type) const
Increment the iterator.
std::vector< VertexIndex > VertexIndices
Base class for the half-edge mesh.
Circulates counter-clockwise around a vertex and returns an index to the terminating vertex of the ou...