873 lines
31 KiB
C
873 lines
31 KiB
C
|
|
/*
|
||
|
|
* Software License Agreement (BSD License)
|
||
|
|
*
|
||
|
|
* Point Cloud Library (PCL) - www.pointclouds.org
|
||
|
|
* Copyright (c) 2009-2012, Willow Garage, Inc.
|
||
|
|
* Copyright (c) 2012-, Open Perception, Inc.
|
||
|
|
*
|
||
|
|
* All rights reserved.
|
||
|
|
*
|
||
|
|
* Redistribution and use in source and binary forms, with or without
|
||
|
|
* modification, are permitted provided that the following conditions
|
||
|
|
* are met:
|
||
|
|
*
|
||
|
|
* * Redistributions of source code must retain the above copyright
|
||
|
|
* notice, this list of conditions and the following disclaimer.
|
||
|
|
* * Redistributions in binary form must reproduce the above
|
||
|
|
* copyright notice, this list of conditions and the following
|
||
|
|
* disclaimer in the documentation and/or other materials provided
|
||
|
|
* with the distribution.
|
||
|
|
* * Neither the name of the copyright holder(s) nor the names of its
|
||
|
|
* contributors may be used to endorse or promote products derived
|
||
|
|
* from this software without specific prior written permission.
|
||
|
|
*
|
||
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
*
|
||
|
|
* $Id$
|
||
|
|
*
|
||
|
|
*/
|
||
|
|
|
||
|
|
// NOTE: This file has been created with
|
||
|
|
// 'pcl_src/geometry/include/pcl/geometry/mesh_circulators.py'
|
||
|
|
|
||
|
|
#pragma once
|
||
|
|
|
||
|
|
#include <pcl/geometry/boost.h>
|
||
|
|
#include <pcl/geometry/mesh_indices.h>
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
// VertexAroundVertexCirculator
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
|
||
|
|
namespace pcl {
|
||
|
|
namespace geometry {
|
||
|
|
/** \brief Circulates counter-clockwise around a vertex and returns an index to the
|
||
|
|
* terminating vertex of the outgoing half-edge (the target). The best way to declare
|
||
|
|
* the circulator is to use the method
|
||
|
|
* pcl::geometry::MeshBase::getVertexAroundVertexCirculator ().
|
||
|
|
* \tparam MeshT Mesh to which this circulator belongs to.
|
||
|
|
* \note The circulator can't be used to change the connectivity in the mesh (only
|
||
|
|
* const circulators are valid).
|
||
|
|
* \author Martin Saelzle
|
||
|
|
* \ingroup geometry
|
||
|
|
*/
|
||
|
|
template <class MeshT>
|
||
|
|
class VertexAroundVertexCirculator
|
||
|
|
: boost::equality_comparable<
|
||
|
|
pcl::geometry::VertexAroundVertexCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<pcl::geometry::VertexAroundVertexCirculator<MeshT>>> {
|
||
|
|
public:
|
||
|
|
using Base = boost::equality_comparable<
|
||
|
|
pcl::geometry::VertexAroundVertexCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<pcl::geometry::VertexAroundVertexCirculator<MeshT>>>;
|
||
|
|
using Self = pcl::geometry::VertexAroundVertexCirculator<MeshT>;
|
||
|
|
|
||
|
|
using Mesh = MeshT;
|
||
|
|
using VertexIndex = typename Mesh::VertexIndex;
|
||
|
|
using HalfEdgeIndex = typename Mesh::HalfEdgeIndex;
|
||
|
|
|
||
|
|
/** \brief Constructor resulting in an invalid circulator. */
|
||
|
|
VertexAroundVertexCirculator() : mesh_(nullptr), idx_outgoing_half_edge_() {}
|
||
|
|
|
||
|
|
/** \brief Construct from the vertex around which we want to circulate. */
|
||
|
|
VertexAroundVertexCirculator(const VertexIndex& idx_vertex, Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_outgoing_half_edge_(mesh->getOutgoingHalfEdgeIndex(idx_vertex))
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Construct directly from the outgoing half-edge. */
|
||
|
|
VertexAroundVertexCirculator(const HalfEdgeIndex& idx_outgoing_half_edge,
|
||
|
|
Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_outgoing_half_edge_(idx_outgoing_half_edge)
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Check if the circulator is valid.
|
||
|
|
* \warning Does NOT check if the stored mesh pointer is valid. You have to ensure
|
||
|
|
* this yourself when constructing the circulator. */
|
||
|
|
inline bool
|
||
|
|
isValid() const
|
||
|
|
{
|
||
|
|
return (idx_outgoing_half_edge_.isValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Comparison operators (with boost::operators): == !=
|
||
|
|
* \warning Does NOT check if the circulators belong to the same mesh. Please check
|
||
|
|
* this yourself. */
|
||
|
|
inline bool
|
||
|
|
operator==(const Self& other) const
|
||
|
|
{
|
||
|
|
return (idx_outgoing_half_edge_ == other.idx_outgoing_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Increment operators (with boost::operators): ++ (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator++()
|
||
|
|
{
|
||
|
|
idx_outgoing_half_edge_ = mesh_->getNextHalfEdgeIndex(
|
||
|
|
mesh_->getOppositeHalfEdgeIndex(idx_outgoing_half_edge_));
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Decrement operators (with boost::operators): -- (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator--()
|
||
|
|
{
|
||
|
|
idx_outgoing_half_edge_ = mesh_->getOppositeHalfEdgeIndex(
|
||
|
|
mesh_->getPrevHalfEdgeIndex(idx_outgoing_half_edge_));
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the index to the target vertex. */
|
||
|
|
inline VertexIndex
|
||
|
|
getTargetIndex() const
|
||
|
|
{
|
||
|
|
return (mesh_->getTerminatingVertexIndex(idx_outgoing_half_edge_));
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the half-edge that is currently stored in the circulator. */
|
||
|
|
inline HalfEdgeIndex
|
||
|
|
getCurrentHalfEdgeIndex() const
|
||
|
|
{
|
||
|
|
return (idx_outgoing_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief The mesh to which this circulator belongs to. */
|
||
|
|
Mesh* mesh_;
|
||
|
|
|
||
|
|
/** \brief The outgoing half-edge of the vertex around which we want to circulate. */
|
||
|
|
HalfEdgeIndex idx_outgoing_half_edge_;
|
||
|
|
};
|
||
|
|
} // End namespace geometry
|
||
|
|
} // End namespace pcl
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
// OutgoingHalfEdgeAroundVertexCirculator
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
|
||
|
|
namespace pcl {
|
||
|
|
namespace geometry {
|
||
|
|
/** \brief Circulates counter-clockwise around a vertex and returns an index to the
|
||
|
|
* outgoing half-edge (the target). The best way to declare the circulator is to use the
|
||
|
|
* method pcl::geometry::MeshBase::getOutgoingHalfEdgeAroundVertexCirculator ().
|
||
|
|
* \tparam MeshT Mesh to which this circulator belongs to.
|
||
|
|
* \note The circulator can't be used to
|
||
|
|
* change the connectivity in the mesh (only const circulators are valid).
|
||
|
|
* \author Martin Saelzle
|
||
|
|
* \ingroup geometry
|
||
|
|
*/
|
||
|
|
template <class MeshT>
|
||
|
|
class OutgoingHalfEdgeAroundVertexCirculator
|
||
|
|
: boost::equality_comparable<
|
||
|
|
pcl::geometry::OutgoingHalfEdgeAroundVertexCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<
|
||
|
|
pcl::geometry::OutgoingHalfEdgeAroundVertexCirculator<MeshT>>> {
|
||
|
|
public:
|
||
|
|
using Base = boost::equality_comparable<
|
||
|
|
pcl::geometry::OutgoingHalfEdgeAroundVertexCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<
|
||
|
|
pcl::geometry::OutgoingHalfEdgeAroundVertexCirculator<MeshT>>>;
|
||
|
|
using Self = pcl::geometry::OutgoingHalfEdgeAroundVertexCirculator<MeshT>;
|
||
|
|
|
||
|
|
using Mesh = MeshT;
|
||
|
|
using VertexIndex = typename Mesh::VertexIndex;
|
||
|
|
using HalfEdgeIndex = typename Mesh::HalfEdgeIndex;
|
||
|
|
|
||
|
|
/** \brief Constructor resulting in an invalid circulator. */
|
||
|
|
OutgoingHalfEdgeAroundVertexCirculator() : mesh_(nullptr), idx_outgoing_half_edge_()
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Construct from the vertex around which we want to circulate. */
|
||
|
|
OutgoingHalfEdgeAroundVertexCirculator(const VertexIndex& idx_vertex,
|
||
|
|
Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_outgoing_half_edge_(mesh->getOutgoingHalfEdgeIndex(idx_vertex))
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Construct directly from the outgoing half-edge. */
|
||
|
|
OutgoingHalfEdgeAroundVertexCirculator(const HalfEdgeIndex& idx_outgoing_half_edge,
|
||
|
|
Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_outgoing_half_edge_(idx_outgoing_half_edge)
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Check if the circulator is valid.
|
||
|
|
* \warning Does NOT check if the stored mesh pointer is valid. You have to ensure
|
||
|
|
* this yourself when constructing the circulator. */
|
||
|
|
inline bool
|
||
|
|
isValid() const
|
||
|
|
{
|
||
|
|
return (idx_outgoing_half_edge_.isValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Comparison operators (with boost::operators): == !=
|
||
|
|
* \warning Does NOT check if the circulators belong to the same mesh. Please check
|
||
|
|
* this yourself. */
|
||
|
|
inline bool
|
||
|
|
operator==(const Self& other) const
|
||
|
|
{
|
||
|
|
return (idx_outgoing_half_edge_ == other.idx_outgoing_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Increment operators (with boost::operators): ++ (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator++()
|
||
|
|
{
|
||
|
|
idx_outgoing_half_edge_ = mesh_->getNextHalfEdgeIndex(
|
||
|
|
mesh_->getOppositeHalfEdgeIndex(idx_outgoing_half_edge_));
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Decrement operators (with boost::operators): -- (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator--()
|
||
|
|
{
|
||
|
|
idx_outgoing_half_edge_ = mesh_->getOppositeHalfEdgeIndex(
|
||
|
|
mesh_->getPrevHalfEdgeIndex(idx_outgoing_half_edge_));
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the index to the outgoing half-edge. */
|
||
|
|
inline HalfEdgeIndex
|
||
|
|
getTargetIndex() const
|
||
|
|
{
|
||
|
|
return (idx_outgoing_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the half-edge that is currently stored in the circulator. */
|
||
|
|
inline HalfEdgeIndex
|
||
|
|
getCurrentHalfEdgeIndex() const
|
||
|
|
{
|
||
|
|
return (idx_outgoing_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief The mesh to which this circulator belongs to. */
|
||
|
|
Mesh* mesh_;
|
||
|
|
|
||
|
|
/** \brief The outgoing half-edge of the vertex around which we want to circulate. */
|
||
|
|
HalfEdgeIndex idx_outgoing_half_edge_;
|
||
|
|
};
|
||
|
|
} // End namespace geometry
|
||
|
|
} // End namespace pcl
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
// IncomingHalfEdgeAroundVertexCirculator
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
|
||
|
|
namespace pcl {
|
||
|
|
namespace geometry {
|
||
|
|
/** \brief Circulates counter-clockwise around a vertex and returns an index to the
|
||
|
|
* incoming half-edge (the target). The best way to declare the circulator is to use the
|
||
|
|
* method pcl::geometry::MeshBase::getIncomingHalfEdgeAroundVertexCirculator ().
|
||
|
|
* \tparam MeshT Mesh to which this circulator belongs to.
|
||
|
|
* \note The circulator can't be used to change the connectivity in the mesh (only
|
||
|
|
* const circulators are valid).
|
||
|
|
* \author Martin Saelzle
|
||
|
|
* \ingroup geometry
|
||
|
|
*/
|
||
|
|
template <class MeshT>
|
||
|
|
class IncomingHalfEdgeAroundVertexCirculator
|
||
|
|
: boost::equality_comparable<
|
||
|
|
pcl::geometry::IncomingHalfEdgeAroundVertexCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<
|
||
|
|
pcl::geometry::IncomingHalfEdgeAroundVertexCirculator<MeshT>>> {
|
||
|
|
public:
|
||
|
|
using Base = boost::equality_comparable<
|
||
|
|
pcl::geometry::IncomingHalfEdgeAroundVertexCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<
|
||
|
|
pcl::geometry::IncomingHalfEdgeAroundVertexCirculator<MeshT>>>;
|
||
|
|
using Self = pcl::geometry::IncomingHalfEdgeAroundVertexCirculator<MeshT>;
|
||
|
|
|
||
|
|
using Mesh = MeshT;
|
||
|
|
using VertexIndex = typename Mesh::VertexIndex;
|
||
|
|
using HalfEdgeIndex = typename Mesh::HalfEdgeIndex;
|
||
|
|
|
||
|
|
/** \brief Constructor resulting in an invalid circulator. */
|
||
|
|
IncomingHalfEdgeAroundVertexCirculator() : mesh_(nullptr), idx_incoming_half_edge_()
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Construct from the vertex around which we want to circulate. */
|
||
|
|
IncomingHalfEdgeAroundVertexCirculator(const VertexIndex& idx_vertex,
|
||
|
|
Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_incoming_half_edge_(mesh->getIncomingHalfEdgeIndex(idx_vertex))
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Construct directly from the incoming half-edge. */
|
||
|
|
IncomingHalfEdgeAroundVertexCirculator(const HalfEdgeIndex& idx_incoming_half_edge,
|
||
|
|
Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_incoming_half_edge_(idx_incoming_half_edge)
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Check if the circulator is valid.
|
||
|
|
* \warning Does NOT check if the stored mesh pointer is valid. You have to ensure
|
||
|
|
* this yourself when constructing the circulator. */
|
||
|
|
inline bool
|
||
|
|
isValid() const
|
||
|
|
{
|
||
|
|
return (idx_incoming_half_edge_.isValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Comparison operators (with boost::operators): == !=
|
||
|
|
* \warning Does NOT check if the circulators belong to the same mesh. Please check
|
||
|
|
* this yourself. */
|
||
|
|
inline bool
|
||
|
|
operator==(const Self& other) const
|
||
|
|
{
|
||
|
|
return (idx_incoming_half_edge_ == other.idx_incoming_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Increment operators (with boost::operators): ++ (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator++()
|
||
|
|
{
|
||
|
|
idx_incoming_half_edge_ = mesh_->getOppositeHalfEdgeIndex(
|
||
|
|
mesh_->getNextHalfEdgeIndex(idx_incoming_half_edge_));
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Decrement operators (with boost::operators): -- (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator--()
|
||
|
|
{
|
||
|
|
idx_incoming_half_edge_ = mesh_->getPrevHalfEdgeIndex(
|
||
|
|
mesh_->getOppositeHalfEdgeIndex(idx_incoming_half_edge_));
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the index to the incoming half-edge. */
|
||
|
|
inline HalfEdgeIndex
|
||
|
|
getTargetIndex() const
|
||
|
|
{
|
||
|
|
return (idx_incoming_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the half-edge that is currently stored in the circulator. */
|
||
|
|
inline HalfEdgeIndex
|
||
|
|
getCurrentHalfEdgeIndex() const
|
||
|
|
{
|
||
|
|
return (idx_incoming_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief The mesh to which this circulator belongs to. */
|
||
|
|
Mesh* mesh_;
|
||
|
|
|
||
|
|
/** \brief The incoming half-edge of the vertex around which we want to circulate. */
|
||
|
|
HalfEdgeIndex idx_incoming_half_edge_;
|
||
|
|
};
|
||
|
|
} // End namespace geometry
|
||
|
|
} // End namespace pcl
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
// FaceAroundVertexCirculator
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
|
||
|
|
namespace pcl {
|
||
|
|
namespace geometry {
|
||
|
|
/** \brief Circulates counter-clockwise around a vertex and returns an index to the face
|
||
|
|
* of the outgoing half-edge (the target). The best way to declare the circulator is to
|
||
|
|
* use the method pcl::geometry::MeshBase::getFaceAroundVertexCirculator ().
|
||
|
|
* \tparam MeshT Mesh to which this circulator belongs to.
|
||
|
|
* \note The circulator can't be used to change the connectivity in the mesh (only
|
||
|
|
* const circulators are valid).
|
||
|
|
* \author Martin Saelzle
|
||
|
|
* \ingroup geometry
|
||
|
|
*/
|
||
|
|
template <class MeshT>
|
||
|
|
class FaceAroundVertexCirculator
|
||
|
|
: boost::equality_comparable<
|
||
|
|
pcl::geometry::FaceAroundVertexCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<pcl::geometry::FaceAroundVertexCirculator<MeshT>>> {
|
||
|
|
public:
|
||
|
|
using Base = boost::equality_comparable<
|
||
|
|
pcl::geometry::FaceAroundVertexCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<pcl::geometry::FaceAroundVertexCirculator<MeshT>>>;
|
||
|
|
using Self = pcl::geometry::FaceAroundVertexCirculator<MeshT>;
|
||
|
|
|
||
|
|
using Mesh = MeshT;
|
||
|
|
using FaceIndex = typename Mesh::FaceIndex;
|
||
|
|
using VertexIndex = typename Mesh::VertexIndex;
|
||
|
|
using HalfEdgeIndex = typename Mesh::HalfEdgeIndex;
|
||
|
|
|
||
|
|
/** \brief Constructor resulting in an invalid circulator. */
|
||
|
|
FaceAroundVertexCirculator() : mesh_(nullptr), idx_outgoing_half_edge_() {}
|
||
|
|
|
||
|
|
/** \brief Construct from the vertex around which we want to circulate. */
|
||
|
|
FaceAroundVertexCirculator(const VertexIndex& idx_vertex, Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_outgoing_half_edge_(mesh->getOutgoingHalfEdgeIndex(idx_vertex))
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Construct directly from the outgoing half-edge. */
|
||
|
|
FaceAroundVertexCirculator(const HalfEdgeIndex& idx_outgoing_half_edge,
|
||
|
|
Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_outgoing_half_edge_(idx_outgoing_half_edge)
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Check if the circulator is valid.
|
||
|
|
* \warning Does NOT check if the stored mesh pointer is valid. You have to ensure
|
||
|
|
* this yourself when constructing the circulator. */
|
||
|
|
inline bool
|
||
|
|
isValid() const
|
||
|
|
{
|
||
|
|
return (idx_outgoing_half_edge_.isValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Comparison operators (with boost::operators): == !=
|
||
|
|
* \warning Does NOT check if the circulators belong to the same mesh. Please check
|
||
|
|
* this yourself. */
|
||
|
|
inline bool
|
||
|
|
operator==(const Self& other) const
|
||
|
|
{
|
||
|
|
return (idx_outgoing_half_edge_ == other.idx_outgoing_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Increment operators (with boost::operators): ++ (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator++()
|
||
|
|
{
|
||
|
|
idx_outgoing_half_edge_ = mesh_->getNextHalfEdgeIndex(
|
||
|
|
mesh_->getOppositeHalfEdgeIndex(idx_outgoing_half_edge_));
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Decrement operators (with boost::operators): -- (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator--()
|
||
|
|
{
|
||
|
|
idx_outgoing_half_edge_ = mesh_->getOppositeHalfEdgeIndex(
|
||
|
|
mesh_->getPrevHalfEdgeIndex(idx_outgoing_half_edge_));
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the index to the target face. */
|
||
|
|
inline FaceIndex
|
||
|
|
getTargetIndex() const
|
||
|
|
{
|
||
|
|
return (mesh_->getFaceIndex(idx_outgoing_half_edge_));
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the half-edge that is currently stored in the circulator. */
|
||
|
|
inline HalfEdgeIndex
|
||
|
|
getCurrentHalfEdgeIndex() const
|
||
|
|
{
|
||
|
|
return (idx_outgoing_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief The mesh to which this circulator belongs to. */
|
||
|
|
Mesh* mesh_;
|
||
|
|
|
||
|
|
/** \brief The outgoing half-edge of the vertex around which we want to circulate. */
|
||
|
|
HalfEdgeIndex idx_outgoing_half_edge_;
|
||
|
|
};
|
||
|
|
} // End namespace geometry
|
||
|
|
} // End namespace pcl
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
// VertexAroundFaceCirculator
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
|
||
|
|
namespace pcl {
|
||
|
|
namespace geometry {
|
||
|
|
/** \brief Circulates clockwise around a face and returns an index to the terminating
|
||
|
|
* vertex of the inner half-edge (the target). The best way to declare the circulator is
|
||
|
|
* to use the method pcl::geometry::MeshBase::getVertexAroundFaceCirculator ().
|
||
|
|
* \tparam MeshT Mesh to which this circulator belongs to.
|
||
|
|
* \note The circulator can't be used to change the connectivity in the mesh (only
|
||
|
|
* const circulators are valid).
|
||
|
|
* \author Martin Saelzle
|
||
|
|
* \ingroup geometry
|
||
|
|
*/
|
||
|
|
template <class MeshT>
|
||
|
|
class VertexAroundFaceCirculator
|
||
|
|
: boost::equality_comparable<
|
||
|
|
pcl::geometry::VertexAroundFaceCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<pcl::geometry::VertexAroundFaceCirculator<MeshT>>> {
|
||
|
|
public:
|
||
|
|
using Base = boost::equality_comparable<
|
||
|
|
pcl::geometry::VertexAroundFaceCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<pcl::geometry::VertexAroundFaceCirculator<MeshT>>>;
|
||
|
|
using Self = pcl::geometry::VertexAroundFaceCirculator<MeshT>;
|
||
|
|
|
||
|
|
using Mesh = MeshT;
|
||
|
|
using VertexIndex = typename Mesh::VertexIndex;
|
||
|
|
using FaceIndex = typename Mesh::FaceIndex;
|
||
|
|
using HalfEdgeIndex = typename Mesh::HalfEdgeIndex;
|
||
|
|
|
||
|
|
/** \brief Constructor resulting in an invalid circulator. */
|
||
|
|
VertexAroundFaceCirculator() : mesh_(nullptr), idx_inner_half_edge_() {}
|
||
|
|
|
||
|
|
/** \brief Construct from the face around which we want to circulate. */
|
||
|
|
VertexAroundFaceCirculator(const FaceIndex& idx_face, Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_inner_half_edge_(mesh->getInnerHalfEdgeIndex(idx_face))
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Construct directly from the inner half-edge. */
|
||
|
|
VertexAroundFaceCirculator(const HalfEdgeIndex& idx_inner_half_edge, Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_inner_half_edge_(idx_inner_half_edge)
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Check if the circulator is valid.
|
||
|
|
* \warning Does NOT check if the stored mesh pointer is valid. You have to ensure
|
||
|
|
* this yourself when constructing the circulator. */
|
||
|
|
inline bool
|
||
|
|
isValid() const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_.isValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Comparison operators (with boost::operators): == !=
|
||
|
|
* \warning Does NOT check if the circulators belong to the same mesh. Please check
|
||
|
|
* this yourself. */
|
||
|
|
inline bool
|
||
|
|
operator==(const Self& other) const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_ == other.idx_inner_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Increment operators (with boost::operators): ++ (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator++()
|
||
|
|
{
|
||
|
|
idx_inner_half_edge_ = mesh_->getNextHalfEdgeIndex(idx_inner_half_edge_);
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Decrement operators (with boost::operators): -- (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator--()
|
||
|
|
{
|
||
|
|
idx_inner_half_edge_ = mesh_->getPrevHalfEdgeIndex(idx_inner_half_edge_);
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the index to the target vertex. */
|
||
|
|
inline VertexIndex
|
||
|
|
getTargetIndex() const
|
||
|
|
{
|
||
|
|
return (mesh_->getTerminatingVertexIndex(idx_inner_half_edge_));
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the half-edge that is currently stored in the circulator. */
|
||
|
|
inline HalfEdgeIndex
|
||
|
|
getCurrentHalfEdgeIndex() const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief The mesh to which this circulator belongs to. */
|
||
|
|
Mesh* mesh_;
|
||
|
|
|
||
|
|
/** \brief The inner half-edge of the face around which we want to circulate. */
|
||
|
|
HalfEdgeIndex idx_inner_half_edge_;
|
||
|
|
};
|
||
|
|
} // End namespace geometry
|
||
|
|
} // End namespace pcl
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
// InnerHalfEdgeAroundFaceCirculator
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
|
||
|
|
namespace pcl {
|
||
|
|
namespace geometry {
|
||
|
|
/** \brief Circulates clockwise around a face and returns an index to the inner
|
||
|
|
* half-edge (the target). The best way to declare the circulator is to use the method
|
||
|
|
* pcl::geometry::MeshBase::getInnerHalfEdgeAroundFaceCirculator ().
|
||
|
|
* \tparam MeshT Mesh to which this circulator belongs to.
|
||
|
|
* \note The circulator can't be used to change the connectivity in the mesh (only
|
||
|
|
* const circulators are valid).
|
||
|
|
* \author Martin Saelzle
|
||
|
|
* \ingroup geometry
|
||
|
|
*/
|
||
|
|
template <class MeshT>
|
||
|
|
class InnerHalfEdgeAroundFaceCirculator
|
||
|
|
: boost::equality_comparable<
|
||
|
|
pcl::geometry::InnerHalfEdgeAroundFaceCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<pcl::geometry::InnerHalfEdgeAroundFaceCirculator<MeshT>>> {
|
||
|
|
public:
|
||
|
|
using Base = boost::equality_comparable<
|
||
|
|
pcl::geometry::InnerHalfEdgeAroundFaceCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<pcl::geometry::InnerHalfEdgeAroundFaceCirculator<MeshT>>>;
|
||
|
|
using Self = pcl::geometry::InnerHalfEdgeAroundFaceCirculator<MeshT>;
|
||
|
|
|
||
|
|
using Mesh = MeshT;
|
||
|
|
using FaceIndex = typename Mesh::FaceIndex;
|
||
|
|
using HalfEdgeIndex = typename Mesh::HalfEdgeIndex;
|
||
|
|
|
||
|
|
/** \brief Constructor resulting in an invalid circulator. */
|
||
|
|
InnerHalfEdgeAroundFaceCirculator() : mesh_(nullptr), idx_inner_half_edge_() {}
|
||
|
|
|
||
|
|
/** \brief Construct from the face around which we want to circulate. */
|
||
|
|
InnerHalfEdgeAroundFaceCirculator(const FaceIndex& idx_face, Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_inner_half_edge_(mesh->getInnerHalfEdgeIndex(idx_face))
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Construct directly from the inner half-edge. */
|
||
|
|
InnerHalfEdgeAroundFaceCirculator(const HalfEdgeIndex& idx_inner_half_edge,
|
||
|
|
Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_inner_half_edge_(idx_inner_half_edge)
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Check if the circulator is valid.
|
||
|
|
* \warning Does NOT check if the stored mesh pointer is valid. You have to ensure
|
||
|
|
* this yourself when constructing the circulator. */
|
||
|
|
inline bool
|
||
|
|
isValid() const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_.isValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Comparison operators (with boost::operators): == !=
|
||
|
|
* \warning Does NOT check if the circulators belong to the same mesh. Please check
|
||
|
|
* this yourself. */
|
||
|
|
inline bool
|
||
|
|
operator==(const Self& other) const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_ == other.idx_inner_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Increment operators (with boost::operators): ++ (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator++()
|
||
|
|
{
|
||
|
|
idx_inner_half_edge_ = mesh_->getNextHalfEdgeIndex(idx_inner_half_edge_);
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Decrement operators (with boost::operators): -- (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator--()
|
||
|
|
{
|
||
|
|
idx_inner_half_edge_ = mesh_->getPrevHalfEdgeIndex(idx_inner_half_edge_);
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the index to the inner half-edge. */
|
||
|
|
inline HalfEdgeIndex
|
||
|
|
getTargetIndex() const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the half-edge that is currently stored in the circulator. */
|
||
|
|
inline HalfEdgeIndex
|
||
|
|
getCurrentHalfEdgeIndex() const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief The mesh to which this circulator belongs to. */
|
||
|
|
Mesh* mesh_;
|
||
|
|
|
||
|
|
/** \brief The inner half-edge of the face around which we want to circulate. */
|
||
|
|
HalfEdgeIndex idx_inner_half_edge_;
|
||
|
|
};
|
||
|
|
} // End namespace geometry
|
||
|
|
} // End namespace pcl
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
// OuterHalfEdgeAroundFaceCirculator
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
|
||
|
|
namespace pcl {
|
||
|
|
namespace geometry {
|
||
|
|
/** \brief Circulates clockwise around a face and returns an index to the outer
|
||
|
|
* half-edge (the target). The best way to declare the circulator is to use the method
|
||
|
|
* pcl::geometry::MeshBase::getOuterHalfEdgeAroundFaceCirculator ().
|
||
|
|
* \tparam MeshT Mesh to which this circulator belongs to.
|
||
|
|
* \note The circulator can't be used to change the connectivity in the mesh (only
|
||
|
|
* const circulators are valid).
|
||
|
|
* \author Martin Saelzle
|
||
|
|
* \ingroup geometry
|
||
|
|
*/
|
||
|
|
template <class MeshT>
|
||
|
|
class OuterHalfEdgeAroundFaceCirculator
|
||
|
|
: boost::equality_comparable<
|
||
|
|
pcl::geometry::OuterHalfEdgeAroundFaceCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<pcl::geometry::OuterHalfEdgeAroundFaceCirculator<MeshT>>> {
|
||
|
|
public:
|
||
|
|
using Base = boost::equality_comparable<
|
||
|
|
pcl::geometry::OuterHalfEdgeAroundFaceCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<pcl::geometry::OuterHalfEdgeAroundFaceCirculator<MeshT>>>;
|
||
|
|
using Self = pcl::geometry::OuterHalfEdgeAroundFaceCirculator<MeshT>;
|
||
|
|
|
||
|
|
using Mesh = MeshT;
|
||
|
|
using FaceIndex = typename Mesh::FaceIndex;
|
||
|
|
using HalfEdgeIndex = typename Mesh::HalfEdgeIndex;
|
||
|
|
|
||
|
|
/** \brief Constructor resulting in an invalid circulator. */
|
||
|
|
OuterHalfEdgeAroundFaceCirculator() : mesh_(nullptr), idx_inner_half_edge_() {}
|
||
|
|
|
||
|
|
/** \brief Construct from the face around which we want to circulate. */
|
||
|
|
OuterHalfEdgeAroundFaceCirculator(const FaceIndex& idx_face, Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_inner_half_edge_(mesh->getInnerHalfEdgeIndex(idx_face))
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Construct directly from the inner half-edge. */
|
||
|
|
OuterHalfEdgeAroundFaceCirculator(const HalfEdgeIndex& idx_inner_half_edge,
|
||
|
|
Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_inner_half_edge_(idx_inner_half_edge)
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Check if the circulator is valid.
|
||
|
|
* \warning Does NOT check if the stored mesh pointer is valid. You have to ensure
|
||
|
|
* this yourself when constructing the circulator. */
|
||
|
|
inline bool
|
||
|
|
isValid() const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_.isValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Comparison operators (with boost::operators): == !=
|
||
|
|
* \warning Does NOT check if the circulators belong to the same mesh. Please check
|
||
|
|
* this yourself. */
|
||
|
|
inline bool
|
||
|
|
operator==(const Self& other) const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_ == other.idx_inner_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Increment operators (with boost::operators): ++ (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator++()
|
||
|
|
{
|
||
|
|
idx_inner_half_edge_ = mesh_->getNextHalfEdgeIndex(idx_inner_half_edge_);
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Decrement operators (with boost::operators): -- (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator--()
|
||
|
|
{
|
||
|
|
idx_inner_half_edge_ = mesh_->getPrevHalfEdgeIndex(idx_inner_half_edge_);
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the index to the outer half-edge. */
|
||
|
|
inline HalfEdgeIndex
|
||
|
|
getTargetIndex() const
|
||
|
|
{
|
||
|
|
return (mesh_->getOppositeHalfEdgeIndex(idx_inner_half_edge_));
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the half-edge that is currently stored in the circulator. */
|
||
|
|
inline HalfEdgeIndex
|
||
|
|
getCurrentHalfEdgeIndex() const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief The mesh to which this circulator belongs to. */
|
||
|
|
Mesh* mesh_;
|
||
|
|
|
||
|
|
/** \brief The inner half-edge of the face around which we want to circulate. */
|
||
|
|
HalfEdgeIndex idx_inner_half_edge_;
|
||
|
|
};
|
||
|
|
} // End namespace geometry
|
||
|
|
} // End namespace pcl
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
// FaceAroundFaceCirculator
|
||
|
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
|
||
|
|
namespace pcl {
|
||
|
|
namespace geometry {
|
||
|
|
/** \brief Circulates clockwise around a face and returns an index to the face of the
|
||
|
|
* outer half-edge (the target). The best way to declare the circulator is to use the
|
||
|
|
* method pcl::geometry::MeshBase::getFaceAroundFaceCirculator ().
|
||
|
|
* \tparam MeshT Mesh to which this circulator belongs to.
|
||
|
|
* \note The circulator can't be used to change the connectivity in the mesh (only
|
||
|
|
* const circulators are valid).
|
||
|
|
* \author Martin Saelzle
|
||
|
|
* \ingroup geometry
|
||
|
|
*/
|
||
|
|
template <class MeshT>
|
||
|
|
class FaceAroundFaceCirculator
|
||
|
|
: boost::equality_comparable<
|
||
|
|
pcl::geometry::FaceAroundFaceCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<pcl::geometry::FaceAroundFaceCirculator<MeshT>>> {
|
||
|
|
public:
|
||
|
|
using Base = boost::equality_comparable<
|
||
|
|
pcl::geometry::FaceAroundFaceCirculator<MeshT>,
|
||
|
|
boost::unit_steppable<pcl::geometry::FaceAroundFaceCirculator<MeshT>>>;
|
||
|
|
using Self = pcl::geometry::FaceAroundFaceCirculator<MeshT>;
|
||
|
|
|
||
|
|
using Mesh = MeshT;
|
||
|
|
using FaceIndex = typename Mesh::FaceIndex;
|
||
|
|
using HalfEdgeIndex = typename Mesh::HalfEdgeIndex;
|
||
|
|
|
||
|
|
/** \brief Constructor resulting in an invalid circulator. */
|
||
|
|
FaceAroundFaceCirculator() : mesh_(nullptr), idx_inner_half_edge_() {}
|
||
|
|
|
||
|
|
/** \brief Construct from the face around which we want to circulate. */
|
||
|
|
FaceAroundFaceCirculator(const FaceIndex& idx_face, Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_inner_half_edge_(mesh->getInnerHalfEdgeIndex(idx_face))
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Construct directly from the inner half-edge. */
|
||
|
|
FaceAroundFaceCirculator(const HalfEdgeIndex& idx_inner_half_edge, Mesh* const mesh)
|
||
|
|
: mesh_(mesh), idx_inner_half_edge_(idx_inner_half_edge)
|
||
|
|
{}
|
||
|
|
|
||
|
|
/** \brief Check if the circulator is valid.
|
||
|
|
* \warning Does NOT check if the stored mesh pointer is valid. You have to ensure
|
||
|
|
* this yourself when constructing the circulator. */
|
||
|
|
inline bool
|
||
|
|
isValid() const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_.isValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Comparison operators (with boost::operators): == !=
|
||
|
|
* \warning Does NOT check if the circulators belong to the same mesh. Please check
|
||
|
|
* this yourself. */
|
||
|
|
inline bool
|
||
|
|
operator==(const Self& other) const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_ == other.idx_inner_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Increment operators (with boost::operators): ++ (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator++()
|
||
|
|
{
|
||
|
|
idx_inner_half_edge_ = mesh_->getNextHalfEdgeIndex(idx_inner_half_edge_);
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Decrement operators (with boost::operators): -- (pre and post) */
|
||
|
|
inline Self&
|
||
|
|
operator--()
|
||
|
|
{
|
||
|
|
idx_inner_half_edge_ = mesh_->getPrevHalfEdgeIndex(idx_inner_half_edge_);
|
||
|
|
return (*this);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the index to the target face. */
|
||
|
|
inline FaceIndex
|
||
|
|
getTargetIndex() const
|
||
|
|
{
|
||
|
|
return (mesh_->getOppositeFaceIndex(idx_inner_half_edge_));
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief Get the half-edge that is currently stored in the circulator. */
|
||
|
|
inline HalfEdgeIndex
|
||
|
|
getCurrentHalfEdgeIndex() const
|
||
|
|
{
|
||
|
|
return (idx_inner_half_edge_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** \brief The mesh to which this circulator belongs to. */
|
||
|
|
Mesh* mesh_;
|
||
|
|
|
||
|
|
/** \brief The inner half-edge of the face around which we want to circulate. */
|
||
|
|
HalfEdgeIndex idx_inner_half_edge_;
|
||
|
|
};
|
||
|
|
} // End namespace geometry
|
||
|
|
} // End namespace pcl
|