922 lines
19 KiB
C++
922 lines
19 KiB
C++
//-----------------------------------------------------------------------------+
|
||
// Copyright (C), 1998-2007, SH Software Co. Ltd.
|
||
// = FileName : X3DFace 类
|
||
// = Version : ver2.0
|
||
// = Author : zjq
|
||
// = CreateDate : 2002-09-09
|
||
// = Description: X3DFace 类定义
|
||
// = Maintainers:
|
||
//
|
||
//-----------------------------------------------------------------------------+
|
||
#include "StdAfx.h"
|
||
#include "XLine.h"
|
||
#include "X3DFace.h"
|
||
#include "X3DFace3Pt.h"
|
||
#include "XPoly3D.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;
|
||
}
|
||
|
||
X3DFace::X3DFace(int tag)
|
||
: m_nFlag(tag)
|
||
{
|
||
|
||
}
|
||
|
||
X3DFace::X3DFace(const AcDbFace &face)
|
||
: m_nFlag(0)
|
||
{
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
face.getVertexAt(i, m_ptVertex[i]);
|
||
Adesk::Boolean bVis = Adesk::kTrue;
|
||
face.isEdgeVisibleAt(i, bVis);
|
||
if (!bVis)
|
||
{
|
||
if (i == 0)
|
||
{
|
||
m_nFlag |= 0x01;
|
||
}
|
||
else if (i == 1)
|
||
{
|
||
m_nFlag |= 0x02;
|
||
}
|
||
else if (i == 2)
|
||
{
|
||
m_nFlag |= 0x04;
|
||
}
|
||
else
|
||
{
|
||
m_nFlag |= 0x08;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
X3DFace::X3DFace(Entity &entFace, ads_matrix tranMat)
|
||
: m_nFlag(0)
|
||
{
|
||
if (!entFace.Is(_T("3DFACE")))
|
||
{
|
||
m_nFlag |= FLAG_UNNORMAL;
|
||
return;
|
||
}
|
||
|
||
entFace.GetData(70, &m_nFlag);
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
XPoint pt;
|
||
entFace.GetData(10 + i, pt);
|
||
|
||
if (tranMat)
|
||
{
|
||
AT_xformpt(tranMat, pt, m_ptVertex[i]);
|
||
}
|
||
else
|
||
{
|
||
m_ptVertex[i] = pt;
|
||
}
|
||
|
||
if (fabs(m_ptVertex[i].x) > 1.0E9 || fabs(m_ptVertex[i].y) > 1.0E9
|
||
|| fabs(m_ptVertex[i].z) > 1.0E9)
|
||
{
|
||
m_nFlag |= FLAG_UNNORMAL;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
// 把两个3Dface3C并成一个3Dface
|
||
X3DFace::X3DFace(X3DFace3Pt &face1, X3DFace3Pt &face2)
|
||
: m_nFlag(0)
|
||
{
|
||
XLine line1, line2;
|
||
if (face1.GetMergeLine(&line1) != RTNORM
|
||
|| face2.GetMergeLine(&line2) != RTNORM
|
||
|| !(line1 == line2))
|
||
{
|
||
m_nFlag |= FLAG_UNNORMAL;
|
||
return;
|
||
}
|
||
|
||
ads_vector vt;
|
||
CT_vector_plan3p(face1.GetVertex(0), face1.GetVertex(1), face1.GetVertex(2), vt);
|
||
|
||
plan_para plan;
|
||
CT_plan_equation(face1.GetVertex(0), vt, &plan);
|
||
|
||
Point prjPt, srcPt = face2.GetVertex(face2.OppHidePoint());
|
||
CT_point_prj_plan(srcPt, &plan, prjPt);
|
||
|
||
if (!(prjPt == srcPt))
|
||
{
|
||
m_nFlag |= FLAG_UNNORMAL;
|
||
return;
|
||
}
|
||
|
||
int index1 = face1.MergeEdge();
|
||
int index2 = face2.MergeEdge();
|
||
if (index1 < 0 || index2 < 0)
|
||
{
|
||
m_nFlag |= FLAG_UNNORMAL;
|
||
return;
|
||
}
|
||
|
||
m_ptVertex[0] = face1.GetVertex(face1.OppHidePoint());
|
||
m_ptVertex[1] = line1.GetStartPoint();
|
||
m_ptVertex[2] = face2.GetVertex(face2.OppHidePoint());
|
||
m_ptVertex[3] = line1.GetEndPoint();
|
||
}
|
||
|
||
X3DFace::X3DFace(const X3DFace& pFace)
|
||
{
|
||
CopyFrom(&pFace);
|
||
}
|
||
|
||
X3DFace::~X3DFace()
|
||
{
|
||
|
||
}
|
||
|
||
int X3DFace::operator !() const
|
||
{
|
||
return (m_nFlag & FLAG_UNNORMAL);
|
||
}
|
||
|
||
X3DFace& X3DFace::operator = (const X3DFace &face)
|
||
{
|
||
if (this != &face)
|
||
{
|
||
CopyFrom(&face);
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
X3DFace & X3DFace::operator << (int nBit)
|
||
{
|
||
for (int i = 0; i < nBit; i++)
|
||
{
|
||
MoveShift(FALSE);
|
||
}
|
||
|
||
return *this;
|
||
}
|
||
|
||
X3DFace & X3DFace::operator >> (int nBit)
|
||
{
|
||
for (int i = 0; i < nBit; i++)
|
||
{
|
||
MoveShift(TRUE);
|
||
}
|
||
|
||
return *this;
|
||
}
|
||
|
||
int X3DFace::Modify(Entity &entFace)
|
||
{
|
||
if (!entFace.Is(_T("3DFACE")))
|
||
{
|
||
return RTERROR;
|
||
}
|
||
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
if (fabs(m_ptVertex[i].x) > 1.0E9
|
||
|| fabs(m_ptVertex[i].y) > 1.0E9
|
||
|| fabs(m_ptVertex[i].z) > 1.0E9)
|
||
{
|
||
ads_printf(_T("\nInorder to modify 3Dface with bad m_ptVertex!"));
|
||
}
|
||
|
||
entFace.SetData(10 + i, &m_ptVertex[i].x);
|
||
}
|
||
entFace.SetData(70, m_nFlag);
|
||
|
||
return entFace.Modify();
|
||
}
|
||
|
||
// nMethod: 0-采用标记来判断,1-采用首没点是否相同来判断,2-采用任意相邻2点相等来判断
|
||
BOOL X3DFace::IsTriangle(int nMethod) const
|
||
{
|
||
if (nMethod == 0)
|
||
{
|
||
return ((m_nFlag & FLAG_TRIANGLE) != 0);
|
||
}
|
||
else if (nMethod == 1)
|
||
{
|
||
return (m_ptVertex[0].Distance(m_ptVertex[3]) < _DIST_SNAP);
|
||
}
|
||
|
||
BOOL bTri = (m_ptVertex[0].Distance(m_ptVertex[3]) < _DIST_SNAP
|
||
|| m_ptVertex[1].Distance(m_ptVertex[0]) < _DIST_SNAP
|
||
|| m_ptVertex[2].Distance(m_ptVertex[1]) < _DIST_SNAP
|
||
|| m_ptVertex[3].Distance(m_ptVertex[2]) < _DIST_SNAP);
|
||
|
||
return bTri;
|
||
}
|
||
|
||
BOOL X3DFace::IsVisible(int nSide) const
|
||
{
|
||
ASSERT(nSide >= 0 && nSide <= 3);
|
||
|
||
int bitFlag = (0x01 << nSide);
|
||
return ((m_nFlag & bitFlag) == 0);
|
||
}
|
||
|
||
void X3DFace::SetVisible(int nSide, BOOL bTrue)
|
||
{
|
||
ASSERT(nSide >= 0 && nSide <= 3);
|
||
int bitFlag = (0x01 << nSide);
|
||
if (bTrue)
|
||
{
|
||
m_nFlag &= ~bitFlag;
|
||
}
|
||
else
|
||
{
|
||
m_nFlag |= bitFlag;
|
||
}
|
||
}
|
||
|
||
void X3DFace::MoveShift(BOOL bForward)
|
||
{
|
||
X3DFace face1(*this);
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
BOOL iNext = (bForward ? i - 1 : i + 1);
|
||
if (iNext == 4)
|
||
{
|
||
iNext = 0;
|
||
}
|
||
else if (iNext == -1)
|
||
{
|
||
iNext = 3;
|
||
}
|
||
|
||
GetVertex(i) = face1.GetVertex(iNext);
|
||
SetVisible(i, face1.IsVisible(iNext));
|
||
}
|
||
}
|
||
|
||
XVector3D X3DFace::GetNormal() const
|
||
{
|
||
XVector3D vt1 = m_ptVertex[1] - m_ptVertex[0];
|
||
XVector3D vt2 = m_ptVertex[2] - m_ptVertex[0];
|
||
BOOL b1 = (vt1.Length() < 1.0E-6);
|
||
BOOL b2 = (vt2.Length() < 1.0E-6);
|
||
if (b1 || b2)
|
||
{
|
||
if (b2)
|
||
{
|
||
#ifndef NDEBUG
|
||
XGeLib::adsout << _T("\n无效的3dface!");
|
||
#endif
|
||
return XVector3D(0,0,1);
|
||
}
|
||
#ifndef NDEBUG
|
||
XGeLib::adsout << _T("\n不好的3dface!");
|
||
#endif
|
||
vt1 = m_ptVertex[3] - m_ptVertex[0];
|
||
if (vt1.Length() < 1.0E-6)
|
||
{
|
||
return XVector3D(0,0,1);
|
||
}
|
||
}
|
||
|
||
XVector3D vtNorm = vt1 * vt2;
|
||
vtNorm /= vtNorm.Length();
|
||
|
||
return vtNorm;
|
||
}
|
||
|
||
AcDbFace *X3DFace::AsDbFace() const
|
||
{
|
||
AcDbFace *pDbFace = new AcDbFace(m_ptVertex[0], m_ptVertex[1], m_ptVertex[2], m_ptVertex[3],
|
||
((m_nFlag & 0x01) == 0), ((m_nFlag & 0x02) == 0), ((m_nFlag & 0x04) == 0), ((m_nFlag & 0x08) == 0));
|
||
|
||
return pDbFace;
|
||
}
|
||
|
||
// 对3dface进行切割
|
||
BOOL X3DFace::SectByPlane(const XPlane &plan, DList<X3DFace> &upFaces, DList<X3DFace> &downFaces) const
|
||
{
|
||
XPlane thisPlan;
|
||
if (!thisPlan.SetFrom3p(GetVertex(0), GetVertex(1), GetVertex(2)))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
XLine lnSect;
|
||
if (!thisPlan.Intersect(plan, lnSect))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
int nOldNumUp = upFaces.Length();
|
||
int nOldNumDown = downFaces.Length();
|
||
|
||
XVector3D vtSect = plan.GetNormal();
|
||
|
||
XVector3D vt_y = lnSect.Direction3d();
|
||
XVector3D vt_z(thisPlan.GetParaA(), thisPlan.GetParaB(), thisPlan.GetParaC());
|
||
XVector3D vt_x = vt_z * vt_y;
|
||
|
||
AcGeMatrix3d mat, matRev;
|
||
matRev.setCoordSystem(lnSect.GetStartPoint(), vt_x, vt_y, vt_z);
|
||
mat = matRev.inverse();
|
||
((AcGeVector3d &)vtSect).transformBy(mat);
|
||
|
||
ads_matrix adsMat;
|
||
AsAdsMatrix(mat, adsMat);
|
||
|
||
X3DFace thisFace(*this);
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
thisFace.GetVertex(i).TransformBy(adsMat);
|
||
}
|
||
|
||
if (!(thisFace.GetFlag() & FLAG_TRIANGLE))
|
||
{
|
||
if (thisFace.IsTriangle(1))
|
||
{
|
||
int nFlag = thisFace.GetFlag();
|
||
nFlag |= FLAG_TRIANGLE;
|
||
thisFace.SetFlag(nFlag);
|
||
}
|
||
}
|
||
|
||
BOOL bRet = TRUE;
|
||
if (!(thisFace.GetFlag() & FLAG_TRIANGLE))
|
||
{
|
||
BOOL bHide0 = ((thisFace.GetFlag() & 0x01) != 0);
|
||
BOOL bHide1 = ((thisFace.GetFlag() & 0x02) != 0);
|
||
BOOL bHide2 = ((thisFace.GetFlag() & 0x04) != 0);
|
||
BOOL bHide3 = ((thisFace.GetFlag() & 0x08) != 0);
|
||
|
||
X3DFace tri1, tri2;
|
||
tri1.SetVertex(0, thisFace.GetVertex(0));
|
||
tri1.SetVertex(3, thisFace.GetVertex(0));
|
||
|
||
int nFlag = tri1.GetFlag();
|
||
if (bHide0)
|
||
{
|
||
nFlag |= 0x01;
|
||
}
|
||
|
||
tri1.SetVertex(1, thisFace.GetVertex(1));
|
||
|
||
if (bHide1)
|
||
{
|
||
nFlag |= 0x02;
|
||
}
|
||
tri1.SetVertex(2, thisFace.GetVertex(2));
|
||
nFlag |= 0x04; //不可见
|
||
|
||
tri2.SetVertex(0, thisFace.GetVertex(2));
|
||
tri2.SetVertex(3, thisFace.GetVertex(2));
|
||
tri2.SetVertex(1, thisFace.GetVertex(3));
|
||
tri2.SetVertex(2, thisFace.GetVertex(0));
|
||
|
||
int nFlagTri2 = tri2.GetFlag();
|
||
if (bHide2)
|
||
{
|
||
nFlagTri2 |= 0x01;
|
||
}
|
||
|
||
if (bHide3)
|
||
{
|
||
nFlagTri2 |= 0x02;
|
||
}
|
||
|
||
nFlag |= FLAG_TRIANGLE;
|
||
nFlagTri2 |= 0x04;
|
||
nFlagTri2 |= FLAG_TRIANGLE;
|
||
tri1.SetFlag(nFlag);
|
||
tri2.SetFlag(nFlagTri2);
|
||
|
||
tri1.SubSortVertex();
|
||
if (vtSect.x < 0.0)
|
||
{
|
||
bRet = tri1.SubSectByX(0.0, upFaces, downFaces);
|
||
}
|
||
else
|
||
{
|
||
bRet = tri1.SubSectByX(0.0, downFaces, upFaces);
|
||
}
|
||
|
||
tri2.SubSortVertex();
|
||
if (vtSect.x < 0.0)
|
||
{
|
||
bRet = tri2.SubSectByX(0.0, upFaces, downFaces);
|
||
}
|
||
else
|
||
{
|
||
bRet = tri2.SubSectByX(0.0, downFaces, upFaces);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
thisFace.SubSortVertex();
|
||
if (vtSect.x < 0.0)
|
||
{
|
||
bRet = thisFace.SubSectByX(0.0, upFaces, downFaces);
|
||
}
|
||
else
|
||
{
|
||
bRet = thisFace.SubSectByX(0.0, downFaces, upFaces);
|
||
}
|
||
}
|
||
|
||
|
||
// 转回三维坐标系
|
||
ads_matrix matTo3d;
|
||
AsAdsMatrix(matRev, matTo3d);
|
||
|
||
XVector3D vtMe = GetNormal();
|
||
for (int i = nOldNumUp; i < upFaces.Length(); i++)
|
||
{
|
||
X3DFace *pFace = upFaces[i];
|
||
pFace->TransformBy(matTo3d);
|
||
|
||
if ((AcGeVector3d &)pFace->GetNormal() != (AcGeVector3d &)vtMe)
|
||
{
|
||
pFace->Reverse();
|
||
}
|
||
}
|
||
|
||
for (int i = nOldNumDown; i < downFaces.Length(); i++)
|
||
{
|
||
X3DFace *pFace = downFaces[i];
|
||
pFace->TransformBy(matTo3d);
|
||
|
||
if ((AcGeVector3d &)pFace->GetNormal() != (AcGeVector3d &)vtMe)
|
||
{
|
||
pFace->Reverse();
|
||
}
|
||
}
|
||
|
||
return bRet;
|
||
}
|
||
|
||
int X3DFace::Make(const TCHAR *lay) const
|
||
{
|
||
RBList ebuf = ads_buildlist(RTDXF0, _T("3DFACE"), 10, &m_ptVertex[0], 11, &m_ptVertex[1],
|
||
12, &m_ptVertex[2], 13, &m_ptVertex[3], 70, m_nFlag, NULL);
|
||
if (lay)
|
||
{
|
||
ebuf.SetData(8, lay);
|
||
}
|
||
|
||
return ads_entmake(ebuf);
|
||
}
|
||
|
||
X3DFace & X3DFace::MakeBetter()
|
||
{
|
||
X3DFace face(*this);
|
||
if (face.IsTriangle(2))
|
||
{
|
||
if (face.GetVertex(0).Distance(face.GetVertex(1)) < _DIST_SNAP)
|
||
{
|
||
face << 1;
|
||
}
|
||
else if (face.GetVertex(1).Distance(face.GetVertex(2)) < _DIST_SNAP)
|
||
{
|
||
face << 2;
|
||
}
|
||
else if (face.GetVertex(2).Distance(face.GetVertex(3)) < _DIST_SNAP)
|
||
{
|
||
face >> 1;
|
||
}
|
||
|
||
ASSERT(face.IsTriangle(1));
|
||
*this = face;
|
||
}
|
||
|
||
return *this;
|
||
}
|
||
|
||
int X3DFace::IsLinear() const
|
||
{
|
||
XPoly aPoly;
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
aPoly.Append(new XPoint(m_ptVertex[i]));
|
||
}
|
||
|
||
return aPoly.IsLinear();
|
||
}
|
||
|
||
int X3DFace::IsPoint() const
|
||
{
|
||
XPoly aPoly;
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
aPoly.Append(new XPoint(m_ptVertex[i]));
|
||
}
|
||
|
||
return aPoly.IsPoint();
|
||
}
|
||
|
||
int X3DFace::GetExtend(ads_point lowPt, ads_point upPt) const
|
||
{
|
||
if (!(*this))
|
||
{
|
||
return RTERROR;
|
||
}
|
||
|
||
upPt[X] = Maximum(4, m_ptVertex[0].x, m_ptVertex[1].x, m_ptVertex[2].x, m_ptVertex[3].x);
|
||
upPt[Y] = Maximum(4, m_ptVertex[0].y, m_ptVertex[1].y, m_ptVertex[2].y, m_ptVertex[3].y);
|
||
upPt[Z] = Maximum(4, m_ptVertex[0].z, m_ptVertex[1].z, m_ptVertex[2].z, m_ptVertex[3].z);
|
||
lowPt[X] = Minimum(4, m_ptVertex[0].x, m_ptVertex[1].x, m_ptVertex[2].x, m_ptVertex[3].x);
|
||
lowPt[Y] = Minimum(4, m_ptVertex[0].y, m_ptVertex[1].y, m_ptVertex[2].y, m_ptVertex[3].y);
|
||
lowPt[Z] = Minimum(4, m_ptVertex[0].z, m_ptVertex[1].z, m_ptVertex[2].z, m_ptVertex[3].z);
|
||
|
||
return RTNORM;
|
||
}
|
||
|
||
int X3DFace::IsRectangular(ads_real *x, ads_real *y) const
|
||
{
|
||
XVector3D vt[4];
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
if (i == 3)
|
||
{
|
||
vt[i] = m_ptVertex[0] - m_ptVertex[3];
|
||
}
|
||
else
|
||
{
|
||
vt[i] = m_ptVertex[i + 1] - m_ptVertex[i];
|
||
}
|
||
|
||
if (!vt[i])
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
if (i == 3)
|
||
{
|
||
if (fabs(vt[3] & vt[0]) > 1E-6)
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (fabs(vt[i] & vt[i + 1]) > 1E-6)
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (x)
|
||
{
|
||
*x = ads_distance(m_ptVertex[0], m_ptVertex[1]);
|
||
}
|
||
|
||
if (y)
|
||
{
|
||
*y = ads_distance(m_ptVertex[1], m_ptVertex[2]);
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
void X3DFace::TransformBy(ads_matrix mat)
|
||
{
|
||
m_ptVertex[0].TransformBy(mat);
|
||
m_ptVertex[1].TransformBy(mat);
|
||
m_ptVertex[2].TransformBy(mat);
|
||
m_ptVertex[3].TransformBy(mat);
|
||
}
|
||
|
||
void X3DFace::ExplodeEdge(DList<XCurveSegment> &lstSegs) const
|
||
{
|
||
if (!(m_nFlag & 0x01) && m_ptVertex[0].Distance(m_ptVertex[1]) > _DIST_SNAP)
|
||
{
|
||
lstSegs.Append(new XCurveSegment(m_ptVertex[0], m_ptVertex[1], 0.0));
|
||
}
|
||
|
||
if (!(m_nFlag & 0x02) && m_ptVertex[1].Distance(m_ptVertex[2]) > _DIST_SNAP)
|
||
{
|
||
lstSegs.Append(new XCurveSegment(m_ptVertex[1], m_ptVertex[2], 0.0));
|
||
}
|
||
|
||
if (!(m_nFlag & 0x04) && m_ptVertex[2].Distance(m_ptVertex[3]) > _DIST_SNAP)
|
||
{
|
||
lstSegs.Append(new XCurveSegment(m_ptVertex[2], m_ptVertex[3], 0.0));
|
||
}
|
||
|
||
if (!IsTriangle(1) && !(m_nFlag & 0x08) && m_ptVertex[3].Distance(m_ptVertex[0]) > _DIST_SNAP)
|
||
{
|
||
lstSegs.Append(new XCurveSegment(m_ptVertex[3], m_ptVertex[0], 0.0));
|
||
}
|
||
}
|
||
|
||
void X3DFace::SetElevation(double nElev)
|
||
{
|
||
m_ptVertex[0].z = m_ptVertex[1].z = m_ptVertex[2].z = m_ptVertex[3].z = nElev;
|
||
}
|
||
|
||
void X3DFace::Reverse()
|
||
{
|
||
X3DFace old(*this);
|
||
m_ptVertex[0] = old.GetVertex(3);
|
||
m_ptVertex[1] = old.GetVertex(2);
|
||
m_ptVertex[2] = old.GetVertex(1);
|
||
m_ptVertex[3] = old.GetVertex(0);
|
||
|
||
m_nFlag &= ~(0x01 | 0x04);
|
||
if (old.GetFlag() & 0x04)
|
||
{
|
||
m_nFlag |= 0x01;
|
||
}
|
||
|
||
if (old.GetFlag() & 0x01)
|
||
{
|
||
m_nFlag |= 0x04;
|
||
}
|
||
}
|
||
|
||
//vtLight都必须是单位向量!
|
||
XPoly3D X3DFace::GetPoly3D()const
|
||
{
|
||
XPoly3D poly(1);
|
||
poly.AppendNode(m_ptVertex[0]);
|
||
poly.AppendNode(m_ptVertex[1]);
|
||
poly.AppendNode(m_ptVertex[2]);
|
||
|
||
if (!IsTriangle(1) && m_ptVertex[0] != m_ptVertex[3])
|
||
{
|
||
poly.AppendNode(m_ptVertex[3]);
|
||
}
|
||
|
||
return poly;
|
||
}
|
||
|
||
XPlane X3DFace::GetPlane()const
|
||
{
|
||
return XPlane(GetVertex(0),GetNormal());
|
||
}
|
||
|
||
int X3DFace::GetFlag()const
|
||
{
|
||
return m_nFlag;
|
||
}
|
||
|
||
void X3DFace::SetFlag(const int nFlag)
|
||
{
|
||
m_nFlag = nFlag;
|
||
}
|
||
|
||
XPoint& X3DFace::GetVertex(int nIndex)
|
||
{
|
||
if (nIndex > 3 || nIndex < 0)
|
||
{
|
||
static XPoint ptOrg(0.0,0.0,0.0);
|
||
return ptOrg;
|
||
}
|
||
|
||
return m_ptVertex[nIndex];
|
||
}
|
||
|
||
XPoint X3DFace::GetVertex(int nIndex)const
|
||
{
|
||
if (nIndex > 3 || nIndex < 0)
|
||
{
|
||
return XPoint();
|
||
}
|
||
|
||
return m_ptVertex[nIndex];
|
||
}
|
||
|
||
void X3DFace::SetVertex(int nIndex, XPoint pt)
|
||
{
|
||
if (nIndex >= 0 && nIndex < 4)
|
||
{
|
||
m_ptVertex[nIndex] = pt;
|
||
}
|
||
}
|
||
|
||
void X3DFace::SubSortVertex()
|
||
{
|
||
X3DFace *pFace = this;
|
||
ASSERT(pFace->GetFlag() & FLAG_TRIANGLE);
|
||
|
||
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);
|
||
}
|
||
|
||
BOOL X3DFace::SubSectByX(double xSect, DList<X3DFace> &leftFaces, DList<X3DFace> &rightFaces) const
|
||
{
|
||
X3DFace face = *this;
|
||
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)
|
||
{
|
||
leftFaces.Append(new X3DFace(face));
|
||
}
|
||
else if (nFlag1 >= 0)
|
||
{
|
||
//无切割发生
|
||
rightFaces.Append(new X3DFace(face));
|
||
}
|
||
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);
|
||
|
||
leftFaces.Append(newFace);
|
||
rightFaces.Append(new X3DFace(face));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ASSERT(0);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
bool X3DFace::IsKindOf(XEntity::TEntityId entType) const
|
||
{
|
||
switch(entType)
|
||
{
|
||
case XEntity::eEntity:
|
||
case XEntity::e3DFace:
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
XEntity::TEntityId X3DFace::Type() const
|
||
{
|
||
return XEntity::e3DFace;
|
||
}
|
||
|
||
void X3DFace::CopyFrom(const XEntity* pImpSrc)
|
||
{
|
||
if (this != pImpSrc && pImpSrc->IsKindOf(XEntity::e3DFace))
|
||
{
|
||
m_nFlag = ((X3DFace* )pImpSrc)->m_nFlag;
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
m_ptVertex[i] = ((X3DFace* )pImpSrc)->m_ptVertex[i];
|
||
}
|
||
}
|
||
|
||
}
|
||
|