|
Shinya Kitaoka |
810553 |
#pragma once
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifndef TCG_MESH_HPP
|
|
Toshihiro Shimizu |
890ddd |
#define TCG_MESH_HPP
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// tcg includes
|
|
Toshihiro Shimizu |
890ddd |
#include "../mesh.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace tcg {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Polygon Mesh methods
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
int Mesh<v, e,="" f="">::edgeInciding(int vIdx1, int vIdx2, int n) const {</v,>
|
|
Shinya Kitaoka |
120a6e |
const V &v1 = vertex(vIdx1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const tcg::list<int> &incidingV1 = v1.edges();</int>
|
|
Shinya Kitaoka |
120a6e |
tcg::list<int>::const_iterator it;</int>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (it = incidingV1.begin(); it != incidingV1.end(); ++it) {
|
|
Shinya Kitaoka |
120a6e |
const E &e = edge(*it);
|
|
Shinya Kitaoka |
120a6e |
if (e.otherVertex(vIdx1) == vIdx2 && n-- == 0) break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return (it == incidingV1.end()) ? -1 : (*it);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
int Mesh<v, e,="" f="">::addEdge(const E &ed) {</v,>
|
|
Shinya Kitaoka |
120a6e |
int e = int(m_edges.push_back(ed));
|
|
Shinya Kitaoka |
120a6e |
m_edges[e].setIndex(e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Add the edge index to the edge's vertices
|
|
Shinya Kitaoka |
120a6e |
typename edge_traits<e>::vertices_const_iterator it, end(ed.verticesEnd());</e>
|
|
Shinya Kitaoka |
120a6e |
for (it = ed.verticesBegin(); it != end; ++it) m_vertices[*it].addEdge(e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return e;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
int Mesh<v, e,="" f="">::addFace(const F &fc) {</v,>
|
|
Shinya Kitaoka |
120a6e |
int f = int(m_faces.push_back(fc));
|
|
Shinya Kitaoka |
120a6e |
m_faces[f].setIndex(f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Add the face index to the face's edges
|
|
Shinya Kitaoka |
120a6e |
typename face_traits<f>::edges_const_iterator it, end = fc.edgesEnd();</f>
|
|
Shinya Kitaoka |
120a6e |
for (it = fc.edgesBegin(); it != end; ++it) m_edges[*it].addFace(f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return f;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void Mesh<v, e,="" f="">::removeVertex(int v) {</v,>
|
|
Shinya Kitaoka |
120a6e |
V &vx = vertex(v);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// As long as there are incident edges, remove them
|
|
Shinya Kitaoka |
120a6e |
while (vx.edgesCount() > 0) removeEdge(vx.edges().front());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_vertices.erase(v);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void Mesh<v, e,="" f="">::removeEdge(int e) {</v,>
|
|
Shinya Kitaoka |
120a6e |
E &ed = edge(e);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Remove all the associated faces
|
|
Shinya Kitaoka |
120a6e |
typename edge_traits<e>::faces_iterator ft;</e>
|
|
Shinya Kitaoka |
120a6e |
while ((ft = ed.facesBegin()) !=
|
|
Shinya Kitaoka |
120a6e |
ed.facesEnd()) // current iterator could be erased here!
|
|
Shinya Kitaoka |
120a6e |
removeFace(*ft);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Remove the edge from the associated vertices
|
|
Shinya Kitaoka |
120a6e |
typename edge_traits<e>::vertices_iterator vt, vEnd = ed.verticesEnd();</e>
|
|
Shinya Kitaoka |
120a6e |
for (vt = ed.verticesBegin(); vt != vEnd; ++vt) {
|
|
Shinya Kitaoka |
120a6e |
V &vx = vertex(*vt);
|
|
Shinya Kitaoka |
120a6e |
typename vertex_traits<v>::edges_iterator et =</v>
|
|
Shinya Kitaoka |
120a6e |
std::find(vx.edgesBegin(), vx.edgesEnd(), e);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(et != vx.edgesEnd());
|
|
Shinya Kitaoka |
120a6e |
vx.eraseEdge(et);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_edges.erase(e);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void Mesh<v, e,="" f="">::removeFace(int f) {</v,>
|
|
Shinya Kitaoka |
120a6e |
F &fc = face(f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Remove the face from all adjacent edges
|
|
Shinya Kitaoka |
120a6e |
typename face_traits<f>::edges_iterator et, eEnd = fc.edgesEnd();</f>
|
|
Shinya Kitaoka |
120a6e |
for (et = fc.edgesBegin(); et != eEnd; ++et) {
|
|
Shinya Kitaoka |
120a6e |
E &ed = edge(*et);
|
|
Shinya Kitaoka |
120a6e |
typename edge_traits<e>::faces_iterator ft =</e>
|
|
Shinya Kitaoka |
120a6e |
std::find(ed.facesBegin(), ed.facesEnd(), f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
assert(ft != ed.facesEnd());
|
|
Shinya Kitaoka |
120a6e |
ed.eraseFace(ft);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_faces.erase(f);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Shinya Kitaoka |
120a6e |
\brief Remaps the mesh indices in a natural order, removing unused cells in
|
|
Shinya Kitaoka |
120a6e |
the internal
|
|
Toshihiro Shimizu |
890ddd |
container model, for minimum memory consumption.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
\warning This is a slow operation, compared to all the others in the Mesh
|
|
Shinya Kitaoka |
120a6e |
class.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void Mesh<v, e,="" f="">::squeeze() {</v,>
|
|
Shinya Kitaoka |
120a6e |
// Build new indices for remapping.
|
|
Shinya Kitaoka |
120a6e |
typename tcg::list<f>::iterator it, endI(m_faces.end());</f>
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0, it = m_faces.begin(); it != endI; ++i, ++it) it->setIndex(i);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
typename tcg::list<e>::iterator jt, endJ(m_edges.end());</e>
|
|
Shinya Kitaoka |
120a6e |
for (i = 0, jt = m_edges.begin(); jt != endJ; ++i, ++jt) jt->setIndex(i);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
typename tcg::list<v>::iterator kt, endK(m_vertices.end());</v>
|
|
Shinya Kitaoka |
120a6e |
for (i = 0, kt = m_vertices.begin(); kt != endK; ++i, ++kt) kt->setIndex(i);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Update stored indices
|
|
Shinya Kitaoka |
120a6e |
for (it = m_faces.begin(); it != endI; ++it) {
|
|
Shinya Kitaoka |
120a6e |
F &face = *it;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
typename face_traits<f>::edges_iterator et, eEnd = face.edgesEnd();</f>
|
|
Shinya Kitaoka |
120a6e |
for (et = face.edgesBegin(); et != eEnd; ++et) *et = edge(*et).getIndex();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (jt = m_edges.begin(); jt != endJ; ++jt) {
|
|
Shinya Kitaoka |
120a6e |
E &edge = *jt;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
typename edge_traits<e>::vertices_iterator vt, vEnd = edge.verticesEnd();</e>
|
|
Shinya Kitaoka |
120a6e |
for (vt = edge.verticesBegin(); vt != vEnd; ++vt)
|
|
Shinya Kitaoka |
120a6e |
*vt = vertex(*vt).getIndex();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
typename edge_traits<e>::faces_iterator ft, fEnd = edge.facesEnd();</e>
|
|
Shinya Kitaoka |
120a6e |
for (ft = edge.facesBegin(); ft != fEnd; ++ft) *ft = face(*ft).getIndex();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
tcg::list<int>::iterator lt;</int>
|
|
Shinya Kitaoka |
120a6e |
for (kt = m_vertices.begin(); kt != endK; ++kt) {
|
|
Shinya Kitaoka |
120a6e |
V &vertex = *kt;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
typename vertex_traits<v>::edges_iterator et, eEnd = vertex.edgesEnd();</v>
|
|
Shinya Kitaoka |
120a6e |
for (et = vertex.edgesBegin(); et != eEnd; ++et) *et = edge(*et).getIndex();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Finally, rebuild the actual containers
|
|
Shinya Kitaoka |
120a6e |
if (!m_faces.empty()) {
|
|
Shinya Kitaoka |
120a6e |
tcg::list<f> temp(m_faces.begin(), m_faces.end());</f>
|
|
Shinya Kitaoka |
120a6e |
std::swap(m_faces, temp);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!m_edges.empty()) {
|
|
Shinya Kitaoka |
120a6e |
tcg::list<e> temp(m_edges.begin(), m_edges.end());</e>
|
|
Shinya Kitaoka |
120a6e |
std::swap(m_edges, temp);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!m_vertices.empty()) {
|
|
Shinya Kitaoka |
120a6e |
tcg::list<v> temp(m_vertices.begin(), m_vertices.end());</v>
|
|
Shinya Kitaoka |
120a6e |
std::swap(m_vertices, temp);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Triangular Mesh methods
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
TriMesh<v, e,="" f="">::TriMesh(int verticesHint) {</v,>
|
|
Shinya Kitaoka |
120a6e |
int edgesHint = (3 * verticesHint) / 2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_vertices.reserve(verticesHint);
|
|
Shinya Kitaoka |
120a6e |
m_edges.reserve(edgesHint);
|
|
Shinya Kitaoka |
120a6e |
m_faces.reserve(edgesHint + 1); // Since V - E + F = 1 for planar graphs (no
|
|
Shinya Kitaoka |
120a6e |
// outer face), and vMin == 0
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
int TriMesh<v, e,="" f="">::addFace(V &vx1, V &vx2, V &vx3) {</v,>
|
|
Shinya Kitaoka |
120a6e |
int v1 = vx1.getIndex(), v2 = vx2.getIndex(), v3 = vx3.getIndex();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Retrieve the edges having v1, v2, v3 in common
|
|
Shinya Kitaoka |
120a6e |
int e1, e2, e3;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
e1 = this->edgeInciding(v1, v2);
|
|
Shinya Kitaoka |
120a6e |
e2 = this->edgeInciding(v2, v3);
|
|
Shinya Kitaoka |
120a6e |
e3 = this->edgeInciding(v3, v1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (e1 < 0) e1 = this->addEdge(E(v1, v2));
|
|
Shinya Kitaoka |
120a6e |
if (e2 < 0) e2 = this->addEdge(E(v2, v3));
|
|
Shinya Kitaoka |
120a6e |
if (e3 < 0) e3 = this->addEdge(E(v3, v1));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
F fc;
|
|
Shinya Kitaoka |
120a6e |
fc.addEdge(e1), fc.addEdge(e2), fc.addEdge(e3);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int f = int(m_faces.push_back(fc));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_faces[f].setIndex(f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
E &E1 = this->edge(e1);
|
|
Shinya Kitaoka |
120a6e |
E1.addFace(f);
|
|
Shinya Kitaoka |
120a6e |
E &E2 = this->edge(e2);
|
|
Shinya Kitaoka |
120a6e |
E2.addFace(f);
|
|
Shinya Kitaoka |
120a6e |
E &E3 = this->edge(e3);
|
|
Shinya Kitaoka |
120a6e |
E3.addFace(f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return f;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
int TriMesh<v, e,="" f="">::otherFaceVertex(int f, int e) const {</v,>
|
|
Shinya Kitaoka |
120a6e |
const F &face = Mesh<v, e,="" f="">::face(f);</v,>
|
|
Shinya Kitaoka |
120a6e |
const E &otherEdge =
|
|
Shinya Kitaoka |
120a6e |
face.edge(0) == e ? this->edge(face.edge(1)) : this->edge(face.edge(0));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int v1 = this->edge(e).vertex(0), v2 = this->edge(e).vertex(1),
|
|
Shinya Kitaoka |
120a6e |
v3 = otherEdge.otherVertex(v1);
|
|
Shinya Kitaoka |
120a6e |
return (v3 == v2) ? otherEdge.otherVertex(v2) : v3;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
int TriMesh<v, e,="" f="">::otherFaceEdge(int f, int v) const {</v,>
|
|
Shinya Kitaoka |
120a6e |
const F &face = Mesh<v, e,="" f="">::face(f);</v,>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
const E &ed = this->edge(face.edge(0));
|
|
Shinya Kitaoka |
120a6e |
if (ed.vertex(0) != v && ed.vertex(1) != v) return face.edge(0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
const E &ed = this->edge(face.edge(1));
|
|
Shinya Kitaoka |
120a6e |
if (ed.vertex(0) != v && ed.vertex(1) != v) return face.edge(1);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return face.edge(2);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
int TriMesh<v, e,="" f="">::swapEdge(int e) {</v,>
|
|
Shinya Kitaoka |
120a6e |
E &ed = this->edge(e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (ed.facesCount() < 2) return -1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int f1 = ed.face(0), f2 = ed.face(1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Retrieve the 2 vertices not belonging to e in the adjacent faces
|
|
Shinya Kitaoka |
120a6e |
int v1 = ed.vertex(0), v2 = ed.vertex(1);
|
|
Shinya Kitaoka |
120a6e |
int v3 = otherFaceVertex(f1, e), v4 = otherFaceVertex(f2, e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
assert(this->edgeInciding(v3, v4) < 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Remove e
|
|
Shinya Kitaoka |
120a6e |
this->removeEdge(e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Insert the new faces
|
|
Shinya Kitaoka |
120a6e |
addFace(v1, v3, v4); // Inserts edge E(v3, v4)
|
|
Shinya Kitaoka |
120a6e |
addFace(v2, v4, v3);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return this->edgeInciding(v3, v4);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
*---*---* Common case * FORBIDDEN case:
|
|
Toshihiro Shimizu |
890ddd |
/ \ / x / \ /|\ note that the collapsed edge
|
|
Shinya Kitaoka |
120a6e |
*---*-x-X---* /_*_\ have 3 (possibly more) other
|
|
Shinya Kitaoka |
120a6e |
vertices
|
|
Shinya Kitaoka |
120a6e |
\ / \ x \ / *--X--* with edges inciding both the
|
|
Shinya Kitaoka |
120a6e |
collapsed
|
|
Toshihiro Shimizu |
890ddd |
*---*---* \ / edge's extremes.
|
|
Toshihiro Shimizu |
890ddd |
\ /
|
|
Shinya Kitaoka |
120a6e |
* This cannot be processed,
|
|
Shinya Kitaoka |
120a6e |
since the
|
|
Shinya Kitaoka |
120a6e |
unexpected merged edge would
|
|
Shinya Kitaoka |
120a6e |
either have
|
|
Shinya Kitaoka |
120a6e |
more than 2 adjacent faces,
|
|
Shinya Kitaoka |
120a6e |
or a hole.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
int TriMesh<v, e,="" f="">::collapseEdge(int e) {</v,>
|
|
Shinya Kitaoka |
120a6e |
E &ed = this->edge(e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// First, retrieve ed's adjacent vertices
|
|
Shinya Kitaoka |
120a6e |
int vKeep = ed.vertex(0), vDelete = ed.vertex(1);
|
|
Shinya Kitaoka |
120a6e |
V &vxKeep = this->vertex(vKeep), &vxDelete = this->vertex(vDelete);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Then, retrieve the 2 vertices not belonging to e in the adjacent faces
|
|
Shinya Kitaoka |
120a6e |
int f, fCount = ed.facesCount();
|
|
Shinya Kitaoka |
120a6e |
int otherV[2];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (f = 0; f != fCount; ++f) otherV[f] = otherFaceVertex(ed.face(f), e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Remove e
|
|
Shinya Kitaoka |
120a6e |
this->removeEdge(e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Merge edges inciding vDelete and otherV with the corresponding inciding
|
|
Shinya Kitaoka |
120a6e |
// vKeep and otherV
|
|
Shinya Kitaoka |
120a6e |
for (f = 0; f != fCount; ++f) {
|
|
Shinya Kitaoka |
120a6e |
int srcE = this->edgeInciding(vDelete, otherV[f]),
|
|
Shinya Kitaoka |
120a6e |
dstE = this->edgeInciding(vKeep, otherV[f]);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
E &srcEd = this->edge(srcE), &dstEd = this->edge(dstE);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
typename edge_traits<e>::faces_iterator ft = srcEd.facesBegin();</e>
|
|
Shinya Kitaoka |
120a6e |
while (ft != srcEd.facesEnd()) // current iterator will be erased
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
F &fc = this->face(*ft);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
(fc.edge(0) == srcE)
|
|
Shinya Kitaoka |
120a6e |
? fc.setEdge(0, dstE)
|
|
Shinya Kitaoka |
120a6e |
: (fc.edge(1) == srcE) ? fc.setEdge(1, dstE) : fc.setEdge(2, dstE);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
dstEd.addFace(*ft);
|
|
Shinya Kitaoka |
120a6e |
ft = srcEd.eraseFace(ft); // here
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
this->removeEdge(srcE);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Move further edges adjacent to vDelete to vKeep
|
|
Shinya Kitaoka |
120a6e |
typename vertex_traits<v>::edges_iterator et = vxDelete.edgesBegin();</v>
|
|
Shinya Kitaoka |
120a6e |
while (et != vxDelete.edgesEnd()) // current iterator will be erased
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
E &ed = this->edge(*et);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Ensure that there is no remaining edge which would be duplicated
|
|
Toshihiro Shimizu |
890ddd |
// after vDelete and vKeep merge
|
|
Toshihiro Shimizu |
890ddd |
/* FIXME: edgeInciding がないと言われるのでとりあえず省略 */
|
|
Toshihiro Shimizu |
890ddd |
#if 0
|
|
Toshihiro Shimizu |
890ddd |
assert("Detected vertex adjacent to collapsed edge's endpoints, but not to its faces." &&
|
|
Toshihiro Shimizu |
890ddd |
edgeInciding(ed.otherVertex(vDelete), vKeep) < 0);
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Shinya Kitaoka |
120a6e |
(ed.vertex(0) == vDelete) ? ed.setVertex(0, vKeep) : ed.setVertex(1, vKeep);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
vxKeep.addEdge(*et);
|
|
Shinya Kitaoka |
120a6e |
et = vxDelete.eraseEdge(et); // here
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Finally, update vKeep's position and remove vDelete
|
|
Shinya Kitaoka |
120a6e |
vxKeep.P() = 0.5 * (vxKeep.P() + vxDelete.P());
|
|
Shinya Kitaoka |
120a6e |
m_vertices.erase(vDelete);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return vKeep;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename e,="" f="" typename="" v,=""></typename>
|
|
Shinya Kitaoka |
120a6e |
int TriMesh<v, e,="" f="">::splitEdge(int e) {</v,>
|
|
Shinya Kitaoka |
120a6e |
E &ed = this->edge(e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Build a new vertex on the middle of e
|
|
Shinya Kitaoka |
120a6e |
int v1 = ed.vertex(0), v2 = ed.vertex(1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
V &vx1 = this->vertex(v1), &vx2 = this->vertex(v2);
|
|
Shinya Kitaoka |
120a6e |
V v(0.5 * (vx1.P() + vx2.P()));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int vIdx = this->addVertex(v);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Retrieve opposite vertices
|
|
Shinya Kitaoka |
120a6e |
int otherV[2]; // NOTE: If ever extended to support edges with
|
|
Shinya Kitaoka |
120a6e |
int f,
|
|
Shinya Kitaoka |
120a6e |
fCount =
|
|
Shinya Kitaoka |
120a6e |
ed.facesCount(); // MORE than 2 adjacent faces, the new faces
|
|
Shinya Kitaoka |
120a6e |
// should be inserted BEFORE removing the split
|
|
Shinya Kitaoka |
120a6e |
for (f = 0; f != fCount; ++f) // edge.
|
|
Shinya Kitaoka |
120a6e |
otherV[f] = otherFaceVertex(ed.face(f), e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Remove e
|
|
Shinya Kitaoka |
120a6e |
this->removeEdge(e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Add the new edges
|
|
Shinya Kitaoka |
120a6e |
this->addEdge(E(v1, vIdx));
|
|
Shinya Kitaoka |
120a6e |
this->addEdge(E(vIdx, v2));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Add the new faces
|
|
Shinya Kitaoka |
120a6e |
for (f = 0; f != fCount; ++f)
|
|
Shinya Kitaoka |
120a6e |
addFace(v1, vIdx, otherV[f]), addFace(vIdx, v2, otherV[f]);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return vIdx;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace tcg
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
#endif // TCG_MESH_HPP
|