#include "stdafx.h" // extern GEOAPI XPface * ConstructPolyFace(const AcDbVoidPtrArray &entSet); // 已经坐标变换到polyClip平面上 BOOL PolyClip3D(XPolygonEx &polySrc, const XPoly2D &polyClip, DList &inSet, DList &outSet) { ASSERT(polySrc.Length()>=3); XVector3D vtNorm; if (polySrc.GetNormal(vtNorm)!=RTNORM) return FALSE; ((AcGeVector3d &)vtNorm).normalize(); double nVal=(vtNorm&XVector3D(0,0,1)); BOOL bVert=(fabs(nVal)<1.0E-6); BOOL nRet=TRUE; if (bVert) { /* int nEdgeNum=0, nInNum=0, nOutNum=0; double nElev=polyClip[0].z; for(int i=0; i0) outSet.Append(new XPolygonEx(polySrc)); else if (nOutNum==0 && nInNum>0) inSet.Append(new XPolygonEx(polySrc)); else */ nRet=FALSE; //求解过程比较复杂,暂时放弃 } else { AcGePlane srcPlane(*polySrc[0], vtNorm); AcGePlane tarPlane((AcGePoint3d &)*polyClip[0], AcGeVector3d(0,0,1)); ASSERT(fabs(polyClip[0].z)<_DIST_SNAP); // 被裁剪面投影到裁剪区域平面内,并设置z=0 XPoly2D poly2d(1); for(int i=0; i lstInSide, lstOutSide; TchSubExport::Intersect(poly2d, polyClip, lstInSide); TchSubExport::Subtract(poly2d, polyClip, lstOutSide); for(int m=0; m<2; m++) { DList &lstRegion=m? lstOutSide : lstInSide; DList &lstSet=m? outSet : inSet; for(int k=0; k1.0E-6) polyReg.Reverse(); XPolygonEx *pNewReg=new XPolygonEx; for(int i=0; i0? polySrc.IsVisible(abs(nHitFlag)-1) : TRUE); XPoint ptNew=((AcGePoint3d &)seg.StartPoint()).project(srcPlane, AcGeVector3d(0,0,1)); pNewReg->AppendNode(ptNew, bVis); } lstSet.Append(pNewReg); } } } return nRet; } // 坐标变换不正确,应当使用投影的方法 BOOL PolyClip3DFace(const AcDbPolyline &plane, const AcDbFace &face, AcDbVoidPtrArray &inSet, AcDbVoidPtrArray &outSet) { //extern GEOAPI void Trianglize(const XPolygonEx &poly2d, DList &lstFace); AcGePoint3d ptArray[4]; Adesk::Boolean visArray[4]; for(int i=0; i<4; i++) { VERIFY(face.getVertexAt(i, ptArray[i])==Acad::eOk); VERIFY(face.isEdgeVisibleAt(i, visArray[i])==Acad::eOk); } BOOL bTri=FALSE; for(i=0; i<4; i++) { int j=i+1; if (j==4) j=0; if (ptArray[i].distanceTo(ptArray[j])<_DIST_SNAP) { switch(j) { case 1: //消除第1顶点 ptArray[1]=ptArray[2]; ptArray[2]=ptArray[3]; visArray[0]=visArray[1]; visArray[1]=visArray[2]; visArray[2]=visArray[3]; break; case 2: //消除第2顶点 ptArray[2]=ptArray[3]; visArray[1]=visArray[2]; visArray[2]=visArray[3]; break; case 3: //消除第3顶点 visArray[2]=visArray[3]; break; } bTri=TRUE; break; } } XPoly2D polyClip; PolyConvert(plane, polyClip); XVector3D vtNormal; (AcGeVector3d &)vtNormal=plane.normal(); polyClip.SetElevation(0.0); int nLen=(bTri? 3 : 4); XPolygonEx polySrc; for(i=0; i frontSet, backSet; BOOL bRet=PolyClip3D(polySrc, polyClip, frontSet, backSet); if (!bRet) return bRet; for(int m=0; m<2; m++) { DList &lstSet=m? backSet : frontSet; int nCount=lstSet.Length(); for(int n=0; nLength(); k++) { *(*pRegion)[k]=Ecs2Wcs(*(*pRegion)[k], vtNormal); } DList lstFaces(0); Trianglize(*pRegion, lstFaces); for(k=0; ksetPropertiesFrom(&face); if (m==0) inSet.append(pFace); else outSet.append(pFace); } */ DList lstTris; double nElev=(*pRegion)[0]->z; pRegion->SetElevation(0.0); if (pRegion->Trianglize(lstTris, TRUE)==RTNORM) { for(int k=0; km_nFlag&SIDE1_INVISIBLE); Adesk::Boolean bSide2=!(triangle->m_nFlag&SIDE2_INVISIBLE); Adesk::Boolean bSide3=!(triangle->m_nFlag&SIDE3_INVISIBLE); triangle->vertex1.z=triangle->vertex2.z=triangle->vertex3.z=nElev; XPoint pt1=Ecs2Wcs(triangle->vertex1, vtNormal); XPoint pt2=Ecs2Wcs(triangle->vertex2, vtNormal); XPoint pt3=Ecs2Wcs(triangle->vertex3, vtNormal); AcDbFace *pFace=new AcDbFace(pt1, pt2, pt3, pt1, bSide1, bSide2, bSide3); pFace->setPropertiesFrom(&face); if (m==0) inSet.append(pFace); else outSet.append(pFace); } } } } return TRUE; } // 3DFace的裁剪 BOOL Clip3DFace(const AcGePlane &plane, const AcGePoint3d *ptArray, const Adesk::Boolean *visArray, BOOL bTri, AcDbVoidPtrArray &frontSet, AcDbVoidPtrArray &backSet) { AcGeVector3d vtNormal=plane.normal(); XPoint *ptArray1=(XPoint *)ptArray; XVector3D vtNorm; CT_vector_plan3p(ptArray1[0], ptArray1[1], ptArray1[2], vtNorm); AcGePlane plan1(ptArray[0], vtNorm); AcGeLine3d line; if (!plane.intersectWith(plan1, line)) { return FALSE; } // 用交线和3DFACE的边求交。 int nVertice=(bTri? 3 : 4); int nIntFlag1=0, nIntFlag2=0; // 在顶点则为负(-idx-1),在边则为正(idx+1) AcGePoint3d ptInt1, ptInt2; for(int i=0; i0) poly1.AppendNode(ptInt2, TRUE); // nFlag2~nFlag1, poly2 for(n=abs(nIntFlag2)-1; n<=abs(nIntFlag1)-1+nVertice; n++) { if (n==abs(nIntFlag2)-1) poly2.AppendNode(ptInt2, visArray[DePeriod(nVertice, n)]); else if (n==abs(nIntFlag1)-1+nVertice && nIntFlag2<0) poly2.AppendNode(ptInt1, TRUE); else poly2.AppendNode(ptArray[DePeriod(nVertice,n)], visArray[DePeriod(nVertice,n)]); } if (nIntFlag1>0) poly2.AppendNode(ptInt1, TRUE); } else { return FALSE; } XPoint ptMid; Midpoint(ptInt1, ptInt2, ptMid); for(int nSide=0; nSide<2; nSide++) { XPolygonEx &poly2d=(nSide? poly2 : poly1); if (poly2d.Length()>=3) { XPoint ptCen1; poly2d.Center(ptCen1); XVector3D vt1=ptCen1-ptMid; XVector3D vt2; (AcGeVector3d &)vt2=vtNormal; double nVal=(vt1&vt2); BOOL bFrontSet=(nVal>0.0); if (poly2d.Length()>=5) { DList lstTris; if (poly2d.Trianglize(lstTris, TRUE)==RTNORM) { for(int n=0; nm_nFlag&SIDE1_INVISIBLE); Adesk::Boolean bSide2=!(triangle->m_nFlag&SIDE2_INVISIBLE); Adesk::Boolean bSide3=!(triangle->m_nFlag&SIDE3_INVISIBLE); AcDbFace *pFace=new AcDbFace(triangle->vertex1, triangle->vertex2, triangle->vertex3, triangle->vertex1, bSide1, bSide2, bSide3); if (bFrontSet) frontSet.append(pFace); else backSet.append(pFace); } } } else { AcDbFace *pFace=NULL; if (poly2d.Length()==3) { pFace=new AcDbFace(*poly2d[0], *poly2d[1], *poly2d[2], *poly2d[0], poly2d.IsVisible(0), poly2d.IsVisible(1), poly2d.IsVisible(2)); } else { pFace=new AcDbFace(*poly2d[0], *poly2d[1], *poly2d[2], *poly2d[3], poly2d.IsVisible(0), poly2d.IsVisible(1), poly2d.IsVisible(2), poly2d.IsVisible(3)); } if (bFrontSet) frontSet.append(pFace); else backSet.append(pFace); } } } return TRUE; } // 用面裁剪3dface BOOL Clip3DFace(const AcGePlane &plane, const AcDbFace &face, AcDbVoidPtrArray &frontSet, AcDbVoidPtrArray &backSet) { XPlane planeMe; // [2010-3-16 9:34 wubo] 移植到新Geo库 // plane.getCoefficients(planeMe.a, planeMe.b, planeMe.c, planeMe.d); double dParaA = planeMe.GetParaA(); double dParaB = planeMe.GetParaB(); double dParaC = planeMe.GetParaC(); double dParaD = planeMe.GetParaD(); plane.getCoefficients(dParaA, dParaB, dParaC, dParaD); planeMe.SetParaA(dParaA); planeMe.SetParaB(dParaB); planeMe.SetParaC(dParaC); planeMe.SetParaD(dParaD); X3DFace faceMe(face); DList upFaces, downFaces; BOOL bOk=faceMe.SectByPlane(planeMe, upFaces, downFaces); for(int kk=0; kkAsDbFace()); } for(kk=0; kkAsDbFace()); } return bOk; AcGePoint3d ptArray[4]; Adesk::Boolean visArray[4]; for(int i=0; i<4; i++) { VERIFY(face.getVertexAt(i, ptArray[i])==Acad::eOk); VERIFY(face.isEdgeVisibleAt(i, visArray[i])==Acad::eOk); } BOOL bTri=FALSE; for(i=0; i<4; i++) { int j=i+1; if (j==4) j=0; if (ptArray[i].distanceTo(ptArray[j])<_DIST_SNAP) { switch(j) { case 1: //消除第1顶点 ptArray[1]=ptArray[2]; ptArray[2]=ptArray[3]; visArray[0]=visArray[1]; visArray[1]=visArray[2]; visArray[2]=visArray[3]; break; case 2: //消除第2顶点 ptArray[2]=ptArray[3]; visArray[1]=visArray[2]; visArray[2]=visArray[3]; break; case 3: //消除第3顶点 visArray[2]=visArray[3]; break; } bTri=TRUE; break; } } if (bTri) { if ((XPoint(ptArray[2])&XLine(XPoint(ptArray[0]), XPoint(ptArray[1])))!=PR_OUTSIDE) return FALSE; //共线 } BOOL bRet=Clip3DFace(plane, ptArray, visArray, bTri, frontSet, backSet); if (!bRet) { XPoint ptCen; ptCen.x=(ptArray[0].x+ptArray[1].x+ptArray[2].x)/3.0; ptCen.y=(ptArray[0].y+ptArray[1].y+ptArray[2].y)/3.0; ptCen.z=(ptArray[0].z+ptArray[1].z+ptArray[2].z)/3.0; // 平行平面 XPoint pt=ptArray[0].orthoProject(plane); XVector3D vt1=ptCen-pt; XVector3D vt2; AcGeVector3d vtNormal=plane.normal(); (AcGeVector3d &)vt2=vtNormal; double nVal=(vt1&vt2); BOOL bFrontSet=(nVal>0.0); AcDbFace *pFace=(AcDbFace *)face.clone(); if (bFrontSet) frontSet.append(pFace); else backSet.append(pFace); bRet = TRUE; } int nCount=frontSet.length(); for(int n=0; nsetPropertiesFrom(&face); } nCount=backSet.length(); for(n=0; nsetPropertiesFrom(&face); } return bRet; } // Command: 平面切割 void Clip3D() { PickSet ss(SS_FREE); RBList mask=ads_buildlist(RTDXF0, _T("3DSOLID,REGION,3DBODY,3DFACE,POLYLINE,LINE,ARC,CIRCLE"), NULL); if (SelectEntities(_T("\n选择待切割的三维对象:"), ss, mask)!=RTNORM) return; XPoint pt1, pt2; int nRetCode; //INITGET_BEG(0, _T("P")); nRetCode=ads_getpoint(NULL, _T("\n切割线第一点<退出>:"), pt1); //INITGET_END(); if (nRetCode!=RTNORM && nRetCode!=RTKWORD) return; AcDbPolyline *pClip=NULL; AcGePlane plane; if (nRetCode==RTKWORD) { RBList mask(RTDXF0, _T("LWPOLYLINE"), 70, 1, NULL); Entity entPoly; if (entPoly.FilterSelect(_T("\n选择作为裁剪边界的封闭多段线<退出>:"), mask)!=RTNORM) return; OPENOBJ_BEGIN(entPoly, AcDb::kForRead, AcDbPolyline, pLine); ASSERT(pLine); pClip=(AcDbPolyline*)pLine->clone(); OPENOBJ_END(); } else { if (XGetPoint(pt1, _T("\n切割线第二点"), pt2)!=RTNORM) return; XVector3D vt1=pt2-pt1; vt1=Ucs2Wcs(vt1, TRUE); XVector3D vt0(0,0,1); vt0=Ucs2Wcs(vt0, TRUE); XVector3D vt2=vt0*vt1; plane=AcGePlane((const AcGePoint3d &)Ucs2Wcs(pt1), (const AcGeVector3d &)vt2); } long lCount=ss.Length(); for(long i=0; iisA()==AcDbFace::desc()) { if (pClip) PolyClip3DFace(*pClip, *(AcDbFace *)pEnt, frontSet, backSet); else Clip3DFace(plane, *(AcDbFace *)pEnt, frontSet, backSet); } else if (pEnt->isKindOf(AcDbCurve::desc())) { double nThickness=0.0; if (pEnt->isA()==AcDbLine::desc()) nThickness=((AcDbLine *)pEnt)->thickness(); else if (pEnt->isA()==AcDbArc::desc()) nThickness=((AcDbArc *)pEnt)->thickness(); else if (pEnt->isA()==AcDbCircle::desc()) nThickness=((AcDbCircle *)pEnt)->thickness(); else if (pEnt->isA()==AcDbPolyline::desc()) nThickness=((AcDbPolyline *)pEnt)->thickness(); else if (pEnt->isA()==AcDb2dPolyline::desc()) nThickness=((AcDb2dPolyline *)pEnt)->thickness(); if (nThickness>_DIST_SNAP) { AcDbVoidPtrArray entSet; InitModel(prop, pEnt, NULL, entSet); int num=entSet.length(); for(int n=0; nisA()==AcDbFace::desc()) { if (pClip) { if (!PolyClip3DFace(*pClip, *(AcDbFace *)pFace, frontSet, backSet)) { entSet0.append(pFace->clone()); } } else Clip3DFace(plane, *(AcDbFace *)pFace, frontSet, backSet); } } ReleaseEntSet(entSet); } } else { AcDbVoidPtrArray entSet; InitModel(prop, pEnt, NULL, entSet); int num=entSet.length(); for(int n=0; nisA()==AcDbFace::desc()) { if (pClip) { if (!PolyClip3DFace(*pClip, *(AcDbFace *)pFace, frontSet, backSet)) { entSet0.append(pFace->clone()); } } else Clip3DFace(plane, *(AcDbFace *)pFace, frontSet, backSet); } } ReleaseEntSet(entSet); } if (frontSet.length()>0 || backSet.length()>0) { if (pEnt->upgradeOpen()==Acad::eOk) { pEnt->erase(); pEnt->downgradeOpen(); // 不能裁剪的变成单独的PFACE/3DFACE for(int nn=0; nn<3; nn++) { AcDbVoidPtrArray *pEntSet=NULL; if (nn==0) pEntSet=&entSet0; else if (nn==1) pEntSet=&frontSet; else pEntSet=&backSet; AcDbVoidPtrArray &eSet=*pEntSet; int num=eSet.length(); if (num>1) { XPface *pFace=ConstructPolyFace(eSet); if (pFace) { pFace->Make(); Entity entLast; entLast.GetLast(); OPENOBJ_BEGIN(entLast, AcDb::kForWrite, AcDbEntity, pLast); if (pLast) pLast->setPropertiesFrom(pEnt); OPENOBJ_END(); delete pFace; } ReleaseEntSet(eSet); } else if (num==1){ AcDbEntity *pFace=(AcDbFace *)eSet[0]; pFace->setPropertiesFrom(pEnt); AddToCurrentSpace(pFace, Adesk::kTrue); } } } else { ReleaseEntSet(frontSet); ReleaseEntSet(backSet); ReleaseEntSet(entSet0); } } else { ReleaseEntSet(frontSet); ReleaseEntSet(backSet); ReleaseEntSet(entSet0); } OPENOBJ_END(); } if (pClip) delete pClip; } // Command: 区域封面 void Poly2Face() { Entity entPoly; if (SelectEntity(_T("\n选择封闭的多段线<退出>: "), entPoly, RBList(RTDXF0, _T("POLYLINE,LWPOLYLINE"), 70, 1, NULL))==RTNORM) { XPoly2D poly2d(entPoly); XPoly poly1; poly2d.MapToPolygon1(poly1, _AS_SYS_UNIT(g_nCirDeviation)); XPolygonEx polyEx(poly1); XTrianglePface lstTris; if (polyEx.Trianglize(lstTris, TRUE)==RTNORM) { lstTris.MakePolyface(); adsout << _T("\n成功的转成面!"); } } }