Point Cloud Library (PCL)
1.9.1
|
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 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.
std::vector< VertexIndex > VertexIndices
std::vector< FaceIndex > FaceIndices
void setVertex(const VertexIndex &idx_vertex, const Vertex &vertex)
Set the vertex at the given index.
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.
Faces::iterator FaceIterator
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)
MeshBase< DerivedT, MeshTraitsT, MeshTagT > Self
HalfEdgeIndex getOutgoingHalfEdgeIndex(const VertexIndex &idx_vertex) const
Get the outgoing half-edge index to a given vertex.
Vertices::iterator VertexIterator
std::vector< Vertex > Vertices
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
boost::integral_constant< bool, !boost::is_same< VertexData, pcl::geometry::NoData >::value > HasVertexData
FaceDataCloud getFaceDataCloud() const
Get the stored face data.
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 empty() const
Check if the mesh is empty.
bool isManifold(boost::false_type) const
Check if all vertices in the mesh are manifold.
pcl::geometry::EdgeIndex EdgeIndex
bool isValid(const EdgeIndex &idx_edge) const
Check if the given edge index is a valid index into the mesh.
void resizeFaces(const size_t n, const FaceData &data=FaceData())
Resize the faces to n elements.
OutgoingHalfEdgeAroundVertexCirculator getOutgoingHalfEdgeAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
HalfEdgeIndex getTargetIndex() const
Get the index to the outgoing half-edge.
size_t sizeFaces() const
Get the number of the faces.
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 clearData(DataCloudT &, boost::false_type) const
Does nothing.
FaceAroundFaceCirculator getFaceAroundFaceCirculator(const FaceIndex &idx_face) const
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.
bool checkTopology1(const VertexIndex &idx_v_a, const VertexIndex &idx_v_b, HalfEdgeIndex &idx_he_ab, std::vector< bool >::reference is_new_ab, boost::false_type) const
Non manifold version of checkTopology1.
boost::shared_ptr< Self > Ptr
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).
HalfEdgeIndex getNextHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the next half-edge index to a given half-edge.
MeshTraitsT::HalfEdgeData HalfEdgeData
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
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.
std::vector< HalfEdge > HalfEdges
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.
bool checkTopology2(const HalfEdgeIndex &, const HalfEdgeIndex &, const bool is_new_ab, const bool is_new_bc, const bool is_isolated_b, std::vector< bool >::reference, HalfEdgeIndex &, boost::true_type) const
Check if the face may be added (mesh does not become non-manifold).
void 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 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).
pcl::geometry::VertexIndex VertexIndex
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).
HalfEdges::const_iterator HalfEdgeConstIterator
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.
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.
void addData(pcl::PointCloud< DataT > &, const DataT &, boost::false_type)
Does nothing.
EdgeIndex getEdgeIndex(const EdgeData &edge_data) const
Get the index associated to the given edge data.
EdgeDataCloud getEdgeDataCloud() const
Get the stored edge data.
boost::integral_constant< bool, !boost::is_same< HalfEdgeData, pcl::geometry::NoData >::value > HasHalfEdgeData
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).
void resizeVertices(const size_t n, const VertexData &data=VertexData())
Resize the the vertices to n elements.
Faces::const_iterator FaceConstIterator
std::vector< HalfEdgeIndex > HalfEdgeIndices
MeshTraitsT::IsManifold IsManifold
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
MeshTraitsT::EdgeData EdgeData
HalfEdgeDataCloud getHalfEdgeDataCloud() const
Get the stored half-edge data.
size_t sizeEdges() const
Get the number of the edges.
bool isBoundary(const FaceIndex &idx_face, boost::false_type) const
Check if any edge of the face lies on the boundary.
pcl::geometry::VertexAroundFaceCirculator< const Self > VertexAroundFaceCirculator
void reserveFaces(const size_t n)
Reserve storage space for n faces.
bool isDeleted(const HalfEdgeIndex &idx_he) const
Check if the given half-edge 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::true_type) const
Check if the edge between the two vertices can be added.
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.
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 isBoundary(const FaceIndex &idx_face) const
Check if the given face lies on the boundary.
void connectOldOld(const HalfEdgeIndex &, const HalfEdgeIndex &, const VertexIndex &, boost::true_type)
Both half-edges are old (manifold version).
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.
pcl::PointCloud< VertexData > VertexDataCloud
Circulates clockwise around a face and returns an index to the face of the outer half-edge (the targe...
Index used to access elements in the half-edge mesh.
pcl::PointCloud< HalfEdgeData > HalfEdgeDataCloud
VectorType::const_iterator const_iterator
std::vector< Face > Faces
void setOutgoingHalfEdgeIndex(const VertexIndex &idx_vertex, const HalfEdgeIndex &idx_outgoing_half_edge)
Set the outgoing half-edge index to a given vertex.
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 markDeleted(const EdgeIndex &idx_edge)
Mark the given edge (both half-edges) as deleted.
InnerHalfEdgeAroundFaceCirculator getInnerHalfEdgeAroundFaceCirculator(const FaceIndex &idx_face) const
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).
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.
bool isManifold(const VertexIndex &idx_vertex, boost::false_type) const
Check if the given vertex is manifold.
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.
VectorType::iterator iterator
FaceIndex connectFace(const HalfEdgeIndices &inner_he, const FaceData &face_data)
Add a face to the mesh and connect it to the half-edges.
void setFace(const FaceIndex &idx_face, const Face &face)
Set the face at the given index.
HalfEdges::iterator HalfEdgeIterator
void clear()
Clear all mesh elements and data.
InnerHalfEdgeAroundFaceCirculator getInnerHalfEdgeAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
boost::shared_ptr< const Self > ConstPtr
const PointT & back() const
MeshTraitsT::FaceData FaceData
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.
void deleteFace(const FaceIndex &idx_face, boost::true_type)
Manifold version of deleteFace.
HalfEdge getHalfEdge(const HalfEdgeIndex &idx_he) const
Get the half-edge for the given index.
pcl::PointCloud< EdgeData > EdgeDataCloud
void resizeData(DataCloudT &, const size_t n, const typename DataCloudT::value_type &data, boost::true_type) const
Resize the mesh data.
bool isBoundary(const FaceIndex &idx_face, boost::true_type) const
Check if any vertex of the face lies on the boundary.
VertexAroundFaceCirculator getVertexAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
Index used to access elements in the half-edge mesh.
void resize(size_t n)
Resize the cloud.
FaceIndex getFaceIndex(const HalfEdgeIndex &idx_half_edge) const
Get the face index to a given half-edge.
void reserveData(DataCloudT &cloud, const size_t n, boost::true_type) const
Reserve storage space for the mesh data.
void assignIf(const ConstIteratorT, IteratorT, boost::false_type) const
Does nothing.
VertexIndex getTargetIndex() const
Get the index to the target vertex.
OutgoingHalfEdgeAroundVertexCirculator getOutgoingHalfEdgeAroundVertexCirculator(const VertexIndex &idx_vertex) const
pcl::geometry::FaceAroundFaceCirculator< const Self > FaceAroundFaceCirculator
EdgeDataCloud & getEdgeDataCloud()
Get access to the stored edge data.
FaceAroundVertexCirculator getFaceAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
void reserveVertices(const size_t n)
Reserve storage space n vertices.
void reconnectNBNB(const HalfEdgeIndex &idx_he_bc, const HalfEdgeIndex &, const VertexIndex &idx_v_b, boost::false_type)
Both edges are not on the boundary.
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.
void reserveData(DataCloudT &, const size_t, boost::false_type) const
Does nothing.
Circulates counter-clockwise around a vertex and returns an index to the face of the outgoing half-ed...
boost::integral_constant< bool, !boost::is_same< FaceData, pcl::geometry::NoData >::value > HasFaceData
FaceIndex getFaceIndex(const FaceData &face_data) const
Get the index associated to the given face data.
void invalidate()
Invalidate the index.
boost::integral_constant< bool, !boost::is_same< EdgeData, pcl::geometry::NoData >::value > HasEdgeData
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.
void clearData(DataCloudT &cloud, boost::true_type) const
Clear the mesh data.
std::vector< EdgeIndex > EdgeIndices
OuterHalfEdgeAroundFaceCirculator getOuterHalfEdgeAroundFaceCirculator(const FaceIndex &idx_face) const
bool isManifold() const
Check if the mesh is manifold.
HalfEdgeDataCloud & getHalfEdgeDataCloud()
Get access to the stored half-edge data.
Half-edge mesh that can only store quads.
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.
bool isManifold(const VertexIndex &, boost::true_type) const
Always manifold.
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.
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.
const PointT & front() const
void incrementIf(IteratorT &it, boost::true_type) const
Increment the iterator.
pcl::geometry::OutgoingHalfEdgeAroundVertexCirculator< const Self > OutgoingHalfEdgeAroundVertexCirculator
MeshTraitsT::VertexData VertexData
pcl::geometry::HalfEdgeIndex toHalfEdgeIndex(const EdgeIndex &index, const bool get_first=true)
Convert the given edge index to a half-edge index.
pcl::geometry::InnerHalfEdgeAroundFaceCirculator< const Self > InnerHalfEdgeAroundFaceCirculator
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
bool isValid() const
Returns true if the index is valid.
void invalidate()
Invalidate the index.
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.
pcl::geometry::Vertex Vertex
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.
HalfEdgeIndex getCurrentHalfEdgeIndex() const
Get the half-edge that is currently stored in the circulator.
OuterHalfEdgeAroundFaceCirculator getOuterHalfEdgeAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
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.
FaceAroundVertexCirculator getFaceAroundVertexCirculator(const VertexIndex &idx_vertex) const
void reserveEdges(const size_t n)
Reserve storage space for n edges (2*n storage space is reserved for the half-edges).
void deleteFace(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.
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.
pcl::geometry::IncomingHalfEdgeAroundVertexCirculator< const Self > IncomingHalfEdgeAroundVertexCirculator
void connectNewOld(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b)
The first half-edge is new.
IndexContainerT remove(ElementContainerT &elements, DataContainerT &data_cloud)
Removes mesh elements and data that are marked as deleted from the container.
bool setFaceDataCloud(const FaceDataCloud &face_data_cloud)
Change the stored face data.
void incrementIf(IteratorT &, boost::false_type) const
Does nothing.
IncomingHalfEdgeAroundVertexCirculator getIncomingHalfEdgeAroundVertexCirculator(const HalfEdgeIndex &idx_incoming_half_edge) const
int get() const
Get the index.
pcl::geometry::HalfEdge HalfEdge
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
Vertices::const_iterator VertexConstIterator
FaceIndex getTargetIndex() const
Get the index to the target face.
void markDeleted(const VertexIndex &idx_vertex)
Mark the given vertex as deleted.
BOOST_CONCEPT_ASSERT((boost::Convertible< IsManifold, bool >))
size_t sizeHalfEdges() const
Get the number of the half-edges.
int get() const
Get the index.
pcl::PointCloud< FaceData > FaceDataCloud
pcl::geometry::OuterHalfEdgeAroundFaceCirculator< const Self > OuterHalfEdgeAroundFaceCirculator
bool isManifold(boost::true_type) const
Always manifold.
pcl::geometry::FaceIndex FaceIndex
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 deleteFace(const FaceIndex &idx_face, boost::false_type)
Non-manifold version of deleteFace.
pcl::geometry::HalfEdgeIndex HalfEdgeIndex
Base class for the half-edge mesh.
pcl::geometry::FaceAroundVertexCirculator< const Self > FaceAroundVertexCirculator
Circulates counter-clockwise around a vertex and returns an index to the terminating vertex of the ou...