Files
create/src/Mod/Mesh/App/WildMagic4/Wm4VEManifoldMesh.cpp
2011-10-10 13:44:52 +00:00

299 lines
8.5 KiB
C++

// Wild Magic Source Code
// David Eberly
// http://www.geometrictools.com
// Copyright (c) 1998-2007
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or (at
// your option) any later version. The license is available for reading at
// either of the locations:
// http://www.gnu.org/copyleft/lgpl.html
// http://www.geometrictools.com/License/WildMagicLicense.pdf
// The license applies to versions 0 through 4 of Wild Magic.
//
// Version: 4.0.0 (2006/06/28)
#include "Wm4FoundationPCH.h"
#include "Wm4VEManifoldMesh.h"
using namespace Wm4;
//----------------------------------------------------------------------------
VEManifoldMesh::VEManifoldMesh (VCreator oVCreator, ECreator oECreator)
{
m_oVCreator = (oVCreator ? oVCreator : CreateVertex);
m_oECreator = (oECreator ? oECreator : CreateEdge);
}
//----------------------------------------------------------------------------
VEManifoldMesh::~VEManifoldMesh ()
{
VMap::iterator pkVIter;
for (pkVIter = m_kVMap.begin(); pkVIter != m_kVMap.end(); pkVIter++)
{
WM4_DELETE pkVIter->second;
}
EMap::iterator pkEIter;
for (pkEIter = m_kEMap.begin(); pkEIter != m_kEMap.end(); pkEIter++)
{
WM4_DELETE pkEIter->second;
}
}
//----------------------------------------------------------------------------
VEManifoldMesh::VPtr VEManifoldMesh::CreateVertex (int iV)
{
return WM4_NEW Vertex(iV);
}
//----------------------------------------------------------------------------
VEManifoldMesh::EPtr VEManifoldMesh::CreateEdge (int iV0, int iV1)
{
return WM4_NEW Edge(iV0,iV1);
}
//----------------------------------------------------------------------------
VEManifoldMesh::EPtr VEManifoldMesh::InsertEdge (int iV0, int iV1)
{
std::pair<int,int> kEKey(iV0,iV1);
EMapIterator pkEIter = m_kEMap.find(kEKey);
if (pkEIter != m_kEMap.end())
{
// edge already exists
return 0;
}
// add new edge
EPtr pkEdge = m_oECreator(iV0,iV1);
m_kEMap[kEKey] = pkEdge;
// add vertices to mesh
for (int i = 0; i < 2; i++)
{
int iV = pkEdge->V[i];
VPtr pkVertex;
VMapIterator pkVIter = m_kVMap.find(iV);
if (pkVIter == m_kVMap.end())
{
// first time vertex encountered
pkVertex = m_oVCreator(iV);
m_kVMap[iV] = pkVertex;
// update vertex
pkVertex->E[0] = pkEdge;
}
else
{
// second time vertex encountered
pkVertex = pkVIter->second;
assert(pkVertex);
// update vertex
if (pkVertex->E[1])
{
assert(false); // mesh must be manifold
return 0;
}
pkVertex->E[1] = pkEdge;
// update adjacent edge
EPtr pkAdjacent = pkVertex->E[0];
assert(pkAdjacent);
for (int j = 0; j < 2; j++)
{
if (pkAdjacent->V[j] == iV)
{
pkAdjacent->E[j] = pkEdge;
break;
}
}
// update edge
pkEdge->E[i] = pkAdjacent;
}
}
return pkEdge;
}
//----------------------------------------------------------------------------
bool VEManifoldMesh::RemoveEdge (int iV0, int iV1)
{
std::pair<int,int> kEKey(iV0,iV1);
EMapIterator pkEIter = m_kEMap.find(kEKey);
if (pkEIter == m_kEMap.end())
{
// edge does not exist
return false;
}
EPtr pkEdge = pkEIter->second;
for (int i = 0; i < 2; i++)
{
// inform vertices you are going away
VMapIterator pkVIter = m_kVMap.find(pkEdge->V[i]);
assert(pkVIter != m_kVMap.end());
Vertex* pkVertex = pkVIter->second;
assert(pkVertex);
if (pkVertex->E[0] == pkEdge)
{
// one-edge vertices always have pointer in slot zero
pkVertex->E[0] = pkVertex->E[1];
pkVertex->E[1] = 0;
}
else if (pkVertex->E[1] == pkEdge)
{
pkVertex->E[1] = 0;
}
else
{
assert(false);
return false;
}
// remove vertex if you had the last reference to it
if (!pkVertex->E[0] && !pkVertex->E[1])
{
m_kVMap.erase(pkVertex->V);
WM4_DELETE pkVertex;
}
// inform adjacent edges you are going away
EPtr pkAdjacent = pkEdge->E[i];
if (pkAdjacent)
{
for (int j = 0; j < 2; j++)
{
if (pkAdjacent->E[j] == pkEdge)
{
pkAdjacent->E[j] = 0;
break;
}
}
}
}
m_kEMap.erase(kEKey);
WM4_DELETE pkEdge;
return true;
}
//----------------------------------------------------------------------------
bool VEManifoldMesh::IsClosed () const
{
VMapCIterator pkVIter;
for (pkVIter = m_kVMap.begin(); pkVIter != m_kVMap.end(); pkVIter++)
{
const Vertex* pkVertex = pkVIter->second;
if (!pkVertex->E[0] || !pkVertex->E[1])
{
return false;
}
}
return true;
}
//----------------------------------------------------------------------------
void VEManifoldMesh::Print (const char* acFilename)
{
std::ofstream kOStr(acFilename);
if (!kOStr)
{
return;
}
// assign unique indices to the edges
std::map<EPtr,int> kEIndex;
kEIndex[0] = 0;
int i = 1;
EMapIterator pkEIter;
for (pkEIter = m_kEMap.begin(); pkEIter != m_kEMap.end(); pkEIter++)
{
if (pkEIter->second)
{
kEIndex[pkEIter->second] = i++;
}
}
// print vertices
kOStr << "vertex quantity = " << (int)m_kVMap.size() << std::endl;
VMapIterator pkVIter;
for (pkVIter = m_kVMap.begin(); pkVIter != m_kVMap.end(); pkVIter++)
{
const Vertex& rkVertex = *pkVIter->second;
kOStr << 'v' << rkVertex.V << " <";
if (rkVertex.E[0])
{
kOStr << 'e' << kEIndex[rkVertex.E[0]];
}
else
{
kOStr << '*';
}
kOStr << ',';
if (rkVertex.E[1])
{
kOStr << 'e' << kEIndex[rkVertex.E[1]];
}
else
{
kOStr << '*';
}
kOStr << '>' << std::endl;
}
// print edges
kOStr << "edge quantity = " << (int)m_kEMap.size() << std::endl;
for (pkEIter = m_kEMap.begin(); pkEIter != m_kEMap.end(); pkEIter++)
{
const Edge& rkEdge = *pkEIter->second;
kOStr << 'e' << kEIndex[pkEIter->second] << " <"
<< 'v' << rkEdge.V[0] << ",v" << rkEdge.V[1] << "; ";
if (rkEdge.E[0])
{
kOStr << 'e' << kEIndex[rkEdge.E[0]];
}
else
{
kOStr << '*';
}
kOStr << ',';
if (rkEdge.E[1])
{
kOStr << 'e' << kEIndex[rkEdge.E[1]];
}
else
{
kOStr << '*';
}
kOStr << '>' << std::endl;
}
kOStr << std::endl;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// VEManifoldMesh::Vertex
//----------------------------------------------------------------------------
VEManifoldMesh::Vertex::Vertex (int iV)
{
V = iV;
E[0] = 0;
E[1] = 0;
}
//----------------------------------------------------------------------------
VEManifoldMesh::Vertex::~Vertex ()
{
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// VEManifoldMesh::Edge
//----------------------------------------------------------------------------
VEManifoldMesh::Edge::Edge (int iV0, int iV1)
{
V[0] = iV0;
V[1] = iV1;
E[0] = 0;
E[1] = 0;
}
//----------------------------------------------------------------------------
VEManifoldMesh::Edge::~Edge ()
{
}
//----------------------------------------------------------------------------