Files
envi-code/SourceCode/Code2026/ArchCmd/command_part1.cpp
T

585 lines
15 KiB
C++
Raw Normal View History

2026-09-28 15:28:50 +08:00
#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<AcGeLineSeg3d> &segs
, const bool &hasDoor
, std::vector<AcGeLineSeg3d> &wallsWithDoor)
{
if (ids.isEmpty()) return;
AcGeVector3d vtDir;
AcGePoint3d pt1, pt2, pt;
// 取第一个的几何尺寸
AcDbObjectPointer<AecDbEwEquipment> 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<AecDbEwEquipment> ptr1(ids[i], AcDb::kForRead);
AcDbObjectPointer<AecDbEwEquipment> 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)
{
AcDbObjectPointer<AecDbXWall>wall(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 &param)
{
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<AecDbColumn> 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<AecDbXWall> 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_ptr<AcDbCurve>pCurve(_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<AcGeLineSeg3d> 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<AcGeLineSeg3d> 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);
}
}