Point Cloud Library (PCL)  1.11.1-dev
mesh_base.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2009-2012, Willow Garage, Inc.
6  * Copyright (c) 2012-, Open Perception, Inc.
7  *
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * * Neither the name of the copyright holder(s) nor the names of its
21  * contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * $Id$
38  *
39  */
40 
41 #pragma once
42 
43 #include <pcl/geometry/mesh_circulators.h>
44 #include <pcl/geometry/mesh_indices.h>
45 #include <pcl/geometry/mesh_elements.h>
46 #include <pcl/geometry/mesh_traits.h>
47 #include <pcl/memory.h>
48 #include <pcl/pcl_macros.h>
49 #include <pcl/point_cloud.h>
50 
51 #include <vector>
52 #include <type_traits>
53 
54 ////////////////////////////////////////////////////////////////////////////////
55 // Global variables used during testing
56 ////////////////////////////////////////////////////////////////////////////////
57 
58 #ifdef PCL_GEOMETRY_MESH_BASE_TEST_DELETE_FACE_MANIFOLD_2
59 namespace pcl
60 {
61  namespace geometry
62  {
63  bool g_pcl_geometry_mesh_base_test_delete_face_manifold_2_success;
64  } // End namespace geometry
65 } // End namespace pcl
66 #endif
67 
68 ////////////////////////////////////////////////////////////////////////////////
69 // Forward declarations
70 ////////////////////////////////////////////////////////////////////////////////
71 
72 namespace pcl
73 {
74  namespace geometry
75  {
76  template <class MeshT>
77  class MeshIO;
78  } // End namespace geometry
79 } // End namespace pcl
80 
81 ////////////////////////////////////////////////////////////////////////////////
82 // MeshBase
83 ////////////////////////////////////////////////////////////////////////////////
84 
85 namespace pcl
86 {
87  namespace geometry
88  {
89  /** \brief Base class for the half-edge mesh.
90  * \tparam DerivedT Has to implement the method 'addFaceImpl'. Please have a look at pcl::geometry::TriangleMesh, pcl::geometry::QuadMesh and pcl::geometry::PolygonMesh.
91  * \tparam MeshTraitsT Please have a look at pcl::geometry::DefaultMeshTraits.
92  * \tparam MeshTagT Tag describing the type of the mesh, e.g. TriangleMeshTag, QuadMeshTag, PolygonMeshTag.
93  * \author Martin Saelzle
94  * \ingroup geometry
95  * \todo Add documentation
96  */
97  template <class DerivedT, class MeshTraitsT, class MeshTagT>
98  class MeshBase
99  {
100  public:
101 
103  using Ptr = shared_ptr<Self>;
104  using ConstPtr = shared_ptr<const Self>;
105 
106  using Derived = DerivedT;
107 
108  // These have to be defined in the traits class.
109  using VertexData = typename MeshTraitsT::VertexData;
110  using HalfEdgeData = typename MeshTraitsT::HalfEdgeData;
111  using EdgeData = typename MeshTraitsT::EdgeData;
112  using FaceData = typename MeshTraitsT::FaceData;
113  using IsManifold = typename MeshTraitsT::IsManifold;
114 
115  // Check if the mesh traits are defined correctly.
116  static_assert (std::is_convertible<IsManifold, bool>::value, "MeshTraitsT::IsManifold is not convertible to bool");
117 
118  using MeshTag = MeshTagT;
119 
120  // Data
121  using HasVertexData = std::integral_constant <bool, !std::is_same <VertexData , pcl::geometry::NoData>::value>;
122  using HasHalfEdgeData = std::integral_constant <bool, !std::is_same <HalfEdgeData, pcl::geometry::NoData>::value>;
123  using HasEdgeData = std::integral_constant <bool, !std::is_same <EdgeData , pcl::geometry::NoData>::value>;
124  using HasFaceData = std::integral_constant <bool, !std::is_same <FaceData , pcl::geometry::NoData>::value>;
125 
130 
131  // Indices
136 
137  using VertexIndices = std::vector<VertexIndex>;
138  using HalfEdgeIndices = std::vector<HalfEdgeIndex>;
139  using EdgeIndices = std::vector<EdgeIndex>;
140  using FaceIndices = std::vector<FaceIndex>;
141 
142  // Circulators
151 
152  /** \brief Constructor. */
154  : vertex_data_cloud_ (),
155  half_edge_data_cloud_ (),
156  edge_data_cloud_ (),
157  face_data_cloud_ ()
158  {
159  }
160 
161  ////////////////////////////////////////////////////////////////////////
162  // addVertex / addFace / deleteVertex / deleteEdge / deleteFace / cleanUp
163  ////////////////////////////////////////////////////////////////////////
164 
165  /** \brief Add a vertex to the mesh.
166  * \param[in] vertex_data Data that is stored in the vertex. This is only added if the mesh has data associated with the vertices.
167  * \return Index to the new vertex.
168  */
169  inline VertexIndex
170  addVertex (const VertexData& vertex_data=VertexData ())
171  {
172  vertices_.push_back (Vertex ());
173  this->addData (vertex_data_cloud_, vertex_data, HasVertexData ());
174  return (VertexIndex (static_cast <int> (this->sizeVertices () - 1)));
175  }
176 
177  /** \brief Add a face to the mesh. Data is only added if it is associated with the elements. The last vertex is connected with the first one.
178  * \param[in] vertices Indices to the vertices of the new face.
179  * \param[in] face_data Data that is set for the face.
180  * \param[in] half_edge_data Data that is set for all added half-edges.
181  * \param[in] edge_data Data that is set for all added edges.
182  * \return Index to the new face. Failure is signaled by returning an invalid face index.
183  * \warning The vertices must be valid and unique (each vertex may be contained only once). Not complying with this requirement results in undefined behavior!
184  */
185  inline FaceIndex
186  addFace (const VertexIndices& vertices,
187  const FaceData& face_data = FaceData (),
188  const EdgeData& edge_data = EdgeData (),
189  const HalfEdgeData& half_edge_data = HalfEdgeData ())
190  {
191  // NOTE: The derived class has to implement addFaceImpl. If needed it can use the general method addFaceImplBase.
192  return (static_cast <Derived*> (this)->addFaceImpl (vertices, face_data, edge_data, half_edge_data));
193  }
194 
195  /** \brief Mark the given vertex and all connected half-edges and faces as deleted.
196  * \note Call cleanUp () to finally delete all mesh-elements.
197  */
198  void
199  deleteVertex (const VertexIndex& idx_vertex)
200  {
201  assert (this->isValid (idx_vertex));
202  if (this->isDeleted (idx_vertex)) return;
203 
204  delete_faces_vertex_.clear ();
206  const FaceAroundVertexCirculator circ_end = circ;
207  do
208  {
209  if (circ.getTargetIndex ().isValid ()) // Check for boundary.
210  {
211  delete_faces_vertex_.push_back (circ.getTargetIndex ());
212  }
213  } while (++circ!=circ_end);
214 
215  for (FaceIndices::const_iterator it = delete_faces_vertex_.begin (); it!=delete_faces_vertex_.end (); ++it)
216  {
217  this->deleteFace (*it);
218  }
219  }
220 
221  /** \brief Mark the given half-edge, the opposite half-edge and the associated faces as deleted.
222  * \note Call cleanUp () to finally delete all mesh-elements.
223  */
224  void
225  deleteEdge (const HalfEdgeIndex& idx_he)
226  {
227  assert (this->isValid (idx_he));
228  if (this->isDeleted (idx_he)) return;
229 
230  HalfEdgeIndex opposite = this->getOppositeHalfEdgeIndex (idx_he);
231 
232  if (this->isBoundary (idx_he)) this->markDeleted (idx_he);
233  else this->deleteFace (this->getFaceIndex (idx_he));
234  if (this->isBoundary (opposite)) this->markDeleted (opposite);
235  else this->deleteFace (this->getFaceIndex (opposite));
236  }
237 
238  /** \brief Mark the given edge (both half-edges) and the associated faces as deleted.
239  * \note Call cleanUp () to finally delete all mesh-elements.
240  */
241  inline void
242  deleteEdge (const EdgeIndex& idx_edge)
243  {
244  assert (this->isValid (idx_edge));
245  this->deleteEdge (pcl::geometry::toHalfEdgeIndex (idx_edge));
246  assert (this->isDeleted (pcl::geometry::toHalfEdgeIndex (idx_edge, false))); // Bug in this class!
247  }
248 
249  /** \brief Mark the given face as deleted. More faces are deleted if the manifold mesh would become non-manifold.
250  * \note Call cleanUp () to finally delete all mesh-elements.
251  */
252  inline void
253  deleteFace (const FaceIndex& idx_face)
254  {
255  assert (this->isValid (idx_face));
256  if (this->isDeleted (idx_face)) return;
257 
258  this->deleteFace (idx_face, IsManifold ());
259  }
260 
261  /** \brief Removes all mesh elements and data that are marked as deleted.
262  * \note This removes all isolated vertices as well.
263  */
264  void
266  {
267  // Copy the non-deleted mesh elements and store the index to their new position
268  const VertexIndices new_vertex_indices =
269  this->remove <Vertices, VertexDataCloud, VertexIndices, HasVertexData>
270  (vertices_, vertex_data_cloud_);
271  const HalfEdgeIndices new_half_edge_indices =
272  this->remove <HalfEdges, HalfEdgeDataCloud, HalfEdgeIndices, HasHalfEdgeData>
273  (half_edges_, half_edge_data_cloud_);
274  const FaceIndices new_face_indices =
275  this->remove <Faces, FaceDataCloud, FaceIndices, HasFaceData>
276  (faces_, face_data_cloud_);
277 
278  // Remove deleted edge data
279  if (HasEdgeData::value)
280  {
281  auto it_ed_old = edge_data_cloud_.begin ();
282  auto it_ed_new = edge_data_cloud_.begin ();
283 
284  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)
285  {
286  if (it_ind->isValid ())
287  {
288  *it_ed_new++ = *it_ed_old;
289  }
290  }
291  edge_data_cloud_.resize (this->sizeEdges ());
292  }
293 
294  // Adjust the indices
295  for (VertexIterator it = vertices_.begin (); it!=vertices_.end (); ++it)
296  {
297  if (it->idx_outgoing_half_edge_.isValid ())
298  {
299  it->idx_outgoing_half_edge_ = new_half_edge_indices [it->idx_outgoing_half_edge_.get ()];
300  }
301  }
302 
303  for (HalfEdgeIterator it = half_edges_.begin (); it!=half_edges_.end (); ++it)
304  {
305  it->idx_terminating_vertex_ = new_vertex_indices [it->idx_terminating_vertex_.get ()];
306  it->idx_next_half_edge_ = new_half_edge_indices [it->idx_next_half_edge_.get ()];
307  it->idx_prev_half_edge_ = new_half_edge_indices [it->idx_prev_half_edge_.get ()];
308  if (it->idx_face_.isValid ())
309  {
310  it->idx_face_ = new_face_indices [it->idx_face_.get ()];
311  }
312  }
313 
314  for (FaceIterator it = faces_.begin (); it!=faces_.end (); ++it)
315  {
316  it->idx_inner_half_edge_ = new_half_edge_indices [it->idx_inner_half_edge_.get ()];
317  }
318  }
319 
320  ////////////////////////////////////////////////////////////////////////
321  // Vertex connectivity
322  ////////////////////////////////////////////////////////////////////////
323 
324  /** \brief Get the outgoing half-edge index to a given vertex. */
325  inline HalfEdgeIndex
326  getOutgoingHalfEdgeIndex (const VertexIndex& idx_vertex) const
327  {
328  assert (this->isValid (idx_vertex));
329  return (this->getVertex (idx_vertex).idx_outgoing_half_edge_);
330  }
331 
332  /** \brief Get the incoming half-edge index to a given vertex. */
333  inline HalfEdgeIndex
334  getIncomingHalfEdgeIndex (const VertexIndex& idx_vertex) const
335  {
336  assert (this->isValid (idx_vertex));
337  return (this->getOppositeHalfEdgeIndex (this->getOutgoingHalfEdgeIndex (idx_vertex)));
338  }
339 
340  ////////////////////////////////////////////////////////////////////////
341  // Half-edge connectivity
342  ////////////////////////////////////////////////////////////////////////
343 
344  /** \brief Get the terminating vertex index to a given half-edge. */
345  inline VertexIndex
346  getTerminatingVertexIndex (const HalfEdgeIndex& idx_half_edge) const
347  {
348  assert (this->isValid (idx_half_edge));
349  return (this->getHalfEdge (idx_half_edge).idx_terminating_vertex_);
350  }
351 
352  /** \brief Get the originating vertex index to a given half-edge. */
353  inline VertexIndex
354  getOriginatingVertexIndex (const HalfEdgeIndex& idx_half_edge) const
355  {
356  assert (this->isValid (idx_half_edge));
357  return (this->getTerminatingVertexIndex (this->getOppositeHalfEdgeIndex (idx_half_edge)));
358  }
359 
360  /** \brief Get the opposite half-edge index to a given half-edge. */
361  inline HalfEdgeIndex
362  getOppositeHalfEdgeIndex (const HalfEdgeIndex& idx_half_edge) const
363  {
364  assert (this->isValid (idx_half_edge));
365  // Check if the index is even or odd and return the other index.
366  return (HalfEdgeIndex (idx_half_edge.get () & 1 ? idx_half_edge.get () - 1 : idx_half_edge.get () + 1));
367  }
368 
369  /** \brief Get the next half-edge index to a given half-edge. */
370  inline HalfEdgeIndex
371  getNextHalfEdgeIndex (const HalfEdgeIndex& idx_half_edge) const
372  {
373  assert (this->isValid (idx_half_edge));
374  return (this->getHalfEdge (idx_half_edge).idx_next_half_edge_);
375  }
376 
377  /** \brief Get the previous half-edge index to a given half-edge. */
378  inline HalfEdgeIndex
379  getPrevHalfEdgeIndex (const HalfEdgeIndex& idx_half_edge) const
380  {
381  assert (this->isValid (idx_half_edge));
382  return (this->getHalfEdge (idx_half_edge).idx_prev_half_edge_);
383  }
384 
385  /** \brief Get the face index to a given half-edge. */
386  inline FaceIndex
387  getFaceIndex (const HalfEdgeIndex& idx_half_edge) const
388  {
389  assert (this->isValid (idx_half_edge));
390  return (this->getHalfEdge (idx_half_edge).idx_face_);
391  }
392 
393  /** \brief Get the face index to a given half-edge. */
394  inline FaceIndex
395  getOppositeFaceIndex (const HalfEdgeIndex& idx_half_edge) const
396  {
397  assert (this->isValid (idx_half_edge));
398  return (this->getFaceIndex (this->getOppositeHalfEdgeIndex (idx_half_edge)));
399  }
400 
401  ////////////////////////////////////////////////////////////////////////
402  // Face connectivity
403  ////////////////////////////////////////////////////////////////////////
404 
405  /** \brief Get the inner half-edge index to a given face. */
406  inline HalfEdgeIndex
407  getInnerHalfEdgeIndex (const FaceIndex& idx_face) const
408  {
409  assert (this->isValid (idx_face));
410  return (this->getFace (idx_face).idx_inner_half_edge_);
411  }
412 
413  /** \brief Get the outer half-edge inex to a given face. */
414  inline HalfEdgeIndex
415  getOuterHalfEdgeIndex (const FaceIndex& idx_face) const
416  {
417  assert (this->isValid (idx_face));
418  return (this->getOppositeHalfEdgeIndex (this->getInnerHalfEdgeIndex (idx_face)));
419  }
420 
421  ////////////////////////////////////////////////////////////////////////
422  // Circulators
423  ////////////////////////////////////////////////////////////////////////
424 
425  /** \see pcl::geometry::VertexAroundVertexCirculator */
428  {
429  assert (this->isValid (idx_vertex));
430  return (VertexAroundVertexCirculator (idx_vertex, this));
431  }
432 
433  /** \see pcl::geometry::VertexAroundVertexCirculator */
435  getVertexAroundVertexCirculator (const HalfEdgeIndex& idx_outgoing_half_edge) const
436  {
437  assert (this->isValid (idx_outgoing_half_edge));
438  return (VertexAroundVertexCirculator (idx_outgoing_half_edge, this));
439  }
440 
441  /** \see pcl::geometry::OutgoingHalfEdgeAroundVertexCirculator */
444  {
445  assert (this->isValid (idx_vertex));
446  return (OutgoingHalfEdgeAroundVertexCirculator (idx_vertex, this));
447  }
448 
449  /** \see pcl::geometry::OutgoingHalfEdgeAroundVertexCirculator */
451  getOutgoingHalfEdgeAroundVertexCirculator (const HalfEdgeIndex& idx_outgoing_half_edge) const
452  {
453  assert (this->isValid (idx_outgoing_half_edge));
454  return (OutgoingHalfEdgeAroundVertexCirculator (idx_outgoing_half_edge, this));
455  }
456 
457  /** \see pcl::geometry::IncomingHalfEdgeAroundVertexCirculator */
460  {
461  assert (this->isValid (idx_vertex));
462  return (IncomingHalfEdgeAroundVertexCirculator (idx_vertex, this));
463  }
464 
465  /** \see pcl::geometry::IncomingHalfEdgeAroundVertexCirculator */
467  getIncomingHalfEdgeAroundVertexCirculator (const HalfEdgeIndex& idx_incoming_half_edge) const
468  {
469  assert (this->isValid (idx_incoming_half_edge));
470  return (IncomingHalfEdgeAroundVertexCirculator (idx_incoming_half_edge, this));
471  }
472 
473  /** \see pcl::geometry::FaceAroundVertexCirculator */
475  getFaceAroundVertexCirculator (const VertexIndex& idx_vertex) const
476  {
477  assert (this->isValid (idx_vertex));
478  return (FaceAroundVertexCirculator (idx_vertex, this));
479  }
480 
481  /** \see pcl::geometry::FaceAroundVertexCirculator */
483  getFaceAroundVertexCirculator (const HalfEdgeIndex& idx_outgoing_half_edge) const
484  {
485  assert (this->isValid (idx_outgoing_half_edge));
486  return (FaceAroundVertexCirculator (idx_outgoing_half_edge, this));
487  }
488 
489  /** \see pcl::geometry::VertexAroundFaceCirculator */
491  getVertexAroundFaceCirculator (const FaceIndex& idx_face) const
492  {
493  assert (this->isValid (idx_face));
494  return (VertexAroundFaceCirculator (idx_face, this));
495  }
496 
497  /** \see pcl::geometry::VertexAroundFaceCirculator */
499  getVertexAroundFaceCirculator (const HalfEdgeIndex& idx_inner_half_edge) const
500  {
501  assert (this->isValid (idx_inner_half_edge));
502  return (VertexAroundFaceCirculator (idx_inner_half_edge, this));
503  }
504 
505  /** \see pcl::geometry::InnerHalfEdgeAroundFaceCirculator */
508  {
509  assert (this->isValid (idx_face));
510  return (InnerHalfEdgeAroundFaceCirculator (idx_face, this));
511  }
512 
513  /** \see pcl::geometry::InnerHalfEdgeAroundFaceCirculator */
515  getInnerHalfEdgeAroundFaceCirculator (const HalfEdgeIndex& idx_inner_half_edge) const
516  {
517  assert (this->isValid (idx_inner_half_edge));
518  return (InnerHalfEdgeAroundFaceCirculator (idx_inner_half_edge, this));
519  }
520 
521  /** \see pcl::geometry::OuterHalfEdgeAroundFaceCirculator */
524  {
525  assert (this->isValid (idx_face));
526  return (OuterHalfEdgeAroundFaceCirculator (idx_face, this));
527  }
528 
529  /** \see pcl::geometry::OuterHalfEdgeAroundFaceCirculator */
531  getOuterHalfEdgeAroundFaceCirculator (const HalfEdgeIndex& idx_inner_half_edge) const
532  {
533  assert (this->isValid (idx_inner_half_edge));
534  return (OuterHalfEdgeAroundFaceCirculator (idx_inner_half_edge, this));
535  }
536 
537  /** \see pcl::geometry::FaceAroundFaceCirculator */
539  getFaceAroundFaceCirculator (const FaceIndex& idx_face) const
540  {
541  assert (this->isValid (idx_face));
542  return (FaceAroundFaceCirculator (idx_face, this));
543  }
544 
545  /** \see pcl::geometry::FaceAroundFaceCirculator */
547  getFaceAroundFaceCirculator (const HalfEdgeIndex& idx_inner_half_edge) const
548  {
549  assert (this->isValid (idx_inner_half_edge));
550  return (FaceAroundFaceCirculator (idx_inner_half_edge, this));
551  }
552 
553  //////////////////////////////////////////////////////////////////////////
554  // isEqualTopology
555  //////////////////////////////////////////////////////////////////////////
556 
557  /** \brief Check if the other mesh has the same topology as this mesh. */
558  bool
559  isEqualTopology (const Self& other) const
560  {
561  if (this->sizeVertices () != other.sizeVertices ()) return (false);
562  if (this->sizeHalfEdges () != other.sizeHalfEdges ()) return (false);
563  if (this->sizeFaces () != other.sizeFaces ()) return (false);
564 
565  for (std::size_t i=0; i<this->sizeVertices (); ++i)
566  {
567  if (this->getOutgoingHalfEdgeIndex (VertexIndex (i)) !=
568  other.getOutgoingHalfEdgeIndex (VertexIndex (i))) return (false);
569  }
570 
571  for (std::size_t i=0; i<this->sizeHalfEdges (); ++i)
572  {
573  if (this->getTerminatingVertexIndex (HalfEdgeIndex (i)) !=
574  other.getTerminatingVertexIndex (HalfEdgeIndex (i))) return (false);
575 
576  if (this->getNextHalfEdgeIndex (HalfEdgeIndex (i)) !=
577  other.getNextHalfEdgeIndex (HalfEdgeIndex (i))) return (false);
578 
579  if (this->getPrevHalfEdgeIndex (HalfEdgeIndex (i)) !=
580  other.getPrevHalfEdgeIndex (HalfEdgeIndex (i))) return (false);
581 
582  if (this->getFaceIndex (HalfEdgeIndex (i)) !=
583  other.getFaceIndex (HalfEdgeIndex (i))) return (false);
584  }
585 
586  for (std::size_t i=0; i<this->sizeFaces (); ++i)
587  {
588  if (this->getInnerHalfEdgeIndex (FaceIndex (i)) !=
589  other.getInnerHalfEdgeIndex (FaceIndex (i))) return (false);
590  }
591 
592  return (true);
593  }
594 
595  ////////////////////////////////////////////////////////////////////////
596  // isValid
597  ////////////////////////////////////////////////////////////////////////
598 
599  /** \brief Check if the given vertex index is a valid index into the mesh. */
600  inline bool
601  isValid (const VertexIndex& idx_vertex) const
602  {
603  return (idx_vertex >= VertexIndex (0) && idx_vertex < VertexIndex (int (vertices_.size ())));
604  }
605 
606  /** \brief Check if the given half-edge index is a valid index into the mesh. */
607  inline bool
608  isValid (const HalfEdgeIndex& idx_he) const
609  {
610  return (idx_he >= HalfEdgeIndex (0) && idx_he < HalfEdgeIndex (half_edges_.size ()));
611  }
612 
613  /** \brief Check if the given edge index is a valid index into the mesh. */
614  inline bool
615  isValid (const EdgeIndex& idx_edge) const
616  {
617  return (idx_edge >= EdgeIndex (0) && idx_edge < EdgeIndex (half_edges_.size () / 2));
618  }
619 
620  /** \brief Check if the given face index is a valid index into the mesh. */
621  inline bool
622  isValid (const FaceIndex& idx_face) const
623  {
624  return (idx_face >= FaceIndex (0) && idx_face < FaceIndex (faces_.size ()));
625  }
626 
627  ////////////////////////////////////////////////////////////////////////
628  // isDeleted
629  ////////////////////////////////////////////////////////////////////////
630 
631  /** \brief Check if the given vertex is marked as deleted. */
632  inline bool
633  isDeleted (const VertexIndex& idx_vertex) const
634  {
635  assert (this->isValid (idx_vertex));
636  return (!this->getOutgoingHalfEdgeIndex (idx_vertex).isValid ());
637  }
638 
639  /** \brief Check if the given half-edge is marked as deleted. */
640  inline bool
641  isDeleted (const HalfEdgeIndex& idx_he) const
642  {
643  assert (this->isValid (idx_he));
644  return (!this->getTerminatingVertexIndex (idx_he).isValid ());
645  }
646 
647  /** \brief Check if the given edge (any of the two half-edges) is marked as deleted. */
648  inline bool
649  isDeleted (const EdgeIndex& idx_edge) const
650  {
651  assert (this->isValid (idx_edge));
652  return (this->isDeleted (pcl::geometry::toHalfEdgeIndex (idx_edge, true)) ||
653  this->isDeleted (pcl::geometry::toHalfEdgeIndex (idx_edge, false)));
654  }
655 
656  /** \brief Check if the given face is marked as deleted. */
657  inline bool
658  isDeleted (const FaceIndex& idx_face) const
659  {
660  assert (this->isValid (idx_face));
661  return (!this->getInnerHalfEdgeIndex (idx_face).isValid ());
662  }
663 
664  ////////////////////////////////////////////////////////////////////////
665  // isIsolated
666  ////////////////////////////////////////////////////////////////////////
667 
668  /** \brief Check if the given vertex is isolated (not connected to other elements). */
669  inline bool
670  isIsolated (const VertexIndex& idx_vertex) const
671  {
672  assert (this->isValid (idx_vertex));
673  return (!this->getOutgoingHalfEdgeIndex (idx_vertex).isValid ());
674  }
675 
676  ////////////////////////////////////////////////////////////////////////
677  // isBoundary
678  ////////////////////////////////////////////////////////////////////////
679 
680  /** \brief Check if the given vertex lies on the boundary. Isolated vertices are considered to be on the boundary. */
681  inline bool
682  isBoundary (const VertexIndex& idx_vertex) const
683  {
684  assert (this->isValid (idx_vertex));
685  if (this->isIsolated (idx_vertex)) return (true);
686  return (this->isBoundary (this->getOutgoingHalfEdgeIndex (idx_vertex)));
687  }
688 
689  /** \brief Check if the given half-edge lies on the bounddary. */
690  inline bool
691  isBoundary (const HalfEdgeIndex& idx_he) const
692  {
693  assert (this->isValid (idx_he));
694  return (!this->getFaceIndex (idx_he).isValid ());
695  }
696 
697  /** \brief Check if the given edge lies on the boundary (any of the two half-edges lies on the boundary. */
698  inline bool
699  isBoundary (const EdgeIndex& idx_edge) const
700  {
701  assert (this->isValid (idx_edge));
702  const HalfEdgeIndex& idx = pcl::geometry::toHalfEdgeIndex (idx_edge);
703  return (this->isBoundary (idx) || this->isBoundary (this->getOppositeHalfEdgeIndex (idx)));
704  }
705 
706  /** \brief Check if the given face lies on the boundary. There are two versions of this method, selected by the template parameter.
707  * \tparam CheckVerticesT Check if any vertex lies on the boundary (true) or check if any edge lies on the boundary (false).
708  */
709  template <bool CheckVerticesT> inline bool
710  isBoundary (const FaceIndex& idx_face) const
711  {
712  assert (this->isValid (idx_face));
713  return (this->isBoundary (idx_face, std::integral_constant <bool, CheckVerticesT> ()));
714  }
715 
716  /** \brief Check if the given face lies on the boundary. This method uses isBoundary \c true which checks if any vertex lies on the boundary. */
717  inline bool
718  isBoundary (const FaceIndex& idx_face) const
719  {
720  assert (this->isValid (idx_face));
721  return (this->isBoundary (idx_face, std::true_type ()));
722  }
723 
724  ////////////////////////////////////////////////////////////////////////
725  // isManifold
726  ////////////////////////////////////////////////////////////////////////
727 
728  /** \brief Check if the given vertex is manifold. Isolated vertices are manifold. */
729  inline bool
730  isManifold (const VertexIndex& idx_vertex) const
731  {
732  assert (this->isValid (idx_vertex));
733  if (this->isIsolated (idx_vertex)) return (true);
734  return (this->isManifold (idx_vertex, IsManifold ()));
735  }
736 
737  /** \brief Check if the mesh is manifold. */
738  inline bool
739  isManifold () const
740  {
741  return (this->isManifold (IsManifold ()));
742  }
743 
744  ////////////////////////////////////////////////////////////////////////
745  // size
746  ////////////////////////////////////////////////////////////////////////
747 
748  /** \brief Get the number of the vertices. */
749  inline std::size_t
750  sizeVertices () const
751  {
752  return (vertices_.size ());
753  }
754 
755  /** \brief Get the number of the half-edges. */
756  inline std::size_t
757  sizeHalfEdges () const
758  {
759  assert (half_edges_.size () % 2 == 0); // This would be a bug in the mesh.
760  return (half_edges_.size ());
761  }
762 
763  /** \brief Get the number of the edges. */
764  inline std::size_t
765  sizeEdges () const
766  {
767  assert (half_edges_.size () % 2 == 0); // This would be a bug in the mesh.
768  return (half_edges_.size () / 2);
769  }
770 
771  /** \brief Get the number of the faces. */
772  inline std::size_t
773  sizeFaces () const
774  {
775  return (faces_.size ());
776  }
777 
778  ////////////////////////////////////////////////////////////////////////
779  // empty
780  ////////////////////////////////////////////////////////////////////////
781 
782  /** \brief Check if the mesh is empty. */
783  inline bool
784  empty () const
785  {
786  return (this->emptyVertices () && this->emptyEdges () && this->emptyFaces ());
787  }
788 
789  /** \brief Check if the vertices are empty. */
790  inline bool
791  emptyVertices () const
792  {
793  return (vertices_.empty ());
794  }
795 
796  /** \brief Check if the edges are empty. */
797  inline bool
798  emptyEdges () const
799  {
800  return (half_edges_.empty ());
801  }
802 
803  /** \brief Check if the faces are empty. */
804  inline bool
805  emptyFaces () const
806  {
807  return (faces_.empty ());
808  }
809 
810  ////////////////////////////////////////////////////////////////////////
811  // reserve
812  ////////////////////////////////////////////////////////////////////////
813 
814  /** \brief Reserve storage space n vertices. */
815  inline void
816  reserveVertices (const std::size_t n)
817  {
818  vertices_.reserve (n);
819  this->reserveData (vertex_data_cloud_, n, HasVertexData ());
820  }
821 
822  /** \brief Reserve storage space for n edges (2*n storage space is reserved for the half-edges). */
823  inline void
824  reserveEdges (const std::size_t n)
825  {
826  half_edges_.reserve (2*n);
827  this->reserveData (half_edge_data_cloud_, 2*n, HasHalfEdgeData ());
828  this->reserveData (edge_data_cloud_ , n, HasEdgeData ());
829  }
830 
831  /** \brief Reserve storage space for n faces. */
832  inline void
833  reserveFaces (const std::size_t n)
834  {
835  faces_.reserve (n);
836  this->reserveData (face_data_cloud_, n, HasFaceData ());
837  }
838 
839  ////////////////////////////////////////////////////////////////////////
840  // resize
841  ////////////////////////////////////////////////////////////////////////
842 
843  /** \brief Resize the the vertices to n elements. */
844  inline void
845  resizeVertices (const std::size_t n, const VertexData& data = VertexData ())
846  {
847  vertices_.resize (n);
848  this->resizeData (vertex_data_cloud_, n, data, HasVertexData ());
849  }
850 
851  /** \brief Resize the edges to n elements (half-edges will hold 2*n elements). */
852  inline void
853  resizeEdges (const std::size_t n,
854  const EdgeData& edge_data = EdgeData (),
855  const HalfEdgeData he_data = HalfEdgeData ())
856  {
857  half_edges_.resize (2*n);
858  this->resizeData (half_edge_data_cloud_, 2*n, he_data , HasHalfEdgeData ());
859  this->resizeData (edge_data_cloud_ , n, edge_data, HasEdgeData ());
860  }
861 
862  /** \brief Resize the faces to n elements. */
863  inline void
864  resizeFaces (const std::size_t n, const FaceData& data = FaceData ())
865  {
866  faces_.resize (n);
867  this->resizeData (face_data_cloud_, n, data, HasFaceData ());
868  }
869 
870  ////////////////////////////////////////////////////////////////////////
871  // clear
872  ////////////////////////////////////////////////////////////////////////
873 
874  /** \brief Clear all mesh elements and data. */
875  void
876  clear ()
877  {
878  vertices_.clear ();
879  half_edges_.clear ();
880  faces_.clear ();
881 
882  this->clearData (vertex_data_cloud_ , HasVertexData ());
883  this->clearData (half_edge_data_cloud_, HasHalfEdgeData ());
884  this->clearData (edge_data_cloud_ , HasEdgeData ());
885  this->clearData (face_data_cloud_ , HasFaceData ());
886  }
887 
888  ////////////////////////////////////////////////////////////////////////
889  // get / set the vertex data cloud
890  ////////////////////////////////////////////////////////////////////////
891 
892  /** \brief Get access to the stored vertex data.
893  * \warning Please make sure to NOT add or remove elements from the cloud.
894  */
895  inline VertexDataCloud&
897  {
898  return (vertex_data_cloud_);
899  }
900 
901  /** \brief Get the stored vertex data. */
902  inline VertexDataCloud
904  {
905  return (vertex_data_cloud_);
906  }
907 
908  /** \brief Change the stored vertex data.
909  * \param[in] vertex_data_cloud The new vertex data. Must be the same as the current data.
910  * \return true if the cloud could be set.
911  */
912  inline bool
913  setVertexDataCloud (const VertexDataCloud& vertex_data_cloud)
914  {
915  if (vertex_data_cloud.size () == vertex_data_cloud_.size ())
916  {
917  vertex_data_cloud_ = vertex_data_cloud;
918  return (true);
919  }
920  return (false);
921  }
922 
923  ////////////////////////////////////////////////////////////////////////
924  // get / set the half-edge data cloud
925  ////////////////////////////////////////////////////////////////////////
926 
927  /** \brief Get access to the stored half-edge data.
928  * \warning Please make sure to NOT add or remove elements from the cloud.
929  */
930  inline HalfEdgeDataCloud&
932  {
933  return (half_edge_data_cloud_);
934  }
935 
936  /** \brief Get the stored half-edge data. */
937  inline HalfEdgeDataCloud
939  {
940  return (half_edge_data_cloud_);
941  }
942 
943  /** \brief Change the stored half-edge data.
944  * \param[in] half_edge_data_cloud The new half-edge data. Must be the same as the current data.
945  * \return true if the cloud could be set.
946  */
947  inline bool
948  setHalfEdgeDataCloud (const HalfEdgeDataCloud& half_edge_data_cloud)
949  {
950  if (half_edge_data_cloud.size () == half_edge_data_cloud_.size ())
951  {
952  half_edge_data_cloud_ = half_edge_data_cloud;
953  return (true);
954  }
955  return (false);
956  }
957 
958  ////////////////////////////////////////////////////////////////////////
959  // get / set the edge data cloud
960  ////////////////////////////////////////////////////////////////////////
961 
962  /** \brief Get access to the stored edge data.
963  * \warning Please make sure to NOT add or remove elements from the cloud.
964  */
965  inline EdgeDataCloud&
967  {
968  return (edge_data_cloud_);
969  }
970 
971  /** \brief Get the stored edge data. */
972  inline EdgeDataCloud
974  {
975  return (edge_data_cloud_);
976  }
977 
978  /** \brief Change the stored edge data.
979  * \param[in] edge_data_cloud The new edge data. Must be the same as the current data.
980  * \return true if the cloud could be set.
981  */
982  inline bool
983  setEdgeDataCloud (const EdgeDataCloud& edge_data_cloud)
984  {
985  if (edge_data_cloud.size () == edge_data_cloud_.size ())
986  {
987  edge_data_cloud_ = edge_data_cloud;
988  return (true);
989  }
990  return (false);
991  }
992 
993  ////////////////////////////////////////////////////////////////////////
994  // get / set the face data cloud
995  ////////////////////////////////////////////////////////////////////////
996 
997  /** \brief Get access to the stored face data.
998  * \warning Please make sure to NOT add or remove elements from the cloud.
999  */
1000  inline FaceDataCloud&
1002  {
1003  return (face_data_cloud_);
1004  }
1005 
1006  /** \brief Get the stored face data. */
1007  inline FaceDataCloud
1009  {
1010  return (face_data_cloud_);
1011  }
1012 
1013  /** \brief Change the stored face data.
1014  * \param[in] face_data_cloud The new face data. Must be the same as the current data.
1015  * \return true if the cloud could be set.
1016  */
1017  inline bool
1018  setFaceDataCloud (const FaceDataCloud& face_data_cloud)
1019  {
1020  if (face_data_cloud.size () == face_data_cloud_.size ())
1021  {
1022  face_data_cloud_ = face_data_cloud;
1023  return (true);
1024  }
1025  return (false);
1026  }
1027 
1028  ////////////////////////////////////////////////////////////////////////
1029  // getVertexIndex / getHalfEdgeIndex / getEdgeIndex / getFaceIndex
1030  ////////////////////////////////////////////////////////////////////////
1031 
1032  /** \brief Get the index associated to the given vertex data.
1033  * \return Invalid index if the mesh does not have associated vertex data.
1034  */
1035  inline VertexIndex
1036  getVertexIndex (const VertexData& vertex_data) const
1037  {
1038  if (HasVertexData::value)
1039  {
1040  assert (&vertex_data >= &vertex_data_cloud_.front () && &vertex_data <= &vertex_data_cloud_.back ());
1041  return (VertexIndex (std::distance (&vertex_data_cloud_.front (), &vertex_data)));
1042  }
1043  return (VertexIndex ());
1044  }
1045 
1046  /** \brief Get the index associated to the given half-edge data. */
1047  inline HalfEdgeIndex
1048  getHalfEdgeIndex (const HalfEdgeData& half_edge_data) const
1049  {
1050  if (HasHalfEdgeData::value)
1051  {
1052  assert (&half_edge_data >= &half_edge_data_cloud_.front () && &half_edge_data <= &half_edge_data_cloud_.back ());
1053  return (HalfEdgeIndex (std::distance (&half_edge_data_cloud_.front (), &half_edge_data)));
1054  }
1055  return (HalfEdgeIndex ());
1056  }
1057 
1058  /** \brief Get the index associated to the given edge data. */
1059  inline EdgeIndex
1060  getEdgeIndex (const EdgeData& edge_data) const
1061  {
1062  if (HasEdgeData::value)
1063  {
1064  assert (&edge_data >= &edge_data_cloud_.front () && &edge_data <= &edge_data_cloud_.back ());
1065  return (EdgeIndex (std::distance (&edge_data_cloud_.front (), &edge_data)));
1066  }
1067  return (EdgeIndex ());
1068  }
1069 
1070  /** \brief Get the index associated to the given face data. */
1071  inline FaceIndex
1072  getFaceIndex (const FaceData& face_data) const
1073  {
1074  if (HasFaceData::value)
1075  {
1076  assert (&face_data >= &face_data_cloud_.front () && &face_data <= &face_data_cloud_.back ());
1077  return (FaceIndex (std::distance (&face_data_cloud_.front (), &face_data)));
1078  }
1079  return (FaceIndex ());
1080  }
1081 
1082  protected:
1083 
1084  ////////////////////////////////////////////////////////////////////////
1085  // Types
1086  ////////////////////////////////////////////////////////////////////////
1087 
1088  // Elements
1092 
1093  using Vertices = std::vector<Vertex>;
1094  using HalfEdges = std::vector<HalfEdge>;
1095  using Faces = std::vector<Face>;
1096 
1097  using VertexIterator = typename Vertices::iterator;
1098  using HalfEdgeIterator = typename HalfEdges::iterator;
1099  using FaceIterator = typename Faces::iterator;
1100 
1101  using VertexConstIterator = typename Vertices::const_iterator;
1102  using HalfEdgeConstIterator = typename HalfEdges::const_iterator;
1103  using FaceConstIterator = typename Faces::const_iterator;
1104 
1105  /** \brief General implementation of addFace. */
1106  FaceIndex
1107  addFaceImplBase (const VertexIndices& vertices,
1108  const FaceData& face_data,
1109  const EdgeData& edge_data,
1110  const HalfEdgeData& half_edge_data)
1111  {
1112  const int n = static_cast<int> (vertices.size ());
1113  if (n < 3) return (FaceIndex ());
1114 
1115  // Check for topological errors
1116  inner_he_.resize (n);
1117  free_he_.resize (n);
1118  is_new_.resize (n);
1119  make_adjacent_.resize (n);
1120  for (int i=0; i<n; ++i)
1121  {
1122  if (!this->checkTopology1 (vertices [i], vertices [(i+1)%n], inner_he_ [i], is_new_ [i], IsManifold ()))
1123  {
1124  return (FaceIndex ());
1125  }
1126  }
1127  for (int i=0; i<n; ++i)
1128  {
1129  int j = (i+1)%n;
1130  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 ()))
1131  {
1132  return (FaceIndex ());
1133  }
1134  }
1135 
1136  // Reconnect the existing half-edges if needed
1137  if (!IsManifold::value)
1138  {
1139  for (int i=0; i<n; ++i)
1140  {
1141  if (make_adjacent_ [i])
1142  {
1143  this->makeAdjacent (inner_he_ [i], inner_he_ [(i+1)%n], free_he_ [i]);
1144  }
1145  }
1146  }
1147 
1148  // Add new half-edges if needed
1149  for (int i=0; i<n; ++i)
1150  {
1151  if (is_new_ [i])
1152  {
1153  inner_he_ [i] = this->addEdge (vertices [i], vertices [(i+1)%n], half_edge_data, edge_data);
1154  }
1155  }
1156 
1157  // Connect
1158  for (int i=0; i<n; ++i)
1159  {
1160  int j = (i+1)%n;
1161  if ( is_new_ [i] && is_new_ [j]) this->connectNewNew (inner_he_ [i], inner_he_ [j], vertices [j], IsManifold ());
1162  else if ( is_new_ [i] && !is_new_ [j]) this->connectNewOld (inner_he_ [i], inner_he_ [j], vertices [j]);
1163  else if (!is_new_ [i] && is_new_ [j]) this->connectOldNew (inner_he_ [i], inner_he_ [j], vertices [j]);
1164  else this->connectOldOld (inner_he_ [i], inner_he_ [j], vertices [j], IsManifold ());
1165  }
1166  return (this->connectFace (inner_he_, face_data));
1167  }
1168 
1169  ////////////////////////////////////////////////////////////////////////
1170  // addEdge
1171  ////////////////////////////////////////////////////////////////////////
1172 
1173  /** \brief Add an edge between the two given vertices and connect them with the vertices.
1174  * \param[in] idx_v_a The first vertex index
1175  * \param[in] idx_v_b The second vertex index
1176  * \param[in] he_data Data associated with the half-edges. This is only added if the mesh has data associated with the half-edges.
1177  * \param[in] edge_data Data associated with the edge. This is only added if the mesh has data associated with the edges.
1178  * \return Index to the half-edge from vertex a to vertex b.
1179  */
1181  addEdge (const VertexIndex& idx_v_a,
1182  const VertexIndex& idx_v_b,
1183  const HalfEdgeData& he_data,
1184  const EdgeData& edge_data)
1185  {
1186  half_edges_.push_back (HalfEdge (idx_v_b));
1187  half_edges_.push_back (HalfEdge (idx_v_a));
1188 
1189  this->addData (half_edge_data_cloud_, he_data , HasHalfEdgeData ());
1190  this->addData (half_edge_data_cloud_, he_data , HasHalfEdgeData ());
1191  this->addData (edge_data_cloud_ , edge_data, HasEdgeData ());
1192 
1193  return (HalfEdgeIndex (static_cast <int> (half_edges_.size () - 2)));
1194  }
1195 
1196  ////////////////////////////////////////////////////////////////////////
1197  // topology checks
1198  ////////////////////////////////////////////////////////////////////////
1199 
1200  /** \brief Check if the edge between the two vertices can be added.
1201  * \param[in] idx_v_a Index to the first vertex.
1202  * \param[in] idx_v_b Index to the second vertex.
1203  * \param[out] idx_he_ab Index to the half-edge ab if is_new_ab=false.
1204  * \param[out] is_new_ab true if the edge between the vertices exists already. Must be initialized with true!
1205  * \return true if the half-edge may be added.
1206  */
1207  bool
1208  checkTopology1 (const VertexIndex& idx_v_a,
1209  const VertexIndex& idx_v_b,
1210  HalfEdgeIndex& idx_he_ab,
1211  std::vector <bool>::reference is_new_ab,
1212  std::true_type /*is_manifold*/) const
1213  {
1214  is_new_ab = true;
1215  if (this->isIsolated (idx_v_a)) return (true);
1216 
1217  idx_he_ab = this->getOutgoingHalfEdgeIndex (idx_v_a);
1218 
1219  if (!this->isBoundary (idx_he_ab)) return (false);
1220  if (this->getTerminatingVertexIndex (idx_he_ab) == idx_v_b) is_new_ab = false;
1221  return (true);
1222  }
1223 
1224  /** \brief Non manifold version of checkTopology1 */
1225  bool
1226  checkTopology1 (const VertexIndex& idx_v_a,
1227  const VertexIndex& idx_v_b,
1228  HalfEdgeIndex& idx_he_ab,
1229  std::vector <bool>::reference is_new_ab,
1230  std::false_type /*is_manifold*/) const
1231  {
1232  is_new_ab = true;
1233  if (this->isIsolated (idx_v_a)) return (true);
1234  if (!this->isBoundary (this->getOutgoingHalfEdgeIndex (idx_v_a))) return (false);
1235 
1237  const VertexAroundVertexCirculator circ_end = circ;
1238 
1239  do
1240  {
1241  if (circ.getTargetIndex () == idx_v_b)
1242  {
1243  idx_he_ab = circ.getCurrentHalfEdgeIndex ();
1244  if (!this->isBoundary (idx_he_ab)) return (false);
1245 
1246  is_new_ab = false;
1247  return (true);
1248  }
1249  } while (++circ!=circ_end);
1250 
1251  return (true);
1252  }
1253 
1254  /** \brief Check if the face may be added (mesh does not become non-manifold). */
1255  inline bool
1256  checkTopology2 (const HalfEdgeIndex& /*idx_he_ab*/,
1257  const HalfEdgeIndex& /*idx_he_bc*/,
1258  const bool is_new_ab,
1259  const bool is_new_bc,
1260  const bool is_isolated_b,
1261  std::vector <bool>::reference /*make_adjacent_ab_bc*/,
1262  HalfEdgeIndex& /*idx_free_half_edge*/,
1263  std::true_type /*is_manifold*/) const
1264  {
1265  return !(is_new_ab && is_new_bc && !is_isolated_b);
1266  }
1267 
1268  /** \brief Check if the half-edge bc is the next half-edge of ab.
1269  * \param[in] idx_he_ab Index to the half-edge between the vertices a and b.
1270  * \param[in] idx_he_bc Index to the half-edge between the vertices b and c.
1271  * \param[in] is_new_ab Half-edge ab is new.
1272  * \param[in] is_new_bc Half-edge bc is new.
1273  * \param[out] make_adjacent_ab_bc Half-edges ab and bc need to be made adjacent.
1274  * \param[out] idx_free_half_edge Free half-edge (needed for makeAdjacent)
1275  * \return true if addFace may be continued.
1276  */
1277  inline bool
1278  checkTopology2 (const HalfEdgeIndex& idx_he_ab,
1279  const HalfEdgeIndex& idx_he_bc,
1280  const bool is_new_ab,
1281  const bool is_new_bc,
1282  const bool /*is_isolated_b*/,
1283  std::vector <bool>::reference make_adjacent_ab_bc,
1284  HalfEdgeIndex& idx_free_half_edge,
1285  std::false_type /*is_manifold*/) const
1286  {
1287  if (is_new_ab || is_new_bc)
1288  {
1289  make_adjacent_ab_bc = false;
1290  return (true); // Make adjacent is only needed for two old half-edges
1291  }
1292 
1293  if (this->getNextHalfEdgeIndex (idx_he_ab) == idx_he_bc)
1294  {
1295  make_adjacent_ab_bc = false;
1296  return (true); // already adjacent
1297  }
1298 
1299  make_adjacent_ab_bc = true;
1300 
1301  // Find the next boundary half edge
1303 
1304  do ++circ; while (!this->isBoundary (circ.getTargetIndex ()));
1305  idx_free_half_edge = circ.getTargetIndex ();
1306 
1307  // This would detach the faces around the vertex from each other.
1308  return (circ.getTargetIndex () != idx_he_ab);
1309  }
1310 
1311  /** \brief Make the half-edges bc the next half-edge of ab.
1312  * \param[in] idx_he_ab Index to the half-edge between the vertices a and b.
1313  * \param[in] idx_he_bc Index to the half-edge between the vertices b and c.
1314  * \param[in, out] idx_free_half_edge Free half-edge needed to re-connect the half-edges around vertex b.
1315  */
1316  void
1317  makeAdjacent (const HalfEdgeIndex& idx_he_ab,
1318  const HalfEdgeIndex& idx_he_bc,
1319  HalfEdgeIndex& idx_free_half_edge)
1320  {
1321  // Re-link. No references!
1322  const HalfEdgeIndex idx_he_ab_next = this->getNextHalfEdgeIndex (idx_he_ab);
1323  const HalfEdgeIndex idx_he_bc_prev = this->getPrevHalfEdgeIndex (idx_he_bc);
1324  const HalfEdgeIndex idx_he_free_next = this->getNextHalfEdgeIndex (idx_free_half_edge);
1325 
1326  this->connectPrevNext (idx_he_ab, idx_he_bc);
1327  this->connectPrevNext (idx_free_half_edge, idx_he_ab_next);
1328  this->connectPrevNext (idx_he_bc_prev, idx_he_free_next);
1329  }
1330 
1331  ////////////////////////////////////////////////////////////////////////
1332  // connect
1333  ////////////////////////////////////////////////////////////////////////
1334 
1335  /** \brief Add a face to the mesh and connect it to the half-edges.
1336  * \param[in] inner_he Inner half-edges of the face.
1337  * \param[in] face_data Data that is stored in the face. This is only added if the mesh has data associated with the faces.
1338  * \return Index to the new face.
1339  */
1340  FaceIndex
1341  connectFace (const HalfEdgeIndices& inner_he,
1342  const FaceData& face_data)
1343  {
1344  faces_.push_back (Face (inner_he.back ()));
1345  this->addData (face_data_cloud_, face_data, HasFaceData ());
1346 
1347  const FaceIndex idx_face (static_cast <int> (this->sizeFaces () - 1));
1348 
1349  for (const auto &idx_half_edge : inner_he)
1350  {
1351  this->setFaceIndex (idx_half_edge, idx_face);
1352  }
1353 
1354  return (idx_face);
1355  }
1356 
1357  /** \brief Connect the next and prev indices of the two half-edges with each other. */
1358  inline void
1359  connectPrevNext (const HalfEdgeIndex& idx_he_ab,
1360  const HalfEdgeIndex& idx_he_bc)
1361  {
1362  this->setNextHalfEdgeIndex (idx_he_ab, idx_he_bc);
1363  this->setPrevHalfEdgeIndex (idx_he_bc, idx_he_ab);
1364  }
1365 
1366  /** \brief Both half-edges are new (manifold version). */
1367  void
1368  connectNewNew (const HalfEdgeIndex& idx_he_ab,
1369  const HalfEdgeIndex& idx_he_bc,
1370  const VertexIndex& idx_v_b,
1371  std::true_type /*is_manifold*/)
1372  {
1373  const HalfEdgeIndex idx_he_ba = this->getOppositeHalfEdgeIndex (idx_he_ab);
1374  const HalfEdgeIndex idx_he_cb = this->getOppositeHalfEdgeIndex (idx_he_bc);
1375 
1376  this->connectPrevNext (idx_he_ab, idx_he_bc);
1377  this->connectPrevNext (idx_he_cb, idx_he_ba);
1378 
1379  this->setOutgoingHalfEdgeIndex (idx_v_b, idx_he_ba);
1380  }
1381 
1382  /** \brief Both half-edges are new (non-manifold version). */
1383  void
1384  connectNewNew (const HalfEdgeIndex& idx_he_ab,
1385  const HalfEdgeIndex& idx_he_bc,
1386  const VertexIndex& idx_v_b,
1387  std::false_type /*is_manifold*/)
1388  {
1389  if (this->isIsolated (idx_v_b))
1390  {
1391  this->connectNewNew (idx_he_ab, idx_he_bc, idx_v_b, std::true_type ());
1392  }
1393  else
1394  {
1395  const HalfEdgeIndex idx_he_ba = this->getOppositeHalfEdgeIndex (idx_he_ab);
1396  const HalfEdgeIndex idx_he_cb = this->getOppositeHalfEdgeIndex (idx_he_bc);
1397 
1398  // No references!
1399  const HalfEdgeIndex idx_he_b_out = this->getOutgoingHalfEdgeIndex (idx_v_b);
1400  const HalfEdgeIndex idx_he_b_out_prev = this->getPrevHalfEdgeIndex (idx_he_b_out);
1401 
1402  this->connectPrevNext (idx_he_ab, idx_he_bc);
1403  this->connectPrevNext (idx_he_cb, idx_he_b_out);
1404  this->connectPrevNext (idx_he_b_out_prev, idx_he_ba);
1405  }
1406  }
1407 
1408  /** \brief The first half-edge is new. */
1409  void
1410  connectNewOld (const HalfEdgeIndex& idx_he_ab,
1411  const HalfEdgeIndex& idx_he_bc,
1412  const VertexIndex& idx_v_b)
1413  {
1414  const HalfEdgeIndex idx_he_ba = this->getOppositeHalfEdgeIndex (idx_he_ab);
1415  const HalfEdgeIndex idx_he_bc_prev = this->getPrevHalfEdgeIndex (idx_he_bc); // No reference!
1416 
1417  this->connectPrevNext (idx_he_ab, idx_he_bc);
1418  this->connectPrevNext (idx_he_bc_prev, idx_he_ba);
1419 
1420  this->setOutgoingHalfEdgeIndex (idx_v_b, idx_he_ba);
1421  }
1422 
1423  /** \brief The second half-edge is new. */
1424  void
1425  connectOldNew (const HalfEdgeIndex& idx_he_ab,
1426  const HalfEdgeIndex& idx_he_bc,
1427  const VertexIndex& idx_v_b)
1428  {
1429  const HalfEdgeIndex idx_he_cb = this->getOppositeHalfEdgeIndex (idx_he_bc);
1430  const HalfEdgeIndex idx_he_ab_next = this->getNextHalfEdgeIndex (idx_he_ab); // No reference!
1431 
1432  this->connectPrevNext (idx_he_ab, idx_he_bc);
1433  this->connectPrevNext (idx_he_cb, idx_he_ab_next);
1434 
1435  this->setOutgoingHalfEdgeIndex (idx_v_b, idx_he_ab_next);
1436  }
1437 
1438  /** \brief Both half-edges are old (manifold version). */
1439  void
1440  connectOldOld (const HalfEdgeIndex& /*idx_he_ab*/,
1441  const HalfEdgeIndex& /*idx_he_bc*/,
1442  const VertexIndex& /*idx_v_b*/,
1443  std::true_type /*is_manifold*/)
1444  {
1445  }
1446 
1447  /** \brief Both half-edges are old (non-manifold version). */
1448  void
1449  connectOldOld (const HalfEdgeIndex& /*idx_he_ab*/,
1450  const HalfEdgeIndex& idx_he_bc,
1451  const VertexIndex& idx_v_b,
1452  std::false_type /*is_manifold*/)
1453  {
1454  const HalfEdgeIndex& idx_he_b_out = this->getOutgoingHalfEdgeIndex (idx_v_b);
1455 
1456  // The outgoing half edge MUST be a boundary half-edge (if there is one)
1457  if (idx_he_b_out == idx_he_bc) // he_bc is no longer on the boundary
1458  {
1460  const OutgoingHalfEdgeAroundVertexCirculator circ_end = circ;
1461 
1462  while (++circ!=circ_end)
1463  {
1464  if (this->isBoundary (circ.getTargetIndex ()))
1465  {
1466  this->setOutgoingHalfEdgeIndex (idx_v_b, circ.getTargetIndex ());
1467  return;
1468  }
1469  }
1470  }
1471  }
1472 
1473  ////////////////////////////////////////////////////////////////////////
1474  // addData
1475  ////////////////////////////////////////////////////////////////////////
1476 
1477  /** \brief Add mesh data. */
1478  template <class DataT>
1479  inline void
1480  addData (pcl::PointCloud <DataT>& cloud, const DataT& data, std::true_type /*has_data*/)
1481  {
1482  cloud.push_back (data);
1483  }
1484 
1485  /** \brief Does nothing. */
1486  template <class DataT>
1487  inline void
1488  addData (pcl::PointCloud <DataT>& /*cloud*/, const DataT& /*data*/, std::false_type /*has_data*/)
1489  {
1490  }
1491 
1492  ////////////////////////////////////////////////////////////////////////
1493  // deleteFace
1494  ////////////////////////////////////////////////////////////////////////
1495 
1496  /** \brief Manifold version of deleteFace. If the mesh becomes non-manifold due to the delete operation the faces around the non-manifold vertex are deleted until the mesh becomes manifold again. */
1497  void
1498  deleteFace (const FaceIndex& idx_face,
1499  std::true_type /*is_manifold*/)
1500  {
1501  assert (this->isValid (idx_face));
1502  delete_faces_face_.clear ();
1503  delete_faces_face_.push_back (idx_face);
1504 
1505  while (!delete_faces_face_.empty ())
1506  {
1507  const FaceIndex idx_face_cur = delete_faces_face_.back ();
1508  delete_faces_face_.pop_back ();
1509 
1510  // This calls the non-manifold version of deleteFace, which will call the manifold version of reconnect.
1511  this->deleteFace (idx_face_cur, std::false_type ());
1512  }
1513  }
1514 
1515  /** \brief Non-manifold version of deleteFace. */
1516  void
1517  deleteFace (const FaceIndex& idx_face,
1518  std::false_type /*is_manifold*/)
1519  {
1520  assert (this->isValid (idx_face));
1521  if (this->isDeleted (idx_face)) return;
1522 
1523  // Store all half-edges in the face
1524  inner_he_.clear ();
1525  is_boundary_.clear ();
1527  const InnerHalfEdgeAroundFaceCirculator circ_end = circ;
1528  do
1529  {
1530  inner_he_.push_back (circ.getTargetIndex ());
1531  is_boundary_.push_back (this->isBoundary (this->getOppositeHalfEdgeIndex (circ.getTargetIndex ())));
1532  } while (++circ != circ_end);
1533  assert (inner_he_.size () >= 3); // Minimum should be a triangle.
1534 
1535  const int n = static_cast <int> (inner_he_.size ());
1536  int j;
1537 
1538  if (IsManifold::value)
1539  {
1540  for (int i=0; i<n; ++i)
1541  {
1542  j = (i+1)%n;
1543  this->reconnect (inner_he_ [i], inner_he_ [j], is_boundary_ [i], is_boundary_ [j]);
1544  }
1545  for (int i=0; i<n; ++i)
1546  {
1547  this->getHalfEdge (inner_he_ [i]).idx_face_.invalidate ();
1548  }
1549  }
1550  else
1551  {
1552  for (int i=0; i<n; ++i)
1553  {
1554  j = (i+1)%n;
1555  this->reconnect (inner_he_ [i], inner_he_ [j], is_boundary_ [i], is_boundary_ [j]);
1556  this->getHalfEdge (inner_he_ [i]).idx_face_.invalidate ();
1557  }
1558  }
1559 
1560  this->markDeleted (idx_face);
1561  }
1562 
1563  ////////////////////////////////////////////////////////////////////////
1564  // reconnect
1565  ////////////////////////////////////////////////////////////////////////
1566 
1567  /** \brief Deconnect the input half-edges from the mesh and adjust the indices of the connected half-edges. */
1568  void
1569  reconnect (const HalfEdgeIndex& idx_he_ab,
1570  const HalfEdgeIndex& idx_he_bc,
1571  const bool is_boundary_ba,
1572  const bool is_boundary_cb)
1573  {
1574  const HalfEdgeIndex idx_he_ba = this->getOppositeHalfEdgeIndex (idx_he_ab);
1575  const HalfEdgeIndex idx_he_cb = this->getOppositeHalfEdgeIndex (idx_he_bc);
1576  const VertexIndex idx_v_b = this->getTerminatingVertexIndex (idx_he_ab);
1577 
1578  if (is_boundary_ba && is_boundary_cb) // boundary - boundary
1579  {
1580  const HalfEdgeIndex& idx_he_cb_next = this->getNextHalfEdgeIndex (idx_he_cb);
1581 
1582  if (idx_he_cb_next == idx_he_ba) // Vertex b is isolated
1583  {
1584  this->markDeleted (idx_v_b);
1585  }
1586  else
1587  {
1588  this->connectPrevNext (this->getPrevHalfEdgeIndex (idx_he_ba), idx_he_cb_next);
1589  this->setOutgoingHalfEdgeIndex (idx_v_b, idx_he_cb_next);
1590  }
1591 
1592  this->markDeleted (idx_he_ab);
1593  this->markDeleted (idx_he_ba);
1594  }
1595  else if (is_boundary_ba && !is_boundary_cb) // boundary - no boundary
1596  {
1597  this->connectPrevNext (this->getPrevHalfEdgeIndex (idx_he_ba), idx_he_bc);
1598  this->setOutgoingHalfEdgeIndex (idx_v_b, idx_he_bc);
1599 
1600  this->markDeleted (idx_he_ab);
1601  this->markDeleted (idx_he_ba);
1602  }
1603  else if (!is_boundary_ba && is_boundary_cb) // no boundary - boundary
1604  {
1605  const HalfEdgeIndex& idx_he_cb_next = this->getNextHalfEdgeIndex (idx_he_cb);
1606  this->connectPrevNext (idx_he_ab, idx_he_cb_next);
1607  this->setOutgoingHalfEdgeIndex (idx_v_b, idx_he_cb_next);
1608  }
1609  else // no boundary - no boundary
1610  {
1611  this->reconnectNBNB (idx_he_bc, idx_he_cb, idx_v_b, IsManifold ());
1612  }
1613  }
1614 
1615  /** \brief Both edges are not on the boundary. Manifold version. */
1616  void
1617  reconnectNBNB (const HalfEdgeIndex& idx_he_bc,
1618  const HalfEdgeIndex& idx_he_cb,
1619  const VertexIndex& idx_v_b,
1620  std::true_type /*is_manifold*/)
1621  {
1622  if (this->isBoundary (idx_v_b))
1623  {
1624  // Deletion of this face makes the mesh non-manifold
1625  // -> delete the neighboring faces until it is manifold again
1627 
1628  while (!this->isBoundary (circ.getTargetIndex ()))
1629  {
1630  delete_faces_face_.push_back (this->getFaceIndex ((circ++).getTargetIndex ()));
1631 
1632 #ifdef PCL_GEOMETRY_MESH_BASE_TEST_DELETE_FACE_MANIFOLD_2
1633  if (circ == this->getIncomingHalfEdgeAroundVertexCirculator (idx_he_cb)) // Abort infinity loop
1634  {
1635  // In a manifold mesh we can't invalidate the face while reconnecting!
1636  // See the implementation of
1637  // deleteFace (const FaceIndex& idx_face,
1638  // std::false_type /*is_manifold*/)
1639  pcl::geometry::g_pcl_geometry_mesh_base_test_delete_face_manifold_2_success = false;
1640  return;
1641  }
1642 #endif
1643  }
1644  }
1645  else
1646  {
1647  this->setOutgoingHalfEdgeIndex (idx_v_b, idx_he_bc);
1648  }
1649  }
1650 
1651  /** \brief Both edges are not on the boundary. Non-manifold version. */
1652  void
1653  reconnectNBNB (const HalfEdgeIndex& idx_he_bc,
1654  const HalfEdgeIndex& /*idx_he_cb*/,
1655  const VertexIndex& idx_v_b,
1656  std::false_type /*is_manifold*/)
1657  {
1658  if (!this->isBoundary (idx_v_b))
1659  {
1660  this->setOutgoingHalfEdgeIndex (idx_v_b, idx_he_bc);
1661  }
1662  }
1663 
1664  ////////////////////////////////////////////////////////////////////////
1665  // markDeleted
1666  ////////////////////////////////////////////////////////////////////////
1667 
1668  /** \brief Mark the given vertex as deleted. */
1669  inline void
1670  markDeleted (const VertexIndex& idx_vertex)
1671  {
1672  assert (this->isValid (idx_vertex));
1673  this->getVertex (idx_vertex).idx_outgoing_half_edge_.invalidate ();
1674  }
1675 
1676  /** \brief Mark the given half-edge as deleted. */
1677  inline void
1678  markDeleted (const HalfEdgeIndex& idx_he)
1679  {
1680  assert (this->isValid (idx_he));
1681  this->getHalfEdge (idx_he).idx_terminating_vertex_.invalidate ();
1682  }
1683 
1684  /** \brief Mark the given edge (both half-edges) as deleted. */
1685  inline void
1686  markDeleted (const EdgeIndex& idx_edge)
1687  {
1688  assert (this->isValid (idx_edge));
1689  this->markDeleted (pcl::geometry::toHalfEdgeIndex (idx_edge, true));
1690  this->markDeleted (pcl::geometry::toHalfEdgeIndex (idx_edge, false));
1691  }
1692 
1693  /** \brief Mark the given face as deleted. */
1694  inline void
1695  markDeleted (const FaceIndex& idx_face)
1696  {
1697  assert (this->isValid (idx_face));
1698  this->getFace (idx_face).idx_inner_half_edge_.invalidate ();
1699  }
1700 
1701  ////////////////////////////////////////////////////////////////////////
1702  // For cleanUp
1703  ////////////////////////////////////////////////////////////////////////
1704 
1705  /** \brief Removes mesh elements and data that are marked as deleted from the container.
1706  * \tparam ElementContainerT e.g. std::vector <Vertex>
1707  * \tparam DataContainerT e.g. std::vector <VertexData>
1708  * \tparam IndexContainerT e.g. std::vector <VertexIndex>
1709  * \tparam HasDataT Integral constant specifying if the mesh has data associated with the elements.
1710  *
1711  * \param[in, out] elements Container for the mesh elements. Resized to the new size.
1712  * \param[in, out] data_cloud Container for the mesh data. Resized to the new size.
1713  * \return Container with the same size as the old input data. Holds the indices to the new elements for each non-deleted element and an invalid index if it is deleted.
1714  */
1715  template <class ElementContainerT, class DataContainerT, class IndexContainerT, class HasDataT> IndexContainerT
1716  remove (ElementContainerT& elements, DataContainerT& data_cloud)
1717  {
1718  using Index = typename IndexContainerT::value_type;
1719  using Element = typename ElementContainerT::value_type;
1720 
1721  if (HasDataT::value) assert (elements.size () == data_cloud.size ());
1722  else assert (data_cloud.empty ()); // Bug in this class!
1723 
1724  IndexContainerT new_indices (elements.size (), typename IndexContainerT::value_type ());
1725  Index ind_old (0), ind_new (0);
1726 
1727  typename ElementContainerT::const_iterator it_e_old = elements.begin ();
1728  typename ElementContainerT::iterator it_e_new = elements.begin ();
1729 
1730  typename DataContainerT::const_iterator it_d_old = data_cloud.begin ();
1731  typename DataContainerT::iterator it_d_new = data_cloud.begin ();
1732 
1733  typename IndexContainerT::iterator it_ind_new = new_indices.begin ();
1734  typename IndexContainerT::const_iterator it_ind_new_end = new_indices.end ();
1735 
1736  while (it_ind_new!=it_ind_new_end)
1737  {
1738  if (!this->isDeleted (ind_old))
1739  {
1740  *it_ind_new = ind_new++;
1741 
1742  // TODO: Test for self assignment?
1743  *it_e_new++ = *it_e_old;
1744  this->assignIf (it_d_old, it_d_new, HasDataT ());
1745  this->incrementIf ( it_d_new, HasDataT ());
1746  }
1747  ++ind_old;
1748  ++it_e_old;
1749  this->incrementIf (it_d_old, HasDataT ());
1750  ++it_ind_new;
1751  }
1752 
1753  elements.resize (ind_new.get (), Element ());
1754  if (HasDataT::value)
1755  {
1756  data_cloud.resize (ind_new.get ());
1757  }
1758  else if (it_d_old != data_cloud.begin () || it_d_new != data_cloud.begin ())
1759  {
1760  std::cerr << "TODO: Bug in MeshBase::remove!\n";
1761  assert (false);
1762  exit (EXIT_FAILURE);
1763  }
1764 
1765  return (new_indices);
1766  }
1767 
1768  /** \brief Increment the iterator. */
1769  template <class IteratorT> inline void
1770  incrementIf (IteratorT& it, std::true_type /*has_data*/) const
1771  {
1772  ++it;
1773  }
1774 
1775  /** \brief Does nothing. */
1776  template <class IteratorT> inline void
1777  incrementIf (IteratorT& /*it*/, std::false_type /*has_data*/) const
1778  {
1779  }
1780 
1781  /** \brief Assign the source iterator to the target iterator. */
1782  template <class ConstIteratorT, class IteratorT> inline void
1783  assignIf (const ConstIteratorT source, IteratorT target, std::true_type /*has_data*/) const
1784  {
1785  *target = *source;
1786  }
1787 
1788  /** \brief Does nothing. */
1789  template <class ConstIteratorT, class IteratorT> inline void
1790  assignIf (const ConstIteratorT /*source*/, IteratorT /*target*/, std::false_type /*has_data*/) const
1791  {
1792  }
1793 
1794  ////////////////////////////////////////////////////////////////////////
1795  // Vertex / Half-edge / Face connectivity
1796  ////////////////////////////////////////////////////////////////////////
1797 
1798  /** \brief Set the outgoing half-edge index to a given vertex. */
1799  inline void
1800  setOutgoingHalfEdgeIndex (const VertexIndex& idx_vertex, const HalfEdgeIndex& idx_outgoing_half_edge)
1801  {
1802  assert (this->isValid (idx_vertex));
1803  this->getVertex (idx_vertex).idx_outgoing_half_edge_ = idx_outgoing_half_edge;
1804  }
1805 
1806  /** \brief Set the terminating vertex index to a given half-edge. */
1807  inline void
1808  setTerminatingVertexIndex (const HalfEdgeIndex& idx_half_edge, const VertexIndex& idx_terminating_vertex)
1809  {
1810  assert (this->isValid (idx_half_edge));
1811  this->getHalfEdge (idx_half_edge).idx_terminating_vertex_ = idx_terminating_vertex;
1812  }
1813 
1814  /** \brief Set the next half_edge index to a given half-edge. */
1815  inline void
1816  setNextHalfEdgeIndex (const HalfEdgeIndex& idx_half_edge, const HalfEdgeIndex& idx_next_half_edge)
1817  {
1818  assert (this->isValid (idx_half_edge));
1819  this->getHalfEdge (idx_half_edge).idx_next_half_edge_ = idx_next_half_edge;
1820  }
1821 
1822  /** \brief Set the previous half-edge index to a given half-edge. */
1823  inline void
1824  setPrevHalfEdgeIndex (const HalfEdgeIndex& idx_half_edge,
1825  const HalfEdgeIndex& idx_prev_half_edge)
1826  {
1827  assert (this->isValid (idx_half_edge));
1828  this->getHalfEdge (idx_half_edge).idx_prev_half_edge_ = idx_prev_half_edge;
1829  }
1830 
1831  /** \brief Set the face index to a given half-edge. */
1832  inline void
1833  setFaceIndex (const HalfEdgeIndex& idx_half_edge, const FaceIndex& idx_face)
1834  {
1835  assert (this->isValid (idx_half_edge));
1836  this->getHalfEdge (idx_half_edge).idx_face_ = idx_face;
1837  }
1838 
1839  /** \brief Set the inner half-edge index to a given face. */
1840  inline void
1841  setInnerHalfEdgeIndex (const FaceIndex& idx_face, const HalfEdgeIndex& idx_inner_half_edge)
1842  {
1843  assert (this->isValid (idx_face));
1844  this->getFace (idx_face).idx_inner_half_edge_ = idx_inner_half_edge;
1845  }
1846 
1847  ////////////////////////////////////////////////////////////////////////
1848  // isBoundary / isManifold
1849  ////////////////////////////////////////////////////////////////////////
1850 
1851  /** \brief Check if any vertex of the face lies on the boundary. */
1852  bool
1853  isBoundary (const FaceIndex& idx_face, std::true_type /*check_vertices*/) const
1854  {
1856  const VertexAroundFaceCirculator circ_end = circ;
1857 
1858  do
1859  {
1860  if (this->isBoundary (circ.getTargetIndex ()))
1861  {
1862  return (true);
1863  }
1864  } while (++circ!=circ_end);
1865 
1866  return (false);
1867  }
1868 
1869  /** \brief Check if any edge of the face lies on the boundary. */
1870  bool
1871  isBoundary (const FaceIndex& idx_face, std::false_type /*check_vertices*/) const
1872  {
1874  const OuterHalfEdgeAroundFaceCirculator circ_end = circ;
1875 
1876  do
1877  {
1878  if (this->isBoundary (circ.getTargetIndex ()))
1879  {
1880  return (true);
1881  }
1882  } while (++circ!=circ_end);
1883 
1884  return (false);
1885  }
1886 
1887  /** \brief Always manifold. */
1888  inline bool
1889  isManifold (const VertexIndex&, std::true_type /*is_manifold*/) const
1890  {
1891  return (true);
1892  }
1893 
1894  /** \brief Check if the given vertex is manifold. */
1895  bool
1896  isManifold (const VertexIndex& idx_vertex, std::false_type /*is_manifold*/) const
1897  {
1899  const OutgoingHalfEdgeAroundVertexCirculator circ_end = circ;
1900 
1901  if (!this->isBoundary ((circ++).getTargetIndex ())) return (true);
1902  do
1903  {
1904  if (this->isBoundary (circ.getTargetIndex ())) return (false);
1905  } while (++circ != circ_end);
1906 
1907  return (true);
1908  }
1909 
1910  /** \brief Always manifold. */
1911  inline bool
1912  isManifold (std::true_type /*is_manifold*/) const
1913  {
1914  return (true);
1915  }
1916 
1917  /** \brief Check if all vertices in the mesh are manifold. */
1918  bool
1919  isManifold (std::false_type /*is_manifold*/) const
1920  {
1921  for (std::size_t i=0; i<this->sizeVertices (); ++i)
1922  {
1923  if (!this->isManifold (VertexIndex (i))) return (false);
1924  }
1925  return (true);
1926  }
1927 
1928  ////////////////////////////////////////////////////////////////////////
1929  // reserveData / resizeData / clearData
1930  ////////////////////////////////////////////////////////////////////////
1931 
1932  /** \brief Reserve storage space for the mesh data. */
1933  template <class DataCloudT> inline void
1934  reserveData (DataCloudT& cloud, const std::size_t n, std::true_type /*has_data*/) const
1935  {
1936  cloud.reserve (n);
1937  }
1938 
1939  /** \brief Does nothing */
1940  template <class DataCloudT> inline void
1941  reserveData (DataCloudT& /*cloud*/, const std::size_t /*n*/, std::false_type /*has_data*/) const
1942  {
1943  }
1944 
1945  /** \brief Resize the mesh data. */
1946  template <class DataCloudT> inline void
1947  resizeData (DataCloudT& /*data_cloud*/, const std::size_t n, const typename DataCloudT::value_type& data, std::true_type /*has_data*/) const
1948  {
1949  data.resize (n, data);
1950  }
1951 
1952  /** \brief Does nothing. */
1953  template <class DataCloudT> inline void
1954  resizeData (DataCloudT& /*data_cloud*/, const std::size_t /*n*/, const typename DataCloudT::value_type& /*data*/, std::false_type /*has_data*/) const
1955  {
1956  }
1957 
1958  /** \brief Clear the mesh data. */
1959  template <class DataCloudT> inline void
1960  clearData (DataCloudT& cloud, std::true_type /*has_data*/) const
1961  {
1962  cloud.clear ();
1963  }
1964 
1965  /** \brief Does nothing. */
1966  template <class DataCloudT> inline void
1967  clearData (DataCloudT& /*cloud*/, std::false_type /*has_data*/) const
1968  {
1969  }
1970 
1971  ////////////////////////////////////////////////////////////////////////
1972  // get / set Vertex
1973  ////////////////////////////////////////////////////////////////////////
1974 
1975  /** \brief Get the vertex for the given index. */
1976  inline Vertex&
1977  getVertex (const VertexIndex& idx_vertex)
1978  {
1979  assert (this->isValid (idx_vertex));
1980  return (vertices_ [idx_vertex.get ()]);
1981  }
1982 
1983  /** \brief Get the vertex for the given index. */
1984  inline Vertex
1985  getVertex (const VertexIndex& idx_vertex) const
1986  {
1987  assert (this->isValid (idx_vertex));
1988  return (vertices_ [idx_vertex.get ()]);
1989  }
1990 
1991  /** \brief Set the vertex at the given index. */
1992  inline void
1993  setVertex (const VertexIndex& idx_vertex, const Vertex& vertex)
1994  {
1995  assert (this->isValid (idx_vertex));
1996  vertices_ [idx_vertex.get ()] = vertex;
1997  }
1998 
1999  ////////////////////////////////////////////////////////////////////////
2000  // get / set HalfEdge
2001  ////////////////////////////////////////////////////////////////////////
2002 
2003  /** \brief Get the half-edge for the given index. */
2004  inline HalfEdge&
2005  getHalfEdge (const HalfEdgeIndex& idx_he)
2006  {
2007  assert (this->isValid (idx_he));
2008  return (half_edges_ [idx_he.get ()]);
2009  }
2010 
2011  /** \brief Get the half-edge for the given index. */
2012  inline HalfEdge
2013  getHalfEdge (const HalfEdgeIndex& idx_he) const
2014  {
2015  assert (this->isValid (idx_he));
2016  return (half_edges_ [idx_he.get ()]);
2017  }
2018 
2019  /** \brief Set the half-edge at the given index. */
2020  inline void
2021  setHalfEdge (const HalfEdgeIndex& idx_he, const HalfEdge& half_edge)
2022  {
2023  assert (this->isValid (idx_he));
2024  half_edges_ [idx_he.get ()] = half_edge;
2025  }
2026 
2027  ////////////////////////////////////////////////////////////////////////
2028  // get / set Face
2029  ////////////////////////////////////////////////////////////////////////
2030 
2031  /** \brief Get the face for the given index. */
2032  inline Face&
2033  getFace (const FaceIndex& idx_face)
2034  {
2035  assert (this->isValid (idx_face));
2036  return (faces_ [idx_face.get ()]);
2037  }
2038 
2039  /** \brief Get the face for the given index. */
2040  inline Face
2041  getFace (const FaceIndex& idx_face) const
2042  {
2043  assert (this->isValid (idx_face));
2044  return (faces_ [idx_face.get ()]);
2045  }
2046 
2047  /** \brief Set the face at the given index. */
2048  inline void
2049  setFace (const FaceIndex& idx_face, const Face& face)
2050  {
2051  assert (this->isValid (idx_face));
2052  faces_ [idx_face.get ()] = face;
2053  }
2054 
2055  private:
2056 
2057  ////////////////////////////////////////////////////////////////////////
2058  // Members
2059  ////////////////////////////////////////////////////////////////////////
2060 
2061  /** \brief Data stored for the vertices. */
2062  VertexDataCloud vertex_data_cloud_;
2063 
2064  /** \brief Data stored for the half-edges. */
2065  HalfEdgeDataCloud half_edge_data_cloud_;
2066 
2067  /** \brief Data stored for the edges. */
2068  EdgeDataCloud edge_data_cloud_;
2069 
2070  /** \brief Data stored for the faces. */
2071  FaceDataCloud face_data_cloud_;
2072 
2073  /** \brief Connectivity information for the vertices. */
2074  Vertices vertices_;
2075 
2076  /** \brief Connectivity information for the half-edges. */
2077  HalfEdges half_edges_;
2078 
2079  /** \brief Connectivity information for the faces. */
2080  Faces faces_;
2081 
2082  // NOTE: It is MUCH faster to store these variables permamently.
2083 
2084  /** \brief Storage for addFaceImplBase and deleteFace. */
2085  HalfEdgeIndices inner_he_;
2086 
2087  /** \brief Storage for addFaceImplBase. */
2088  HalfEdgeIndices free_he_;
2089 
2090  /** \brief Storage for addFaceImplBase. */
2091  std::vector <bool> is_new_;
2092 
2093  /** \brief Storage for addFaceImplBase. */
2094  std::vector <bool> make_adjacent_;
2095 
2096  /** \brief Storage for deleteFace. */
2097  std::vector <bool> is_boundary_;
2098 
2099  /** \brief Storage for deleteVertex. */
2100  FaceIndices delete_faces_vertex_;
2101 
2102  /** \brief Storage for deleteFace. */
2103  FaceIndices delete_faces_face_;
2104 
2105  public:
2106 
2107  template <class MeshT>
2109 
2111  };
2112  } // End namespace geometry
2113 } // End namespace pcl
pcl::geometry::MeshBase::getIncomingHalfEdgeIndex
HalfEdgeIndex getIncomingHalfEdgeIndex(const VertexIndex &idx_vertex) const
Get the incoming half-edge index to a given vertex.
Definition: mesh_base.h:334
pcl::geometry::MeshBase::getVertexIndex
VertexIndex getVertexIndex(const VertexData &vertex_data) const
Get the index associated to the given vertex data.
Definition: mesh_base.h:1036
pcl::geometry::MeshBase::emptyEdges
bool emptyEdges() const
Check if the edges are empty.
Definition: mesh_base.h:798
pcl::geometry::MeshBase::setVertex
void setVertex(const VertexIndex &idx_vertex, const Vertex &vertex)
Set the vertex at the given index.
Definition: mesh_base.h:1993
pcl_macros.h
Defines all the PCL and non-PCL macros used.
pcl::geometry::MeshBase::isBoundary
bool isBoundary(const HalfEdgeIndex &idx_he) const
Check if the given half-edge lies on the bounddary.
Definition: mesh_base.h:691
pcl
Definition: convolution.h:46
pcl::geometry::MeshBase::connectOldNew
void connectOldNew(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b)
The second half-edge is new.
Definition: mesh_base.h:1425
pcl::geometry::HalfEdge
An edge is a connection between two vertices.
Definition: mesh_elements.h:106
pcl::geometry::MeshBase::getPrevHalfEdgeIndex
HalfEdgeIndex getPrevHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the previous half-edge index to a given half-edge.
Definition: mesh_base.h:379
pcl::geometry::MeshBase::isDeleted
bool isDeleted(const VertexIndex &idx_vertex) const
Check if the given vertex is marked as deleted.
Definition: mesh_base.h:633
pcl::geometry::MeshBase::setVertexDataCloud
bool setVertexDataCloud(const VertexDataCloud &vertex_data_cloud)
Change the stored vertex data.
Definition: mesh_base.h:913
pcl::geometry::MeshBase::getOppositeHalfEdgeIndex
HalfEdgeIndex getOppositeHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the opposite half-edge index to a given half-edge.
Definition: mesh_base.h:362
pcl::geometry::distance
float distance(const PointT &p1, const PointT &p2)
Definition: geometry.h:60
pcl::geometry::MeshBase::getOutgoingHalfEdgeIndex
HalfEdgeIndex getOutgoingHalfEdgeIndex(const VertexIndex &idx_vertex) const
Get the outgoing half-edge index to a given vertex.
Definition: mesh_base.h:326
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::HalfEdgeIterator
typename HalfEdges::iterator HalfEdgeIterator
Definition: mesh_base.h:1098
pcl::geometry::MeshBase::setPrevHalfEdgeIndex
void setPrevHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge, const HalfEdgeIndex &idx_prev_half_edge)
Set the previous half-edge index to a given half-edge.
Definition: mesh_base.h:1824
pcl::geometry::MeshBase::getIncomingHalfEdgeAroundVertexCirculator
IncomingHalfEdgeAroundVertexCirculator getIncomingHalfEdgeAroundVertexCirculator(const VertexIndex &idx_vertex) const
Definition: mesh_base.h:459
pcl::geometry::MeshBase::getFaceDataCloud
FaceDataCloud getFaceDataCloud() const
Get the stored face data.
Definition: mesh_base.h:1008
pcl::geometry::MeshBase::deleteEdge
void deleteEdge(const EdgeIndex &idx_edge)
Mark the given edge (both half-edges) and the associated faces as deleted.
Definition: mesh_base.h:242
pcl::geometry::MeshBase::empty
bool empty() const
Check if the mesh is empty.
Definition: mesh_base.h:784
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::EdgeIndices
std::vector< EdgeIndex > EdgeIndices
Definition: mesh_base.h:139
pcl::geometry::MeshBase::isValid
bool isValid(const EdgeIndex &idx_edge) const
Check if the given edge index is a valid index into the mesh.
Definition: mesh_base.h:615
pcl::geometry::MeshBase::resizeVertices
void resizeVertices(const std::size_t n, const VertexData &data=VertexData())
Resize the the vertices to n elements.
Definition: mesh_base.h:845
pcl::geometry::MeshBase::checkTopology2
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).
Definition: mesh_base.h:1256
pcl::geometry::MeshBase::getOutgoingHalfEdgeAroundVertexCirculator
OutgoingHalfEdgeAroundVertexCirculator getOutgoingHalfEdgeAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
Definition: mesh_base.h:451
pcl::geometry::OutgoingHalfEdgeAroundVertexCirculator::getTargetIndex
HalfEdgeIndex getTargetIndex() const
Get the index to the outgoing half-edge.
Definition: mesh_circulators.h:243
pcl::geometry::MeshBase::isIsolated
bool isIsolated(const VertexIndex &idx_vertex) const
Check if the given vertex is isolated (not connected to other elements).
Definition: mesh_base.h:670
pcl::PointCloud::begin
iterator begin() noexcept
Definition: point_cloud.h:422
pcl::geometry::MeshBase::emptyFaces
bool emptyFaces() const
Check if the faces are empty.
Definition: mesh_base.h:805
pcl::geometry::MeshBase::setInnerHalfEdgeIndex
void setInnerHalfEdgeIndex(const FaceIndex &idx_face, const HalfEdgeIndex &idx_inner_half_edge)
Set the inner half-edge index to a given face.
Definition: mesh_base.h:1841
pcl::geometry::MeshBase::addData
void addData(pcl::PointCloud< DataT > &cloud, const DataT &data, std::true_type)
Add mesh data.
Definition: mesh_base.h:1480
pcl::geometry::MeshBase::isManifold
bool isManifold(std::false_type) const
Check if all vertices in the mesh are manifold.
Definition: mesh_base.h:1919
pcl::geometry::MeshBase::getFaceAroundFaceCirculator
FaceAroundFaceCirculator getFaceAroundFaceCirculator(const FaceIndex &idx_face) const
Definition: mesh_base.h:539
pcl::geometry::MeshBase::getOriginatingVertexIndex
VertexIndex getOriginatingVertexIndex(const HalfEdgeIndex &idx_half_edge) const
Get the originating vertex index to a given half-edge.
Definition: mesh_base.h:354
pcl::geometry::MeshBase::isDeleted
bool isDeleted(const EdgeIndex &idx_edge) const
Check if the given edge (any of the two half-edges) is marked as deleted.
Definition: mesh_base.h:649
pcl::geometry::MeshBase::getVertexDataCloud
VertexDataCloud getVertexDataCloud() const
Get the stored vertex data.
Definition: mesh_base.h:903
pcl::geometry::MeshBase::getFaceDataCloud
FaceDataCloud & getFaceDataCloud()
Get access to the stored face data.
Definition: mesh_base.h:1001
pcl::geometry::MeshBase::clearData
void clearData(DataCloudT &cloud, std::true_type) const
Clear the mesh data.
Definition: mesh_base.h:1960
pcl::geometry::MeshBase::emptyVertices
bool emptyVertices() const
Check if the vertices are empty.
Definition: mesh_base.h:791
pcl::geometry::InnerHalfEdgeAroundFaceCirculator
Circulates clockwise around a face and returns an index to the inner half-edge (the target).
Definition: mesh_circulators.h:605
pcl::geometry::MeshBase::VertexDataCloud
pcl::PointCloud< VertexData > VertexDataCloud
Definition: mesh_base.h:126
pcl::geometry::MeshBase::checkTopology1
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.
Definition: mesh_base.h:1226
pcl::geometry::MeshBase::getNextHalfEdgeIndex
HalfEdgeIndex getNextHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge) const
Get the next half-edge index to a given half-edge.
Definition: mesh_base.h:371
pcl::geometry::MeshBase::setHalfEdgeDataCloud
bool setHalfEdgeDataCloud(const HalfEdgeDataCloud &half_edge_data_cloud)
Change the stored half-edge data.
Definition: mesh_base.h:948
pcl::geometry::Vertex
A vertex is a node in the mesh.
Definition: mesh_elements.h:69
pcl::geometry::MeshBase::MeshBase
MeshBase()
Constructor.
Definition: mesh_base.h:153
pcl::geometry::MeshBase::getVertexAroundVertexCirculator
VertexAroundVertexCirculator getVertexAroundVertexCirculator(const VertexIndex &idx_vertex) const
Definition: mesh_base.h:427
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::VertexData
typename MeshTraitsT::VertexData VertexData
Definition: mesh_base.h:109
pcl::geometry::MeshBase::setHalfEdge
void setHalfEdge(const HalfEdgeIndex &idx_he, const HalfEdge &half_edge)
Set the half-edge at the given index.
Definition: mesh_base.h:2021
pcl::geometry::MeshBase::resizeData
void resizeData(DataCloudT &, const std::size_t, const typename DataCloudT::value_type &, std::false_type) const
Does nothing.
Definition: mesh_base.h:1954
pcl::geometry::MeshBase::sizeVertices
std::size_t sizeVertices() const
Get the number of the vertices.
Definition: mesh_base.h:750
pcl::geometry::OuterHalfEdgeAroundFaceCirculator
Circulates clockwise around a face and returns an index to the outer half-edge (the target).
Definition: mesh_circulators.h:713
pcl::geometry::MeshBase::deleteEdge
void deleteEdge(const HalfEdgeIndex &idx_he)
Mark the given half-edge, the opposite half-edge and the associated faces as deleted.
Definition: mesh_base.h:225
pcl::geometry::MeshBase::connectPrevNext
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.
Definition: mesh_base.h:1359
pcl::geometry::MeshBase::reconnectNBNB
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.
Definition: mesh_base.h:1617
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::FaceIterator
typename Faces::iterator FaceIterator
Definition: mesh_base.h:1099
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::IsManifold
typename MeshTraitsT::IsManifold IsManifold
Definition: mesh_base.h:113
pcl::geometry::IncomingHalfEdgeAroundVertexCirculator
Circulates counter-clockwise around a vertex and returns an index to the incoming half-edge (the targ...
Definition: mesh_circulators.h:279
pcl::geometry::MeshBase::setNextHalfEdgeIndex
void setNextHalfEdgeIndex(const HalfEdgeIndex &idx_half_edge, const HalfEdgeIndex &idx_next_half_edge)
Set the next half_edge index to a given half-edge.
Definition: mesh_base.h:1816
pcl::geometry::MeshBase::connectOldOld
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).
Definition: mesh_base.h:1449
pcl::geometry::MeshBase::getVertex
Vertex getVertex(const VertexIndex &idx_vertex) const
Get the vertex for the given index.
Definition: mesh_base.h:1985
pcl::geometry::MeshBase::getOuterHalfEdgeIndex
HalfEdgeIndex getOuterHalfEdgeIndex(const FaceIndex &idx_face) const
Get the outer half-edge inex to a given face.
Definition: mesh_base.h:415
pcl::geometry::MeshBase::getEdgeIndex
EdgeIndex getEdgeIndex(const EdgeData &edge_data) const
Get the index associated to the given edge data.
Definition: mesh_base.h:1060
pcl::PointCloud< VertexData >
pcl::geometry::MeshBase::getEdgeDataCloud
EdgeDataCloud getEdgeDataCloud() const
Get the stored edge data.
Definition: mesh_base.h:973
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::HalfEdges
std::vector< HalfEdge > HalfEdges
Definition: mesh_base.h:1094
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::FaceData
typename MeshTraitsT::FaceData FaceData
Definition: mesh_base.h:112
pcl::geometry::MeshBase::isManifold
bool isManifold(std::true_type) const
Always manifold.
Definition: mesh_base.h:1912
pcl::geometry::MeshBase::isValid
bool isValid(const VertexIndex &idx_vertex) const
Check if the given vertex index is a valid index into the mesh.
Definition: mesh_base.h:601
pcl::geometry::MeshBase::getFaceAroundFaceCirculator
FaceAroundFaceCirculator getFaceAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
Definition: mesh_base.h:547
pcl::geometry::MeshBase::connectNewNew
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).
Definition: mesh_base.h:1384
pcl::geometry::MeshBase::getHalfEdgeDataCloud
HalfEdgeDataCloud getHalfEdgeDataCloud() const
Get the stored half-edge data.
Definition: mesh_base.h:938
pcl::geometry::MeshBase::isDeleted
bool isDeleted(const HalfEdgeIndex &idx_he) const
Check if the given half-edge is marked as deleted.
Definition: mesh_base.h:641
pcl::geometry::MeshBase::resizeEdges
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).
Definition: mesh_base.h:853
pcl::geometry::MeshBase::resizeFaces
void resizeFaces(const std::size_t n, const FaceData &data=FaceData())
Resize the faces to n elements.
Definition: mesh_base.h:864
pcl::geometry::VertexAroundFaceCirculator
Circulates clockwise around a face and returns an index to the terminating vertex of the inner half-e...
Definition: mesh_circulators.h:496
pcl::geometry::MeshBase::getHalfEdge
HalfEdge & getHalfEdge(const HalfEdgeIndex &idx_he)
Get the half-edge for the given index.
Definition: mesh_base.h:2005
pcl::geometry::MeshBase::isBoundary
bool isBoundary(const FaceIndex &idx_face) const
Check if the given face lies on the boundary.
Definition: mesh_base.h:710
pcl::geometry::MeshBase::reserveFaces
void reserveFaces(const std::size_t n)
Reserve storage space for n faces.
Definition: mesh_base.h:833
pcl::geometry::MeshBase::getHalfEdgeIndex
HalfEdgeIndex getHalfEdgeIndex(const HalfEdgeData &half_edge_data) const
Get the index associated to the given half-edge data.
Definition: mesh_base.h:1048
pcl::geometry::HalfEdgeIndex
Index used to access elements in the half-edge mesh.
Definition: mesh_indices.h:200
pcl::geometry::FaceAroundFaceCirculator
Circulates clockwise around a face and returns an index to the face of the outer half-edge (the targe...
Definition: mesh_circulators.h:821
pcl::geometry::MeshBase::deleteFace
void deleteFace(const FaceIndex &idx_face, std::false_type)
Non-manifold version of deleteFace.
Definition: mesh_base.h:1517
pcl::geometry::VertexIndex
Index used to access elements in the half-edge mesh.
Definition: mesh_indices.h:61
pcl::geometry::MeshBase::setOutgoingHalfEdgeIndex
void setOutgoingHalfEdgeIndex(const VertexIndex &idx_vertex, const HalfEdgeIndex &idx_outgoing_half_edge)
Set the outgoing half-edge index to a given vertex.
Definition: mesh_base.h:1800
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::HalfEdgeData
typename MeshTraitsT::HalfEdgeData HalfEdgeData
Definition: mesh_base.h:110
pcl::geometry::OutgoingHalfEdgeAroundVertexCirculator
Circulates counter-clockwise around a vertex and returns an index to the outgoing half-edge (the targ...
Definition: mesh_circulators.h:171
pcl::geometry::MeshBase::addVertex
VertexIndex addVertex(const VertexData &vertex_data=VertexData())
Add a vertex to the mesh.
Definition: mesh_base.h:170
pcl::geometry::MeshBase::incrementIf
void incrementIf(IteratorT &, std::false_type) const
Does nothing.
Definition: mesh_base.h:1777
pcl::geometry::MeshBase::markDeleted
void markDeleted(const EdgeIndex &idx_edge)
Mark the given edge (both half-edges) as deleted.
Definition: mesh_base.h:1686
pcl::geometry::MeshBase::getInnerHalfEdgeAroundFaceCirculator
InnerHalfEdgeAroundFaceCirculator getInnerHalfEdgeAroundFaceCirculator(const FaceIndex &idx_face) const
Definition: mesh_base.h:507
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::HalfEdgeIndices
std::vector< HalfEdgeIndex > HalfEdgeIndices
Definition: mesh_base.h:138
pcl::geometry::MeshBase::sizeEdges
std::size_t sizeEdges() const
Get the number of the edges.
Definition: mesh_base.h:765
pcl::geometry::MeshBase::setTerminatingVertexIndex
void setTerminatingVertexIndex(const HalfEdgeIndex &idx_half_edge, const VertexIndex &idx_terminating_vertex)
Set the terminating vertex index to a given half-edge.
Definition: mesh_base.h:1808
pcl::geometry::OuterHalfEdgeAroundFaceCirculator::getTargetIndex
HalfEdgeIndex getTargetIndex() const
Get the index to the outer half-edge.
Definition: mesh_circulators.h:785
pcl::geometry::MeshBase::makeAdjacent
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.
Definition: mesh_base.h:1317
pcl::geometry::MeshBase::addEdge
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.
Definition: mesh_base.h:1181
pcl::geometry::VertexAroundVertexCirculator::getTargetIndex
VertexIndex getTargetIndex() const
Get the index to the target vertex.
Definition: mesh_circulators.h:135
pcl::geometry::MeshBase::getFace
Face & getFace(const FaceIndex &idx_face)
Get the face for the given index.
Definition: mesh_base.h:2033
pcl::geometry::MeshBase::isBoundary
bool isBoundary(const VertexIndex &idx_vertex) const
Check if the given vertex lies on the boundary.
Definition: mesh_base.h:682
pcl::geometry::MeshBase::reconnect
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.
Definition: mesh_base.h:1569
pcl::geometry::MeshBase::addFaceImplBase
FaceIndex addFaceImplBase(const VertexIndices &vertices, const FaceData &face_data, const EdgeData &edge_data, const HalfEdgeData &half_edge_data)
General implementation of addFace.
Definition: mesh_base.h:1107
pcl::geometry::Face
A face is a closed loop of edges.
Definition: mesh_elements.h:164
pcl::geometry::MeshBase::connectFace
FaceIndex connectFace(const HalfEdgeIndices &inner_he, const FaceData &face_data)
Add a face to the mesh and connect it to the half-edges.
Definition: mesh_base.h:1341
pcl::geometry::MeshBase::reserveData
void reserveData(DataCloudT &cloud, const std::size_t n, std::true_type) const
Reserve storage space for the mesh data.
Definition: mesh_base.h:1934
pcl::geometry::MeshBase::setFace
void setFace(const FaceIndex &idx_face, const Face &face)
Set the face at the given index.
Definition: mesh_base.h:2049
pcl::geometry::MeshBase::clear
void clear()
Clear all mesh elements and data.
Definition: mesh_base.h:876
pcl::geometry::MeshBase::clearData
void clearData(DataCloudT &, std::false_type) const
Does nothing.
Definition: mesh_base.h:1967
pcl::geometry::MeshBase::getInnerHalfEdgeAroundFaceCirculator
InnerHalfEdgeAroundFaceCirculator getInnerHalfEdgeAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
Definition: mesh_base.h:515
pcl::geometry::MeshBase::isManifold
bool isManifold(const VertexIndex &, std::true_type) const
Always manifold.
Definition: mesh_base.h:1889
pcl::PointCloud::back
const PointT & back() const
Definition: point_cloud.h:493
pcl::geometry::MeshBase::getVertex
Vertex & getVertex(const VertexIndex &idx_vertex)
Get the vertex for the given index.
Definition: mesh_base.h:1977
pcl::geometry::MeshBase::getFace
Face getFace(const FaceIndex &idx_face) const
Get the face for the given index.
Definition: mesh_base.h:2041
pcl::geometry::MeshBase::FaceDataCloud
pcl::PointCloud< FaceData > FaceDataCloud
Definition: mesh_base.h:129
pcl::geometry::MeshBase::assignIf
void assignIf(const ConstIteratorT source, IteratorT target, std::true_type) const
Assign the source iterator to the target iterator.
Definition: mesh_base.h:1783
PCL_MAKE_ALIGNED_OPERATOR_NEW
#define PCL_MAKE_ALIGNED_OPERATOR_NEW
Macro to signal a class requires a custom allocator.
Definition: memory.h:63
pcl::geometry::MeshBase::getHalfEdge
HalfEdge getHalfEdge(const HalfEdgeIndex &idx_he) const
Get the half-edge for the given index.
Definition: mesh_base.h:2013
pcl::geometry::MeshBase::deleteFace
void deleteFace(const FaceIndex &idx_face, std::true_type)
Manifold version of deleteFace.
Definition: mesh_base.h:1498
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::HasFaceData
std::integral_constant< bool, !std::is_same< FaceData, pcl::geometry::NoData >::value > HasFaceData
Definition: mesh_base.h:124
pcl::geometry::MeshBase::getVertexAroundFaceCirculator
VertexAroundFaceCirculator getVertexAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
Definition: mesh_base.h:499
pcl::geometry::EdgeIndex
Index used to access elements in the half-edge mesh.
Definition: mesh_indices.h:339
pcl::geometry::MeshBase::reserveEdges
void reserveEdges(const std::size_t n)
Reserve storage space for n edges (2*n storage space is reserved for the half-edges).
Definition: mesh_base.h:824
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::VertexIterator
typename Vertices::iterator VertexIterator
Definition: mesh_base.h:1097
pcl::PointCloud::resize
void resize(std::size_t count)
Resizes the container to contain count elements.
Definition: point_cloud.h:455
pcl::geometry::QuadMeshTag
Tag describing the type of the mesh.
Definition: quad_mesh.h:52
pcl::geometry::MeshBase::isBoundary
bool isBoundary(const FaceIndex &idx_face, std::false_type) const
Check if any edge of the face lies on the boundary.
Definition: mesh_base.h:1871
pcl::geometry::MeshBase::getFaceIndex
FaceIndex getFaceIndex(const HalfEdgeIndex &idx_half_edge) const
Get the face index to a given half-edge.
Definition: mesh_base.h:387
pcl::geometry::MeshBase::reconnectNBNB
void reconnectNBNB(const HalfEdgeIndex &idx_he_bc, const HalfEdgeIndex &, const VertexIndex &idx_v_b, std::false_type)
Both edges are not on the boundary.
Definition: mesh_base.h:1653
pcl::geometry::VertexAroundFaceCirculator::getTargetIndex
VertexIndex getTargetIndex() const
Get the index to the target vertex.
Definition: mesh_circulators.h:569
pcl::geometry::MeshBase::getOutgoingHalfEdgeAroundVertexCirculator
OutgoingHalfEdgeAroundVertexCirculator getOutgoingHalfEdgeAroundVertexCirculator(const VertexIndex &idx_vertex) const
Definition: mesh_base.h:443
pcl::geometry::MeshBase::getEdgeDataCloud
EdgeDataCloud & getEdgeDataCloud()
Get access to the stored edge data.
Definition: mesh_base.h:966
pcl::geometry::MeshBase::getFaceAroundVertexCirculator
FaceAroundVertexCirculator getFaceAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
Definition: mesh_base.h:483
pcl::geometry::MeshBase::getOppositeFaceIndex
FaceIndex getOppositeFaceIndex(const HalfEdgeIndex &idx_half_edge) const
Get the face index to a given half-edge.
Definition: mesh_base.h:395
pcl::geometry::VertexIndex::invalidate
void invalidate()
Invalidate the index.
Definition: mesh_indices.h:97
pcl::geometry::IncomingHalfEdgeAroundVertexCirculator::getTargetIndex
HalfEdgeIndex getTargetIndex() const
Get the index to the incoming half-edge.
Definition: mesh_circulators.h:351
pcl::geometry::HalfEdgeIndex::get
int get() const
Get the index.
Definition: mesh_indices.h:243
pcl::geometry::MeshBase::HalfEdgeDataCloud
pcl::PointCloud< HalfEdgeData > HalfEdgeDataCloud
Definition: mesh_base.h:127
pcl::geometry::FaceAroundVertexCirculator
Circulates counter-clockwise around a vertex and returns an index to the face of the outgoing half-ed...
Definition: mesh_circulators.h:387
pcl::geometry::MeshBase::getFaceIndex
FaceIndex getFaceIndex(const FaceData &face_data) const
Get the index associated to the given face data.
Definition: mesh_base.h:1072
pcl::PointCloud::size
std::size_t size() const
Definition: point_cloud.h:436
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::EdgeData
typename MeshTraitsT::EdgeData EdgeData
Definition: mesh_base.h:111
pcl::geometry::HalfEdgeIndex::invalidate
void invalidate()
Invalidate the index.
Definition: mesh_indices.h:236
pcl::geometry::InnerHalfEdgeAroundFaceCirculator::getTargetIndex
HalfEdgeIndex getTargetIndex() const
Get the index to the inner half-edge.
Definition: mesh_circulators.h:677
pcl::geometry::MeshBase::isValid
bool isValid(const FaceIndex &idx_face) const
Check if the given face index is a valid index into the mesh.
Definition: mesh_base.h:622
pcl::geometry::MeshBase::getInnerHalfEdgeIndex
HalfEdgeIndex getInnerHalfEdgeIndex(const FaceIndex &idx_face) const
Get the inner half-edge index to a given face.
Definition: mesh_base.h:407
pcl::geometry::MeshBase::setEdgeDataCloud
bool setEdgeDataCloud(const EdgeDataCloud &edge_data_cloud)
Change the stored edge data.
Definition: mesh_base.h:983
pcl::geometry::MeshBase::getOuterHalfEdgeAroundFaceCirculator
OuterHalfEdgeAroundFaceCirculator getOuterHalfEdgeAroundFaceCirculator(const FaceIndex &idx_face) const
Definition: mesh_base.h:523
pcl::geometry::MeshBase::isManifold
bool isManifold() const
Check if the mesh is manifold.
Definition: mesh_base.h:739
pcl::geometry::MeshBase::addData
void addData(pcl::PointCloud< DataT > &, const DataT &, std::false_type)
Does nothing.
Definition: mesh_base.h:1488
pcl::geometry::MeshBase::getHalfEdgeDataCloud
HalfEdgeDataCloud & getHalfEdgeDataCloud()
Get access to the stored half-edge data.
Definition: mesh_base.h:931
pcl::geometry::MeshBase::isManifold
bool isManifold(const VertexIndex &idx_vertex, std::false_type) const
Check if the given vertex is manifold.
Definition: mesh_base.h:1896
pcl::geometry::QuadMesh
Half-edge mesh that can only store quads.
Definition: quad_mesh.h:60
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::HasVertexData
std::integral_constant< bool, !std::is_same< VertexData, pcl::geometry::NoData >::value > HasVertexData
Definition: mesh_base.h:121
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::HalfEdgeConstIterator
typename HalfEdges::const_iterator HalfEdgeConstIterator
Definition: mesh_base.h:1102
pcl::geometry::MeshBase::getVertexDataCloud
VertexDataCloud & getVertexDataCloud()
Get access to the stored vertex data.
Definition: mesh_base.h:896
pcl::geometry::MeshIO
Read / write the half-edge mesh from / to a file.
Definition: mesh_base.h:77
pcl::geometry::MeshBase::setFaceIndex
void setFaceIndex(const HalfEdgeIndex &idx_half_edge, const FaceIndex &idx_face)
Set the face index to a given half-edge.
Definition: mesh_base.h:1833
pcl::geometry::MeshBase::getTerminatingVertexIndex
VertexIndex getTerminatingVertexIndex(const HalfEdgeIndex &idx_half_edge) const
Get the terminating vertex index to a given half-edge.
Definition: mesh_base.h:346
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::Vertices
std::vector< Vertex > Vertices
Definition: mesh_base.h:1093
pcl::geometry::FaceIndex
Index used to access elements in the half-edge mesh.
Definition: mesh_indices.h:478
pcl::geometry::MeshBase::isEqualTopology
bool isEqualTopology(const Self &other) const
Check if the other mesh has the same topology as this mesh.
Definition: mesh_base.h:559
pcl::geometry::MeshBase::EdgeDataCloud
pcl::PointCloud< EdgeData > EdgeDataCloud
Definition: mesh_base.h:128
pcl::PointCloud::front
const PointT & front() const
Definition: point_cloud.h:491
pcl::geometry::MeshBase::resizeData
void resizeData(DataCloudT &, const std::size_t n, const typename DataCloudT::value_type &data, std::true_type) const
Resize the mesh data.
Definition: mesh_base.h:1947
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::Ptr
shared_ptr< Self > Ptr
Definition: mesh_base.h:103
pcl::geometry::toHalfEdgeIndex
pcl::geometry::HalfEdgeIndex toHalfEdgeIndex(const EdgeIndex &index, const bool get_first=true)
Convert the given edge index to a half-edge index.
Definition: mesh_indices.h:625
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::VertexConstIterator
typename Vertices::const_iterator VertexConstIterator
Definition: mesh_base.h:1101
pcl::Vertices
Describes a set of vertices in a polygon mesh, by basically storing an array of indices.
Definition: Vertices.h:14
pcl::geometry::MeshBase::getVertexAroundVertexCirculator
VertexAroundVertexCirculator getVertexAroundVertexCirculator(const HalfEdgeIndex &idx_outgoing_half_edge) const
Definition: mesh_base.h:435
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::HasHalfEdgeData
std::integral_constant< bool, !std::is_same< HalfEdgeData, pcl::geometry::NoData >::value > HasHalfEdgeData
Definition: mesh_base.h:122
pcl::geometry::FaceIndex::isValid
bool isValid() const
Returns true if the index is valid.
Definition: mesh_indices.h:507
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::FaceIndices
std::vector< FaceIndex > FaceIndices
Definition: mesh_base.h:140
pcl::geometry::MeshBase::reserveVertices
void reserveVertices(const std::size_t n)
Reserve storage space n vertices.
Definition: mesh_base.h:816
pcl::geometry::FaceIndex::invalidate
void invalidate()
Invalidate the index.
Definition: mesh_indices.h:514
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::HasEdgeData
std::integral_constant< bool, !std::is_same< EdgeData, pcl::geometry::NoData >::value > HasEdgeData
Definition: mesh_base.h:123
pcl::geometry::MeshBase::cleanUp
void cleanUp()
Removes all mesh elements and data that are marked as deleted.
Definition: mesh_base.h:265
pcl::geometry::MeshBase::addFace
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.
Definition: mesh_base.h:186
pcl::geometry::MeshBase::isManifold
bool isManifold(const VertexIndex &idx_vertex) const
Check if the given vertex is manifold.
Definition: mesh_base.h:730
pcl::geometry::MeshBase::sizeHalfEdges
std::size_t sizeHalfEdges() const
Get the number of the half-edges.
Definition: mesh_base.h:757
pcl::geometry::MeshBase::checkTopology1
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.
Definition: mesh_base.h:1208
pcl::geometry::MeshBase::isDeleted
bool isDeleted(const FaceIndex &idx_face) const
Check if the given face is marked as deleted.
Definition: mesh_base.h:658
pcl::geometry::VertexAroundVertexCirculator::getCurrentHalfEdgeIndex
HalfEdgeIndex getCurrentHalfEdgeIndex() const
Get the half-edge that is currently stored in the circulator.
Definition: mesh_circulators.h:142
pcl::geometry::MeshBase::getOuterHalfEdgeAroundFaceCirculator
OuterHalfEdgeAroundFaceCirculator getOuterHalfEdgeAroundFaceCirculator(const HalfEdgeIndex &idx_inner_half_edge) const
Definition: mesh_base.h:531
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::ConstPtr
shared_ptr< const Self > ConstPtr
Definition: mesh_base.h:104
pcl::geometry::MeshBase::deleteVertex
void deleteVertex(const VertexIndex &idx_vertex)
Mark the given vertex and all connected half-edges and faces as deleted.
Definition: mesh_base.h:199
pcl::geometry::MeshBase::isValid
bool isValid(const HalfEdgeIndex &idx_he) const
Check if the given half-edge index is a valid index into the mesh.
Definition: mesh_base.h:608
pcl::geometry::MeshBase::connectOldOld
void connectOldOld(const HalfEdgeIndex &, const HalfEdgeIndex &, const VertexIndex &, std::true_type)
Both half-edges are old (manifold version).
Definition: mesh_base.h:1440
pcl::geometry::MeshBase::getFaceAroundVertexCirculator
FaceAroundVertexCirculator getFaceAroundVertexCirculator(const VertexIndex &idx_vertex) const
Definition: mesh_base.h:475
pcl::geometry::MeshBase::deleteFace
void deleteFace(const FaceIndex &idx_face)
Mark the given face as deleted.
Definition: mesh_base.h:253
pcl::geometry::MeshBase::isBoundary
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.
Definition: mesh_base.h:699
pcl::geometry::MeshBase::markDeleted
void markDeleted(const FaceIndex &idx_face)
Mark the given face as deleted.
Definition: mesh_base.h:1695
pcl::geometry::MeshBase::connectNewOld
void connectNewOld(const HalfEdgeIndex &idx_he_ab, const HalfEdgeIndex &idx_he_bc, const VertexIndex &idx_v_b)
The first half-edge is new.
Definition: mesh_base.h:1410
pcl::geometry::MeshBase::reserveData
void reserveData(DataCloudT &, const std::size_t, std::false_type) const
Does nothing.
Definition: mesh_base.h:1941
pcl::geometry::MeshBase::remove
IndexContainerT remove(ElementContainerT &elements, DataContainerT &data_cloud)
Removes mesh elements and data that are marked as deleted from the container.
Definition: mesh_base.h:1716
pcl::geometry::MeshBase::isBoundary
bool isBoundary(const FaceIndex &idx_face, std::true_type) const
Check if any vertex of the face lies on the boundary.
Definition: mesh_base.h:1853
pcl::geometry::MeshBase::sizeFaces
std::size_t sizeFaces() const
Get the number of the faces.
Definition: mesh_base.h:773
pcl::geometry::MeshBase::setFaceDataCloud
bool setFaceDataCloud(const FaceDataCloud &face_data_cloud)
Change the stored face data.
Definition: mesh_base.h:1018
pcl::geometry::MeshBase::getIncomingHalfEdgeAroundVertexCirculator
IncomingHalfEdgeAroundVertexCirculator getIncomingHalfEdgeAroundVertexCirculator(const HalfEdgeIndex &idx_incoming_half_edge) const
Definition: mesh_base.h:467
pcl::geometry::VertexIndex::get
int get() const
Get the index.
Definition: mesh_indices.h:104
pcl::PointCloud::push_back
void push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
Definition: point_cloud.h:543
pcl::geometry::MeshBase::getVertexAroundFaceCirculator
VertexAroundFaceCirculator getVertexAroundFaceCirculator(const FaceIndex &idx_face) const
Definition: mesh_base.h:491
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::FaceConstIterator
typename Faces::const_iterator FaceConstIterator
Definition: mesh_base.h:1103
pcl::geometry::MeshBase::checkTopology2
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.
Definition: mesh_base.h:1278
pcl::geometry::MeshBase::assignIf
void assignIf(const ConstIteratorT, IteratorT, std::false_type) const
Does nothing.
Definition: mesh_base.h:1790
pcl::geometry::FaceAroundVertexCirculator::getTargetIndex
FaceIndex getTargetIndex() const
Get the index to the target face.
Definition: mesh_circulators.h:460
pcl::geometry::MeshBase::markDeleted
void markDeleted(const VertexIndex &idx_vertex)
Mark the given vertex as deleted.
Definition: mesh_base.h:1670
memory.h
Defines functions, macros and traits for allocating and using memory.
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::Faces
std::vector< Face > Faces
Definition: mesh_base.h:1095
pcl::geometry::FaceIndex::get
int get() const
Get the index.
Definition: mesh_indices.h:521
pcl::geometry::MeshBase::connectNewNew
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).
Definition: mesh_base.h:1368
pcl::geometry::MeshBase::markDeleted
void markDeleted(const HalfEdgeIndex &idx_he)
Mark the given half-edge as deleted.
Definition: mesh_base.h:1678
pcl::geometry::MeshBase::isBoundary
bool isBoundary(const FaceIndex &idx_face) const
Check if the given face lies on the boundary.
Definition: mesh_base.h:718
pcl::geometry::MeshBase::incrementIf
void incrementIf(IteratorT &it, std::true_type) const
Increment the iterator.
Definition: mesh_base.h:1770
pcl::geometry::MeshBase< QuadMesh< MeshTraitsT >, MeshTraitsT, QuadMeshTag >::VertexIndices
std::vector< VertexIndex > VertexIndices
Definition: mesh_base.h:137
pcl::geometry::MeshBase
Base class for the half-edge mesh.
Definition: mesh_base.h:98
pcl::geometry::VertexAroundVertexCirculator
Circulates counter-clockwise around a vertex and returns an index to the terminating vertex of the ou...
Definition: mesh_circulators.h:63