📄 wmlmtmesh.cpp
字号:
{
MTTriangle& rkA = m_akTriangle[iA];
rkA.ReplaceAdjacent(iTOld,iTNew);
}
}
pkT = m_kTMap.find(MTITriangle(rkV0.GetLabel(),rkV1.GetLabel(),
rkV2.GetLabel()));
assert( pkT != m_kTMap.end() );
pkT->second = iTNew;
}
}
//----------------------------------------------------------------------------
void MTMesh::AttachTriangleToEdge (int iT, MTTriangle& rkT, int i, int iE,
MTEdge& rkE)
{
if ( rkE.Triangle(0) == -1 )
{
rkE.Triangle(0) = iT;
}
else
{
int iTAdj = rkE.Triangle(0);
MTTriangle& rkTAdj = m_akTriangle[iTAdj];
rkT.Adjacent(i) = iTAdj;
for (int j = 0; j < 3; j++)
{
if ( rkTAdj.Edge(j) == iE )
{
rkTAdj.Adjacent(j) = iT;
break;
}
}
if ( rkE.Triangle(1) == -1 )
{
rkE.Triangle(1) = iT;
}
else
{
// mesh is not manifold
assert( false );
}
}
rkT.Edge(i) = iE;
}
//----------------------------------------------------------------------------
void MTMesh::DetachTriangleFromEdge (int iT, MTTriangle& rkT, int i, int iE,
MTEdge& rkE)
{
// This function leaves T only partially complete. The edge E is no
// longer referenced by T, even though the vertices of T reference the
// end points of E. If T has an adjacent triangle A that shares E, then
// A is a complete triangle.
if ( rkE.Triangle(0) == iT )
{
int iTAdj = rkE.Triangle(1);
if ( iTAdj != -1 )
{
// T and TAdj share E, update adjacency information for both
MTTriangle& rkTAdj = m_akTriangle[iTAdj];
for (int j = 0; j < 3; j++)
{
if ( rkTAdj.Edge(j) == iE )
{
rkTAdj.Adjacent(j) = -1;
break;
}
}
}
rkE.Triangle(0) = iTAdj;
}
else if ( rkE.Triangle(1) == iT )
{
// T and TAdj share E, update adjacency information for both
MTTriangle& rkTAdj = m_akTriangle[rkE.Triangle(0)];
for (int j = 0; j < 3; j++)
{
if ( rkTAdj.Edge(j) == iE )
{
rkTAdj.Adjacent(j) = -1;
break;
}
}
}
else
{
// Should not get here. The specified edge must share the input
// triangle.
assert( false );
}
rkE.Triangle(1) = -1;
rkT.Edge(i) = -1;
rkT.Adjacent(i) = -1;
}
//----------------------------------------------------------------------------
bool MTMesh::SubdivideCentroid (int iLabel0, int iLabel1, int iLabel2,
int& riNextLabel)
{
int iT = T(iLabel0,iLabel1,iLabel2);
if ( iT == -1 )
return false;
if ( m_kVMap.find(MTIVertex(riNextLabel)) != m_kVMap.end() )
{
// vertex already exists with this label
return false;
}
// subdivide the triangle
Remove(iLabel0,iLabel1,iLabel2);
Insert(iLabel0,iLabel1,riNextLabel);
Insert(iLabel1,iLabel2,riNextLabel);
Insert(iLabel2,iLabel0,riNextLabel);
riNextLabel++;
return true;
}
//----------------------------------------------------------------------------
bool MTMesh::SubdivideCentroidAll (int& riNextLabel)
{
// verify that the next-label range is valid
int iT, iTMax = m_akTriangle.GetQuantity();
int iTempLabel = riNextLabel;
for (iT = 0; iT < iTMax; iT++, iTempLabel++)
{
if ( m_kVMap.find(MTIVertex(iTempLabel)) != m_kVMap.end() )
{
// vertex already exists with this label
return false;
}
}
// Care must be taken when processing the triangles iteratively. The
// side of effect of removing the first triangle is that the last triangle
// in the array is moved into the vacated position. The first problem is
// that the moved triangle will be skipped in the iteration. The second
// problem is that the insertions cause the triangle array to grow. To
// avoid skipping the moved triangle, a different algorithm than the one
// in SubdivideCentroid(int,int,int,int&) is used. The triangle to be
// removed is detached from two edges. Two of the subtriangles are added
// to the mesh. The third subtriangle is calculated in the already
// existing memory that stored the original triangle. To avoid the
// infinite recursion induced by a growing array, the original size of
// the triangle array is stored int iTMax. This guarantees that only the
// original triangles are subdivided and that newly added triangles are
// not.
for (iT = 0; iT < iTMax; iT++, riNextLabel++)
{
// the triangle to subdivide
MTTriangle& rkT = m_akTriangle[iT];
int iLabel0 = GetVLabel(rkT.Vertex(0));
int iLabel1 = GetVLabel(rkT.Vertex(1));
int iLabel2 = GetVLabel(rkT.Vertex(2));
// detach the triangle from two edges
int iE1 = rkT.Edge(1), iE2 = rkT.Edge(2);
MTEdge& rkE1 = m_akEdge[iE1];
MTEdge& rkE2 = m_akEdge[iE2];
DetachTriangleFromEdge(iT,rkT,1,iE1,rkE1);
DetachTriangleFromEdge(iT,rkT,2,iE2,rkE2);
// Insert the two subtriangles that share edges E1 and E2. A
// potential side effect is that the triangle array is reallocated
// to make room for the new triangles. This will invalidate the
// reference rkT from the code above, but the index iT into the array
// is still correct. A reallocation of the vertex array might also
// occur.
Insert(iLabel1,iLabel2,riNextLabel);
Insert(iLabel2,iLabel0,riNextLabel);
// stitch the third subtriangle to the other subtriangles.
MTTriangle& rkTN = m_akTriangle[iT];
int iSubE1 = E(iLabel1,riNextLabel);
int iSubE2 = E(iLabel0,riNextLabel);
MTEdge& rkSubE1 = m_akEdge[iSubE1];
MTEdge& rkSubE2 = m_akEdge[iSubE2];
AttachTriangleToEdge(iT,rkTN,1,iSubE1,rkSubE1);
AttachTriangleToEdge(iT,rkTN,2,iSubE2,rkSubE2);
}
return true;
}
//----------------------------------------------------------------------------
bool MTMesh::SubdivideEdge (int iLabel0, int iLabel1, int& riNextLabel)
{
int iE = E(iLabel0,iLabel1);
if ( iE == -1 )
return false;
if ( m_kVMap.find(MTIVertex(riNextLabel)) != m_kVMap.end() )
{
// vertex already exists with this label
return false;
}
// split the triangles sharing the edge
MTEdge& rkE = m_akEdge[iE];
int iT0 = rkE.Triangle(0), iT1 = rkE.Triangle(1);
int iT0L0, iT0L1, iT0L2, iT1L0, iT1L1, iT1L2;
int iT0E0, iT0E1, iT1E0, iT1E1;
if ( iT0 >= 0 && iT1 == -1 )
{
// edge shared by only T0
MTTriangle& rkT0 = m_akTriangle[iT0];
iT0L0 = GetVLabel(rkT0.Vertex(0));
iT0L1 = GetVLabel(rkT0.Vertex(1));
iT0L2 = GetVLabel(rkT0.Vertex(2));
iT0E0 = rkT0.Edge(0);
iT0E1 = rkT0.Edge(1);
Remove(iT0L0,iT0L1,iT0L2);
if ( iT0E0 == iE )
{
Insert(iT0L0,riNextLabel,iT0L2);
Insert(riNextLabel,iT0L1,iT0L2);
}
else if ( iT0E1 == iE )
{
Insert(iT0L1,riNextLabel,iT0L0);
Insert(riNextLabel,iT0L2,iT0L0);
}
else
{
Insert(iT0L2,riNextLabel,iT0L1);
Insert(riNextLabel,iT0L0,iT0L1);
}
}
else if ( iT1 >= 0 && iT0 == -1 )
{
// Edge shared by only T1. The Remove(int,int,int) call is not
// factored outside the conditional statements to avoid potential
// reallocation side effects that would invalidate the reference rkT1.
MTTriangle& rkT1 = m_akTriangle[iT1];
iT1L0 = GetVLabel(rkT1.Vertex(0));
iT1L1 = GetVLabel(rkT1.Vertex(1));
iT1L2 = GetVLabel(rkT1.Vertex(2));
iT1E0 = rkT1.Edge(0);
iT1E1 = rkT1.Edge(1);
Remove(iT1L0,iT1L1,iT1L2);
if ( iT1E0 == iE )
{
Insert(iT1L0,riNextLabel,iT1L2);
Insert(riNextLabel,iT1L1,iT1L2);
}
else if ( iT1E1 == iE )
{
Insert(iT1L1,riNextLabel,iT1L0);
Insert(riNextLabel,iT1L2,iT1L0);
}
else
{
Insert(iT1L2,riNextLabel,iT1L1);
Insert(riNextLabel,iT1L0,iT1L1);
}
}
else
{
assert( iT0 >= 0 && iT1 >= 0 );
// Edge shared by both T0 and T1. The Remove(int,int,int) call is not
// factored outside the conditional statements to avoid potential
// reallocation side effects that would invalidate the references
// rkT0 and rkT1.
MTTriangle& rkT0 = m_akTriangle[iT0];
iT0L0 = GetVLabel(rkT0.Vertex(0));
iT0L1 = GetVLabel(rkT0.Vertex(1));
iT0L2 = GetVLabel(rkT0.Vertex(2));
iT0E0 = rkT0.Edge(0);
iT0E1 = rkT0.Edge(1);
MTTriangle& rkT1 = m_akTriangle[iT1];
iT1L0 = GetVLabel(rkT1.Vertex(0));
iT1L1 = GetVLabel(rkT1.Vertex(1));
iT1L2 = GetVLabel(rkT1.Vertex(2));
iT1E0 = rkT1.Edge(0);
iT1E1 = rkT1.Edge(1);
// Both triangles must be removed before the insertions to guarantee
// that the common edge is deleted from the mesh first.
Remove(iT0L0,iT0L1,iT0L2);
Remove(iT1L0,iT1L1,iT1L2);
if ( iT0E0 == iE )
{
Insert(iT0L0,riNextLabel,iT0L2);
Insert(riNextLabel,iT0L1,iT0L2);
}
else if ( iT0E1 == iE )
{
Insert(iT0L1,riNextLabel,iT0L0);
Insert(riNextLabel,iT0L2,iT0L0);
}
else
{
Insert(iT0L2,riNextLabel,iT0L1);
Insert(riNextLabel,iT0L0,iT0L1);
}
if ( iT1E0 == iE )
{
Insert(iT1L0,riNextLabel,iT1L2);
Insert(riNextLabel,iT1L1,iT1L2);
}
else if ( iT1E1 == iE )
{
Insert(iT1L1,riNextLabel,iT1L0);
Insert(riNextLabel,iT1L2,iT1L0);
}
else
{
Insert(iT1L2,riNextLabel,iT1L1);
Insert(riNextLabel,iT1L0,iT1L1);
}
}
riNextLabel++;
return true;
}
//----------------------------------------------------------------------------
void MTMesh::Print (ofstream& rkOStr) const
{
int i;
// print vertices
rkOStr << "vertex quantity = " << m_akVertex.GetQuantity() << endl;
for (int iV = 0; iV < m_akVertex.GetQuantity(); iV++)
{
const MTVertex& rkV = m_akVertex.Get(iV);
rkOStr << "vertex<" << iV << ">" << endl;
rkOStr << " l: " << rkV.GetLabel() << endl;
rkOStr << " e: ";
for (i = 0; i < rkV.GetEdgeQuantity(); i++)
rkOStr << rkV.GetEdge(i) << ' ';
rkOStr << endl;
rkOStr << " t: ";
for (i = 0; i < rkV.GetTriangleQuantity(); i++)
rkOStr << rkV.GetTriangle(i) << ' ';
rkOStr << endl;
}
rkOStr << endl;
// print edges
rkOStr << "edge quantity = " << m_akEdge.GetQuantity() << endl;
for (int iE = 0; iE < m_akEdge.GetQuantity(); iE++)
{
const MTEdge& rkE = m_akEdge.Get(iE);
rkOStr << "edge<" << iE << ">" << endl;
rkOStr << " v: "
<< rkE.GetVertex(0) << ' '
<< rkE.GetVertex(1) << endl;
rkOStr << " t: " << rkE.GetTriangle(0) << ' ' << rkE.GetTriangle(1)
<< endl;
}
rkOStr << endl;
// print triangles
rkOStr << "triangle quantity = " << m_akTriangle.GetQuantity() << endl;
for (int iT = 0; iT < m_akTriangle.GetQuantity(); iT++)
{
const MTTriangle& rkT = m_akTriangle.Get(iT);
rkOStr << "triangle<" << iT << ">" << endl;
rkOStr << " v: "
<< rkT.GetVertex(0) << ' '
<< rkT.GetVertex(1) << ' '
<< rkT.GetVertex(2) << endl;
rkOStr << " e: " << rkT.GetEdge(0) << ' ' << rkT.GetEdge(1)
<< ' ' << rkT.GetEdge(2) << endl;
rkOStr << " a: " << rkT.GetAdjacent(0) << ' ' << rkT.GetAdjacent(1)
<< ' ' << rkT.GetAdjacent(2) << endl;
}
rkOStr << endl;
}
//----------------------------------------------------------------------------
bool MTMesh::Print (const char* acFilename) const
{
ofstream kOStr(acFilename);
if ( !kOStr )
return false;
Print(kOStr);
return true;
}
//----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -