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