|
Shinya Kitaoka |
810553 |
// #pragma once // could not use by INCLUDE_HPP
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifndef MESH_H
|
|
Toshihiro Shimizu |
890ddd |
#define MESH_H
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// tcg includes
|
|
Toshihiro Shimizu |
890ddd |
#include "list.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace tcg {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//********************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Polygon Mesh template class
|
|
Toshihiro Shimizu |
890ddd |
//********************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
\brief The mesh class models entities composed of vertices, edges and face
|
|
Toshihiro Shimizu |
890ddd |
using an index-based random access approach.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\details This mesh implementation uses 3 separate tcg::list to provide the
|
|
Shinya Kitaoka |
120a6e |
fundamental index-based access to components, one per component
|
|
Shinya Kitaoka |
120a6e |
type.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Said component containers are an explicit requirement of the mesh
|
|
Toshihiro Shimizu |
890ddd |
class, and direct access is therefore provided. However, use of
|
|
Toshihiro Shimizu |
890ddd |
(mutating) direct accessors should be restricted to special cases,
|
|
Toshihiro Shimizu |
890ddd |
since direct components manipulation is \a nontrivial - use the
|
|
Toshihiro Shimizu |
890ddd |
appropriate \p add and \p remove methods to manipulate single
|
|
Toshihiro Shimizu |
890ddd |
components.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
\sa Classes tcg::Vertex, tcg::Edge and tcg::Face for
|
|
Shinya Kitaoka |
120a6e |
tcg::Mesh-compatible
|
|
Toshihiro Shimizu |
890ddd |
VEF models.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
class Mesh {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
typedef V vertex_type;
|
|
Shinya Kitaoka |
120a6e |
typedef E edge_type;
|
|
Shinya Kitaoka |
120a6e |
typedef F face_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
typedef list<v> vertices_container;</v>
|
|
Shinya Kitaoka |
120a6e |
typedef list<e> edges_container;</e>
|
|
Shinya Kitaoka |
120a6e |
typedef list<f> faces_container;</f>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
protected:
|
|
Shinya Kitaoka |
120a6e |
vertices_container m_vertices;
|
|
Shinya Kitaoka |
120a6e |
edges_container m_edges;
|
|
Shinya Kitaoka |
120a6e |
faces_container m_faces;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
Mesh() {}
|
|
Shinya Kitaoka |
120a6e |
~Mesh() {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool empty() const { return m_vertices.empty(); }
|
|
Shinya Kitaoka |
120a6e |
void clear() {
|
|
Shinya Kitaoka |
120a6e |
m_vertices.clear();
|
|
Shinya Kitaoka |
120a6e |
m_edges.clear();
|
|
Shinya Kitaoka |
120a6e |
m_faces.clear();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int verticesCount() const { return int(m_vertices.size()); }
|
|
Shinya Kitaoka |
120a6e |
int edgesCount() const { return int(m_edges.size()); }
|
|
Shinya Kitaoka |
120a6e |
int facesCount() const { return int(m_faces.size()); }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const vertices_container &vertices() const { return m_vertices; }
|
|
Shinya Kitaoka |
120a6e |
vertices_container &vertices() { return m_vertices; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const edges_container &edges() const { return m_edges; }
|
|
Shinya Kitaoka |
120a6e |
edges_container &edges() { return m_edges; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const faces_container &faces() const { return m_faces; }
|
|
Shinya Kitaoka |
120a6e |
faces_container &faces() { return m_faces; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int addVertex(const V &v) {
|
|
Shinya Kitaoka |
120a6e |
int idx = int(m_vertices.push_back(v));
|
|
Shinya Kitaoka |
120a6e |
m_vertices[idx].setIndex(idx);
|
|
Shinya Kitaoka |
120a6e |
return idx;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
int addEdge(const E &e);
|
|
Shinya Kitaoka |
120a6e |
int addFace(const F &f);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void removeVertex(int v); //!< Removes the <tt>v</tt>-th vertex from the
|
|
Shinya Kitaoka |
38fd86 |
//! mesh. \warning Any adjacent edge or face will
|
|
Shinya Kitaoka |
38fd86 |
//! be removed, too. \param v Index of the vertex
|
|
Shinya Kitaoka |
38fd86 |
//! to be removed.
|
|
Shinya Kitaoka |
38fd86 |
void removeEdge(int e); //!< Removes the <tt>e</tt>-th edge from the mesh.
|
|
Shinya Kitaoka |
120a6e |
//!\warning Any adjacent face will be removed, too.
|
|
Shinya Kitaoka |
120a6e |
//!\param e Index of the edge to be removed.
|
|
Shinya Kitaoka |
120a6e |
void removeFace(int f); //!< Removes the <tt>f</tt>-th face from the mesh.
|
|
Shinya Kitaoka |
120a6e |
//!\param f Index of the face to be removed.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const V &vertex(int v) const { return m_vertices[v]; }
|
|
Shinya Kitaoka |
120a6e |
V &vertex(int v) {
|
|
Shinya Kitaoka |
120a6e |
return m_vertices[v];
|
|
Shinya Kitaoka |
120a6e |
} //!< Returns the <tt>v</tt>-th mesh vertex. \param v Index of the vertex
|
|
Shinya Kitaoka |
38fd86 |
//! to be returned. \return See description.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const E &edge(int e) const { return m_edges[e]; }
|
|
Shinya Kitaoka |
120a6e |
E &edge(int e) {
|
|
Shinya Kitaoka |
120a6e |
return m_edges[e];
|
|
Shinya Kitaoka |
120a6e |
} //!< Returns the <tt>e</tt>-th mesh edge. \param e Index of the edge to
|
|
Shinya Kitaoka |
38fd86 |
//! be returned. \return See description.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const F &face(int f) const { return m_faces[f]; }
|
|
Shinya Kitaoka |
120a6e |
F &face(int f) {
|
|
Shinya Kitaoka |
120a6e |
return m_faces[f];
|
|
Shinya Kitaoka |
120a6e |
} //!< Returns the <tt>f</tt>-th mesh face. \param f Index of the face to
|
|
Shinya Kitaoka |
38fd86 |
//! be returned. \return See description.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const V &edgeVertex(int e, int i) const { return vertex(edge(e).vertex(i)); }
|
|
Shinya Kitaoka |
120a6e |
V &edgeVertex(int e, int i) //! \param e Host edge index. \param i Vertex
|
|
Shinya Kitaoka |
120a6e |
//! index in e. \return See description.
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
return vertex(edge(e).vertex(i));
|
|
Shinya Kitaoka |
120a6e |
} //!< Returns the <tt>i</tt>-th vertex in the edge of index \p e.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const F &edgeFace(int e, int i) const { return face(edge(e).face(i)); }
|
|
Shinya Kitaoka |
120a6e |
F &edgeFace(int e, int i) //! \param e Host edge index. \param i Face
|
|
Shinya Kitaoka |
120a6e |
//! index in e. \return See description.
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
return face(edge(e).face(i));
|
|
Shinya Kitaoka |
120a6e |
} //!< Returns the <tt>i</tt>-th face in the edge of index \p e.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const V &otherEdgeVertex(int e, int v) const {
|
|
Shinya Kitaoka |
120a6e |
return vertex(edge(e).otherVertex(v));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
V &otherEdgeVertex(int e, int v) //! \param e Host edge index. \param v
|
|
Shinya Kitaoka |
120a6e |
//! Index of the adjacent vertex to \p e
|
|
Shinya Kitaoka |
120a6e |
//! we're not interested in. \return See
|
|
Shinya Kitaoka |
120a6e |
//! description.
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
return vertex(edge(e).otherVertex(v));
|
|
Shinya Kitaoka |
120a6e |
} //!< Retrieves the vertex adjacent to \p e whose index is \a not \p v.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const F &otherEdgeFace(int e, int f) const {
|
|
Shinya Kitaoka |
120a6e |
return face(edge(e).otherFace(f));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
F &otherEdgeFace(int e, int f) //! \param e Host edge index. \param f
|
|
Shinya Kitaoka |
120a6e |
//! Index of the adjacent face to \p e we're
|
|
Shinya Kitaoka |
120a6e |
//! not interested in. \return See
|
|
Shinya Kitaoka |
120a6e |
//! description.
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
return face(edge(e).otherFace(f));
|
|
Shinya Kitaoka |
120a6e |
} //!< Retrieves the face adjacent to \p e whose index is \a not \p f.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*!
|
|
Shinya Kitaoka |
120a6e |
\remark Index \p n is arbitrary. Use it to traverse all edges inciding \p v1
|
|
Shinya Kitaoka |
120a6e |
and \p v2:
|
|
Shinya Kitaoka |
120a6e |
\code for(int n=0; mesh.edgeInciding(v1, v2, n) > 0; ++n) ... \endcode
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
int edgeInciding(int v1, int v2, int n = 0) const; //!< \brief Returns the
|
|
Shinya Kitaoka |
38fd86 |
//! edge index of the
|
|
Shinya Kitaoka |
38fd86 |
//!<tt>n</tt>-th edge
|
|
Shinya Kitaoka |
38fd86 |
//! inciding
|
|
Shinya Kitaoka |
120a6e |
//! \p v1 and \p v2, or \p -1 if the required edge could not be found.
|
|
Shinya Kitaoka |
120a6e |
//! \param v1 First edge endpoint. \param v2 Second edge endpoint. \param
|
|
Shinya Kitaoka |
120a6e |
//! n Index in the sequence of all edges inciding \p v1 and \p v2. \return
|
|
Shinya Kitaoka |
120a6e |
//! See description.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
//! \remark All indices and iterators will be \a invalidated.
|
|
Shinya Kitaoka |
120a6e |
void
|
|
Shinya Kitaoka |
120a6e |
squeeze(); //!< \brief Eliminates unused list nodes in the representation of
|
|
Shinya Kitaoka |
120a6e |
//! vertices, edges and faces.
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//********************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Triangular Mesh template class
|
|
Toshihiro Shimizu |
890ddd |
//********************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
class TriMesh : public Mesh<v, e,="" f=""> {</v,>
|
|
Toshihiro Shimizu |
890ddd |
protected:
|
|
Shinya Kitaoka |
120a6e |
using Mesh<v, e,="" f="">::m_vertices;</v,>
|
|
Shinya Kitaoka |
120a6e |
using Mesh<v, e,="" f="">::m_edges;</v,>
|
|
Shinya Kitaoka |
120a6e |
using Mesh<v, e,="" f="">::m_faces;</v,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
TriMesh() {}
|
|
Shinya Kitaoka |
120a6e |
TriMesh(int verticesHint);
|
|
Shinya Kitaoka |
120a6e |
~TriMesh() {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int addFace(V &v1, V &v2, V &v3);
|
|
Shinya Kitaoka |
120a6e |
int addFace(int v1, int v2, int v3) {
|
|
Shinya Kitaoka |
120a6e |
return addFace(Mesh<v, e,="" f="">::vertex(v1), Mesh<v, e,="" f="">::vertex(v2),</v,></v,>
|
|
Shinya Kitaoka |
120a6e |
Mesh<v, e,="" f="">::vertex(v3));</v,>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int otherFaceVertex(int f, int e) const;
|
|
Shinya Kitaoka |
120a6e |
int otherFaceVertex(int f, int v1, int v2) const {
|
|
Shinya Kitaoka |
120a6e |
return otherFaceVertex(f, Mesh<v, e,="" f="">::edgeInciding(v1, v2));</v,>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int otherFaceEdge(int f, int v) const;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void faceVertices(int f, int &v1, int &v2, int &v3) const {
|
|
Shinya Kitaoka |
120a6e |
const E &ed = Mesh<v, e,="" f="">::edge(Mesh<v, e,="" f="">::face(f).edge(0));</v,></v,>
|
|
Shinya Kitaoka |
120a6e |
v1 = ed.vertex(0);
|
|
Shinya Kitaoka |
120a6e |
v2 = ed.vertex(1);
|
|
Shinya Kitaoka |
120a6e |
v3 = otherFaceVertex(f, ed.getIndex());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*!
|
|
Shinya Kitaoka |
120a6e |
\details This function selects an edge with \a two adjacent faces, and swaps
|
|
Shinya Kitaoka |
120a6e |
its endpoints with their otherFaceVertex().
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
\remark This function is idempotent - swapEdge(swapEdge(e)) has no effect
|
|
Shinya Kitaoka |
120a6e |
on the mesh (assuming swapEdge(e) is not \p -1). In particular,
|
|
Shinya Kitaoka |
120a6e |
indices
|
|
Shinya Kitaoka |
120a6e |
should remain the same.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
\note In current implementation, the result is the very same input
|
|
Shinya Kitaoka |
120a6e |
edge index.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
\return The swapped edge, or \p -1 if the supplied edge did not have \a two
|
|
Shinya Kitaoka |
120a6e |
adjacent faces.
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
int swapEdge(
|
|
Shinya Kitaoka |
120a6e |
int e); //!< Swaps the specified edge in the \a two adjacent faces.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*!
|
|
Shinya Kitaoka |
120a6e |
\details Specifically, this function removes <tt>edgeVertex(e, 1)</tt> and
|
|
Shinya Kitaoka |
120a6e |
redirects its edges to
|
|
Shinya Kitaoka |
120a6e |
<tt>edgeVertex(e, 0)</tt>. One edge per adjacent face (other than \p
|
|
Shinya Kitaoka |
120a6e |
e) will be removed
|
|
Shinya Kitaoka |
120a6e |
(which can be thought as 'merged' with the remaining one), and each
|
|
Shinya Kitaoka |
120a6e |
adjacent face will be
|
|
Shinya Kitaoka |
120a6e |
removed.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
\note This function removes at most 1 vertex, 3 edges and 2 faces,
|
|
Shinya Kitaoka |
120a6e |
total.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
\warning The user is respondible for ensuring that every vertex adjacent to
|
|
Shinya Kitaoka |
120a6e |
\a both the
|
|
Shinya Kitaoka |
120a6e |
collapsed edge's endpoints is \a also adjacent to one of the edge's \a
|
|
Shinya Kitaoka |
120a6e |
faces.
|
|
Shinya Kitaoka |
120a6e |
If not, the output configuration would be ill-formed. This function
|
|
Shinya Kitaoka |
120a6e |
will
|
|
Shinya Kitaoka |
120a6e |
\a assert in this case, and result in undefined behavior.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
\return The remaining vertex index - specifically, <tt>edgeVertex(e,</tt>
|
|
Shinya Kitaoka |
120a6e |
0).
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
int collapseEdge(int e); //!< Collapses the specified edge.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*!
|
|
Shinya Kitaoka |
120a6e |
\details This function inserts a new vertex at the midpoint of the specified
|
|
Shinya Kitaoka |
120a6e |
edge, and
|
|
Shinya Kitaoka |
120a6e |
splits any adjacent face in two.
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
\return The inserted vertex index.
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
int splitEdge(int e); //!< \brief Splits the specified edge, inserting a new
|
|
Shinya Kitaoka |
120a6e |
//! vertex at the middle.
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace tcg
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
#endif // MESH_H
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef INCLUDE_HPP
|
|
Toshihiro Shimizu |
890ddd |
#include "hpp/mesh.hpp"
|
|
Toshihiro Shimizu |
890ddd |
#endif
|