2330 lines
59 KiB
C++
2330 lines
59 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;
|
|
} |