Files
envi-code/SourceCode/Code2026/tg_shs/shs_geLib/TArcWallUnit.cpp
T
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

453 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//-----------------------------------------------------------------------------+
// 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);
}