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

2330 lines
58 KiB
C++

#include "StdAfx.h"
#include "UnfoldInstallSanitarySys.h"
#define WALL_MAX_THICK (DocGetCurMeterUnitDraw() ? 1 : 1000) // 墙体最大厚度
UnfoldInstallSanitarySys::UnfoldInstallSanitarySys()
{
m_dElev = 0.0;
m_pNodeStart = NULL;
m_nInstallType = 0;
m_bErrorNote = false;
m_bCreatPipe = true;
m_bPipeDir = true;
m_tolVec.setEqualVector(0.01);
}
void UnfoldInstallSanitarySys::IsCreatPipe(bool bCreatPipe)
{
m_bCreatPipe = bCreatPipe;
}
bool UnfoldInstallSanitarySys::GetErrorNote()
{
return m_bErrorNote;
}
void UnfoldInstallSanitarySys::SetErrorNote(bool bErrorNote)
{
m_bErrorNote = bErrorNote;
}
// 设置明装还是安装方式
void UnfoldInstallSanitarySys::SetInstallType(int nInstallType)
{
m_nInstallType = nInstallType;
}
void UnfoldInstallSanitarySys::AutoLinkSanitary( const SanitarySysData &data )
{
m_dPipeDn = GetPipeDn(data.id);
m_sysPipe = data.type;
m_idPipe = data.id;
m_ptFeed = data.pt;
m_ptFeed.z = 0;
InitWallEnt();
ModifyUsefulWall();
// 将洁具按距离给水点远近排序
SanitarySysData sanData = data;
std::vector<SanitaryNode> &vecSanNode = sanData.vecSanitaryNode;
Sort(vecSanNode, sanData.pt);
// 按洁具点距给水点远近连接洁具
LinkSanitary(sanData);
}
void UnfoldInstallSanitarySys::LinkSanitary(const SanitarySysData &data)
{
// 获得最远洁具给水点 洁具id
std::vector<SanitaryNode> vecNode = data.vecSanitaryNode;
std::vector<SanitaryNode>::iterator it = vecNode.begin();
AcGePoint3d ptSan = it->pt;
ptSan.z = 0;
AcDbObjectId idSan = it->idSanitary;
AcGePoint3d ptFeed = data.pt;
ptFeed.z = 0;
AcGeVector3d vtPipe = AcGeVector3d::kXAxis, vtDir;
AcDbLine lineStart, lineEnd;
double dWallThick = 0.0;
bool bIsParallel = false;
bool bExtendFeedPipe = true;
AcGeVector3d vtSan;
bIsParallel = IsSanPtsParallel(vecNode, vtSan);
m_tolVec.setEqualVector(0.01);
CString sNote = _T("供水明装无法检测到可用上华墙体 ");
// 设定主干方向
if (ConfirmPipeDir(vtPipe, ptSan, vtDir))
{
AcGePoint3d ptFar;
if (!IsVertivalPipe(m_idPipe))// 更新供水管
{
AcGePoint3d ptS, ptE, ptOnLine;
GetPipePoint(m_idPipe, ptS, ptE);
ptS.z = 0;
ptE.z = 0;
ptS = Wcs2Ucs(ptS);
ptE = Wcs2Ucs(ptE);
AcGeVector3d vt = ptE - ptS;
vt.normalize();
ptS = Ucs2Wcs(ptS);
ptE = Ucs2Wcs(ptE);
AcDbLine lineFeed;
lineFeed.setStartPoint(ptS);
lineFeed.setEndPoint(ptE);
lineFeed.getClosestPointTo(ptSan, ptOnLine, Adesk::kTrue);
if (fabs(ptS.distanceTo(ptE) - ptOnLine.distanceTo(ptS) - ptOnLine.distanceTo(ptE)) < 0.001)// 洁具点在管线上的投影点在管线上
{
bExtendFeedPipe = false;
}
vtPipe.normalize();
if (vtPipe.isEqualTo(vt, m_tolVec))
{
ptFar = ptS;
AddPipeLine(ptS, ptE, PipeType::eMainPipe);
}
else
{
ptFar = ptE;
m_bPipeDir = false;
}
}
// 查找给水点的起始墙体
if (!GetIntersectWall(ptFar, vtDir, lineStart, vtPipe, true))
{
if (bIsParallel)
{
LinkSanWithoutWall(vecNode, vtPipe, bExtendFeedPipe, vtSan);
}
else if (!m_bErrorNote)
{
AfxMessageBox(sNote, MB_OK);
m_bErrorNote = true;
}
return;
}
}
else
{
// 主干方向无法确定时,查找最近墙体
if (!GetWallMiddleLine(ptFeed, lineStart))
{
if (bIsParallel)
{
LinkSanWithoutWall(vecNode, vtPipe, bExtendFeedPipe, vtSan);
}
else if (!m_bErrorNote)
{
AfxMessageBox(sNote, MB_OK);
m_bErrorNote = true;
}
return;
}
}
// 查找最远洁具点的终止墙体
GetSanitaryDir(vtDir, idSan);
if (!GetIntersectWall(ptSan, vtDir.perpVector(), lineEnd, vtDir.negate(), false))
{
if (!GetWallMiddleLine(ptSan, lineEnd))
{
if (bIsParallel)
{
LinkSanWithoutWall(vecNode, vtPipe, bExtendFeedPipe, vtSan);
}
else if (!m_bErrorNote)
{
AfxMessageBox(sNote, MB_OK);
m_bErrorNote = true;
}
return;
}
}
// 搜寻最短路径
std::vector<WallData *> vecRoad;
if (!GetWallRoad(lineStart, lineEnd, vecRoad))
{
if (!m_bErrorNote)
{
AfxMessageBox(sNote, MB_OK);
m_bErrorNote = true;
}
return;
}
// 设定主干
if (!SetMainPipe(vecRoad, vecNode))
{
return;
}
m_vecRoad = vecRoad;
// 连接洁具
LinkSanitary(vecRoad, vecNode);
// 设定管线标高
SetLinkableNode();
if (!IsVertivalPipe(m_idPipe))// 更新供水管
{
Entity ent;
ads_name name;
acdbGetAdsName(name, m_idPipe);
ent = name;
ent.Erase();
}
}
// 连接无墙洁具
void UnfoldInstallSanitarySys::LinkSanWithoutWall(std::vector<SanitaryNode> &vecNode, AcGeVector3d &vtPipe, bool bExtendFeedPipe, AcGeVector3d &vtSan)
{
std::vector<SanitaryNode>::iterator it;
it = vecNode.begin();
AcGePoint3d ptSan = it->pt, ptInter, ptE;
ptSan.z = 0;
ptSan = Wcs2Ucs(ptSan);
m_ptFeed = Wcs2Ucs(m_ptFeed);
AcGePoint3d ptX, ptY;
ptX.x = ptSan.x;
ptX.y = m_ptFeed.y;
ptX.z = 0;
ptY.x = m_ptFeed.x;
ptY.y = ptSan.y;
ptY.z = 0;
if (IsVertivalPipe(m_idPipe))
{
if (vecNode.size() > 1)
{
vtPipe = vtSan;
}
else
{
vtPipe = ptX - m_ptFeed;
}
}
AcDbLine lineMain;
lineMain.setStartPoint(m_ptFeed);
AcGeVector3d vtX, vtY;
vtX = ptY - m_ptFeed;
vtY = ptX - m_ptFeed;
if (vtX.isParallelTo(vtPipe, m_tolVec))
{
lineMain.setEndPoint(ptY);
ptSan = Ucs2Wcs(ptSan);
m_ptFeed = Ucs2Wcs(m_ptFeed);
ptY = Ucs2Wcs(ptY);
ptE = ptY;
if (bExtendFeedPipe)
{
AddPipeLine(m_ptFeed, ptY, PipeType::eMainPipe);
}
}
else if (vtY.isParallelTo(vtPipe, m_tolVec))
{
lineMain.setEndPoint(ptX);
ptSan = Ucs2Wcs(ptSan);
m_ptFeed = Ucs2Wcs(m_ptFeed);
ptX = Ucs2Wcs(ptX);
ptE = ptX;
if (bExtendFeedPipe)
{
AddPipeLine(m_ptFeed, ptX, PipeType::eMainPipe);
}
}
else
{
return;
}
// 存储洁具点结构
for (it = vecNode.begin(); it != vecNode.end(); it++)
{
m_mapSanPt.insert(std::make_pair(it->idSanitary, it->pt));
}
if (vecNode.size() > 1 && vtSan.isPerpendicularTo(vtPipe))// 供水管和洁具线垂直,管线直接穿过洁具点
{
LinkSanCrossPipe(vecNode, ptE);
}
else// 供水管和洁具线平行,直接投影
{
LinkSan2Proj(vecNode, lineMain);
}
if (!IsVertivalPipe(m_idPipe))// 更新供水管
{
Entity ent;
ads_name name;
acdbGetAdsName(name, m_idPipe);
ent = name;
ent.Erase();
}
}
// 连接管线直接穿过洁具点的洁具
void UnfoldInstallSanitarySys::LinkSanCrossPipe(std::vector<SanitaryNode> &vecNode, AcGePoint3d &ptCross)
{
if (!IsVertivalPipe(m_idPipe))
{
AcGePoint3d ptStart, ptEnd;
GetPipePoint(m_idPipe, ptStart, ptEnd);
ptStart.z = 0;
m_ptFeed = ptStart;
}
LinkNode *pNodeS = new LinkNode;
LinkNode *pNodeFeed = new LinkNode;
pNodeS->ptCur = ptCross;
pNodeS->type = Point_Int;
pNodeS->pPreNode = pNodeFeed;
pNodeFeed->ptCur = m_ptFeed;
pNodeFeed->type = Point_Feed;
pNodeFeed->pPreNode = NULL;
pNodeFeed->m_vecNode.push_back(pNodeS);
AcGePoint3d ptSan;
std::vector<SanitaryNode>::reverse_iterator itRev;
for (itRev = vecNode.rbegin(); itRev != vecNode.rend(); itRev++)
{
ptSan = (*itRev).pt;
ptSan.z = 0;
LinkNode *pNode = new LinkNode;
LinkNode *pNodeSan = new LinkNode;
pNode->ptCur = ptSan;
pNode->type = Point_Int | Point_KW;
pNode->m_vecNode.push_back(pNodeSan);
pNodeS->m_vecNode.push_back(pNode);
pNode->pPreNode = pNodeS;
pNodeSan->ptCur = ptSan;
pNodeSan->type = Point_Sanitary;
pNodeSan->pPreNode = pNode;
pNodeS = pNode;
}
m_pNodeStart = pNodeFeed;
ModifyPipeElve();// 设定管线标高
}
// 连接投影到管线的洁具点
void UnfoldInstallSanitarySys::LinkSan2Proj(std::vector<SanitaryNode> &vecNode, AcDbLine &lineMain)
{
AcGePoint3d ptSan, ptInter;
std::vector<SanitaryNode>::iterator it;
while (!vecNode.empty())
{
it = vecNode.begin();
ptSan = (*it).pt;
ptSan.z = 0;
ptSan = Wcs2Ucs(ptSan);
lineMain.getClosestPointTo(ptSan, ptInter, Adesk::kTrue);
ptSan = Ucs2Wcs(ptSan);
ptInter = Ucs2Wcs(ptInter);
if (ptSan.distanceTo(ptInter) < 0.001)
{
ptSan.z = 100;
}
AddPipeLine(ptInter, ptSan, PipeType::eBranch);
vecNode.erase(it);
}
// 设定管线标高
SetLinkableNode();
}
// 判断所有洁具点是否共线
bool UnfoldInstallSanitarySys::IsSanPtsParallel(std::vector<SanitaryNode> &vecNode, AcGeVector3d &vtSan)
{
m_tolVec.setEqualVector(0.001);
if (vecNode.size() < 2)
{
return true;
}
std::vector<SanitaryNode>::iterator it;
it = vecNode.begin();
AcGeVector3d vtFirst, vtSecond;
AcGePoint3d ptFirst, ptSecond, ptThird;
ptFirst = it->pt;
ptFirst.z = 0;
it++;
ptSecond = it->pt;
ptSecond.z = 0;
vtFirst = ptFirst - ptSecond;
ptFirst = Wcs2Ucs(ptFirst);
ptSecond = Wcs2Ucs(ptSecond);
it++;
vtSan = ptFirst - ptSecond;
ptSecond = Ucs2Wcs(ptSecond);
while (it != vecNode.end())
{
ptThird = it->pt;
ptThird.z = 0;
vtSecond = ptSecond - ptThird;
if (!vtFirst.isParallelTo(vtSecond, m_tolVec))
{
return false;
}
ptSecond = ptThird;
it++;
}
return true;
}
// 设定主干
bool UnfoldInstallSanitarySys::SetMainPipe(std::vector<WallData *> &vecRoad, std::vector<SanitaryNode> &vecNode)
{
if (vecRoad.size() < 1)
{
return false;
}
std::vector<WallData *>::iterator itWall;
AcGePoint3d ptOnLine, ptS, ptE, ptPerS, ptPerE;
AcGeVector3d vt, vtPer, vtStart, vtCur;
std::vector<AcDbLine *> vecLine;
AcDbLine line;
double dWidth = 0.0, dDistPipe2Wall = 0.0, dDistOldPipe2Wall = m_dDistPipe2Wall;;
AcDbLine *pLine = NULL;
bool bNotTurned = false;
for (itWall = vecRoad.begin(); itWall != vecRoad.end(); itWall++)
{
if (NULL == (*itWall))
{
continue;
}
dWidth = (*itWall)->dWidth / 2;
ptS = (*itWall)->ptS;
ptE = (*itWall)->ptE;
ptS.z = 0;
ptE.z = 0;
pLine = new AcDbLine();
line.setStartPoint(ptS);
line.setEndPoint(ptE);
// 起始墙体和终止墙体需要特殊设定
if (itWall == vecRoad.begin())// 起始墙体
{
if (!IsVertivalPipe(m_idPipe))// 给水管为非立管时
{
// 根据墙体两侧是否有洁具 确定管线与墙体的位置(即管线安置在墙体有洁具的一侧)
bool bSeted = false;// 能否确定管线与墙的关系
std::vector<SanitaryNode>::iterator itSan;
for (itSan = vecNode.begin(); itSan != vecNode.end(); itSan++)
{
AcGePoint3d ptSan = (*itSan).pt;
ptSan.z = 0;
if (line.getClosestPointTo(ptSan, ptOnLine) == Acad::eOk && ptOnLine.distanceTo(ptSan) < m_dDistSearchWall)
{
AcGeVector3d vtLine = ptE - ptS;
vt = ptSan - ptOnLine;
vt.normalize();
if (vtLine.isPerpendicularTo(vt, m_tolVec))
{
bSeted = true;
break;
}
}
}
GetPipePoint(m_idPipe, ptS, ptE);
ptS.z = 0;
ptE.z = 0;
if (line.getClosestPointTo(m_ptFeed, ptOnLine) == Acad::eOk)
{
if (!bSeted)// 无法确定管线沿墙方向,穿墙布线
{
vt = ptOnLine - m_ptFeed;
if (!IsVertivalPipe(m_idPipe))
{
vt = ptE - ptS;
if (!m_bPipeDir)
{
vt = ptS - ptE;
}
}
vt.normalize();
}
ptOnLine = ptOnLine + vt * ((*itWall)->dWidth / 2 + m_dDistPipe2Wall);
}
// 延长管线从给水点到关联墙体
AcDbLine lineStart;
lineStart.setStartPoint(ptS);
lineStart.setEndPoint(ptE);
AcGePoint3d ptTmp;
lineStart.getClosestPointTo(ptOnLine, ptTmp);
if (ptTmp.distanceTo(ptOnLine) > 0.001 && ptOnLine.distanceTo(m_ptFeed) > 0.001)
{
AcDbLine *pLineNew = new AcDbLine();
pLineNew->setStartPoint(m_ptFeed);
pLineNew->setEndPoint(ptOnLine);
vecLine.push_back(pLineNew);
}
m_ptFeed = ptOnLine;
}
else// 给水管为立管时,偏移距离为立管距墙距离
{
vtStart = ptE - ptS;
bNotTurned = true;
line.getClosestPointTo(m_ptFeed, ptOnLine);
dDistPipe2Wall = ptOnLine.distanceTo(m_ptFeed) - (*itWall)->dWidth / 2;
}
ptS = line.startPoint();
ptE = line.endPoint();
SetStartPipe(pLine, m_ptFeed, line, vtPer);
if ((*itWall)->id == vecRoad.back()->id)// 路径只存在一个墙体
{
AcGePoint3d ptStart = pLine->startPoint();
if (bNotTurned)// 墙体和起始墙体平行
{
vtCur = ptE - ptS;
if (vtCur.isParallelTo(vtStart, m_tolVec))
{
m_dDistPipe2Wall = dDistPipe2Wall;
}
}
SetEndPipe(pLine, (*vecNode.begin()).pt, line, dWidth);
m_dDistPipe2Wall = dDistOldPipe2Wall;
pLine->setStartPoint(ptStart);
AcGePoint3dArray arryPts;
arryPts.setLogicalLength(0);
pLine->intersectWith(&line, AcDb::kOnBothOperands, arryPts);
if (arryPts.length() > 0)// 主干和墙体相交,无法连接
{
AfxMessageBox(_T("无法获取最优路径 "), MB_OK);
return false;
}
}
}
else if ((*itWall)->id == vecRoad.back()->id)// 终止墙体
{
if (bNotTurned)// 墙体和起始墙体平行
{
vtCur = ptE - ptS;
if (vtCur.isParallelTo(vtStart, m_tolVec))
{
m_dDistPipe2Wall = dDistPipe2Wall;
}
}
SetEndPipe(pLine, (*vecNode.begin()).pt, line, dWidth);
m_dDistPipe2Wall = dDistOldPipe2Wall;
}
else // 中间墙体
{
if (bNotTurned)// 墙体和起始墙体平行
{
vtCur = ptE - ptS;
if (vtCur.isParallelTo(vtStart, m_tolVec))
{
m_dDistPipe2Wall = dDistPipe2Wall;
}
else
{
m_dDistPipe2Wall = dDistOldPipe2Wall;
bNotTurned = false;
}
}
SetMiddlePipe(ptS, ptE, line, vecNode, dWidth, ptPerS, ptPerE, vtPer);
pLine->setStartPoint(ptS);
pLine->setEndPoint(ptE);
}
vecLine.push_back(pLine);
ptPerS = ptS;
ptPerE = ptE;
}
ModifyPipe(vecLine, dWidth);
std::vector<AcDbLine *>::iterator it;
for (it = vecLine.begin(); it != vecLine.end(); it++)
{
if (NULL == (*it) || (*it)->startPoint().distanceTo((*it)->endPoint()) < 0.001)
{
continue;
}
AddPipeLine((*it)->startPoint(), (*it)->endPoint(), PipeType::eMainPipe);
}
FreeLine(vecLine);
return true;
}
// 根据主干 设定分支管和小支管
void UnfoldInstallSanitarySys::LinkSanitary(std::vector<WallData *> &vecRoad, std::vector<SanitaryNode> &vecNode)
{
std::vector<SanitaryNode>::iterator it;
AcGePoint3d ptSan, ptS, ptE;
AcDbObjectId idSan;
AcDbLine line;
AcGeVector3d vt;
while (!vecNode.empty())
{
it = vecNode.begin();
ptSan = (*it).pt;
ptSan.z = 0;
idSan = (*it).idSanitary;
GetSanitaryDir(vt, idSan);
if (!GetIntersectWall(ptSan, vt.perpVector(), line, vt.negate(), false))
{
if (!GetWallMiddleLine(ptSan, line))
{
vecNode.erase(it);
continue;
}
}
ptS = line.startPoint();
ptE = line.endPoint();
ptS.z = 0;
ptE.z = 0;
if (LinkSanitary2MainPipe(ptSan, ptS, ptE, vecNode))
{
m_mapSanPt.insert(std::make_pair(it->idSanitary, it->pt));// 存储洁具点结构
}
vecNode.erase(it);
}
}
#define MAX_DIST 100000
// 添加支管和小支管
bool UnfoldInstallSanitarySys::LinkSanitary2MainPipe(const AcGePoint3d &ptSan, const AcGePoint3d &ptS, const AcGePoint3d &ptE, const std::vector<SanitaryNode> vecNode)
{
AcDbLine line;
line.setStartPoint(ptS);
line.setEndPoint(ptE);
AcDbLine lineCheck;
AcGePoint3d ptOnLine, ptCheck, ptOnPipe, ptStart, ptEnd;
if (line.getClosestPointTo(ptSan, ptOnLine) != Acad::eOk)
{
return false;
}
AcGeVector3d vtCheck = ptSan - ptOnLine, vtPipe;
vtCheck.normalize();
ptCheck = ptOnLine + vtCheck * 1000;
lineCheck.setStartPoint(ptOnLine);
lineCheck.setEndPoint(ptCheck);
std::vector<WallData *> vecRoad;
double dDist = 0.0, dLen = 0.0, dDist1 = 0.0, dDist2 = 0.0;
std::map<double, LinkedLine> mapPipe;
std::map<double, LinkedLine>::iterator itMap;
if (GetExtendPipe(mapPipe, lineCheck, ptSan, false))// 获取到可直接连接的主干
{
itMap = mapPipe.begin();
ptOnPipe = (*itMap).second.ptIntersect;
AcDbLine *pLine = (*itMap).second.pLine;
if (NULL == pLine)
{
return false;
}
ptStart = pLine->startPoint();
ptEnd = pLine->endPoint();
dLen = ptStart.distanceTo(ptEnd);
dDist1 = ptStart.distanceTo(ptOnPipe);
dDist2 = ptEnd.distanceTo(ptOnPipe);
AcGeVector3d vt = ptSan - ptOnLine;
vt.normalize();
if (CheckPipe2Wall(ptEnd, ptOnPipe, line))
{
if (fabs(dLen - dDist1 - dDist2) < 0.001)// 交点在管线上
{
;
}
else if (fabs(dDist1 - dLen - dDist2) < 0.001)// 交点在终点的延长线上
{
if (!CheckPipePos(ptEnd, ptOnPipe))
{
AcGePoint3d ptPer = ptEnd;
ptEnd = ptEnd + vt * m_dDistPipe2Wall;
ptOnPipe = ptOnPipe + vt * m_dDistPipe2Wall;
AddPipeLine(ptPer, ptEnd, PipeType::eBranch);
}
AddPipeLine(ptEnd, ptOnPipe, PipeType::eMainPipe);
}
else if (fabs(dDist2 - dLen - dDist1) < 0.001)// 交点在起点的延长线上
{
if (!CheckPipePos(ptStart, ptOnPipe))
{
AcGePoint3d ptPer = ptStart;
ptStart = ptStart + vt * m_dDistPipe2Wall;
ptOnPipe = ptOnPipe + vt * m_dDistPipe2Wall;
AddPipeLine(ptPer, ptStart, PipeType::eBranch);
}
AddPipeLine(ptStart, ptOnPipe, PipeType::eMainPipe);
}
AcGePoint3d ptSanitary = ptSan;
if (ptOnPipe.distanceTo(ptSanitary) < 0.001)// 洁具直接穿过主干线
{
ptSanitary.z = 100;
}
AddPipeLine(ptOnPipe, ptSanitary, PipeType::eSmallPipe);// 小支管不用偏移
return true;
}
}
// 得到所有与墙线相交的主干
if (GetExtendPipe(mapPipe, line, ptSan, false))
{
if(ExtendPipe2San(mapPipe, ptSan, ptOnLine, line))
{
return true;
}
}
// 延长墙体 得到主干
if (GetExtendPipe(mapPipe, line, ptSan, true))
{
if(ExtendPipe2San(mapPipe, ptSan, ptOnLine, line))
{
return true;
}
}
// 未找到可连接管线,继续寻找最短路径
if (!GetBranchWallRoad(line, vecRoad))
{
return false;
}
SetNewMainPipe(ptSan, vecRoad, vecNode);
return true;
}
// 沿墙体延长管线 连接洁具
bool UnfoldInstallSanitarySys::ExtendPipe2San(std::map<double, LinkedLine> &mapPipe, const AcGePoint3d &ptSan, AcGePoint3d &ptOnLine, AcDbLine &line)
{
AcGePoint3d ptS, ptE, ptSanitary = ptSan;
double dLen = 0.0, dDist1 = 0.0, dDist2 = 0.0 , dWallThick = 0.0;
AcGePoint3d ptMainEnd;
AcGePoint3d ptMainStart;
std::map<double, LinkedLine>::iterator itMap;
AcDbLine line1, line2;
bool bRet1 = false, bRet2 = false;
m_vtSan = ptSanitary - ptOnLine;
while (!mapPipe.empty())
{
itMap = mapPipe.begin();
ptMainEnd = ptOnLine;
ptMainStart = (*itMap).second.ptIntersect;
bRet1 = GetNearestWall(ptMainEnd, ptMainEnd - ptMainStart, line1, dWallThick);
ptS = (*itMap).second.pLine->startPoint();
ptE = (*itMap).second.pLine->endPoint();
bRet2 = GetNearestWall(ptS, ptE - ptS, line2, dWallThick);
if (bRet2 && bRet1)
{
if (CheckPipe2Wall(ptMainStart, ptMainEnd, line1) && CheckPipe2Wall(ptS, ptMainStart, line2))
{
break;
}
}
else if (bRet1 && CheckPipe2Wall(ptMainStart, ptMainEnd, line1) && (*itMap).second.nId == 0)// 与供水管相交时,不用考虑供水管延长线是否穿越墙体
{
break;
}
mapPipe.erase(itMap);
}
if (mapPipe.empty())
{
return false;
}
AcDbObjectId id;
WallData *pNode = NULL;
GetWallId(m_vecAllWall, line, id);
CheckWallInLst(m_vecAllWall, id, pNode);
if (NULL == pNode)
{
return false;
}
OffSetPipe(ptMainStart, ptMainEnd, ptSan - ptMainEnd, pNode->dWidth / 2);
AddPipeLine(ptMainEnd, ptSanitary, PipeType::eSmallPipe);
AddPipeLine(ptMainStart, ptMainEnd, PipeType::eMainPipe);
dLen = ptS.distanceTo(ptE);
dDist1 = ptS.distanceTo(ptMainStart);
dDist2 = ptE.distanceTo(ptMainStart);
AcGeVector3d vt = ptSan - ptOnLine;
vt.normalize();
if (fabs(dDist1 - dLen - dDist2) < 0.001)
{
AddPipeLine(ptE, ptMainStart, PipeType::eMainPipe);
}
else if (fabs(dDist2 - dLen - dDist1) < 0.001)
{
AddPipeLine(ptS, ptMainStart, PipeType::eMainPipe);
}
return true;
}
// 释放管线节点
void UnfoldInstallSanitarySys::FreeLine(std::vector<AcDbLine *> &vecLine)
{
std::vector<AcDbLine *>::iterator it;
for (it = vecLine.begin(); it != vecLine.end(); it++)
{
if ((*it) != NULL)
{
delete *it;
*it = NULL;
}
}
}
// 释放路径节点
void UnfoldInstallSanitarySys::FreeNode(std::vector<WallData *> &vecNode)
{
std::vector<WallData *>::iterator it;
for (it = vecNode.begin(); it != vecNode.end(); it++)
{
if ((*it) != NULL)
{
delete *it;
*it = NULL;
}
}
}
// 连接次级主干
void UnfoldInstallSanitarySys::SetNewMainPipe(const AcGePoint3d &pt, std::vector<WallData *> &vecRoad, const std::vector<SanitaryNode> &vecNode)
{
WallData *pNodeS = NULL, *pNodeE = NULL;
AcGePoint3d ptNodeS, ptNodeS2, ptNodeE, ptNodeE2;
std::vector<WallData *>::reverse_iterator itCur;
std::vector<WallData *>::iterator itNor;
if (vecRoad.empty())
{
return;
}
// 查找本路线相连的已存在的管线
itCur = vecRoad.rbegin();
// 记录修改前的墙体数据
pNodeS = *itCur;
ptNodeS = pNodeS->ptS;
ptNodeS2 = pNodeS->ptE;
AcDbLine line;
AcGePoint3d ptS = (*itCur)->ptS;
AcGePoint3d ptE = (*itCur)->ptE;
ptS.z = 0;
ptE.z = 0;
line.setStartPoint(ptS);
line.setEndPoint(ptE);
AcGePoint3d ptOnLine, ptPerS, ptPerE, ptStart, ptEnd;
AcGeVector3d vtPer;
double dLen = 0.0, dDist1 = 0.0, dDist2 = 0.0, dDist = 0.0;
std::map<double, LinkedLine> mapLink;
// 得到所有与起始墙线相交的主干
bool bExtendWall = false;
if (!GetExtendPipe(mapLink, line, pt, false))// 找不到相关管线
{
bExtendWall = true;
GetExtendPipe(mapLink, line, pt, true);// 延长墙体
}
// 设定起始墙体
if (mapLink.empty())
{
return;
}
std::map<double, LinkedLine>::iterator itMap = mapLink.begin();
ptOnLine = (*itMap).second.ptIntersect;
AcGePoint3d ptMainEnd = ptOnLine;
AcGePoint3d ptMainStart;
ptPerS = (*itMap).second.pLine->startPoint();
ptPerE = (*itMap).second.pLine->endPoint();
vtPer = ptPerE - ptPerS;
vtPer = vtPer.perpVector();
(*itCur)->ptE = ptOnLine;
// 设置结束管线
itNor = vecRoad.begin();
pNodeE = *itNor;
ptNodeE = pNodeE->ptS;
ptNodeE2 = pNodeE->ptE;
ptS = vecRoad.front()->ptS;
ptE = vecRoad.front()->ptE;
ptS.z = 0;
ptE.z = 0;
line.setStartPoint(ptS);
line.setEndPoint(ptE);
AcGePoint3d ptOnWall;
line.getClosestPointTo(pt, ptOnWall);
(*itNor)->ptS = ptOnWall;
ptEnd = ptOnWall;
// 连接次级主干
LinkNewMainPipe(vecRoad, vecNode, mapLink, pt, ptOnLine, ptPerS, ptPerE, vtPer);
// 恢复墙体数据
pNodeE->ptS = ptNodeE;
pNodeE->ptE = ptNodeE2;
pNodeE->ptS = ptNodeE;
pNodeE->ptE = ptNodeE2;
}
void UnfoldInstallSanitarySys::LinkNewMainPipe(std::vector<WallData *> &vecRoad, const std::vector<SanitaryNode> &vecNode, std::map<double, LinkedLine> &mapLink,
const AcGePoint3d &pt, AcGePoint3d &ptOnLine, AcGePoint3d &ptPerS, AcGePoint3d ptPerE, AcGeVector3d &vtPer)
{
AcGePoint3d ptMainEnd = ptOnLine;
AcGePoint3d ptMainStart;
std::vector<WallData *>::reverse_iterator itCur;
std::map<double, LinkedLine>::iterator itMap = mapLink.begin();
double dWidth = 0.0;
std::vector<AcDbLine *> vecLine;
AcDbLine line;
AcGePoint3d ptS, ptE;
for (itCur = vecRoad.rbegin(); itCur != vecRoad.rend(); itCur++)
{
if (NULL == *itCur)
{
continue;
}
ptE = (*itCur)->ptS;
ptS = (*itCur)->ptE;
ptS.z = 0;
ptE.z = 0;
line.setStartPoint(ptS);
line.setEndPoint(ptE);
AcDbLine *pLine = new AcDbLine;
dWidth = (*itCur)->dWidth / 2;
SetMiddlePipe(ptS, ptE, line, vecNode, dWidth, ptPerS, ptPerE, vtPer);
if (itCur == vecRoad.rbegin() && fabs((*itMap).first - MAX_DIST) < 0.001)// 与主干延长线相交时,延长主干
{
AcDbLine *pLineExtend = new AcDbLine;
ptMainStart = (*itMap).second.pLine->endPoint();
// 交点在主干反方向时
if (ptMainEnd.distanceTo((*itMap).second.pLine->endPoint()) - (*itMap).second.pLine->startPoint().distanceTo((*itMap).second.pLine->endPoint()))
{
ptMainStart = (*itMap).second.pLine->startPoint();
}
AcGeVector3d vt = ptE - ptS;
vt.normalize();
if (!CheckPipePos(ptMainStart, ptMainEnd))// 判断延长线是否与其他管线碰撞
{
AcGePoint3d ptOld = ptMainStart;
ptMainStart = ptMainStart + vt * m_dDistPipe2Wall;
ptMainEnd = ptMainEnd + vt * m_dDistPipe2Wall;
AddPipeLine(ptOld, ptMainStart, PipeType::eMainPipe);
}
pLineExtend->setStartPoint(ptMainStart);
pLineExtend->setEndPoint(ptMainEnd);
vecLine.push_back(pLineExtend);
}
pLine->setStartPoint(ptS);
pLine->setEndPoint(ptE);
vecLine.push_back(pLine);
ptPerE = pLine->endPoint();
ptPerS = pLine->startPoint();
}
// 设定洁具点到管线的连线
AddPipeLine(ptE, pt, PipeType::eBranch);
ModifyPipe(vecLine, dWidth);
std::vector<AcDbLine *>::iterator it;
for (it = vecLine.begin(); it != vecLine.end(); it++)
{
if (*it == NULL || (*it)->startPoint().distanceTo((*it)->endPoint()) < 0.001)
{
continue;
}
AddPipeLine((*it)->startPoint(), (*it)->endPoint(), PipeType::eMainPipe);
}
FreeLine(vecLine);
}
// 检查管线是否沿墙敷设
bool UnfoldInstallSanitarySys::CheckPipe2Wall(const AcGePoint3d &ptS, const AcGePoint3d &ptE, const AcDbLine &lineStartWall)
{
AcDbLine line;
line.setStartPoint(ptS);
line.setEndPoint(ptE);
AcGeVector3d vtLine = ptS - ptE, vtPipe2Wall, vtWall, vt;
vtLine.normalize();
AcGePoint3d ptStart, ptEnd, ptOnLine1, ptOnLine2;
double dLen = 0.0, dDist2Start = 0.0, dDist2End = 0.0, dLength = 0.0, dDist2End2 = 0.0, dDist2Start2 = 0.0, dWallLen = 0.0;
dLen = ptS.distanceTo(ptE);
const double dDist = DocGetMeterUnitDim() ? 0.70 : 700;
AcDbLine lineWall;
lineWall.setStartPoint(lineStartWall.startPoint());
lineWall.setEndPoint(lineStartWall.endPoint());
lineWall.getClosestPointTo(ptS, ptOnLine1, Adesk::kTrue);
if (ptS.distanceTo(ptOnLine1) > 0.001)
{
vtPipe2Wall = ptOnLine1 - ptS;
}
else
{
vtPipe2Wall = m_vtSan;
}
vtPipe2Wall.normalize();
double dDist2Wall = ptS.distanceTo(ptOnLine1);
// 找到所有与管线平行墙体
std::vector<WallData *>::iterator it;
for (it = m_vecAllWall.begin(); it != m_vecAllWall.end(); it++)
{
// 墙体和管线的关系
ptStart = (*it)->ptS;
ptEnd = (*it)->ptE;
dLength = ptStart.distanceTo(ptEnd);
lineWall.setStartPoint(ptStart);
lineWall.setEndPoint(ptEnd);
lineWall.getClosestPointTo(ptS, ptOnLine1, Adesk::kTrue);
if (ptS.distanceTo(ptOnLine1) > 0.001)
{
vt = ptOnLine1 - ptS;
}
else
{
vt = m_vtSan;
}
vt.normalize();
vtWall = ptStart - ptEnd;
vtWall.normalize();
double dDistPipe2Wall = GetDistLines(&lineWall, &line);
// 平行墙体 且墙体距离管线距离为 初始墙体到管线距离 且在管线同侧
if (vtWall.isParallelTo(vtLine, m_tolVec) && fabs(dDistPipe2Wall - dDist2Wall) < dDist && vt.isEqualTo(vtPipe2Wall, m_tolVec))
{
// 墙体长度
lineWall.getClosestPointTo(ptS, ptOnLine1, Adesk::kTrue);
dDist2Start = ptOnLine1.distanceTo(ptStart);
dDist2End = ptOnLine1.distanceTo(ptEnd);
lineWall.getClosestPointTo(ptE, ptOnLine2, Adesk::kTrue);
dDist2Start2 = ptOnLine2.distanceTo(ptStart);
dDist2End2 = ptOnLine2.distanceTo(ptEnd);
double dDistWall2Pipe = 0.0, dDistWall2Pipe2 = 0.0;
AcGePoint3d ptTmp;
line.getClosestPointTo(ptStart, ptTmp, Adesk::kTrue);
dDistWall2Pipe = ptStart.distanceTo(ptTmp);
line.getClosestPointTo(ptStart, ptTmp, Adesk::kFalse);
dDistWall2Pipe2 = ptStart.distanceTo(ptTmp);
if (fabs(dLength - dDist2Start - dDist2End) < 0.001 && fabs(dLength - dDist2Start2 - dDist2End2) < 0.001)// 既是起始墙体 又是结束墙体
{
return true;
}
if (fabs(dLength - dDist2Start - dDist2End) < 0.001)// 起始墙体
{
if (vtLine.isEqualTo(vtWall))
{
dWallLen += ptEnd.distanceTo(ptOnLine1);
}
else
{
dWallLen += ptStart.distanceTo(ptOnLine1);
}
}
else if (fabs(dLength - dDist2Start2 - dDist2End2) < 0.001)// 结束墙体
{
if (vtLine.isEqualTo(vtWall))
{
dWallLen += ptStart.distanceTo(ptOnLine2);
}
else
{
dWallLen += ptEnd.distanceTo(ptOnLine2);
}
}
else if (fabs(dDistWall2Pipe - dDistWall2Pipe2) < 0.001)// 中间墙体
{
line.getClosestPointTo(ptStart, ptOnLine1);
dDist2Start = ptOnLine1.distanceTo(ptS);
dDist2End = ptOnLine1.distanceTo(ptE);
line.getClosestPointTo(ptEnd, ptOnLine2);
dDist2Start2 = ptOnLine2.distanceTo(ptS);
dDist2End2 = ptOnLine2.distanceTo(ptE);
if (fabs(dLen - dDist2Start - dDist2End) < 0.001 && fabs(dLen - dDist2Start2 - dDist2End2) < 0.001)
{
dWallLen += ptStart.distanceTo(ptEnd);
}
}
}
}
if (fabs(dWallLen - dLen) < dDist)
{
return true;
}
return false;
}
// 分别延长管线和墙体 求交点
bool UnfoldInstallSanitarySys::GetExtendPipe(std::map<double, LinkedLine> &mapLink, AcDbLine &line, const AcGePoint3d &pt, bool bExtend)
{
mapLink.clear();
double dDist = 0.0, dLen = 0.0, dDist1 = 0.0, dDist2 = 0.0;
AcGePoint3d ptOnLine, ptS, ptE, ptLineS, ptLineE;
AcGePoint3dArray arryPts;
std::vector<PipeData>::iterator itPipe;
ptLineS = line.startPoint();
ptLineE = line.endPoint();
ptLineE = Wcs2Ucs(ptLineE);
ptLineS = Wcs2Ucs(ptLineS);
AcGeVector3d vtWall = ptLineE - ptLineS, vtPipe;
vtWall.normalize();
for (itPipe = m_vecPipeData.begin(); itPipe != m_vecPipeData.end(); itPipe++)
{
if ((*itPipe).type != PipeType::eMainPipe || (*itPipe).pLine == NULL)
{
continue;
}
arryPts.setLogicalLength(0);
Acad::ErrorStatus es1, es2;
if (bExtend)
{
es1 = (*itPipe).pLine->intersectWith(&line, AcDb::kExtendBoth, arryPts);
}
else
{
// 只延长管线和 墙体本身 求交点
es2 = (*itPipe).pLine->intersectWith(&line, AcDb::kExtendThis, arryPts);
}
ptS = (*itPipe).pLine->startPoint();
ptE = (*itPipe).pLine->endPoint();
ptS = Wcs2Ucs(ptS);
ptE = Wcs2Ucs(ptE);
vtPipe = ptE - ptS;
vtPipe.normalize();
if (arryPts.length() == 1 && vtWall.isPerpendicularTo(vtPipe, m_tolVec))
{
ptOnLine = arryPts[0];
ptOnLine.z = 0;
dDist = 0.0;
ptS = (*itPipe).pLine->startPoint();
ptE = (*itPipe).pLine->endPoint();
dLen = ptS.distanceTo(ptE);
dDist1 = ptS.distanceTo(ptOnLine);
dDist2 = ptE.distanceTo(ptOnLine);
if (fabs(dLen - dDist1 - dDist2) < 0.001 && ptOnLine.distanceTo(ptS) > 0.001)// 与管线本身相交
{
dDist = ptOnLine.distanceTo(pt);
}
else// 与管线延长线相交
{
dDist = MAX_DIST;
}
LinkedLine WallData;
WallData.pLine = (*itPipe).pLine;
WallData.ptIntersect = ptOnLine;
WallData.nId = itPipe->nId;
mapLink.insert(std::make_pair(dDist, WallData));
}
}
if (mapLink.empty())
{
return false;
}
return true;
}
// 添加管线
void UnfoldInstallSanitarySys::AddPipeLine(const AcGePoint3d &ptS, const AcGePoint3d &ptE, PipeType type)
{
if (ptS.distanceTo(ptE) < 0.001)
{
return;
}
AcDbLine *pLine = new AcDbLine;
pLine->setStartPoint(ptS);
pLine->setEndPoint(ptE);
AcGePoint3d pt1 = ptS, pt2 = ptE;
AcGeVector3d vtX = AcGeVector3d::kXAxis;
AcGeVector3d vtY = AcGeVector3d::kYAxis;
AcGeVector3d vt = pt1 - pt2;
PipeData data;
if (vt.isParallelTo(vtX, m_tolVec))
{
data.drection = PipeDir::eParallelX;
}
else if (vt.isParallelTo(vtY, m_tolVec))
{
data.drection = PipeDir::eParallelY;
}
else
{
data.drection = PipeDir::eParallelX;
}
data.pLine = pLine;
data.type = type;
data.nId = m_nId++;
m_vecPipeData.push_back(data);
}
// 在XOY平面内与vtDir平行,并且在pt点的vtPipe方向的墙体
bool UnfoldInstallSanitarySys::GetIntersectWall( const AcGePoint3d &pt, const AcGeVector3d &vtDir, AcDbLine &line, AcGeVector3d &vtPipe, bool bExtend)
{
vtPipe.normalize();
AcGeVector3d vt = vtDir;
vt.z = 0.0;
std::vector<std::pair<XCurveSegment, XCurveSegment> > vecWall;
std::vector<std::pair<XCurveSegment, XCurveSegment> >::iterator it;
AcGeVector3d vtWall, vtLine;
AcDbLine lineWall;
AcGePoint3d ptOnLine, ptEnt = pt;
ptEnt.z = 0;
AcGeTol tolVec;
tolVec.setEqualVector(0.1);
for (it = m_vecWallSide.begin(); it != m_vecWallSide.end(); it++)
{
if (it->first.GetCurveType() == CURVE_LINE)
{
lineWall.setStartPoint(it->first.StartPoint());
lineWall.setEndPoint(it->first.EndPoint());
lineWall.getClosestPointTo(ptEnt, ptOnLine);
double dDist = ptEnt.distanceTo(ptOnLine);
ptOnLine.z = 0;
ptOnLine = Wcs2Ucs(ptOnLine);
AcGePoint3d ptSan = pt;
ptSan = Wcs2Ucs(ptSan);
vtLine = ptOnLine - ptSan;
vtLine.normalize();
vtLine.z = 0;
vtWall = Wcs2Ucs(it->first.StartPoint()) - Wcs2Ucs(it->first.EndPoint());
vtWall.z = 0.0;
if (vtWall.isParallelTo(vt, tolVec) && (vtLine.isEqualTo(vtPipe, tolVec)))
{
vecWall.push_back(*it);
}
}
}
// 找到距离pt最近的墙体
XCurveSegment segNear, segFar;
if (GetWallSide(pt, vecWall, segNear, segFar))
{
// 墙体厚度
AcGePoint3d ptS = segFar.StartPoint();
AcGePoint3d ptE = segFar.EndPoint();
ptS.z = 0.0;
ptE.z = 0.0;
AcDbLine lineTemp(ptS, ptE);
AcGePoint3d pt = segNear.StartPoint();
pt.z = 0.0;
AcGePoint3d ptPrj;
const double dDist = DocGetMeterUnitDim() ? 1.0 : 1000;
double dDistWall2San = 0.0;
if (lineTemp.getClosestPointTo(pt, ptPrj, Adesk::kTrue) == Acad::eOk)
{
double dWallThick = pt.distanceTo(ptPrj);
if (!bExtend)
{
// 墙体距离Pt点距离大于1000时,查找失败
lineTemp.getClosestPointTo(ptEnt, ptOnLine, Adesk::kTrue);
dDistWall2San = ptEnt.distanceTo(ptOnLine);
if (dDistWall2San - dWallThick / 2 > dDist + dWallThick * 0.5)
{
return false;
}
}
AcGeVector3d vt = pt - ptPrj;
vt.normalize();
line.setStartPoint(segFar.StartPoint() + vt * dWallThick * 0.5);
line.setEndPoint(segFar.EndPoint() + vt * dWallThick * 0.5);
return true;
}
}
return false;
}
// 设置起始管线
void UnfoldInstallSanitarySys::SetStartPipe(AcDbLine *pLine, AcGePoint3d &ptStart, const AcDbLine &line, AcGeVector3d &vtPer)
{
AcGePoint3d ptTmp;
if (line.getClosestPointTo(ptStart, ptTmp) != Acad::eOk)
{
return;
}
AcGeVector3d vt = ptStart - ptTmp;
vt.normalize();
AcGePoint3d ptEnd;
ptEnd = line.endPoint() + vt * ptStart.distanceTo(ptTmp);
if (!CheckPipePos(ptStart, ptEnd))
{
ptTmp = ptStart;
ptStart = ptStart + vt * m_dDistPipe2Wall;
ptEnd = ptEnd + vt * m_dDistPipe2Wall;
AddPipeLine(ptTmp, ptStart, PipeType::eMainPipe);
}
vtPer = vt;
pLine->setEndPoint(ptEnd);
pLine->setStartPoint(ptStart);
}
// 设置中间管线
void UnfoldInstallSanitarySys::SetMiddlePipe(AcGePoint3d &ptStart, AcGePoint3d &ptEnd, const AcDbLine &line, const std::vector<SanitaryNode> &vecNode, double dWidth, AcGePoint3d &ptPerS, AcGePoint3d &ptPerE, AcGeVector3d &vtPer)
{
AcGePoint3d ptS = line.startPoint();
AcGePoint3d ptE = line.endPoint();
AcGePoint3d ptOnLine;
bool bSeted = false;
AcGeVector3d vt;
std::vector<SanitaryNode>::const_iterator itSan;
// 根据墙体两侧是否有洁具 确定管线与墙体的位置(即管线安置在墙体有洁具的一侧)
for (itSan = vecNode.begin(); itSan != vecNode.end(); itSan++)
{
AcGePoint3d ptSan = (*itSan).pt;
ptSan.z = 0;
if (line.getClosestPointTo(ptSan, ptOnLine) == Acad::eOk && ptOnLine.distanceTo(ptSan) < m_dDistSearchWall)
{
AcGeVector3d vtLine = ptE - ptS;
vt = ptSan - ptOnLine;
vt.normalize();
if (vtLine.isPerpendicularTo(vt, m_tolVec))
{
OffSetPipe(ptS, ptE, vt, dWidth);
vtPer = vt;
bSeted = true;
break;
}
}
}
if (!bSeted)// 墙体两侧1000范围无洁具
{
// 和上游墙体平行时,按照上游偏移方向 偏移. 垂直时,向上游方向偏移
AcGeVector3d vtNor = ptE - ptS;
vt = ptPerE - ptPerS;
if (!vt.isParallelTo(vtNor, m_tolVec))
{
vtPer = -vt;
}
OffSetPipe(ptS, ptE, vtPer, dWidth);
}
ptStart = ptS;
ptEnd = ptE;
}
// 设置终止管线
void UnfoldInstallSanitarySys::SetEndPipe(AcDbLine *pLine, AcGePoint3d &ptEnd, const AcDbLine &line, double dWidth)
{
AcGePoint3d ptTmp;
ptEnd.z = 0;
if (line.getClosestPointTo(ptEnd, ptTmp) != Acad::eOk)
{
return;
}
AcGeVector3d vt = ptEnd - ptTmp;
AcGePoint3d ptStart;
ptStart = line.startPoint();
OffSetPipe(ptStart, ptTmp, vt, dWidth);
pLine->setEndPoint(ptTmp);
pLine->setStartPoint(ptStart);
}
// 从链表起点生成管网
void UnfoldInstallSanitarySys::CreatePipeFromStart(LinkNode *pNode, std::vector<LinkNode *> &vecNode)
{
LinkNode *pNodeNext = NULL;
if (NULL != pNode)
{
std::vector<LinkNode *>::iterator it;
if (pNode->m_vecNode.empty())
{
vecNode.push_back(pNode);
return;
}
for (it = pNode->m_vecNode.begin(); it != pNode->m_vecNode.end(); it++)
{
pNodeNext = *it;
CString sLayer = GetPipeLayer(m_sysPipe);
TDbPipe *pPipe = new TDbPipe();
XLine x;
x.SetStartPoint(pNode->ptCur);
x.SetEndPoint(pNodeNext->ptCur);
x.Make();
CreatePipeFromStart(pNodeNext, vecNode);
}
}
}
// 生成管线
void UnfoldInstallSanitarySys::CreatePipe()
{
std::vector<PipeData>::iterator it;
CString sLayer = GetPipeLayer(m_sysPipe);
InitPipeLayer(sLayer);
AcGePoint3d ptS, ptE;
for (it = m_vecPipeData.begin(); it != m_vecPipeData.end(); it++)
{
TDbPipe *pPipe = new TDbPipe();
ptS = it->pLine->startPoint();
ptE = it->pLine->endPoint();
ptS.z = m_dElev;
ptE.z = m_dElev;
pPipe->SetStartPoint(ptS);
pPipe->SetEndPoint(ptE);
pPipe->SetFlowDir(TPipeSys::kFromStart);
pPipe->SetDnDiameter(m_dPipeDn);
pPipe->setLayer(sLayer);
pPipe->SetSysType(GetPipeSysByLayer(sLayer));
AddToCurrentSpace(pPipe, Adesk::kTrue);
}
}
// 偏移管线
void UnfoldInstallSanitarySys::OffSetPipe(AcGePoint3d &ptS, AcGePoint3d &ptE, AcGeVector3d vt, double dWidth)
{
// 发生碰撞时,最多偏移2次
vt.normalize();
ptS = ptS + vt * (m_dDistPipe2Wall + dWidth);
ptE = ptE + vt * (m_dDistPipe2Wall + dWidth);
if (!CheckPipePos(ptS, ptE))
{
ptS = ptS + vt * m_dDistPipe2Wall;
ptE = ptE + vt * m_dDistPipe2Wall;
if (!CheckPipePos(ptS, ptE))
{
ptS = ptS + vt * m_dDistPipe2Wall;
ptE = ptE + vt * m_dDistPipe2Wall;
}
}
}
// 校准管线
void UnfoldInstallSanitarySys::ModifyPipe(std::vector<AcDbLine *> &vecLine, double dDist)
{
AcGePoint3dArray arryPts;
AcGePoint3d ptTmp, ptS, ptE;
AcGeVector3d vt;
int n = vecLine.size();
std::vector<AcDbLine *> vecNew;
std::vector<AcDbLine *>::iterator it;
it = vecLine.begin();
if ((*it) == NULL)
{
return;
}
AcDbLine *pLineFirst = NULL, *pLineSecond = NULL;
pLineFirst = *it;
it++;
while (it != vecLine.end())
{
arryPts.setLogicalLength(0);
if ((*it) == NULL || (*it)->startPoint().distanceTo((*it)->endPoint()) < (dDist + 200))
{
it = vecLine.erase(it);
continue;
}
pLineSecond = *it;
Acad::ErrorStatus es = pLineFirst->intersectWith(pLineSecond,AcDb::kExtendBoth, arryPts);
if (arryPts.length() == 1)
{
ptTmp = arryPts[0];
pLineFirst->setEndPoint(ptTmp);
pLineSecond->setStartPoint(ptTmp);
}
else if (pLineFirst->endPoint().distanceTo(pLineSecond->startPoint()) > 0.001)// 前后两根管线平行
{
ptS = pLineFirst->startPoint();
ptE = pLineFirst->endPoint();
ptS = Wcs2Ucs(ptS);
ptE = Wcs2Ucs(ptE);
double dDist2Pipe = GetDistLines(pLineFirst, pLineSecond);
if (dDist2Pipe - (200 - m_dDistPipe2Wall) < 0.001)// 平行管线距离小于80时,平移第二根对齐第一根管
{
ptE = Ucs2Wcs(ptE);
pLineSecond->getClosestPointTo(ptE, ptTmp, Adesk::kTrue);
pLineSecond->setStartPoint(ptE);
ptE = Wcs2Ucs(ptE);
ptTmp = Wcs2Ucs(ptTmp);
vt = ptE - ptTmp;
ptE = pLineSecond->endPoint();
ptE = Wcs2Ucs(ptE);
ptE += vt;
ptE = Ucs2Wcs(ptE);
pLineSecond->setEndPoint(ptE);
}
else
{
vt = ptE - ptS;
vt.normalize();
ptS = pLineSecond->startPoint();
pLineFirst->getClosestPointTo(ptS, ptE, Adesk::kTrue);
OffSetPipe(ptS, ptE, vt, dDist / 2);
pLineFirst->setEndPoint(ptE);
pLineSecond->setStartPoint(ptS);
AcDbLine *pLine = new AcDbLine;
pLine->setStartPoint(ptE);
pLine->setEndPoint(ptS);
vecNew.push_back(pLine);
}
}
pLineFirst = pLineSecond;
it++;
}
for (it = vecNew.begin(); it != vecNew.end(); it++)
{
if ((*it) == NULL || (*it)->startPoint().distanceTo((*it)->endPoint()) < 0.001)
{
continue;
}
vecLine.push_back(*it);
}
for (it = vecLine.begin(); it != vecLine.end();)
{
if ((*it) == NULL || (*it)->startPoint().distanceTo((*it)->endPoint()) < 0.001)
{
it = vecLine.erase(it);
}
else
{
it++;
}
}
}
// 判定管线位置是否合适
bool UnfoldInstallSanitarySys::CheckPipePos(const AcGePoint3d &ptS, const AcGePoint3d &ptE)
{
AcDbLine line(ptS, ptE);
if ((!PassParallelWall(ptS, ptE)) // 没有穿过平行墙体
&& !IsPassOtherSanitarySysPt(ptS, ptE) // 没有穿过其他系统洁具点
&& !IsCollidePipe(&line, m_dDistPipe2Pipe))// 没有与其他系统平行管线发生碰撞
{
return true;
}
return false;
}
// 给水管是立管时 确定主干方向
bool UnfoldInstallSanitarySys::ConfirmPipeDir(AcGeVector3d &vtPipe, const AcGePoint3d &ptSan, AcGeVector3d &vtDir)
{
AcGePoint3d ptS, ptE, pt = ptSan;
GetPipePoint(m_idPipe, ptS, ptE);
m_dElev = ptS.z;
ptE.z = 0;
ptS.z = 0;
ptE = Wcs2Ucs(ptE);
ptS = Wcs2Ucs(ptS);
pt.z = 0;
pt = Wcs2Ucs(pt);
AcGePoint3d ptX, ptY;
ptX.x = pt.x;
ptX.y = ptS.y;
ptX.z = 0;
ptY.x = ptS.x;
ptY.y = pt.y;
ptY.z = 0;
if (IsVertivalPipe(m_idPipe))// 立管
{
m_dElev = 0.0;
int nIndX = PassVertivalPipeNumByLine(ptS, ptX);
int nIndY = PassVertivalPipeNumByLine(ptS, ptY);
// 都经过立管或都不经过立管时
if ((nIndX > 0 && nIndY > 0) || (nIndX == 0 && nIndY == 0))
{
return false;
}
else if (nIndX > 0)
{
vtDir = ptY - ptS;
}
else
{
vtDir = ptX - ptS;
}
}
else// 直管
{
vtPipe = ptE - ptS;
if (vtPipe.isParallelTo(ptY - ptS, m_tolVec))
{
vtPipe = ptY - ptS;
}
else if (vtPipe.isParallelTo(ptX - ptS, m_tolVec))
{
vtPipe = ptX - ptS;
}
vtPipe.normalize();
vtDir = vtPipe.perpVector();
}
return true;
}
// 获取全部有用墙体边线,过滤掉厚度小于100的墙体
void UnfoldInstallSanitarySys::ModifyUsefulWall()
{
m_vecAllWallSide = m_vecWallSide;
m_vecWallSide.clear();
XCurveSegment segNear, segFar;
std::vector<std::pair<XCurveSegment, XCurveSegment> >::iterator it;
double dWallThick = 0.0;
const double dThick = DocGetMeterUnitDim() ? 0.07 : 70;
for (it = m_vecAllWallSide.begin(); it != m_vecAllWallSide.end(); it++)
{
segNear = it->first;
segFar = it->second;
// 墙体厚度
AcGePoint3d ptS = segFar.StartPoint();
AcGePoint3d ptE = segFar.EndPoint();
ptS.z = 0.0;
ptE.z = 0.0;
AcDbLine lineTemp(ptS, ptE);
AcGePoint3d pt = segNear.StartPoint();
pt.z = 0.0;
AcGePoint3d ptPrj;
if (lineTemp.getClosestPointTo(pt, ptPrj, Adesk::kTrue) == Acad::eOk)
{
dWallThick = pt.distanceTo(ptPrj);
if (dWallThick - dThick > 0.001)
{
m_vecWallSide.push_back(*it);
}
}
}
Entity ent;
PickSet ssWall(SS_FREE);
for(long i = 0; i < m_ssDoorWall.Length(); i++)
{
ent = m_ssDoorWall[i];
if (ent.Is(_T("TCH_Wall")))
{
OPENOBJ_BEGIN(ent, AcDb::kForRead, TDbWall, pWall);
if(pWall && pWall->GetWidth(4) - 100.0 < 0.001)
{
ssWall += ent;
}
OPENOBJ_END();
}
}
m_ssDoorWall -= ssWall;
}
// 获取距离点最近的墙体的中线
bool UnfoldInstallSanitarySys::GetWallMiddleLine(const AcGePoint3d &pt, AcDbLine &line)
{
XCurveSegment segNear, segFar;
if (!GetNearestWall(pt, m_dDistSearchWall, segNear, segFar))
{
return false;
}
AcGePoint3d ptS = segFar.StartPoint();
AcGePoint3d ptE = segFar.EndPoint();
ptS.z = 0.0;
ptE.z = 0.0;
AcDbLine lineTemp(ptS, ptE);
AcGePoint3d ptNear = segNear.StartPoint();
ptNear.z = 0.0;
AcGePoint3d ptPrj;
if (lineTemp.getClosestPointTo(ptNear, ptPrj, Adesk::kTrue) == Acad::eOk)
{
double dWallThick = ptNear.distanceTo(ptPrj);
AcGeVector3d vt = ptNear - ptPrj;
vt.normalize();
line.setStartPoint(segFar.StartPoint() + vt * dWallThick * 0.5);
line.setEndPoint(segFar.EndPoint() + vt * dWallThick * 0.5);
return true;
}
else
{
return false;
}
return false;
}
// 判断该ID是否存在于墙体链表中,若存在,则返回指向该节点的链表
bool UnfoldInstallSanitarySys::CheckWallInLst(const std::vector<WallData *> &vecNode, const AcDbObjectId &id, WallData *&pNodeFind)
{
pNodeFind = NULL;
std::vector<WallData *>::const_iterator it;
for (it = vecNode.begin(); it != vecNode.end(); it++)
{
if ((*it)->id == id)
{
pNodeFind = *it;
return true;
}
}
return false;
}
// 判断两个墙体节点之间是否有关联关系
bool UnfoldInstallSanitarySys::CheckRelation(WallData *pNode, WallData *pNodeFind)
{
for (int i = 0; i < pNode->lstNode.Length(); i++)
{
if (pNode->lstNode[i] == pNodeFind)
{
return true;
}
}
return false;
}
// 把墙体关系转换为链表
void UnfoldInstallSanitarySys::SetWallMap(PickSet &ss, WallData *&pNode, std::vector<WallData *> &vecNode)
{
if (NULL == pNode)
{
return;
}
AcGePoint3d ptS, ptE;
for (long l = 0; l < ss.Length(); l++)
{
Entity ent = ss[l];// 找出一个墙体
OPENOBJ_BEGIN(ent, AcDb::kForRead, TDbWall, pWall);
if(NULL != pWall)
{
ptS = pWall->StartPoint();
ptS.z = 0.0;
ptE = pWall->EndPoint();
ptE.z = 0.0;
if ((ptS.distanceTo(pNode->ptS) < 0.001 || ptS.distanceTo(pNode->ptE) < 0.001
|| ptE.distanceTo(pNode->ptS) < 0.001 || ptE.distanceTo(pNode->ptE) < 0.001)
&& (pWall->id() != pNode->id))
{
// 该墙体和当前链表节点相连
WallData *pNodeFind = NULL;
if (CheckWallInLst(vecNode, pWall->id(), pNodeFind))// 墙体在链表中
{
if (NULL != pNodeFind && pNodeFind->id != pNode->id)
{
// 检查关联是否存在,不存在则创建关联
if (!CheckRelation(pNode, pNodeFind))
{
pNode->lstNode.Append(pNodeFind);
}
if (!CheckRelation(pNodeFind, pNode))
{
pNodeFind->lstNode.Append(pNode);
}
}
continue;
}
// 墙体不在链表中,创建新节点
WallData *pNewNode = new WallData;
pNewNode->dWidth = pWall->GetWidth(4);
pNewNode->id = pWall->id();
pNewNode->ptE = ptE;
pNewNode->ptS = ptS;
pNewNode->nNum = pWall->GetOpeningIdList().Length();
pNode->lstNode.Append(pNewNode);
pNewNode->lstNode.Append(pNode);
vecNode.push_back(pNewNode);
SetWallMap(ss, pNewNode, vecNode);
}
}
OPENOBJ_END();
}
}
// 查找该节点到最近主干的所有路径
void UnfoldInstallSanitarySys::GetBranchRoad(WallData *pNode, std::map<double, std::vector<WallData *> > &mapRoad, std::vector<WallData *> &vecRoad, double dLen, WallData *pNodePre = NULL)
{
if (NULL != pNode)
{
WallData *pNextNode = NULL;
std::vector<WallData *> vecRef;
// 排除掉该节点的父节点及兄弟节点
std::vector<WallData *> vecCheck = vecRoad;
if (NULL != pNodePre)
{
for (int j = 0; j < pNodePre->lstNode.Length(); j++)
{
vecCheck.push_back(pNodePre->lstNode[j]);
}
}
double dDist = 0.0;
for (int i = 0; i < pNode->lstNode.Length(); i++)
{
vecRef = vecRoad;
dDist = dLen;
pNextNode = pNode->lstNode[i];
if (NULL == pNextNode)
{
continue;
}
WallData *pNodeFind = NULL;
if (CheckWallInLst(m_vecRoad, pNextNode->id, pNodeFind))// 当前节点为主干墙体时,存储路径
{
vecRoad = vecRef;
dLen = dDist;
mapRoad.insert(std::make_pair(dLen, vecRoad));
break;
}
if (CheckWallInLst(vecCheck, pNextNode->id, pNodeFind))
{
continue;
}
dDist += pNextNode->ptS.distanceTo(pNextNode->ptE);
vecRef.push_back(pNextNode);
GetBranchRoad(pNextNode, mapRoad, vecRef, dDist, pNode);
}
}
}
// 获取起始墙体到终止墙体之间的所有路径
void UnfoldInstallSanitarySys::GetRoad(WallData *pNode, const AcDbObjectId &idEnd, std::map<double, std::vector<WallData *> > &mapRoad, std::vector<WallData *> vecRoad, double dLen, WallData *pNodePre = NULL)
{
if (NULL != pNode)
{
WallData *pNextNode = NULL;
std::vector<WallData *> vecRef;
// 排除掉该节点的父节点及兄弟节点
std::vector<WallData *> vecCheck = vecRoad;
if (NULL != pNodePre)
{
for (int j = 0; j < pNodePre->lstNode.Length(); j++)
{
vecCheck.push_back(pNodePre->lstNode[j]);
}
}
double dDist = 0.0;
for (int i = 0; i < pNode->lstNode.Length(); i++)
{
vecRef = vecRoad;
dDist = dLen;
pNextNode = pNode->lstNode[i];
if (NULL == pNextNode)
{
continue;
}
if (pNextNode->id == idEnd)// 当前节点为终止墙体时,存储路径
{
vecRef.push_back(pNextNode);
vecRoad = vecRef;
dDist += pNextNode->ptS.distanceTo(pNextNode->ptE);
dLen = dDist;
mapRoad.insert(std::make_pair(dLen, vecRoad));
break;
}
WallData *pNodeFind = NULL;
if (CheckWallInLst(vecCheck, pNextNode->id, pNodeFind))
{
continue;
}
dDist += pNextNode->ptS.distanceTo(pNextNode->ptE);
vecRef.push_back(pNextNode);
GetRoad(pNextNode, idEnd, mapRoad, vecRef, dDist, pNode);
}
}
}
// 获得路径的转折点总数
int UnfoldInstallSanitarySys::GetTurnNum(const std::vector<WallData *> &vecPt)
{
if (vecPt.size() < 2)
{
return 0;
}
int nNum = 0;
std::vector<WallData *>::const_iterator it = vecPt.begin();
AcGeVector3d vt1 = (*it)->ptS - (*it)->ptE, vt2;
it++;
while (it != vecPt.end())
{
vt2 = (*it)->ptS - (*it)->ptE;
if (!vt1.isParallelTo(vt2))
{
nNum++;
}
vt1 = vt2;
it++;
}
return nNum;
}
// 根据路径长度和转折点数量 取得最短路径
void UnfoldInstallSanitarySys::GetShortestRoad(std::map<double, std::vector<WallData *> > &mapRoad, std::vector<WallData *> &vecRoad)
{
std::map<double, std::vector<WallData *> >::iterator itMap = mapRoad.begin();
double dLen = (*itMap++).first;
const double dDist = DocGetMeterUnitDim() ? 0.20 : 200;
if (mapRoad.size() > 1)
{
while ((*itMap).first - dLen < dDist && itMap != mapRoad.end())
{
itMap++;
}
}
mapRoad.erase(itMap, mapRoad.end());
std::map<double, std::vector<WallData *> > mapSorted;
for (itMap = mapRoad.begin(); itMap != mapRoad.end(); itMap++)
{
double dNum = GetTurnNum((*itMap).second);
mapSorted.insert(std::make_pair(dNum, (*itMap).second));
}
itMap = mapSorted.begin();
vecRoad = (*itMap).second;
}
// 用墙体的起点和终点 获取墙体ID
bool UnfoldInstallSanitarySys::GetWallId(const std::vector<WallData *> &vecWall, const AcDbLine &line, AcDbObjectId &id)
{
std::vector<WallData *>::const_iterator it;
XPoint ptS, ptE;
ptS = line.startPoint();
ptE = line.endPoint();
const double dDist = DocGetMeterUnitDim() ? 0.35 : 350;
for (it = vecWall.begin(); it != vecWall.end(); it++)
{
if (*it == NULL)
{
continue;
}
if (((*it)->ptS.distanceTo(ptS) - dDist < 0.001 && (*it)->ptE.distanceTo(ptE) - dDist < 0.001)
|| ((*it)->ptS.distanceTo(ptE) - dDist < 0.001 && (*it)->ptE.distanceTo(ptS) - dDist < 0.001))
{
id = (*it)->id;
return true;
}
}
return false;
}
// 查找距离该墙体最近的主干管
bool UnfoldInstallSanitarySys::GetBranchWallRoad(AcDbLine &line, std::vector<WallData *> &vecRoad)
{
AcDbObjectId idStart;
AcGePoint3d ptS = line.startPoint();
AcGePoint3d ptE = line.endPoint();
std::vector<WallData *> vecAllRoad = m_vecAllWall;
if (!GetWallId(vecAllRoad, line, idStart))
{
return false;
}
WallData *pNodeS = NULL;
if (CheckWallInLst(m_vecRoad, idStart, pNodeS))
{
return false;
}
if (!CheckWallInLst(vecAllRoad, idStart, pNodeS))
{
return false;
}
vecRoad.clear();
vecRoad.push_back(pNodeS);
std::map<double, std::vector<WallData *> > mapRoad;
double dLen = 0.0;
GetBranchRoad(pNodeS, mapRoad, vecRoad, dLen);
GetShortestRoad(mapRoad, vecRoad);
ModifyRoad(vecRoad);
return true;
}
// 获取两个墙体之间的最短路径 并初始化墙体节点结构
bool UnfoldInstallSanitarySys::GetWallRoad(AcDbLine &lineStart, AcDbLine &lineEnd, std::vector<WallData *> &vecRoad)
{
Entity ent;
PickSet ssWall(SS_FREE);
for(long i = 0; i < m_ssDoorWall.Length(); i++)// 获取所有上华墙体
{
ent = m_ssDoorWall[i];
if (ent.Is(_T("TCH_Wall")))
{
ssWall += ent;
}
}
ent = ssWall[0l];
WallData *pNode = new WallData;
OPENOBJ_BEGIN(ent, AcDb::kForRead, TDbWall, pWall);
if(pWall)
{
pNode->dWidth = pWall->GetWidth(4);
pNode->id = pWall->id();
pNode->ptE = pWall->GetEndPoint();
pNode->ptE.z = 0.0;
pNode->ptS = pWall->GetStartPoint();
pNode->ptS.z = 0.0;
pNode->nNum = pWall->GetOpeningIdList().Length();
}
OPENOBJ_END();
std::vector<WallData *> vecNode;
vecNode.push_back(pNode);
SetWallMap(ssWall, pNode, vecNode);// 初始化墙体节点结构
AcDbObjectId idStart, idEnd;
if (!GetWallId(vecNode, lineEnd, idEnd) || !GetWallId(vecNode, lineStart, idStart))
{
return false;
}
m_vecAllWall = vecNode;
WallData *pNodeS = NULL;
if (!CheckWallInLst(vecNode, idStart, pNodeS))
{
return false;
}
vecRoad.clear();
vecRoad.push_back(pNodeS);
if (idStart == idEnd)// 系统只有一个墙体
{
return true;
}
std::map<double, std::vector<WallData *> > mapRoad;
double dLen = 0.0;
GetRoad(pNodeS, idEnd, mapRoad, vecRoad, dLen);
vecRoad.clear();
GetShortestRoad(mapRoad, vecRoad);
// 获取不到路径
if (vecRoad.front()->id != pNodeS->id || vecRoad.back()->id != idEnd)
{
return false;
}
ModifyRoad(vecRoad);
vecNode.clear();
return true;
}
// 校准墙体路径的起点到终点顺序
void UnfoldInstallSanitarySys::ModifyRoad(std::vector<WallData *> &vecRoad)
{
AcGePoint3d ptS, ptE, ptS2, ptE2;
std::vector<WallData *>::iterator it = vecRoad.begin();
ptS = (*it)->ptS;
ptE = (*it)->ptE;
while (++it != vecRoad.end())
{
ptS2 = (*it)->ptS;
ptE2 = (*it)->ptE;
if (ptS.distanceTo(ptS2) < 0.001)
{
it--;
(*it)->ptS = ptE;
(*it)->ptE = ptS;
it++;
}
else if (ptS.distanceTo(ptE2) < 0.001)
{
it--;
(*it)->ptS = ptE;
(*it)->ptE = ptS;
it++;
(*it)->ptS = ptE2;
(*it)->ptE = ptS2;
}
else if (ptE.distanceTo(ptE2) < 0.001)
{
(*it)->ptS = ptE2;
(*it)->ptE = ptS2;
}
ptS = ptS2;
ptE = ptE2;
}
}
// 设定管线标高
void UnfoldInstallSanitarySys::ModifyPipeElve()
{
UnfoldInstallAdjustElevation Elev;
Elev.SetLinkNode(m_pNodeStart);
Elev.SetFeedElevation(1.0);
Elev.SetFeedPipe(m_idPipe);
Elev.SetSanitaryPt(m_mapSanPt);
Elev.SetPipeSysType(m_sysPipe);
Elev.AdjustElevation();
}
// 从交点处打断管线,构造管网
void UnfoldInstallSanitarySys::SetLinkableNode()
{
std::vector<PipeData>::iterator it;
std::vector<PipeData>::iterator itCheck;
std::map<double, AcGePoint3d>::iterator itMap;
std::vector<AcDbLine *> vecLine;// 保存打断后的管线
// 打断连接有多个分支的管线
AcDbLine *pLine = NULL, *pLineCheck = NULL;
AcGePoint3d ptCheck, ptOnLine;
for (it = m_vecPipeData.begin(); it != m_vecPipeData.end(); it++)
{
std::map<double, AcGePoint3d> mapPts;
pLine = it->pLine;
for (itCheck = m_vecPipeData.begin(); itCheck != m_vecPipeData.end(); itCheck++)
{
pLineCheck = itCheck->pLine;
ptCheck = pLineCheck->startPoint();
pLine->getClosestPointTo(ptCheck, ptOnLine);
if (ptCheck.distanceTo(ptOnLine) < 0.01 && ptOnLine.distanceTo(pLine->startPoint()) > 0.01 && ptOnLine.distanceTo(pLine->endPoint()) > 0.01)
{
mapPts.insert(std::make_pair(pLine->startPoint().distanceTo(ptOnLine), ptOnLine));
}
}
if (mapPts.size() > 0)
{
itMap = mapPts.begin();
ptCheck = itMap->second;
AcGePoint3d ptEnd = pLine->endPoint();
pLine->setEndPoint(ptCheck);
itMap++;
for (; itMap != mapPts.end(); itMap++)
{
AcDbLine *pLineNew = new AcDbLine;
pLineNew->setStartPoint(ptCheck);
pLineNew->setEndPoint(itMap->second);
vecLine.push_back(pLineNew);
ptCheck = itMap->second;
}
AcDbLine *pLineEnd = new AcDbLine;
pLineEnd->setStartPoint(ptCheck);
pLineEnd->setEndPoint(ptEnd);
vecLine.push_back(pLineEnd);
}
}
std::vector<AcDbLine *>::iterator itLine;
for (itLine = vecLine.begin(); itLine != vecLine.end(); itLine++)
{
if ((*itLine)->startPoint().distanceTo((*itLine)->endPoint()) < 0.001)
{
continue;
}
AddPipeLine((*itLine)->startPoint(), (*itLine)->endPoint(), PipeType::eMainPipe);
}
std::vector<LinkNode *> vecNode;
GetNodeLst(vecNode);
ModifyNode(vecNode);
//CreatePipeFromStart(m_pNodeStart, vecNode);
ModifyPipeElve();// 设定管线标高
}
// 校准标高点
void UnfoldInstallSanitarySys::ModifyNode(std::vector<LinkNode *> &vecNode)
{
m_pNodeStart = vecNode.front();
while (m_pNodeStart->pPreNode != NULL)
{
m_pNodeStart = m_pNodeStart->pPreNode;
}
m_pNodeStart->type = Point_Feed;
std::vector<LinkNode *>::iterator itNode;
std::vector<LinkNode *>::iterator itN;
std::vector<LinkNode *> vecEnd;
LinkNode *pNode = NULL, *pNodePer = NULL, *pNodeNext = NULL;
AcGeVector3d vtPer, vtNext;
// 设定各个点的属性
for (itNode = vecNode.begin(); itNode != vecNode.end(); )
{
if ((*itNode)->m_vecNode.empty())
{
(*itNode)->type = Point_Sanitary;
if ((*itNode)->ptCur.z > 1.0)
{
(*itNode)->ptCur.z = 0;
}
if (m_nInstallType == 1)
{
(*itNode)->type = (*itNode)->type | Point_KW;
}
else if (m_nInstallType == 0)
{
(*itNode)->pPreNode->type = Point_Int | Point_KW;
}
vecEnd.push_back(*itNode);
}
pNode = *itNode;
pNodePer = pNode->pPreNode;
if (pNodePer != NULL && pNode->m_vecNode.size() == 1)
{
pNodeNext = pNode->m_vecNode.front();
vtPer = pNodePer->ptCur - pNode->ptCur;
vtNext = pNode->ptCur - pNodeNext->ptCur;
if (vtNext.isParallelTo(vtPer, m_tolVec))
{
pNodeNext->pPreNode = pNodePer;
for (itN = pNodePer->m_vecNode.begin(); itN != pNodePer->m_vecNode.end(); itN++)
{
if ((*itN) == pNode)
{
break;
}
}
pNodePer->m_vecNode.erase(itN);
pNodePer->m_vecNode.push_back(pNodeNext);
itNode = vecNode.erase(itNode);
}
else
{
itNode++;
}
}
else
{
itNode++;
}
}
}
// 根据管线构造管网
void UnfoldInstallSanitarySys::GetNodeLst(std::vector<LinkNode *> &vecNode)
{
std::vector<PipeData>::iterator it;
std::vector<PipeData>::iterator itCheck;
AcDbLine *pLine = NULL, *pLineCheck = NULL;
for (it = m_vecPipeData.begin(); it != m_vecPipeData.end(); it++)
{
pLine = it->pLine;
LinkNode *pNodeS = NULL, *pNodeE = NULL, *pNodePer = NULL, *pNodeNext = NULL, *pNodeFind = NULL;
// 获取起始节点
if (!CheckPtInLst(vecNode, pNodeS, pLine->startPoint()))
{
pNodeS = new LinkNode;
pNodeS->ptCur = pLine->startPoint();
pNodeS->type = Point_Int;
pNodeS->pPreNode = NULL;
vecNode.push_back(pNodeS);
}
// 获取终止节点
if (!CheckPtInLst(vecNode, pNodeE, pLine->endPoint()))
{
pNodeE = new LinkNode;
pNodeE->ptCur = pLine->endPoint();
pNodeE->type = Point_Int;
vecNode.push_back(pNodeE);
}
pNodeE->pPreNode = pNodeS;
if (!CheckPtInLst(pNodeS->m_vecNode, pNodeFind, pNodeE->ptCur))
{
pNodeS->m_vecNode.push_back(pNodeE);
}
for (itCheck = m_vecPipeData.begin(); itCheck != m_vecPipeData.end(); itCheck++)
{
if (it->nId == itCheck->nId)
{
continue;
}
pLineCheck = itCheck->pLine;
// 根据管线起点 设定其前节点
if (pNodeS->ptCur.distanceTo(pLineCheck->endPoint()) < 0.01)
{
if (!CheckPtInLst(vecNode, pNodePer, pLineCheck->startPoint()))
{
pNodePer = new LinkNode;
pNodePer->ptCur = pLineCheck->startPoint();
pNodePer->type = Point_Int;
pNodePer->pPreNode = NULL;
pNodePer->m_vecNode.push_back(pNodeS);
vecNode.push_back(pNodePer);
}
else if (!CheckPtInLst(pNodePer->m_vecNode, pNodeFind, pNodeS->ptCur))
{
pNodePer->m_vecNode.push_back(pNodeS);
}
pNodeS->pPreNode = pNodePer;
}
else if (pNodeE->ptCur.distanceTo(pLineCheck->startPoint()) < 0.01)// 根据管线终点 设定其后续节点
{
if (!CheckPtInLst(vecNode, pNodeNext, pLineCheck->endPoint()))
{
pNodeNext = new LinkNode;
pNodeNext->ptCur = pLineCheck->endPoint();
pNodeNext->type = Point_Int;
pNodeE->m_vecNode.push_back(pNodeNext);
vecNode.push_back(pNodeNext);
}
else if (!CheckPtInLst(pNodeE->m_vecNode, pNodeFind, pNodeNext->ptCur))
{
pNodeE->m_vecNode.push_back(pNodeNext);
}
pNodeNext->pPreNode = pNodeE;
}
}
}
}
// 判断点是否在链表中,若在 ,返回该节点
bool UnfoldInstallSanitarySys::CheckPtInLst(std::vector<LinkNode *> &vecNode, LinkNode *&pNode, AcGePoint3d pt)
{
std::vector<LinkNode *>::iterator it;
AcGePoint3d ptCur;
for (it = vecNode.begin(); it != vecNode.end(); it++)
{
ptCur = (*it)->ptCur;
if (ptCur.distanceTo(pt) < 0.01)
{
pNode = *it;
return true;
}
}
return false;
}