📄 wmlmtmesh.cpp
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// http://www.wild-magic.com
// Copyright (c) 2003. All Rights Reserved
//
// The Wild Magic Library (WML) source code is supplied under the terms of
// the license agreement http://www.magic-software.com/License/WildMagic.pdf
// and may not be copied or disclosed except in accordance with the terms of
// that agreement.
#include "WmlMTMesh.h"
#include <fstream>
using namespace Wml;
using namespace std;
//----------------------------------------------------------------------------
MTMesh::MTMesh (int iVQuantity, int iEQuantity, int iTQuantity)
:
m_akVertex(iVQuantity),
m_akEdge(iEQuantity),
m_akTriangle(iTQuantity)
{
m_iInitialELabel = -1;
m_iInitialTLabel = -1;
}
//----------------------------------------------------------------------------
MTMesh::MTMesh (const MTMesh& rkMesh)
{
*this = rkMesh;
}
//----------------------------------------------------------------------------
MTMesh::~MTMesh ()
{
}
//----------------------------------------------------------------------------
void MTMesh::Reset (int iVQuantity, int iEQuantity, int iTQuantity)
{
m_akVertex.Reset(iVQuantity);
m_akEdge.Reset(iEQuantity);
m_akTriangle.Reset(iTQuantity);
m_kVMap.clear();
m_kEMap.clear();
m_kTMap.clear();
}
//----------------------------------------------------------------------------
MTMesh& MTMesh::operator= (const MTMesh& rkMesh)
{
m_akVertex = rkMesh.m_akVertex;
m_akEdge = rkMesh.m_akEdge;
m_akTriangle = rkMesh.m_akTriangle;
m_kVMap = rkMesh.m_kVMap;
m_kEMap = rkMesh.m_kEMap;
m_kTMap = rkMesh.m_kTMap;
m_iInitialELabel = rkMesh.m_iInitialELabel;
m_iInitialTLabel = rkMesh.m_iInitialTLabel;
return *this;
}
//----------------------------------------------------------------------------
bool MTMesh::Insert (int iLabel0, int iLabel1, int iLabel2)
{
// insert triangle
int iT = InsertTriangle(iLabel0,iLabel1,iLabel2);
if ( iT == -1 )
{
// triangle already exists
return true;
}
// insert vertices
int iV0 = InsertVertex(iLabel0);
int iV1 = InsertVertex(iLabel1);
int iV2 = InsertVertex(iLabel2);
// insert edges
int iE0 = InsertEdge(iLabel0,iLabel1);
int iE1 = InsertEdge(iLabel1,iLabel2);
int iE2 = InsertEdge(iLabel2,iLabel0);
// set the connections between components
MTTriangle& rkT = m_akTriangle[iT];
MTVertex& rkV0 = m_akVertex[iV0];
MTVertex& rkV1 = m_akVertex[iV1];
MTVertex& rkV2 = m_akVertex[iV2];
MTEdge& rkE0 = m_akEdge[iE0];
MTEdge& rkE1 = m_akEdge[iE1];
MTEdge& rkE2 = m_akEdge[iE2];
// attach edges to vertices
rkV0.InsertEdge(iE2);
rkV0.InsertEdge(iE0);
rkV1.InsertEdge(iE0);
rkV1.InsertEdge(iE1);
rkV2.InsertEdge(iE1);
rkV2.InsertEdge(iE2);
rkE0.Vertex(0) = iV0;
rkE0.Vertex(1) = iV1;
rkE1.Vertex(0) = iV1;
rkE1.Vertex(1) = iV2;
rkE2.Vertex(0) = iV2;
rkE2.Vertex(1) = iV0;
// attach triangles to vertices
rkV0.InsertTriangle(iT);
rkV1.InsertTriangle(iT);
rkV2.InsertTriangle(iT);
rkT.Vertex(0) = iV0;
rkT.Vertex(1) = iV1;
rkT.Vertex(2) = iV2;
// attach triangle to edges
AttachTriangleToEdge(iT,rkT,0,iE0,rkE0);
AttachTriangleToEdge(iT,rkT,1,iE1,rkE1);
AttachTriangleToEdge(iT,rkT,2,iE2,rkE2);
return true;
}
//----------------------------------------------------------------------------
int MTMesh::InsertVertex (int iLabel)
{
MTIVertex kV(iLabel);
int iV;
VIter pkV = m_kVMap.find(kV);
if ( pkV != m_kVMap.end() )
{
// vertex already exists
iV = pkV->second;
}
else
{
// create new vertex
iV = m_akVertex.Append(MTVertex(iLabel));
m_kVMap.insert(make_pair(kV,iV));
}
return iV;
}
//----------------------------------------------------------------------------
int MTMesh::InsertEdge (int iLabel0, int iLabel1)
{
MTIEdge kE(iLabel0,iLabel1);
int iE;
EIter pkE = m_kEMap.find(kE);
if ( pkE != m_kEMap.end() )
{
// edge already exists
iE = pkE->second;
}
else
{
// create new edge
iE = m_akEdge.Append(MTEdge(m_iInitialELabel));
m_kEMap.insert(make_pair(kE,iE));
}
return iE;
}
//----------------------------------------------------------------------------
int MTMesh::InsertTriangle (int iLabel0, int iLabel1, int iLabel2)
{
MTITriangle kT(iLabel0,iLabel1,iLabel2);
int iT;
TIter pkT = m_kTMap.find(kT);
if ( pkT != m_kTMap.end() )
{
// triangle already exists
iT = -1;
}
else
{
// create new triangle
iT = m_akTriangle.Append(MTTriangle(m_iInitialTLabel));
m_kTMap.insert(make_pair(kT,iT));
}
return iT;
}
//----------------------------------------------------------------------------
bool MTMesh::Remove (int iLabel0, int iLabel1, int iLabel2)
{
MTITriangle kT(iLabel0,iLabel1,iLabel2);
TIter pkT = m_kTMap.find(kT);
if ( pkT == m_kTMap.end() )
{
// triangle does not exist
return false;
}
int iT = pkT->second;
MTTriangle& rkT = m_akTriangle[iT];
// detach triangle from edges
int iE0 = rkT.Edge(0), iE1 = rkT.Edge(1), iE2 = rkT.Edge(2);
MTEdge& rkE0 = m_akEdge[iE0];
MTEdge& rkE1 = m_akEdge[iE1];
MTEdge& rkE2 = m_akEdge[iE2];
DetachTriangleFromEdge(iT,rkT,0,iE0,rkE0);
DetachTriangleFromEdge(iT,rkT,1,iE1,rkE1);
DetachTriangleFromEdge(iT,rkT,2,iE2,rkE2);
// detach triangles from vertices
int iV0 = rkT.Vertex(0);
MTVertex& rkV0 = m_akVertex[iV0];
rkV0.RemoveTriangle(iT);
int iV1 = rkT.Vertex(1);
MTVertex& rkV1 = m_akVertex[iV1];
rkV1.RemoveTriangle(iT);
int iV2 = rkT.Vertex(2);
MTVertex& rkV2 = m_akVertex[iV2];
rkV2.RemoveTriangle(iT);
// detach edges from vertices (only if last edge to reference vertex)
bool bE0Destroy = (rkE0.Triangle(0) == -1);
if ( bE0Destroy )
{
rkV0.RemoveEdge(iE0);
rkV1.RemoveEdge(iE0);
}
bool bE1Destroy = (rkE1.Triangle(0) == -1);
if ( bE1Destroy )
{
rkV1.RemoveEdge(iE1);
rkV2.RemoveEdge(iE1);
}
bool bE2Destroy = (rkE2.Triangle(0) == -1);
if ( bE2Destroy )
{
rkV0.RemoveEdge(iE2);
rkV2.RemoveEdge(iE2);
}
// Removal of components from the sets and maps starts here. Be careful
// using set indices, component references, and map iterators since
// deletion has side effects. Deletion of a component might cause another
// component to be moved within the corresponding set or map.
bool bV0Destroy = (rkV0.GetEdgeQuantity() == 0);
bool bV1Destroy = (rkV1.GetEdgeQuantity() == 0);
bool bV2Destroy = (rkV2.GetEdgeQuantity() == 0);
// remove edges if no longer used
if ( bE0Destroy )
RemoveEdge(iLabel0,iLabel1);
if ( bE1Destroy )
RemoveEdge(iLabel1,iLabel2);
if ( bE2Destroy )
RemoveEdge(iLabel2,iLabel0);
// remove vertices if no longer used
if ( bV0Destroy )
RemoveVertex(iLabel0);
if ( bV1Destroy )
RemoveVertex(iLabel1);
if ( bV2Destroy )
RemoveVertex(iLabel2);
// remove triangle (definitely no longer used)
RemoveTriangle(iLabel0,iLabel1,iLabel2);
return true;
}
//----------------------------------------------------------------------------
void MTMesh::RemoveVertex (int iLabel)
{
// get array location of vertex
VIter pkV = m_kVMap.find(MTIVertex(iLabel));
assert( pkV != m_kVMap.end() );
int iV = pkV->second;
// remove the vertex from the array and from the map
int iVOld, iVNew;
m_akVertex.RemoveAt(iV,&iVOld,&iVNew);
m_kVMap.erase(pkV);
if ( iVNew >= 0 )
{
// The vertex at the end of the array moved into the slot vacated by
// the deleted vertex. Update all the components sharing the moved
// vertex.
MTVertex& rkV = m_akVertex[iVNew];
int i;
// inform edges about location change
for (i = 0; i < rkV.GetEdgeQuantity(); i++)
{
MTEdge& rkE = m_akEdge[rkV.GetEdge(i)];
rkE.ReplaceVertex(iVOld,iVNew);
}
// inform triangles about location change
for (i = 0; i < rkV.GetTriangleQuantity(); i++)
{
MTTriangle& rkT = m_akTriangle[rkV.GetTriangle(i)];
rkT.ReplaceVertex(iVOld,iVNew);
}
pkV = m_kVMap.find(MTIVertex(rkV.GetLabel()));
assert( pkV != m_kVMap.end() );
pkV->second = iVNew;
}
}
//----------------------------------------------------------------------------
void MTMesh::RemoveEdge (int iLabel0, int iLabel1)
{
// get array location of edge
EIter pkE = m_kEMap.find(MTIEdge(iLabel0,iLabel1));
assert( pkE != m_kEMap.end() );
int iE = pkE->second;
// remove the edge from the array and from the map
int iEOld, iENew;
m_akEdge.RemoveAt(iE,&iEOld,&iENew);
m_kEMap.erase(pkE);
if ( iENew >= 0 )
{
// The edge at the end of the array moved into the slot vacated by
// the deleted edge. Update all the components sharing the moved
// edge.
MTEdge& rkE = m_akEdge[iENew];
// inform vertices about location change
MTVertex& rkV0 = m_akVertex[rkE.Vertex(0)];
MTVertex& rkV1 = m_akVertex[rkE.Vertex(1)];
rkV0.ReplaceEdge(iEOld,iENew);
rkV1.ReplaceEdge(iEOld,iENew);
// inform triangles about location change
for (int i = 0; i < 2; i++)
{
int iT = rkE.GetTriangle(i);
if ( iT != -1 )
{
MTTriangle& rkT = m_akTriangle[iT];
rkT.ReplaceEdge(iEOld,iENew);
}
}
pkE = m_kEMap.find(MTIEdge(rkV0.GetLabel(),rkV1.GetLabel()));
assert( pkE != m_kEMap.end() );
pkE->second = iENew;
}
}
//----------------------------------------------------------------------------
void MTMesh::RemoveTriangle (int iLabel0, int iLabel1, int iLabel2)
{
// get array location of triangle
TIter pkT = m_kTMap.find(MTITriangle(iLabel0,iLabel1,iLabel2));
assert( pkT != m_kTMap.end() );
int iT = pkT->second;
// remove the triangle from the array and from the map
int iTOld, iTNew;
m_akTriangle.RemoveAt(iT,&iTOld,&iTNew);
m_kTMap.erase(pkT);
if ( iTNew >= 0 )
{
// The triangle at the end of the array moved into the slot vacated by
// the deleted triangle. Update all the components sharing the moved
// triangle.
MTTriangle& rkT = m_akTriangle[iTNew];
// inform vertices about location change
MTVertex& rkV0 = m_akVertex[rkT.Vertex(0)];
MTVertex& rkV1 = m_akVertex[rkT.Vertex(1)];
MTVertex& rkV2 = m_akVertex[rkT.Vertex(2)];
rkV0.ReplaceTriangle(iTOld,iTNew);
rkV1.ReplaceTriangle(iTOld,iTNew);
rkV2.ReplaceTriangle(iTOld,iTNew);
// inform edges about location change
int i;
for (i = 0; i < 3; i++)
{
MTEdge& rkE = m_akEdge[rkT.GetEdge(i)];
rkE.ReplaceTriangle(iTOld,iTNew);
}
// inform adjacents about location change
for (i = 0; i < 3; i++)
{
int iA = rkT.GetAdjacent(i);
if ( iA != -1 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -