#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 &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 vecNode = data.vecSanitaryNode; std::vector::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::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 &data, const AcGePoint3d &pt ) { // 计算洁具点与给水点在XOY平面内的距离 std::map mapDist; std::vector::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::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 > vecWall; std::vector >::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::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 > &mapDist, const AcGePoint3d &pt, const AcGeVector3d &vtDir, PipeType type ) { std::vector::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 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 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::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 > mapData; GetPtToLineDist(mapData, ptSan, vtPipe, eMainPipe); GetPtToLineDist(mapData, ptSan, vtPipe, eBranch); GetPtToLineDist(mapData, ptSan, vtPipe, eBranch2); // 找出与vtDir同向的直线 std::multimap > mapNew; std::multimap >::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::iterator it; for (it = m_mapSan.begin(); it != m_mapSan.end(); it++) { DrawFeedEquip(it->first, it->second); } }