#include "StdAfx.h" #include "KTCadUtility.h" #include "KTCadUtilityEx.h" #include "BZJJDlg.h" #include "CoreTools.h" #include "dbobjptr.h" #include "AecDbWall.h" #include "AecDbEwEquipment.h" #include "AecDbOpening.h" #include "AecDbColumn.h" #include "ZZDZDlg.h" #define DATA_JIEJU_WIDTH _T("__DATA_WIDTH__") // 洁具宽 #define DATA_JIEJU_LENGTH _T("__DATA_LENGTH__") // 洁具长 #define DATA_JIEJU_INS_DIST_TO_WALL _T("__DATA_INS_DIST_TO_WALL__") // 洁具插入点据墙距离 #define DATA_JIEJU_SPACE _T("__DATA_LENGTH__") // 洁具长 #define DATA_GB_LENGTH 1200 // 隔板进深 #define DATA_GB_ELEV 400 // 隔板据洁具底部的标高 #define DATA_GB_HEIGTH 800 // 隔板高 #define DATA_GB_THICK 25 // 隔板厚 #define DATA_DOOR_WIDTH 600 // 门板宽 #define DATA_DOOR_NAME_2D _T("KTDOOR01") // 门名称 #define DATA_DOOR_NAME_3D _T("KTDOOR01_3D") // 门名称 #define DATA_DOOR_FILE_2D _T("KTDOOR02.dwg") namespace { BOOL CreateBlockRecord(LPCTSTR pszSrc, LPCTSTR pszBlk) { AcDbObjectId idRec; AcDbDatabase *pWorkDb = acdbHostApplicationServices()->workingDatabase(); AcDbBlockTable *pTbl = NULL; pWorkDb->getSymbolTable(pTbl, AcDb::kForRead); if (pTbl != NULL) { if (Acad::eOk == pTbl->getAt(pszBlk, idRec)) { pTbl->close(); return TRUE; } pTbl->close(); } AcDbDatabase *pDb = new AcDbDatabase(false); ASSERT(pDB != NULL); if (pDb->readDwgFile(pszSrc, AcDbDatabase::kForReadAndAllShare) != Acad::eOk) { delete pDb; return FALSE; } AcDbBlockTable *pBT = NULL; pDb->getSymbolTable(pBT, AcDb::kForRead); if (pBT == NULL) { delete pDb; return FALSE; } AcDbObjectId idBlock; pBT->getAt(pszBlk, idBlock); pBT->close(); AcDbDatabase *pTempDb = NULL; pDb->wblock(pTempDb, idBlock); delete pDb; if (pTempDb == NULL) return FALSE; if (pWorkDb->insert(idRec, pszBlk, pTempDb) != Acad::eOk) { delete pTempDb; return FALSE; } delete pTempDb; return TRUE; } struct resbuf* makeFence(ads_point ptCen , const AcGeVector3d &X , const AcGeVector3d &Y) { AcGePoint3d pt[4]; pt[0] = asPnt3d(ptCen); pt[0] += .5 * Y; pt[0] += .5 * X; pt[1] = pt[0] - Y; pt[2] = pt[1] - X; pt[3] = pt[2] + Y; return acutBuildList(RTPOINT, pt[0], RTPOINT, pt[1], RTPOINT, pt[2], RTPOINT, pt[3], RTPOINT, pt[0], 0); } struct resbuf* makeFence(ads_point ptCen) { double dSize = CoreTools::PixelToWcs(5);//5 return makeFence(ptCen, AcGeVector3d::kXAxis * dSize, AcGeVector3d::kYAxis * dSize); } struct resbuf* makeFence(ads_point pt1, ads_point pt2) { double dSize = CoreTools::PixelToWcs(5);//5 AcGeVector3d X(asPnt3d(pt2) - asPnt3d(pt1)); AcGeVector3d Y(X); Y.rotateBy(PI * .5, AcGeVector3d::kZAxis); Y.normalize(); Y *= dSize; return makeFence(asDblArray(CoreTools::MidPt(asPnt3d(pt2), asPnt3d(pt1))) , X, Y); } bool collectJieJu(AcDbObjectIdArray &ids) { ads_name ss, ent; acutPrintf(_T("\n请输入一直线,用来选择通过这条直线的洁具!")); ads_point adspt1, adspt2; int nRes = acedGetPoint(NULL, _T("\n选择洁具开始点:"), adspt1); if (nRes != RTNORM) return false; nRes = acedGetPoint(adspt1, _T("\n选择洁具结束点:"), adspt2); if (nRes != RTNORM) return false; struct resbuf *ptlst = makeFence(adspt1, adspt2); struct resbuf *pRb = acutBuildList(RTDXF0, _T("AEC_DBWEQUIPMENT"), 0); nRes = acedSSGet(_T("CP"), ptlst, NULL, pRb, ss); acutRelRb(pRb); acutRelRb(ptlst); if (nRes != RTNORM) { acutPrintf(_T("\n选择洁具失败!")); return false; } Adesk::Int32 lLen = 0; acedSSLength(ss, &lLen); AcDbObjectId id; for (int i(0); i < lLen; ++i) { acedSSName(ss, i, ent); acdbGetObjectId(id, ent); if (id.isValid()) ids.append(id); } acedSSFree(ss); return !ids.isEmpty(); } void getGBPosition(const AcDbObjectIdArray &ids , const double &dWallLen , std::vector &segs , const bool &hasDoor , std::vector &wallsWithDoor) { if (ids.isEmpty()) return; AcGeVector3d vtDir; AcGePoint3d pt1, pt2, pt; // 取第一个的几何尺寸 AcDbObjectPointer equ(ids.first(), AcDb::kForRead); if (equ.openStatus() != Acad::eOk) return; double dWidth(.0), dLength(.0), dSpaceWall(.0), dSpace(.0); if (!equ->GetSpecialtyData(AcDb::kForRead)->GetAt(DATA_JIEJU_WIDTH, dWidth) || !equ->GetSpecialtyData(AcDb::kForRead)->GetAt(DATA_JIEJU_LENGTH, dLength) || !equ->GetSpecialtyData(AcDb::kForRead)->GetAt(DATA_JIEJU_SPACE, dSpace) || !equ->GetSpecialtyData(AcDb::kForRead)->GetAt(DATA_JIEJU_INS_DIST_TO_WALL, dSpaceWall)) { acutPrintf(_T("\n请使用“布置洁具”命令生成洁具!")); return; } equ->GetInsert(pt1, vtDir); equ.close(); vtDir.rotateBy(-PI * .5, AcGeVector3d::kZAxis); vtDir.normalize(); AcGeVector3d vt(vtDir); // 洁具布置方向 vt.rotateBy(PI * .5, AcGeVector3d::kZAxis); vt.normalize(); for (int i(0); i < ids.length() - 1; ++i) { AcDbObjectPointer ptr1(ids[i], AcDb::kForRead); AcDbObjectPointer ptr2(ids[i + 1], AcDb::kForRead); if (ptr1.openStatus() == Acad::eOk && ptr2.openStatus() == Acad::eOk) { ptr1->GetInsert(pt1, vt); ptr2->GetInsert(pt2, vt); vt = pt2 - pt1; dSpace = pt1.distanceTo(pt2); pt = CoreTools::MidPt(pt1, pt2); pt1 = pt - vtDir * dSpaceWall; pt2 = pt1 + vtDir * dWallLen; segs.push_back(AcGeLineSeg3d(pt1, pt2)); } } vt.normalize(); AcGeMatrix3d mat; // 补上第一个 AcGeLineSeg3d lnFirst(*segs.begin()); mat.setToTranslation(-vt * dSpace); lnFirst.transformBy(mat); segs.insert(segs.begin(), lnFirst); // 补上最后一个 AcGeLineSeg3d lnEnd(*segs.rbegin()); mat.setToTranslation(vt * dSpace); lnEnd.transformBy(mat); segs.push_back(lnEnd); if (!hasDoor) return; for (size_t i(0); i < segs.size() - 1; ++i) { AcGeLineSeg3d &seg1(segs[i]), &seg2(segs[i + 1]); pt1 = seg1.endPoint(); pt2 = seg2.endPoint(); wallsWithDoor.push_back(AcGeLineSeg3d(pt1, pt2)); } } AcDbObjectId makeGB(const AcGeLineSeg3d &ln , const double &dSpaceElev = DATA_GB_ELEV , const double &dHeight = DATA_GB_HEIGTH , const double &dThick = DATA_GB_THICK) { AecDbXWall *pWall = new AecDbXWall; AcGePoint3d ptS(ln.startPoint()), ptE(ln.endPoint()); double dElev = ptS.z + dSpaceElev; ptS.z = ptE.z = .0; pWall->SetBaseCurve(ptS, ptE); pWall->GetSpecialtyData()->SetAt(KEY_MATERIAL, _T("轻质隔墙")); pWall->SetWallData(dThick, dHeight, dElev, kMid); AcDbObjectId id; CoreTools::AddToModelSpace(pWall, NULL, true, &id); return id; } bool makeDoor( AcDbObjectId idWall , const AcGePoint3d &ptIns , const AcGeVector3d &vtDoor , LPCTSTR pszBlk2D , LPCTSTR pszBlk3D , const double &dHeight , const double &dWidth) { AcDbObjectPointerwall(idWall, AcDb::kForRead); if (wall.openStatus() != Acad::eOk) return false; WALLDATA wallData; ::memset(&wallData, 0, sizeof(WALLDATA)); wall->GetWallData(wallData); wall->close(); AecDbXOpening *pOpen = new AecDbXOpening; OpeningData oData; ::memset(&oData, 0, sizeof(OpeningData)); oData.dHeight = DATA_GB_HEIGTH; oData.dWidth = DATA_DOOR_WIDTH; oData.dBomEl = wallData.dBomEl; oData.nFlag = 0; oData.nType = 2; oData.ptPos = ptIns; _tcscpy(oData.szBlockName2d, pszBlk2D); _tcscpy(oData.szBlockName3d, pszBlk3D); _tcscpy(oData.szName, pszBlk2D); pOpen->SetOpeningData(oData, idWall); AecComplexCurve win2d; pOpen->GetStandardDraw2d(win2d, false); AcDbObjectId idOpen; CKTCadUtility::AddToBlockTableRecord(pOpen); idOpen = pOpen->objectId(); AcGeVector3d vtDef; pOpen->GetDoorOpenDir(vtDef); if (!vtDef.isCodirectionalTo(vtDoor)) pOpen->GetSpecialtyData()->SetAt(PIPE_TDIR, -1); pOpen->close(); wall.open(idWall, AcDb::kForWrite); if (wall.openStatus() == Acad::eOk) { wall->AppendAssocPart(idOpen); wall->SubtractDraw2d(win2d); } } bool insertColumn(const AcGePoint3d &pt, ColumnParam ¶m) { typedef bool (_cdecl *func_OnInsertByPoint) (ads_point, ColumnParam&); #ifndef ZWCAD HINSTANCE hmod = ::LoadLibrary(FilePath::GetArxDir() + _T("\\pool3dcmd.arx")); #else HINSTANCE hmod = ::LoadLibrary(FilePath::GetArxDir() + _T("\\pool3dcmd.zrx")); #endif if (!hmod) return NULL; func_OnInsertByPoint proc = (func_OnInsertByPoint)::GetProcAddress(hmod, "OnInsertByPoint"); if (!proc) { ::FreeLibrary(hmod); return NULL; } bool brel = proc(asDblArray(pt), param); ::FreeLibrary(hmod); return brel; } } //柱子底座 void implement_ZZDZ() { CAcModuleResourceOverride myResources; CZZDZDlg dlg; if (dlg.DoModal() != IDOK) return; ads_name ent; struct resbuf *pRb = acutBuildList(RTDXF0, _T("AEC_DBCOLMN"), 0); int nRes = CKTCadUtility::SelectEntity(_T("\n请选择一个柱子:"), ent, pRb); acutRelRb(pRb); if (nRes != RTNORM) return; AcDbObjectId id; acdbGetObjectId(id, ent); if (!id.isValid()) return; AcDbObjectPointer pColumn(id, AcDb::kForRead); if (pColumn.openStatus() != Acad::eOk) return; ColumnParam data; ::memset(&data, 0, sizeof(ColumnParam)); pColumn->GetColumnData(data); data.m_dBomEl -= dlg.m_iHeight; data.m_dH = dlg.m_iHeight; if (dlg.m_bRect) { data.m_nShape = 0; data.m_dXScale = dlg.m_iLength; data.m_dYScale = dlg.m_iWidth; _tcscpy(data.m_sBlockName, _T("_FZH.dwg")); } else { data.m_nShape = 1; data.m_dXScale = dlg.m_iRadius; data.m_dYScale = dlg.m_iRadius; _tcscpy(data.m_sBlockName, _T("_YZH.dwg")); } data.m_szNo[0] = _T('\0'); data.m_dXExtend = data.m_dYExtend = .0; _tcscpy(data.m_sMaterial, _T("钢筋混凝土")); data.bPtPos = false; data.ptPos = pColumn->GetPosition(); data.ptPos.z -= dlg.m_iHeight; insertColumn(data.ptPos, data); } //布置洁具 void implement_BZJJ() { ads_name ss, ent; ads_point adspt1, adspt2, adspt3; int nRes = acedGetPoint(NULL, _T("\n请选择墙体上布置开始点:"), adspt1); if (nRes != RTNORM) return; nRes = acedGetPoint(adspt1, _T("\n请选择墙体上布置结束点:"), adspt2); if (nRes != RTNORM) return; // pt1 点附近的墙 struct resbuf *pointlist = makeFence(adspt1); struct resbuf *pRb = acutBuildList(RTDXF0, _T("AEC_DBWALL"), 0); nRes = acedSSGet(_T("CP"), pointlist, NULL, pRb, ss); acutRelRb(pointlist); acutRelRb(pRb); if (nRes != RTNORM) { acutPrintf(_T("\n没有找到墙体!")); return; } // 得到第一面墙 AcDbObjectId id; Adesk::Int32 lLen = 0; acedSSLength(ss, &lLen); if (lLen > 0) { acedSSName(ss, 0, ent); acdbGetObjectId(id, ent); } acedSSFree(ss); if (!id.isValid()) { acutPrintf(_T("\n未找到墙体!")); return; } AcDbObjectPointer wall(id, AcDb::kForRead); if (wall.openStatus() != Acad::eOk) { acutPrintf(_T("\n墙体打开失败!")); return; } WALLDATA data; ::memset(&data, 0, sizeof(WALLDATA)); wall->GetWallData(data); AcDbCurve *_pCurve = wall->GetBaseCurve(); wall.close(); if (!_pCurve) { acutPrintf(_T("\n墙体基线获取失败!")); return; } std::shared_ptrpCurve(_pCurve); AcGePoint3d pt1, pt2, pt3; CoreTools::UCS2WCS(asPnt3d(adspt1), pt1); CoreTools::UCS2WCS(asPnt3d(adspt2), pt2); double dCurveLen(.0); AcGePoint3d ptS, ptE, ptM; pCurve->getEndPoint(ptE); pCurve->getDistAtPoint(ptE, dCurveLen); pCurve->getClosestPointTo(pt1, ptS); pCurve->getClosestPointTo(pt2, ptE); nRes = acedGetPoint(adspt2, _T("\n请选择墙体侧方向:"), adspt3); if (nRes != RTNORM) return; CoreTools::UCS2WCS(asPnt3d(adspt3), pt3); pCurve->getClosestPointTo(pt3, ptM, true); AcGeVector3d vt = pt3 - ptM; vt.normalize(); if (vt.length() < 1e-4) { acutPrintf(_T("\n选择方向时,不要选择墙基线上的点!")); return; } CAcModuleResourceOverride myResources; CBZJJDlg dlg; if (IDOK != dlg.DoModal()) return; double dParam1, dParam2; pCurve->getParamAtPoint(ptS, dParam1); pCurve->getParamAtPoint(ptE, dParam2); if (dParam1 > dParam2) // 交换 { pCurve->reverseCurve(); pCurve->getClosestPointTo(pt1, ptS); pCurve->getClosestPointTo(pt2, ptE); } if (dlg.m_dFirst >= dCurveLen || dlg.m_dSpace >= dCurveLen || dlg.m_dFirst + dlg.m_dWidth * .5 >= dCurveLen) { acutPrintf(_T("\n请检查头部保留空间或者墙体长度!")); return; } if (pCurve->getPointAtDist(dlg.m_dFirst + dlg.m_dWidth * .5, ptS) != Acad::eOk) return; double dist1(.0), dist2(.0); pCurve->getDistAtPoint(ptS, dist1); pCurve->getDistAtPoint(ptE, dist2); dCurveLen = dist2 - dist1; int count = int(dCurveLen / dlg.m_dSpace); AcGeVector3d vtDir(vt); vtDir.rotateBy(PI * .5, AcGeVector3d::kZAxis); for (int i(0); i < count + 1; ++i) { AecDbEwEquipment *pEqu = dlg.getEquPtr(); if (!pEqu) continue; #ifndef NDEBUG AcDbCircle *pCir = new AcDbCircle(ptS, AcGeVector3d::kZAxis, 10); CoreTools::AddToModelSpace(pCir); #endif // !NDEBUG ptS += vt * (dlg.m_dSpaceWall + data.dThick * .5 + dlg.m_dLength * .5); #ifndef NDEBUG pCir = new AcDbCircle(ptS, AcGeVector3d::kZAxis, 10); CoreTools::AddToModelSpace(pCir); #endif // !NDEBUG pEqu->SetInsert(ptS , vtDir); // 设置一些基本数据 pEqu->GetSpecialtyData()->SetAt(DATA_JIEJU_WIDTH, dlg.m_dWidth); pEqu->GetSpecialtyData()->SetAt(DATA_JIEJU_LENGTH, dlg.m_dLength); pEqu->GetSpecialtyData()->SetAt(DATA_JIEJU_SPACE, dlg.m_dSpace); pCurve->getClosestPointTo(ptS, ptM); pEqu->GetSpecialtyData()->SetAt(DATA_JIEJU_INS_DIST_TO_WALL, ptS.distanceTo(ptM) - data.dThick * .5); CoreTools::AddToModelSpace(pEqu); dist1 += dlg.m_dSpace; pCurve->getPointAtDist(dist1, ptS); } } //布置隔板 void implement_BZGB() { AcDbObjectIdArray ids; if (!collectJieJu(ids)) return; double dWallLen(DATA_GB_LENGTH); acedGetReal(_T("\n请输入隔板进深<1200>:"), &dWallLen); std::vector segs, wallsWithDoor; getGBPosition(ids, dWallLen, segs, false, wallsWithDoor); for (size_t i(0); i < segs.size(); ++i) makeGB(segs[i]); } //布置隔间 void implement_BZGJ() { AcDbObjectIdArray ids; if (!collectJieJu(ids)) return; double dWallLen(DATA_GB_LENGTH); acedGetReal(_T("\n请输入隔板进深<1200>:"), &dWallLen); std::vector segs, wallsWithDoor; getGBPosition(ids, dWallLen, segs, true, wallsWithDoor); if (segs.empty()) return; for (size_t i(0); i < segs.size(); ++i) makeGB(segs[i]); // 通过 隔板得到门的开合方向,隔板是从墙向洁具方向绘制的。 AcGeLineSeg3d &seg(*segs.begin()); AcGeVector3d vtDoor = seg.direction().normalize(); CString blkPath(FilePath::GetRootDir() + _T("\\Support\\Cells\\")); CreateBlockRecord(blkPath + DATA_DOOR_FILE_2D, DATA_DOOR_NAME_2D); CreateBlockRecord(blkPath + DATA_DOOR_NAME_3D + _T(".dwg"), DATA_DOOR_NAME_3D); AcGePoint3d ptIns(AcGePoint3d::kOrigin); AcDbObjectId idWall(AcDbObjectId::kNull); for (size_t i(0); i < wallsWithDoor.size(); ++i) { AcGeLineSeg3d &seg(wallsWithDoor[i]); idWall = makeGB(seg); ptIns = CoreTools::MidPt(seg.startPoint(), seg.endPoint()); ptIns.z = .0; makeDoor(idWall , ptIns , vtDoor , DATA_DOOR_NAME_2D , DATA_DOOR_NAME_3D , DATA_GB_HEIGTH , DATA_DOOR_WIDTH); } }