453 lines
12 KiB
C++
453 lines
12 KiB
C++
//-----------------------------------------------------------------------------+
|
||
// 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);
|
||
} |