Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

585 lines
15 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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);
}
}