1620 lines
40 KiB
C++
1620 lines
40 KiB
C++
#include "StdAfx.h"
|
|
#include "ConcealInstallSanitarySys.h"
|
|
|
|
#define OFFSET_TIME 4 // 管线偏移次数
|
|
|
|
ConcealInstallSanitarySys::ConcealInstallSanitarySys()
|
|
{
|
|
m_dVPipeEle = DocGetMeterUnitDraw() ? 2.6 : 2600;
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::AutoLinkSanitary( const SanitarySysData &data )
|
|
{
|
|
m_dPipeDn = GetPipeDn(data.id);
|
|
m_sysPipe = data.type;
|
|
m_idPipe = data.id;
|
|
InitWallEnt();
|
|
// 独立洁具
|
|
if (IsSingleSanitary(data))
|
|
{
|
|
LinkSingleSanitary(data);
|
|
return;
|
|
}
|
|
|
|
// 将洁具按距离给水点远近排序
|
|
SanitarySysData sanData = data;
|
|
std::vector<SanitaryNode> &vecSanNode = sanData.vecSanitaryNode;
|
|
Sort(vecSanNode, sanData.pt);
|
|
// 按洁具点距给水点远近连接洁具
|
|
LinkSanitary(sanData);
|
|
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::IsSingleSanitary( const SanitarySysData &data )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::LinkSingleSanitary( const SanitarySysData &data )
|
|
{
|
|
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::LinkSanitary(const SanitarySysData &data)
|
|
{
|
|
// 获得最远洁具给水点 洁具id
|
|
std::vector<SanitaryNode> vecNode = data.vecSanitaryNode;
|
|
std::vector<SanitaryNode>::iterator it = vecNode.begin();
|
|
AcGePoint3d ptSan = it->pt;
|
|
AcDbObjectId idSan = it->idSanitary;
|
|
vecNode.erase(it);
|
|
// 确定X轴Y轴
|
|
ComfirmXAxisYAxis(data.id);
|
|
|
|
bool bSuccess = true;
|
|
if (IsVertivalPipe(data.id)) // 给水管是立管
|
|
{
|
|
// 给水管为立管时,设置给水点高度
|
|
m_ptFeed = data.pt;
|
|
m_ptFeed.z = m_dVPipeEle;
|
|
bSuccess = SelectMainPipeFromVPipe(m_ptFeed, ptSan, data.id, idSan);
|
|
}
|
|
else // 给水管是非立管
|
|
{
|
|
m_ptFeed = data.pt;
|
|
bSuccess = SelectMainPipeFromPipe(data.pt, ptSan, data.id, idSan);
|
|
}
|
|
|
|
if (!bSuccess)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 按距离远近依次连接洁具
|
|
it = vecNode.begin();
|
|
while(it != vecNode.end())
|
|
{
|
|
LinkSanitary(it->pt, it->idSanitary);
|
|
it++;
|
|
}
|
|
|
|
// 生成管线
|
|
CreatePipe();
|
|
// 添加附件
|
|
InsertFeedEquip();
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::LinkSanitary( const AcGePoint3d &pt, const AcDbObjectId &idSan )
|
|
{
|
|
// 通过延长管线直接连接洁具
|
|
if (LinkSanitaryByExtendedPipe(pt, idSan))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 洁具直接连接最近的管线
|
|
LinkDate data;
|
|
data.ptSan = pt;
|
|
data.idSan = idSan;
|
|
data.nTransformTime = 0;
|
|
data.bInWall = false;
|
|
ModifyLinkSanPt(data);
|
|
if (GetLinkData(data))
|
|
{
|
|
LinkDate data1;
|
|
data1.ptSan = pt;
|
|
data1.idSan = idSan;
|
|
data1.nTransformTime = 1;
|
|
data1.bInWall = false;
|
|
ModifyLinkSanPt(data1);
|
|
if (GetLinkData(data1))
|
|
{
|
|
// 通过比较直接连接和一次变换连接的管线长度取近者连接
|
|
if (data.dLinkLen < data1.dLinkLen)
|
|
{
|
|
LinkSanitary2Pipe(data);
|
|
}
|
|
else
|
|
{
|
|
LinkSanitary2Pipe(data1);
|
|
}
|
|
}
|
|
else // 直接连接洁具与管线
|
|
{
|
|
LinkSanitary2Pipe(data);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// 变换一次连接洁具
|
|
LinkDate data1;
|
|
data1.ptSan = pt;
|
|
data1.idSan = idSan;
|
|
data1.nTransformTime = 1;
|
|
data1.bInWall = false;
|
|
ModifyLinkSanPt(data1);
|
|
if (GetLinkData(data1))
|
|
{
|
|
LinkSanitary2Pipe(data1);
|
|
return;
|
|
}
|
|
|
|
// 变换两次连接洁具
|
|
LinkDate data2;
|
|
data2.ptSan = pt;
|
|
data2.idSan = idSan;
|
|
data2.nTransformTime = 2;
|
|
data2.bInWall = false;
|
|
ModifyLinkSanPt(data2);
|
|
if (GetLinkData(data2))
|
|
{
|
|
LinkSanitary2Pipe(data2);
|
|
return;
|
|
}
|
|
acutPrintf(_T("\n洁具不能连接!"));
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::LinkSanitary( const AcGePoint3d &ptSan, const AcGePoint3d &ptFeed, const AcDbObjectId &idSan, PipeType type, bool bInSanPtWall, const AcGePoint3d &ptWall )
|
|
{
|
|
if (IsSanitaryPtEleSamePipe(idSan)) // 洁具给水点标高随支管标高
|
|
{
|
|
if (bInSanPtWall)
|
|
{
|
|
AcGePoint3d ptPrj = ptWall;
|
|
if (ptPrj.distanceTo(ptSan) > 0.001) // 洁具点在墙外
|
|
{
|
|
// 转换为真正的洁具点和墙体投影点
|
|
AcGePoint3d ptSanTemp = ptWall;
|
|
ptSanTemp.z = ptFeed.z;
|
|
CreateVirtualPipe(ptFeed, ptSanTemp, type);
|
|
m_mapSan.insert(std::make_pair(idSan, ptSanTemp));
|
|
}
|
|
else // 洁具点在墙内
|
|
{
|
|
AcGePoint3d ptTemp = ptSan;
|
|
ptTemp.z = ptFeed.z;
|
|
CreateVirtualPipe(ptFeed, ptTemp, type);
|
|
m_mapSan.insert(std::make_pair(idSan, ptTemp));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AcGePoint3d ptTemp = ptSan;
|
|
ptTemp.z = ptFeed.z;
|
|
CreateVirtualPipe(ptFeed, ptTemp, type);
|
|
m_mapSan.insert(std::make_pair(idSan, ptTemp));
|
|
}
|
|
}
|
|
else // 指定给水点标高
|
|
{
|
|
// 暗装时,得到给水点到最近墙上的投影点
|
|
if (bInSanPtWall)
|
|
{
|
|
AcGePoint3d ptPrj = ptWall;
|
|
// 转换为真正的洁具点和墙体投影点
|
|
ptPrj = ptSan;
|
|
AcGePoint3d ptSanTemp = ptWall;
|
|
|
|
ptPrj.z = ptFeed.z;
|
|
CreateVirtualPipe(ptFeed, ptPrj, type);
|
|
// 扣弯
|
|
AcGePoint3d pt = ptPrj;
|
|
pt.z = GetSanitaryPtEle(idSan); // 给水点标高
|
|
CreateVirtualPipe(ptPrj, pt, eVertival);
|
|
|
|
// 连接洁具
|
|
ptSanTemp.z = pt.z;
|
|
ptPrj.z = pt.z;
|
|
CreateVirtualPipe(ptPrj, ptSanTemp, eSmallPipe);
|
|
m_mapSan.insert(std::make_pair(idSan, ptSanTemp));
|
|
}
|
|
else // 找不到墙体时直接连接
|
|
{
|
|
AcGePoint3d ptSanTemp = ptSan;
|
|
ptSanTemp.z = ptFeed.z;
|
|
CreateVirtualPipe(ptFeed, ptSanTemp, type);
|
|
AcGePoint3d ptTemp = ptSan;
|
|
ptTemp.z = GetSanitaryPtEle(idSan);
|
|
CreateVirtualPipe(ptSanTemp, ptTemp, eVertival);
|
|
m_mapSan.insert(std::make_pair(idSan, ptTemp));
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::LinkSanitaryByExtendedPipe( const AcGePoint3d &ptSan, const AcDbObjectId &idSan )
|
|
{
|
|
// 获得所有可被延长的管线
|
|
std::vector<PipeData>::iterator it;
|
|
AcGePoint3d ptTemp = ptSan, ptPrj;
|
|
AcDbLine *pLine = NULL;
|
|
PipeType type;
|
|
for(it = m_vecPipeData.begin(); it != m_vecPipeData.end(); it++)
|
|
{
|
|
pLine = it->pLine;
|
|
if (pLine == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
type = it->type;
|
|
if (type != eMainPipe && type != eBranch
|
|
&& type != eSmallPipe && type != eBranch2)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ptTemp.z = pLine->startPoint().z;
|
|
if (pLine->getClosestPointTo(ptTemp, ptPrj, Adesk::kTrue) == Acad::eOk)
|
|
{
|
|
if (ptTemp.distanceTo(ptPrj) > 0.001) // 不在直线内或其延长线上
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// 洁具点标高
|
|
double dSanEle = 0.0;
|
|
if (IsSanitaryPtEleSamePipe(idSan)) // 随支管
|
|
{
|
|
dSanEle = pLine->startPoint().z;
|
|
}
|
|
else // 指定标高
|
|
{
|
|
dSanEle = GetSanitaryPtEle(idSan);
|
|
}
|
|
|
|
// 延长小支管连接洁具时,扣弯需要产生在墙体内
|
|
if (type == eSmallPipe)
|
|
{
|
|
//当洁具点在墙外时,需安装洁具
|
|
AcGePoint3d ptWall;
|
|
AcGeVector3d vtDir;
|
|
if (GetSanitaryDir(vtDir, idSan) && GetPtInWall(ptWall, ptTemp, vtDir) && ptWall.distanceTo(ptTemp) > 0.001)
|
|
{
|
|
ptWall.z = pLine->startPoint().z;
|
|
AcGePoint3d ptWallPrj;
|
|
if (pLine->getClosestPointTo(ptWall, ptWallPrj, Adesk::kTrue) == Acad::eOk
|
|
&& ptWall.distanceTo(ptWallPrj) < 0.001)
|
|
{
|
|
// 修改管线使之延伸到洁具点
|
|
ExtendLine(pLine, ptWallPrj);
|
|
// 连接洁具
|
|
ptWall.z = dSanEle;
|
|
CreateVirtualPipe(ptWallPrj, ptWall, eVertival);
|
|
ptTemp = ptSan;
|
|
ptTemp.z = dSanEle;
|
|
CreateVirtualPipe(ptWall, ptTemp, eSmallPipe);
|
|
m_mapSan.insert(std::make_pair(idSan, ptTemp));
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 修改管线使之延伸到洁具点
|
|
ExtendLine(pLine, ptPrj);
|
|
// 连接洁具
|
|
ptTemp = ptSan;
|
|
ptTemp.z = dSanEle;
|
|
LinkSanitary(ptTemp, ptPrj, idSan, eSmallPipe, false, AcGePoint3d());
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::PipeParallelXorYAxis( const AcDbObjectId &idPipe )
|
|
{
|
|
AcGeVector3d vtDir;
|
|
TDbPipe *pPipe = NULL;
|
|
acdbOpenObject(pPipe, idPipe, AcDb::kForRead);
|
|
if (pPipe != NULL)
|
|
{
|
|
vtDir = pPipe->StartPoint() - pPipe->EndPoint();
|
|
vtDir.z = 0.0;
|
|
pPipe->close();
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (vtDir.isParallelTo(m_vtXAxis) || vtDir.isParallelTo(m_vtYAxis))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::Sort( std::vector<SanitaryNode> &data, const AcGePoint3d &pt )
|
|
{
|
|
// 计算洁具点与给水点在XOY平面内的距离
|
|
std::map<double, SanitaryNode> mapDist;
|
|
std::vector<SanitaryNode>::iterator it;
|
|
AcGePoint3d pt1 = pt, pt2;
|
|
pt1.z = 0.0;
|
|
for (it = data.begin(); it != data.end(); it++)
|
|
{
|
|
pt2 = it->pt;
|
|
pt2.z = 0.0;
|
|
mapDist.insert(std::make_pair(pt1.distanceTo(pt2), *it));
|
|
}
|
|
|
|
// 按由大到小排序
|
|
data.clear();
|
|
std::map<double,SanitaryNode>::reverse_iterator itR;
|
|
for (itR = mapDist.rbegin(); itR != mapDist.rend(); itR++)
|
|
{
|
|
data.push_back(itR->second);
|
|
}
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::SetFeedPointEle( double dEle )
|
|
{
|
|
m_dVPipeEle = dEle;
|
|
if (!DocGetCurMeterUnitDraw())
|
|
{
|
|
m_dVPipeEle *= 1000;
|
|
}
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::SelectMainPipeFromVPipe( const AcGePoint3d &ptWater, const AcGePoint3d &ptSan, const AcDbObjectId &idPipe, const AcDbObjectId &idSan )
|
|
{
|
|
// 确定主干管位置
|
|
LinkDate data;
|
|
data.ptLink = ptWater;
|
|
data.ptSan = ptSan;
|
|
data.idSan = idSan;
|
|
data.bInWall = false;
|
|
ModifyLinkSanPt(data);
|
|
if (!ConfirmMianPipePosFromVPipe(data, idPipe))
|
|
{
|
|
return false;
|
|
}
|
|
// 连接主干管
|
|
return LinkMainPipe(data);
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::SelectMainPipeFromPipe( const AcGePoint3d &ptWater, const AcGePoint3d &ptSan, const AcDbObjectId &idPipe, const AcDbObjectId &idSan )
|
|
{
|
|
// 给水管方向
|
|
AcGeVector3d vtPipeDir = m_vtXAxis;
|
|
TDbPipe *pPipe = NULL;
|
|
acdbOpenObject(pPipe, m_idPipe, AcDb::kForRead);
|
|
if (pPipe != NULL)
|
|
{
|
|
vtPipeDir = pPipe->StartPoint() - pPipe->EndPoint();
|
|
vtPipeDir.z = 0.0;
|
|
vtPipeDir.normalize();
|
|
pPipe->close();
|
|
}
|
|
|
|
LinkDate data;
|
|
data.ptLink = ptWater;
|
|
data.ptSan = ptSan;
|
|
data.idSan = idSan;
|
|
data.bInWall = false;
|
|
ModifyLinkSanPt(data);
|
|
if (!ConfirmMianPipePosFromPipe(data, vtPipeDir))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 根据主干管铺设点调整给水点位置使之在给水管流入点
|
|
AcGePoint3d ptWaterNew = ptWater;
|
|
pPipe = NULL;
|
|
acdbOpenObject(pPipe, idPipe, AcDb::kForRead);
|
|
if (pPipe != NULL)
|
|
{
|
|
AcGeVector3d vtPipeDir = pPipe->StartPoint() - pPipe->EndPoint();
|
|
vtPipeDir.z = 0.0;
|
|
|
|
AcGeVector3d vtDir = data.vecPts[0] - ptWater;
|
|
vtDir.z = 0;
|
|
if (vtDir.isCodirectionalTo(vtPipeDir, m_tolVec))
|
|
{
|
|
ptWaterNew = pPipe->EndPoint();
|
|
}
|
|
else
|
|
{
|
|
ptWaterNew = pPipe->StartPoint();
|
|
}
|
|
pPipe->close();
|
|
}
|
|
|
|
// 连接主干管
|
|
data.ptLink = ptWaterNew;
|
|
return LinkMainPipe(data);
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::GetPipe( AcGePoint3d &ptS, AcGePoint3d &ptE, const AcGeVector3d &vtDir )
|
|
{
|
|
// 获得最近的墙体
|
|
AcGePoint3d pt1 = ptS, pt2 = ptE;
|
|
AcGeVector3d vtWall = pt1 - pt2;
|
|
vtWall.z = 0.0;
|
|
AcDbLine line;
|
|
double dWallThick = 0.0;
|
|
if (!GetNearestWall(pt2, vtWall, line, dWallThick))
|
|
{
|
|
line.setStartPoint(ptS);
|
|
line.setEndPoint(ptE);
|
|
dWallThick = 0.0;
|
|
}
|
|
|
|
for(int i = 0; i < OFFSET_TIME; i++)
|
|
{
|
|
// 检查是否与其他系统碰撞
|
|
if (!IsConflicting(pt1, pt2, m_dDistPipe2Pipe))
|
|
{
|
|
ptS = pt1;
|
|
ptE = pt2;
|
|
break;
|
|
}
|
|
// 将点移动到距墙m_dDistPipe2Wall * (i + 1)处
|
|
MovePipe(pt1, line, vtDir, dWallThick * 0.5 + m_dDistPipe2Wall * (i + 1));
|
|
MovePipe(pt2, line, vtDir, dWallThick * 0.5 + m_dDistPipe2Wall * (i + 1));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::GetPtInWall( AcGePoint3d &ptWall, const AcGePoint3d &ptSan, const AcGeVector3d &vtDir )
|
|
{
|
|
// 找到与vtDir垂直的墙
|
|
AcGeVector3d vt = vtDir;
|
|
vt.z = 0.0;
|
|
vt.normalize();
|
|
AcGeVector3d vtWall;
|
|
std::vector<std::pair<XCurveSegment, XCurveSegment> > vecWall;
|
|
std::vector<std::pair<XCurveSegment, XCurveSegment> >::iterator it;
|
|
for (it = m_vecWallSide.begin(); it != m_vecWallSide.end(); it++)
|
|
{
|
|
if (it->first.GetCurveType() == CURVE_LINE)
|
|
{
|
|
vtWall = it->first.StartPoint() - it->first.EndPoint();
|
|
vtWall.z = 0.0;
|
|
if (vt.isPerpendicularTo(vtWall, m_tolVec))
|
|
{
|
|
vecWall.push_back(*it);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 找到距离ptSan最近的墙体
|
|
XCurveSegment segNear, segFar;
|
|
if (!GetWallSide(ptSan, vecWall, segNear, segFar))
|
|
{
|
|
acutPrintf(_T("\n未找到墙体!"));
|
|
return false;
|
|
}
|
|
|
|
XPoly2D poly;
|
|
GetWallOutLine(poly, segNear, segFar);
|
|
poly.SetElevation(0.0);
|
|
AcGePoint3d pt = ptSan;
|
|
pt.z = 0.0;
|
|
if (((pt & poly) == PR_EDGE)
|
|
|| ((pt & poly) == PR_INSIDE)) // 点在墙内
|
|
{
|
|
ptWall = ptSan;
|
|
return true;
|
|
}
|
|
else // 点在墙外
|
|
{
|
|
AcGePoint3d ptS, ptE;
|
|
ptS = segNear.StartPoint();
|
|
ptE = segNear.EndPoint();
|
|
ptS.z = 0.0;
|
|
ptE.z = 0.0;
|
|
AcDbLine lineNear(ptS, ptE);
|
|
ptS = segFar.StartPoint();
|
|
ptE = segFar.EndPoint();
|
|
ptS.z = 0.0;
|
|
ptE.z = 0.0;
|
|
AcDbLine lineFar(ptS, ptE);
|
|
AcGePoint3d pt = ptSan, ptPrj;
|
|
pt.z = 0.0;
|
|
if ((lineNear.getClosestPointTo(pt, ptPrj, Adesk::kTrue) == Acad::eOk))
|
|
{
|
|
AcGeVector3d vt = ptPrj - pt;
|
|
vt.z = 0.0;
|
|
vt.normalize();
|
|
double dVPipeRadius = GetVPipeDrawRadius();
|
|
ptPrj += vt * dVPipeRadius;
|
|
ptWall = ptPrj;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::CreateVirtualPipe( const AcGePoint3d &ptS, const AcGePoint3d &ptE, const PipeType &type)
|
|
{
|
|
// 点重合直接返回
|
|
if (ptS.distanceTo(ptE) < 0.001)
|
|
{
|
|
return;
|
|
}
|
|
|
|
AcGeVector3d vtDir = ptS - ptE;
|
|
vtDir.z = 0.0;
|
|
PipeDir dir = GetPipeDir(vtDir);
|
|
|
|
AcDbLine *pNewLine = new AcDbLine();
|
|
pNewLine->setStartPoint(ptS);
|
|
pNewLine->setEndPoint(ptE);
|
|
PipeData node;
|
|
node.pLine = pNewLine;
|
|
node.nId = m_nId++;
|
|
node.drection = dir;
|
|
node.type = type;
|
|
m_vecPipeData.push_back(node);
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::ConfirmMianPipePosFromVPipe( LinkDate &data, const AcDbObjectId &idPipe )
|
|
{
|
|
|
|
// 从给水点沿m_vtXAxis后m_vtYAxis方向铺设管线
|
|
LinkDate dataX = data;
|
|
bool bXAxis = ConfirmMianPipePosFromPipe(dataX, m_vtXAxis);
|
|
// 从给水点沿m_vtYAxis后m_vtXAxis方向铺设管线
|
|
LinkDate dataY = data;
|
|
bool bYAxis = ConfirmMianPipePosFromPipe(dataY, m_vtYAxis);
|
|
if (bXAxis && bYAxis) // 两方向均可
|
|
{
|
|
AcGePoint3d ptWater = dataX.ptLink, ptSanX, ptX, ptSanY, ptY;
|
|
if (dataX.nTransformTime == 0)
|
|
{
|
|
ptX = dataX.vecPts[0];
|
|
ptSanX = dataX.ptSan;
|
|
}
|
|
else
|
|
{
|
|
ptX = dataX.vecPts[0];
|
|
ptSanX = dataX.vecPts[1];
|
|
}
|
|
|
|
if (dataY.nTransformTime == 0)
|
|
{
|
|
ptY = dataY.vecPts[0];
|
|
ptSanY = dataY.ptSan;
|
|
}
|
|
else
|
|
{
|
|
ptY = dataY.vecPts[0];
|
|
ptSanY = dataY.vecPts[1];
|
|
}
|
|
|
|
int nNumVPipeX = PassVertivalPipeNumByLine(ptWater, ptX); // 穿过立管个数
|
|
int nNumVPipeY = PassVertivalPipeNumByLine(ptWater, ptY);
|
|
if ((nNumVPipeX == 0 && nNumVPipeY == 0) || (nNumVPipeX > 0 && nNumVPipeY > 0)) // 都穿过立管或都不穿过立管
|
|
{
|
|
// 以经过门窗少为准
|
|
double dWidth = 0.0;
|
|
int nNumDoorX = PassWallNumByLine(ptX, ptSanX, dWidth); // 挨门窗个数
|
|
int nNumDoorY = PassWallNumByLine(ptY, ptSanY, dWidth);
|
|
if (nNumDoorX <= nNumDoorY) // 以穿过门窗少为准
|
|
{
|
|
data = dataX;
|
|
}
|
|
else
|
|
{
|
|
data = dataY;
|
|
}
|
|
}
|
|
else if (nNumVPipeX == 0)// 以不穿过立管为准
|
|
{
|
|
data = dataX;
|
|
}
|
|
else if (nNumVPipeY == 0)// 以不穿过立管为准
|
|
{
|
|
data = dataY;
|
|
}
|
|
}
|
|
else if (bXAxis && !bYAxis)
|
|
{
|
|
data = dataX;
|
|
}
|
|
else if (!bXAxis && bYAxis)
|
|
{
|
|
data = dataY;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::ConfirmMianPipePosFromPipe( LinkDate &data, const AcGeVector3d &vtPipeDir)
|
|
{
|
|
AcGePoint3d ptSan = data.ptSan; // 洁具点
|
|
AcGePoint3d ptFeed = data.ptLink; // 供水点
|
|
AcDbObjectId idSan = data.idSan;
|
|
// 根据水管方向确定连接方向
|
|
AcGeVector3d vtLinkDir1, vtLinkDir2;
|
|
if (vtPipeDir.isParallelTo(m_vtXAxis, m_tolVec))
|
|
{
|
|
vtLinkDir1 = m_vtXAxis;
|
|
vtLinkDir2 = m_vtYAxis;
|
|
}
|
|
else if (vtPipeDir.isParallelTo(m_vtYAxis, m_tolVec))
|
|
{
|
|
vtLinkDir1 = m_vtYAxis;
|
|
vtLinkDir2 = m_vtXAxis;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 先按m_vtXAxis后m_vtYAxis方向铺设管线时,管线交点
|
|
AcDbLine lineX(ptFeed, ptFeed + vtLinkDir1);
|
|
AcDbLine lineY(ptSan, ptSan + vtLinkDir2);
|
|
AcGePoint3dArray ptArr;
|
|
lineX.intersectWith(&lineY, AcDb::kExtendBoth, AcGePlane::kXYPlane, ptArr);
|
|
if (ptArr.length() != 1)
|
|
{
|
|
return false;
|
|
}
|
|
AcGePoint3d ptX = ptArr[0];
|
|
ptX.z = ptFeed.z;
|
|
// if (!IsPipe(idSan)) // 洁具 zxl 2013.11.11 del
|
|
{
|
|
if (!LayMainPipe(ptSan, ptX, m_dDistPipe2Pipe)) // 直接连接洁具连接线发生碰撞
|
|
{
|
|
// 偏移连接线
|
|
AcGeVector3d vtDir;
|
|
if (!GetSanitaryDir(vtDir, idSan))
|
|
{
|
|
acutPrintf(_T("\n无法获取洁具方向!"));
|
|
return false;
|
|
}
|
|
|
|
AcGeVector3d vtOffset;
|
|
if (vtDir.isParallelTo(vtLinkDir1, m_tolVec))
|
|
{
|
|
vtOffset = vtDir;
|
|
}
|
|
else if (vtDir.isPerpendicularTo(vtLinkDir1, m_tolVec))
|
|
{
|
|
if (!GetSanitaryOffsetDir(vtOffset, ptSan, idSan))
|
|
{
|
|
vtOffset = ptFeed - ptX;
|
|
vtOffset.z = 0.0;
|
|
vtOffset.normalize();
|
|
}
|
|
}
|
|
else // 偏移方向需要与m_vtXAxis或m_vtYAxis平行
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 转换一次
|
|
AcGePoint3d ptSan1 = ptSan;
|
|
if (OffsetMainPipe(ptSan1, ptX, m_dDistPipe2Pipe, m_dDistPipe2Wall, vtOffset, OFFSET_TIME))
|
|
{
|
|
if (LayMainPipe(ptSan, ptSan1, m_dDistPipe2Pipe)) // 无碰撞
|
|
{
|
|
data.nTransformTime = 1;
|
|
data.vecPts.push_back(ptX);
|
|
ptSan1.z = ptFeed.z;
|
|
data.vecPts.push_back(ptSan1);
|
|
}
|
|
else
|
|
{
|
|
// 转换两次
|
|
AcGeVector3d vtOffset2 = ptX - ptSan1;
|
|
vtOffset2.z = 0.0;
|
|
vtOffset2.normalize();
|
|
if (vtOffset2.isParallelTo(vtDir, m_tolVec))
|
|
{
|
|
vtOffset2 = vtDir;
|
|
}
|
|
|
|
AcGePoint3d ptSan2 = ptSan;
|
|
if (OffsetMainPipe(ptSan2, ptSan1, m_dDistPipe2Pipe, m_dDistPipe2Wall, vtOffset2, OFFSET_TIME))
|
|
{
|
|
if (LayMainPipe(ptSan, ptSan2, m_dDistPipe2Pipe))
|
|
{
|
|
data.nTransformTime = 2;
|
|
data.vecPts.push_back(ptX);
|
|
ptSan1.z = ptFeed.z;
|
|
data.vecPts.push_back(ptSan1);
|
|
ptSan2.z = ptFeed.z;
|
|
data.vecPts.push_back(ptSan2);
|
|
}
|
|
else // 找不到合适位置连接洁具
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else // 找不到合适位置连接洁具
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else // 找不到合适位置连接洁具
|
|
{
|
|
return false;
|
|
}
|
|
|
|
}
|
|
else // 直接连接洁具
|
|
{
|
|
data.nTransformTime = 0; // 无需转换
|
|
data.vecPts.push_back(ptX);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::LayMainPipe( const AcGePoint3d &ptS, const AcGePoint3d &ptE, double dDist )
|
|
{
|
|
AcDbLine line(ptS, ptE);
|
|
if ((!PassParallelWall(ptS, ptE)) // 没有穿过平行墙体
|
|
&& !IsPassOtherSanitarySysPt(ptS, ptE) // 没有穿过其他系统洁具点
|
|
&& !IsCollidePipe(&line, dDist)) // 没有与其他系统平行管线发生碰撞
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::LinkMainPipe( LinkDate &data )
|
|
{
|
|
// 洁具实际上是管线 zxl 2013.11.11 del
|
|
// if (IsPipe(data.idSan))
|
|
// {
|
|
// // return LinkPipe(ptWater, ptS, ptE);
|
|
// return false;
|
|
// }
|
|
|
|
int nTransformTime = data.nTransformTime;
|
|
PipeType type;
|
|
AcGePoint3d ptFeed;
|
|
switch(nTransformTime)
|
|
{
|
|
case 0:
|
|
{
|
|
AcGePoint3d ptTemp = data.ptSan;
|
|
ptTemp.z = data.ptLink.z;
|
|
AcGePoint3d pt1 = data.ptLink, pt2 = data.vecPts[0];
|
|
ModifyMainPipePt(pt1, pt2);
|
|
CreateVirtualPipe(pt1, pt2, eMainPipe);
|
|
type = eMainPipe;
|
|
ptFeed = data.vecPts[0];
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
AcGePoint3d ptTemp = data.ptSan;
|
|
ptTemp.z = data.ptLink.z;
|
|
AcGePoint3d pt1 = data.ptLink, pt2 = data.vecPts[0];
|
|
ModifyMainPipePt(pt1, pt2);
|
|
CreateVirtualPipe(pt1, pt2, eMainPipe);
|
|
CreateVirtualPipe(data.vecPts[0], data.vecPts[1], eMainPipe);
|
|
type = eSmallPipe;
|
|
ptFeed = data.vecPts[1];
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
AcGePoint3d ptTemp = data.ptSan;
|
|
ptTemp.z = data.ptLink.z;
|
|
AcGePoint3d pt1 = data.ptLink, pt2 = data.vecPts[0];
|
|
ModifyMainPipePt(pt1, pt2);
|
|
CreateVirtualPipe(pt1, pt2, eMainPipe);
|
|
CreateVirtualPipe(data.vecPts[0], data.vecPts[1], eMainPipe);
|
|
CreateVirtualPipe(data.vecPts[1], data.vecPts[2], eBranch);
|
|
type = eSmallPipe;
|
|
ptFeed = data.vecPts[2];
|
|
break;
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
// 连接洁具
|
|
AcGePoint3d ptSan = data.ptSan;
|
|
AcDbObjectId idSan = data.idSan;
|
|
LinkSanitary(ptSan, ptFeed, idSan, type, data.bInWall, data.ptInWall);
|
|
return true;
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::OffsetMainPipe( AcGePoint3d &ptS, AcGePoint3d &ptE, double dCollideDist, double dOffsetDist, const AcGeVector3d &vtOffset, int nOffsetTime )
|
|
{
|
|
AcDbLine line;
|
|
double dWallThick = 0.0;
|
|
AcGeVector3d vtWall = ptS - ptE;
|
|
vtWall.z = 0.0;
|
|
if (!GetNearestWall(ptS, vtWall, line, dWallThick))
|
|
{
|
|
line.setStartPoint(ptS);
|
|
line.setEndPoint(ptE);
|
|
dWallThick = 0.0;
|
|
}
|
|
|
|
bool bRet = false;
|
|
AcGePoint3d pt1 = ptS, pt2 = ptE;
|
|
for (int j = 0; j < nOffsetTime; j++)
|
|
{
|
|
MovePipe(pt1, line, vtOffset, dWallThick * 0.5 + dOffsetDist * (j + 1));
|
|
MovePipe(pt2, line, vtOffset, dWallThick * 0.5 + dOffsetDist * (j + 1));
|
|
if (LayMainPipe(pt1, pt2, dCollideDist))
|
|
{
|
|
ptS = pt1;
|
|
ptE = pt2;
|
|
bRet = true;
|
|
break;
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::ComfirmXAxisYAxis( const AcDbObjectId &idPipe )
|
|
{
|
|
// 给水管为立管时,连接洁具时方向
|
|
m_vtXAxis = AcGeVector3d::kXAxis;
|
|
m_vtYAxis = AcGeVector3d::kYAxis;
|
|
m_vtXAxis.rotateBy(Ucs2Wcs(0.0), AcGeVector3d::kZAxis);
|
|
m_vtYAxis.rotateBy(Ucs2Wcs(0.0), AcGeVector3d::kZAxis);
|
|
// 非立管时,以管线方向和其垂涎方向为x轴y轴
|
|
if (!IsVertivalPipe(idPipe))
|
|
{
|
|
return;
|
|
AcGeVector3d vt = AcGeVector3d::kIdentity;
|
|
TDbPipe *pPipe = NULL;
|
|
acdbOpenObject(pPipe, idPipe, AcDb::kForRead);
|
|
if (pPipe != NULL)
|
|
{
|
|
vt = pPipe->StartPoint() - pPipe->EndPoint();
|
|
vt.z = 0.0;
|
|
pPipe->close();
|
|
}
|
|
// 管线垂直方向
|
|
AcGeVector3d vt2 = vt;
|
|
vt2.rotateBy(PI / 2, AcGeVector3d::kZAxis);
|
|
|
|
// 以与世界坐标系x轴夹角小的胃X轴方向
|
|
if (vt != AcGeVector3d::kIdentity)
|
|
{
|
|
AcGeVector3d vtX = AcGeVector3d::kXAxis;
|
|
double dAngle1 = vtX.angleTo(vt);
|
|
double dAngle2 = vtX.angleTo(vt2);
|
|
|
|
if (dAngle2 > dAngle1)
|
|
{
|
|
m_vtXAxis = vt;
|
|
m_vtYAxis = vt2;
|
|
}
|
|
else
|
|
{
|
|
m_vtXAxis = vt2;
|
|
m_vtYAxis = vt;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ConcealInstallSanitarySys::CreatePipe()
|
|
{
|
|
// 获得给水点
|
|
AcGePoint3d ptFeed;
|
|
TDbPipe *pPipe = NULL;
|
|
acdbOpenObject(pPipe, m_idPipe, AcDb::kForRead);
|
|
if (pPipe != NULL)
|
|
{
|
|
if (pPipe->IsVertical())
|
|
{
|
|
ptFeed = pPipe->StartPoint();
|
|
}
|
|
else
|
|
{
|
|
if (pPipe->GetFlowDir() == TPipeSys::kFromStart)
|
|
{
|
|
ptFeed = pPipe->StartPoint();
|
|
}
|
|
else
|
|
{
|
|
ptFeed = pPipe->EndPoint();
|
|
}
|
|
}
|
|
pPipe->close();
|
|
}
|
|
|
|
std::vector<PipeData>::iterator it;
|
|
CString sLayer = GetPipeLayer(m_sysPipe);
|
|
CString sVPipeLayer = GetVPipeLayer(m_sysPipe);
|
|
InitPipeLayer(sLayer);
|
|
InitPipeLayer(sVPipeLayer);
|
|
int iPipeIdx = GetPipeLayerIdxByName(sLayer);
|
|
CString sLineType = GetPipeWireLayLineType(sLayer);
|
|
CString sMaterial = GetPipeMaterialByIdx(g_iPipeMaterial[iPipeIdx]);
|
|
CString sDnType = GetDnByMat(sMaterial);
|
|
CString sLineType2 = GetLayerLineType(sLayer);
|
|
for (it = m_vecPipeData.begin(); it != m_vecPipeData.end(); it++)
|
|
{
|
|
AcDbLine *pline = (*it).pLine;
|
|
// 供水点在管线中间的管线序切断分别设置流向
|
|
if (PipePassFeedPt(pline, ptFeed, sLayer))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
TDbPipe *pPipe = new TDbPipe();
|
|
pPipe->SetRadius(g_nPipeRadius[iPipeIdx]);
|
|
if (it->type == eVertival)//设置立管显示半径
|
|
{
|
|
if(g_bPipeDouble[iPipeIdx])
|
|
{
|
|
pPipe->SetRadiusIn(g_nPipeRadius[iPipeIdx] / 2);
|
|
}
|
|
else
|
|
{
|
|
if(!g_bStandPipeArc)//传统扣弯
|
|
pPipe->SetRadiusIn(-2);
|
|
}
|
|
}
|
|
pPipe->SetStartPoint(pline->startPoint());
|
|
pPipe->SetEndPoint(pline->endPoint());
|
|
pPipe->SetFlowDir(TPipeSys::kFromStart);
|
|
if(sLineType2.Find(_T("TG")) > -1)
|
|
{
|
|
XLine lineTemp(asDblArray(pline->startPoint()), asDblArray(pline->endPoint()));
|
|
double nAng = lineTemp.Direction();
|
|
if(nAng > PI/2 && nAng < (PI/2*3 + 0.001))
|
|
{
|
|
pPipe->SetStartPoint(pline->endPoint());
|
|
pPipe->SetEndPoint(pline->startPoint());
|
|
pPipe->SetFlowDir(TPipeSys::kFromEnd);
|
|
}
|
|
}
|
|
pPipe->SetDnDiameter(m_dPipeDn);
|
|
pPipe->setLayer(sLayer);
|
|
pPipe->SetSysType(GetPipeSysByLayer(sLayer));
|
|
pPipe->setColor(AcCmColor()); //随层
|
|
pPipe->SetPipeWeight(g_nPipeWidth[iPipeIdx]);
|
|
pPipe->setLinetype(sLineType);
|
|
pPipe->setLineWeight(AcDb::kLnWtByLayer);
|
|
pPipe->SetMaterial(g_iPipeMaterial[iPipeIdx]);
|
|
pPipe->SetLabel(sDnType);
|
|
AddToCurrentSpace(pPipe, Adesk::kTrue);
|
|
}
|
|
// 更新给水管
|
|
ModifyFeedPipe();
|
|
}
|
|
|
|
SanitarySys::PipeDir ConcealInstallSanitarySys::GetPipeDir( const AcGeVector3d &vtDir )
|
|
{
|
|
PipeDir dir = eNone;
|
|
if (vtDir.isParallelTo(m_vtXAxis))
|
|
{
|
|
dir = eParallelX;
|
|
}
|
|
else if (vtDir.isParallelTo(m_vtYAxis))
|
|
{
|
|
dir = eParallelY;
|
|
}
|
|
else
|
|
{
|
|
dir = eOther;
|
|
}
|
|
return dir;
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::ModifyFeedPipe()
|
|
{
|
|
TDbPipe *pPipe = NULL;
|
|
acdbOpenObject(pPipe, m_idPipe, AcDb::kForWrite);
|
|
if (pPipe != NULL)
|
|
{
|
|
if (pPipe->IsVertical())
|
|
{
|
|
AcDbLine line(pPipe->StartPoint(), pPipe->EndPoint());
|
|
AcGePoint3d pt;
|
|
if (line.getClosestPointTo(m_ptFeed, pt, Adesk::kTrue) == Acad::eOk)
|
|
{
|
|
AcGePoint3d ptS = pPipe->StartPoint();
|
|
AcGePoint3d ptE = pPipe->EndPoint();
|
|
double dDistS = ptS.distanceTo(pt);
|
|
double dDistE = ptE.distanceTo(pt);
|
|
double dDist = ptS.distanceTo(ptE);
|
|
if (fabs(dDist - dDistE - dDistS) > 0.001) // 点在管线延长线上
|
|
{
|
|
if (dDistS < dDistE)
|
|
{
|
|
pPipe->SetStartPoint(pt);
|
|
}
|
|
else
|
|
{
|
|
pPipe->SetEndPoint(pt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pPipe->erase();
|
|
}
|
|
pPipe->close();
|
|
}
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::IsPipe( const AcDbObjectId idEnt )
|
|
{
|
|
ads_name name;
|
|
acdbGetAdsName(name, idEnt);
|
|
Entity ent(name);
|
|
if (ent.Is(_T("ATS_PIPE")))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::LinkPipe( const AcGePoint3d &ptWater, const AcGePoint3d &ptS, const AcGePoint3d &ptE )
|
|
{
|
|
CreateVirtualPipe(ptWater, ptS, eMainPipe);
|
|
CreateVirtualPipe(ptS, ptE, eMainPipe);
|
|
return true;
|
|
}
|
|
|
|
double ConcealInstallSanitarySys::GetVPipeDrawRadius()
|
|
{
|
|
double dRadius = 0.5 * DocGetPScale();
|
|
TDbPipe *pPipe = NULL;
|
|
acdbOpenObject(pPipe, m_idPipe, AcDb::kForRead);
|
|
if (pPipe != NULL)
|
|
{
|
|
dRadius = pPipe->GetRadius() * DocGetPScale();
|
|
pPipe->close();
|
|
}
|
|
return dRadius;
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::GetPtToLineDist( std::multimap<double, std::pair<AcDbLine*, AcGePoint3d> > &mapDist, const AcGePoint3d &pt, const AcGeVector3d &vtDir, PipeType type )
|
|
{
|
|
std::vector<PipeData>::iterator it;
|
|
AcGeVector3d vtTemp;
|
|
AcGePoint3d ptPrj, ptTemp = pt, ptS, ptE;
|
|
AcDbLine *pLine = NULL;
|
|
AcDbLine line;
|
|
for (it = m_vecPipeData.begin(); it != m_vecPipeData.end(); it++)
|
|
{
|
|
pLine = it->pLine;
|
|
if (pLine == NULL || it->type != type)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
vtTemp = pLine->startPoint() - pLine->endPoint();
|
|
vtTemp.z = 0.0;
|
|
if (vtTemp.isParallelTo(vtDir, m_tolVec))
|
|
{
|
|
ptS = pLine->startPoint();
|
|
ptE = pLine->endPoint();
|
|
ptS.z = 0.0;
|
|
ptE.z = 0.0;
|
|
line.setStartPoint(ptS);
|
|
line.setEndPoint(ptE);
|
|
if (line.getClosestPointTo(ptTemp, ptPrj, Adesk::kTrue) == Acad::eOk)
|
|
{
|
|
double dDist = ptTemp.distanceTo(ptPrj);
|
|
ptPrj.z = pLine->startPoint().z;
|
|
mapDist.insert(std::make_pair(dDist, std::make_pair(pLine, ptPrj)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::ExtendLine( AcDbLine *pLine, const AcGePoint3d &pt )
|
|
{
|
|
ASSERT(pLine != NULL);
|
|
AcGePoint3d ptS = pLine->startPoint();
|
|
AcGePoint3d ptE = pLine->endPoint();
|
|
double dDistS = ptS.distanceTo(pt);
|
|
double dDistE = ptE.distanceTo(pt);
|
|
double dDist = ptS.distanceTo(ptE);
|
|
double dLen = dDistS + dDistE;
|
|
if (fabs(dLen - dDist) > 0.001 && dLen > dDist) // 在延长线上
|
|
{
|
|
if (dDistS < dDistE)
|
|
{
|
|
pLine->setStartPoint(pt);
|
|
}
|
|
else
|
|
{
|
|
pLine->setEndPoint(pt);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::OffsetLine( AcGePoint3d &ptS, AcGePoint3d &ptE, double dCollideDist, const AcGeVector3d &vtOffset, int nOffsetTime)
|
|
{
|
|
AcDbLine line;
|
|
double dWallThick = 0.0;
|
|
AcGeVector3d vtWall = ptS - ptE;
|
|
vtWall.z = 0.0;
|
|
if (!GetNearestWall(ptS, vtWall, line, dWallThick))
|
|
{
|
|
line.setStartPoint(ptS);
|
|
line.setEndPoint(ptE);
|
|
dWallThick = 0.0;
|
|
}
|
|
|
|
bool bRet = false;
|
|
AcGePoint3d pt1 = ptS, pt2 = ptE;
|
|
for (int j = 0; j < nOffsetTime; j++)
|
|
{
|
|
MovePipe(pt1, line, vtOffset, dWallThick * 0.5 + m_dDistPipe2Wall * (j + 1));
|
|
MovePipe(pt2, line, vtOffset, dWallThick * 0.5 + m_dDistPipe2Wall * (j + 1));
|
|
if (!IsConflicting(pt1, pt2, dCollideDist))
|
|
{
|
|
ptS = pt1;
|
|
ptE = pt2;
|
|
bRet = true;
|
|
break;
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::GetOffsetDir( AcGeVector3d &vtOffset, const AcGePoint3d &ptSan, const AcGeVector3d &vtSanitaryDir, const AcGeVector3d &vtLinkedPipe, const AcDbObjectId &idSan )
|
|
{
|
|
if (vtSanitaryDir.isParallelTo(vtLinkedPipe, m_tolVec)) // 洁具方向与洁具连接的管线方向平行
|
|
{
|
|
if (!GetSanitaryOffsetDir(vtOffset, ptSan, idSan)) // 给水点相对另一个给水点的方向
|
|
{
|
|
vtOffset = vtLinkedPipe;
|
|
vtOffset.rotateBy(PI / 2, AcGeVector3d::kZAxis);
|
|
}
|
|
}
|
|
else if (vtSanitaryDir.isPerpendicularTo(vtLinkedPipe, m_tolVec))
|
|
{
|
|
vtOffset = vtSanitaryDir;
|
|
}
|
|
else
|
|
{
|
|
vtOffset = vtLinkedPipe;
|
|
vtOffset.rotateBy(PI / 2, AcGeVector3d::kZAxis);
|
|
}
|
|
|
|
vtOffset.z = 0.0;
|
|
vtOffset.normalize();
|
|
|
|
// 偏移方向有可能需与m_vtXAxis或m_vtYAxis平行
|
|
std::map<double, AcGeVector3d> mapDir;
|
|
double dAngle = vtOffset.angleTo(m_vtYAxis);
|
|
mapDir.insert(std::make_pair(dAngle, m_vtYAxis));
|
|
dAngle = vtOffset.angleTo(-m_vtYAxis);
|
|
mapDir.insert(std::make_pair(dAngle, -m_vtYAxis));
|
|
dAngle = vtOffset.angleTo(m_vtXAxis);
|
|
mapDir.insert(std::make_pair(dAngle, m_vtXAxis));
|
|
dAngle = vtOffset.angleTo(-m_vtXAxis);
|
|
mapDir.insert(std::make_pair(dAngle, -m_vtXAxis));
|
|
vtOffset = mapDir.begin()->second;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void ConcealInstallSanitarySys::DrawSanitaryDir( const AcGePoint3d &pt, const AcGeVector3d &vtDir )
|
|
{
|
|
AcGeVector3d vt = vtDir;
|
|
vt.normalize();
|
|
XPoint ptE = pt + vt * 500;
|
|
AcGeVector3d vt1 = vt;
|
|
vt1.rotateBy(PI/2, AcGeVector3d::kZAxis);
|
|
|
|
XPoint pt1 = ptE - vt * 50 + vt1 * 50;
|
|
XPoint pt2 = ptE - vt * 50 - vt1 * 50;
|
|
XLine line1(asDblArray(pt), ptE);
|
|
line1.Make();
|
|
XLine line2(ptE, pt1);
|
|
line2.Make();
|
|
XLine line3(ptE, pt2);
|
|
line3.Make();
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::GetLinkData( LinkDate &data )
|
|
{
|
|
// 连接洁具时可参考的四个方向的管线
|
|
AcGeVector3d vtLinkDir1 = m_vtXAxis;
|
|
AcGeVector3d vtLinkDir2 = m_vtXAxis;
|
|
AcGeVector3d vtLinkDir3 = m_vtXAxis;
|
|
AcGeVector3d vtLinkDir4 = m_vtXAxis;
|
|
vtLinkDir2.rotateBy(PI * 0.5, AcGeVector3d::kZAxis);
|
|
vtLinkDir3.rotateBy(PI, AcGeVector3d::kZAxis);
|
|
vtLinkDir4.rotateBy(PI * 1.5, AcGeVector3d::kZAxis);
|
|
|
|
AcDbObjectId idSan = data.idSan;
|
|
AcGePoint3d ptSan = data.ptSan;
|
|
|
|
// 洁具方向
|
|
AcGeVector3d vtSanitaryDir;
|
|
GetSanitaryDir(vtSanitaryDir, idSan);
|
|
|
|
// 在四个方向连接洁具
|
|
AcDbLine *pLineTemp = NULL;
|
|
double dDist = 0.0;
|
|
AcGePoint3d ptLinkTemp, ptCornerTemp;
|
|
std::multimap<double, LinkDate> mapLinkDist;
|
|
AcGeVector3d vtOffset; // 偏移方向
|
|
GetOffsetDir(vtOffset, ptSan, vtSanitaryDir, vtLinkDir1, idSan);
|
|
LinkDate DataTemp1 = data;
|
|
if (GetLinkData(DataTemp1, vtLinkDir1, m_vtYAxis, vtOffset))
|
|
{
|
|
mapLinkDist.insert(std::make_pair(DataTemp1.dLinkLen, DataTemp1));
|
|
}
|
|
|
|
LinkDate DataTemp2 = data;
|
|
GetOffsetDir(vtOffset, ptSan, vtSanitaryDir, vtLinkDir2, idSan);
|
|
if (GetLinkData(DataTemp2, vtLinkDir2, m_vtXAxis, vtOffset))
|
|
{
|
|
mapLinkDist.insert(std::make_pair(DataTemp2.dLinkLen, DataTemp2));
|
|
}
|
|
|
|
LinkDate DataTemp3 = data;
|
|
GetOffsetDir(vtOffset, ptSan, vtSanitaryDir, vtLinkDir3, idSan);
|
|
if (GetLinkData(DataTemp3, vtLinkDir3, m_vtYAxis, vtOffset))
|
|
{
|
|
mapLinkDist.insert(std::make_pair(DataTemp3.dLinkLen, DataTemp3));
|
|
}
|
|
|
|
LinkDate DataTemp4 = data;
|
|
GetOffsetDir(vtOffset, ptSan, vtSanitaryDir, vtLinkDir4, idSan);
|
|
if (GetLinkData(DataTemp4, vtLinkDir4, m_vtXAxis, vtOffset))
|
|
{
|
|
mapLinkDist.insert(std::make_pair(DataTemp4.dLinkLen, DataTemp4));
|
|
}
|
|
|
|
// 找到连接线最短的路径
|
|
std::multimap<double, LinkDate>::iterator it;
|
|
it = mapLinkDist.begin();
|
|
if (it != mapLinkDist.end())
|
|
{
|
|
data = (*it).second;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::GetLinkData( LinkDate &data, const AcGeVector3d &vtLink, const AcGeVector3d &vtPipe, const AcGeVector3d &vtOffset )
|
|
{
|
|
// 获得点pt到所有与vtLine平行的直线的距离
|
|
AcGePoint3d ptSan = data.ptSan;
|
|
std::multimap<double, std::pair<AcDbLine*, AcGePoint3d> > mapData;
|
|
GetPtToLineDist(mapData, ptSan, vtPipe, eMainPipe);
|
|
GetPtToLineDist(mapData, ptSan, vtPipe, eBranch);
|
|
GetPtToLineDist(mapData, ptSan, vtPipe, eBranch2);
|
|
// 找出与vtDir同向的直线
|
|
std::multimap<double, std::pair<AcDbLine*, AcGePoint3d> > mapNew;
|
|
std::multimap<double, std::pair<AcDbLine*, AcGePoint3d> >::iterator it;
|
|
AcGeVector3d vtTemp;
|
|
for (it = mapData.begin(); it != mapData.end(); it++)
|
|
{
|
|
vtTemp = ((*it).second).second - ptSan;
|
|
vtTemp.z = 0.0;
|
|
vtTemp.normalize();
|
|
if (vtTemp.isCodirectionalTo(vtLink, m_tolVec)) // 与连接方向同向
|
|
{
|
|
mapNew.insert(*it);
|
|
}
|
|
}
|
|
|
|
// 获得同向最近的直线
|
|
bool bRet = false;
|
|
it = mapNew.begin();
|
|
if (it != mapNew.end())
|
|
{
|
|
ptSan.z = (*it).second.second.z;
|
|
int nTransfromTime = data.nTransformTime;
|
|
switch(nTransfromTime)
|
|
{
|
|
case 0:
|
|
{
|
|
/*
|
|
*
|
|
*
|
|
ptSan*********************** ptLink
|
|
*
|
|
*
|
|
洁具连接管线示意图,ptSan为洁具点
|
|
*/
|
|
if (!IsConflicting(ptSan, ((*it).second).second, m_dDistPipe2Pipe))
|
|
{
|
|
data.pLine = ((*it).second).first;
|
|
data.ptLink = ((*it).second).second;
|
|
if (!data.bInWall) // 洁具点在墙内
|
|
{
|
|
data.dLinkLen = (*it).first;
|
|
}
|
|
else // 在墙外
|
|
{
|
|
data.dLinkLen = (data.ptInWall).distanceTo(((*it).second).second);
|
|
}
|
|
bRet = true;
|
|
}
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
/*
|
|
*
|
|
*
|
|
ptConer*********************** ptLink
|
|
* *
|
|
* *
|
|
*
|
|
ptSan
|
|
洁具连接管线示意图,ptSan为洁具点
|
|
*/
|
|
AcGePoint3d pt1 = (*it).second.second, pt2 = ptSan;
|
|
AcGeVector3d vtMove = vtOffset;
|
|
if (OffsetLine(pt1, pt2, m_dDistPipe2Wall, vtMove, OFFSET_TIME))
|
|
{
|
|
if (!IsConflicting(pt2, ptSan, m_dDistPipe2Pipe))
|
|
{
|
|
data.pLine = ((*it).second).first;
|
|
data.ptLink = pt1;
|
|
data.vecPts.push_back(pt2);
|
|
if (!data.bInWall)
|
|
{
|
|
data.dLinkLen = (*it).first + GetDist(ptSan, pt2);
|
|
}
|
|
else
|
|
{
|
|
data.dLinkLen = (*it).first + GetDist(data.ptInWall, pt2);
|
|
}
|
|
bRet = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
/*
|
|
*
|
|
*
|
|
ptCorner1*********************** ptLink
|
|
* *
|
|
* *
|
|
*
|
|
ptSan*******ptCorner2
|
|
|
|
洁具连接管线示意图,ptSan为洁具点
|
|
*/
|
|
AcGePoint3d pt1 = (*it).second.second, pt2 = ptSan;
|
|
AcGeVector3d vtMove = vtOffset;
|
|
if (OffsetLine(pt1, pt2, m_dDistPipe2Wall, vtMove, OFFSET_TIME))
|
|
{
|
|
AcGeVector3d vtMove2 = pt1 - pt2;
|
|
vtMove2.z = 0.0;
|
|
vtMove2.normalize();
|
|
AcGePoint3d pt3 = ptSan, pt4 = pt2;
|
|
if (IsConflicting(pt3, pt4, m_dDistPipe2Pipe))
|
|
{
|
|
if (OffsetLine(pt3, pt4, m_dDistPipe2Wall, vtMove2, OFFSET_TIME) && !IsConflicting(ptSan, pt3, m_dDistPipe2Pipe))
|
|
{
|
|
data.pLine = ((*it).second).first;
|
|
data.ptLink = pt1;
|
|
data.dLinkLen = (*it).first + GetDist(pt3, pt4);
|
|
data.vecPts.push_back(pt4);
|
|
data.vecPts.push_back(pt3);
|
|
bRet = true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::LinkSanitary2Pipe( const LinkDate &data )
|
|
{
|
|
AcGePoint3d ptFeed;
|
|
PipeType type;
|
|
switch(data.nTransformTime)
|
|
{
|
|
case 0:
|
|
{
|
|
ExtendLine(data.pLine, data.ptLink);
|
|
ptFeed = data.ptLink;
|
|
type = eSmallPipe;
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
if (data.vecPts.size() == 1)
|
|
{
|
|
ExtendLine(data.pLine, data.ptLink);
|
|
CreateVirtualPipe(data.ptLink, data.vecPts[0], eBranch);
|
|
ptFeed = data.vecPts[0];
|
|
type = eSmallPipe;
|
|
}
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
if (data.vecPts.size() == 2)
|
|
{
|
|
ExtendLine(data.pLine, data.ptLink);
|
|
CreateVirtualPipe(data.ptLink, data.vecPts[0], eBranch);
|
|
CreateVirtualPipe(data.vecPts[0], data.vecPts[1], eBranch);
|
|
ptFeed = data.vecPts[1];
|
|
type = eSmallPipe;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
return;
|
|
}
|
|
|
|
if (IsPipe(data.idSan))
|
|
{
|
|
AcGePoint3d ptSan = data.ptSan;
|
|
ptSan.z = ptFeed.z;
|
|
CreateVirtualPipe(ptFeed, ptSan, eMainPipe);
|
|
}
|
|
else
|
|
{
|
|
LinkSanitary(data.ptSan, ptFeed, data.idSan, type, data.bInWall, data.ptInWall);
|
|
}
|
|
}
|
|
|
|
double ConcealInstallSanitarySys::GetDist( const AcGePoint3d &pt1, const AcGePoint3d &pt2 )
|
|
{
|
|
AcGePoint3d ptS = pt1, ptE = pt2;
|
|
ptS.z = 0.0;
|
|
ptE.z = 0.0;
|
|
return ptS.distanceTo(ptE);
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::ModifyLinkSanPt(LinkDate &data)
|
|
{
|
|
// 当洁具点在墙外时,以洁具点暗装时到墙体的投影点为虚拟洁具点进行连接
|
|
AcGeVector3d vtDir;
|
|
GetSanitaryDir(vtDir, data.idSan);
|
|
AcGePoint3d ptSan = data.ptSan, ptWall;
|
|
if (GetPtInWall(ptWall, ptSan, vtDir) && ptSan.distanceTo(ptWall) > 0.001)
|
|
{
|
|
data.ptSan = ptWall; // 将洁具点到墙体的投影点当做待连接洁具点
|
|
data.ptInWall = ptSan;
|
|
data.bInWall = true;
|
|
}
|
|
}
|
|
|
|
bool ConcealInstallSanitarySys::PipePassFeedPt( AcDbLine *pLine, const AcGePoint3d &ptFeed, const CString &sLayer)
|
|
{
|
|
AcGePoint3d ptTemp = ptFeed;
|
|
AcGePoint3d ptS = pLine->startPoint();
|
|
AcGePoint3d ptE = pLine->endPoint();
|
|
ptTemp.z = ptS.z;
|
|
// 供水点在线的端点处
|
|
if (ptS.distanceTo(ptTemp) < 0.001 || ptE.distanceTo(ptTemp) < 0.001)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 供水点在线内
|
|
double dLen = ptS.distanceTo(ptE);
|
|
double dDist = ptS.distanceTo(ptTemp) + ptE.distanceTo(ptTemp);
|
|
if (fabs(dDist - dLen) < 0.001)
|
|
{
|
|
int iPipeIdx = GetPipeLayerIdxByName(sLayer);
|
|
CString sLineType = GetPipeWireLayLineType(sLayer);
|
|
CString sMaterial = GetPipeMaterialByIdx(g_iPipeMaterial[iPipeIdx]);
|
|
CString sDnType = GetDnByMat(sMaterial);
|
|
CString sLineType2 = GetLayerLineType(sLayer);
|
|
|
|
TDbPipe *pPipe = new TDbPipe();
|
|
pPipe->SetStartPoint(ptTemp);
|
|
pPipe->SetEndPoint(ptS);
|
|
pPipe->SetFlowDir(TPipeSys::kFromStart);
|
|
if(sLineType2.Find(_T("TG")) > -1)
|
|
{
|
|
XLine line(asDblArray(ptTemp), asDblArray(ptS));
|
|
double nAng = line.Direction();
|
|
if(nAng > PI/2 && nAng < (PI/2*3 + 0.001))
|
|
{
|
|
pPipe->SetStartPoint(ptS);
|
|
pPipe->SetEndPoint(ptTemp);
|
|
pPipe->SetFlowDir(TPipeSys::kFromEnd);
|
|
}
|
|
}
|
|
pPipe->SetDnDiameter(m_dPipeDn);
|
|
pPipe->setLayer(sLayer);
|
|
pPipe->SetSysType(GetPipeSysByLayer(sLayer));
|
|
pPipe->setColor(AcCmColor()); //随层
|
|
pPipe->SetPipeWeight(g_nPipeWidth[iPipeIdx]);
|
|
pPipe->setLinetype(sLineType);
|
|
pPipe->setLineWeight(AcDb::kLnWtByLayer);
|
|
pPipe->SetMaterial(g_iPipeMaterial[iPipeIdx]);
|
|
pPipe->SetLabel(sDnType);
|
|
AddToCurrentSpace(pPipe, Adesk::kTrue);
|
|
|
|
TDbPipe *pPipe2 = new TDbPipe();
|
|
pPipe2->SetStartPoint(ptTemp);
|
|
pPipe2->SetEndPoint(ptE);
|
|
pPipe2->SetFlowDir(TPipeSys::kFromStart);
|
|
if(sLineType2.Find(_T("TG")) > -1)
|
|
{
|
|
XLine line(asDblArray(ptTemp), asDblArray(ptE));
|
|
double nAng = line.Direction();
|
|
if(nAng > PI/2 && nAng < (PI/2*3 + 0.001))
|
|
{
|
|
pPipe2->SetStartPoint(ptE);
|
|
pPipe2->SetEndPoint(ptTemp);
|
|
pPipe2->SetFlowDir(TPipeSys::kFromEnd);
|
|
}
|
|
}
|
|
pPipe2->SetDnDiameter(m_dPipeDn);
|
|
pPipe2->setLayer(sLayer);
|
|
pPipe2->SetSysType(GetPipeSysByLayer(sLayer));
|
|
pPipe2->setColor(AcCmColor()); //随层
|
|
pPipe2->SetPipeWeight(g_nPipeWidth[iPipeIdx]);
|
|
pPipe2->setLinetype(sLineType);
|
|
pPipe2->setLineWeight(AcDb::kLnWtByLayer);
|
|
pPipe2->SetMaterial(g_iPipeMaterial[iPipeIdx]);
|
|
pPipe2->SetLabel(sDnType);
|
|
AddToCurrentSpace(pPipe2, Adesk::kTrue);
|
|
return true;
|
|
}
|
|
// 供水点不在线上
|
|
return false;
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::ModifyMainPipePt( AcGePoint3d &ptS, AcGePoint3d &ptE )
|
|
{
|
|
TDbPipe *pPipe = NULL;
|
|
acdbOpenObject(pPipe, m_idPipe, AcDb::kForRead);
|
|
if (pPipe != NULL)
|
|
{
|
|
if (!pPipe->IsVertical())
|
|
{
|
|
AcGePoint3d pt1 = pPipe->StartPoint();
|
|
AcGePoint3d pt2 = pPipe->EndPoint();
|
|
AcGeVector3d vt1 = pt1 - pt2;
|
|
AcGeVector3d vt2 = ptS - ptE;
|
|
AcGeTol tol;
|
|
tol.setEqualVector(0.001);
|
|
if (vt2.isParallelTo(vt1, tol))
|
|
{
|
|
if (ptS.distanceTo(pt1) < 0.001)
|
|
{
|
|
if (ptS.distanceTo(ptE) < pt1.distanceTo(pt2))
|
|
{
|
|
ptE = pt2;
|
|
}
|
|
}
|
|
else if (ptS.distanceTo(pt2) < 0.001)
|
|
{
|
|
if (ptS.distanceTo(ptE) < pt1.distanceTo(pt2))
|
|
{
|
|
ptE = pt1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pPipe->close();
|
|
}
|
|
}
|
|
|
|
void ConcealInstallSanitarySys::InsertFeedEquip()
|
|
{
|
|
std::map<AcDbObjectId,AcGePoint3d>::iterator it;
|
|
for (it = m_mapSan.begin(); it != m_mapSan.end(); it++)
|
|
{
|
|
DrawFeedEquip(it->first, it->second);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|