Files
envi-code/SourceCode/Code2026/tg_shs/shs_outdoor/SiphonRainwater.cpp
T
2026-09-28 15:28:50 +08:00

3769 lines
89 KiB
C++

#include "StdAfx.h"
#include "TAPI.h"
#include "TchGlobalCurveFunc.h"
#include "TwtDef.h"
#include "RoofInfoCalcDlg.h"
#include "algorithm"
#include "OverfallWeirCalcDlg.h"
#include "WaterBucketDlg.h"
#include "DbEquipment.h"
#include "TWellJig.h"
#include "DbPipeFitting.h"
#include "SSearchPipeList.h"
#include "SiphonRainwaterCalcDlg.h"
#include "WaterBucketParameterDlg.h"
#include "PipeWireMonitor.h"
#include "DbPool.h"
#include"TGAs.h"
/*============================================================================*
* Copyright(c), 1994-2007, Beijing Tangent Engineering Software Co.Ltd.
* 作 者: 陈恩涛
* 创建时间: 2010-9-13
* 描 述: 虹吸雨水
* 归属项目: 给排水
* 历史记录:
=============================================================================*/
//***************************************************************************************************
// 屋面汇水划分
//***************************************************************************************************
// 搜索划分线
void SerachDivisionLine(PickSet &ss)
{
RBList rbMark = ads_buildlist(RTDXF0, _T("LINE,LWPOLYLINE,ARC"), NULL);
PickSet ss2(SS_FREE);
acedSSGet(_T("A"), NULL, NULL, rbMark, ss2);
PickSet ssAdd(SS_FREE);
for(long i = 0; i < ss2.Length(); i++)
{
Entity ent;
ent = ss2[i];
CString strTmp = ReadXdata(ent, _T("DivisionLine"));
if (strTmp.Compare(_T("1")) == 0)
{
ssAdd += ent;
}
}
ss += ssAdd;
}
// 改变划分线的颜色
void ChangeDivisionLineColor(PickSet &ss, std::map<AcDbObjectId,int> &data)
{
for(long i = 0; i < ss.Length(); i++)
{
Entity ent = ss[i];
AcDbObjectId id;
acdbGetObjectId(id, ent);
AcDbEntity *pEnt = NULL;
acdbOpenObject(pEnt, id, AcDb::kForWrite);
if (pEnt != NULL)
{
int nColor = pEnt->colorIndex();
data.insert(std::make_pair(id, nColor));
pEnt->setColorIndex(3);
pEnt->close();
WriteXdata(ent, _T("DivisionLine"), _T("1"));
}
}
}
// 恢复划分线的颜色
void RecoverDivsionLineColor(std::map<AcDbObjectId,int> &data)
{
std::map<AcDbObjectId,int>::iterator it;
for(it = data.begin(); it != data.end(); it++)
{
AcDbEntity *pEnt = NULL;
acdbOpenObject(pEnt, (*it).first, AcDb::kForWrite);
if (pEnt != NULL)
{
pEnt->setColorIndex((*it).second);
pEnt->close();
}
}
}
// 由划分线获得闭合区域
void GetClosePoly2D(PickSet &ss, TDPtrList<TGGePoly2D> &lstDest)
{
// 处理划分线
TDPtrList<TGGeCurveSegment> lstSeg1In;
for (long i = 0; i < ss.Length(); i++)
{
Entity ent = ss[i];
if (ent.Is(_T("LWPOLYLINE")))
{
AcDbObjectId id;
acdbGetObjectId(id, ent);
AcDbPolyline *pPoly = NULL;
acdbOpenObject(pPoly, id, AcDb::kForRead);
if (pPoly != NULL)
{
AcDbVoidPtrArray ptAr;
pPoly->explode(ptAr);
for (int i = 0; i < ptAr.length(); i++)
{
AcDbEntity *pEnt = (AcDbEntity*)ptAr[i];
AcDbLine *pLine = AcDbLine::cast(pEnt);
AcDbArc *pArc = AcDbArc::cast(pEnt);
if (pLine != NULL)
{
XPoint ptS, ptE;
pLine->getStartPoint(ptS);
pLine->getEndPoint(ptE);
XLine line(ptS, ptE);
line.SetLineFlag(1);
TGGeCurveSegment *pSeg = new TGGeCurveSegment();
*pSeg = line;
lstSeg1In.Append(pSeg);
}
else if (pArc != NULL)
{
XPoint ptS, ptE;
double dAngle = 0.0, dLen = 0.0;
pArc->getStartPoint(ptS);
pArc->getEndPoint(ptE);
pArc->getDistAtPoint(ptE, dLen);
dAngle = dLen / pArc->radius();
XArc arc(ptS, ptE, dAngle);
TGGeCurveSegment *pSeg = new TGGeCurveSegment();
*pSeg = arc;
lstSeg1In.Append(pSeg);
}
pLine = NULL;
pArc = NULL;
}
ReleaseEntSet(ptAr);
pPoly->close();
}
}
else
{
TGGeCurveSegment *pSeg = new TGGeCurveSegment(ent);
lstSeg1In.Append(pSeg);
}
}
// 从交点处打断
IntersectCurves(lstSeg1In, 0.001);
// 获得由划分线构成的闭合区域
TchExport2::SearchRegions(lstSeg1In, lstDest);
//过滤多余的闭合区域
std::set<int> setIndex; // 保存多余闭合区域索引
int nLen = lstDest.Length();
for (i = 0; i < nLen; i++)
{
TGGePoly2D *pPoly2D = lstDest.GetAt(i);
for (int j = i + 1; j < nLen; j++)
{
TGGePoly2D *pPoly2D2 = lstDest.GetAt(j);
XPoint pt2 = pPoly2D2->GetInsidePoint();
XPoint pt1 = pPoly2D->GetInsidePoint();
if ((pt2 & (*pPoly2D)) == PR_INSIDE || (pt1 & (*pPoly2D2)) == PR_INSIDE)
{
double dArea1 = pPoly2D->Area();
double dArea2 = pPoly2D2->Area();
if (dArea1 > dArea2)
{
setIndex.insert(i);
}
else
{
setIndex.insert(j);
}
}
}
}
TDPtrList<TGGePoly2D> lstTmp;
lstTmp.copyFrom(lstDest);
lstDest.Reset();
std::set<int>::iterator it;
for (i = 0; i < lstTmp.Length(); i++)
{
it = setIndex.find(i);
if (it == setIndex.end())
{
TGGePoly2D *pPoly2d = new TGGePoly2D(*lstTmp.GetAt(i));
if (pPoly2d->Area() < 1e-3)
{
continue;
}
lstDest.Append(pPoly2d);
}
}
}
// 根据闭合区域生成ATS_SPACE实体
void CreateTchSpace(TDPtrList<TGGePoly2D> &lstDest)
{
for (int i = 0; i < lstDest.Length(); i++)
{
TGGePoly2D *pPoly2d = new TGGePoly2D(*lstDest.GetAt(i));
double dArea = 0.0;
if(!DocGetMeterUnitDraw())
dArea = _AS_SQMETER(pPoly2d->Area());
else
dArea = pPoly2d->Area();
CString strArea;
strArea.Format(_T("面积:%.2fm^U2^U"), dArea);
TDbSpace *pDbSpace = new TDbSpace();
pDbSpace->SetMText(TRUE);
pDbSpace->SetHasHatch(FALSE);
int nSpFlag = DocGetSpaceDispMode(); // 隐藏标注面积
nSpFlag &= ~SPF_AREA;
DocSetSpaceDispMode(nSpFlag);
pDbSpace->m_sName = strArea;
pDbSpace->SetSndName(_T(""));
XPoint ptLoc = pPoly2d->GetInsidePoint();
pDbSpace->m_ptLocation = ptLoc;
pDbSpace->SetHas3D(FALSE);
pDbSpace->SetHighlight(TRUE);
pDbSpace->m_outline = *pPoly2d;
pDbSpace->m_nUseArea = dArea;
pDbSpace->m_nOccuArea = 0;
pDbSpace->m_nCeilArea = 0;
pDbSpace->m_nWallSurfArea = 0;
pDbSpace->m_nExtWallArea = 0;
pDbSpace->m_nExtWinArea = 0;
pDbSpace->m_nExtDoorArea = 0;
pDbSpace->m_nPerimeter = 0;
pDbSpace->m_nKickboardLength = 0;
pDbSpace->SetShowOutline(TRUE);
pDbSpace->SetTextStyleId(InitTextStyle(g_csDimWellStyle));
pDbSpace->SetTextHeight(g_nDimWellHeight);
pDbSpace->AddToCSpace(Adesk::kFalse);
pDbSpace->setLayer(InitLayer(LAY_CALC_AREA));
pDbSpace->close();
}
}
//根据选择的参考线生成过滤条件,并将这些线变为划分线
void GetRBListByLine(RBList &rbList, PickSet &ss, std::map<AcDbObjectId, int> &data)
{
struct resbuf *pBuf = ads_buildlist(-4, _T("<or"), NULL);
rbList.Append(pBuf);
std::vector<CString> vec;
std::vector<CString>::iterator it;
for (long i = 0; i < ss.Length(); i++)
{
Entity ent = ss[i];
AcDbEntity *pEnt = NULL;
AcDbObjectId idEnt;
CString strLayerName,strLineStyle, strColor;
int nColor = 0;
acdbGetObjectId(idEnt, ent);
acdbOpenObject(pEnt, idEnt, AcDb::kForWrite);
if (pEnt != NULL)
{
strLayerName = pEnt->layer();
strLineStyle = pEnt->linetype();
nColor = pEnt->colorIndex();
pEnt->setColorIndex(3);
pEnt->close();
WriteXdata(ent, _T("DivisionLine"), _T("1"));
data.insert(std::make_pair(idEnt, nColor));
}
CString strEntName;
if (ent.Is(_T("LINE")))
{
strEntName = _T("LINE");
}
else if (ent.Is(_T("ARC")))
{
strEntName = _T("ARC");
}
else if (ent.Is(_T("LWPOLYLINE")))
{
strEntName = _T("LWPOLYLINE");
}
strColor.Format(_T("%d"), nColor);
CString strTmp = strEntName + strLayerName + strLineStyle + strColor;
it = std::find(vec.begin(), vec.end(), strTmp);
if (it == vec.end())
{
vec.push_back(strTmp);
struct resbuf *pBuf1 = ads_buildlist(-4, _T("<and"), RTDXF0, strEntName, 6, strLineStyle, 8, strLayerName, 62, nColor, -4, _T("and>"), NULL);
rbList.Append(pBuf1);
}
}
struct resbuf *pBuf3 = ads_buildlist(-4, _T("or>"), NULL);
rbList.Append(pBuf3);
}
// (主函数)雨水划分线
void DivisionLine()
{
g_ssPickFirst.Free(); //清空当前选择集,避免执行命令前已选择实体
PickSet ss(SS_FREE);
SerachDivisionLine(ss);
std::map<AcDbObjectId, int> data; // 保存划分线原来颜色值
ChangeDivisionLineColor(ss, data); // 显示已存在的划分线
RBList rbMark = ads_buildlist(RTDXF0, _T("LINE,LWPOLYLINE,ARC"), NULL);
int nRet = 0;
TCHAR chRet;
while (TRUE)
{
PickSet ssSel(SS_FREE);
INITGET_BEG(0, _T("D"));
nRet = SelectEntities(_T("\n请选择作为参考的汇水划分线{删除划分线(D)}<退出>:"), ssSel, rbMark, _T("D"), chRet);
INITGET_END();
if(nRet == RTKWORD){
if(chRet==_T('D'))
{
PickSet ss2(SS_FREE);
if (SelectEntities(_T("\n请选择对象:"),ss2,rbMark) != RTNORM)
{
continue;
}
ss -= ss2;
std::map<AcDbObjectId, int>::iterator it;
for (long i = 0; i < ss2.Length(); i++)
{
Entity ent2 = ss2[i];
AcDbObjectId id;
acdbGetObjectId(id, ent2);
it = data.find(id);
if (it != data.end())
{
AcDbEntity *pEnt = NULL;
acdbOpenObject(pEnt, id, AcDb::kForWrite);
if (pEnt != NULL)
{
pEnt->setColorIndex((*it).second);
pEnt->close();
}
WriteXdata(ent2, _T("DivisionLine"), _T("0"));
data.erase((*it).first);
}
}
continue;
}
}
else if(nRet != RTNORM)
{
// 恢复划分线颜色
RecoverDivsionLineColor(data);
return;
}
ss += ssSel;
RBList rblst;
GetRBListByLine(rblst, ssSel, data);
PickSet ssAdd(SS_FREE);
nRet = SelectEntities(_T("请选择范围<整张图>:"), ssAdd, rblst);
if (nRet == RTERROR)
{
acedSSGet(_T("A"), NULL, NULL, rblst, ssAdd);
}
else if (nRet != RTNORM)
{
break;;
}
ss += ssAdd;
ChangeDivisionLineColor(ssAdd, data);
}
}
//***************************************************************************************************
// 屋面汇水面积
//***************************************************************************************************
// 获得TDbSpace的外围框(PLINE)
void ExplodeSpace(PickSet &ss, TDPtrList<TGGePoly2D> &lstDest)
{
for (long i = 0; i < ss.Length(); i++)
{
Entity ent = ss[i];
AcDbObjectId idSpace;
acdbGetObjectId(idSpace, ent);
TDbSpace *pSpace = NULL;
acdbOpenObject(pSpace, idSpace, AcDb::kForWrite);
if (pSpace != NULL)
{
AcDbVoidPtrArray arPt;
pSpace->explode(arPt);
for (int i = 0; i < arPt.length(); i++)
{
AcDbEntity *pEnt = (AcDbEntity*)arPt[i];
AcDbPolyline *pLine = AcDbPolyline::cast(pEnt);
if (pLine != NULL)
{
AcDbObjectId id = AddToCurrentSpace(pLine, Adesk::kTrue);
ads_name sName;
acdbGetAdsName(sName, id);
Entity entPline(sName);
TGGePoly2D *pPoly = new TGGePoly2D(entPline);
lstDest.Append(pPoly);
entPline.Erase();
continue;
}
delete pEnt;
}
pSpace->close();
}
}
}
// 合并闭合pLine
void UnionPLine(TDPtrList<TGGePoly2D> &lstPoly)
{
for (int j = 0; j < lstPoly.Length(); j++)
{
TDPtrList<TGGePoly2D> lst;
lst.Append(new TGGePoly2D(*lstPoly.GetAt(j)));
for (int h = j + 1; h < lstPoly.Length(); h++)
{
TDPtrList<TGGePoly2D> lstClip, lstRes;
lstClip.Append(new TGGePoly2D(*lstPoly.GetAt(h)));
Union(lst, lstClip, lstRes);
if (lstRes.Length() > 0)
{
TDPtrList<TGGePoly2D> lstTemp;
lstTemp.copyFrom(lstPoly);
lstPoly.Reset();
int n = lstTemp.Length();
for (int k = 0; k < lstTemp.Length(); k++)
{
if (k != j && k != h)
{
TGGePoly2D *p = new TGGePoly2D(*lstTemp.GetAt(k));
lstPoly.Append(p);
}
}
for (k = 0; k < lstRes.Length(); k++)
{
TGGePoly2D *p = new TGGePoly2D(*lstRes.GetAt(k));
lstPoly.Append(p);
}
j = -1;
break;
}
}
}
}
// 合并汇水面积
void UnionSpace(PickSet &ss)
{
// 获得Pline
TDPtrList<TGGePoly2D> lstPoly;
ExplodeSpace(ss, lstPoly);
// 合并PLINE
UnionPLine(lstPoly);
// 由闭合区域生成ATS_SPACE实体(汇水面积)
CreateTchSpace(lstPoly);
}
// 主函数
void CreateRunoffArea()
{
// 搜索已存在的雨水划分线
PickSet ss(SS_FREE);
SerachDivisionLine(ss);
std::map<AcDbObjectId, int> data; // 保存划分线原来颜色值
ChangeDivisionLineColor(ss, data); // 显示已存在的划分线
int nRet = 0;
TCHAR chRet;
RBList rbMark = ads_buildlist(RTDXF0, _T("LINE,LWPOLYLINE,ARC"), NULL);
while (TRUE)
{
PickSet ssSel(SS_FREE);
INITGET_BEG(0, _T("A D"));
nRet = SelectEntities(_T("\n请框选需要围合面积的汇水划分线{合并汇水面积(A)/绘制汇水面积(D)}<退出>:"), ssSel, rbMark, _T("A D"), chRet);
INITGET_END();
if (nRet == RTKWORD)
{
// 恢复划分线颜色
RecoverDivsionLineColor(data);
if (chRet == _T('A'))
{
RBList rbList = ads_buildlist(RTDXF0, _T("ATS_SPACE"), NULL);
PickSet ssSpace(SS_FREE);
if (SelectEntities(_T("\n请选择需要合并汇水面积的区域<退出>:"), ssSpace, rbList) != RTNORM)
{
continue;
}
// 合并汇水面积
UnionSpace(ssSpace);
// 删除当前选择的汇水面积
ssSpace.Erase();
}
else if (chRet == _T('D'))
{
XPoly2D poly2d;
if (GetOpenPoly2D(_T("\n请勾绘封闭汇流面积:"), poly2d) != RTNORM)
{
continue;
}
else
{
if (!poly2d.IsClosed())
{
poly2d.SetFlag(1);
}
TDPtrList<TGGePoly2D> lstPoly2d;
lstPoly2d.Append(new TGGePoly2D(poly2d));
// 由闭合区域生成ATS_SPACE实体(汇水面积)
CreateTchSpace(lstPoly2d);
}
}
continue;
}
else if (nRet != RTNORM)
{
// 恢复划分线颜色
RecoverDivsionLineColor(data);
return;
}
if (ss.Length() ==0)
{
acutPrintf(_T("\n请先选好汇水划分线!"));
return;
}
// 过滤掉非划分线
PickSet ssDel(SS_FREE);
for (long i = 0; i < ssSel.Length(); i++)
{
if (!ss.IsInclude(ssSel[i]))
{
ssDel += ssSel[i];
}
}
ssSel -= ssDel;
// 根据选择的划分线,获得闭合区域
TDPtrList<TGGePoly2D> lstDest;
GetClosePoly2D(ssSel, lstDest);
// 由闭合区域生成ATS_SPACE实体(汇水面积)
CreateTchSpace(lstDest);
}
}
//***************************************************************************************************
// 屋面信息计算
//***************************************************************************************************
void RoofInfoCalc()
{
RBList rbMark = ads_buildlist(RTDXF0, _T("ATS_SPACE"), NULL);
PickSet ss(SS_FREE);
int nRet = 0;
TCHAR chRet;
BOOL bSideWall = FALSE; // 是否有侧墙
INITGET_BEG(0, _T("A"));
nRet = SelectEntities(_T("\n请框选屋面汇水面积{带侧墙屋面汇水面积(A)}<退出>:"), ss, rbMark, _T("A"), chRet);
INITGET_END();
if (nRet == RTKWORD)
{
if (chRet == _T('A'))
{
Entity ent;
if (SelectEntity(_T("\n请单选屋面汇水面积<退出>:"), ent, rbMark) != RTNORM)
{
return;
}
bSideWall = TRUE;
ss += ent;
}
}
else if (nRet != RTNORM)
{
return;
}
std::vector<AcDbObjectId> data;
for (long i = 0; i < ss.Length(); i++)
{
AcDbObjectId id;
acdbGetObjectId(id, ss[i]);
data.push_back(id);
}
CTemporaryResourceOverride vTemp;
CRoofInfoCalcDlg dlg(0,acedGetAcadFrame());
dlg.SetSpaceIdData(data);
dlg.SetSideWall(bSideWall);
dlg.DoModal();
}
//***************************************************************************************************
// 溢流堰计算
//***************************************************************************************************
void OverfallWeirCalc()
{
CTemporaryResourceOverride vTemp;
COverfallWeirCalcDlg dlg;
dlg.DoModal();
}
//***************************************************************************************************
// 布雨水斗
//***************************************************************************************************
// 插入雨水斗
void InsEqumentBlk(const XPoint &pt, CWaterBucketDlg &dlg)
{
// 标注
XPoint ptIns = pt;
ptIns = Wcs2Ucs(ptIns);
AcGeVector3d vt = AcGeVector3d::kXAxis;
vt.rotateBy(PI / 4, AcGeVector3d::kZAxis);
ptIns += vt * dlg.GetSize() * DocGetPScale() * DocGetPScale() / 100 * 0.6;
ptIns = Ucs2Wcs(ptIns);
TDbText *pText = new TDbText;
AcDbObjectId idTextStyle=InitTwtTextStyle(g_csSheetStyle);
pText->SetStyleId(idTextStyle);
pText->SetHeight(0.4 * dlg.GetSize() * DocGetPScale() / 100);
pText->SetAlignment(XExplodeDraw::kBottomLeft);
pText->SetRotation(Ucs2Wcs(0.0));
pText->SetText(dlg.GetNumber());
pText->setLayer(InitLayer(LAY_DIM_RAIN));
pText->SetLocation(ptIns);
pText->setColorIndex(7);
AddToCurrentSpace(pText, Adesk::kTrue);
// 雨水斗
CString csBlkName = dlg.GetBlkName();
CString csTK, csRecord;
SplitBlkStr(csBlkName, csTK, csRecord);
TDbEquipment *pEqup = new TDbEquipment;
pEqup->SetBlock2d(GetBlkIdByName(csBlkName));
pEqup->SetBlock3d(GetBlkIdByName(_T("$TwtSys$00000525")));
pEqup->SetLocation(pt);
pEqup->SetInsert(pt);
pEqup->SetScale(dlg.GetSize() * DocGetPScale());
pEqup->setLayer(InitLayer(LAY_EQ_RAIN));
AddToCurrentSpace(pEqup, Adesk::kTrue);
// 添加扩展数据
Entity ent;
ent.GetLast();
double dDeep = dlg.GetDeep();
CString strDia, strFlux, strDeep;
strDia.Format(_T("%f"), dlg.GetPipeDia());
WriteXdata(ent, _T("PipeDia"), strDia);
WriteXdata(ent, _T("WaterBucket"), _T("1")); // TDbEquipment是雨水斗的标志
dlg.AddNumber();
}
// 已知一个线段,在上面按等距布置雨水斗,并连管
//如果pCurve为空退出
BOOL InsWaterBucketByCurve(AcDbCurve *pCurve, XPoint ptWell, XPoint &ptPick, Entity &entLastWell, CWaterBucketDlg &dlg)
{
if (pCurve == NULL)
return FALSE;
double dDistEven = dlg.GetDistance();
if(!DocGetMeterUnitDraw())
dDistEven = dDistEven * 1000;
double dEndParam, dStartParam, dWellParam, dPickParam;
XPointList lstPt;
lstPt.NewAppend(ptWell);
XPoint ptOnCurve;
pCurve->getClosestPointTo(ptWell, ptOnCurve);
double dDist = ads_distance(ptWell, ptOnCurve);
if(dDist > 0.001)
return FALSE;
ptWell = ptOnCurve;
pCurve->getClosestPointTo(ptPick, ptPick);
pCurve->getEndParam(dEndParam);
pCurve->getStartParam(dStartParam);
pCurve->getParamAtPoint(ptWell, dWellParam);
pCurve->getParamAtPoint(ptPick, dPickParam);
double dFromStart = fabs(dPickParam - dStartParam);
double dFromEnd = fabs(dPickParam - dEndParam);
BOOL bToStart = FALSE;
if(dPickParam > dWellParam)
bToStart = FALSE;
else if(dPickParam < dWellParam)
bToStart = TRUE;
double dDist2Well(0), dAllLength(0), dLength(0), dParamDist(0);
pCurve->getDistAtPoint(ptWell, dDist2Well);
pCurve->getDistAtParam(dPickParam, dAllLength);
if(bToStart)
dLength = dDist2Well - dAllLength;
else
dLength = dAllLength - dDist2Well;
int num = int(dLength / dDistEven);
double dTmpDist(dDist2Well);
for(int i=0;i<num;i++)
{
if(bToStart)
dTmpDist -= dDistEven;
else
dTmpDist += dDistEven;
XPoint ptTmp;
pCurve->getPointAtDist(dTmpDist, ptTmp);
lstPt.NewAppend(ptTmp);
ptPick = ptTmp;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// 第二步, 绘制雨水斗
int nLen = lstPt.Length();
if(nLen < 2)
return FALSE;
CString csBlkName = dlg.GetBlkName();
double dEle = dlg.GetEle();
if (!DocGetMeterUnitDraw())
{
dEle *= 1000;
}
for(i=1;i < nLen; i++)
{
XPoint ptIns = *lstPt[i];
ptIns.z = dEle;
InsEqumentBlk(ptIns, dlg);
}
return TRUE;
}
// 沿线等距布置雨水斗(支持OFFSET)
void InsWaterBucketByLine(XPoint pt, Entity &entLast, CWaterBucketDlg &dlg)
{
XPoint ptTemp = pt;
PickSet ss(SS_FREE);
RBList rbMask(RTDXF0, _T("LWPOLYLINE,LINE,ARC"), NULL);
GetPointPickSet(ptTemp,ss,rbMask,1);
pt.z = 0;
Entity ent, ent2;
XPoint ptPick, ptPick2;
double dOffsetDist(0);
if (ss.Length() <= 0)
{
//雨水斗不在所选的线上面
if(SelectEntity1(0.3, _T("\n请拾取布置雨水斗需要沿的PLINE、直线、弧线 <退出>"), ent, ptPick, rbMask) != RTNORM)
return;
ptPick = Ucs2Wcs(ptPick);
OPENOBJ_BEGIN(ent, AcDb::kForRead, AcDbCurve, pCurve);
if(pCurve)
{
XPoint ptOnCurve;
pCurve->getClosestPointTo(pt, ptOnCurve);
dOffsetDist = ads_distance(pt, ptOnCurve);
if(dOffsetDist > 0.001)
{
AcDbCurve *pCurve2 = GetOffsetCurve(pCurve, dOffsetDist, pt);
if (pCurve2 == NULL)
return;
InsWaterBucketByCurve(pCurve2, pt, ptPick, entLast, dlg);
delete pCurve2;
pt = ptPick;
pCurve->getClosestPointTo(ptPick, ptPick);
}
else
{
InsWaterBucketByCurve(pCurve, pt, ptPick, entLast, dlg);
}
}
OPENOBJ_END();
if(ent.Is(_T("LWPOLYLINE")))
return;
}
else
{
ptPick = ptTemp;
long lIndex = 0;
ent = ss[lIndex];
}
while(SelectEntity1(0.3, _T("\n请拾取下一段PLINE、直线、弧线 <退出>"), ent2, ptPick2, rbMask) == RTNORM)
{
ptPick2 = Ucs2Wcs(ptPick2);
//临时创建1条PLINE线,反复调用InsWellByCurve
AcDbPolyline *pLine = GetNextPloyLine(ent, ent2, ptPick, ptPick2);
if(pLine != NULL)
{
if(dOffsetDist > 0.001)
{
AcDbCurve *pCurveOffset = GetOffsetCurve((AcDbCurve *)pLine, dOffsetDist, pt);
pCurveOffset->getClosestPointTo(ptPick, pt);
pCurveOffset->getClosestPointTo(ptPick2, ptPick2);
InsWaterBucketByCurve(pCurveOffset, pt, ptPick2, entLast, dlg);
pt = ptPick2;
delete pCurveOffset;
pLine->getClosestPointTo(ptPick2, ptPick2);
}
else
InsWaterBucketByCurve(pLine, ptPick, ptPick2, entLast, dlg);
delete pLine;
ptPick = ptPick2;
ent = ent2;
}
}
}
// 主函数
void InsWaterBucket()
{
int nOsMode=0;
xg_getvar(_T("OSMODE"), &nOsMode);
if(g_bTgOsnap)
{
nOsMode &= ~0x4000;
nOsMode |= OS_INT|OS_END|OS_NEA;
}
XPushVar<int> vOsMode(_T("OSMODE"), nOsMode);
CWaterBucketDlg dlg(acedGetAcadFrame());
{
CTemporaryResourceOverride vTemp;
dlg.Create(IDD_WATER_BUCKET, acedGetAcadFrame());
dlg.ShowWindow(SW_SHOW);
acedGetAcadDwgView()->SetFocus();
}
XPoint ptStart;
int ret0(0);;
while (ret0 != RTNORM)
{
INITGET_BEG(0, _T("F L"));
ret0 = ads_getpoint(NULL, _T("\n请点取插入点[输入参考点(F)/选取参考线(L)]<退出>:"), ptStart);
INITGET_END();
if(ret0 == RTKWORD)
{
XString sKeyword;
ads_getinput(sKeyword);
TCHAR cKey = sKeyword[0];
if(cKey==_T('F'))
{
if(ads_getpoint(NULL,_T("\n请输入参考点:"), ptStart) != RTNORM){
dlg.DestroyWindow();
return;
}
ptStart = Ucs2Wcs(ptStart);
ads_getpoint(ptStart, _T("\n请输入距参考点的距离<确定>:"), ptStart);
break;
}
if(cKey==_T('L'))
{
RBList rbMask(RTDXF0, _T("LINE"), NULL);
Entity entLine;
XPoint ptPick;
if(SelectEntity(_T("\n请拾取布置雨水斗需要参考的边线<退出>"), entLine, ptPick, rbMask) != RTNORM)
{
dlg.DestroyWindow();
return;
}
ptPick = Ucs2Wcs(ptPick);
XCurveSegment seg(entLine);
seg.ProjectToMe(ptPick, ptPick);
double nAng = ads_angle(seg.EndPoint(), seg.StartPoint());
double dDist2Line(1000);
ads_getreal(_T("\n请输入距基线距离<1000>"), &dDist2Line);
XPoint ptend, ptPipe;
int itype = -1;
ads_prompt(_T("\n请选择插入方向<确定>"));
while(true)
{
struct resbuf pointbuf;
int iRet = ads_grread(5, &itype, &pointbuf);
ads_point_set(pointbuf.resval.rpoint, ptend);
ptend = Ucs2Wcs(ptend);
if(itype != 5 && itype != 3 && itype != 11)
break;
AcGeVector3d vectBase(seg.EndPoint().x - seg.StartPoint().x, seg.EndPoint().y - seg.StartPoint().y, 0);
AcGeVector3d vectTmp(ptend.x - ptPick.x, ptend.y - ptPick.y, 0);
double dAng2 = vectBase.angleTo(vectTmp, AcGeVector3d::kZAxis);
if(dAng2 < PI)
ads_polar(ptPick, nAng - PI/2, dDist2Line, ptPipe);
else{
ads_polar(ptPick, nAng + PI/2, dDist2Line, ptPipe);
}
ads_redraw(NULL, 1);
if(itype == 3 || itype == 11)
{
ptStart = Wcs2Ucs(ptPipe);
break;
}
else
{
XPoint ptTmpUcs1 = Wcs2Ucs(ptPick);
XPoint ptTmpUcs2 = Wcs2Ucs(ptPipe);
ads_grdraw(ptTmpUcs1, ptTmpUcs2, -1, 0);
}
}
break;
}
}
else if(ret0 == RTCAN || ret0 == RTNONE)
{
dlg.DestroyWindow();
return;
}
}
// 加载雨水斗三维图块
CString strDwb = g_csDwbPath + _T("TwtSys");
XString xsTmp1;
if(LoadDwbBlock(strDwb, _T("00000525"), xsTmp1) != RTNORM) //三维雨水斗
{
acutPrintf(_T("\n三维雨水斗图块加载失败!"));
dlg.DestroyWindow();
return;
}
// 在插入点布置雨水斗
ptStart = Ucs2Wcs(ptStart);
dlg.UpdateData(TRUE);
CString csBlkName = dlg.GetBlkName();
CString csTK, csRecord;
SplitBlkStr(csBlkName, csTK, csRecord);
XString xsTmp;
if(LoadDwbBlock((const TCHAR*)csTK, (const TCHAR*)csRecord, xsTmp) != RTNORM)
{
dlg.DestroyWindow();
return;
}
double dMeter = 1.0;
if (!DocGetMeterUnitDraw())
{
dMeter = 1000;
}
XPoint pt = ptStart;
pt.z = dlg.GetEle() * dMeter;
InsEqumentBlk(pt, dlg);
Entity entLast;
entLast.GetLast();
// 根据布置方式布置雨水斗
XPointList lstPt;
lstPt.NewAppend(ptStart);
double nOld = g_nSprinklerRadius;
double dJigLockAng(-1);
while(true)
{
TWellJig jig(ptStart);
jig.m_nLockAng = dJigLockAng;
dlg.UpdateData(TRUE);
double dDist = dlg.GetDistance();
int nMode = dlg.GetMode();
if(!DocGetMeterUnitDraw())
{
dDist = dDist * 1000;
}
if (nMode == 0)
{
jig.SetDist(0);
}
else if (nMode == 2)
{
jig.SetDist(dDist);
}
else if (nMode == 3)
{
jig.SetDist2(dDist);
}
else if (nMode == 1) //沿线定距
{
InsWaterBucketByLine(ptStart, entLast, dlg);
break;
}
jig.SetPrompt(_T("\n请点取雨水斗插入点[回退(U)/选取行向线(F)]<退出>:"));
jig.SetKeyword(_T("U F R"));
int nKeyIndex;
int nRetCode = jig.DoIt(&nKeyIndex);
if(nRetCode == RTKWORD)
{
if(nKeyIndex == 0)
{
int nLen = lstPt.Length();
if(nLen == 1) continue; //最后一个, 不能再退了
SHads_command(RTSTR, _T("UNDO"), RTSTR, _T("BACK"), NULL);
lstPt.Remove(nLen - 1);
XPoint ptTemp = *lstPt[nLen - 2];
jig.SetStartPoint(ptTemp);
ptStart = ptTemp;
}
else if(nKeyIndex == 1)
{
double s_angle(0);
int err_value=get_line_angle(s_angle);
if(err_value == RTNORM)
{
dJigLockAng = s_angle;
}
}
continue;
}
else if(nRetCode != RTNORM)
{
break;
}
XPoint ptIns = jig.GetPickPoint();
XPoint ptUcs = Ucs2Wcs(jig.GetPickPoint());
if(jig.m_nLockAng > -1)
{
ptUcs = jig.GetCorrectPt();
ptIns = jig.GetCorrectPt();
jig.m_nLockAng = -1;
}
SHads_command(RTSTR, _T(".UNDO"), RTSTR, _T("MARK"), NULL); // Make a undo mark
dlg.UpdateData(TRUE);
nMode = dlg.GetMode();
if (nMode == 0 || nMode == 2) //任意布置或定距单布
{
XPoint pt = ptIns;
pt.z = dlg.GetEle() * dMeter;
InsEqumentBlk(pt, dlg);
}
else if (nMode == 3) //两点定距
{
XLine line(ptStart, jig.GetPickPoint(), 1);
double nRotate = line.Direction();
XCurveSegment seg;
seg = line;
XPointList lstPt;
GetPointList(seg, dDist, lstPt);
int nLen = lstPt.Length();
CString csName = dlg.GetBlkName();
for(int i=1; i < nLen; i++)
{
XPoint ptIns = *lstPt[i];
ptIns.z = dlg.GetEle() * dMeter;
InsEqumentBlk(ptIns, dlg);
}
break;
}
ptStart = ptIns;
jig.SetStartPoint(ptStart);
lstPt.NewAppend(ptStart);
}
dlg.DestroyWindow();
UNDOE;
}
//***************************************************************************************************
// 连雨水斗
//***************************************************************************************************
void DrawPipe(Entity &ent, XPoint ptS, XPoint ptE, double dDia, bool bVertical = false)
{
OPENOBJ_BEGIN(ent, AcDb::kForRead, TDbPipe, pPipe);
if(pPipe){
TDbPipe *pNewPipe = new TDbPipe;
pNewPipe = (TDbPipe*)pPipe->clone();
pNewPipe->ResetAllShip(); //新创建的管线前后节点信息清空
pNewPipe->SetStartPoint(ptS);
pNewPipe->SetEndPoint(ptE);
// 修改管线图层
pNewPipe->setLayer(pPipe->layerId());
pNewPipe->SetDnDiameter(dDia);
if (bVertical)
{
pNewPipe->SetRadius(0.01);
}
AddToCurrentSpace(pNewPipe, Adesk::kTrue);
}
OPENOBJ_END();
}
void LinkWaterBucketToPipe(Entity& entMain, PickSet &ss, PickSet &ssPipe)
{
XLine line(1);
double dDn = 0;
OPENOBJ_BEGIN(entMain, AcDb::kForRead, TDbPipe, pPipe);
if(pPipe)
{
line.StartPoint() = pPipe->StartPoint();
line.EndPoint() = pPipe->EndPoint();
dDn = pPipe->GetDnDiameter();
}
OPENOBJ_END();
for(long i = 0; i < ss.Length(); i++)
{
Entity ent = ss[i];
XPoint ptNew, ptIns;
double dEle = 0;
OPENOBJ_BEGIN(ent, AcDb::kForRead, TDbEquipment, pEqup);
if(pEqup != NULL)
{
ptIns = pEqup->GetLocation();
dEle = ptIns.z;
}
OPENOBJ_END();
if (!DocGetMeterUnitDraw())
{
dEle /= 1000;
}
if(!ptIns)
continue;
if(dEle > 0.001)
{
ptIns.z = dEle * 1000;//得到给水点指定标高
}
ptIns.Project(&line, ptNew);
if(fabs(ptIns.z - ptNew.z) > 0.001) //有标高差,需要绘制一段立管
{
double dFeedEle = ptIns.z;
ptIns.z = ptNew.z;
DrawPipe(entMain, ptIns, ptNew, dDn);
Entity ent;
ent.GetLast();
ssPipe += ent;
XPoint p1,p2;
p1 = ptIns;
p2 = ptIns;
p1.z = dFeedEle;
DrawPipe(entMain, p1, p2, dDn, true);
}
else
{
DrawPipe(entMain, ptIns, ptNew, dDn);
Entity ent;
ent.GetLast();
ssPipe += ent;
}
}
}
// 检查出流端管道另一侧是否连着其他管件(管道流向流进端)
BOOL ExistPipeAttachment(Entity &ent, XPoint &ptPick)
{
BOOL bExist = FALSE;
AcDbObjectId id, id2;
acdbGetObjectId(id, ent);
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, id, AcDb::kForRead);
if (pPipe != NULL)
{
XPoint ptS, ptE;
ptS = pPipe->StartPoint();
ptE = pPipe->EndPoint();
// 找出出流端
double dLen1 = ptS.Distance(ptPick);
double dLen2 = ptE.Distance(ptPick);
XPoint pt;
if (dLen2 > dLen1)
{
id2 = pPipe->GetNode(1);
}
else
{
id2 = pPipe->GetNode(0);
}
pPipe->close();
}
if (id2.isValid())
{
bExist = TRUE;
TDbPipeFitting *pFit = NULL;
acdbOpenObject(pFit, id2, AcDb::kForRead);
if (pFit != NULL)
{
if (pFit->GetInterfaceNum() == 1) //堵头
{
bExist = FALSE;
}
pFit->close();
}
}
return bExist;
}
// 生成倒角
void MakeChafer(Entity &ent, PickSet &ss, double dChamferLen, XPoint &ptPick)
{
XPoint ptS, ptE;
OPENOBJ_BEGIN(ent, AcDb::kForRead, TDbPipe, pPipe);
if (pPipe != NULL)
{
ptS = pPipe->StartPoint();
ptE = pPipe->EndPoint();
}
OPENOBJ_END();
// 确定管道流向
XPoint ptFlow; // 出流端管线端点
double dLen1 = ptS.Distance2d(ptPick);
double dLen2 = ptE.Distance2d(ptPick);
AcGeVector3d vt;
if (dLen1 < dLen2)
{
vt = ptS - ptE;
ptFlow = ptS;
}
else
{
vt = ptE - ptS;
ptFlow = ptE;
}
vt.normalize();
XLine line(ptS, ptE, 1);
std::map<double, XPoint> data; //保存出流端管段上的交点
for (long i = 0; i < ss.Length(); i++)
{
Entity entPipe = ss[i];
AcDbObjectId idPipe;
acdbGetObjectId(idPipe, entPipe);
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, idPipe, AcDb::kForWrite);
if (pPipe != NULL)
{
XPoint pt1, pt2;
pt1 = pPipe->StartPoint();
pt2 = pPipe->EndPoint();
XPoint pt3, pt4;
pt1.Project(&line, pt3);
pt2.Project(&line, pt4);
double dLen1 = pt1.Distance2d(pt3);
double dLen2 = pt2.Distance2d(pt4);
if (pPipe->IsVertical())
{
if (dLen1 < 1e-3)
{
data.insert(std::make_pair(ptFlow.Distance(pt1), pt1));
}
else if (dLen2 < 1e-3)
{
data.insert(std::make_pair(ptFlow.Distance(pt2), pt2));
}
pPipe->erase();
pPipe->close();
continue;
}
// 生成倒角
if (pt1.Distance(pt2) >= dChamferLen) // 管线长度大于等于倒角长度可以倒角
{
AcGeVector3d vt2 = pt1 - pt2;
vt2.normalize();
if (dLen1 < 1e-3)
{
XPoint pt = pt1 - vt2 * dChamferLen;
pPipe->SetStartPoint(pt);
pPipe->close();
XPoint ptTmp= pt1 + vt * dChamferLen;
DrawPipe(entPipe, pt, ptTmp, pPipe->GetDnDiameter());
Entity ent;
ent.GetLast();
WriteXdata(ent, _T("Chamfer"), _T("1"));
data.insert(std::make_pair(ptFlow.Distance(ptTmp), ptTmp));
}
else if (dLen2 < 1e-3)
{
vt2 = -vt2;
XPoint pt = pt2 - vt2 * dChamferLen;
pPipe->SetEndPoint(pt);
pPipe->close();
XPoint ptTmp= pt2 + vt * dChamferLen;
DrawPipe(entPipe, pt, ptTmp, pPipe->GetDnDiameter());
Entity ent;
ent.GetLast();
WriteXdata(ent, _T("Chamfer"), _T("1"));
data.insert(std::make_pair(ptFlow.Distance(ptTmp), ptTmp));
}
else
{
pPipe->close();
}
}
else // 管线长度小于倒角长度不能倒角
{
if (dLen1 < 1e-3)
{
data.insert(std::make_pair(ptFlow.Distance(pt1), pt1));
}
else if (dLen2 < 1e-3)
{
data.insert(std::make_pair(ptFlow.Distance(pt2), pt2));
}
pPipe->close();
}
}
}
// 处理多余管道
if (data.size() > 0 && !ExistPipeAttachment(ent, ptPick))
{
std::map<double,XPoint>::iterator it;
it = data.end();
--it;
XPoint pt = (*it).second;
double d = (*it).first;
OPENOBJ_BEGIN(ent, AcDb::kForWrite, TDbPipe, pPipe);
if (pPipe != NULL)
{
ptS = pPipe->StartPoint();
ptE = pPipe->EndPoint();
if (ptFlow.Distance(ptS) < 1e-3)
{
pPipe->SetEndPoint(pt);
}
else if (ptFlow.Distance(ptE) < 1e-3)
{
pPipe->SetStartPoint(pt);
}
}
OPENOBJ_END();
}
}
void UpdataPipeMatrial(SSearchPipeList *pListAll)
{
if (pListAll != NULL)
{
if (pListAll->m_iType == 0)
{
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, pListAll->m_ID, AcDb::kForWrite);
if (pPipe != NULL)
{
CString strTmp = GetPipeMaterialByIdx(pPipe->GetMaterial());
if (strTmp.Compare(_T("排水铸铁管")) == 0)
{
XStringList lstMat;
GetPipeMaterialList(lstMat);
for (int i = 0; i < lstMat.Length(); i++)
{
strTmp = lstMat.GetAt(i);
if (strTmp.Compare(_T("内壁涂塑离心排水铸铁管")) == 0)
{
pPipe->SetMaterial(i);
break;
}
}
}
pPipe->close();
}
}
for (int i = 0; i < pListAll->m_lstNode.Length(); i++)
{
UpdataPipeMatrial(pListAll->m_lstNode[i]);
}
}
}
//更新pt点存在的管段的管材
void UpdataPipeMatrial(XPoint &pt)
{
const double dDist = 100;
AcGePoint3d ptGeLB ,ptGeLT, ptGeRB, ptGeRT;
AcGeVector3d vtX = AcGeVector3d::kXAxis;
AcGeVector3d vtY = AcGeVector3d::kYAxis;
ptGeLB = pt - vtX * dDist / 2;
ptGeLB = ptGeLB - vtY * dDist / 2;
ptGeLT = ptGeLB + vtY * dDist;
ptGeRB = ptGeLB + vtX * dDist;
ptGeRT = ptGeRB + vtY * dDist;
PickSet ssSel(SS_FREE);
RBList rbFilter = acutBuildList( -4, _T("<or"),
-4, _T("<and"), RTDXF0, _T("ATS_PIPE"), 8, LAY_PIPE_RAIN, -4, _T("and>"),
-4, _T("<and"), RTDXF0, _T("ATS_PIPE"), 8, LAY_VPIPE_RAIN, -4, _T("and>"),
-4, _T("or>"), NULL);
TADSGePoint3d _pt1 = Wcs2Ucs(ptGeLB)
, _pt2 = Wcs2Ucs(ptGeLT)
, _pt3 = Wcs2Ucs(ptGeRT)
, _pt4 = Wcs2Ucs(ptGeRB);
RBList rbPt = acutBuildList(RTPOINT,&_pt1,RTPOINT,&_pt2,RTPOINT,&_pt3, RTPOINT,&_pt4,NULL);
acedSSGet(_T("CP"),rbPt,NULL,rbFilter,ssSel);
for (long i = 0; i < ssSel.Length(); i++)
{
OPENOBJ_BEGIN(ssSel[i], AcDb::kForWrite, TDbPipe, pPipe);
if (pPipe != NULL)
{
CString strTmp = GetPipeMaterialByIdx(pPipe->GetMaterial());
if (strTmp.Compare(_T("排水铸铁管")) == 0)
{
XStringList lstMat;
GetPipeMaterialList(lstMat);
for (int i = 0; i < lstMat.Length(); i++)
{
strTmp = lstMat.GetAt(i);
if (strTmp.Compare(_T("内壁涂塑离心排水铸铁管")) == 0)
{
pPipe->SetMaterial(i);
break;
}
}
}
}
OPENOBJ_END();
}
}
// 主函数
void LinkWaterBucket()
{
Entity entMain;
RBList rbMask = ads_buildlist(RTDXF0, _T("ATS_EQUIPMENT"), 8, _T("*"), NULL);
RBList rbMaskPipe(RTDXF0, _T("ATS_PIPE"), 8, LAY_PIPE_RAIN, NULL);
int nRet = 0;
TCHAR chKey = _T('\0');
double dChamferLen = 300;
XPoint ptPick;
while (TRUE)
{
INITGET_BEG(0, _T("A"));
nRet = SelectEntity(_T("\n请选择连接雨水斗管线的末端{改变倒角长度[A]}<退出>:"), entMain, ptPick, rbMaskPipe, _T("A"), chKey);
INITGET_END();
#if (ADS == 19)
if (chKey == _T('\0'))
{
TCHAR szCh[20];
acedGetInput(szCh);
chKey = szCh[0];
}
#endif
if (nRet == RTKWORD)
{
if (chKey == _T('A'))
{
CString strTip;
strTip.Format(_T("\n请输入倒角长度(mm)<%.0f>:"), dChamferLen);
acedGetReal(strTip, &dChamferLen);
//dChamferLen *= sqrt(2.0);
}
continue;
}
else if (nRet != RTNORM)
{
return;
}
break;
}
// 如果搜索到的管道系统中管道为雨水管并且为排水铸铁管,则将管材改为 内壁涂塑离心排水铸铁管
SSearchPipeList *pListAll = new SSearchPipeList();
PickSet ssAll(SS_FREE);
ssAll += entMain;
if(!SearchSprinkPipeSys(entMain, NULL, pListAll, ssAll))
{
AfxMessageBox(_T("系统有回路!"));
delete pListAll;
return;
}
//修改管段端点处可能存在的管段的管材
XPoint pt1, pt2;
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, pListAll->m_ID, AcDb::kForRead);
if (pPipe != NULL)
{
pt1 = pPipe->StartPoint();
pt2 = pPipe->EndPoint();
pPipe->close();
}
UpdataPipeMatrial(pt1); //修改pt1点可能不在系统中的管道管材
UpdataPipeMatrial(pt2);
UpdataPipeMatrial(pListAll);
delete pListAll;
PickSet ss(SS_FREE);
if(SelectEntities(_T("\n请选择与该管道相连的雨水斗<退出>:"), ss, rbMask) != RTNORM)
{
return;
}
// 雨水斗连接管线
PickSet ssPipe(SS_FREE);
LinkWaterBucketToPipe(entMain, ss, ssPipe);
//生成倒角
ptPick = Ucs2Wcs(ptPick);
MakeChafer(entMain, ssPipe, dChamferLen, ptPick);
}
//***************************************************************************************************
// 虹吸计算
//***************************************************************************************************
// 判断管子角度是否是45°的整数倍数
BOOL Is45Angle(AcDbObjectId &id1, AcDbObjectId &id2)
{
ads_name name1, name2;
acdbGetAdsName(name1, id1);
acdbGetAdsName(name2, id2);
Entity ent1(name1), ent2(name2);
XPoint pt1, pt2, pt3, pt4;
GetPipePoint(ent1, pt1, pt2);
GetPipePoint(ent2, pt3, pt4);
AcGeVector3d vt1 = pt1 - pt2, vt2 = pt3 - pt4;
double dAngle = vt1.angleTo(vt2);
if(fabs(dAngle - PI / 4) < 1e-3 || fabs(dAngle - 3 * PI / 4) < 1e-3)
{
return TRUE;
}
return FALSE;
}
BOOL IsPipeChamfer(SSearchPipeList *pList)
{
if (pList == NULL)
{
return FALSE;
}
AcDbObjectId id = pList->m_ID;
// 查看扩展数据
ads_name sName;
acdbGetAdsName(sName, id);
Entity ent(sName);
CString str = ReadXdata(ent, _T("Chamfer"));
if (str == _T("1"))
{
return TRUE;
}
else if (str == _T("0"))
{
return FALSE;
}
// 检查该管与相邻管的关系判断是否为倒角(该管节点为A,B)必须同时满足:
// ⑴ A、B两个节点与相连的管线的角度必须是 45°的整数倍数
// ⑵ AB管线长度必须在 5 * sqrt(2) 到 500 * sqrt(2) 之间
// ⑶ A、B两节点任意一个节点连接的管线为2条或三条。
XPoint ptS, ptE;
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, id, AcDb::kForRead);
if (pPipe != NULL)
{
ptS = pPipe->StartPoint();
ptE = pPipe->EndPoint();
pPipe->close();
}
// 条件2
double dDist = ptS.Distance(ptE);
if (dDist < 5 * sqrt(2.0) || dDist > 500 * sqrt(2.0))
{
WriteXdata(ent, _T("Chamfer"), _T("0"));
return FALSE;
}
// 条件3
AcDbObjectId id1, id2;
SSearchPipeList *pPre = pList->m_pPrevious;
if (pList->m_lstNode.Length() != 1 || pList->m_lstNode[0]->m_iType != 1
|| pList->m_lstNode[0]->m_lstNode.Length() != 1
|| pList->m_lstNode[0]->m_lstNode[0]->m_iType != 0 // 靠近雨水斗节点未连接管子(只考虑管线倒角靠近雨水斗一端只连接一个管子的情况)
|| pPre == NULL || pPre->m_pPrevious == NULL
|| pPre->m_pPrevious->m_iType != 0) // 远离雨水斗节点未连接管子
{
WriteXdata(ent, _T("Chamfer"), _T("0"));
return FALSE;
}
id1 = pPre->m_pPrevious->m_ID; //靠近雨水斗节点连接的管子
id2 = pList->m_lstNode[0]->m_lstNode[0]->m_ID; // 远离雨水斗节点连接的管子
// 条件1
if (!Is45Angle(id, id1) || !Is45Angle(id, id2))
{
WriteXdata(ent, _T("Chamfer"), _T("0"));
return FALSE;
}
WriteXdata(ent, _T("Chamfer"), _T("1"));
return TRUE;
}
BOOL IsWaterBucket(SSearchPipeList *pList)
{
if(pList == NULL || pList->m_iType == 0 || pList->m_iType == 1)
{
return FALSE;
}
ads_name sname;
acdbGetAdsName(sname, pList->m_ID);
Entity ent(sname);
CString str = ReadXdata(ent, _T("WaterBucket"));
if (str == _T("1"))
{
return TRUE;
}
return FALSE;
}
void GetWaterBucket(SSearchPipeList* pList, std::vector<SSearchPipeList*> &vec, bool bCalc = false)
{
if (pList == NULL)
{
return;
}
if (bCalc) //保存所有雨水斗
{
if (IsWaterBucket(pList))
{
vec.push_back(pList);
return;
}
}
else //只保存未编号雨水斗
{
if (IsWaterBucket(pList) && pList->m_csName != _T("1"))
{
vec.push_back(pList);
return;
}
}
for (int i = 0; i < pList->m_lstNode.Length(); i++)
{
GetWaterBucket(pList->m_lstNode[i], vec, bCalc);
}
}
double GetPipeLen(AcDbObjectId &id)
{
double dLen = 0.0;
TDbPipe *pPipe = NULL;
Acad::ErrorStatus st = acdbOpenObject(pPipe, id, AcDb::kForRead);
if (pPipe != NULL)
{
dLen = pPipe->GetLength();
pPipe->close();
}
return dLen;
}
void GetWaterBucketInfo(SSearchPipeList* pList, std::map<SSearchPipeList*, double> &data)
{
if(pList != NULL)
{
std::vector<SSearchPipeList*> vec;
GetWaterBucket(pList, vec);
std::vector<SSearchPipeList*>::iterator it;
for (it = vec.begin(); it != vec.end(); it++)
{
SSearchPipeList *pTemp = *it;
double dLen = 0.0;
while(pTemp != NULL)
{
if (pTemp->m_csName == _T("1"))
{
data.insert(std::make_pair(*it, dLen));
break;
}
else if (pTemp->m_iType == 0 )
{
if (IsPipeChamfer(pTemp))
{
dLen += pTemp->m_nLength / sqrt(2.0);
}
else
{
dLen += pTemp->m_nLength;
}
}
pTemp = pTemp->m_pPrevious;
}
if (pTemp == NULL)
{
data.insert(std::make_pair(*it, dLen));
}
}
}
}
SSearchPipeList* GetNextWaterBucket(SSearchPipeList *pList)
{
std::map<SSearchPipeList*, double> data;
GetWaterBucketInfo(pList, data); // 得到pList上所有未标注的雨水斗
SSearchPipeList *pTemp = NULL;
std::map<SSearchPipeList*, double>::iterator it;
double dLen = 0.0;
for(it = data.begin(); it != data.end(); it++)
{
if (it == data.begin())
{
dLen = (*it).second;
pTemp = (*it).first;
continue;
}
if (dLen < (*it).second)
{
dLen = (*it).second;
pTemp = (*it).first;
}
}
return pTemp;
}
// 从数据库中根据管径获取雨水斗信息
void GetWaterBucketInfo(double dDia, WaterBucketInfo &info)
{
XString fullFile;
if(!FindFile(_T("datastore.dbf"), fullFile))
{
acutPrintf(_T("对不起,没有发现datastore.dbf文件!"));
return;
}
CodeBase db;
db.read_only = 1;
XDbfTable *pTable = db.Open(fullFile);
if(!pTable)
return;
CString strDia, strFlux, strDeep,strNum;
for(pTable->MoveFirst(); !pTable->IsEOF(); pTable->MoveNext())
{
GET_FIELD(pTable, _T("Typenumber"), strNum);
if (strNum.Compare(_T("45")) != 0)
{
continue;
}
GET_FIELD(pTable, _T("Typename"), strDia);
if (fabs(_tstof(strDia) - dDia) < 1e-3)
{
GET_FIELD(pTable, _T("Typevalue"), strFlux);
GET_FIELD(pTable, _T("Remark"), strDeep);
info.dDeep = _tstof(strDeep);
info.dFlux = _tstof(strFlux);
info.dPipeDia = _tstof(strDia);
break;
}
}
pTable->Close();
}
//管道流量
void GetPipeQ(SSearchPipeList *pList, double& dQ)
{
if (pList == NULL)
{
return;
}
if (IsWaterBucket(pList))
{
AcDbObjectId id = pList->m_ID;
ads_name name;
acdbGetAdsName(name, id);
Entity ent(name);
CString strDia = ReadXdata(ent, _T("PipeDia"));
WaterBucketInfo info;
GetWaterBucketInfo(_tstof(strDia), info);
dQ += info.dFlux;
return;
}
for (int i = 0; i < pList->m_lstNode.Length(); i++)
{
GetPipeQ(pList->m_lstNode[i], dQ);
}
}
//返回值表示管材类型:0表示内壁涂塑离心排水铸铁管 1表示排水塑料管 2表示钢管
int GetPipeMaterialType(const CString &strMaterial)
{
if (strMaterial.Find(_T("复合")) != -1 || strMaterial.Find(_T("衬塑")) != -1
|| strMaterial.Find(_T("涂塑")) != -1) //内壁涂塑离心排水铸铁管
{
return 0;
}
else if (strMaterial.Find(_T("PEX")) != -1 || strMaterial.Find(_T("PPR")) != -1
|| strMaterial.Find(_T("PVC-U")) != -1 || strMaterial.Find(_T("UPVC")) != -1
|| strMaterial.Find(_T("聚乙烯")) != -1) //排水塑料管
{
return 1;
}
else //钢管
{
return 2;
}
}
// 返回值表示管连接点类型(水流出点)
// 0:支管上斜三通 1:2个45度弯头 2:90度弯头 3:干管上斜三通
// 4:转变为重力流处出口(出流端管)5:干管三通 6 支管三通
int GetPipeLinkNodeType(SSearchPipeList *pList, AcDbObjectId &id)
{
int nType = -1;
if (pList != NULL && pList->m_iType == 0 && pList->m_pPrevious != NULL)
{
SSearchPipeList *pPre = pList->m_pPrevious;
if (pPre->m_iType == 1 && pPre->m_lstNode.Length() == 1)
{
if (pPre->m_pPrevious != NULL && pPre->m_pPrevious->m_iType == 0)
{
if (IsPipeChamfer(pPre->m_pPrevious)) // 管-弯头-倒角管形式
{
SSearchPipeList *pPre1 = pPre->m_pPrevious;
if (pPre1->m_pPrevious != NULL && pPre1->m_pPrevious->m_iType == 1)
{
SSearchPipeList *pPre2 = pPre1->m_pPrevious;
if (pPre2->m_lstNode.Length() == 2
&& pPre2->m_pPrevious != NULL
&& pPre2->m_pPrevious->m_iType == 0
&& !IsPipeChamfer(pPre2->m_pPrevious)) //管-弯头-倒角管-三通
{
SSearchPipeList *pPre3 = pPre1 == pPre2->m_lstNode[0] ? pPre2->m_lstNode[1] : pPre2->m_lstNode[0];
if (pPre3->m_iType == 0 && !IsPipeChamfer(pPre3)) // 支管上斜三通
{
nType = 0;
id = pPre2->m_pPrevious->m_ID;
}
}
else if (pPre2->m_lstNode.Length() == 1
&& pPre2->m_pPrevious != NULL
&& pPre2->m_pPrevious->m_iType == 0) // 管-弯头-倒角管-弯头-管形式(2个45度弯头)
{
nType = 1;
}
}
}
else // 管-弯头-管形式
{
AcDbObjectId id1, id2;
id1 = pList->m_ID;
id2 = pPre->m_pPrevious->m_ID;
ads_name name1, name2;
acdbGetAdsName(name1,id1);
acdbGetAdsName(name2, id2);
Entity ent1(name1), ent2(name2);
XPoint pt1, pt2, pt3, pt4;
GetPipePoint(ent1, pt1, pt2);
GetPipePoint(ent2, pt3, pt4);
if (!!pt1 && !!pt2 && !!pt3 && !!pt4)
{
AcGeVector3d vt1 = pt1 - pt2, vt2 = pt3 - pt4;
double dAngle = vt1.angleTo(vt2);
if (fabs(dAngle - PI / 2) < 1e-3) // 90度弯头
{
nType = 2;
id = id2;
}
}
}
}
}
else if (pPre->m_iType == 1 && pPre->m_lstNode.Length() == 2) //三通
{
SSearchPipeList *pPre2 = pPre->m_pPrevious;
SSearchPipeList *pPre3 = pList == pPre->m_lstNode[0] ? pPre->m_lstNode[1] : pPre->m_lstNode[0];
if (pPre2 != NULL && pPre3 != NULL && pPre2->m_iType == 0
&& pPre3->m_iType == 0 && IsPipeChamfer(pPre3) && !IsPipeChamfer(pPre2)) //干管上斜三通 (管-三通-管(倒角管))
{
nType = 3;
id = pPre2->m_ID;
}
else if (pPre2 != NULL && pPre3 != NULL && pPre2->m_iType == 0
&& pPre3->m_iType == 0 && !IsPipeChamfer(pPre3) && !IsPipeChamfer(pPre2)) //管-三通-管(管)
{
if (pList->m_nSpare == 1)
{
nType = 5; //干管三通(干管-三通-管(管))
id = pPre2->m_ID;
}
else
{
nType = 6; //支管三通(支管-三通-管(管))
id = pPre2->m_ID;
}
}
}
}
else if (pList != NULL && pList->m_iType == 0 && pList->m_pPrevious == NULL) // 出流段管
{
nType = 4;
}
return nType;
}
BOOL IsVerticalPipe(AcDbObjectId &id)
{
BOOL bVertical = FALSE;
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, id, AcDb::kForRead);
if (pPipe != NULL)
{
bVertical = pPipe->IsVertical();
pPipe->close();
}
return bVertical;
}
//悬吊管上距离立管最近的雨水斗
void SetNearestWaterBucket(SSearchPipeList *plist)
{
if (IsWaterBucket(plist))
{
plist = plist->m_pPrevious;
SSearchPipeList *pTemp = NULL;
std::vector<SSearchPipeList*> data; //按编号顺序依次保存悬吊管上的分支
while(plist != NULL)
{
if (plist->m_iType == 0 && IsPipeChamfer(plist))
{
plist = plist->m_pPrevious;
if (plist != NULL && plist->m_iType == 1 && plist->m_lstNode.Length() == 1
&& plist->m_pPrevious != NULL && plist->m_pPrevious->m_iType == 0 && !IsPipeChamfer(plist->m_pPrevious)) // 管-弯头-倒角管-弯头-管
{
pTemp = plist->m_pPrevious; //悬吊管起点
data.push_back(plist);
break;
}
}
else if (plist->m_iType == 0 && IsVerticalPipe(plist->m_ID)
&& plist->m_pPrevious != NULL && plist->m_pPrevious->m_iType == 1 && plist->m_pPrevious->m_lstNode.Length() ==1
&& plist->m_pPrevious->m_pPrevious != NULL && plist->m_pPrevious->m_pPrevious->m_iType == 0 && !IsPipeChamfer(plist->m_pPrevious->m_pPrevious)) //最远雨水斗没有倒角时
{
pTemp = plist->m_pPrevious->m_pPrevious;
data.push_back(pTemp);
break;
}
plist = plist->m_pPrevious;
}
AcDbObjectId id = pTemp->m_ID; //最大负压值所在管段
if (pTemp != NULL) //找出所有悬吊管上的雨水斗分支(pTemp的父指针只要是管线除立管则表示该管为悬吊管)
{
plist = pTemp;
while(plist != NULL)
{
if (plist->m_iType == 1 && plist->m_lstNode.Length() > 1)
{
for (int i = 0; i < plist->m_lstNode.Length(); i++)
{
if (pTemp != plist->m_lstNode[i])
{
data.push_back(plist->m_lstNode[i]);
}
}
}
else if (plist->m_iType == 0 && !IsVerticalPipe(plist->m_ID))
{
pTemp = plist;
id = pTemp->m_ID;
}
else if (plist->m_iType == 0 && IsVerticalPipe(plist->m_ID))
{
break;
}
plist = plist->m_pPrevious;
}
}
//设置最大负压值所在管段
ads_name name;
acdbGetAdsName(name, id);
Entity ent(name);
WriteXdata(ent, _T("MaxNP"), _T("1"));
//找出悬吊管上距离立管最近的雨水斗
std::vector<SSearchPipeList*>::reverse_iterator it;
for (it = data.rbegin(); it != data.rend(); it++)
{
std::vector<SSearchPipeList*> vec;
GetWaterBucket(*it, vec, true);
if (vec.size() == 1 && IsWaterBucket(vec[0]))
{
vec[0]->m_iSpare = 1; //表示悬吊管上距离立管最近的雨水斗
break;
}
plist = *it;
}
}
}
void GetSiphonRainWaterCalcInfo(SSearchPipeList *pList, int &nNum, std::vector<SIPHONINFO> &data)
{
if (pList == NULL)
{
return;
}
double dEle = 0.0; //雨水斗标高
double dDeep = 0.0; //斗前水深
bool bNearestWaterBucket = false; //是否是悬吊管上距离立管最近的雨水斗
if (IsWaterBucket(pList))
{
ads_name name;
acdbGetAdsName(name, pList->m_ID);
CString strDia, strDeep;
strDia = ReadXdata(name, _T("PipeDia"));
strDeep = ReadXdata(name, _T("Deep"));
TDbEquipment *pEuqip = NULL;
acdbOpenObject(pEuqip, pList->m_ID, AcDb::kForRead);
if(pEuqip != NULL)
{
dEle = pEuqip->GetLocation().z;
pEuqip->close();
}
if (!DocGetMeterUnitDraw())
{
dEle /= 1000;
}
WaterBucketInfo info;
GetWaterBucketInfo(_tstof(strDia), info);
dDeep = info.dDeep;
}
while(pList != NULL)
{
if (pList->m_csName == _T("1"))
{
break;
}
if (pList->m_iType == 0 && !IsPipeChamfer(pList) && pList->m_csName != _T("1"))
{
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, pList->m_ID, AcDb::kForRead);
if (pPipe != NULL)
{
XPoint ptS, ptE;
ptS = pPipe->StartPoint();
ptE = pPipe->EndPoint();
BOOL bVertical = pPipe->IsVertical();
double dLen = pPipe->GetLength();
double dDia = pPipe->GetDnDiameter();
Adesk::UInt16 nMaterial = pPipe->GetMaterial();
pPipe->close();
CString str;
str.Format(_T("%d"), nNum);
++nNum;
SIPHONINFO info;
info.strName = str;
info.id = pList->m_ID;
info.nType = 0;
info.dLen = dLen;
info.dPipeDia = dDia;
info.bDia = false;
info.bVertical = bVertical;
info.bLinkWaterBucket = FALSE;
//高差
double dPipeEle = ptS.z;
if (bVertical)
{
if (ptS.z < ptE.z)
{
dPipeEle = ptS.z;
}
else
{
dPipeEle = ptE.z;
}
}
if (!DocGetMeterUnitDraw())
{
dPipeEle /= 1000;
}
info.dEle = dEle - dPipeEle + dDeep;
//流量
double dQ = 0.0;
GetPipeQ(pList, dQ);
info.dQ = dQ;
//管长
SSearchPipeList *pPre = pList->m_pPrevious;
if (pPre != NULL && pPre->m_iType == 1 && pPre->m_pPrevious != NULL //连接倒角时需加上倒角长度
&& pPre->m_pPrevious->m_iType == 0)
{
if (IsPipeChamfer(pPre->m_pPrevious))
{
info.dLen += pPre->m_pPrevious->m_nLength / sqrt(2.0);
}
}
if (!DocGetMeterUnitDraw())
{
info.dLen /= 1000.0;
}
//局部阻力系数
double dT = 0.0;
if (pList->m_lstNode.Length() == 1 && IsWaterBucket(pList->m_lstNode[0])) // 管子连着雨水斗
{
info.bLinkWaterBucket = TRUE;
if (pList->m_lstNode[0]->m_iSpare == 1)
{
bNearestWaterBucket = true;
}
AcDbObjectId id = pList->m_lstNode[0]->m_ID;
ads_name name;
acdbGetAdsName(name, id);
Entity ent(name);
CString strDia = ReadXdata(ent, _T("PipeDia"));
double dDia = _tstof(strDia);
if (bNearestWaterBucket) //悬吊管上距离立管最近的雨水斗
{
dT += 3.2;
}
else
{
if (fabs(dDia - 50) < 1e-3)
{
dT += 1.3;
}
else if (fabs(dDia - 75) < 1e-3)
{
dT += 2.4;
}
else if (fabs(dDia - 100) < 1e-3)
{
dT += 5.6;
}
else
{
dT += 2.4;
}
}
}
AcDbObjectId id2; //考虑变径时另一根管子
int nPipeType = GetPipeMaterialType(GetPipeMaterialByIdx(nMaterial));
int nType = GetPipeLinkNodeType(pList, id2);
// nType 0:支管上斜三通 1:2个45度弯头 2:90度弯头 3:干管上斜三通 4 转变为重力流处出口(出流端管)5:干管三通 6 支管三通
if (nType == 1) // 2个45度弯头
{
if (nPipeType == 0 || nPipeType == 2) //内壁涂塑离心排水铸铁管 钢管
{
dT += 0.3 * 2;
}
else if (nPipeType == 1) //排水塑料管
{
dT += 0.4 * 2;
}
}
else if (nType == 0 || nType == 2 || nType == 3 || nType == 5 || nType == 6)
{
info.id2 = id2;
TDbPipe *pPipe2 = NULL;
acdbOpenObject(pPipe2, id2, AcDb::kForRead);
if (pPipe2 != NULL)
{
double dPipeDia = pPipe2->GetDnDiameter();
pPipe2->close();
if (fabs(dDia - dPipeDia) > 1e-3) //变径
{
dT += 0.4;
info.bDia = true; //进行了变径处理
}
}
if (nPipeType == 0 || nPipeType == 2) //内壁涂塑离心排水铸铁管 钢管
{
if (nType == 0) //支管上斜三通 + 45度弯头
{
dT += 1.0 + 0.3;
pList->m_pPrevious->m_nSpare = 1; //标记斜三通,用于计算后续计算
}
else if (nType == 2) //90度弯头
{
dT += 0.8;
}
else if (nType == 3 || nType == 5) //干管上斜三通 干管三通
{
dT += 0.5;
pList->m_pPrevious->m_nSpare = 1; //标记斜三通 干管三通,用于计算后续计算
}
else if (nType == 6) //支管三通
{
dT += 1.0;
pList->m_pPrevious->m_nSpare = 1; //标记支管三通,用于计算后续计算
}
}
else if (nPipeType == 1) //排水塑料管
{
if (nType == 0) //支管上斜三通 + 45度弯头
{
dT += 1.2 + 0.4;
pList->m_pPrevious->m_nSpare = 1; //标记斜三通,用于计算后续计算
}
else if (nType == 2) //90度弯头
{
dT += 1.0;
}
else if (nType == 3 || nType == 5)//干管上斜三通 干管三通
{
dT += 0.35;
pList->m_pPrevious->m_nSpare = 1; //标记斜三通 干管三通,用于计算后续计算
}
else if (nType == 6) //支管三通
{
dT += 1.2;
pList->m_pPrevious->m_nSpare = 1; //标记支管三通,用于计算后续计算
}
}
}
else if (nType == 4) //转变为重力流处出口(出流端管)
{
dT += 1.8;
}
info.dT = dT;
data.push_back(info);
}
pList->m_csName = _T("1");
}
else if(IsWaterBucket(pList) && pList->m_csName != _T("1"))
{
CString str;
str.Format(_T("%d"), nNum);
++nNum;
SIPHONINFO info;
info.strName = str;
info.nType = 1;
info.id = pList->m_ID;
ads_name name;
acdbGetAdsName(name, pList->m_ID);
str = ReadXdata(name, _T("PipeDia"));
WaterBucketInfo waterBucket;
GetWaterBucketInfo(_tstof(str), waterBucket);
info.dPipeDia = waterBucket.dPipeDia;
info.dQ = waterBucket.dFlux;
info.dDeep = waterBucket.dDeep;
data.push_back(info);
pList->m_csName = _T("1");
}
pList = pList->m_pPrevious;
}
}
void UpDataPipeLen(SSearchPipeList *pListAll)
{
if (pListAll != NULL)
{
pListAll->m_iSpare = 0;
if (pListAll->m_iType == 0)
{
pListAll->m_nLength = GetPipeLen(pListAll->m_ID);
}
for(int i = 0; i < pListAll->m_lstNode.Length(); i++)
{
SSearchPipeList *pList = pListAll->m_lstNode[i];
UpDataPipeLen(pList);
}
}
}
// 设置主干管
void SetMianPipe(SSearchPipeList *pList)
{
while(pList != NULL)
{
if (pList->m_iType == 0 && !IsPipeChamfer(pList))
{
pList->m_nSpare = 1;
}
pList = pList->m_pPrevious;
}
}
// 编号规则:1 首先找出管道系统中最长的带有雨水斗的支路(主干线)
// 2 对主干线上的雨水斗 管道次编号(管道倒角除外)
// 3 从主干线雨水斗开始依次检查各节点,如果存在其他支路,返回1开始处理;
// 如果不存在其他支路,继续搜索下个节点
// bFirst = true 表示为最远雨水斗所在主干线
void DoSiphonRainWater(SSearchPipeList *pListAll, int &nNum, std::vector<SIPHONINFO> &data, bool bFirst = false)
{
SSearchPipeList *pList = GetNextWaterBucket(pListAll); // 得到主干线
if (pList != NULL)
{
if (bFirst)
{
SetNearestWaterBucket(pList); //设置悬吊管上距离立管最近的雨水斗
SetMianPipe(pList); //设置干管
}
GetSiphonRainWaterCalcInfo(pList, nNum, data);
}
while (pList != NULL) // 处理主干线上的分支
{
if (pList->m_iType == 1 && pList->m_lstNode.Length() > 1) // 存在其他未处理分支
{
DoSiphonRainWater(pList, nNum, data);
}
pList = pList->m_pPrevious;
}
}
BOOL IsWaterBucket(Entity &ent)
{
CString str = ReadXdata(ent, _T("WaterBucket"));
if (str == _T("1"))
{
return TRUE;
}
return FALSE;
}
// 对管道和雨水斗添加标注信息
AcDbObjectId DoDimPipeWaterBucket(AcDbObjectId &id, CString &strText)
{
ads_name name;
acdbGetAdsName(name, id);
Entity ent(name);
CString str = ReadXdata(ent, _T("WaterBucket"));
XPoint pt;
double dAngle = 0;
if (str == _T("1")) //雨水斗
{
double dScale = 1;
OPENOBJ_BEGIN(ent, AcDb::kForRead, TDbEquipment, pEquip);
if (pEquip != NULL)
{
pt = pEquip->GetLocation();
dScale = pEquip->GetScale();
}
OPENOBJ_END();
pt = Wcs2Ucs(pt);
pt = pt + 1 * dScale * (AcGeVector3d::kXAxis + AcGeVector3d::kYAxis);
pt = Ucs2Wcs(pt);
}
else //管子
{
TDbPipe *pPipe = NULL;
XPoint pt1, pt2;
acdbOpenObject(pPipe, id, AcDb::kForRead);
if (pPipe != NULL)
{
pt = pPipe->MidPoint();
pt1 = pPipe->StartPoint();
pt2 = pPipe->EndPoint();
pPipe->close();
}
pt1 = Wcs2Ucs(pt1);
pt2 = Wcs2Ucs(pt2);
pt1.z = 0;
pt2.z = 0;
AcGeVector3d vt = pt1 - pt2;
if((pt2.x > pt1.x) || (fabs(pt1.x - pt2.x) < 1e-3 && pt1.y < pt2.y))
{
vt *= -1;
}
dAngle = vt.angleTo(AcGeVector3d::kXAxis);
if (dAngle > PI / 2 && dAngle < PI)
{
dAngle -= PI / 2;
}
else if (fabs(PI -dAngle) < 1e-3)
{
dAngle = 0;
}
if ((pt1.y > pt2.y && pt2.x > pt1.x) || (pt1.y < pt2.y && pt2.x < pt1.x))
{
dAngle = 2 * PI - dAngle;
}
if (fabs(dAngle - PI * 3 / 2) < 1e-3)
{
dAngle = PI / 2;
}
}
AcDbMText *pText = new AcDbMText;
AcDbObjectId idTextStyle=InitTwtTextStyle(_T("STANDARD"));
pText->setTextStyle(idTextStyle);
pText->setContents(strText);
pText->setLineSpacingFactor(0.6);
pText->setTextHeight(1.0 * DocGetPScale());
pText->setLocation(pt);
pText->setColorIndex(7);
AcGePoint3dArray ptArr;
pText->setRotation(dAngle);
pText->getBoundingPoints(ptArr);
if (ptArr.length() == 4) // 使用外包框是因为版本变动导致有些函数无法使用
{
XPoint pt1 = ptArr[0], pt2 = ptArr[2];
AcGeVector3d vt = AcGeVector3d::kXAxis;
vt.rotateBy(Ucs2Wcs(0.0), AcGeVector3d::kZAxis);
vt.rotateBy(dAngle + PI / 2,AcGeVector3d::kZAxis);
pt += vt * (pt1.Distance(pt2));
pText->setLocation(pt);
}
return AddToCurrentSpace(pText, Adesk::kTrue);
}
void Plan2SysWaterBucket(AcDbObjectId id, TDbPipe *pPipe, double nRadian, AcGeMatrix3d mat, AcGeScale3d scale)
{
if(!pPipe || !id)
{
return;
}
XPoint ptStart, ptEnd, ptNewS, ptNewE;
double dX = scale.sx;
double dY = scale.sy;
double dZ = scale.sz;
TDbEquipment *pNewEquip = NULL;
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbEquipment, pEquip);
if(pEquip != NULL)
{
ptStart = pEquip->GetLocation();
pNewEquip = (TDbEquipment *)pEquip->clone();
}
OPENOBJ_END();
ptStart.TransformBy(mat);
ptStart = Wcs2Ucs(ptStart); //系统生成支持UCS
// 加载雨水斗系统图图块
CString strDwb = g_csDwbPath + _T("TwtSys");
XString xsTmp1;
if(LoadDwbBlock(strDwb, _T("00000526"), xsTmp1) == RTNORM) //系统图雨水斗
{
pNewEquip->SetBlock2d(GetBlkIdByName(_T("$TwtSys$00000526")));
}
ptNewS.x = ptStart.x*dX + cos(nRadian)*ptStart.y*dY;
ptNewS.y = ptStart.z*dZ + sin(nRadian)*ptStart.y*dY;
ptNewS = Ucs2Wcs(ptNewS); //系统生成支持UCS
ptNewE = ptNewS;
pNewEquip->SetLocation(ptNewS);
pNewEquip->SetInsert(ptNewE);
pNewEquip->SetAngle(Ucs2Wcs(0.0));
AddToCurrentSpace(pNewEquip, Adesk::kTrue);
}
//系统图生成
BOOL Plan2SysSiphonRainwater(const PickSet &ss, std::map<AcDbObjectId, AcDbObjectId> &mapPipe)
{
PickSet ssNew(SS_FREE);
ssNew.IncludeBegin();
XPoint ptPick, ptPick2, ptStart, ptEnd, ptNewS, ptNewE;
double dRadian = 45.0/180.0*PI;
long len = ss.Length();
DList<AcDbObjectId> lstNode;
for(long i = 0; i < len; i++)
{
Entity entSel = ss[i];
if(IsWaterBucket(entSel))
{
continue;
}
CString csSerial;
GetPipePoint(entSel, ptStart, ptEnd);
if(ptStart == ptEnd)
continue;
ptStart = Wcs2Ucs(ptStart);
ptEnd = Wcs2Ucs(ptEnd);
ptNewS.x = ptStart.x + cos(dRadian)*ptStart.y;
ptNewS.y = ptStart.z + sin(dRadian)*ptStart.y;
ptNewE.x = ptEnd.x + cos(dRadian)*ptEnd.y;
ptNewE.y = ptEnd.z + sin(dRadian)*ptEnd.y;
ptNewE = Ucs2Wcs(ptNewE);
ptNewS = Ucs2Wcs(ptNewS);
AcDbObjectId idPipe;
acdbGetObjectId(idPipe, entSel);
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, idPipe, AcDb::kForRead);
if(!pPipe || pPipe->GetModelType() == TPipeSys::kSystem) //系统管线不理会
{
if (pPipe !=NULL)
{
pPipe->close();
}
continue;
}
TDbPipe *pNewPipe = ClonePipe(pPipe);
if(pPipe->IsVertical())
{
csSerial = ReadXdata(entSel, _T("PIPE-SERIAL"));
pNewPipe->SetHideLevel(100);
}
else
{
pNewPipe->SetHideLevel(int(ptStart.z/1000*10)); //设置遮挡关系,把平面图标高转为米×10
}
pNewPipe->SetStartPoint(ptNewS);
pNewPipe->SetEndPoint(ptNewE);
pNewPipe->SetModelType(TPipeSys::kSystem);
AddToCurrentSpace(pNewPipe, Adesk::kTrue);
Entity entLast;
entLast.GetLast();
// cet 2011.7.6 del 记录倒角
//CString strChamfer = ReadXdata(entSel, _T("Chamfer"));
//if (strChamfer != _T("1"))
{
AcDbObjectId id1, id2;
acdbGetObjectId(id1, entSel);
acdbGetObjectId(id2, entLast);
mapPipe.insert(std::make_pair(id1, id2));
}
XString xsTmp(_T("%.3f"), ptStart.z/1000);
WriteXdata(entLast, _T("TG-ELEVATION"), (const TCHAR*)xsTmp);
if(csSerial != _T(""))
WriteXdata(entLast, _T("PIPE-SERIAL"), (const TCHAR*)csSerial);
//阀门阀件
DList<AcDbObjectId> lstAttachment;
pPipe->GetAttachments(lstAttachment);
int leng = lstAttachment.Length();
AcGeMatrix3d mat;
for(int m=0; m< leng; m++)
{
AcDbObjectId idTmp = *lstAttachment[m];
if(IsValve(idTmp))
PlanValve2Sys(idTmp, pPipe, dRadian, mat, AcGeScale3d(1, 1, 1));
else if(IsPipeLabel(idTmp))
PlanLabel2Sys(idTmp, pNewPipe);
}
//设备
AcDbObjectId nodeId1(NULL), nodeId2(NULL);
nodeId1 = pPipe->GetNode(0);
nodeId2 = pPipe->GetNode(1);
ads_name name1, name2;
acdbGetAdsName(name1, nodeId1);
Entity ent1(name1), ent2(name2);
if(IsAppandEquip(lstNode, nodeId1) && !IsWaterBucket(ent1))
{
PlanEquip2Sys(nodeId1, pPipe, dRadian, mat, AcGeScale3d(1, 1, 1));
}
if(IsAppandEquip(lstNode, nodeId2) && !IsWaterBucket(ent2))
{
PlanEquip2Sys(nodeId2, pPipe, dRadian, mat, AcGeScale3d(1, 1, 1));
}
if (IsWaterBucket(ent1) || IsWaterBucket(ent2))
{
Plan2SysWaterBucket(nodeId1, pPipe, dRadian, mat, AcGeScale3d(1, 1, 1));
Entity ent;
ent.GetLast();
AcDbObjectId id;
acdbGetObjectId(id, ent);
mapPipe.insert(std::make_pair(nodeId1, id));
}
if (IsWaterBucket(ent2))
{
Plan2SysWaterBucket(nodeId2, pPipe, dRadian, mat, AcGeScale3d(1, 1, 1));
}
pPipe->close();
}
ssNew.IncludeEnd();
int nOsMode=0;
xg_getvar(_T("OSMODE"), &nOsMode);
nOsMode &= ~0x4000;
nOsMode |= OS_INT|OS_END|OS_NEA|OS_MID;
XPushVar<int> vOsMode(_T("OSMODE"), nOsMode);
double x,y,z;
XPoint ptIns;
ssNew.Redraw(2);
ssNew.GetExtend(ptIns, &x, &y, &z);
actrTransactionManager->flushGraphics(); //acad 刷新
ptIns = Wcs2Ucs(ptIns);
ptIns.z = 0; //标高置为0
XPoint xp;
int nRet = DragMovePickSet(ssNew, _T("\n请点取系统图位置<退出>: "), ptIns, xp);
if(nRet != RTNORM)
{
ssNew.Erase();
return FALSE;
}
ssNew.Redraw(1);
return TRUE;
}
//获得标注信息
CString GetDimInfo(std::vector<SIPHONINFO> &data, const AcDbObjectId &id)
{
CString strText;
std::vector<SIPHONINFO>::iterator it;
for (it = data.begin(); it != data.end(); it++)
{
if ((*it).id == id)
{
CString strName, strLen, strQ, strDia;
strName = _T("NO.") + (*it).strName;
if ((*it).nType == 0) //管
{
strLen.Format(_T("%.2fm"), (*it).dLen);
}
else // 雨水斗
{
strLen.Format(_T("%f"), (*it).dDeep);
strLen.TrimRight(_T("0"));
strLen += _T("m");
}
strQ.Format(_T("%.1fL/s"), (*it).dQ);
strDia.Format(_T("%.0fmm"), (*it).dPipeDia);
strText = strName + _T("\\P") + strDia + _T("\\P") + strQ + _T("\\P") + strLen;
break;
}
}
return strText;
}
//获得三通(支管斜三通、干管斜三通、干管三通、支管三通)中的两根管道(计算各节点压力差时使用)
void Get2PipeId(SSearchPipeList *pList, std::map<AcDbObjectId, AcDbObjectId> &data)
{
if (pList != NULL)
{
if (pList->m_iType == 1 && pList->m_nSpare == 1 && pList->m_lstNode.Length() == 2)
{
AcDbObjectId id1, id2;
if (IsPipeChamfer(pList->m_lstNode[0]))
{
id1 = pList->m_lstNode[1]->m_ID; //斜三通干管
id2 = pList->m_lstNode[0]->m_lstNode[0]->m_lstNode[0]->m_ID; //斜三通支管
}
else if (IsPipeChamfer(pList->m_lstNode[1]))
{
id1 = pList->m_lstNode[0]->m_ID; //斜三通干管
id2 = pList->m_lstNode[1]->m_lstNode[0]->m_lstNode[0]->m_ID; //斜三通支管
}
else if (pList->m_lstNode[0]->m_nSpare == 1)
{
id1 = pList->m_lstNode[0]->m_ID; //三通干管
id2 = pList->m_lstNode[1]->m_ID; //三通支管
}
else if (pList->m_lstNode[1]->m_nSpare == 1)
{
id1 = pList->m_lstNode[1]->m_ID; //三通干管
id2 = pList->m_lstNode[0]->m_ID; //三通支管
}
if (id1.isValid() && id2.isValid())
{
data.insert(std::make_pair(id1, id2));
}
}
for (int i = 0; i < pList->m_lstNode.Length(); i++)
{
Get2PipeId(pList->m_lstNode[i], data);
}
}
}
// 获得端点在pt点的管子
BOOL GetPipe(XPoint &pt, PickSet &ss)
{
const double dDist = 100;
AcGePoint3d ptGeLB ,ptGeLT, ptGeRB, ptGeRT;
AcGeVector3d vtX = AcGeVector3d::kXAxis;
AcGeVector3d vtY = AcGeVector3d::kYAxis;
ptGeLB = pt - vtX * dDist / 2;
ptGeLB = ptGeLB - vtY * dDist / 2;
ptGeLT = ptGeLB + vtY * dDist;
ptGeRB = ptGeLB + vtX * dDist;
ptGeRT = ptGeRB + vtY * dDist;
PickSet ssSel(SS_FREE);
RBList rbFilter = acutBuildList( -4, _T("<or"),
-4, _T("<and"), RTDXF0, _T("ATS_PIPE"), 8, LAY_PIPE_RAIN, -4, _T("and>"),
-4, _T("<and"), RTDXF0, _T("ATS_PIPE"), 8, LAY_VPIPE_RAIN, -4, _T("and>"),
-4, _T("or>"), NULL);
TADSGePoint3d _pt1 = Wcs2Ucs(ptGeLB)
, _pt2 = Wcs2Ucs(ptGeLT)
, _pt3 = Wcs2Ucs(ptGeRT)
, _pt4 = Wcs2Ucs(ptGeRB);
RBList rbPt = acutBuildList(RTPOINT,&_pt1,RTPOINT,&_pt2,RTPOINT,&_pt3, RTPOINT,&_pt4,NULL);
acedSSGet(_T("CP"),rbPt,NULL,rbFilter,ssSel);
PickSet ss2(SS_FREE);
for (long i = 0; i < ssSel.Length(); i++)
{
OPENOBJ_BEGIN(ssSel[i], AcDb::kForRead, TDbPipe, pPipe);
if (pPipe != NULL)
{
XPoint pt1, pt2;
pt1 = pPipe->StartPoint();
pt2 = pPipe->EndPoint();
if (pt1.Distance2d(pt) < 1e-3 || pt2.Distance2d(pt) < 1e-3)
{
ss2 += ssSel[i];
}
}
OPENOBJ_END();
}
ss += ss2;
if (ss.Length() < 3) //至少存在两根非立管才能修改立管标高
{
return FALSE;
}
return TRUE;
}
//出流端是否连接着立管
BOOL CheckSys(SSearchPipeList *plist)
{
if (plist != NULL)
{
SSearchPipeList *pTemp = NULL;
if (plist->m_lstNode.Length() == 2)
{
SSearchPipeList *p1 = plist->m_lstNode[0];
SSearchPipeList *p2 = plist->m_lstNode[1];
if(p1->m_lstNode.Length() >= 1)
{
pTemp = p1;
}
else if (p2->m_lstNode.Length() >= 1)
{
pTemp = p2;
}
if (pTemp != NULL && pTemp->m_iType == 1 && pTemp->m_lstNode.Length() == 1
&& pTemp->m_lstNode[0]->m_iType == 0&&IsVerticalPipe(pTemp->m_lstNode[0]->m_ID)) // 立管-弯头-出流管
{
return TRUE;
}
else if (pTemp != NULL && pTemp->m_iType == 1 && pTemp->m_lstNode.Length() == 1
&& pTemp->m_lstNode[0]->m_iType == 0 && !IsVerticalPipe(pTemp->m_lstNode[0]->m_ID))// 管-弯头-出流管
{
return FALSE;
}
}
}
return FALSE;
}
//管道两端是否存在唯一的一根立管
BOOL ExistOnlyVPipe(AcDbObjectId &id)
{
XPoint ptS, ptE;
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, id, AcDb::kForRead);
if (pPipe != NULL)
{
ptS = pPipe->StartPoint();
ptE = pPipe->EndPoint();
pPipe->close();
}
PickSet ss1(SS_FREE), ss2(SS_FREE), ss(SS_FREE);
BOOL bVal1 = GetPipe(ptS, ss1);
BOOL bVal2 = GetPipe(ptE, ss2);
XPoint pt;
if (bVal1)
{
ss += ss1;
pt = ptS;
}
else if (bVal2)
{
ss += ss2;
pt = ptE;
}
if (ss.Length() != 0)
{
PickSet ssDel(SS_FREE);
for(long i = 0; i < ss.Length(); i++)
{
OPENOBJ_BEGIN(ss[i], AcDb::kForRead, TDbPipe, pPipe);
if (pPipe != NULL)
{
if (pPipe->IsVertical())
{
ssDel += ss[i];
}
}
OPENOBJ_END();
}
ss -= ssDel;
if (ssDel.Length() < 1 || ss.Length() < 2)
{
return FALSE;
}
TCHAR sz[256];
if(ads_getstring(NULL, _T("\n是否连接立管(Y/N)<退出>:"), sz) != RTNORM)
{
return FALSE;
}
if (_tcscmp(sz, _T("Y")) != 0 && _tcscmp(sz, _T("y")) != 0)
{
return FALSE;
}
std::set<double> setEle;
for(i = 0; i < ss.Length(); i++)
{
OPENOBJ_BEGIN(ss[i], AcDb::kForRead, TDbPipe, pPipe);
if (pPipe != NULL)
{
XPoint pt1, pt2;
pt1 = pPipe->StartPoint();
pt2 = pPipe->EndPoint();
if (pt1.Distance2d(pt) < 1e-3)
{
setEle.insert(pt1.z);
}
else if (pt2.Distance2d(pt) < 1e-3)
{
setEle.insert(pt2.z);
}
}
OPENOBJ_END();
}
double dMinEle = 0, dMaxEle = 0;
dMinEle = *std::min_element(setEle.begin(), setEle.end());
dMaxEle = *std::max_element(setEle.begin(), setEle.end());
if (dMaxEle > dMinEle)
{
AcDbObjectId idVPipe;
Entity ent = ssDel[0L];
ssDel -= ent;
ssDel.Erase();
acdbGetObjectId(idVPipe, ent);
TDbPipe *pPipe = NULL;
Acad::ErrorStatus st = acdbOpenObject(pPipe, idVPipe, AcDb::kForWrite);
if (pPipe != NULL)
{
pPipe->StartPoint().z = dMaxEle;
pPipe->EndPoint().z = dMinEle;
pPipe->close();
}
return TRUE;
}
}
return FALSE;
}
//系统中所有管道管径
void GetALLPipeDia(SSearchPipeList *plist, std::set<double> &data)
{
if (plist != NULL)
{
if (plist->m_iType == 0)
{
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, plist->m_ID, AcDb::kForRead);
if(pPipe != NULL)
{
data.insert(pPipe->GetDnDiameter());
pPipe->close();
}
}
for (int i = 0; i < plist->m_lstNode.Length(); i++)
{
GetALLPipeDia(plist->m_lstNode[i], data);
}
}
}
// 复制管道系统 pList必须为系统的一个根节点
void CopySSearchPipeList(SSearchPipeList *pList, SSearchPipeList *&pRes, SSearchPipeList *pPre)
{
if (pList != NULL && pRes != NULL)
{
pRes->m_iType = pList->m_iType;
pRes->m_nLength = pList->m_nLength;
pRes->m_ID = pList->m_ID;
pRes->m_pPrevious = pPre;
for(int i = 0; i < pList->m_lstNode.Length(); i++)
{
SSearchPipeList *pTemp = new SSearchPipeList;
CopySSearchPipeList(pList->m_lstNode[i], pTemp, pRes);
pRes->m_lstNode.Append(pTemp);
}
}
}
//是否需要预计算
BOOL NeedBeforeCalc(SSearchPipeList *pList)
{
BOOL bVal = FALSE;
std::set<double> data; //虹吸雨水系统中所有管段管径
GetALLPipeDia(pList, data);
if (data.size() < 3)
{
bVal = TRUE;
}
return bVal;
}
void BeforehandCalc(SSearchPipeList *pListAll);
// cet 2011.7.5 add 获得倒角对应的管段(倒角管径随该管段变化)
void GetChamferPipe(SSearchPipeList *pList, const std::vector<AcDbObjectId> &vecPipe, std::map<AcDbObjectId, AcDbObjectId> &mapData)
{
if (pList != NULL)
{
if (pList->m_iType == 0 && pList->m_pPrevious != NULL
&& pList->m_pPrevious->m_pPrevious != NULL && pList->m_pPrevious->m_pPrevious->m_iType == 0)
{
AcDbObjectId idPipe = pList->m_pPrevious->m_pPrevious->m_ID;
std::vector<AcDbObjectId>::const_iterator it;
it = std::find(vecPipe.begin(), vecPipe.end(), idPipe);
if (it != vecPipe.end())
{
mapData.insert(std::make_pair(pList->m_ID, idPipe));
}
}
for(int i = 0; i < pList->m_lstNode.Length(); i++)
{
GetChamferPipe(pList->m_lstNode[i], vecPipe, mapData);
}
}
}
// cet 2011.7.5 add 更新倒角管管径
void UpdateChamferPipe(const std::map<AcDbObjectId, AcDbObjectId> &mapData)
{
TDbPipe *pPipe = NULL;
std::map<AcDbObjectId, AcDbObjectId>::const_iterator it;
for (it = mapData.begin(); it != mapData.end(); it++)
{
acdbOpenObject(pPipe, (*it).first, AcDb::kForRead);
if (pPipe == NULL)
{
continue;
}
double dPipeDn = pPipe->GetDnDiameter();
pPipe->close();
acdbOpenObject(pPipe, (*it).second, AcDb::kForWrite);
if (pPipe != NULL)
{
pPipe->SetDnDiameter(dPipeDn);
pPipe->close();
}
pPipe = NULL;
}
}
void GetChamferPipe(SSearchPipeList *pListAll, std::vector<AcDbObjectId> &vecPipe);
//重新确定水流方向 cet 2011.9.1 add
void ResetPipeDir(SSearchPipeList *pListAll)
{
long len = pListAll->m_lstNode.Length();
if(pListAll->m_iType == 0){
XPoint ptFront;
if(pListAll->m_pPrevious != NULL){
OPENOBJ_BEGIN(pListAll->m_pPrevious->m_ID, AcDb::kForRead, TDbPipeNode, pNode);
if(pNode){
ptFront = pNode->GetLocation();
// cet 2012.7.26 add 考虑化粪池
TDbPool *pPool = TDbPool::cast(pNode);
if (pPool != NULL)
{
int nNum = pPool->GetInterfaceNum();
for (int i = 0; i < nNum; i++)
{
const TPipeInterface &face = pPool->GetInterface(i);
if (face.m_idPipe == pListAll->m_ID)
{
ptFront = face.m_ptLocation;
break;
}
}
}
}
OPENOBJ_END();
}
OPENOBJ_BEGIN(pListAll->m_ID, AcDb::kForWrite, TDbPipe, pPipe);
if(pPipe && !!ptFront){
XPoint p1 = ptFront;
p1.z = 0;
XPoint p2 = pPipe->StartPoint();
p2.z = 0;
if (pPipe->IsVertical()) // 考虑立管 cet 2011.9.15 add
{
if (pPipe->StartPoint().z > pPipe->EndPoint().z)
{
pPipe->SetFlowDir(TPipeSys::kFromStart);
}
else
{
pPipe->SetFlowDir(TPipeSys::kFromEnd);
}
}
else if(p1 == p2)
pPipe->SetFlowDir(TPipeSys::kFromEnd);
else
pPipe->SetFlowDir(TPipeSys::kFromStart);
}
OPENOBJ_END();
}
for(long i=0;i<len;i++){
SSearchPipeList *pList = pListAll->m_lstNode[i];
ResetPipeDir(pList);
}
}
// 主函数
void SiphonRainWaterCalc()
{
RBList rbMaskPipe(RTDXF0, _T("ATS_PIPE"), 8, LAY_PIPE_RAIN, NULL);
Entity entMainPipe;
if (SelectEntity(_T("\n请选择该段管道的出流端<退出>:"), entMainPipe, rbMaskPipe) != RTNORM)
{
return;
}
SSearchPipeList *pListAll = new SSearchPipeList();
PickSet ssAll(SS_FREE);
ssAll += entMainPipe;
if(!SearchSprinkPipeSys(entMainPipe, NULL, pListAll, ssAll))
{
AfxMessageBox(_T("系统有回路!"));
delete pListAll;
return;
}
if(pListAll->m_lstNode.Length() == 2)
{
SSearchPipeList *p1 = pListAll->m_lstNode[0];
SSearchPipeList *p2 = pListAll->m_lstNode[1];
if(p1->m_lstNode.Length() >= 1 && p2->m_lstNode.Length() >= 1)
{
adsout << _T("\n请选择末端排水管道!");
return;
}
else if (p1->m_lstNode.Length() == 0 && p2->m_lstNode.Length() == 0) //系统只有一根管段
{
//管段两端是否有且只有一根立管并且修改了立管标高
if (ExistOnlyVPipe(pListAll->m_ID))
{
acutPrintf(_T("\n请重新选择虹吸雨水系统!"));
return;
}
}
}
std::vector<SSearchPipeList*> vecBucket;
GetWaterBucket(pListAll, vecBucket, true);
if (vecBucket.empty())
{
acutPrintf(_T("\n请选择虹吸雨水系统!"));
return;
}
//出流端是否连接着立管
if(!CheckSys(pListAll))
{
acutPrintf(_T("\n虹吸雨水系统缺少立管!"));
return;
}
// cet 2011.9.1 add 改变管道流向
ResetPipeDir(pListAll);
WriteXdata(entMainPipe, _T("OutPipe"), _T("1")); //标记出流端管段
//预计算管径
if (NeedBeforeCalc(pListAll))
{
SSearchPipeList *pTemp = new SSearchPipeList;
CopySSearchPipeList(pListAll, pTemp, NULL); //预计算时可能对链表结构进行修改
BeforehandCalc(pTemp);
delete pTemp;
}
// cet 2011.7.5 add 更新倒角管径
//获得所有倒角管段
std::vector<AcDbObjectId> vecPipe;
GetChamferPipe(pListAll, vecPipe);
std::map<AcDbObjectId, AcDbObjectId> mapChamferPipe;
GetChamferPipe(pListAll, vecPipe, mapChamferPipe);
UpdateChamferPipe(mapChamferPipe);
UpDataPipeLen(pListAll);
std::vector<SIPHONINFO> data;
int nNum = 1;
DoSiphonRainWater(pListAll, nNum, data, true); //得到雨水斗,管段信息
std::map<AcDbObjectId, AcDbObjectId> map2PipeId; //保存斜三通上干管和支管
Get2PipeId(pListAll, map2PipeId);
delete pListAll;
BOOL bExistPlan2Sys = FALSE;
std::map<AcDbObjectId, AcDbObjectId> mapPipe, mapDim; //mapPipe保存原管 系统图中相应的管 mapDim保存原管 系统图中相应的管对应的标注
if (Plan2SysSiphonRainwater(ssAll, mapPipe))
{
bExistPlan2Sys = TRUE;
std::map<AcDbObjectId, AcDbObjectId>::iterator it;
for (it = mapPipe.begin(); it != mapPipe.end(); it++) // 标注管管段
{
CString strText = GetDimInfo(data, (*it).first);
if(strText != _T(""))
{
AcDbObjectId id = DoDimPipeWaterBucket((*it).second, strText);
mapDim.insert(std::make_pair((*it).first, id));
}
}
TPipePerDocData *pData = GetCurPipeDocData();
pData->ApplyUpdates();
}
//管材信息
CString strMaterial;
OPENOBJ_BEGIN(entMainPipe, AcDb::kForRead, TDbPipe, pPipe);
if (pPipe != NULL)
{
strMaterial = GetPipeMaterialByIdx(pPipe->GetMaterial());
}
OPENOBJ_END();
CTemporaryResourceOverride vTemp;
CSiphonRainwaterCalcDlg dlg;
dlg.SetSiphonInfo(data);
dlg.SetMapInfo(mapPipe, mapDim, map2PipeId);
dlg.SetPlan2Sys(bExistPlan2Sys);
dlg.SetPipeMaterial(strMaterial);
dlg.SetChamferPipe(mapChamferPipe); // cet 2011.7.6 add
dlg.DoModal();
}
//***************************************************************************************************
// 预计算
//***************************************************************************************************
// 将虹吸雨水系统最远雨水斗所在主干线上的支路中雨水斗数大于分支拆分出来,以便进行
void BreakBucketSys(SSearchPipeList *pListAll, std::vector<SSearchPipeList*> &data)
{
SSearchPipeList *pList = GetNextWaterBucket(pListAll); // 得到主干线
BOOL bVal = FALSE; // 是否已找到支路雨水斗数大于1的支路
SSearchPipeList *pTemp = NULL;
while (pList != NULL)
{
if (pList->m_iType == 1 && pList->m_lstNode.Length() == 2) //三通
{
std::vector<SSearchPipeList*> vecBucket;
SSearchPipeList *pOther = pTemp == pList->m_lstNode[0] ? pList->m_lstNode[1] : pList->m_lstNode[0];
GetWaterBucket(pOther, vecBucket, true);
int nNum = vecBucket.size();
if (nNum > 1|| (nNum == 1 && bVal)) // 如果已搜索到雨水斗数大于1的分支,则剩余分支全部拆分下来
{
pOther->m_pPrevious = NULL;
pList->m_nSpare = 1; //节点已经被拆分
data.push_back(pOther);
bVal = TRUE;
}
}
pTemp = pList;
pList = pList->m_pPrevious;
}
data.push_back(pListAll);
}
// 获得系统中的倒角
void GetChamferPipe(SSearchPipeList *pListAll, std::vector<AcDbObjectId> &vecPipe)
{
if (pListAll != NULL)
{
if (pListAll->m_iType == 0 && IsPipeChamfer(pListAll))
{
vecPipe.push_back(pListAll->m_ID);
}
for (int i = 0; i < pListAll->m_lstNode.Length(); i++)
{
GetChamferPipe(pListAll->m_lstNode[i], vecPipe);
}
}
}
//雨水斗是否连接着立管
BOOL ExistVPipe(SSearchPipeList *pList)
{
BOOL bVal = FALSE;
if (pList != NULL && IsWaterBucket(pList))
{
if (pList->m_pPrevious != NULL && pList->m_pPrevious->m_iType == 0)
{
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, pList->m_pPrevious->m_ID, AcDb::kForRead);
if (pPipe != NULL)
{
if (pPipe->IsVertical())
{
bVal = TRUE;
}
pPipe->close();
}
}
}
return bVal;
}
//雨水斗附近是否存在连接管
BOOL ExistPipe(SSearchPipeList *pList)
{
BOOL bVal = TRUE;
if (pList != NULL && IsWaterBucket(pList))
{
AcDbObjectId idBucket = pList->m_ID;
if (ExistVPipe(pList)) // 雨水斗连接着立管
{
pList = pList->m_pPrevious->m_pPrevious;
SSearchPipeList *pTemp = pList;
BOOL bChamfer = FALSE; // 是否存在倒角
while(pList != NULL)
{
if(pList->m_iType == 0 && IsPipeChamfer(pList))
{
bChamfer = TRUE;
pList = pList->m_pPrevious;
break;
}
pList = pList->m_pPrevious;
}
if (!bChamfer)
{
pList = pTemp;
}
AcDbObjectId id;
while(pList != NULL)
{
if(pList->m_iType == 0 && !IsPipeChamfer(pList))
{
id = pList->m_ID;
break;
}
pList = pList->m_pPrevious;
}
if (!!id)
{
//检查雨水斗是否在主干管垂直上端
XPoint ptLoc;
TDbEquipment *pEquip = NULL;
acdbOpenObject(pEquip, idBucket, AcDb::kForRead);
if (pEquip != NULL)
{
ptLoc = pEquip->GetLocation();
pEquip->close();
}
XPoint pt1, pt2;
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, id, AcDb::kForRead);
if (pPipe != NULL)
{
pt1 = pPipe->StartPoint();
pt2 = pPipe->EndPoint();
pPipe->close();
}
XLine l(pt1, pt2, 1);
XPoint pt3;
ptLoc.Project(&l, pt3);
if (pt3.Distance2d(ptLoc) < 1e-3)
{
bVal = FALSE;
}
}
}
else // 雨水斗没有连接立管时,默认存在连接管
{
bVal = TRUE;
}
}
return bVal;
}
void GetPipeIdByNO(SSearchPipeList *pListAll, std::vector<std::vector<AcDbObjectId> > &data)
{
SSearchPipeList *pList = GetNextWaterBucket(pListAll); // 得到主干线
SSearchPipeList *pTemp = pList;
std::vector<AcDbObjectId> vec;
while(pList != NULL)
{
if (pList->m_iType == 0)
{
vec.push_back(pList->m_ID);
}
pList = pList->m_pPrevious;
}
if (!ExistVPipe(pTemp))
{
vec.insert(vec.begin(), AcDbObjectId::kNull);
}
if (!ExistPipe(pTemp))
{
std::vector<AcDbObjectId>::iterator it;
it = vec.begin();
++it;
vec.insert(it, AcDbObjectId::kNull);
}
data.push_back(vec);
pList = pTemp;
SSearchPipeList *pPre = NULL;
while (pList != NULL) // 处理主干线上的分支
{
if (pList->m_iType == 1 && pList->m_lstNode.Length() == 2 && pList->m_nSpare != 1) // 存在其他未处理分支
{
SSearchPipeList *pOther = pPre == pList->m_lstNode[0] ? pList->m_lstNode[1] : pList->m_lstNode[0];
pOther->m_pPrevious = NULL;
GetPipeIdByNO(pOther, data);
}
pPre = pList;
pList = pList->m_pPrevious;
}
}
//获得雨水斗管径
double GetWaterBucketPipeDia(SSearchPipeList *pList)
{
if(pList != NULL)
{
std::vector<SSearchPipeList*> data;
GetWaterBucket(pList, data, true);
if (!data.empty())
{
ads_name name;
acdbGetAdsName(name, data[0]->m_ID);
Entity ent(name);
CString strDia = ReadXdata(ent, _T("PipeDia"));
return _tstof(strDia);
}
}
return 0;
}
//根据管材管径获得特定的管径
double GetPipeDia(double dDia, CString &strMatriel)
{
int nType = GetPipeMaterialType(strMatriel);
if (nType == 1) //排水塑料管
{
if (fabs(100 - dDia) < 1e-3)
{
dDia = 110;
}
else if (fabs(150 - dDia) < 1e-3)
{
dDia = 160;
}
}
else if (nType == 2) //钢管
{
if (fabs(75 - dDia) < 1e-3)
{
dDia = 80;
}
}
return dDia;
}
//根据雨水斗数从数据库中提取管径信息,修改管径
void ModifyPipeDia(std::vector<std::vector<AcDbObjectId> > &data, std::vector<AcDbObjectId> &vecPipe, double dDia)
{
if (!data.empty())
{
if (dDia < 50)
{
dDia = 50;
}
else if (dDia > 50 && dDia < 75)
{
dDia = 75;
if (fabs(dDia - 70) < 1e-3)
{
dDia = 75;
}
}
else if (dDia > 75)
{
dDia = 100;
}
//从数据库中提取管径
XString fullFile;
if(!FindFile(_T("SiphonRain.dbf"), fullFile))
{
acutPrintf(_T("对不起,没有发现SiphonRain.dbf文件!"));
return;
}
CodeBase db;
db.read_only = 1;
XDbfTable *pTable = db.Open(fullFile);
if(!pTable)
return;
int nBucketNum = data.size();
CString strNum, strNum2;
if (nBucketNum > 6) //分支雨水斗数大于6时多余斗按第六斗管径赋值
{
nBucketNum = 6;
}
strNum2.Format(_T("%.0f-%d"), dDia, nBucketNum);
std::vector<std::vector<double> > vecDia;
double dMDia = 0, dOutDia = 0;
for(pTable->MoveFirst(); !pTable->IsEOF(); pTable->MoveNext())
{
GET_FIELD(pTable, _T("Type"), strNum);
if (strNum.Compare(strNum2) != 0)
{
continue;
}
std::vector<double> vec1, vec2, vec3, vec4, vec5, vec6;
CString strV, strL, strH;
double dVDia = 0, dLDia = 0, dHDia = 0;
GET_FIELD(pTable, _T("V1"), strV);
GET_FIELD(pTable, _T("L1"), strL);
GET_FIELD(pTable, _T("H1"), strH);
dVDia = _tstof(strV);
dLDia = _tstof(strL);
dHDia = _tstof(strH);
vec1.push_back(dVDia);
vec1.push_back(dLDia);
vec1.push_back(dHDia);
GET_FIELD(pTable, _T("V2"), strV);
GET_FIELD(pTable, _T("L2"), strL);
GET_FIELD(pTable, _T("H2"), strH);
dVDia = _tstof(strV);
dLDia = _tstof(strL);
dHDia = _tstof(strH);
vec2.push_back(dVDia);
vec2.push_back(dLDia);
vec1.push_back(dHDia);
GET_FIELD(pTable, _T("V3"), strV);
GET_FIELD(pTable, _T("T3"), strL);
GET_FIELD(pTable, _T("H3"), strH);
dVDia = _tstof(strV);
dLDia = _tstof(strL);
dHDia = _tstof(strH);
vec3.push_back(dVDia);
vec3.push_back(dLDia);
vec1.push_back(dHDia);
GET_FIELD(pTable, _T("V4"), strV);
GET_FIELD(pTable, _T("T4"), strL);
GET_FIELD(pTable, _T("H4"), strH);
dVDia = _tstof(strV);
dLDia = _tstof(strL);
dHDia = _tstof(strH);
vec4.push_back(dVDia);
vec4.push_back(dLDia);
vec1.push_back(dHDia);
GET_FIELD(pTable, _T("V5"), strV);
GET_FIELD(pTable, _T("T5"), strL);
GET_FIELD(pTable, _T("H5"), strH);
dVDia = _tstof(strV);
dLDia = _tstof(strL);
dHDia = _tstof(strH);
vec5.push_back(dVDia);
vec5.push_back(dLDia);
vec1.push_back(dHDia);
GET_FIELD(pTable, _T("V6"), strV);
GET_FIELD(pTable, _T("T6"), strL);
GET_FIELD(pTable, _T("H6"), strH);
dVDia = _tstof(strV);
dLDia = _tstof(strL);
dHDia = _tstof(strH);
vec6.push_back(dVDia);
vec6.push_back(dLDia);
vec1.push_back(dHDia);
GET_FIELD(pTable, _T("Mainv"), strV);
GET_FIELD(pTable, _T("Mainout"), strL);
dMDia = _tstof(strV);
dOutDia = _tstof(strL);
vecDia.push_back(vec1);
vecDia.push_back(vec2);
vecDia.push_back(vec3);
vecDia.push_back(vec4);
vecDia.push_back(vec5);
vecDia.push_back(vec6);
for(int i = 6; i < data.size(); i++) //多余六个斗时,多余都按第六个斗规则处理
{
vecDia.push_back(vec6);
}
break;
}
pTable->Close();
//修改管径
std::vector<std::vector<AcDbObjectId> >::iterator it;
std::vector<AcDbObjectId>::iterator it1, it2;
std::vector<double> vec;
int i = 0; //雨水斗编号
for(it = data.begin(); it != data.end(); it++)
{
vec = vecDia[i];
int j = 0; //管段编号
double dDiaPre = 0; //记录上一管管径
double dCurDia = 0;
double dSize = vec.size();
for (it1 = (*it).begin(); it1 != (*it).end(); it1++)
{
if (vec.size() <= j || vec[j] < 1e-3) //已无有效管径
{
break;
}
dCurDia = vec[j];
it2 = std::find(vecPipe.begin(), vecPipe.end(), *it1);
if (it2 != vecPipe.end()) //倒角
{
dCurDia = dDiaPre;
}
else //非倒角
{
dDiaPre = dCurDia;
j++;
}
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, *it1, AcDb::kForWrite);
if (pPipe != NULL)
{
CString ss = GetPipeMaterialByIdx(pPipe->GetMaterial());
double dPipeDia = GetPipeDia(dCurDia, ss);
pPipe->SetDnDiameter(dPipeDia);
pPipe->close();
}
}
dCurDia = dDiaPre;
BOOL bVPipe = FALSE; //是否修改了立管
while(it1 != (*it).end() && i == 0) //主干管上其余管段(立管、排出管)
{
TDbPipe *pPipe = NULL;
acdbOpenObject(pPipe, *it1, AcDb::kForWrite);
if (pPipe != NULL)
{
if (pPipe->IsVertical())
{
dCurDia = dMDia;
bVPipe = TRUE;
}
else if (bVPipe)
{
dCurDia = dOutDia;
}
CString ss = GetPipeMaterialByIdx(pPipe->GetMaterial());
double dPipeDia = GetPipeDia(dCurDia, ss);
pPipe->SetDnDiameter(dPipeDia);
pPipe->close();
}
++it1;
}
++i;
}
}
}
void BeforehandCalc(SSearchPipeList *pListAll)
{
//初始化链表
UpDataPipeLen(pListAll);
//获得所有倒角管段
std::vector<AcDbObjectId> vecPipe;
GetChamferPipe(pListAll, vecPipe);
//拆分系统以便获得满足要求的虹吸预计算规则的子系统
std::vector<SSearchPipeList*> vecData;
BreakBucketSys(pListAll, vecData);
//雨水斗管径
double dBucketDia = GetWaterBucketPipeDia(pListAll);
//按编号顺序存储管段(包括倒角),并修改管径
std::vector<SSearchPipeList*>::iterator it;
for (it = vecData.begin(); it != vecData.end(); it++)
{
std::vector<std::vector<AcDbObjectId> > dataPipe;
GetPipeIdByNO(*it, dataPipe);
if (!dataPipe.empty())
{
//根据雨水斗数从数据库中提取管径信息,修改管径
ModifyPipeDia(dataPipe, vecPipe, dBucketDia);
}
}
}
// 主函数
void BeforehandCalc()
{
RBList rbMaskPipe(RTDXF0, _T("ATS_PIPE"), 8, LAY_PIPE_RAIN, NULL);
Entity entMainPipe;
if (SelectEntity(_T("\n请选择该段管道的出流端<退出>:"), entMainPipe, rbMaskPipe) != RTNORM)
{
return;
}
SSearchPipeList *pListAll = new SSearchPipeList();
PickSet ssAll(SS_FREE);
ssAll += entMainPipe;
if(!SearchSprinkPipeSys(entMainPipe, NULL, pListAll, ssAll))
{
AfxMessageBox(_T("系统有回路!"));
delete pListAll;
return;
}
BeforehandCalc(pListAll);
}