#include "stdafx.h" #include "aecroof.h" #include "XGlobalFunc.h" #include "XScreenDc.h" #include "XCurveInline.h" static int g_nDbgFlag=0; //extern int DePeriod(int nPeriod, int nIndex); ///////////////////////////////////// // 屋顶数据类 ///////////////////////////////////// ////////////////////////////////// // 求三阶行列式 double MatrixValue(double a[3][3]) { double nRes = a[0][0]*a[1][1]*a[2][2] + a[0][1]*a[1][2]*a[2][0] + a[0][2]*a[1][0]*a[2][1] - a[0][2]*a[1][1]*a[2][0] - a[0][1]*a[1][0]*a[2][2] - a[0][0]*a[1][2]*a[2][1]; return nRes; } /////////////////////////////////////// // 求三个面的交点 int IntersectWith(const XPlanePara &plan1, const XPlanePara &plan2, const XPlanePara &plan3, XPoint &ptInter) { double a[3][3]={ {plan1.nParaA, plan1.nParaB, plan1.nParaC}, {plan2.nParaA, plan2.nParaB, plan2.nParaC}, {plan3.nParaA, plan3.nParaB, plan3.nParaC}, }; double nDelta = MatrixValue(a); if(fabs(nDelta)<1.0E-5) return 0; double a1[3][3] = { {-plan1.nParaD, plan1.nParaB, plan1.nParaC}, {-plan2.nParaD, plan2.nParaB, plan2.nParaC}, {-plan3.nParaD, plan3.nParaB, plan3.nParaC}, }; double a2[3][3] = { {plan1.nParaA, -plan1.nParaD, plan1.nParaC}, {plan2.nParaA, -plan2.nParaD, plan2.nParaC}, {plan3.nParaA, -plan3.nParaD, plan3.nParaC}, }; double a3[3][3] = { {plan1.nParaA, plan1.nParaB, -plan1.nParaD}, {plan2.nParaA, plan2.nParaB, -plan2.nParaD}, {plan3.nParaA, plan3.nParaB, -plan3.nParaD}, }; ptInter.x = MatrixValue(a1)/nDelta; ptInter.y = MatrixValue(a2)/nDelta; ptInter.z = MatrixValue(a3)/nDelta; return 1; } ///////////////////////////////////////////////// // 求线和面的交点,考虑了线是否为无限长 int IntersectWith(const XLine &ln, const XPlanePara &plan, XPoint &res) { if(!CT_inter_line_plan1(ln.StartPoint(), ln.EndPoint(), (const plan_para *)&plan, res)) return 0; if(ln.GetLineFlag()==LS_FINITE) { int nFlag=(res&ln); if(nFlag==PR_INSIDE || nFlag==PR_ONPT1 || nFlag==PR_ONPT2) return 1; else return 0; } return 1; } ////////////////////////////////////////////////// // XAecPlan: 空间几何平面的类 ////////////////////////////////////////////////// //////////////////////////////////////////////////////////// // 平面内一点及法向量来初始化平面 int XPlanePara::InitPlane(const XPoint &pt0, const XVector3D &vt) { ASSERT(sizeof(XPlane)==sizeof(plan_para)); if(!CT_plan_equation(pt0, vt, (plan_para *)this)) return RTERROR; return RTNORM; } int XPlanePara::InitPlane(const XPoint &pt1, const XPoint &pt2, const XPoint &pt3) { XPoint vt; if(!CT_vector_plan3p(pt1, pt2, pt3, vt)) return RTERROR; ASSERT(sizeof(XPlanePara)==sizeof(plan_para)); if(!CT_plan_equation(pt1, vt, (plan_para *)this)) return RTERROR; return RTNORM; } ////////////////////////////////////////////////// // XAecPlan: 坡屋顶几何类 ////////////////////////////////////////////////// ///////////////////////////////////////////////////// // 用底面和倾角来初始化等坡屋顶 /* XAecRoof::XAecRoof(const XPoly2D &poly, double nSlant) { InitRoof(poly, nSlant); } */ ////////////////////////////////////////////////////// // 用底面和倾角初始化等坡屋顶 int XAecRoof::InitRoof(const XPoly2D &poly, double nSlant) { m_lstEdges.Reset(); m_lstSlopeFaces.Reset(); poly.Disperse(m_polyBoundry, 20); for(int i=0; im_ptVertex); } return RTNORM; } //////////////////////////////////////// // 计算屋顶各个坡面 int XAecRoof::Calculate() { m_lstSlopeFaces.Reset(); m_lstRidges.Reset(); for(int n=0; n=3); ads_matrix matTran; get_matrix(*poly[0], *poly[1], *poly[2], matTran); poly.TransUCS(matTran); poly.Compress(); XTrianglePface lstTris; if(poly.Trianglize(0, lstTris)==RTNORM) { ads_matrix aMatTran; //逆变换 for(int n=0; nvertex1.TransformBy(aMatTran); triangle->vertex2.TransformBy(aMatTran); triangle->vertex3.TransformBy(aMatTran); } lstTris.MakePolyface(); } else { adsout << _T("error"); return RTERROR; } #endif } return RTNORM; } //////////////////////////////////////////////////////////////////////// // 功能: 求当前坡面的下一个屋脊线 // nThis, thisPlane -- 当前斜面的全局序号和当前斜面 // nLast, lastPlane -- 最近的一个轮面, 确定一待定下一个顶点, nLast>nThis // ptLast -- 已经确定的前一个顶点,在lastPlane上 // pNextIndex, nextPlane -- 下一个轮面 // ptNext -- 待确定的点 // 如果返回RTERROR,则找不到 // 如果pNextIndex == nThis+nEdgeNum-1, 则下回不用再轮了, 因为下次将回到起点 int XAecRoof::GetNext(int nThis, const XPlanePara &thisPlane, int nLast, const XPlanePara &lastPlane, const XPoint &ptLast, int *pNextIndex, XPlanePara &nextPlane, XPoint &ptNext) { int nTotalEdge = GetTotalEdge(); ASSERT(nLast=j+1; k--) lstVertexes.Remove(k); lstVertexes.Append(new XPoint(ptInter)); break; } }*/ lstVertexes.Append(new XPoint(ptNext)); if(g_nDbgFlag) { dc << lstVertexes; if(ads_getint(_T("\nStep: "), &nNextIndex)==RTCAN) return RTCAN; ads_redraw(NULL,0); } if(nNextIndex == n+nTotalEdge-1) // 最后一边 break; lastPlane=nextPlane; nLastIndex=nNextIndex; ptLast = ptNext; } if(g_nDbgFlag) { int nTemp; dc.Draw(lstVertexes, 1); if(ads_getint(_T("\nFinal Step: "), &nTemp)==RTCAN) return RTCAN; ads_redraw(NULL,0); } return RTNORM; } /////////////////////////////////////////////////// // 取得第n个坡面的几何平面 int XAecRoof::GetPlane(int n, XPlanePara &thisPlane) const { int nTotalEdge = GetTotalEdge(); n=DePeriod(nTotalEdge, n); XRoofEdge edge; if(GetEdge(n, edge)!=RTNORM) return RTERROR; XLine lnLeft=edge.Offset(-1000.0); double nHeight=1000.0*tan(edge.m_nSlope); XPoint pt3=lnLeft.StartPoint(); pt3.z += nHeight; if(thisPlane.InitPlane(edge.StartPoint(), edge.EndPoint(), pt3)!=RTNORM) return RTERROR; return RTNORM; } ///////////////////////////////////////////////////////////////// // 取得第n条棱(屋脊线) // bOnBottom -- 是否投影到底面 int XAecRoof::GetRidge(int n, XLine &lnRidge, int bQuickGet) const { if(bQuickGet) { n = DePeriod(GetTotalEdge(), n); ASSERT(n=3); double nSlopeAngle=m_lstEdges[n].m_nSlope; ads_matrix matTran; get_matrix(slopeFace[0], slopeFace[1], slopeFace[2], matTran); XPoly2D poly(1); for(int i=0; i0.0); //double nRes=((XPoly &)slopeFace).Area()/cos(nSlopeAngle); return nRes; } ////////////////////////////////////////////////////////////////////////// // 求面的描述 // 由调用函数负责释放点表和面表 typedef DList IntList; int XAecRoof::GetSurfaceData(int *nVerticeNum, XPoint * &pVerticeList, int *pFaceListLen, Adesk::Int32 * &pFaceList, Adesk::UInt8 * &pEdgeVisArray) const { int nTotalFaceNum=m_lstSlopeFaces.Length(); if(!nTotalFaceNum) return RTERROR; int nTotalEdge=GetTotalEdge(); XPointList lstVertices; DList lstFaces; DList lstEdgeVis; //边的可见性 int nFaceListLen=0; int nEdgeListLen=0; for(int i=0; i=3); DList *pFace = new DList; DList *pEdge = new DList; int nLastVertex=0; int nFirstVertexIndex=0; double nPreSlope=m_lstEdges[DePeriod(nTotalEdge, i-1)].m_nSlope; double nNextSlope=m_lstEdges[DePeriod(nTotalEdge, i+1)].m_nSlope; for(int j=0; jAppend(new int(nCurIndex)); if(j==0) nFirstVertexIndex = nCurIndex; else if(j==1) { //第2个顶点确定第一边, 底边 pEdge->Append(new int(m_bBotVisible? kAcGiVisible : kAcGiInvisible)); } else { //否则升序的边为可见 if(fabs(nPreSlope-PI/2)<_angSnap || fabs(nNextSlope-PI/2)<_angSnap) { pEdge->Append(new int(kAcGiVisible)); } else { if(nCurIndex>nLastVertex) pEdge->Append(new int(kAcGiVisible)); else pEdge->Append(new int(kAcGiInvisible)); } } nLastVertex = nCurIndex; } if(fabs(nPreSlope-PI/2)<_angSnap || fabs(nNextSlope-PI/2)<_angSnap) { pEdge->Append(new int(kAcGiVisible)); } else { //最后一边 nLastVertex->nFirstVertexIndex if(nFirstVertexIndex>nLastVertex) pEdge->Append(new int(kAcGiVisible)); else pEdge->Append(new int(kAcGiInvisible)); } lstFaces.Append(pFace); lstEdgeVis.Append(pEdge); nEdgeListLen += pEdge->Length(); nFaceListLen += slopeFace.Length()+1; } *nVerticeNum = lstVertices.Length(); pVerticeList = new XPoint[*nVerticeNum]; for(i=0; i<*nVerticeNum; i++) { pVerticeList[i]=*lstVertices[i]; } *pFaceListLen = nFaceListLen; pFaceList = new Adesk::Int32[nFaceListLen]; Adesk::Int32 *pInt=pFaceList; for(i=0; i *pFace=lstFaces[i]; *pInt = pFace->Length(); pInt ++; for(int j=0; jLength(); j++) { *pInt = *(*pFace)[j]; pInt ++; } } pEdgeVisArray = new Adesk::UInt8[nEdgeListLen]; Adesk::UInt8 *pUInt=pEdgeVisArray; for(i=0; i *pEdge=lstEdgeVis[i]; for(int j=0; jLength(); j++) { *pUInt = *(*pEdge)[j]; pUInt ++; } } return RTNORM; } ////////////////////////////////////////////////////////////////////////// // 求边的描述 // 由调用函数负责释放点表和面表 static int CompareForFindNode(const XIntDotPair *p1, const void *p2) { const XIntDotPair *pp2 = (const XIntDotPair *)p2; if((p1->nFrom==pp2->nFrom && p1->nTo==pp2->nTo) || (p1->nFrom==pp2->nTo && p1->nTo==pp2->nFrom)) return 0; return 1; } int XAecRoof::GetEdgeData(XPointList &lstVertices, DList &lstEdgeData) const { int nTotalFaceNum=m_lstSlopeFaces.Length(); if(!nTotalFaceNum) return RTERROR; for(int i=0; i=3); const XPoint &ptLast=slopeFace[0]; int nLast=0; if(lstVertices.FindPoint(ptLast)) { nLast=lstVertices.CurPosition(); } else { nLast=lstVertices.Length(); lstVertices.Append(new XPoint(ptLast)); } int nFirst=nLast; for(int j=1; j<=slopeFace.Length(); j++) { int nCurIndex=0; if(j==slopeFace.Length()) { nCurIndex = nFirst; } else { const XPoint &ptCur=slopeFace[j]; if(lstVertices.FindPoint(ptCur)) { nCurIndex=lstVertices.CurPosition(); } else { nCurIndex=lstVertices.Length(); lstVertices.Append(new XPoint(ptCur)); } } XIntDotPair edge(nLast, nCurIndex); if(!lstEdgeData.FindNode(&edge, CompareForFindNode)) lstEdgeData.Append(new XIntDotPair(edge)); nLast = nCurIndex; } } return RTNORM; }