#include "stdafx.h" #include "resource.h" //add by xlc on 070712 //求线与线的交点 BOOL GetLineIntPoint(AcDbCurve *projLine,AcGePoint3d ptStart,AcGePoint3d ptEnd,AcGePoint3d &ptInt) { AcDbLine line(ptStart,ptEnd); AcGePoint3dArray points; if (projLine != NULL) projLine->intersectWith(&line, AcDb::kOnBothOperands, points); if (points.length() > 0) { ptInt = points.at(0); return TRUE; } return FALSE; } //add by xlc on 070712 //获得线段与屋顶面边线的投影交点 void GetLineIntSectPoint(DList &lstFace, //[in]屋顶面 XLine xLine, //[in]线段 XPoly3D &poly //[out]投影点数组 ) { int num = lstFace.Length(); for(int i = 0; i < lstFace.Length(); i++) //获得直线所在平面与投影面的交点 { AcDbLine line(xLine.StartPoint(),xLine.EndPoint()); X3DFace face(*lstFace[i]); face.MakeBetter(); AcGePlane roof(AcGePoint3d(face.GetVertex(0)),AcGePoint3d(face.GetVertex(1)),AcGePoint3d(face.GetVertex(2))); AcDbCurve *projLine = NULL; //在face平面上的投影线 line.getProjectedCurve(roof, AcGeVector3d::kZAxis, projLine); if (projLine != NULL) { AcGePoint3d ptInt; //平面与face面交线与face边的交点 if (GetLineIntPoint(projLine,AcGePoint3d(face.GetVertex(0)),AcGePoint3d(face.GetVertex(1)),ptInt) && face.IsVisible(0)) poly.AppendNode(ptInt); if (GetLineIntPoint(projLine,AcGePoint3d(face.GetVertex(1)),AcGePoint3d(face.GetVertex(2)),ptInt) && face.IsVisible(1)) poly.AppendNode(ptInt); if (!face.IsTriangle(2)) { if (GetLineIntPoint(projLine,AcGePoint3d(face.GetVertex(2)),AcGePoint3d(face.GetVertex(3)),ptInt) && face.IsVisible(2)) poly.AppendNode(ptInt); if (GetLineIntPoint(projLine,AcGePoint3d(face.GetVertex(3)),AcGePoint3d(face.GetVertex(0)),ptInt) && face.IsVisible(3)) poly.AppendNode(ptInt); } else { if (GetLineIntPoint(projLine,AcGePoint3d(face.GetVertex(2)),AcGePoint3d(face.GetVertex(0)),ptInt) && face.IsVisible(2)) poly.AppendNode(ptInt); } delete projLine; } } } //add by xlc on 070712 //获得线段在屋顶面上的投影点 //返回值:TRUE,成功;FALSE,失败 BOOL GetLineEndIntSectPoint(DList &lstFace, //[in]屋顶面 XLine xLine, //[in]线段 XPoint &start, //[out]xLine线起点的投影点 XPoint &end //[out]xLine线终点的投影点 ) { int posS = 0,posE = 0; //face在链表中的位置 XPoint ptStart(xLine.StartPoint().x,xLine.StartPoint().y,0), ptEnd(xLine.EndPoint().x,xLine.EndPoint().y,0); BOOL bFindS = FALSE,bFindE = FALSE; //是否找到起始点所在的face //找线段端点所在的face for(int i = 0; i < lstFace.Length(); i++) { AcGePoint3d pt; XPoly2D polyFace(1); X3DFace face(*lstFace[i]); face.MakeBetter(); for(int j = 0; j < 3; j++) { pt = face.GetVertex(j); polyFace.AppendNode(pt); } if (!face.IsTriangle(2))//四边形 { pt = face.GetVertex(3); polyFace.AppendNode(pt); } polyFace.SetElevation(0.0); //投影到z=0的平面上 if (!bFindS) { if ( (ptStart & polyFace) != PR_OUTSIDE) { posS = i; bFindS = TRUE; } } if (!bFindE) { if ( (ptEnd & polyFace) != PR_OUTSIDE) { posE = i; bFindE = TRUE; } } if (bFindS && bFindE) break; } //线段端点上的face面 if (bFindS) { X3DFace pFace(*lstFace[posS]); pFace.MakeBetter(); AcGePlane sPlane(AcGePoint3d(pFace.GetVertex(0)), AcGePoint3d(pFace.GetVertex(1)),AcGePoint3d(pFace.GetVertex(2))); AcGePoint3d tmp = xLine.StartPoint(); tmp.z += _AS_SYS_UNIT(1000.0);// [11/15/2007 nsh] AcGeLine3d sLine(AcGePoint3d(xLine.StartPoint()),tmp); sLine.intersectWith(sPlane,start); //modify by xlc on 080303 部分在屋顶外边简单处理 if (!bFindE) { end = xLine.EndPoint(); end.z = start.z; } } else //modify by xlc on 080303 部分在屋顶外边简单处理 //{ // return FALSE; //} { if (!bFindE) { return FALSE; } } if (bFindE) { X3DFace pFace(*lstFace[posE]); pFace.MakeBetter(); AcGePlane ePlane(AcGePoint3d(pFace.GetVertex(0)), AcGePoint3d(pFace.GetVertex(1)),AcGePoint3d(pFace.GetVertex(2))); AcGePoint3d tmp = xLine.EndPoint(); tmp.z +=_AS_SYS_UNIT(1000.0);// [11/15/2007 nsh] AcGeLine3d eLine(AcGePoint3d(xLine.EndPoint()),tmp); eLine.intersectWith(ePlane,end); //modify by xlc on 080303 部分在屋顶外边简单处理 if (!bFindS) { start = xLine.StartPoint(); start.z = end.z; } } //modify by xlc on 080303 部分在屋顶外边简单处理 //else //{ // return FALSE; //} return TRUE; } //add by xlc on 070712 //计算平板的高度 BOOL CalSlabMaxHeight(XPoly2D polyOutline, //[in]平板线 double botElev, //[in]平板底标高 double &height, //[in/out]平板高度 DList &lstFace //[in]屋顶面 ) { XPoint start,end; XLine xLine1(*polyOutline[0],*polyOutline[polyOutline.Length()-1]); //modify by xlc on 080303 BOOL bFlag=TRUE; //bFlag为TRUE时为变量height初始化 if (GetLineEndIntSectPoint(lstFace,xLine1,start,end)) //获得线端点的投影点 { if (bFlag) { height = start.z; bFlag = FALSE; } if (height > end.z) height = end.z; XPoly3D poly; GetLineIntSectPoint(lstFace,xLine1,poly); //获得线平面与face平面边线的交点 for(int j = 0; j < poly.Length(); j++) { if (height > poly[j]->z) { height = poly[j]->z; } } } for(int i = 0; i < polyOutline.Length()-1; i++) { XPoly3D poly1; XLine xLine(*polyOutline[i],*polyOutline[i+1]); GetLineIntSectPoint(lstFace,xLine,poly1); for(int j = 0; j < poly1.Length(); j++) { //modify by xlc on 080303 if (bFlag) { height=poly1[j]->z; bFlag=FALSE; } if (height > poly1[j]->z) { height = poly1[j]->z; } } if (!GetLineEndIntSectPoint(lstFace,xLine,start,end)) { //modify by xlc on 080303 部分在屋顶外边简单处理 //return FALSE; continue; } if (height > start.z) height = start.z; if (height > end.z) height = end.z; } height -= _DIST_SNAP; if (height < botElev) { return FALSE; } return TRUE; } //add by xlc on 070712 //线段与屋顶的交线 BOOL GetLineIntSectPoly(DList &lstFace, //[in]屋顶面 XLine xLine, //[in]线段 XPoly3D &poly //[out]交线 ) { GetLineIntSectPoint(lstFace,xLine,poly); //获得线段平面在face平面上的交点 //删除重合点 int ptNum = poly.Length(); for(int i = 0; i < ptNum-1; i++) { for(int j = i+1;j < ptNum;) { if (*poly[i] == *poly[j]) { poly.RemoveNode(j); ptNum--; continue; } j++; } } //排序 Array ptArray; //交点 if (ptNum > 0) { ptArray.Realloc(ptNum); for(long i = 0; i < ptNum; i++) { ptArray[i] = *poly[i]; } bool bIncrease = true; if (fabs(xLine.StartPoint().x - xLine.EndPoint().x) < 1e-6) { if (xLine.StartPoint().y - xLine.EndPoint().y > 0) bIncrease = false; } else { if (xLine.StartPoint().x - xLine.EndPoint().x > 0) bIncrease = false; } ptArray.Arrange(bIncrease); //按线段起点到终点的顺序排序 for(i = 0; i < ptNum; i++) { *poly[i] = ptArray[i]; } } //求线段的起点和终点与face的交点 XPoint start,end; if (!GetLineEndIntSectPoint(lstFace,xLine,start,end)) return FALSE; //添加线段的端点 if (poly.Length() > 0) { if (start != *poly[0]) { poly.InsertNodeAt(0,start); } } else { poly.InsertNodeAt(0,start); } if (end != *poly[poly.Length()-1]) { poly.AppendNode(end); } return TRUE; } //add by xlc on 070712 //获得屋顶向内的面 void GetAllRoofPoly(AcDbObjectId id, //[in]屋顶对象ID DList &lstFace //[out]屋顶向内的面 ) { OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbEntity, pRoof); if (pRoof) { int nFlag = 0; //是否屋顶对象,0:非屋顶对象;1:人字屋顶或攒尖屋顶,矩形屋顶;2:任意屋顶(有内侧缺面) BOOL bRoof = FALSE; //是否可视为屋顶 if (pRoof->isKindOf(TDbDualSlopeRoof::desc()) || pRoof->isKindOf(TDbCuspRoof::desc()) || pRoof->isKindOf(TDbMountRoof::desc()) ) { nFlag = 1; bRoof = TRUE; } else if (pRoof->isKindOf(TDbSlopeRoof::desc())) { nFlag = 2; bRoof = TRUE; } else if (pRoof->isKindOf(AcDbPolyFaceMesh::desc()) || pRoof->isKindOf(AcDbPolygonMesh::desc()) || pRoof->isKindOf(AcDbFace::desc()) ) { bRoof = TRUE; } if (bRoof) { TMasterProperties prop; AcDbVoidPtrArray entSet; int nOldMode=DocGetDrawMode(); DocSetDrawMode(DRAW_3D); if (nFlag == 2) { AcDbEntity *pEnt = (AcDbEntity*)pRoof->clone(); if (pEnt) { double height = _AS_SYS_UNIT(200.0);// [11/15/2007 nsh] AcGeMatrix3d mat; mat.setToTranslation(AcGeVector3d(0,0,-height)); pEnt->upgradeOpen(); pEnt->transformBy(mat); InitModel(prop, pEnt, NULL, entSet); delete pEnt; } } else { InitModel(prop, pRoof, NULL, entSet); } DocSetDrawMode(nOldMode); int nLen=entSet.length(); for(int n=0; nisKindOf(AcDbFace::desc())) { AcDbFace *pFace = AcDbFace::cast(pEnt); if (pFace != NULL) { X3DFace p3DFace(*pFace); XVector3D vtNormal = p3DFace.GetNormal(); if (fabs(vtNormal.z) < 1.0e-6) //立面 continue; if (nFlag == 1) { if (vtNormal.z > 1.0e-6) //人字坡顶或攒尖屋顶向下的面 continue; } else if (nFlag == 2) { if (vtNormal.z < 1.0e-6) //任意坡顶向上的面 continue; } lstFace.Append(new X3DFace(p3DFace)); } } } ReleaseEntSet(entSet); } } OPENOBJ_END(); } //平板对齐屋顶 void SlabAlignRoof() { RBList rbMask1(RTDXF0, _T("TCH_MOUNTROOF,TCH_SLOPEROOF,TCH_CUSPROOF,TCH_DUALROOF,POLYLINE,3DFACE"), NULL); PickSet ssRoofs(SS_FREE); int nRetCode=SelectEntities(_T("\n请选择屋顶:"), ssRoofs, rbMask1); if (nRetCode!=RTNORM) return; RBList rbMask(RTDXF0, _T("TCH_SLAB"), NULL); PickSet ssSlabs(SS_FREE); nRetCode=SelectEntities(_T("\n请选择平板:"), ssSlabs, rbMask); if (nRetCode!=RTNORM) return; DList lstFace; long m = 0; do { AcDbObjectId id; //任意屋顶id if (acdbGetObjectId(id, ssRoofs[m]) != Acad::eOk) { m++; continue; } GetAllRoofPoly(id, lstFace); //获得屋顶的下表面 m++; }while(m < ssRoofs.Length()); if (lstFace.Length() < 1) return; acedSetStatusBarProgressMeter(_T("正在处理中,请稍候..."),1,ssSlabs.Length()); long n = 0; do { acedSetStatusBarProgressMeterPos(n+1); XDbObject obj(ssSlabs[n],AcDb::kForWrite); TDbSlab *pSlab = TDbSlab::cast(obj.m_pObject); XPoly2D polyOutline=pSlab->GetOutline();; double botElev=0,height=0; botElev=pSlab->GetElevation(); if (CalSlabMaxHeight(polyOutline,botElev,height,lstFace)) { pSlab->assertWriteEnabled(); pSlab->SetThickness(height); } n++; } while(n < ssSlabs.Length()); acedRestoreStatusBar(); }