Files
envi-code/SourceCode/Code2026/tg_shs/shs_kerncmd/energytool.cpp
T

454 lines
13 KiB
C++
Raw Normal View History

2026-10-04 00:04:20 +08:00
#include "stdafx.h"
2026-09-28 15:28:50 +08:00
#include "TgAs.h"
//EnergyTool.cpp
2026-10-04 00:04:20 +08:00
// 节能评估有关的程序
2026-09-28 15:28:50 +08:00
///////////////////////////////////////////////////////////////////
2026-10-04 00:04:20 +08:00
// 搜索外墙轮廓
// 局限性:适用于无天井、无沉降缝的情况
2026-09-28 15:28:50 +08:00
BOOL SearchFloorOutline(AcDbDatabase *pFloor, XPoly2D &poly)
{
ASSERT(pFloor);
DList<AcDbObjectId> lstWalls;
DList<AcDbObjectId> lstColus;
if (GetEntityFromDatabase(lstWalls, *pFloor, _T("TCH_WALL,TCH_CURTAIN_WALL"), 1, ACDB_MODEL_SPACE)!=Acad::eOk)
return FALSE;
GetEntityFromDatabase(lstColus, *pFloor, _T("TCH_COLUMN"), 0, ACDB_MODEL_SPACE);
XSearchSpaceFromWall aSearch;
try {
aSearch.InitStart(lstWalls, lstColus);
} catch (...) {
2026-10-04 00:04:20 +08:00
adsout << _T("\n发生例外情况!");
2026-09-28 15:28:50 +08:00
return FALSE;
}
XAecSpaceCell *pExt=aSearch.SearchSpaces();
if (!pExt)
return FALSE;
pExt->InternalPoly2D(poly,2);
poly.Compress();
BOOL bRet=(poly.Length()>1);
return bRet;
}
/////////////////////////////////////////////////////////////////////////////
2026-10-04 00:04:20 +08:00
// 取得室外空间轮廓
// 如果没有找到编号为0的房间,则搜索
2026-09-28 15:28:50 +08:00
BOOL GetFloorOutlines(AcDbDatabase *pFloor, DList<XPoly2D> &lstPoly)
{
lstPoly.Reset();
ASSERT(pFloor);
DList<AcDbObjectId> lstSpaces;
if (GetEntityFromDatabase(lstSpaces, *pFloor, _T("TCH_SPACE"), 0, ACDB_MODEL_SPACE)!=Acad::eOk)
return FALSE;
BOOL bFindExtSpace=FALSE;
for(int i=0; i<lstSpaces.Length(); i++) {
AcDbObjectId id=*lstSpaces[i];
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbSpace, pSpace);
if (pSpace) {
if (_tcscmp(pSpace->GetCode(), _T("0"))==0 && pSpace->m_outline.Length()) {
lstPoly.Append(new XPoly2D(pSpace->m_outline));
bFindExtSpace=TRUE;
}
}
OPENOBJ_END();
}
if (!bFindExtSpace) {
XPoly2D poly(1);
bFindExtSpace=SearchFloorOutline(pFloor, poly);
if (bFindExtSpace)
lstPoly.Append(new XPoly2D(poly));
}
XPoint ptBase=pFloor->insbase();
ads_matrix mat;
ptBase.GetMoveMatrix(XPoint(), mat);
for(i=0; i<lstPoly.Length(); i++)
lstPoly[i]->TransUCS(mat);
return bFindExtSpace;
}
//////////////////////////////////////////////////////////////////////////
2026-10-04 00:04:20 +08:00
// 创建外墙轮廓
2026-09-28 15:28:50 +08:00
void MakeExtSpace()
{
g_ssPickFirst.Free();
PickSet ssWalls(SS_FREE), ssColus(SS_FREE);
RBList wallMask(RTDXF0, _T("TCH_WALL,TCH_CURTAIN_WALL,TCH_COLUMN"), NULL);
2026-10-04 00:04:20 +08:00
if (SelectEntities(_T("\n请选择构成一完整建筑物的所有维护结构:"), ssWalls, wallMask)!=RTNORM) {
2026-09-28 15:28:50 +08:00
return;
}
ssColus += ssWalls;
ssColus.BaseFilter(RBList(RTDXF0, _T("TCH_COLUMN"), NULL));
ssWalls -= ssColus;
//MakeWallSet(ssWalls);
2026-10-04 00:04:20 +08:00
//取得所有的裁剪区域
2026-09-28 15:28:50 +08:00
DList<AcDbObjectId> lstColu;
long lColuNum=ssColus.Length();
for(long idx=0L; idx<lColuNum; idx++) {
Entity ent=ssColus[idx];
AcDbObjectId id;
if (acdbGetObjectId(id, ent)==Acad::eOk) {
lstColu.Append(new AcDbObjectId(id));
}
}
XSearchSpaceFromWall aSearch;
try {
aSearch.InitStart(ssWalls, lstColu);
} catch(...) {
2026-10-04 00:04:20 +08:00
adsout << /*UMSG*/_T("\n发生例外情况!");
2026-09-28 15:28:50 +08:00
return;
}
XAecSpaceCell * extCell=aSearch.SearchSpaces();
if (extCell) {
XPoint ptLoc;
2026-10-04 00:04:20 +08:00
if (ads_getpoint(NULL, _T("\n标识位置<退出>:"), ptLoc)!=RTNORM)
2026-09-28 15:28:50 +08:00
return;;
ptLoc=Ucs2Wcs(ptLoc);
ptLoc.z = 0.0;
XPoly2D polySpace(1);
extCell->CenterPoly2D(polySpace);
2026-10-04 00:04:20 +08:00
polySpace.SetElevation(0.0); //投影到z=0的平面上
2026-09-28 15:28:50 +08:00
TDbSpace *pDbSpace = new TDbSpace();
pDbSpace->m_sCode=_T("0");
2026-10-04 00:04:20 +08:00
pDbSpace->m_sName = _T("外墙轮廓");
2026-09-28 15:28:50 +08:00
pDbSpace->SetHas3D(FALSE);
pDbSpace->m_ptLocation = ptLoc;
pDbSpace->SetTextStyleId(InitTextStyle(TS_SPACE));
2026-10-04 00:04:20 +08:00
pDbSpace->SetType(TDbSpace::kTotalArea); // sg add 081226,房间类型
2026-09-28 15:28:50 +08:00
if (pDbSpace->AddToMSpace(Adesk::kFalse).isValid()) {
pDbSpace->UpdateFrom(*extCell, TRUE);
pDbSpace->close();
} else {
delete pDbSpace;
}
}
}
2026-10-04 00:04:20 +08:00
// Tool: 计算一层的建筑面积
// 单位:m2
2026-09-28 15:28:50 +08:00
double CalBuildingArea(AcDbDatabase *pFloor)
{
double nArea=0.0;
DList<XPoly2D> lstPoly;
if (GetFloorOutlines(pFloor, lstPoly)) {
for(int i=0; i<lstPoly.Length(); i++) {
XPoly2D &poly=*lstPoly[i];
nArea += _AS_SQMETER(poly.Area());
}
}
return nArea;
}
2026-10-04 00:04:20 +08:00
// Tool: 计算一层的建筑周长
// 单位:m
2026-09-28 15:28:50 +08:00
double CalBuildingPerimeter(AcDbDatabase *pFloor)
{
double nLen=0.0;
DList<XPoly2D> lstPoly;
if (GetFloorOutlines(pFloor, lstPoly)) {
for(int i=0; i<lstPoly.Length(); i++) {
XPoly2D &poly=*lstPoly[i];
nLen += _AS_METER(poly.Distance2d());
}
}
return nLen;
}
TARCH_IMPEXP int GetFloorData(const TCHAR *szFolder, XDbfTable &grp, DList<XFloorData> &lstFloors);
AcDbRegion *AsRegion(const DList<XPoly2D> &lstPoly)
{
AcDbRegion *pRegAll=NULL;
for(int i=0; i<lstPoly.Length(); i++) {
const XPoly2D &rPoly=lstPoly[i];
AcDb::BoolOperType op=rPoly.PathArea()<0? AcDb::kBoolUnite : AcDb::kBoolSubtract;
AcDbRegion *pReg=rPoly.AsRegion();
if (pRegAll) {
if (pRegAll->booleanOper(op, pReg)!=Acad::eOk) {
delete pRegAll;
delete pReg;
return NULL;
}
} else {
pRegAll=pReg;
}
}
return pRegAll;
}
2026-10-04 00:04:20 +08:00
// Tool: 计算某工程的指标
// sFloorTalbe-楼层表文件
// nOccupyArea(m2) = 占地面积,即首层建筑面积
// nBuildingArea(m2) = 建筑面积,不含阳台、凸窗
// nEnvelopArea(m2) = 外表面积, 侧面积、屋顶面积和挑出的楼板面积
// nBuildingVolume(m3) = 建筑体积,层高*建筑面积的累加
// nBuildingHeight(m) = 建筑高度,首层地面算起
2026-09-28 15:28:50 +08:00
BOOL GetBuildingPara(const TCHAR *sFloorTable,
double *nOccupyArea,
double *nBuildingArea,
double *nEnvelopArea,
double *nBuildingVolume,
double *nBuildingHeight)
{
XPathParser paser(sFloorTable);
XString sFolder;
sFolder << paser.m_sDrive << paser.m_sDir;
CodeBase cb;
cb.read_only=1;
XDbfTable *pTable=cb.Open(sFloorTable);
if (!pTable)
return FALSE;
DList<XFloorData> lstFloors;
if (GetFloorData(sFolder, *pTable, lstFloors)!=RTNORM || CheckFloorData(lstFloors)!=RTNORM)
return FALSE;
pTable->Close();
*nOccupyArea=0.0;
*nBuildingArea=0.0;
*nEnvelopArea=0.0;
*nBuildingVolume=0.0;
*nBuildingHeight=0.0;
DList<XPoly2D> lstPolyLast;
XString sLastDwg;
for(int i=0; i<lstFloors.Length(); i++) {
XFloorData *pData=lstFloors[i];
if (pData->m_nIndex<1)
continue;
if (_tcscmp(pData->m_sDwgFile, sLastDwg)==0) {
for(int k=0; k<lstPolyLast.Length(); k++) {
XPoly2D &poly2d=*lstPolyLast[k];
double nPerimeter=_AS_METER(poly2d.Distance2d());
double nArea=_AS_SQMETER(poly2d.Area());
if (pData->m_nIndex==1) {
*nOccupyArea=nArea;
}
*nBuildingArea += nArea;
*nEnvelopArea += nPerimeter*_AS_METER(pData->m_nHeight);
*nBuildingVolume += nArea*_AS_METER(pData->m_nHeight);
}
*nBuildingHeight += _AS_METER(pData->m_nHeight);
} else {
AcDbDatabase db(false, true);
#if ADS < 21
if (db.readDwgFile(pData->m_sDwgFile, _SH_DENYNO, false)!=Acad::eOk)
#else
if (db.readDwgFile(pData->m_sDwgFile, AcDbDatabase::kForReadAndAllShare, false)!=Acad::eOk)
#endif
return FALSE;
DList<XPoly2D> lstPolys;
if (GetFloorOutlines(&db, lstPolys)) {
for(int k=0; k<lstPolys.Length(); k++) {
XPoly2D &poly2d=*lstPolys[k];
double nPerimeter=_AS_METER(poly2d.Distance2d());
double nArea=_AS_SQMETER(poly2d.Area());
if (pData->m_nIndex==1) {
*nOccupyArea=nArea;
}
*nBuildingArea += nArea;
2026-10-04 00:04:20 +08:00
*nEnvelopArea += nPerimeter*_AS_METER(pData->m_nHeight); //加侧面积
2026-09-28 15:28:50 +08:00
*nBuildingVolume += nArea*_AS_METER(pData->m_nHeight);
}
*nBuildingHeight += _AS_METER(pData->m_nHeight);
/*
DList<XPoly2D> lstRoofs, lstGrounds;
2026-10-04 00:04:20 +08:00
Subtract(lstPolyLast, lstPolys, lstRoofs); //求得上层的屋顶
Subtract(lstPolys, lstPolyLast, lstGrounds); //求得本层暴露在室外的楼板
2026-09-28 15:28:50 +08:00
for(int n=0; n<lstRoofs.Length(); n++) {
*nEnvelopArea += _AS_SQMETER(lstRoofs[n]->Area());
}
for(int m=0; m<lstGrounds.Length(); m++) {
*nEnvelopArea += _AS_SQMETER(lstGrounds[m]->Area());
}*/
AcDbRegion *pRegLast=AsRegion(lstPolyLast);
if (pRegLast) {
2026-10-04 00:04:20 +08:00
double nRoofArea=0.0, nGroundArea=0.0; //上层屋顶,本层挑出地板
2026-09-28 15:28:50 +08:00
AcDbRegion *pRegCur=AsRegion(lstPolys);
if (!pRegCur) {
pRegLast->getArea(nRoofArea);
*nEnvelopArea += nRoofArea;
delete pRegLast;
return FALSE;
}
double nCurRoofArea=0.0;
pRegCur->getArea(nCurRoofArea);
AcDbRegion *pRegRoof=(AcDbRegion *)pRegLast->clone();
AcDbRegion *pRegGround=(AcDbRegion *)pRegCur->clone();
pRegRoof->booleanOper(AcDb::kBoolSubtract, pRegCur);
pRegGround->booleanOper(AcDb::kBoolSubtract, pRegLast);
pRegRoof->getArea(nRoofArea);
pRegGround->getArea(nGroundArea);
2026-10-04 00:04:20 +08:00
*nEnvelopArea += _AS_SQMETER(nRoofArea); //上表面超外的面积
*nEnvelopArea += _AS_SQMETER(nGroundArea); //下表面超外的面积
if (pData==lstFloors.Tail()) { //本层屋顶
2026-09-28 15:28:50 +08:00
*nEnvelopArea += _AS_SQMETER(nCurRoofArea);
}
delete pRegLast;
delete pRegCur;
delete pRegRoof;
delete pRegGround;
}
lstPolyLast.Reset();
for(k=0; k<lstPolys.Length(); k++) {
XPoly2D &poly2d=*lstPolys[k];
lstPolyLast.Append(new XPoly2D(poly2d));
}
} else {
for(int k=0; k<lstPolyLast.Length(); k++) {
XPoly2D &poly2d=*lstPolyLast[k];
*nEnvelopArea += _AS_SQMETER(poly2d.Area());
}
}
sLastDwg=pData->m_sDwgFile;
}
//adsout << _T("\nEnvelop=") << (*nEnvelopArea);
}
return TRUE;
}
2026-10-04 00:04:20 +08:00
// 报告建筑工程量指标
2026-09-28 15:28:50 +08:00
void RepBuildingPara()
{
XString sFileName;
sFileName << _T("building.dbf");
if (GetFileDia(sFileName, 0, _T("dbf"), _T("FileName"))!=RTNORM)
return;
double nOccupyArea=0,
nBuildingArea=0,
nEnvelopArea=0,
nBuildingVolume=0,
nBuildingHeight=0;
if (GetBuildingPara(sFileName, &nOccupyArea, &nBuildingArea, &nEnvelopArea, &nBuildingVolume, &nBuildingHeight)) {
2026-10-04 00:04:20 +08:00
adsout << _T("\n占地面积 = ") << nOccupyArea
<< _T("\n建筑面积 = ") << nBuildingArea
<< _T("\n外表面积 = ") << nEnvelopArea
<< _T("\n建筑体积 = ") << nBuildingVolume
<< _T("\n建筑高度 = ") << nBuildingHeight
<< _T("\n体形系数 = ") << nEnvelopArea/nBuildingVolume;
2026-09-28 15:28:50 +08:00
} else {
2026-10-04 00:04:20 +08:00
adsout << _T("\n无法统计参数!");
2026-09-28 15:28:50 +08:00
}
}
2026-10-04 00:04:20 +08:00
// 计算露点温度(C)
// t--干球温度(C)
// p--大气压(Pa)
// rh--相对湿度(0--1.0)
2026-09-28 15:28:50 +08:00
double CalDewpoint(double t, double p, double rh)
{
double x[] = { -10.79574, 5.02808, -1.50475e-4, 18.2969, 0.42875e-3,
-4.76955 };
double y[4], tk, z, z1, z2, ps, pv, temp;
double td;
tk = t+273.16;
z = 273.16/tk;
y[0] = x[0]*(z-1.0);
y[1] = x[1]*log10(z);
z1 = x[3]*(1.0 - 1.0/z);
y[2] = x[2]*(pow(10.0,z1)-1.0);
z2 = x[5]*(z-1.0);
y[3] = x[4]*(pow(10.0,z2)-1.0)-2.2195768;
ps = p * pow(10.0, y[0]+y[1]+y[2]+y[3]);
pv = rh*ps;
temp = 2.015 + log(pv/1000.0);
if ( temp > 1.522)
td = -18.807 + 11.005*temp + 0.88887*temp*temp;
else
td = -19.237 + 11.533*temp + 0.72733*temp*temp;
return td;
}
2026-10-04 00:04:20 +08:00
// 计算内表面温度
// nAlfIn -- 内表明对流换热系数, 通常8.7W/m2.K
// nTempIn -- 室内温度(C)
// nTempOut -- 室外温度(C)
// uValue -- 平均传热系数
2026-09-28 15:28:50 +08:00
// NOTICE:
// Q = alf_in*(Tsuf_in-T_in) = U_val*(T_out-T_in)
// THEN:
// Tsuf_in = Q/alf_in + T_in
double CalSurfTemp(double nAlfIn, double nTempIn, double nTempOut, double uValue)
{
double q =uValue*(nTempOut - nTempIn);
double nTempSurf = nTempIn + q/nAlfIn;
return nTempSurf;
}
2026-10-04 00:04:20 +08:00
//Tool: 结露检查:民用建筑节能设计标准(采暖居住建筑部分)JGJ26-95的4.2.7规定了不结露的要求
// 判断内表面温度和露点温度的关系
2026-09-28 15:28:50 +08:00
void CondensionCheck()
{
2026-10-04 00:04:20 +08:00
double nPressure=99860.0; //大气压Pa,由气象数据库查找获得
double nTempOut=-9.0; //室外设计温度C
double nTempIn = 18.0; //室内设计温度C
double nHumidityIn=0.5; //室内相对湿度
2026-09-28 15:28:50 +08:00
2026-10-04 00:04:20 +08:00
double uValue=2.3; //搜索获得, W/m2.K
2026-09-28 15:28:50 +08:00
double nSurfInTemp=CalSurfTemp(8.7, nTempIn, nTempOut, uValue);
double nTempDewpoint=CalDewpoint(nTempIn, nPressure, nHumidityIn);
2026-10-04 00:04:20 +08:00
adsout << _T("\n露点温度=") << nTempDewpoint << _T("; 内表面温度=") << nSurfInTemp
<< _T(";") << ((nSurfInTemp>nTempDewpoint)? _T(" 结露!") : _T(" 不结露!"));
2026-09-28 15:28:50 +08:00
}
2026-10-04 00:04:20 +08:00
//// 报告墙的坐标
2026-09-28 15:28:50 +08:00
//void RepWallCoord()
//{
// DList<XCurveSegment> lstAxis;
// PickSet ssAxis(SS_FREE);
// if (ssAxis.Get(_T("X"), NULL, NULL, RBList(RTDXF0, _T("LINE,ARC"), 8, LAY_AXIS, NULL))!=RTNORM)
// return;
// long num=ssAxis.Length();
// for(long idx=0L; idx<num; idx++) {
// Entity ent=ssAxis[idx];
// XCurveSegment *pSeg=new XCurveSegment(ent);
// if (!(*pSeg))
// delete pSeg;
// else
// lstAxis.Append(pSeg);
// }
//
//
//
// DList<AcDbObjectId> lstLab;
// if (GetEntityFromDatabase(lstLab, *acdbCurDwg(), _T("TCH_AXIS_LABEL"), 0, ACDB_MODEL_SPACE)!=Acad::eOk)
// return;
// Entity entWall;
2026-10-04 00:04:20 +08:00
// if (SelectEntity(_T("\n选择墙体<退出>:"), entWall, RBList(RTDXF0, _T("TCH_WALL,TCH_CURTAIN_WALL"), NULL))==RTNORM) {
2026-09-28 15:28:50 +08:00
// OPENOBJ_BEGIN(entWall, AcDb::kForRead, TDbWall, pWall);
// if (pWall) {
// XString s1, s2, s3, s4;
// if (pWall->HitOnAxis(lstLab, lstAxis, s1, s2, s3, s4)) {
2026-10-04 00:04:20 +08:00
// adsout << _T("\n(") << s1 << _T(",") << s2 << _T(")~(") << s3 << _T(",") << s4 << _T(")");
2026-09-28 15:28:50 +08:00
// } else {
// adsout << _T("\nnone!");
// }
// }
// OPENOBJ_END();
// }
//}