//-----------------------------------------------------------------------------+ // Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd. // = FileName : TGGe3DFace 类 // = Version : ver2.0 // = Author : wlw // = CreateDate : 2002-09-09 // = Description: TGGe3DFace 类定义 // = Maintainers: // //-----------------------------------------------------------------------------+ #include "StdAfx.h" #include "TGGeLine.h" #include "TGGe3DFace.h" #include "TGGe3DFace3Pt.h" #include "TGGePoly3D.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; } TGGe3DFace::TGGe3DFace(int tag) : m_nFlag(tag) { } TGGe3DFace::TGGe3DFace(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; } } } } TGGe3DFace::TGGe3DFace(TEntitySet &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++) { TADSGePoint3d pt; entFace.GetData(10 + i, pt); if (tranMat) { PointTransformBy(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 TGGe3DFace::TGGe3DFace(TGGe3DFace3Pt &face1, TGGe3DFace3Pt &face2) : m_nFlag(0) { TGGeLine line1, line2; if (face1.GetMergeLine(&line1) != RTNORM || face2.GetMergeLine(&line2) != RTNORM || !(line1 == line2)) { m_nFlag |= FLAG_UNNORMAL; return; } ads_vector vt; PlaneNormalBy3Pt(face1.GetVertex(0), face1.GetVertex(1), face1.GetVertex(2), vt); STPlanePara plan; GetPlaneEquation(face1.GetVertex(0), vt, &plan); Point prjPt, srcPt = face2.GetVertex(face2.OppHidePoint()); PointProjectToPlane(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(); } TGGe3DFace::TGGe3DFace(const TGGe3DFace& pFace) { CopyFrom(&pFace); } TGGe3DFace::~TGGe3DFace() { } int TGGe3DFace::operator !() const { return (m_nFlag & FLAG_UNNORMAL); } TGGe3DFace& TGGe3DFace::operator = (const TGGe3DFace &face) { if (this != &face) { CopyFrom(&face); } return *this; } TGGe3DFace & TGGe3DFace::operator << (int nBit) { for (int i = 0; i < nBit; i++) { MoveShift(FALSE); } return *this; } TGGe3DFace & TGGe3DFace::operator >> (int nBit) { for (int i = 0; i < nBit; i++) { MoveShift(TRUE); } return *this; } int TGGe3DFace::Modify(TEntitySet &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 TGGe3DFace::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 TGGe3DFace::IsVisible(int nSide) const { ASSERT(nSide >= 0 && nSide <= 3); int bitFlag = (0x01 << nSide); return ((m_nFlag & bitFlag) == 0); } void TGGe3DFace::SetVisible(int nSide, BOOL bTrue) { ASSERT(nSide >= 0 && nSide <= 3); int bitFlag = (0x01 << nSide); if (bTrue) { m_nFlag &= ~bitFlag; } else { m_nFlag |= bitFlag; } } void TGGe3DFace::MoveShift(BOOL bForward) { TGGe3DFace 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)); } } TVector3D TGGe3DFace::GetNormal() const { TVector3D vt1 = m_ptVertex[1] - m_ptVertex[0]; TVector3D 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 TchGeLib::adsout << _T("\n无效的3dface!"); #endif return TVector3D(0,0,1); } #ifndef NDEBUG TchGeLib::adsout << _T("\n不好的3dface!"); #endif vt1 = m_ptVertex[3] - m_ptVertex[0]; if (vt1.Length() < 1.0E-6) { return TVector3D(0,0,1); } } TVector3D vtNorm = vt1 * vt2; vtNorm /= vtNorm.Length(); return vtNorm; } AcDbFace *TGGe3DFace::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 TGGe3DFace::SectByPlane(const TGGePlane &plan, TDPtrList &upFaces, TDPtrList &downFaces) const { TGGePlane thisPlan; if (!thisPlan.SetFrom3p(GetVertex(0), GetVertex(1), GetVertex(2))) { return FALSE; } TGGeLine lnSect; if (!thisPlan.Intersect(plan, lnSect)) { return FALSE; } int nOldNumUp = upFaces.Length(); int nOldNumDown = downFaces.Length(); TVector3D vtSect = plan.GetNormal(); TVector3D vt_y = lnSect.Direction3d(); TVector3D vt_z(thisPlan.GetParaA(), thisPlan.GetParaB(), thisPlan.GetParaC()); TVector3D 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); TGGe3DFace 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); TGGe3DFace 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); TVector3D vtMe = GetNormal(); for (i = nOldNumUp; i < upFaces.Length(); i++) { TGGe3DFace *pFace = upFaces[i]; pFace->TransformBy(matTo3d); if ((AcGeVector3d &)pFace->GetNormal() != (AcGeVector3d &)vtMe) { pFace->Reverse(); } } for (i = nOldNumDown; i < downFaces.Length(); i++) { TGGe3DFace *pFace = downFaces[i]; pFace->TransformBy(matTo3d); if ((AcGeVector3d &)pFace->GetNormal() != (AcGeVector3d &)vtMe) { pFace->Reverse(); } } return bRet; } int TGGe3DFace::Make(const TCHAR *lay) const { TRBList 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); } TGGe3DFace & TGGe3DFace::MakeBetter() { TGGe3DFace 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 TGGe3DFace::IsLinear() const { TGGePoly aPoly; for (int i = 0; i < 4; i++) { aPoly.Append(new TADSGePoint3d(m_ptVertex[i])); } return aPoly.IsLinear(); } int TGGe3DFace::IsPoint() const { TGGePoly aPoly; for (int i = 0; i < 4; i++) { aPoly.Append(new TADSGePoint3d(m_ptVertex[i])); } return aPoly.IsPoint(); } int TGGe3DFace::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 TGGe3DFace::IsRectangular(ads_real *x, ads_real *y) const { TVector3D 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 (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 TGGe3DFace::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 TGGe3DFace::ExplodeEdge(TDPtrList &lstSegs) const { if (!(m_nFlag & 0x01) && m_ptVertex[0].Distance(m_ptVertex[1]) > _DIST_SNAP) { lstSegs.Append(new TGGeCurveSegment(m_ptVertex[0], m_ptVertex[1], 0.0)); } if (!(m_nFlag & 0x02) && m_ptVertex[1].Distance(m_ptVertex[2]) > _DIST_SNAP) { lstSegs.Append(new TGGeCurveSegment(m_ptVertex[1], m_ptVertex[2], 0.0)); } if (!(m_nFlag & 0x04) && m_ptVertex[2].Distance(m_ptVertex[3]) > _DIST_SNAP) { lstSegs.Append(new TGGeCurveSegment(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 TGGeCurveSegment(m_ptVertex[3], m_ptVertex[0], 0.0)); } } void TGGe3DFace::SetElevation(double nElev) { m_ptVertex[0].z = m_ptVertex[1].z = m_ptVertex[2].z = m_ptVertex[3].z = nElev; } void TGGe3DFace::Reverse() { TGGe3DFace 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都必须是单位向量! TGGePoly3D TGGe3DFace::GetPoly3D()const { TGGePoly3D 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; } TGGePlane TGGe3DFace::GetPlane()const { return TGGePlane(GetVertex(0),GetNormal()); } int TGGe3DFace::GetFlag()const { return m_nFlag; } void TGGe3DFace::SetFlag(const int nFlag) { m_nFlag = nFlag; } TADSGePoint3d& TGGe3DFace::GetVertex(int nIndex) { if (nIndex > 3 || nIndex < 0) { static TADSGePoint3d ptOrg(0.0,0.0,0.0); return ptOrg; } return m_ptVertex[nIndex]; } TADSGePoint3d TGGe3DFace::GetVertex(int nIndex)const { if (nIndex > 3 || nIndex < 0) { return TADSGePoint3d(); } return m_ptVertex[nIndex]; } void TGGe3DFace::SetVertex(int nIndex, TADSGePoint3d pt) { if (nIndex >= 0 && nIndex < 4) { m_ptVertex[nIndex] = pt; } } void TGGe3DFace::SubSortVertex() { TGGe3DFace *pFace = this; ASSERT(pFace->GetFlag() & FLAG_TRIANGLE); TDPtrList 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); } BOOL TGGe3DFace::SubSectByX(double xSect, TDPtrList &leftFaces, TDPtrList &rightFaces) const { TGGe3DFace 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 TGGe3DFace(face)); } else if (nFlag1 >= 0) { //无切割发生 rightFaces.Append(new TGGe3DFace(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; 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); leftFaces.Append(newFace); rightFaces.Append(new TGGe3DFace(face)); } } else { ASSERT(0); return FALSE; } return TRUE; } bool TGGe3DFace::IsKindOf(TGGeEntity::TEntityId entType) const { switch(entType) { case TGGeEntity::eEntity: case TGGeEntity::e3DFace: return true; } return false; } TGGeEntity::TEntityId TGGe3DFace::Type() const { return TGGeEntity::e3DFace; } void TGGe3DFace::CopyFrom(const TGGeEntity* pImpSrc) { if (this != pImpSrc && pImpSrc->IsKindOf(TGGeEntity::e3DFace)) { m_nFlag = ((TGGe3DFace* )pImpSrc)->m_nFlag; for (int i = 0; i < 4; i++) { m_ptVertex[i] = ((TGGe3DFace* )pImpSrc)->m_ptVertex[i]; } } }