Files
envi-code/SourceCode/Code2026/tg_shs/shs_geLib/TArcWallUnit.cpp
T

453 lines
12 KiB
C++
Raw Normal View History

2026-09-28 15:28:50 +08:00
//-----------------------------------------------------------------------------+
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
// = FileName : TArcWallUnit.cpp
// = Version : ver2.0
// = Author : xlc
// = CreateDate : 2002-09-09
// = Description: 类的定义
// = Maintainers:
//
//-----------------------------------------------------------------------------+
#include "StdAfx.h"
#include "TArcWallUnit.h"
#include "TGGeTrianglePface.h"
#include "TchPrivateGlobalFunc.h"
static int CompareDouble(double x1, double x2)
{
if (fabs(x1 - x2) < _DIST_SNAP)
{
return 0;
}
if (x1 < x2)
{
return -1;
}
return 1;
}
static int ComparePointByX(const TADSGePoint3d *p1, const TADSGePoint3d *p2)
{
if (fabs(p1->x - p2->x) < _DIST_SNAP)
{
return 0;
}
if (p1->x < p2->x)
{
return -1;
}
return 1;
}
TArcWallUnit::TArcWallUnit()
: lstHoles(FALSE),xWallBeg(0),xHoleBeg(0),xHoleEnd(0),nRadius(0)
{
}
TArcWallUnit::TArcWallUnit(double rad, double wBeg, double hBeg, double hEnd)
: lstHoles(FALSE), nRadius(rad), xWallBeg(wBeg), xHoleBeg(hBeg), xHoleEnd(hEnd)
{
}
TArcWallUnit::~TArcWallUnit()
{
}
// 对一系列3dface进行镶嵌
// 对lstFaces,根据xBeg开始,以nStep的步长进行num次镶嵌
// 结果存入lstSectFaces,lstFaces在镶嵌后扣除
void TArcWallUnit::Tessellate(double xBeg, double nStep, int num, TDPtrList<TGGe3DFace> &lstFaces, TDPtrList<TGGe3DFace> &lstSectFaces)
{
for(int n = 0; n < num; n++)
{
double xSect = xBeg + (1 + n) * nStep; //切割位置
int nFaceNum = lstFaces.Length();
for(int k = 0; k<nFaceNum; k++)
{
TGGe3DFace &face = *lstFaces[k];
if (face.GetFlag() & FLAG_TRIANGLE)
{
//3角形
int nFlag1 = CompareDouble(face.GetVertex(0).x, xSect);
int nFlag2 = CompareDouble(face.GetVertex(1).x, xSect);
int nFlag3 = CompareDouble(face.GetVertex(2).x, xSect);
if (nFlag3 <= 0)
{
lstSectFaces.Append(new TGGe3DFace(face));
lstFaces.Remove(k);
k--;
nFaceNum--;
}
else if (nFlag1 >= 0)
{
//无切割发生
}
else
{
//发生切割
double x1 = face.GetVertex(0).x, x2 = face.GetVertex(1).x, x3 = face.GetVertex(2).x;
double y1 = face.GetVertex(0).y, y2 = face.GetVertex(1).y, y3 = face.GetVertex(2).y;
double x = xSect;
TGGe3DFace *newFace = new TGGe3DFace(face);
int nFlag = face.GetFlag();
int nFlagNew = newFace->GetFlag();
if (nFlag2 > 0)
{ //切割第一点, 三角形 + 四边形
nFlagNew |= 0x02 + 0x08;
double y = ((x-x1) * y2 + y1 * (x2-x)) / (x2-x1);
newFace->SetVertex(1, TADSGePoint3d(x, y));
y = ((x-x1) * y3 + y1 * (x3-x)) / (x3-x1);
newFace->SetVertex(2, TADSGePoint3d(x, y));
face.SetVertex(0, newFace->GetVertex(1));
face.SetVertex(3, newFace->GetVertex(2));
nFlag |= 0x08;
nFlag &= ~FLAG_TRIANGLE;
}
else if (nFlag2 == 0)
{ // 三角形+三角形
nFlagNew |= 0x02 + 0x08;
double y = ((x - x1) * y3 + y1 * (x3 - x)) / (x3 - x1);
newFace->SetVertex(2, TADSGePoint3d(x, y));
nFlag |= 0x01 + 0x08;
face.SetVertex(0, TADSGePoint3d(x, y));
face.SetVertex(3, TADSGePoint3d(x, y));
}
else
{ // 四边形 + 三角形
double y = ((x - x3) * y2 + y3 * (x2 - x)) / (x2 - x3);
nFlagNew |= 0x04;
newFace->SetVertex(2, TADSGePoint3d(x,y));
y = ((x - x1) * y3 + y1 * (x3 - x)) / (x3 - x1);
newFace->SetVertex(3, TADSGePoint3d(x,y));
if (nFlag & 0x04)
{
nFlagNew |= 0x08;
}
else
{
nFlagNew &= ~0x08;
}
face.SetVertex(0, newFace->GetVertex(3));
face.SetVertex(3, newFace->GetVertex(3));
face.SetVertex(1, newFace->GetVertex(2));
nFlag |= 0x01 + 0x08;
}
face.SetFlag(nFlag);
newFace->SetFlag(nFlagNew);
lstSectFaces.Append(newFace);
}
}
else
{
//4边形,已经切割过
int nFlag2 = CompareDouble(face.GetVertex(1).x, xSect);
int nFlag3 = CompareDouble(face.GetVertex(2).x, xSect);
// 分4种情况
if (nFlag3 <= 0)
{ //整个输出
lstSectFaces.Append(new TGGe3DFace(face));
lstFaces.Remove(k);
k--;
nFaceNum--;
}
else
{
double x1 = face.GetVertex(0).x,
x2 = face.GetVertex(1).x,
x3 = face.GetVertex(2).x,
x4 = face.GetVertex(3).x;
double y1 = face.GetVertex(0).y,
y2 = face.GetVertex(1).y,
y3 = face.GetVertex(2).y,
y4 = face.GetVertex(3).y;
double x = xSect;
TGGe3DFace *newFace = new TGGe3DFace(face);
int nFlag = face.GetFlag();
int nFlagNew = newFace->GetFlag();
if (nFlag2 > 0)
{ // 2个四边形
nFlagNew |= 0x02;
double y = ((x - x1) * y2 + y1 * (x2 - x)) / (x2 - x1);
newFace->SetVertex(1, TADSGePoint3d(x, y));
y = ((x - x3) * y4 + y3 * (x4 - x)) / (x4 - x3);
newFace->SetVertex(2, TADSGePoint3d(x, y));
face.SetVertex(0, newFace->GetVertex(1));
face.SetVertex(3, newFace->GetVertex(2));
}
else if (nFlag2 == 0)
{ // 4边形+三角形
nFlagNew |= 0x02;
double y = ((x - x3) * y4 + y3 * (x4 - x)) / (x4 - x3);
newFace->SetVertex(2, TADSGePoint3d(x, y));
face.SetVertex(0, TADSGePoint3d(x, y));
face.SetVertex(3, TADSGePoint3d(x, y));
nFlag |= 0x01 + 0x08;
nFlag |= FLAG_TRIANGLE;
}
else if (nFlag2 < 0)
{ // 5边形+三角形
double y = ((x - x3) * y2 + y3 * (x2 - x)) / (x2 - x3);
double yy = ((x - x3) * y4 + y3 * (x4 - x)) / (x4 - x3);
newFace->SetVertex(2, TADSGePoint3d(x, yy));
nFlagNew |= 0x02;
TGGe3DFace *pp = new TGGe3DFace(face);
pp->SetVertex(0, TADSGePoint3d(x, yy));
pp->SetVertex(3, TADSGePoint3d(x, yy));
pp->SetVertex(2, TADSGePoint3d(x, y));
int nFlagP = pp->GetFlag();
nFlagP |= 0x01 + 0x04 + 0x08;
pp->SetFlag(nFlagP);
lstSectFaces.Append(pp);
face.SetVertex(0, TADSGePoint3d(x, yy));
face.SetVertex(3, TADSGePoint3d(x, yy));
nFlag |= 0x01;
nFlag |= FLAG_TRIANGLE;
face.SetVertex(1, TADSGePoint3d(x, y));
}
face.SetFlag(nFlag);
newFace->SetFlag(nFlagNew);
lstSectFaces.Append(newFace);
}
} // end if Triangle
} // end for k
} // end for n
}
void TArcWallUnit::Tessellate(TDPtrList<TGGe3DFace> &lstSectFaces, double nHeight,
BOOL bHasTop, BOOL bHasBot, BOOL bHasLeft, BOOL bHasRight)
{
double xMin = xHoleBeg, xMax = xHoleEnd;
double xBeg = xWallBeg;
int nCirDiv = GetCirDivNum(nRadius, _AS_SYS_UNIT(g_nCirDeviation)); //整圆的分段数目
//1. 输出xBeg~xMin的一段墙(四边形)
if (xMin-xBeg > _DIST_SNAP)
{
int nDivNum = AS_INT((xMin - xBeg) / (2.0 * PI * nRadius) * nCirDiv);
nDivNum = max(1, nDivNum);
double nStep = (xMin - xBeg) / nDivNum;
Tessellate(lstSectFaces, xBeg, nStep, nDivNum, nHeight,
bHasTop, bHasBot, bHasLeft, (bHasRight && (xMax - xMin) < _DIST_SNAP));
}
if (xMax - xMin < _DIST_SNAP)
{
return;
}
//2. 输出xMin~xMax的一段墙(包含洞口)
TGGePolygonEx polyOut; //外轮廓-展开坐标系
polyOut.AppendNode(TADSGePoint3d(xMin,0), bHasBot);
polyOut.AppendNode(TADSGePoint3d(xMax, 0), bHasRight);
polyOut.AppendNode(TADSGePoint3d(xMax, nHeight), bHasTop);
polyOut.AppendNode(TADSGePoint3d(xMin, nHeight), (bHasLeft && fabs(xMin - xBeg) < _DIST_SNAP));
//在展开坐标系,分解为三角形
TDPtrList<TGGe3DFace> lstFaces;
AsTriangleFaces(polyOut, lstHoles, lstFaces);
// 根据x坐标排序顶点(可能导致顺时针顶点方向)
for(int i = 0; i < lstFaces.Length(); i++)
{
TGGe3DFace *pFace = lstFaces[i];
SortVertex(pFace);
}
//3. 在展开坐标系,用分弧精度切割三角形,形成三角形或4边形
int num = AS_INT((xMax - xMin) / (2.0 * PI * nRadius) * nCirDiv);
num = max(1, num);
double nStep = (xMax - xMin) / num;
Tessellate(xMin, nStep, num, lstFaces, lstSectFaces);
}
// 对xBeg开始,以步长nStep共nDivNum步,高度为nHeight,进行镶嵌,
// 结果存入lstSectFaces。bHasTop, bHasBot, bHasLeft, bHasRight,外围边的可见性
void TArcWallUnit::Tessellate(TDPtrList<TGGe3DFace> &lstSectFaces, double xBeg, double nStep, int nDivNum, double nHeight,
BOOL bHasTop, BOOL bHasBot, BOOL bHasLeft, BOOL bHasRight)
{
double nPrev = xBeg;
for (int n = 1; n <= nDivNum; n++)
{
double nNext = xBeg + n * nStep;
TGGe3DFace *pFace = new TGGe3DFace;
int nFlag = pFace->GetFlag();
// 底-右-顶-左
if (!bHasBot)
{
nFlag |= 0x01;
}
if (bHasRight && n == nDivNum)
{
;
}
else
{
nFlag |= 0x02;
}
if (!bHasTop)
{
nFlag |= 0x04;
}
if (bHasLeft && n == 1)
{
;
}
else
{
nFlag |= 0x08;
}
pFace->SetFlag(nFlag);
pFace->SetVertex(0, TADSGePoint3d(nPrev, 0.0));
pFace->SetVertex(1, TADSGePoint3d(nNext, 0.0));
pFace->SetVertex(2, TADSGePoint3d(nNext, nHeight));
pFace->SetVertex(3, TADSGePoint3d(nPrev, nHeight));
lstSectFaces.Append(pFace);
nPrev = nNext;
}
}
// 把平面(含洞口)的模型,化解为三角形
// z坐标全部为0
int TArcWallUnit::AsTriangleFaces(const TGGePolygonEx &polyOut, const TDPtrList<TGGePoly2D> &lstHoles, TDPtrList<TGGe3DFace> &lstFaces)
{
TGGeTrianglePface lstTris;
if (Triangulate(polyOut, lstHoles, lstTris))
{
int nFlag = 0;
for (int n = 0; n < lstTris.Length(); n++)
{
TGGeTriangle *triangle = lstTris[n];
ASSERT(triangle);
TGGe3DFace *pFace = new TGGe3DFace;
nFlag = triangle->m_nFlag;
pFace->SetVertex(0, triangle->vertex1);
pFace->SetVertex(1, triangle->vertex2);
pFace->SetVertex(2, triangle->vertex3);
pFace->SetVertex(3, triangle->vertex1);
nFlag |= FLAG_TRIANGLE;
pFace->SetFlag(nFlag);
lstFaces.Append(pFace);
}
return RTNORM;
}
return RTERROR;
}
// 把平面(含洞口)的模型,化解为三角形
// z坐标全部为0
int TArcWallUnit::AsTriangleFaces(const TGGePoly2D &polyOut, const TDPtrList<TGGePoly2D> &lstHoles, TDPtrList<TGGe3DFace> &lstFaces)
{
TGGePoly poly1;
((TGGePoly2D &)polyOut).MapToPolygon1(poly1, _AS_SYS_UNIT(g_nCirDeviation));
ASSERT(poly1.Length() > 2);
TGGePolygonEx polyEx1(poly1);
if (polyEx1.PathArea() > 0.0)
{
polyEx1.Reverse();
}
return AsTriangleFaces(polyEx1, lstHoles, lstFaces);
}
void TArcWallUnit::SortVertex(TGGe3DFace *pFace)
{
ASSERT(pFace);
TDPtrList<TADSGePoint3d> vertices;
BOOL bInvis1 = ((pFace->GetFlag() & 0x01) != 0);
BOOL bInvis2 = ((pFace->GetFlag() & 0x02) != 0);
BOOL bInvis3 = ((pFace->GetFlag() & 0x04) != 0);
vertices.Append(new TADSGePoint3d(pFace->GetVertex(0).x, pFace->GetVertex(0).y, bInvis1));
vertices.Append(new TADSGePoint3d(pFace->GetVertex(1).x, pFace->GetVertex(1).y, bInvis2));
vertices.Append(new TADSGePoint3d(pFace->GetVertex(2).x, pFace->GetVertex(2).y, bInvis3));
vertices.QuickSort(ComparePointByX);
TADSGePoint3d ver0 = *vertices[0], ver1 = *vertices[1], ver2 = *vertices[2];
TVector3D vtOld = pFace->GetNormal();
pFace->GetVertex(0).x = ver0.x;
pFace->GetVertex(0).y = ver0.y;
pFace->GetVertex(1).x = ver1.x;
pFace->GetVertex(1).y = ver1.y;
pFace->GetVertex(2).x = ver2.x;
pFace->GetVertex(2).y = ver2.y;
pFace->GetVertex(3) = pFace->GetVertex(0);
bInvis1 = (ver0.z > 1.0E-3);
bInvis2 = (ver1.z > 1.0E-3);
bInvis3 = (ver2.z > 1.0E-3);
TVector3D vtNew = pFace->GetNormal();
if ((vtNew & vtOld) < 0)
{
// 可见标记也要反转
BOOL b1 = bInvis1, b2 = bInvis2, b3 = bInvis3;
bInvis1 = b2;
bInvis2 = b3;
bInvis3 = b1;
}
int nFlag = pFace->GetFlag();
if (bInvis1)
{
nFlag |= 0x01;
}
else
{
nFlag &= ~0x01;
}
if (bInvis2)
{
nFlag |= 0x02;
}
else
{
nFlag &= ~0x02;
}
if (bInvis3)
{
nFlag |= 0x04;
}
else
{
nFlag &= ~0x04;
}
pFace->SetFlag(nFlag);
}