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

454 lines
11 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, SH Software Co. Ltd.
// = FileName : XArcWallUnit.cpp
// = Version : ver2.0
// = Author : zjq
// = CreateDate : 2002-09-09
// = Description: 类的定义
// = Maintainers:
//
//-----------------------------------------------------------------------------+
#include "StdAfx.h"
#include "XArcWallUnit.h"
#include "XTrianglePface.h"
#include "XPrivateGlobalFunc.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 XPoint *p1, const XPoint *p2)
{
if (fabs(p1->x - p2->x) < _DIST_SNAP)
{
return 0;
}
if (p1->x < p2->x)
{
return -1;
}
return 1;
}
XArcWallUnit::XArcWallUnit()
: lstHoles(FALSE),xWallBeg(0),xHoleBeg(0),xHoleEnd(0),nRadius(0)
{
}
XArcWallUnit::XArcWallUnit(double rad, double wBeg, double hBeg, double hEnd)
: lstHoles(FALSE), nRadius(rad), xWallBeg(wBeg), xHoleBeg(hBeg), xHoleEnd(hEnd)
{
}
XArcWallUnit::~XArcWallUnit()
{
}
// 对一系列3dface进行镶嵌
// 对lstFaces,根据xBeg开始,以nStep的步长进行num次镶嵌
// 结果存入lstSectFaces,lstFaces在镶嵌后扣除
void XArcWallUnit::Tessellate(double xBeg, double nStep, int num, DList<X3DFace> &lstFaces, DList<X3DFace> &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++)
{
X3DFace &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 X3DFace(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;
X3DFace *newFace = new X3DFace(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, XPoint(x, y));
y = ((x-x1) * y3 + y1 * (x3-x)) / (x3-x1);
newFace->SetVertex(2, XPoint(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, XPoint(x, y));
nFlag |= 0x01 + 0x08;
face.SetVertex(0, XPoint(x, y));
face.SetVertex(3, XPoint(x, y));
}
else
{ // 四边形 + 三角形
double y = ((x - x3) * y2 + y3 * (x2 - x)) / (x2 - x3);
nFlagNew |= 0x04;
newFace->SetVertex(2, XPoint(x,y));
y = ((x - x1) * y3 + y1 * (x3 - x)) / (x3 - x1);
newFace->SetVertex(3, XPoint(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 X3DFace(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;
X3DFace *newFace = new X3DFace(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, XPoint(x, y));
y = ((x - x3) * y4 + y3 * (x4 - x)) / (x4 - x3);
newFace->SetVertex(2, XPoint(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, XPoint(x, y));
face.SetVertex(0, XPoint(x, y));
face.SetVertex(3, XPoint(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, XPoint(x, yy));
nFlagNew |= 0x02;
X3DFace *pp = new X3DFace(face);
pp->SetVertex(0, XPoint(x, yy));
pp->SetVertex(3, XPoint(x, yy));
pp->SetVertex(2, XPoint(x, y));
int nFlagP = pp->GetFlag();
nFlagP |= 0x01 + 0x04 + 0x08;
pp->SetFlag(nFlagP);
lstSectFaces.Append(pp);
face.SetVertex(0, XPoint(x, yy));
face.SetVertex(3, XPoint(x, yy));
nFlag |= 0x01;
nFlag |= FLAG_TRIANGLE;
face.SetVertex(1, XPoint(x, y));
}
face.SetFlag(nFlag);
newFace->SetFlag(nFlagNew);
lstSectFaces.Append(newFace);
}
} // end if Triangle
} // end for k
} // end for n
}
void XArcWallUnit::Tessellate(DList<X3DFace> &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的一段墙(包含洞口)
XPolygonEx polyOut; //外轮廓-展开坐标系
polyOut.AppendNode(XPoint(xMin,0), bHasBot);
polyOut.AppendNode(XPoint(xMax, 0), bHasRight);
polyOut.AppendNode(XPoint(xMax, nHeight), bHasTop);
polyOut.AppendNode(XPoint(xMin, nHeight), (bHasLeft && fabs(xMin - xBeg) < _DIST_SNAP));
//在展开坐标系,分解为三角形
DList<X3DFace> lstFaces;
AsTriangleFaces(polyOut, lstHoles, lstFaces);
// 根据x坐标排序顶点(可能导致顺时针顶点方向)
for(int i = 0; i < lstFaces.Length(); i++)
{
X3DFace *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 XArcWallUnit::Tessellate(DList<X3DFace> &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;
X3DFace *pFace = new X3DFace;
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, XPoint(nPrev, 0.0));
pFace->SetVertex(1, XPoint(nNext, 0.0));
pFace->SetVertex(2, XPoint(nNext, nHeight));
pFace->SetVertex(3, XPoint(nPrev, nHeight));
lstSectFaces.Append(pFace);
nPrev = nNext;
}
}
// 把平面(含洞口)的模型,化解为三角形
// z坐标全部为0
int XArcWallUnit::AsTriangleFaces(const XPolygonEx &polyOut, const DList<XPoly2D> &lstHoles, DList<X3DFace> &lstFaces)
{
XTrianglePface lstTris;
if (Triangulate(polyOut, lstHoles, lstTris))
{
int nFlag = 0;
for (int n = 0; n < lstTris.Length(); n++)
{
XTriangle *triangle = lstTris[n];
ASSERT(triangle);
X3DFace *pFace = new X3DFace;
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 XArcWallUnit::AsTriangleFaces(const XPoly2D &polyOut, const DList<XPoly2D> &lstHoles, DList<X3DFace> &lstFaces)
{
XPoly poly1;
((XPoly2D &)polyOut).MapToPolygon1(poly1, _AS_SYS_UNIT(g_nCirDeviation));
ASSERT(poly1.Length() > 2);
XPolygonEx polyEx1(poly1);
if (polyEx1.PathArea() > 0.0)
{
polyEx1.Reverse();
}
return AsTriangleFaces(polyEx1, lstHoles, lstFaces);
}
void XArcWallUnit::SortVertex(X3DFace *pFace)
{
ASSERT(pFace);
DList<XPoint> vertices;
BOOL bInvis1 = ((pFace->GetFlag() & 0x01) != 0);
BOOL bInvis2 = ((pFace->GetFlag() & 0x02) != 0);
BOOL bInvis3 = ((pFace->GetFlag() & 0x04) != 0);
vertices.Append(new XPoint(pFace->GetVertex(0).x, pFace->GetVertex(0).y, bInvis1));
vertices.Append(new XPoint(pFace->GetVertex(1).x, pFace->GetVertex(1).y, bInvis2));
vertices.Append(new XPoint(pFace->GetVertex(2).x, pFace->GetVertex(2).y, bInvis3));
vertices.QuickSort(ComparePointByX);
XPoint ver0 = *vertices[0], ver1 = *vertices[1], ver2 = *vertices[2];
XVector3D 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);
XVector3D 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);
}