#include "stdafx.h" #include "StdArx.h" #include "AecWall2DJoin.h" #include "AecCoverBooleanOper.h" #include "AcDbX3dSolid.h" #include "AecDbX3dPart.h" #include "KTCADUtilityEx.h" const double g_xjoinR = 400.0; const double g_xjoinCol = 10.0; static const Adesk::UInt16 kRed = 1; static const Adesk::UInt16 kYellow = 2; static const Adesk::UInt16 kGreen = 3; extern AcGePoint3d GetArcMidPoint(AcDbArc* pArc); extern AcDbArc* FormatArc(const AcGePoint3d& ptGe1,const AcGePoint3d& ptGe2,const AcGePoint3d& ptGe3); extern AcGePoint3d MidPoint(const AcGePoint3d& pt1, const AcGePoint3d& pt2); extern Acad::ErrorStatus AddToModelSpace(AcDbEntity* pEnt,AcDbDatabase* pDb = NULL,bool bClose = true); extern void RefreshWallOnOpeningDrawEx(const AcDbObjectId& idWall); extern void transfromRegion(AcDbRegion *pRegion, const AcGePoint3d &ptOnRegion, const AcGeVector3d &vtNormal, const AcGePoint3d &ptOnPlan); //weight = 20 - index const LPCTSTR g_pszWallMaterials[] = { _T("钢筋混凝土"), _T("石材"), _T("砖墙"), _T("填充墙"), _T("玻璃幕墙"),_T("轻质隔墙"),NULL}; AecWall2DJoin::AecWall2DJoin(void) { } AecWall2DJoin::~AecWall2DJoin(void) { ClearBuffer(); } bool AecWall2DJoin::DoStruDraw(bool b3dUnit) { int nBoolUnit = b3dUnit ? TRUE : FALSE; AcDbDatabase* pDb = acdbCurDwg(); if (pDb == NULL) return false; //记录有门窗的墙体 AcDbObjectIdArray arWallIds; Acad::ErrorStatus es; AcDbBlockTable* pTbl = NULL; if ( Acad::eOk == (es = pDb->getBlockTable(pTbl,AcDb::kForRead))) { AcDbBlockTableRecord* pRec = NULL; if ( Acad::eOk == (es = pTbl->getAt(ACDB_MODEL_SPACE,pRec,AcDb::kForRead))) { AcDbBlockTableRecordIterator* pIt = NULL; pRec->newIterator(pIt); if (pIt != NULL) { AcDbEntity* pEnt = NULL; for (pIt->start();!pIt->done();pIt->step()) { if ( Acad::eOk == (es = pIt->getEntity(pEnt,AcDb::kForWrite) ) ) { AecDbXWall* pWall = AecDbXWall::cast(pEnt); if (pWall != NULL) { if (!b3dUnit) { pWall->RemoveAddtionShow3dPart(0); pWall->RemoveAddtionShow3dPart(1); } //设置三维融合标志 pWall->GetSpecialtyData()->SetAt(KEY_3DSHOW,nBoolUnit); pWall->ReCreateDraw3d(); if (!b3dUnit) { pWall->ClearForDraw2dables(); AecComplexCurve draw2d; pWall->GetStandardDraw2d(draw2d); pWall->SetDraw2dables(draw2d); if (pWall->GetAssocPartCount() > 0) { arWallIds.append(pWall->objectId()); } pWall->ReCreateDraw3d(); } /*if (nRlt == 0)//不保留 { pWall->ClearForDraw2dables(); AecComplexCurve draw2d; pWall->GetStandardDraw2d(draw2d); pWall->SetDraw2dables(draw2d); if (pWall->GetAssocPartCount() > 0) { arWallIds.append(pWall->objectId()); } pWall->ReCreateDraw3d(); } else//三维融合 { pWall->ReCreateDraw3d(); }*/ } pEnt->close(); } } delete pIt; } pRec->close(); } pTbl->close(); } //墙上门窗的裁剪 AcDbObjectId idWall; for (int i = 0;i < arWallIds.length();i++) { idWall = arWallIds.at(i); RefreshWallOnOpeningDrawEx(idWall); } return true; } bool AecWall2DJoin::DoStruDraw(AcDbObjectIdArray& arIds,bool b3dUnit) { int nBoolUnit = b3dUnit ? TRUE : FALSE; //记录有门窗的墙体 AcDbObjectIdArray arWallIds; AcDbEntity* pEnt = NULL; for (int i = 0;i < arIds.length();i++) { if ( Acad::eOk == (acdbOpenAcDbEntity(pEnt,arIds.at(i),AcDb::kForWrite) ) ) { AecDbXWall* pWall = AecDbXWall::cast(pEnt); if (pWall != NULL) { if (!b3dUnit) { pWall->RemoveAddtionShow3dPart(0); pWall->RemoveAddtionShow3dPart(1); } //设置三维融合标志 pWall->GetSpecialtyData()->SetAt(KEY_3DSHOW,nBoolUnit); pWall->ReCreateDraw3d(); if (!b3dUnit) { pWall->ClearForDraw2dables(); if (pWall->GetAssocPartCount() > 0) { arWallIds.append(arIds.at(i)); } pWall->ReCreateDraw3d(); } /*if (nRlt == 0)//不保留 { pWall->ClearForDraw2dables(); AecComplexCurve draw2d; pWall->GetStandardDraw2d(draw2d); pWall->SetDraw2dables(draw2d); if (pWall->GetAssocPartCount() > 0) { arWallIds.append(pWall->objectId()); } pWall->ReCreateDraw3d(); } else//三维融合 { pWall->ReCreateDraw3d(); }*/ } pEnt->close(); } } //墙上门窗的裁剪 AcDbObjectId idWall; for (int i = 0;i < arWallIds.length();i++) { idWall = arWallIds.at(i); RefreshWallOnOpeningDrawEx(idWall); } return true; } bool AecWall2DJoin::DoWall2DDraw(AcDbObjectIdArray& arIds) { BuildXTJoins(arIds); DoWall2DJoin(); return true; } void AecWall2DJoin::ClearBuffer() { m_arXJoins.removeAll(); m_arTJoins.removeAll(); m_arIntJoins.removeAll(); m_arIDsWallHasOpening.removeAll(); m_arWallExtends.removeAll(); for (int i = 0;i < m_arCmplPtrs.length();i++) { AecComplexCurve* pCmpl = m_arCmplPtrs.at(i); if (pCmpl != NULL) delete pCmpl; } m_arCmplPtrs.removeAll(); CString sKey; AcDbCurve* pValue = NULL; for (POSITION ps = m_mapIdToPtr.GetStartPosition();ps != NULL;) { pValue = NULL; m_mapIdToPtr.GetNextAssoc(ps,sKey,(void*&)pValue); if (pValue != NULL) delete pValue; } m_mapIdToPtr.RemoveAll(); } bool AecWall2DJoin::ColumnAssocWall(ColEnd& ce,WallEnd& weT) { bool bAssoc = false; if (ce.pColCmpl != NULL && weT.pWallCmpl != NULL) { AcDbCurve* pCurve1 = NULL; AcDbCurve* pCurve2 = NULL; AcGePoint3dArray arPts; for (int i = 0;i < ce.pColCmpl->length();i++) { pCurve1 = ce.pColCmpl->segat(i); for (int j = 0;j < weT.pWallCmpl->length();j++) { pCurve2 = weT.pWallCmpl->segat(j); pCurve1->intersectWith(pCurve2,AcDb::kOnBothOperands,AcGePlane::kXYPlane,arPts); if ( !arPts.isEmpty() ) { bAssoc = true; break; } delete pCurve2; } if (bAssoc) { delete pCurve1; break; } delete pCurve1; } } return bAssoc; } bool AecWall2DJoin::ColumnAssocWall(ColEnd& ce,WallLn& weT) { bool bAssoc = false; if (ce.pColCmpl != NULL && weT.pWallCmpl != NULL) { AcDbCurve* pCurve1 = NULL; AcDbCurve* pCurve2 = NULL; AcGePoint3dArray arPts; for (int i = 0;i < ce.pColCmpl->length();i++) { pCurve1 = ce.pColCmpl->segat(i); for (int j = 0;j < weT.pWallCmpl->length();j++) { pCurve2 = weT.pWallCmpl->segat(j); pCurve1->intersectWith(pCurve2,AcDb::kOnBothOperands,AcGePlane::kXYPlane,arPts); if ( !arPts.isEmpty() ) { bAssoc = true; break; } delete pCurve2; } if (bAssoc) { delete pCurve1; break; } delete pCurve1; } } return bAssoc; } bool AecWall2DJoin::ColumnAssocWall(ColEnd& ce,AcGePoint3d& ptPos) { bool bAssoc = false; if ( ce.pColCmpl != NULL) { AcDbCurve* pCurve1 = NULL; AcDbRay ray; ray.setBasePoint(ptPos); ray.setUnitDir(AcGeVector3d::kXAxis); AcGePoint3dArray arPts; for (int i = 0;i < ce.pColCmpl->length();i++) { pCurve1 = ce.pColCmpl->segat(i); ray.intersectWith(pCurve1,AcDb::kOnBothOperands,AcGePlane::kXYPlane,arPts); if (!arPts.isEmpty()) { bAssoc = true; } delete pCurve1; } } return bAssoc; } bool AecWall2DJoin::BuildXTJoins(AcDbObjectIdArray& arIds) { ClearBuffer(); WallData wdata; AcGePoint3d ptSta,ptEnd,ptInt; WallEnd wallEnd; wallEnd.dParamOnM = 0.0; wallEnd.pWallCmpl = NULL; WallLn wallLn; wallLn.nType = 0; AcArray arWallLns; WallIntJoin wallInt; ColEnd colEnd; colEnd.pColCmpl = NULL; AcArray arColEnds; AcArray arWallEnds; //用于标识id1,id2的标识值 CPoint pt; AcArray arIdIds; Adesk::IntDbId nStartRef = 0;//参考最小的ID = BlockTable id AcDbEntity* pEnt = NULL; for (int i = 0;i < arIds.length();i++) { if ( Acad::eOk == acdbOpenAcDbEntity(pEnt,arIds.at(i),AcDb::kForRead)) { AecDbXWall* pWall = AecDbXWall::cast(pEnt); if (pWall != NULL) { pWall->upgradeOpen(); pWall->GetStandardDraw2d(); pWall->downgradeOpen(); ptSta = GetWallStartPoint(pWall); ptEnd = GetWallEndPoint(pWall); pWall->GetWallData(wdata); if (ptSta.distanceTo(ptEnd) < 100.0) { pEnt->close(); continue; } wallEnd.pWallCmpl = new AecComplexCurve; m_arCmplPtrs.append(wallEnd.pWallCmpl); pWall->GetDraw2dables(*wallEnd.pWallCmpl); wallEnd.id = pEnt->objectId(); wallEnd.ptEnd = ptSta; wallEnd.dThick = wdata.dThick; wallEnd.vtEnd = GetWallFirstDeriv(pWall,ptSta); wallEnd.vtEnd.negate();//向外 wallEnd.nWallWeight = MaterialWeight(wdata.szMat); AppendWallEnd(wallEnd,0); arWallEnds.append(wallEnd); wallEnd.ptEnd = ptEnd; wallEnd.vtEnd = GetWallFirstDeriv(pWall,ptEnd); AppendWallEnd(wallEnd,1); arWallEnds.append(wallEnd); wallLn.nType = 0; wallLn.ptGe[0] = ptSta; wallLn.ptGe[1] = ptEnd; wallLn.ptGe[2] = ptEnd; wallLn.dThick= wdata.dThick; wallLn.nWallWeight = wallEnd.nWallWeight; wallLn.id = pEnt->objectId(); if (pWall->IsArcBaseCurve()) { AcDbArc* pArc = AcDbArc::cast(pWall->GetNativeCurve()); wallLn.nType = 1; wallLn.ptGe[1] = GetArcMidPoint(pArc); } wallLn.pWallCmpl = wallEnd.pWallCmpl; arWallLns.append(wallLn); if (pWall->GetAssocPartCount() > 0) { m_arIDsWallHasOpening.append(wallLn.id); } } AecDbColumn* pCol = AecDbColumn::cast(pEnt); if (pCol != NULL) { pCol->getStartPoint(ptSta); ptSta.z = 0.0;//投影 colEnd.pColCmpl = new AecComplexCurve; m_arCmplPtrs.append(colEnd.pColCmpl); pCol->GetDraw2dables(*colEnd.pColCmpl); colEnd.ptPos = ptSta; colEnd.id = pEnt->objectId(); arColEnds.append(colEnd); } pEnt->close(); } } //柱子关联墙体 for (int i = 0;i < arColEnds.length();i++) { ColEnd& colE = arColEnds.at(i); for (int j = 0;j < arWallLns.length();j++) { WallLn& waL = arWallLns.at(j); if (ColumnAssocWall(colE,waL)) { ColOnWall colWall; colWall.idCol = colE.id; colWall.ptPos = colE.ptPos; colWall.idWall = waL.id; colWall.pColCmpl = colE.pColCmpl; m_arColOnWall.append(colWall); } } } //然后构建T结构 for (int i = 0;i < arWallEnds.length();i++) { WallEnd we = arWallEnds.at(i); //找到搭边的实体 for (int ii = 0;ii < arWallLns.length();ii++) { WallLn& wl = arWallLns.at(ii); //判断是否 搭边 T 结构 if (IsTJoin(we,wl)) { if ( we.idCol.isValid() ) { AppendWallTJoin(wl.id,we,wl.nWallWeight); //一端只搭一个墙体,所以去除这个 arWallEnds.removeAt(i); i -= 1; break; } else { if (we.id != wl.id) { AppendWallTJoin(wl.id,we,wl.nWallWeight); //一端只搭一个墙体,所以去除这个 arWallEnds.removeAt(i); i -= 1; break; } } } else//有可能是相交结构 { if (wl.id != we.id) { if (wl.id.asOldId() < we.id.asOldId()) { pt.x = (LONG)(wl.id.asOldId() - nStartRef); pt.y = (LONG)(we.id.asOldId() - nStartRef); } else { pt.x = (LONG)(we.id.asOldId() - nStartRef); pt.y = (LONG)(wl.id.asOldId() - nStartRef); } if (arIdIds.find(pt) == -1) { arIdIds.append(pt);//记下,表示处理过 for (int iii = 0;iii < arWallLns.length();iii++) { WallLn& wl2 = arWallLns.at(iii); if (wl2.id == we.id) { if (IsIntJoin(wl,wl2,ptInt)) { wallInt.id1 = wl.id; wallInt.id2 = we.id; wallInt.ptInt = ptInt; m_arIntJoins.append(wallInt); } break; } } } } } } } if (!m_arIntJoins.isEmpty()) { acutPrintf(_T("\n墙体有相交,需要断开处理!")); } //从X结构中提取==结构 return true; } bool AecWall2DJoin::IsIntJoin(WallLn& wl,WallLn& wl2,AcGePoint3d& ptInt) const { if (wl2.id == wl.id)//自己不交自己 return false; AcGePoint3dArray arPts; if (wl.nType == 0 && wl2.nType == 0)//line { AcDbLine ln1(wl.ptGe[0],wl.ptGe[1]); AcDbLine ln2(wl2.ptGe[0],wl2.ptGe[1]); ln1.intersectWith(&ln2,AcDb::kOnBothOperands,arPts); if (!arPts.isEmpty()) { ptInt = arPts.first(); } return !arPts.isEmpty(); } else { if (wl.nType == 0) { AcDbLine ln1(wl.ptGe[0],wl.ptGe[1]); AcDbArc* pArc = FormatArc(wl2.ptGe[0],wl2.ptGe[1],wl2.ptGe[2]); if (pArc != NULL) { pArc->intersectWith(&ln1,AcDb::kOnBothOperands,arPts); delete pArc; } } else { AcDbLine ln2(wl2.ptGe[0],wl2.ptGe[1]); AcDbArc* pArc = FormatArc(wl.ptGe[0],wl.ptGe[1],wl.ptGe[2]); if (pArc != NULL) { pArc->intersectWith(&ln2,AcDb::kOnBothOperands,arPts); delete pArc; } } if (!arPts.isEmpty()) { ptInt = arPts.first(); } } return !arPts.isEmpty(); } bool AecWall2DJoin::IsTJoin(WallEnd& we,WallLn& wl) const { if (we.id == wl.id)//自己不搭自己 return false; if (wl.nType == 0)//line { AcDbLine ln(wl.ptGe[0],wl.ptGe[1]); AcGeVector3d vtL = wl.ptGe[1] - wl.ptGe[0]; AcGePoint3d ptOn; ln.getClosestPointTo(we.ptEnd,ptOn,Adesk::kFalse); //如果落到端点,则不是T结构 if (ptOn.distanceTo(wl.ptGe[0]) < 1.e-1 || ptOn.distanceTo(wl.ptGe[1]) < 1.e-1) { return false; } double dDis = ptOn.distanceTo(we.ptEnd); if ( (dDis - __min(wl.dThick,we.dThick)) < 1.e-6)//1个墙厚 { if (we.vtEnd.isParallelTo(vtL)) return false; ln.getParamAtPoint(ptOn,we.dParamOnM); return true; } } else if (wl.nType == 1) { AcDbArc* pArc = FormatArc(wl.ptGe[0],wl.ptGe[1],wl.ptGe[2]); if (pArc != NULL) { AcGePoint3d ptOn; pArc->getClosestPointTo(we.ptEnd,ptOn, Adesk::kFalse); double dDis = ptOn.distanceTo(we.ptEnd); if ( (dDis - __min(wl.dThick,we.dThick)) < 1.e-6)//1 个墙厚 { pArc->getParamAtPoint(ptOn,we.dParamOnM); delete pArc; return true; } delete pArc; } } return false; } void AecWall2DJoin::AppendWallTJoin(AcDbObjectId& idMain,const WallEnd& we,int nMainWeight) { //有什么快速方法? bool bFind = false; for (int i = 0;i < m_arTJoins.length();i++) { WallTJoin& wtOf = m_arTJoins.at(i); if (wtOf.idMain == idMain) { if (wtOf.nValid < MAX_T_STRS) { wtOf.wes[wtOf.nValid] = we; wtOf.nValid += 1; bFind = true; return; } else { acutPrintf(_T("\n某一面墙体超过上限T型结构!")); } } if (bFind) { break; } } //没有找到 if (!bFind) { WallTJoin wt; if (we.id.isValid() ) { wt.idMain = idMain; wt.nValid = 1; wt.nWallWeight = nMainWeight; wt.wes[0] = we; m_arTJoins.append(wt); } } } bool GetIntPoint(AcGePoint3d& ptJoin,const AcGeVector3d& vtEnd,const AcGePoint3d& ptEnd,const AcGeVector3d& vtEnd2) { AcGeLine3d ln1(ptJoin,vtEnd),ln2(ptEnd,vtEnd2); AcGePoint3d ptInt; if ( ln1.intersectWith(ln2,ptInt) ) { ptJoin = ptInt; return true; } return false; } bool RayIntersectRay(WallXJoin& wallXj,const WallEnd& wallEnd,AcGePoint3d& ptInt) { //考虑和圆弧相切的情况 //避开自交 for (int ii = 0;ii < wallXj.nValid;ii++) { if ( wallXj.ids[ii] == wallEnd.id) { return false; } } if ( wallXj.vtEnd[0].isParallelTo(wallEnd.vtEnd) ) { ptInt = wallEnd.ptEnd; return true; } AcDbRay ray1,ray2; ray1.setUnitDir(-wallXj.vtEnd[0]); ray1.setBasePoint(wallXj.ptJoin); ray2.setUnitDir(-wallEnd.vtEnd); ray2.setBasePoint(wallEnd.ptEnd); AcGePoint3dArray arPts; ray1.intersectWith(&ray2,AcDb::kOnBothOperands,arPts); //TEST /*if (!arPts.isEmpty()) { AddToModelSpace((AcDbEntity*)ray1.clone()); AddToModelSpace((AcDbEntity*)ray2.clone()); }*/ if (!arPts.isEmpty()) { ptInt = arPts.first(); } else { ray1.intersectWith(&ray2,AcDb::kExtendBoth,arPts); if (!arPts.isEmpty()) { ptInt = arPts.first(); double dDis1 = ptInt.distanceTo(wallEnd.ptEnd); double dDis2 = ptInt.distanceTo(wallXj.ptJoin); if (dDis1 < __max(wallEnd.dThick,wallXj.dThick) && dDis2 < __max(wallEnd.dThick,wallXj.dThick) ) { return true; } else { return false; } } } return !arPts.isEmpty(); } void AecWall2DJoin::AppendWallEnd(const WallEnd& wallEnd,int nFlag) { //有什么快速方法? bool bFind = false; bool bSelX = false; double dDis = 0.0; if (m_arXJoins.isEmpty()) { WallXJoin wallXj; wallXj.nValid = 1;//只有一个 wallXj.nWallWeight[0] = wallEnd.nWallWeight; wallXj.ids[0] = wallEnd.id; wallXj.ptJoin = wallEnd.ptEnd; wallXj.vtEnd[0] = wallEnd.vtEnd; wallXj.dThick = wallEnd.dThick; wallXj.dThicks[0] = wallEnd.dThick; m_arXJoins.append(wallXj); return; } //找到最接近的XJ AcGePoint3d ptInt; int nPos = -1; for(int i = 0;i < m_arXJoins.length();i++) { WallXJoin& wallXj = m_arXJoins.at(i); dDis = wallEnd.ptEnd.distanceTo(wallXj.ptJoin); if (dDis < __max(wallEnd.dThick,wallXj.dThick) ) { if (RayIntersectRay(wallXj,wallEnd,ptInt)) { //避开自交 for (int ii = 0;ii < wallXj.nValid;ii++) { if ( wallXj.ids[ii] == wallEnd.id) { bSelX = true; break; } } if (bSelX) continue; nPos = i; } } } bSelX = false; if (nPos > -1 && nPos < m_arXJoins.length()) { WallXJoin& wallXj = m_arXJoins.at(nPos); bFind = false; dDis = wallEnd.ptEnd.distanceTo(wallXj.ptJoin); if (dDis - __max(wallEnd.dThick,wallXj.dThick) < 1.e-6)//-g_xjoinR { //且射线相交,X 结构 //if ( fabs(wallEnd.dThick - wallXj.dThick) < 1.0)//等厚 { //避开自交 for (int ii = 0;ii < wallXj.nValid;ii++) { if ( wallXj.ids[ii] == wallEnd.id) { bSelX = true; break; } } if (!bSelX) { for (int ii = 0;ii < 4;ii++) { if (!wallXj.ids[ii].isValid() ) { wallXj.ids[ii] = wallEnd.id; wallXj.nValid += 1; wallXj.nWallWeight[ii] = wallEnd.nWallWeight; wallXj.vtEnd[ii] = wallEnd.vtEnd; wallXj.dThicks[ii] = wallEnd.dThick; /*if (ii > 0) { if ( !GetIntPoint(wallXj.ptJoin,wallXj.vtEnd[ii-1],wallEnd.ptEnd,wallEnd.vtEnd) )//取交点 { wallXj.ptJoin = MidPoint(wallXj.ptJoin,wallEnd.ptEnd);//取中点 } } else { wallXj.ptJoin = MidPoint(wallXj.ptJoin,wallEnd.ptEnd);//取中点 }*/ wallXj.ptJoin = ptInt; bFind = true; break; } } } } } } if (!bFind)//没有找到,也加入 { WallXJoin wallXj; wallXj.nValid = 1;//只有一个 wallXj.ids[0] = wallEnd.id; wallXj.ptJoin = wallEnd.ptEnd; wallXj.vtEnd[0] = wallEnd.vtEnd; wallXj.dThick = wallEnd.dThick; wallXj.dThicks[0] = wallEnd.dThick; wallXj.nWallWeight[0] = wallEnd.nWallWeight; m_arXJoins.append(wallXj); } } bool AecWall2DJoin::DoWall2DJoin() { //1.处理X结构 for (int i = 0;i < m_arXJoins.length();i++) { WallXJoin& wj = m_arXJoins.at(i); if (wj.idCol.isValid())//有柱子 { //延伸到柱子 ExtendToColumnRegion(wj); } else { //逆时针排序裁剪 if (wj.nValid > 1)//有X结构 { XJoinSortAndTrimByUClock(wj); } } } //2.处理T结构,同时产生T结构的延伸 for (int i = 0;i < m_arTJoins.length();i++) { WallTJoin& wt = m_arTJoins.at(i); TJoinSortAndTrimByMain(wt); } //3.处理T结构的延伸墙体 AcDbEntity* pEntE = NULL; for (int i = 0;i < m_arWallExtends.length();i++) { WallExtend& exd = m_arWallExtends.at(i); if ( Acad::eOk == acdbOpenAcDbEntity(pEntE,exd.idWall,AcDb::kForWrite)) { AecDbXWall* pWallE = AecDbXWall::cast(pEntE); if (pWallE != NULL) { for (int j = 0;j < exd.nEnds;j++) { Extend(pWallE,exd.bExtendSta[j],exd.ptOn[j],exd.vtEnd[j], exd.idMain, exd.nNearSide); } } pEntE->close(); } } //4.门窗裁剪 AcDbObjectId idWall; for(int i = 0;i < m_arIDsWallHasOpening.length();i++) { idWall = m_arIDsWallHasOpening.at(i); RefreshWallOnOpeningDrawEx(idWall); } //5.处理相交结构 IntJoinsBoolSubtract(); //6.墙体裁剪柱子 for (int i = 0;i < m_arColOnWall.length();i++) { ColOnWall& colWall = m_arColOnWall.at(i); ColumnClipWall(colWall); } return true; } void AecWall2DJoin::ColumnClipWall(ColOnWall& colWall) { AcDbEntity* pEnt = NULL; if ( Acad::eOk == acdbOpenAcDbEntity(pEnt,colWall.idWall,AcDb::kForWrite)) { AecDbXWall* pWall = AecDbXWall::cast(pEnt); if (pWall != NULL) { //进行类似遮挡处理 AecComplexCurve draw2d; pWall->GetDraw2dables(draw2d); //区域裁剪 AecComplexCurve cmplOutSide,cmplInSide; AecCoverBooleanOper::PolyClip(*colWall.pColCmpl,draw2d,cmplOutSide,cmplInSide); pWall->SetDraw2dables(cmplOutSide); //移除端部标记 //pWall->RemoveTailDraw2d(colWall.ptPos); cmplOutSide.removeAll(); cmplInSide.removeAll(); draw2d.removeAll(); pWall->GetDraw2dHideTail(draw2d); AecCoverBooleanOper::PolyClip(*colWall.pColCmpl,draw2d,cmplOutSide,cmplInSide); pWall->SetDraw2dHideTail(cmplOutSide); //墙体关联柱子 // 在这里没有发现关联柱子的必要啊,就是不关联功能也可以实现, // 暂时不关联,不然deepclone和wblockclone会把柱子复制出来 //pWall->AppendAssocPart(colWall.idCol); } pEnt->close(); } } AecDbX3dPart* AecWall2DJoin::Create3DSolid(AecComplexCurve& cmplCol,WallData& data1,WallData& data2) { AcDbX3dSolid* pXSolid = NULL; AcDbCurve* pCurve = NULL; AcDbVoidPtrArray arCurPtrs,arRes; for (int i = 0;i < cmplCol.length();i++) { pCurve = cmplCol.segat(i); if (pCurve != NULL) { arCurPtrs.append(pCurve); } } pCurve = KTCADUtilityEx::ConvertBoundCurve(arCurPtrs,arRes); if (pCurve != NULL) { AcDbPolyline* pPl = AcDbPolyline::cast(pCurve); if (pPl != NULL) { pPl->setElevation(__max(data1.dBomEl,data2.dBomEl)); pPl->setClosed(Adesk::kTrue); AcDbExtents ext; pPl->getGeomExtents(ext); AcGePoint3d ptS = MidPoint(ext.minPoint(),ext.maxPoint()); AcGePoint3d ptE = ptS; ptE.z = __min(data1.dH,data2.dH); arCurPtrs.removeAll(); arCurPtrs.append(pPl); arRes.removeAll(); AcDbRegion::createFromCurves(arCurPtrs,arRes); delete pPl; if (!arRes.isEmpty()) { AcDbRegion* pRegion = (AcDbRegion*)arRes.first(); AcDbLine lnPath; lnPath.setStartPoint(ptS); lnPath.setEndPoint(ptE); pXSolid = new AcDbX3dSolid; pXSolid->CreateExtrude(pRegion,lnPath); delete pRegion; } } } if (pXSolid != NULL) { AecDbX3dPart* pPart = new AecDbX3dPart; pPart->SetName(_T("ExAdd")); pPart->GetSpecialtyData()->SetAt(KEY_ADDTIONSHOW,TRUE); pPart->GetSpecialtyData()->SetAt(KEY_POS,0); pPart->GetSpecialtyData()->SetAt(KEY_FORSLICE,FALSE); pPart->AddX3dSolid(pXSolid); return pPart; } return NULL; } void AecWall2DJoin::IntJoinsBoolSubtract() { AcDbEntity* pEnt2 = NULL,*pEnt1 = NULL; for (int i = 0;i < m_arIntJoins.length();i++) { WallIntJoin& wIntJ = m_arIntJoins.at(i); if ( Acad::eOk == acdbOpenAcDbEntity(pEnt1,wIntJ.id1,AcDb::kForWrite)) { AecDbXWall* pWall1 = AecDbXWall::cast(pEnt1); if (pWall1 != NULL) { AcGeVector3d vt1,vt2; AecEqui::AecCurveElement el; memset(&el,0,sizeof(AecEqui::AecCurveElement)); AecComplexCurve cmplSub,cmplCol; AecEqui::AecCurveElement eL1 = pWall1->GetLeftElement(true); AecEqui::AecCurveElement eR1 = pWall1->GetRightElement(true); AecEqui::AecCurveElement eC1 = pWall1->GetMidElement(); if ( Acad::eOk == acdbOpenAcDbEntity(pEnt2,wIntJ.id2,AcDb::kForWrite)) { AecDbXWall* pWall2 = AecDbXWall::cast(pEnt2); if (pWall2 != NULL) { AecEqui::AecCurveElement eL2 = pWall2->GetLeftElement(true); AecEqui::AecCurveElement eR2 = pWall2->GetRightElement(true); AecEqui::AecCurveElement eC2 = pWall2->GetMidElement(); //墙体在标高上有相交 WallData data1,data2; pWall1->GetWallData(data1); pWall2->GetWallData(data2); int nWallWeight1 = MaterialWeight(data1.szMat); int nWallWeight2 = MaterialWeight(data2.szMat); AcGePoint3dArray arPt; //等标高+H 相交 //不等,部分被裁 //相交结构,墙1=墙2 if ( fabs ( (data1.dBomEl + data1.dH) - ( data2.dBomEl + data2.dH ) ) < 1.e-3) { //L1X(L2 R2) AecComplexCurve::IntersectWith(eL1,eL2,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eL1,eR2,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eL1,eC2,AcDb::kOnBothOperands,arPt); if (arPt.length() == 3) { el.ptGe[0] = arPt.first();//sta el.ptGe[2] = arPt.last();//mid el.ptGe[1] = arPt.at(1);//end vt1 = arPt.last() - arPt.first(); vt2 = arPt.at(1) - arPt.first(); if (vt1.isParallelTo(vt2)) { el.ptGe[2] = el.ptGe[1]; } cmplSub.append(el); } arPt.removeAll(); //R1X(L2 R2) AecComplexCurve::IntersectWith(eR1,eL2,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eR1,eR2,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eR1,eC2,AcDb::kOnBothOperands,arPt); if (arPt.length() == 3) { el.ptGe[0] = arPt.first(); el.ptGe[2] = arPt.last(); el.ptGe[1] = arPt.at(1); vt1 = arPt.last() - arPt.first(); vt2 = arPt.at(1) - arPt.first(); if (vt1.isParallelTo(vt2)) { el.ptGe[2] = el.ptGe[1]; } cmplSub.append(el); } arPt.removeAll(); //裁剪 墙1材质<=墙2材质 if (nWallWeight1 <= nWallWeight2) pWall1->SubtractDraw2d(cmplSub); cmplCol.append(cmplSub); cmplSub.removeAll(); //L2X(L1 R1) AecComplexCurve::IntersectWith(eL2,eL1,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eL2,eR1,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eL2,eC1,AcDb::kOnBothOperands,arPt); if (arPt.length() == 3) { el.ptGe[0] = arPt.first(); el.ptGe[2] = arPt.last(); el.ptGe[1] = arPt.at(1); vt1 = arPt.last() - arPt.first(); vt2 = arPt.at(1) - arPt.first(); if (vt1.isParallelTo(vt2)) { el.ptGe[2] = el.ptGe[1]; } cmplSub.append(el); } arPt.removeAll(); //R2X(L1 R1) AecComplexCurve::IntersectWith(eR2,eL1,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eR2,eR1,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eR2,eC1,AcDb::kOnBothOperands,arPt); if (arPt.length() == 3) { el.ptGe[0] = arPt.first(); el.ptGe[2] = arPt.last(); el.ptGe[1] = arPt.at(1); vt1 = arPt.last() - arPt.first(); vt2 = arPt.at(1) - arPt.first(); if (vt1.isParallelTo(vt2)) { el.ptGe[2] = el.ptGe[1]; } cmplSub.append(el); } arPt.removeAll(); //裁剪 //裁剪 墙2材质<=墙1材质 if (nWallWeight2 <= nWallWeight1) pWall2->SubtractDraw2d(cmplSub); cmplCol.append(cmplSub); //需要判断重墙体轻重,默认wall1去除 AecDbX3dPart* pCol1 = Create3DSolid(cmplCol,data1,data2); if (pCol1 != NULL) { if (nWallWeight1 <= nWallWeight2) { pWall1->AddX3dPart(pCol1, AcDb::kBoolSubtract); } else { delete pCol1; } } } else { //部分相交非等标高和高度的两个墙体处理 if ( (data1.dBomEl + data1.dH) - ( data2.dBomEl + data2.dH ) < 1.e-3) { //wall1 矮于 wall2 wall1 被穿 //L1X(L2 R2) AcGePoint3dArray arPt; AecComplexCurve::IntersectWith(eL1,eL2,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eL1,eR2,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eL1,eC2,AcDb::kOnBothOperands,arPt); if (arPt.length() == 3) { el.ptGe[0] = arPt.first();//sta el.ptGe[2] = arPt.last();//mid el.ptGe[1] = arPt.at(1);//end vt1 = arPt.last() - arPt.first(); vt2 = arPt.at(1) - arPt.first(); if (vt1.isParallelTo(vt2)) { el.ptGe[2] = el.ptGe[1]; } cmplSub.append(el); } arPt.removeAll(); //R1X(L2 R2) AecComplexCurve::IntersectWith(eR1,eL2,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eR1,eR2,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eR1,eC2,AcDb::kOnBothOperands,arPt); if (arPt.length() == 3) { el.ptGe[0] = arPt.first(); el.ptGe[2] = arPt.last(); el.ptGe[1] = arPt.at(1); vt1 = arPt.last() - arPt.first(); vt2 = arPt.at(1) - arPt.first(); if (vt1.isParallelTo(vt2)) { el.ptGe[2] = el.ptGe[1]; } cmplSub.append(el); } arPt.removeAll(); //裁剪 //裁剪 墙1材质<=墙2材质 if (nWallWeight1 <= nWallWeight2) pWall1->SubtractDraw2d(cmplSub); cmplCol.append(cmplSub); cmplSub.removeAll(); } else { //wall2 矮于 wall1 wall2 被穿 //L2X(L1 R1) AecComplexCurve::IntersectWith(eL2,eL1,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eL2,eR1,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eL2,eC1,AcDb::kOnBothOperands,arPt); if (arPt.length() == 3) { el.ptGe[0] = arPt.first(); el.ptGe[2] = arPt.last(); el.ptGe[1] = arPt.at(1); vt1 = arPt.last() - arPt.first(); vt2 = arPt.at(1) - arPt.first(); if (vt1.isParallelTo(vt2)) { el.ptGe[2] = el.ptGe[1]; } cmplSub.append(el); } arPt.removeAll(); //R2X(L1 R1) AecComplexCurve::IntersectWith(eR2,eL1,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eR2,eR1,AcDb::kOnBothOperands,arPt); AecComplexCurve::IntersectWith(eR2,eC1,AcDb::kOnBothOperands,arPt); if (arPt.length() == 3) { el.ptGe[0] = arPt.first(); el.ptGe[2] = arPt.last(); el.ptGe[1] = arPt.at(1); vt1 = arPt.last() - arPt.first(); vt2 = arPt.at(1) - arPt.first(); if (vt1.isParallelTo(vt2)) { el.ptGe[2] = el.ptGe[1]; } cmplSub.append(el); } arPt.removeAll(); //裁剪 //裁剪 墙2材质<=墙1材质 if (nWallWeight2 <= nWallWeight1) pWall2->SubtractDraw2d(cmplSub); cmplCol.append(cmplSub); } } } pEnt2->close(); } } pEnt1->close(); } } } bool SortByParam(IdParamEl& idp1,IdParamEl& idp2) { if (idp1.dParam - idp2.dParam < 1.e-10) return true; return false; } void AecWall2DJoin::GetMidPoint(AecDbXWall* pWall,AcGePoint3d& ptMid) { AcDbCurve* pBaseCurve = GetWallBaseCurve(pWall); if (pBaseCurve != NULL) { AcDbLine* pLn = AcDbLine::cast(pBaseCurve); if (pLn != NULL) { ptMid = MidPoint(pLn->startPoint(),pLn->endPoint()); } AcDbArc* pArc = AcDbArc::cast(pBaseCurve); if (pArc != NULL) { ptMid = GetArcMidPoint(pArc); } } } void AecWall2DJoin::ExtendToColumnRegion(const WallXJoin& wj) { AecDbXWall* pWall = NULL; AcDbEntity* pEntWall = NULL; AcDbEntity* pEntCol = NULL; AecDbColumn* pCol = NULL; if ( Acad::eOk == acdbOpenAcDbEntity(pEntCol,wj.idCol,AcDb::kForRead)) { pCol = AecDbColumn::cast(pEntCol); if (pCol != NULL) { //获取闭合的柱子外包线 AecComplexCurve draw2dCol; pCol->GetDraw2dables(draw2dCol); AcGePoint3d ptPos = pCol->GetPosition(); ptPos.z = 0.0; //墙体裁去柱子的线 for (int i = 0;i < wj.nValid;i++) { if ( Acad::eOk == acdbOpenAcDbEntity(pEntWall,wj.ids[i],AcDb::kForWrite)) { pWall = AecDbXWall::cast(pEntWall); if (pWall != NULL) { //进行类似遮挡处理 AecComplexCurve draw2d; pWall->GetDraw2dables(draw2d); //区域裁剪 AecComplexCurve cmplOutSide,cmplInSide; AecCoverBooleanOper::PolyClip(draw2dCol,draw2d,cmplOutSide,cmplInSide); pWall->SetDraw2dables(cmplOutSide); //移除端部标记 pWall->RemoveTailDraw2d(ptPos); } pEntWall->close(); } } } pEntCol->close(); } } bool SortIdAngleElByAngle(IdAngleEl& idael1,IdAngleEl& idael2) { if (idael1.dParam < idael2.dParam) return true; return false; } void AecWall2DJoin::UnClockWiseSortLR(std::vector& vtIdParams,const AcGePoint3d& ptOn,std::vector& vtIdAngleEl) { double dA1 = 0.0,dA2 = 0.0; AcGeVector3d vt1,vt2; AcGePoint3d ptM1,ptM2; AecEqui::AecCurveElement elT; memset(&elT,0,sizeof(AecEqui::AecCurveElement)); IdAngleEl ael; ael.bIsOverParallel = false; for (int i = 0;i < vtIdParams.size();i++) { IdParamEl& idp1 = vtIdParams.at(i); ptM1 = MidPoint(idp1.eL.ptGe[0],idp1.eL.ptGe[2]); vt1 = ptM1 - ptOn; vt1.z = 0.0; ptM2 = MidPoint(idp1.eR.ptGe[0],idp1.eR.ptGe[2]); vt2 = ptM2 - ptOn; vt2.z = 0.0; //vt1.normalize(); //vt2.normalize(); dA1 = AcGeVector3d::kXAxis.angleTo(vt1,AcGeVector3d::kZAxis); dA2 = AcGeVector3d::kXAxis.angleTo(vt2,AcGeVector3d::kZAxis); ael.el = idp1.eL; ael.id = idp1.id; ael.dParam = dA1; ael.nWallWeight = idp1.nWallWeight; vtIdAngleEl.push_back(ael); ael.el = idp1.eR; ael.id = idp1.id; ael.dParam = dA2; ael.nWallWeight = idp1.nWallWeight; vtIdAngleEl.push_back(ael); } std::sort(vtIdAngleEl.begin(),vtIdAngleEl.end(),SortIdAngleElByAngle); } static void ElementSubtract(AecEqui::AecCurveElement& el1, AecEqui::AecCurveElement& el2, AcArray& elRes1, AcArray& elRes2) { //el1,el2均为直线 AecComplexCurve cpl1; cpl1.append(el1); el2.bHided = 1; cpl1.append(el2); el2.bHided = 0; cpl1.boolSubtract(); for (int i = 0;i < cpl1.length();i++) { elRes1.append(cpl1.at(i)); } AecComplexCurve cpl2; cpl2.append(el2); el1.bHided = 1; cpl2.append(el1); el1.bHided = 0; cpl2.boolSubtract(); for (int i = 0;i < cpl2.length();i++) { elRes2.append(cpl2.at(i)); } } bool AecWall2DJoin::CalWeightWallEndLine(IdParamEl &idPW, IdParamEl &idPQ, AecEqui::AecCurveElement &elWEnd, AecEqui::AecCurveElement &elWExt) { AcGePoint3d ptGe[2],ptGeT; AcGeVector3d vtDir[2]; AcDbCurve *pCrvL = NULL, *pCrvR = NULL; AecComplexCurve::MakeCurve(idPW.eL, pCrvL); AcGePoint3dArray arWPts; arWPts.append(idPW.eL.ptGe[0]); arWPts.append(idPW.eL.ptGe[2]); bool bFind1 = false; if (!bFind1 && arWPts.find(idPQ.eL.ptGe[0]) != -1) { ptGe[0] = idPQ.eL.ptGe[0]; bFind1 = true; } if (!bFind1 && arWPts.find(idPQ.eL.ptGe[2]) != -1) { ptGe[0] = idPQ.eL.ptGe[2]; bFind1 = true; } if (!bFind1 && arWPts.find(idPQ.eR.ptGe[0]) != -1) { ptGe[0] = idPQ.eR.ptGe[0]; bFind1 = true; } if (!bFind1 && arWPts.find(idPQ.eR.ptGe[2]) != -1) { ptGe[0] = idPQ.eR.ptGe[2]; bFind1 = true; } if (pCrvL != NULL) { pCrvL->getFirstDeriv(ptGe[0], vtDir[0]); //delete pCrvL;->POS D } AecComplexCurve::MakeCurve(idPW.eR, pCrvR); bool bFind2 = false; arWPts.removeAll(); arWPts.append(idPW.eR.ptGe[0]); arWPts.append(idPW.eR.ptGe[2]); if (!bFind2 &&arWPts.find(idPQ.eL.ptGe[0]) != -1) { ptGe[1] = idPQ.eL.ptGe[0]; bFind2 = true; } if (!bFind2 && arWPts.find(idPQ.eL.ptGe[2]) != -1) { ptGe[1] = idPQ.eL.ptGe[2]; bFind2 = true; } if (!bFind2 && arWPts.find(idPQ.eR.ptGe[0]) != -1) { ptGe[1] = idPQ.eR.ptGe[0]; bFind2 = true; } if (!bFind2 && arWPts.find(idPQ.eR.ptGe[2]) != -1) { ptGe[1] = idPQ.eR.ptGe[2]; bFind2 = true; } if (pCrvR != NULL) { pCrvR->getFirstDeriv(ptGe[1], vtDir[1]); //delete pCrvR;->POS D } vtDir[0].normalize(); vtDir[1].normalize(); AcDbCurve *pCrvW[2]; pCrvW[0] = pCrvL; pCrvW[1] = pCrvR; //TEST /*for (int n = 0; n < 2; n++) { ptGeT = ptGe[n] + vtDir[n] * 1000; AcDbLine *pLnT = new AcDbLine(ptGe[n], ptGeT); pLnT->setColorIndex(2); AddToModelSpace(pLnT); }*/ //圆弧墙体不考虑轻重搭接,因为可能圆弧和直线可能不相交 //直接轻重隔开 AcDbArc *pArcW = AcDbArc::cast(pCrvW[0]); if (pArcW != NULL) { delete pCrvL; delete pCrvR; elWEnd.ptGe[0] = ptGe[0]; elWEnd.ptGe[1] = ptGe[1]; elWEnd.ptGe[2] = ptGe[1]; elWExt.ptGe[0] = ptGe[0]; elWExt.ptGe[1] = ptGe[0]; elWExt.ptGe[2] = ptGe[0]; return true; } bool bFind = false; if (bFind1 && bFind2) { AcDbCurve* pCrv[2]; AecComplexCurve::MakeCurve(idPQ.eL, pCrv[0]); AecComplexCurve::MakeCurve(idPQ.eR, pCrv[1]); if (pCrv[0] != NULL && pCrv[1] != NULL) { AcGePoint3d ptOn,ptSE[2]; AcGeVector3d vt1, vt2; for (int i = 0;i < 2;i++) { pCrv[i]->getStartPoint(ptSE[0]); pCrv[i]->getEndPoint(ptSE[1]); if (!bFind) { for (int j = 0;j < 2;j++) { pCrv[i]->getClosestPointTo(ptGe[j], vtDir[j], ptOn, Adesk::kFalse); //判断是否落在曲线内 vt1 = ptOn - ptSE[0]; vt2 = ptOn - ptSE[1]; if (!vt1.isZeroLength() && !vt2.isZeroLength() && vt1.dotProduct(vt2) < -1.e-10) { elWEnd.ptGe[0] = ptGe[j]; elWEnd.ptGe[1] = ptOn; elWEnd.ptGe[2] = ptOn; elWExt.ptGe[0] = ptGe[1-j];//取另一个 elWExt.ptGe[1] = ptOn; elWExt.ptGe[2] = ptOn; bFind = true; } if (bFind) break; } } if (bFind) break; } delete pCrv[0]; delete pCrv[1]; } } delete pCrvL; delete pCrvR; return bFind; } void AecWall2DJoin::XJoinSortAndTrimByUClock(const WallXJoin& wj) { IdParamEl idp; idp.bIsOverParallel = false; std::vector vtIdParams; AcGePoint3d ptOn = wj.ptJoin; AcDbObjectIdArray arIds; int nFat = -1; AcGeVector3d vt; AcGePoint3d ptMid,ptOn2; AcDbIntArray arWallWeight; AcDbEntity* pEnt = NULL; for(int i = 0;i < wj.nValid;i++) { idp.id = wj.ids[i]; if (arIds.find(idp.id,nFat) ) { continue; } arIds.append(idp.id);//避开自己和自己处理 if ( Acad::eOk == acdbOpenAcDbEntity(pEnt,wj.ids[i],AcDb::kForRead)) { AecDbXWall* pWall = AecDbXWall::cast(pEnt); if (pWall != NULL) { GetMidPoint(pWall,ptMid); vt = ptMid - ptOn; vt.z = 0.0; idp.dParam = AcGeVector3d::kXAxis.angleTo(vt,AcGeVector3d::kZAxis); idp.eL = pWall->GetLeftElement(); idp.eR = pWall->GetRightElement(); idp.nWallWeight = wj.nWallWeight[i]; if (arWallWeight.isEmpty()) arWallWeight.append(idp.nWallWeight); else { if (arWallWeight.find(idp.nWallWeight) == -1) { arWallWeight.append(idp.nWallWeight); } } vtIdParams.push_back(idp); } pEnt->close(); } } if (vtIdParams.size() == 1) return; std::sort(vtIdParams.begin(),vtIdParams.end(),SortByParam); //以on为圆心,墙体的左右线按圆的逆时针排序 std::vector vtIdAngleEl; UnClockWiseSortLR(vtIdParams,ptOn,vtIdAngleEl); AcGePoint3d ptInt; AcGePoint3dArray arPtInts; AcDbObjectIdArray arIdParallel; for (int i = 0;i < vtIdAngleEl.size() - 1;i++) { IdAngleEl& ael1 = vtIdAngleEl.at(i); IdAngleEl& ael2 = vtIdAngleEl.at(i+1); if ( TrimCurveElement(ael1,ael2,ptInt) ) { arPtInts.append(ptInt); } if (i == (vtIdAngleEl.size() - 2 )) { IdAngleEl& aele = vtIdAngleEl.at(i+1); IdAngleEl& ael0 = vtIdAngleEl.at(0); if ( TrimCurveElement(aele,ael0,ptInt) ) { arPtInts.append(ptInt); } } } //按照id 合成 vtIdParams.clear(); int nPos = 0; for(int i = 0;i < wj.nValid;i++) { idp.id = wj.ids[i]; idp.bIsOverParallel = false; idp.nWallWeight = wj.nWallWeight[i]; nPos = 0; for (int ii = 0;ii < vtIdAngleEl.size();ii++) { IdAngleEl& ael1 = vtIdAngleEl.at(ii); if (ael1.id == idp.id) { if (ael1.bIsOverParallel) { idp.bIsOverParallel = true; } if (nPos == 0) { idp.eL = ael1.el; nPos += 1; } else { idp.eR = ael1.el; break; } } } if (nPos == 1) { vtIdParams.push_back(idp); } } //窟窿补柱子 bool bAddCol = false; AcGeVector3d vt1,vt2; //写回二维图元 AecComplexCurve cmpl; for(int i = 0;i < vtIdParams.size();i++) { IdParamEl& idp1 = vtIdParams.at(i); if ( Acad::eOk == acdbOpenAcDbEntity(pEnt,idp1.id,AcDb::kForWrite)) { AecDbXWall* pWall = AecDbXWall::cast(pEnt); if (pWall != NULL) { WallData wData; memset(&wData,0,sizeof(WallData)); pWall->GetWallData(wData); cmpl.removeAll(); cmpl.append(idp1.eL); cmpl.append(idp1.eR); pWall->SetDraw2dables(cmpl); //AcDbCircle* pCir = new AcDbCircle; //pCir->setCenter(ptOn); //pCir->setRadius(10.0); //AddToModelSpace(pCir); //移除端部标记 pWall->getClosestPointTo(ptOn,ptOn2,Adesk::kFalse); //2022-12-21墙体断开的尾部端线去除 if (!idp1.bIsOverParallel) { //且等宽 pWall->RemoveTailDraw2d(ptOn2); } //判断是否应该补在这个墙体上 //窟窿处补上柱子,确定哪个墙体补 if (!bAddCol) { if (arPtInts.length() > 2) { arPtInts.append(arPtInts.first()); AddXPart(pWall,arPtInts,ptOn); bAddCol = true; } } } pEnt->close(); } } //如果两个节点,并且材质不一致 if (vtIdParams.size() == 2 && arWallWeight.length() > 1) { IdParamEl &idp1 = vtIdParams.at(0); IdParamEl &idp2 = vtIdParams.at(1); if (idp1.bIsOverParallel && idp2.bIsOverParallel) { //平行不同材质不处理 } else { IdParamEl idPW, idPQ; if (idp1.nWallWeight < idp2.nWallWeight) { idPW = idp2; idPQ = idp1; } else { idPW = idp1; idPQ = idp2; } AecEqui::AecCurveElement elWEnd,elWExt; memset(&elWEnd, 0, sizeof(AecEqui::AecCurveElement)); memset(&elWExt, 0, sizeof(AecEqui::AecCurveElement)); if (CalWeightWallEndLine(idPW, idPQ, elWEnd,elWExt)) { //测试TEST /*AcDbCurve *pCrv = NULL; AecComplexCurve::MakeCurve(elWEnd, pCrv); if (pCrv != NULL) { pCrv->setColorIndex(1); AddToModelSpace(pCrv); } AecComplexCurve::MakeCurve(elWExt, pCrv); if (pCrv != NULL) { pCrv->setColorIndex(3); AddToModelSpace(pCrv); }*/ //重 if (Acad::eOk == acdbOpenAcDbEntity(pEnt, idPW.id, AcDb::kForWrite)) { AecDbXWall *pWall = AecDbXWall::cast(pEnt); if (pWall != NULL) { //增加端线 cmpl.removeAll(); pWall->GetDraw2dables(cmpl); cmpl.append(elWEnd); if (!elWExt.ptGe[0].isEqualTo(elWExt.ptGe[2]) ) cmpl.append(elWExt); pWall->SetDraw2dables(cmpl); } pEnt->close(); } //轻 if (!elWExt.ptGe[0].isEqualTo(elWExt.ptGe[2])) { if (Acad::eOk == acdbOpenAcDbEntity(pEnt, idPQ.id, AcDb::kForWrite)) { AecDbXWall *pWall = AecDbXWall::cast(pEnt); if (pWall != NULL) { //轻延伸到重一侧,并封闭端线 cmpl.removeAll(); pWall->GetDraw2dables(cmpl); elWExt.bHided = 1; cmpl.append(elWExt); cmpl.boolSubtract(); pWall->SetDraw2dables(cmpl); } pEnt->close(); } } return; } } } //两平行墙体的端线融合处理,多于两个的墙不处理. if (vtIdParams.size() == 2) { IdParamEl &idp1 = vtIdParams.at(0); IdParamEl &idp2 = vtIdParams.at(1); AecEqui::AecCurveElement el1,el2; memset(&el1, 0, sizeof(AecEqui::AecCurveElement)); memset(&el2, 0, sizeof(AecEqui::AecCurveElement)); //平行连接结构 if (idp1.bIsOverParallel && idp2.bIsOverParallel) { AcDbEntity *pEnt1 = NULL; AcDbEntity *pEnt2 = NULL; if (Acad::eOk == acdbOpenAcDbEntity(pEnt1, idp1.id, AcDb::kForWrite)) { AecDbXWall *pWall1 = AecDbXWall::cast(pEnt1); if (pWall1 != NULL) { pWall1->getClosestPointTo(ptOn, ptOn2, Adesk::kFalse); pWall1->GetTailDraw2d(ptOn2, el1); if (Acad::eOk == acdbOpenAcDbEntity(pEnt2, idp2.id, AcDb::kForWrite)) { AecDbXWall *pWall2 = AecDbXWall::cast(pEnt2); if (pWall2 != NULL) { pWall2->getClosestPointTo(ptOn, ptOn2, Adesk::kFalse); pWall2->GetTailDraw2d(ptOn2, el2); //同等材质,才可以融合端线 if (idp1.nWallWeight == idp2.nWallWeight) { AcArray elRes1, elRes2; ElementSubtract(el1, el2, elRes1, elRes2); if (elRes1.isEmpty()) { pWall1->RemoveTailDraw2d(ptOn2); } else { AecComplexCurve cpl1,cplOn; for (int i = 0; i < elRes1.length(); i++) { cpl1.append(elRes1.at(i)); } pWall1->RemoveTailDraw2d(ptOn2); pWall1->GetDraw2dHideTail(cplOn); cplOn.append(cpl1); pWall1->SetDraw2dHideTail(cplOn); } if (elRes2.isEmpty()) { pWall2->RemoveTailDraw2d(ptOn2); } else { AecComplexCurve cpl2, cplOn; for (int i = 0; i < elRes2.length(); i++) { cpl2.append(elRes2.at(i)); } pWall2->RemoveTailDraw2d(ptOn2); pWall2->GetDraw2dHideTail(cplOn); cplOn.append(cpl2); pWall2->SetDraw2dHideTail(cplOn); } } } pEnt2->close(); } } pEnt1->close(); } return; } } } void AecWall2DJoin::AddXPart(AecDbXWall* pWall,AcGePoint3dArray& arPtInts,const AcGePoint3d& ptOn) { if (pWall == NULL) return; WallData data; pWall->GetWallData(data); AcGePoint3d ptSta,ptEnd; ptSta = arPtInts.first(); ptEnd = ptSta; ptSta.z = data.dBomEl; ptEnd.z = ptSta.z + data.dH; AcDbLine lnPath; lnPath.setStartPoint(ptSta); lnPath.setEndPoint(ptEnd); AcDbRegion* pRegion = AecDbEarthWorm::CreatePolygonRegionOnly(arPtInts.asArrayPtr(),arPtInts.length()); if (pRegion != NULL) { int nPos = pWall->GetNearPosition(ptOn); AecDbX3dPart* pPart = new AecDbX3dPart; pPart->SetName(_T("ExAdd")); pPart->GetSpecialtyData()->SetAt(KEY_ADDTIONSHOW,TRUE); pPart->GetSpecialtyData()->SetAt(KEY_POS,nPos); pPart->GetSpecialtyData()->SetAt(KEY_FORSLICE,FALSE); AcGeVector3d vtMove; vtMove.set(0,0,ptSta.z - arPtInts.first().z); AcGeMatrix3d xform; xform.setToTranslation(vtMove); pRegion->transformBy(xform); AcDbX3dSolid* pXSolid = new AcDbX3dSolid; pXSolid->CreateExtrude(pRegion,lnPath); pPart->AddX3dSolid(pXSolid); pWall->AddX3dPart(pPart); delete pRegion; } } bool AecWall2DJoin::TrimLineArcElement(AcDbLine* pLn,AecEqui::AecCurveElement& el1,AcDbArc* pArc,AecEqui::AecCurveElement& el2,AcGePoint3d& ptInt) { if (pLn == NULL && pArc == NULL) return false; AcGePoint3dArray arPts; pLn->intersectWith(pArc,AcDb::kOnBothOperands,arPts); if (!arPts.isEmpty()) { ptInt = arPts.first(); //L边 double dL1 = ptInt.distanceTo(pLn->startPoint()); double dL2 = ptInt.distanceTo(pLn->endPoint()); if ( (dL1 - dL2) > 1.e-6) // sta+int { el1.ptGe[0] = pLn->startPoint(); el1.ptGe[1] = ptInt; el1.ptGe[2] = ptInt; } else//end + int { el1.ptGe[0] = ptInt; el1.ptGe[1] = pLn->endPoint(); el1.ptGe[2] = pLn->endPoint(); } //ARC AcGePoint3d ptSta,ptEnd,ptMid,ptMidL; pArc->getStartPoint(ptSta); pArc->getEndPoint(ptEnd); dL1 = ptInt.distanceTo(ptSta); dL2 = ptInt.distanceTo(ptEnd); if ( (dL1 - dL2) > 1.e-6) // sta+int { //Sta-Int 之间Mid ptMidL = MidPoint(ptSta,ptInt); pArc->getClosestPointTo(ptMidL,ptMid); el2.ptGe[0] = ptSta; el2.ptGe[1] = ptMid; el2.ptGe[2] = ptInt; } else//end + int { //End-Int 之间Mid ptMidL = MidPoint(ptEnd,ptInt); pArc->getClosestPointTo(ptMidL,ptMid); el2.ptGe[0] = ptInt; el2.ptGe[1] = ptMid; el2.ptGe[2] = ptEnd; } return true; } else { pLn->intersectWith(pArc,AcDb::kExtendBoth,arPts); if (!arPts.isEmpty()) { AcGePoint3d ptSta,ptEnd,ptMid,ptMidL,ptT,ptInt; double dPa = 0.0; //取距离Arc最近的点 pArc->getStartPoint(ptSta); pArc->getEndPoint(ptEnd); BOOL bFind = FALSE; double dL1 = 0.0,dL2 = 0.0,dMin = 9999999.0,dTmp = 0.0; for (int i = 0;i < arPts.length();i++) { ptT = arPts.at(i); dL1 = ptT.distanceTo(ptSta); dL2 = ptT.distanceTo(ptEnd); dTmp = __min(dL1,dL2); if ( (dTmp - dMin) < 1.e-6) { ptInt = ptT; dMin = dTmp; bFind = TRUE; } else//> { //... } } if (bFind) { //TEST //AcDbCircle* pCir = new AcDbCircle; //pCir->setCenter(ptInt); //pCir->setRadius(10.0); //pCir->setColorIndex(1); //AddToModelSpace(pCir); //L dL1 = ptInt.distanceTo(pLn->startPoint()); dL2 = ptInt.distanceTo(pLn->endPoint()); if ( (dL1 - dL2) > 1.e-6) // sta+int { el1.ptGe[0] = pLn->startPoint(); el1.ptGe[1] = ptInt; el1.ptGe[2] = ptInt; } else//end + int { el1.ptGe[0] = ptInt; el1.ptGe[1] = pLn->endPoint(); el1.ptGe[2] = pLn->endPoint(); } //ARC //如果ptInt在Arc上 if ( Acad::eOk == pArc->getParamAtPoint(ptInt,dPa) ) { pArc->getStartPoint(ptSta); pArc->getEndPoint(ptEnd); dL1 = ptInt.distanceTo(ptSta); dL2 = ptInt.distanceTo(ptEnd); if ( (dL1 - dL2) > 1.e-6) // sta+int { //Sta-Int 之间Mid ptMidL = MidPoint(ptSta,ptInt); pArc->getClosestPointTo(ptMidL,ptMid); el2.ptGe[0] = ptSta; el2.ptGe[1] = ptMid; el2.ptGe[2] = ptInt; } else//end + int { //End-Int 之间Mid ptMidL = MidPoint(ptEnd,ptInt); pArc->getClosestPointTo(ptMidL,ptMid); el2.ptGe[0] = ptInt; el2.ptGe[1] = ptMid; el2.ptGe[2] = ptEnd; } } else { pArc->getStartPoint(ptSta); pArc->getEndPoint(ptEnd); dL1 = ptInt.distanceTo(ptSta); dL2 = ptInt.distanceTo(ptEnd); if ( (dL1 - dL2) > 1.e-6) // 距离end近 { el2.ptGe[0] = ptSta; el2.ptGe[1] = ptEnd; el2.ptGe[2] = ptInt; } else//距离sta近 { el2.ptGe[0] = ptInt; el2.ptGe[1] = ptSta; el2.ptGe[2] = ptEnd; } } return true; } } else { //没有交点,圆弧切线法 //... } } return false; } bool AecWall2DJoin::TrimCurveElement(IdAngleEl& ael1,IdAngleEl& ael2,AcGePoint3d& ptInt) { if (ael2.id == ael1.id) return false; int nType1 = AecComplexCurve::GetElementType(ael1.el); int nType2 = AecComplexCurve::GetElementType(ael2.el); if ( nType1 == AecEqui::eLine && nType2 == AecEqui::eLine) { AcDbLine* pLn1 = NULL; AcDbLine* pLn2 = NULL; AecComplexCurve::MakeLine(ael1.el,pLn1); AecComplexCurve::MakeLine(ael2.el,pLn2); if (pLn1 != NULL && pLn2 != NULL) { pLn1->setColorIndex(1); pLn2->setColorIndex(2); //TEST //AddToModelSpace(pLnL); //AddToModelSpace(pLnR); //return; AcGePoint3dArray arPts; pLn2->intersectWith(pLn1,AcDb::kExtendBoth,arPts); if (arPts.length() == 1) { ptInt = arPts.first(); //原则: //依此点,取最长长度为新元素的长度 //2边 double dL1 = ptInt.distanceTo(pLn2->startPoint()); double dL2 = ptInt.distanceTo(pLn2->endPoint()); if ( (dL1 - dL2) > 1.e-6) // sta+int { ael2.el.ptGe[0] = pLn2->startPoint(); ael2.el.ptGe[1] = ptInt; ael2.el.ptGe[2] = ptInt; } else//end + int { ael2.el.ptGe[0] = ptInt; ael2.el.ptGe[1] = pLn2->endPoint(); ael2.el.ptGe[2] = pLn2->endPoint(); } //1边 dL1 = ptInt.distanceTo(pLn1->startPoint()); dL2 = ptInt.distanceTo(pLn1->endPoint()); if ( (dL1 - dL2) > 1.e-6) // sta+int { ael1.el.ptGe[0] = pLn1->startPoint(); ael1.el.ptGe[1] = ptInt; ael1.el.ptGe[2] = ptInt; } else//end + int { ael1.el.ptGe[0] = ptInt; ael1.el.ptGe[1] = pLn1->endPoint(); ael1.el.ptGe[2] = pLn1->endPoint(); } } else { //平行的情况 //不会有两点 AcGeVector3d vt1 = ael1.el.ptGe[1] - ael1.el.ptGe[0]; AcGeVector3d vt2 = ael2.el.ptGe[1] - ael2.el.ptGe[0]; if (vt1.isParallelTo(vt2)) { AcGePoint3dArray arPts; arPts.append(ael1.el.ptGe[0]); arPts.append(ael1.el.ptGe[1]); arPts.append(ael2.el.ptGe[0]); arPts.append(ael2.el.ptGe[1]); AecCoverBooleanOper::SortPoints(arPts,pLn1,false); //判断是否共线 vt1 = ael1.el.ptGe[1] - ael2.el.ptGe[0]; vt2 = ael2.el.ptGe[1] - ael1.el.ptGe[0]; if (!vt1.isParallelTo(vt2)) { ael1.bIsOverParallel = true; ael2.bIsOverParallel = true; } if (arPts.length() == 4) { ptInt = MidPoint(arPts.at(1),arPts.at(2)); delete pLn1; delete pLn2; return true; } } delete pLn1; delete pLn2; return false; } delete pLn1; delete pLn2; return true; } } else { AcDbCurve* pCurve1 = NULL; AcDbCurve* pCurve2 = NULL; AecComplexCurve::MakeCurve(ael1.el,pCurve1); AecComplexCurve::MakeCurve(ael2.el,pCurve2); pCurve1->setColorIndex(1); pCurve2->setColorIndex(2); //TEST //AddToModelSpace(pCurve1); //AddToModelSpace(pCurve2); //return; //圆弧,取末点的切线相交 bool bSuccess = false; if (nType1 == AecEqui::eLine && nType2 == AecEqui::eArc) { AcDbLine* pLn1 = AcDbLine::cast(pCurve1); AcDbArc* pArc2 = AcDbArc::cast(pCurve2); bSuccess = TrimLineArcElement(pLn1,ael1.el,pArc2,ael2.el,ptInt); } if (nType1 == AecEqui::eArc && nType2 == AecEqui::eLine) { AcDbArc* pArc1 = AcDbArc::cast(pCurve1); AcDbLine* pLn2 = AcDbLine::cast(pCurve2); bSuccess = TrimLineArcElement(pLn2,ael2.el,pArc1,ael1.el,ptInt); } delete pCurve1; delete pCurve2; return bSuccess; } return false; } bool SortWallEndByParam(WallEnd& we1,WallEnd& we2) { if ( (we1.dParamOnM - we2.dParamOnM) < 1.e-6 ) return true; return false; } void GetNearIntPointTo(AcDbCurve* pArcR,AcDbCurve* pArcE,const AcGePoint3d& ptEnd,AcGePoint3d& ptInt) { if (pArcE == NULL || pArcR == NULL) return; AcGePoint3dArray arPts; pArcR->intersectWith(pArcE,AcDb::kExtendBoth,arPts); double dDis = 0.0,dMin = 9999999.0; AcGePoint3d ptT; for (int i = 0;i < arPts.length();i++) { ptT = arPts.at(i); dDis = ptT.distanceTo(ptEnd); if (dDis < dMin) { dMin = dDis; ptInt = ptT; } } } void AecWall2DJoin::GetBreakPoint(AcDbCurve* pCurE,AcDbCurve* pCutTo,AcGePoint3d& ptEnd,AecEqui::AecCurveElement& el,const AcGeVector3d& vtEnd,double dThick) { //------------------------------- --> CutTo Line or Arc // el //------------+----+------------- // // / +E / // / / // / / // / / ->CurE Line or Arc // if (pCutTo == NULL) return; AcDbLine* pLineE = AcDbLine::cast(pCurE);// E 线是直线 if (pLineE != NULL)// E 线是直线 { AcDbArc* pArc = AcDbArc::cast(pCutTo);//主线是圆弧 if (pArc != NULL) { //E线是直线vtEnd AcGeVector3d vtDir = vtEnd; vtDir.rotateBy(PI/2.0,AcGeVector3d::kZAxis); vtDir.normalize(); AcGePoint3d pt1 = ptEnd - vtDir * 0.5 * dThick; AcGePoint3d pt2 = ptEnd + vtDir * 0.5 * dThick; pCutTo->getClosestPointTo(pt1,vtEnd,el.ptGe[0]); pCutTo->getClosestPointTo(pt2,vtEnd,el.ptGe[2]); return; } AcDbLine* pLine = AcDbLine::cast(pCutTo);//主线是直线 if (pLine != NULL)//主线是直线 { //E线是直线vtEnd AcGeVector3d vtDir = vtEnd; vtDir.normalize(); vtDir.rotateBy(PI / 2.0,AcGeVector3d::kZAxis); AcGePoint3d pt1 = ptEnd - vtDir * 0.5 * dThick; AcGePoint3d pt2 = ptEnd + vtDir * 0.5 * dThick; pCutTo->getClosestPointTo(pt1,vtEnd,el.ptGe[0]); pCutTo->getClosestPointTo(pt2,vtEnd,el.ptGe[1]); } return; } AcDbArc* pArcE = AcDbArc::cast(pCurE);// E 线是圆弧 if (pArcE != NULL) { AcDbArc* pArc = AcDbArc::cast(pCutTo);//主线是圆弧 if (pArc != NULL) { //E 线是圆弧 double dRad = pArcE->radius(); double dR = dRad + 0.5 * dThick; double dr = dRad - 0.5 * dThick; AcDbArc* pArcR = (AcDbArc*)pArcE->clone(); pArcR->setRadius(dR); AcDbArc* pArcr = (AcDbArc*)pArcE->clone(); pArcr->setRadius(dr); GetNearIntPointTo(pArcR,pArc,ptEnd,el.ptGe[0]); GetNearIntPointTo(pArcr,pArc,ptEnd,el.ptGe[2]); delete pArcR;delete pArcr; } AcDbLine* pLine = AcDbLine::cast(pCutTo);//主线是直线 if (pLine != NULL)//主线是直线 { //E 线是圆弧 double dRad = pArcE->radius(); double dR = dRad + 0.5 * dThick; double dr = dRad - 0.5 * dThick; AcDbArc* pArcR = (AcDbArc*)pArcE->clone(); pArcR->setRadius(dR); AcDbArc* pArcr = (AcDbArc*)pArcE->clone(); pArcr->setRadius(dr); GetNearIntPointTo(pArcR,pLine,ptEnd,el.ptGe[0]); GetNearIntPointTo(pArcr,pLine,ptEnd,el.ptGe[1]); delete pArcR;delete pArcr; //TEST //pArcR->setColorIndex(1); //pArcr->setColorIndex(2); //AddToModelSpace(pArcR); //AddToModelSpace(pArcr); } return; } } int AecWall2DJoin::GetNearSideTo(AcDbCurve* pCurE,AcGePoint3d& ptEnd,const AcGeVector3d& vtEnd,AcDbCurve* pCurM,AcDbCurve* pLeft,AcDbCurve* pRight,double dThick) { int nNearSide = 0; AcGePoint3d ptS,ptE,ptT; pCurE->getStartPoint(ptS); pCurE->getEndPoint(ptE); //取远端 double dL1 = ptS.distanceTo(ptEnd); double dL2 = ptE.distanceTo(ptEnd); double dMin = 0.0; if (dL1 < dL2) { ptT = ptE; } else { ptT = ptS; } AcGePoint3d ptOn; pCurM->getClosestPointTo(ptEnd,vtEnd,ptOn,Adesk::kTrue); //圆弧的getClosestPointTo(ptEnd,vtEnd,ptOn,Adesk::kTrue); 错误!!.ARX接口问题 AcDbArc *pArc = AcDbArc::cast(pCurM); if (pArc != NULL) { pCurM->getClosestPointTo(ptEnd, vtEnd, ptOn, Adesk::kFalse); } dMin = ptOn.distanceTo(ptEnd); if ( ( dMin - 1.5 * dThick) > 1.e-6) { //acutPrintf(_T("\nNear side Len = %g"),dMin); return nNearSide; } AcDbLine ln; ln.setStartPoint(ptT); ln.setEndPoint(ptOn); AcGePoint3dArray arPtsL; ln.intersectWith(pLeft,AcDb::kOnBothOperands,arPtsL); if (!arPtsL.isEmpty()) { return -1; } AcGePoint3dArray arPtsR; ln.intersectWith(pRight,AcDb::kOnBothOperands,arPtsR); if (!arPtsR.isEmpty()) { return 1; } return nNearSide; } void AecWall2DJoin::TJoinSortAndTrimByMain(const WallTJoin& wt) { //先按.wes 的param排序 if (wt.nValid > 0) { std::vector vtWEs; for (int i = 0;i < wt.nValid;i++) { vtWEs.push_back(wt.wes[i]); } std::sort(vtWEs.begin(),vtWEs.end(),SortWallEndByParam); AecComplexCurve cmplL; AecComplexCurve cmplR; AecComplexCurve cmplT; //主墙体不裁剪,采用隐藏的方式绘制 AcDbEntity* pEntM = NULL; if ( Acad::eOk == acdbOpenAcDbEntity(pEntM,wt.idMain,AcDb::kForRead)) { AecDbXWall* pWallM = AecDbXWall::cast(pEntM); if (pWallM != NULL) { AcDbCurve* pLeft = pWallM->GetLeftCurve(); AcDbCurve* pRight = pWallM->GetRightCurve(); AcDbCurve* pCurM = GetWallBaseCurve(pWallM); if (pLeft == NULL || pRight == NULL || pCurM == NULL) { pEntM->close(); return; } //关闭主体墙 pEntM->close(); pEntM = NULL; pWallM = NULL; WallXJoin xj; AcGeVector3d vtT,vt1,vt2; WallData data; AcGePoint3d ptOn1,ptOn2,ptS,ptE,ptCen,ptMid,ptTmp; AcDbEntity* pEntE = NULL; double dDistL = 0.0,dDistR = 0.0; AecEqui::AecCurveElement el; memset(&el,0,sizeof(AecEqui::AecCurveElement)); AecEqui::AecCurveElement elT; memset(&elT,0,sizeof(AecEqui::AecCurveElement)); for (int i = 0;i < vtWEs.size();i++) { WallEnd we = vtWEs.at(i); if (we.idCol.isValid())//延伸到柱子即可 { xj.idCol = we.idCol; xj.nValid = 1; xj.ids[0] = we.id; xj.ptJoin = we.ptEnd; ExtendToColumnRegion(xj); } else//提取墙体的左右侧 { Acad::ErrorStatus es; if ( Acad::eOk == (es = acdbOpenAcDbEntity(pEntE,we.id,AcDb::kForRead)))//forWrite { AecDbXWall* pWallE = AecDbXWall::cast(pEntE); if (pWallE != NULL) { pWallE->GetWallData(data); ptS = GetWallStartPoint(pWallE); ptE = GetWallEndPoint(pWallE); AcDbCurve* pCurE = GetWallBaseCurve(pWallE); pLeft->getClosestPointTo(we.ptEnd,we.vtEnd,ptOn1); pRight->getClosestPointTo(we.ptEnd,we.vtEnd,ptOn2); vt1 = we.ptEnd - ptOn1; vt2 = we.ptEnd - ptOn2; dDistL = vt1.length(); dDistR = vt2.length(); int nNearSide = GetNearSideTo(pCurE,we.ptEnd,we.vtEnd,pCurM,pLeft,pRight,data.dThick); if (nNearSide == -1)//靠近左侧 { AcDbLine* pLnM = AcDbLine::cast(pLeft); if (pLnM != NULL) { vtT = pLnM->endPoint() - pLnM->startPoint(); vtT.normalize(); GetBreakPoint(pCurE,pLeft,we.ptEnd,el,we.vtEnd,we.dThick); //el.ptGe[0] = ptOn1 - vtT * 0.5 * data.dThick; //el.ptGe[1] = ptOn1 + vtT * 0.5 * data.dThick; el.ptGe[2] = el.ptGe[1]; el.gsMark = MaterialWeight(data.szMat); //材质相同,方可裁剪主墙 if (el.gsMark == wt.nWallWeight) cmplL.append(el); } AcDbArc* pArc = AcDbArc::cast(pLeft); if (pArc != NULL)//待定 { //两点定玄, //el.ptGe[0] = ptOn1 - vtT * 0.5 * data.dThick; //el.ptGe[2] = ptOn1 + vtT * 0.5 * data.dThick; GetBreakPoint(pCurE,pLeft,we.ptEnd,el,we.vtEnd,we.dThick); ptTmp = MidPoint(el.ptGe[0],el.ptGe[2]); pArc->getClosestPointTo(ptTmp,ptMid); el.ptGe[1] = ptMid; el.gsMark = MaterialWeight(data.szMat); //材质相同,方可裁剪主墙 if (el.gsMark == wt.nWallWeight) cmplL.append(el); } } else if (nNearSide == 1)//靠近右侧 { AcDbLine* pLnM = AcDbLine::cast(pRight); if (pLnM != NULL) { vtT = pLnM->endPoint() - pLnM->startPoint(); vtT.normalize(); //el.ptGe[0] = ptOn2 - vtT * 0.5 * data.dThick; //el.ptGe[1] = ptOn2 + vtT * 0.5 * data.dThick; GetBreakPoint(pCurE,pRight,we.ptEnd,el,we.vtEnd,we.dThick); el.ptGe[2] = el.ptGe[1]; el.gsMark = MaterialWeight(data.szMat); //材质相同,方可裁剪主墙 if (el.gsMark == wt.nWallWeight) cmplR.append(el); } AcDbArc* pArc = AcDbArc::cast(pRight); if (pArc != NULL)//待定 { //两点定玄, //el.ptGe[0] = ptOn1 - vtT * 0.5 * data.dThick; //el.ptGe[2] = ptOn1 + vtT * 0.5 * data.dThick; GetBreakPoint(pCurE,pRight,we.ptEnd,el,we.vtEnd,we.dThick); ptTmp = MidPoint(el.ptGe[0],el.ptGe[2]); pArc->getClosestPointTo(ptTmp,ptMid); el.ptGe[1] = ptMid; el.gsMark = MaterialWeight(data.szMat); //材质相同,方可裁剪主墙 if (el.gsMark == wt.nWallWeight) cmplR.append(el); } } else { //... } Adesk::Boolean bExtendSta = true; double dDistE = ptE.distanceTo(we.ptEnd); double dDistS = ptS.distanceTo(we.ptEnd); if (dDistE < dDistS) bExtendSta = false; if (nNearSide == -1)//靠主墙左侧 { //Extend(pWallE,bExtendSta,ptOn1); //pWallE->GetStandardDraw2d(); //pWallE->RemoveTailDraw2d(ptOn1); //TrimEnd(pWallE,el,we.vtEnd); AppendExtend(we.id,bExtendSta,ptOn1,el,we.vtEnd, nNearSide, wt.idMain); } else if (nNearSide == 1)//靠主墙右侧 { //Extend(pWallE,bExtendSta,ptOn2); //pWallE->GetStandardDraw2d(); //pWallE->RemoveTailDraw2d(ptOn2); //TrimEnd(pWallE,el,we.vtEnd); AppendExtend(we.id,bExtendSta,ptOn2,el,we.vtEnd, nNearSide, wt.idMain); } } pEntE->close(); } } } if (pLeft != NULL || pRight != NULL) { delete pLeft;pLeft = NULL; delete pRight;pRight = NULL; } //再次打开主体修改 if ( Acad::eOk == acdbOpenAcDbEntity(pEntM,wt.idMain,AcDb::kForWrite)) { AecDbXWall* pWallM = AecDbXWall::cast(pEntM); if (pWallM != NULL) { //进行类似遮挡处理 AecComplexCurve draw2d; pWallM->GetDraw2dables(draw2d); draw2d.setSubElementGsMark(wt.nWallWeight); //柱子裁剪墙体的左右侧 考虑墙体的轻重 AecCoverBooleanOper::BoolSubtract(draw2d,cmplL); AecCoverBooleanOper::BoolSubtract(draw2d,cmplR); pWallM->SetDraw2dables(draw2d); } pEntM->close(); pEntM = NULL; } } //确认关闭 if (pEntM != NULL) pEntM->close(); } } } void AecWall2DJoin::AppendExtend(const AcDbObjectId& id,Adesk::Boolean bExtendSta,const AcGePoint3d& ptOn,AecEqui::AecCurveElement& el,const AcGeVector3d& vtEnd,int nNearSide, const AcDbObjectId& idMain) { for (int i = 0;i < m_arWallExtends.length();i++) { WallExtend& exd = m_arWallExtends.at(i); if (exd.idWall == id && exd.nEnds < 2)//1.找到 { exd.bExtendSta[exd.nEnds] = bExtendSta; memcpy(&exd.el[exd.nEnds],&el,sizeof(AecEqui::AecCurveElement)); exd.ptOn[exd.nEnds] = ptOn; exd.vtEnd[exd.nEnds] = vtEnd; exd.nEnds += 1; return; } } //2.未找到,添加 WallExtend ext; ext.idWall = id; ext.idMain = idMain; ext.nNearSide = nNearSide; ext.nEnds = 1; ext.bExtendSta[0] = bExtendSta; memcpy(&ext.el[0],&el,sizeof(AecEqui::AecCurveElement)); ext.ptOn[0] = ptOn; ext.vtEnd[0] = vtEnd; m_arWallExtends.append(ext); } AcGePoint3d AecWall2DJoin::GetWallStartPoint(AecDbXWall* pWall) const { AcGePoint3d ptSta = AcGePoint3d::kOrigin; if (pWall != NULL) { if (pWall->IsVViewWall()) { AcDbCurve* pCurve = pWall->GetAsNativeCurveOfVView(); if (pCurve != NULL) { pCurve->getStartPoint(ptSta); delete pCurve; } } else { pWall->getStartPoint(ptSta); } } return ptSta; } AcGePoint3d AecWall2DJoin::GetWallEndPoint(AecDbXWall* pWall) const { AcGePoint3d ptEnd = AcGePoint3d::kOrigin; if (pWall != NULL) { if (pWall->IsVViewWall()) { AcDbCurve* pCurve = pWall->GetAsNativeCurveOfVView(); if (pCurve != NULL) { pCurve->getEndPoint(ptEnd); delete pCurve; } } else { pWall->GetNativeCurve()->getEndPoint(ptEnd); } } return ptEnd; } AcGeVector3d AecWall2DJoin::GetWallFirstDeriv(AecDbXWall* pWall,const AcGePoint3d& ptGeOn) const { AcGeVector3d vtDir(0,0,0); if (pWall != NULL) { if (pWall->IsVViewWall()) { AcDbCurve* pCurve = pWall->GetAsNativeCurveOfVView(); if (pCurve != NULL) { pCurve->getFirstDeriv(ptGeOn,vtDir); delete pCurve; } } else { pWall->getFirstDeriv(ptGeOn,vtDir); //TEST vtDir.normalize(); AcGePoint3d ptEnd = ptGeOn; ptEnd += 10.0 * vtDir; AcDbLine* pLnt = new AcDbLine; pLnt->setStartPoint(ptGeOn); pLnt->setEndPoint(ptEnd); pLnt->setColorIndex(1); m_arTestEntPtrs.append(pLnt); } } return vtDir; } Acad::ErrorStatus AecWall2DJoin::Extend(AecDbXWall*pWall,Adesk::Boolean extendStart,const AcGePoint3d& toPoint,AcGeVector3d& vtEnd,AcDbObjectId& idMain, int nNearSide) { Acad::ErrorStatus es = Acad::eOk; if (pWall->IsVViewWall()) { //? } else { AcGePoint3d ptE; if (extendStart) pWall->getStartPoint(ptE); else pWall->getEndPoint(ptE); AcGePoint3d ptOn; es = pWall->getClosestPointTo(toPoint,ptOn,Adesk::kTrue); pWall->RemoveTailDraw2d(ptE); AcDbCurve* pCrv = pWall->GetNativeCurve(); //T分支延伸到主墙 es = pWall->extend(extendStart,ptOn); //T分两侧边线延伸到主墙的边线 AecComplexCurve draw2d; pWall->GetDraw2dables(draw2d); AcGeVector3d vtTan; AcDbEntity *pEntM = NULL; if (Acad::eOk == acdbOpenAcDbEntity(pEntM, idMain, AcDb::kForRead)) { AecDbXWall *pWallM = AecDbXWall::cast(pEntM); if (pWallM != NULL) { AcDbCurve *pCurve = NULL; if ( nNearSide == -1) pCurve = pWallM->GetLeftCurve(); else pCurve = pWallM->GetRightCurve(); pCurve->getFirstDeriv(toPoint, vtTan); if (vtTan.isPerpendicularTo(vtEnd)) { //垂直不需要裁剪和延伸 T } else { //需要处理两侧 7 AecEqui::AecCurveElement el; memset(&el, 0, sizeof(AecEqui::AecCurveElement)); pWall->GetTailDraw2d(ptOn, el); //找到两侧最近的el int nGsMk = 0; AcArray arExEl; for (int i = 0;i < draw2d.length();i++) { AecEqui::AecCurveElement &elT = draw2d.atByRef(i); if (el.ptGe[0].distanceTo(elT.ptGe[0]) < 1.e-2 || el.ptGe[0].distanceTo(elT.ptGe[2]) < 1.e-2) { nGsMk = elT.gsMark; elT.gsMark = i; arExEl.append(elT); elT.gsMark = nGsMk; continue; } if (el.ptGe[1].distanceTo(elT.ptGe[0]) < 1.e-2 || el.ptGe[1].distanceTo(elT.ptGe[2]) < 1.e-2) { nGsMk = elT.gsMark; elT.gsMark = i; arExEl.append(elT); elT.gsMark = nGsMk; } } //两边线 AcGePoint3dArray arPts; for (int j = 0;j < arExEl.length();j++) { AecEqui::AecCurveElement &elE = arExEl.at(j); AcDbCurve *pCrvE = NULL; AecComplexCurve::MakeCurve(elE, pCrvE); arPts.removeAll(); pCrvE->intersectWith(pCurve, AcDb::kOnBothOperands, arPts); if (arPts.length() == 1)//相交裁剪 { // AcGeVector3d vt = elE.ptGe[0] - arPts.first(); if (vt.isCodirectionalTo(vtEnd)) { elE.ptGe[0] = arPts.first(); } vt = elE.ptGe[2] - arPts.first(); if (vt.isCodirectionalTo(vtEnd)) { elE.ptGe[2] = arPts.first(); AcDbLine *pLn = AcDbLine::cast(pCrvE); if (pLn != NULL) { elE.ptGe[1] = arPts.first(); } } AecEqui::AecCurveElement& elT = draw2d.atByRef(elE.gsMark); memcpy(elT.ptGe, elE.ptGe, sizeof(AcGePoint3d) * 3); draw2d.setAt(elE.gsMark, elT); } else//不相交,延长 { pCrvE->intersectWith(pCurve, AcDb::kExtendThis, arPts); if (arPts.length() == 1) { //取最近 arPts.first(); double dL1 = elE.ptGe[0].distanceTo(arPts.first()); double dL2 = elE.ptGe[2].distanceTo(arPts.first()); if (dL1 < dL2) { elE.ptGe[0] = arPts.first(); } else { elE.ptGe[2] = arPts.first(); AcDbLine *pLn = AcDbLine::cast(pCrvE); if (pLn != NULL) { elE.ptGe[1] = arPts.first(); } } AecEqui::AecCurveElement &elT = draw2d.atByRef(elE.gsMark); memcpy(elT.ptGe, elE.ptGe, sizeof(AcGePoint3d) * 3); draw2d.setAt(elE.gsMark, elT); } } delete pCrvE; } pWall->SetDraw2dables(draw2d); } delete pCurve; } pEntM->close(); } } return es; } int FindNearPoint(const AcGePoint3d& pt,AecEqui::AecCurveElement& eT,AcGePoint3d& ptNear,const AcGeVector3d& vtEnd) { AcDbCurve* pCurve = NULL; AecComplexCurve::MakeCurve(eT,pCurve); if (pCurve == NULL) return 0; AcGePoint3d ptOn; pCurve->getClosestPointTo(pt,ptOn,Adesk::kTrue); if (pt.distanceTo(ptOn) - 10.0 > 1.e-3) return 0; double dPa = 0.0,dS = 0.0,dE = 0.0; Acad::ErrorStatus es = pCurve->getParamAtPoint(ptOn,dPa); if (es == Acad::eOk) { //落在上面 AcGePoint3d ptS,ptE; pCurve->getStartPoint(ptS); pCurve->getEndPoint(ptE); dS = ptS.distanceTo(ptOn); dE = ptE.distanceTo(ptOn); if (dS < dE)//靠近Start端 { ptNear = ptS; } else { ptNear = ptE; } AcGeVector3d vtF; pCurve->getFirstDeriv(ptNear,vtF); if (vtF.isParallelTo(vtEnd)) { delete pCurve; return 1; } } else { //不落在上面 pCurve->getClosestPointTo(pt,ptOn,Adesk::kFalse); AcGeVector3d vtF; pCurve->getFirstDeriv(ptOn,vtF); if (vtF.isParallelTo(vtEnd)) { ptNear = ptOn; delete pCurve; return 2; } } delete pCurve; return 0; } void CopyElementSeg(AecEqui::AecCurveElement& eT,AcGePoint3d& pt,AcGePoint3d& ptNear,AecEqui::AecCurveElement& elNew) { // AcDbCurve* pCurve = NULL; AecComplexCurve::MakeCurve(eT,pCurve); if (pCurve == NULL) return; AcDbLine* pLn = AcDbLine::cast(pCurve); if (pLn != NULL) { elNew.ptGe[0] = pt; elNew.ptGe[1] = ptNear; elNew.ptGe[2] = ptNear; } AcDbArc* pArc = AcDbArc::cast(pCurve); if (pArc != NULL) { elNew.ptGe[0] = pt; elNew.ptGe[2] = ptNear; elNew.ptGe[1] = MidPoint(pt,ptNear); AcDbCircle cir; cir.setCenter(pArc->center()); cir.setRadius(pArc->radius()); cir.setNormal(AcGeVector3d::kZAxis); AcGePoint3d ptMid; cir.getClosestPointTo(elNew.ptGe[1],ptMid); elNew.ptGe[1] = ptMid; } delete pCurve; } Acad::ErrorStatus AecWall2DJoin::TrimEnd(AecDbXWall* pWallE,AecEqui::AecCurveElement& el,const AcGeVector3d& vtEnd) { AecComplexCurve draw2d; pWallE->GetDraw2dables(draw2d); AcGePoint3dArray arPts; arPts.append(el.ptGe[0]); if (arPts.find(el.ptGe[1]) == -1) arPts.append(el.ptGe[1]); AcGePoint3d ptTo; int nOnType = 0; AecEqui::AecCurveElement elSub,elAdd0,elAdd2; memset(&elSub,0,sizeof(AecEqui::AecCurveElement)); memset(&elAdd0,0,sizeof(AecEqui::AecCurveElement)); memset(&elAdd2,0,sizeof(AecEqui::AecCurveElement)); AecComplexCurve cmSub,cmAdd; double dDisMin0 = 999999999.0,dDisMin2 = 999999999.0; double dDis0 = 0.0,dDis2 = 0.0; AcGePoint3d ptTo0,ptTo2; AcGePoint3dArray arPt0,arPt2; AecEqui::AecCurveElement eT0,eT2; for (int i = 0;i < draw2d.length();i++) { AecEqui::AecCurveElement& eT = draw2d.atByRef(i); //找距离el的两端最近的点,如果在元素eT上,则取两端最近的点,返回实减 //找距离el的两端最近的点,如果不在元素eT上,则取两端最近的点返回实加 nOnType = FindNearPoint(el.ptGe[0],eT,ptTo,vtEnd); if (nOnType == 1)//落在上面,返回点为最近的端点 { CopyElementSeg(eT,el.ptGe[0],ptTo,elSub); cmSub.append(elSub); } if (nOnType == 2)//落在延长线上 { dDis0 = ptTo.distanceTo(el.ptGe[0]); if (dDis0 < dDisMin0) { dDisMin0 = dDis0; ptTo0 = ptTo; arPt0.removeAll(); arPt0.append(ptTo0); eT0 = eT; } } nOnType = FindNearPoint(el.ptGe[2],eT,ptTo,vtEnd); if (nOnType == 1)//落在上面,返回点为最近的端点 { CopyElementSeg(eT,el.ptGe[2],ptTo,elSub); cmSub.append(elSub); } if (nOnType == 2)//落在延长线上 { dDis2 = ptTo.distanceTo(el.ptGe[2]); if (dDis2 < dDisMin2) { dDisMin2 = dDis2; ptTo2 = ptTo; arPt2.removeAll(); arPt2.append(ptTo2); eT2 = eT; } } } if (!arPt0.isEmpty()) { CopyElementSeg(eT0,el.ptGe[0],arPt0.first(),elAdd0); cmAdd.append(elAdd0); } if (!arPt2.isEmpty()) { CopyElementSeg(eT2,el.ptGe[2],arPt2.first(),elAdd2); cmAdd.append(elAdd2); } AecCoverBooleanOper::BoolSubtract(draw2d,cmSub); //没有交集加入 if (!AecCoverBooleanOper::HasIntersection(draw2d,cmAdd)) { AecCoverBooleanOper::BoolUnite(draw2d,cmAdd); } if (!cmAdd.isEmpty() || !cmSub.isEmpty() ) { pWallE->SetDraw2dables(draw2d); } return Acad::eOk; } void AecWall2DJoin::AddXPart(AecDbXWall* pWallE,const AcGePoint3d& ptEnd,const AcGeVector3d& vtEnd,Adesk::Boolean bExtendSta,const AecEqui::AecCurveElement& el) { if (pWallE == NULL) return; WallData data; pWallE->GetWallData(data); AcDbCurve* pCurveEl = NULL; AecComplexCurve::MakeCurve((AecEqui::AecCurveElement&)el,pCurveEl); if (pCurveEl != NULL) { AcGeVector3d vt = vtEnd; vt.rotateBy(PI / 2.0,AcGeVector3d::kZAxis); vt.normalize(); AcGePoint3d pt1,pt2; pt1 = ptEnd + vt * 0.5 * data.dThick; pt2 = ptEnd - vt * 0.5 * data.dThick; double dDis = data.dThick; AecDbX3dPart* pPart = NULL; AcDbX3dSolid* pXSolid = NULL; if (!pWallE->IsVViewWall()) { //常规截面墙体 vt = vtEnd; vt.normalize(); AcDbLine lnPath; pt1 = ptEnd; pt2 = ptEnd + vt * dDis; pt1.z = data.dBomEl; pt2.z = data.dBomEl; lnPath.setStartPoint(pt1); lnPath.setEndPoint(pt2); AcDbRegion* pRegion = pWallE->GetSection(); if (pRegion != NULL) { //1.创建整体Solid AcGePoint3d ptOnRegion; pWallE->GetSpecialtyData()->GetAt(KEY_SECCEN,ptOnRegion); transfromRegion(pRegion,ptOnRegion,vt,pt1); int nPos = pWallE->GetNearPosition(ptEnd); pPart = new AecDbX3dPart; pPart->SetName(_T("ExAdd")); pPart->GetSpecialtyData()->SetAt(KEY_ADDTIONSHOW,TRUE); pPart->GetSpecialtyData()->SetAt(KEY_POS,nPos); pPart->GetSpecialtyData()->SetAt(KEY_FORSLICE,TRUE); pXSolid = new AcDbX3dSolid; if ( pXSolid->CreateExtrude(pRegion,lnPath) ) { pPart->AddX3dSolid(pXSolid); pPart->Create(); //pWallE->AddX3dPart(pPart,AcDb::kBoolUnite);//???? //TEST /*AcDb3dSolid* pSolid = pXSolid->GetDraw3dSolid(); pSolid->setColorIndex(3); AddToModelSpace(pSolid); */ } else { delete pPart; delete pXSolid; } delete pRegion; } } else { //...是立面拉伸墙体 } } } //获取统一的墙体基线,用完需要删除 AcDbCurve* AecWall2DJoin::GetWallBaseCurve(AecDbXWall* pWall) { AcDbObjectId id = pWall->objectId(); TCHAR tmpStr[256]; id.handle().getIntoAsciiBuffer(tmpStr); AcDbCurve* pBaseCurve = NULL; if (m_mapIdToPtr.Lookup(tmpStr,(void*&)pBaseCurve)) { return pBaseCurve; } if (pWall->IsVViewWall()) { pBaseCurve = pWall->GetAsNativeCurveOfVView(); } else { pBaseCurve = pWall->GetBaseCurve(); } m_mapIdToPtr.SetAt(tmpStr,(void*)pBaseCurve); return pBaseCurve; } //最多20种由重到轻材质的比重 int AecWall2DJoin::MaterialWeight(LPCTSTR pszMaterial) { //最多20种由重到轻材质 static int nMaxWallWeight = 20; for (int i = 0;i < 20;i++) { if (g_pszWallMaterials[i] == NULL) return 0; if (_tcscmp(g_pszWallMaterials[i], pszMaterial) == 0) { return (nMaxWallWeight - i); } } return 0; }