Files

701 lines
17 KiB
C++
Raw Permalink Normal View History

2026-10-04 00:04:20 +08:00
#include "StdAfx.h"
2026-09-28 15:28:50 +08:00
#include "EWCheckerData.h"
#include <sstream>
#include "aecdbearthworm.h"
#include "KTCADUtilityEx.h"
#include "BrowseForFolder.h"
#include "stakeoper.h"
#include <fstream>
#include "MakeDim.h"
#include "UITools.h"
#include "TJSZDlg.h"
int DLLIMPEXP GetConnectedWorms(const AcDbObjectId& idHit, AcDbObjectIdArray& arIds);
int DLLIMPEXP GetConnectedWorms(const AecDbEarthWorm* pEW, AcDbObjectIdArray& arIds);
extern Acad::ErrorStatus AddToModelSpace(AcDbEntity* pEnt,AcDbDatabase* pDb,bool bClose);
namespace
{
using namespace MK_DIM;
using namespace GLStatistics;
struct Statistics
{
2026-10-04 00:04:20 +08:00
CString sStake; // 桩号字符串
CString sRoom; // 舱室名称
CString sType; // 节点类型字符串
NodeDim::ENodeType eType; // 节点类型
double dDist; // 桩号距离
double dVenNum; // 换气次数,只有在 eType 为eVenDoghouse时有效
2026-09-28 15:28:50 +08:00
};
2026-10-04 00:04:20 +08:00
// 设置
2026-09-28 15:28:50 +08:00
TJConfig g_config;
2026-10-04 00:04:20 +08:00
// 集水井
2026-09-28 15:28:50 +08:00
std::vector<Statistics> g_DrainWells;
2026-10-04 00:04:20 +08:00
// 料口
2026-09-28 15:28:50 +08:00
std::vector<Statistics> g_Doghouses;
2026-10-04 00:04:20 +08:00
// 通风口
2026-09-28 15:28:50 +08:00
std::vector<Statistics> g_VenDoghouses;
2026-10-04 00:04:20 +08:00
// 防火墙
2026-09-28 15:28:50 +08:00
std::vector<Statistics> g_Firewalls;
2026-10-04 00:04:20 +08:00
// 逃生口
2026-09-28 15:28:50 +08:00
std::vector<Statistics> g_EscapeHatchs;
2026-10-04 00:04:20 +08:00
// 引出口
2026-09-28 15:28:50 +08:00
std::vector<Statistics> g_Outlets;
2026-10-04 00:04:20 +08:00
// 舱室列表
2026-09-28 15:28:50 +08:00
std::vector<CString> g_Tanks;
2026-10-04 00:04:20 +08:00
// 舱室长宽高信息 (舱名-(宽+高))
2026-09-28 15:28:50 +08:00
std::map<CString, std::pair<double, double>> g_TankWHs;
void initGlobalData(std::vector<NodeDim> &nodes)
{
g_DrainWells.clear();
g_Doghouses.clear();
g_VenDoghouses.clear();
g_Firewalls.clear();
g_EscapeHatchs.clear();
g_Outlets.clear();
Statistics stat;
for (size_t i = 0; i < nodes.size(); ++i)
{
NodeDim &nd = nodes[i];
//if (!GLTools::analyStakeString(nd.stake, stat.dDist)) continue;
stat.sStake = nd.stake;
stat.dDist = nd.distFromHead;
NodeDim::RoomTypes::const_iterator itRT = nd.room_types.begin();
for (; itRT != nd.room_types.end(); ++itRT)
{
if (itRT->second.empty()) continue;
stat.sRoom = itRT->first;
std::set<NodeDim::ENodeType>::const_iterator itType = itRT->second.begin();
for (; itType != itRT->second.end(); ++itType)
{
stat.eType = *itType;
stat.sType = getNodeName(*itType);
switch (*itType)
{
case NodeDim::eDrainWell:
g_DrainWells.push_back(stat);
break;
case NodeDim::eFireWall:
g_Firewalls.push_back(stat);
break;
case NodeDim::eVenDoghouse:
g_VenDoghouses.push_back(stat);
break;
case NodeDim::eEscapeHatch:
g_EscapeHatchs.push_back(stat);
break;
case NodeDim::eDoghouse:
g_Doghouses.push_back(stat);
break;
case NodeDim::eOutlet:
g_Outlets.push_back(stat);
break;
default:
break;
}
}
}
}
}
}
namespace GLStatistics
{
using namespace MK_DIM;
bool init(bool includeFire)
{
2026-10-04 00:04:20 +08:00
// 选择管廊
2026-09-28 15:28:50 +08:00
ads_point adsPnt;
ads_name adsName;
2026-10-04 00:04:20 +08:00
int nRes = acedEntSel(_T("\n请选择要校核的管廊。"), adsName, adsPnt);
2026-09-28 15:28:50 +08:00
if (nRes != RTNORM) return false;
AcDbObjectId idEw(AcDbObjectId::kNull);
acdbGetObjectId(idEw, adsName);
ERoom room;
double w(.0), h(.0);
OPENOBJ_BEGIN(idEw, AcDb::kForRead, AecDbEarthWorm, pEw)
if (!pEw)
{
2026-10-04 00:04:20 +08:00
acutPrintf(_T("\n请选择一段管廊。"));
2026-09-28 15:28:50 +08:00
return false;
}
g_Tanks.clear();
g_TankWHs.clear();
pEw->GetRoomCount();
for (int i = 0; i < pEw->GetRoomCount(); ++i)
{
if (pEw->GetRoom(i, room))
{
w = room.ptGe[0].distanceTo(room.ptGe[1]);
h = room.ptGe[1].distanceTo(room.ptGe[2]);
}
g_Tanks.push_back(pEw->GetRoomTypeByIdx(i));
g_TankWHs.insert(std::make_pair(*g_Tanks.rbegin(), std::make_pair(w, h)));
}
OPENOBJ_END()
std::vector<NodeDim> nodes(0);
collectNodeInfo_Statistic(idEw, nodes, includeFire);
if (nodes.empty()) return false;
initGlobalData(nodes);
return true;
}
std::vector<Statistics>& getGlobalData(const MK_DIM::NodeDim::ENodeType &type)
{
switch (type)
{
case MK_DIM::NodeDim::eFireWall:
return g_Firewalls;
case MK_DIM::NodeDim::eDoghouse:
return g_Doghouses;
case MK_DIM::NodeDim::eVenDoghouse:
return g_VenDoghouses;
case MK_DIM::NodeDim::eOutlet:
return g_Outlets;
case MK_DIM::NodeDim::eDrainWell:
return g_DrainWells;
case MK_DIM::NodeDim::eEscapeHatch:
return g_EscapeHatchs;
default:
return g_Firewalls;
}
return g_Firewalls;
}
void statisticEarthworm(const MK_DIM::NodeDim::ENodeType &type)
{
if (!init(type == MK_DIM::NodeDim::eFireWall)) return;
2026-10-04 00:04:20 +08:00
// 弹对话框
2026-09-28 15:28:50 +08:00
CAcModuleResourceOverride myResources;
CTJSZDlg dlg(type, g_Tanks);
if (dlg.DoModal() != IDOK) return;
readConfig(g_config);
if (g_config.empty()) return;
std::vector<Statistics> &ss = getGlobalData(type);
GLReport::CEWGLReport report;
GLReport::CEWTank tank;
GLReport::EWNodeData data;
for (size_t tk = 0; tk < g_Tanks.size(); ++tk)
{
tank.clear();
CString &name(g_Tanks[tk]);
tank.setName(name);
tank.setWidth(g_TankWHs[name].first);
tank.setHeight(g_TankWHs[name].second);
tank.setOption(g_config[name]);
for (size_t i = 0; i < ss.size(); ++i)
{
Statistics &st(ss[i]);
if (st.sRoom == name)
{
data.m_stake = st.sStake;
data.m_dDistance = st.dDist;
tank.appendData(type, data);
}
}
tank.calcData(type);
report.appendTank(tank);
}
report.outputCADTable(type);
return;
}
void statisticDrainWell()
{
statisticEarthworm(MK_DIM::NodeDim::eDrainWell);
}
void statisticDoghouse()
{
statisticEarthworm(MK_DIM::NodeDim::eDoghouse);
}
void statisticVenDoghouse()
{
statisticEarthworm(MK_DIM::NodeDim::eVenDoghouse);
}
void statisticFireWall()
{
statisticEarthworm(MK_DIM::NodeDim::eFireWall);
}
void statisticEscapeHatch()
{
statisticEarthworm(MK_DIM::NodeDim::eEscapeHatch);
}
void statisticOutlet()
{
statisticEarthworm(MK_DIM::NodeDim::eOutlet);
}
CString getConfigFilePath()
{
CString path = FilePath::getProgramDataFolder();
path += _T("\\tjsz.dat");
return path;
}
void readConfig(TJConfig &config)
{
config.clear();
CString str(_T(""));
CString path = getConfigFilePath();
if (_taccess(path, 0x0) != 0x0) return;
std::vector<CString> sections(0);
INITools::getSections(path, sections);
std::map<CString, CString> mapV;
for (size_t i = 0; i < sections.size(); ++i)
{
const CString &sec(sections[i]);
INITools::getSectionContent(path, sec, mapV);
if (mapV.empty()) continue;
config.insert(std::make_pair(sec, std::map<CString, double>()));
for (std::map<CString, CString>::const_iterator it = mapV.begin(); it != mapV.end(); ++it)
{
config[sec].insert(std::make_pair(it->first, _ttof(it->second)));
}
}
return;
}
}
namespace
{
AcDbObjectId getTableStyleID(LPCTSTR psz)
{
AcDbObjectId idTblStyle(AcDbObjectId::kNull);
if (!psz) return idTblStyle;
AcDbDictionary *pDict(NULL);
acdbHostApplicationServices()->workingDatabase()->getTableStyleDictionary(pDict, AcDb::kForRead);
pDict->getAt(psz, idTblStyle);
pDict->close();
return idTblStyle;
}
AcDbObjectId getTextStyleID(LPCTSTR psz)
{
AcDbObjectId idTxtStyle(AcDbObjectId::kNull);
if (!psz) return idTxtStyle;
AcDbTextStyleTable *pTextStyle(NULL);
acdbHostApplicationServices()->workingDatabase()->getTextStyleTable(pTextStyle, AcDb::kForRead);
pTextStyle->getAt(psz, idTxtStyle);
pTextStyle->close();
return idTxtStyle;
}
}
namespace GLReport
{
AcDbTable* CEWGLReport::outputDataCAD(const MK_DIM::NodeDim::ENodeType &type)
{
AcDbTable *pTbl = new AcDbTable;
AcDbObjectId idTblStyle(getTableStyleID(_T("Standard")));
if (!idTblStyle.isValid()) return NULL;
pTbl->setTableStyle(idTblStyle);
AcDbObjectId idTextStyle(getTextStyleID(_T("Standard")));
if (!idTextStyle.isValid()) return NULL;
pTbl->setTextStyle(idTextStyle);
2026-10-04 00:04:20 +08:00
// 总列数 (舱室名称|桩号范围|长度)
2026-09-28 15:28:50 +08:00
int cols((int)m_tanks.size() * 2 + 1);
2026-10-04 00:04:20 +08:00
// 设置列数
2026-09-28 15:28:50 +08:00
pTbl->setNumColumns(cols);
pTbl->setNumRows(3);
2026-10-04 00:04:20 +08:00
// 合并第0行
2026-09-28 15:28:50 +08:00
pTbl->mergeCells(0, 0, 0, cols - 1);
2026-10-04 00:04:20 +08:00
// 为第0行打上文字
pTbl->setTextString(0, 0, MK_DIM::getNodeName(type) + _T("统计"));
2026-09-28 15:28:50 +08:00
2026-10-04 00:04:20 +08:00
// 合并第1行
2026-09-28 15:28:50 +08:00
for (int i = 0; i < m_tanks.size(); ++i)
{
pTbl->mergeCells(1, 1, i * 2 + 1, i * 2 + 2);
pTbl->setTextString(1, i * 2 + 1, m_tanks[i].getName());
}
2026-10-04 00:04:20 +08:00
pTbl->setTextString(2, 0, _T("序号"));
2026-09-28 15:28:50 +08:00
for (int i = 0; i < m_tanks.size(); ++i)
{
2026-10-04 00:04:20 +08:00
pTbl->setTextString(2, i * 2 + 1, _T("桩号范围"));
pTbl->setTextString(2, i * 2 + 2, _T("长度(m)"));
2026-09-28 15:28:50 +08:00
}
pTbl->setColumnWidth(30);
const EWNodeDatas *pDatas(NULL);
EWNodeDatas datas(0);
AcCmColor clr;
clr.setColorIndex(1);
2026-10-04 00:04:20 +08:00
// 总行数
2026-09-28 15:28:50 +08:00
int rows(3);
int col1(0), col2(0);
for (size_t tk = 0; tk < m_tanks.size(); ++tk)
{
pDatas = NULL;
const CEWTank &tank = m_tanks[tk];
std::map<CString, double> &conf = g_config[tank.getName()];
switch (type)
{
case MK_DIM::NodeDim::eFireWall: pDatas = &tank.getFireZoneData(); break;
case MK_DIM::NodeDim::eEscapeHatch: pDatas = &tank.getEscapeData(); break;
case MK_DIM::NodeDim::eDoghouse: pDatas = &tank.getDoghouseData(); break;
case MK_DIM::NodeDim::eOutlet: pDatas = &tank.getOutletData(); break;
case MK_DIM::NodeDim::eDrainWell: pDatas = &tank.getWellData(); break;
default: break;
}
col1 = (int)tk * 2 + 1;
col2 = (int)tk * 2 + 2;
rows = 3;
if (pDatas)
{
for (size_t i = 0; i < pDatas->size(); ++i)
{
const EWNodeData &da = pDatas->at(i);
if (pTbl->numRows() <= rows)
pTbl->insertRows(rows, 5);
pTbl->setTextString(rows, col1, da.m_stake.c_str());
pTbl->setTextString(rows, col2, _convert_<std::wstring , double>(da.m_dDistance).c_str());
if (da.m_dDistance > conf[MK_DIM::getNodeName(type)])
{
pTbl->setContentColor(rows, col1, clr);
pTbl->setContentColor(rows, col2, clr);
}
++rows;
}
}
}
CString str(_T(""));
for (size_t i= 3; i < pTbl->numRows(); ++i)
{
str.Format(_T("%d"), i - 2);
pTbl->setTextString((int)i, 0, str);
}
int tblHeight(3);
pTbl->setTextHeight(tblHeight);
pTbl->setRowHeight(5);
pTbl->generateLayout();
return pTbl;
}
AcDbTable* CEWGLReport::outputVentilateCAD()
{
CString str(_T(""));
AcDbTable *pTbl = new AcDbTable;
AcDbObjectId idTblStyle(getTableStyleID(_T("Standard")));
if (!idTblStyle.isValid()) return NULL;
pTbl->setTableStyle(idTblStyle);
AcDbObjectId idTextStyle(getTextStyleID(_T("Standard")));
if (!idTextStyle.isValid()) return NULL;
pTbl->setTextStyle(idTextStyle);
2026-10-04 00:04:20 +08:00
// 总列数 (舱室名称|桩号范围|长度)
2026-09-28 15:28:50 +08:00
int cols((int)m_tanks.size() * 5 + 1);
2026-10-04 00:04:20 +08:00
// 设置列数
2026-09-28 15:28:50 +08:00
pTbl->setNumColumns(cols);
pTbl->setNumRows(3);
2026-10-04 00:04:20 +08:00
// 合并第0行
2026-09-28 15:28:50 +08:00
pTbl->mergeCells(0, 0, 0, cols - 1);
2026-10-04 00:04:20 +08:00
// 为第0行打上文字
pTbl->setTextString(0, 0, _T("通风计算"));
2026-09-28 15:28:50 +08:00
2026-10-04 00:04:20 +08:00
// 合并第1行
2026-09-28 15:28:50 +08:00
for (int i = 0; i < m_tanks.size(); ++i)
{
2026-10-04 00:04:20 +08:00
str.Format(_T("%s(%.1fmX%.1fm)"), m_tanks[i].getName(), m_tanks[i].getLength(), m_tanks[i].getWidth());
2026-09-28 15:28:50 +08:00
pTbl->mergeCells(1, 1, i * 5 + 1, i * 5 + 5);
pTbl->setTextString(1, i * 5 + 1, str);
}
2026-10-04 00:04:20 +08:00
pTbl->setTextString(2, 0, _T("序号"));
2026-09-28 15:28:50 +08:00
for (int i = 0; i < m_tanks.size(); ++i)
{
2026-10-04 00:04:20 +08:00
pTbl->setTextString(2, i * 5 + 1, _T("桩号范围"));
pTbl->setTextString(2, i * 5 + 2, _T("长度(m)"));
pTbl->setTextString(2, i * 5 + 3, _T("体积(m3)"));
pTbl->setTextString(2, i * 5 + 4, _T("通风次数(次/h)"));
pTbl->setTextString(2, i * 5 + 5, _T("通风量(m3/h)"));
2026-09-28 15:28:50 +08:00
}
pTbl->setColumnWidth(30);
2026-10-04 00:04:20 +08:00
// 总行数
2026-09-28 15:28:50 +08:00
AcCmColor clr;
clr.setColorIndex(1);
int rows(3);
int col1(0), col2(0), col3(0), col4(0), col5(0);
for (size_t tk = 0; tk < m_tanks.size(); ++tk)
{
const CEWTank &tank = m_tanks[tk];
std::map<CString, double> &conf = g_config[tank.getName()];
const EWVentilates &datas(tank.getVentilateData());
col1 = (int)tk * 5 + 1;
col2 = (int)tk * 5 + 2;
col3 = (int)tk * 5 + 3;
col4 = (int)tk * 5 + 4;
col5 = (int)tk * 5 + 5;
rows = 3;
for (size_t i = 0; i < datas.size(); ++i)
{
const EWVentilate &da = datas[i];
if (pTbl->numRows() <= rows)
pTbl->insertRows(rows, 5);
pTbl->setTextString(rows, col1, da.m_stake.c_str());
pTbl->setTextString(rows, col2, _convert_<std::wstring, double>(da.m_dDistance).c_str());
if (da.m_dDistance > conf[MK_DIM::getNodeName(MK_DIM::NodeDim::eVenDoghouse)])
{
pTbl->setContentColor(rows, col2, clr);
}
pTbl->setTextString(rows, col3, _convert_<std::wstring, double>(da.m_dVolum).c_str());
pTbl->setTextString(rows, col4, _convert_<std::wstring, double>(da.m_dNumVentilate).c_str());
pTbl->setTextString(rows, col5, _convert_<std::wstring, double>(da.m_dAirHr).c_str());
++rows;
}
}
for (size_t i = 3; i < pTbl->numRows(); ++i)
{
str.Format(_T("%d"), i - 2);
pTbl->setTextString((int)i, 0, str);
}
int tblHeight(3);
pTbl->setTextHeight(tblHeight);
pTbl->setRowHeight(5);
pTbl->generateLayout();
return pTbl;
}
void CEWGLReport::outputCADTable(const MK_DIM::NodeDim::ENodeType &type)
{
AcDbTable *pTbl(NULL);
if (type == MK_DIM::NodeDim::eVenDoghouse)
pTbl = outputVentilateCAD();
else
pTbl = outputDataCAD(type);
if (!pTbl) return;
AcGeVector3d vtx = acdbCurDwg()->ucsxdir();
double angle = AcGeVector3d::kXAxis.angleTo(vtx, AcGeVector3d::kZAxis);
pTbl->setDirection(vtx);
pTbl->recomputeTableBlock(true);
pTbl->generateLayout();
2026-10-04 00:04:20 +08:00
TableJig jig(pTbl, _T("\n请确定表格位置<退出>: "));
2026-09-28 15:28:50 +08:00
if (jig.doIt() != AcEdJig::kNormal)
{
DELETE_PTR(pTbl);
return;
}
AddToModelSpace(pTbl, NULL, true);
}
//////////////////////////////////////////////////////////////////////////
void CEWTank::setOption(const std::map<CString, double> &op)
{
m_options.insert(op.begin(), op.end());
}
void CEWTank::appendData(const MK_DIM::NodeDim::ENodeType &type, const EWNodeData &data)
{
switch (type)
{
case MK_DIM::NodeDim::eFireWall:
m_fireWall.push_back(data);
break;
case MK_DIM::NodeDim::eEscapeHatch:
m_escape.push_back(data);
break;
case MK_DIM::NodeDim::eVenDoghouse:
m_Ventilate.push_back(data);
break;
case MK_DIM::NodeDim::eDoghouse:
m_doghouse.push_back(data);
break;
case MK_DIM::NodeDim::eDrainWell:
m_wells.push_back(data);
break;
case MK_DIM::NodeDim::eOutlet:
m_outlets.push_back(data);
break;
default: break;
}
}
void CEWTank::calcData(const MK_DIM::NodeDim::ENodeType &type)
{
switch (type)
{
case MK_DIM::NodeDim::eFireWall:
calcFireZone();
break;
case MK_DIM::NodeDim::eEscapeHatch:
calcEscape();
break;
case MK_DIM::NodeDim::eVenDoghouse:
calcVentilateZone();
calcVentilate();
break;
case MK_DIM::NodeDim::eDoghouse:
calcDoghouse();
break;
case MK_DIM::NodeDim::eDrainWell:
calcWell();
break;
case MK_DIM::NodeDim::eOutlet:
calcOutlet();
break;
default: break;
}
}
void CEWTank::calcFireZone()
{
calc(m_calcFireZone, m_fireWall);
}
void CEWTank::calcVentilateZone()
{
EWVentilate v;
for (size_t i = 0; i < m_Ventilate.size(); ++i)
{
if (i + 1 < m_Ventilate.size())
{
const EWNodeData d1 = m_Ventilate[i];
const EWNodeData d2 = m_Ventilate[i + 1];
v.m_stake = d1.m_dDistance > d2.m_dDistance ? d2.m_stake + _T("~") + d1.m_stake : d1.m_stake + _T("~") + d2.m_stake;
v.m_dDistance = abs(d1.m_dDistance - d2.m_dDistance);
v.m_dNumVentilate = m_options[VEN_NUM];
v.m_dArea = getSectionArea();
m_calcVentilate.push_back(v);
}
}
}
void CEWTank::calcVentilate()
{
2026-10-04 00:04:20 +08:00
// 进行本次计算前,应该先计算出通风分区 calcVentilateZone()
2026-09-28 15:28:50 +08:00
for (size_t i = 0; i < m_calcVentilate.size(); ++i)
{
EWVentilate &v = m_calcVentilate[i];
v.m_dVolum = v.m_dDistance * v.m_dArea;
v.m_dAirHr = v.m_dVolum * v.m_dNumVentilate;
}
}
void CEWTank::calcEscape()
{
calc(m_calcEscape, m_escape);
}
void CEWTank::calcDoghouse()
{
calc(m_calcDoghouse, m_doghouse);
}
void CEWTank::calcWell()
{
calc(m_calcWell, m_wells);
}
void CEWTank::calcOutlet()
{
calc(m_calcOutlet, m_outlets);
}
void CEWTank::calc(EWNodeDatas &out, const EWNodeDatas &data)
{
out.clear();
for (size_t i = 0; i < data.size(); ++i)
{
if (i + 1 < data.size())
{
const EWNodeData &d1 = data[i];
const EWNodeData &d2 = data[i + 1];
out.push_back(
EWNodeData(
d1.m_dDistance > d2.m_dDistance ? d2.m_stake + _T("~") + d1.m_stake : d1.m_stake + _T("~") + d2.m_stake
, abs(d1.m_dDistance - d2.m_dDistance))
);
}
}
}
void SetRoomTypeByIdx()
{
return;
}
//////////////////////////////////////////////////////////////////////////
AcEdJig::DragStatus TableJig::doIt()
{
setDispPrompt(m_Prompt);
AcEdJig::DragStatus st = drag();
return st;
}
AcEdJig::DragStatus TableJig::sampler()
{
AcEdJig::DragStatus st = acquirePoint(m_ptPos);
return st;
}
Adesk::Boolean TableJig::update()
{
if (!m_pTbl) return Adesk::kFalse;
m_pTbl->setPosition(m_ptPos);
m_pTbl->generateLayout();
return Adesk::kTrue;
}
}