#include "StdAfx.h" #include "DrawDrainChamfer.h" // 返回值表示次管道是否修改 bool CDrawDrainChamfer::GetChamferInfo(const AcDbObjectId &IdPipeM, const AcDbObjectId &idPipeBra, std::map &dataMap, double dChamferLen) { // 打开次管道获得起点终点 TDbPipe *pPipe1 = NULL, *pPipe2 = NULL; AcGePoint3d ptS1, ptS2, ptE1, ptE2; acdbOpenObject(pPipe2, idPipeBra, AcDb::kForRead); if (pPipe2 != NULL) { if (pPipe2->GetFlowDir() == TPipeSys::kFromStart) { pPipe2->getStartPoint(ptS2); pPipe2->getEndPoint(ptE2); } else { pPipe2->getStartPoint(ptE2); pPipe2->getEndPoint(ptS2); } pPipe2->close(); } else { return false; } // 获得主管道起点终点 std::map::iterator it; it = dataMap.find(IdPipeM); if (it != dataMap.end()) { ptS1 = (*it).second[0]; ptE1 = (*it).second[1]; } else { acdbOpenObject(pPipe1, IdPipeM, AcDb::kForRead); if (pPipe1 != NULL) { if (pPipe1->GetFlowDir() == TPipeSys::kFromStart) { pPipe1->getStartPoint(ptS1); pPipe1->getEndPoint(ptE1); } else { pPipe1->getStartPoint(ptE1); pPipe1->getEndPoint(ptS1); } pPipe1->close(); } else { return false; } } AcGeVector3d vt1 = ptE1 - ptS1, vt2 = ptE2 - ptS2 ; AcGeTol tol; tol.setEqualVector(1e-3); if (vt1.isParallelTo(vt2, tol)) // 共线 { return false; } // 获得倒角值 double dLen = ptS1.distanceTo(ptE1); if (dLen < 1e-3) { return false; } if (dLen < dChamferLen) { dChamferLen = dLen; } vt1.normalize(); vt2.normalize(); ptS1 += vt1 * dChamferLen; ptE2 -= vt2 * dChamferLen; AcGePoint3dArray arPt; arPt.append(ptS2); // 按流向依次存入 arPt.append(ptE2); arPt.append(ptS1); it = dataMap.find(idPipeBra); if (it == dataMap.end()) { dataMap.insert(std::make_pair(idPipeBra, arPt)); return true; } return false; } bool CDrawDrainChamfer::IsVerticalPipe(const AcDbObjectId &id) { bool bRet = false; TDbPipe *pPipe = NULL; acdbOpenObject(pPipe, id, AcDb::kForRead); if (pPipe != NULL) { if (pPipe->IsVertical()) { bRet = true; } pPipe->close(); } return bRet; } // 判断管线是否在选择集中 bool CDrawDrainChamfer::IsValidPipe(PickSet &ssAll, AcDbObjectId &id) { ads_name sname; acdbGetAdsName(sname, id); Entity ent(sname); return ssAll.IsInclude(ent); } // 节点上所有的次管道是否在选择集内 bool CDrawDrainChamfer::IsAllVaildPipe(PickSet &ssAll, SSearchPipeList *pLst) { if (pLst == NULL) { return false; } int nNum = pLst->m_lstNode.Length(); for(int i = 0; i < nNum; i++) { ads_name sname; acdbGetAdsName(sname, pLst->m_lstNode[i]->m_ID); Entity ent(sname); if (!ssAll.IsInclude(ent)) { return false; } } return true; } // 是否有次管道与主管道共线 bool CDrawDrainChamfer::IsExistOnLine(AcDbObjectId &id, SSearchPipeList *pLst, SSearchPipeList *&pLstOut) { if (pLst != NULL) { TDbPipe *pPipe = NULL; AcGePoint3d ptS, ptE; acdbOpenObject(pPipe, id, AcDb::kForRead); if (pPipe != NULL) { pPipe->getStartPoint(ptS); pPipe->getEndPoint(ptE); pPipe->close(); } else { return false; } AcGeVector3d vt = ptS - ptE; int nNum = pLst->m_lstNode.Length(); AcGePoint3d pt1, pt2; AcGeTol tol; tol.setEqualVector(1e-3); for(int i = 0; i < nNum; i++) { pPipe = NULL; acdbOpenObject(pPipe, pLst->m_lstNode[i]->m_ID, AcDb::kForRead); if (pPipe != NULL) { pPipe->getStartPoint(pt1); pPipe->getEndPoint(pt2); pPipe->close(); AcGeVector3d vt1 = pt2 - pt1; if (vt.isParallelTo(vt1, tol)) { pLstOut = pLst->m_lstNode[i]; return true; } } } } return false; } // 两管是否共线 bool CDrawDrainChamfer::IsOnSameLine(const AcDbObjectId &id1, const AcDbObjectId &id2) { TDbPipe *pPipe1 = NULL, *pPipe2 = NULL; AcGePoint3d ptS1, ptS2, ptE1, ptE2; Acad::ErrorStatus st = acdbOpenObject(pPipe1, id1, AcDb::kForRead); if (pPipe1 != NULL) { pPipe1->getStartPoint(ptS1); pPipe1->getEndPoint(ptE1); pPipe1->close(); } else { return false; } st = acdbOpenObject(pPipe2, id2, AcDb::kForRead); if (pPipe2 != NULL) { pPipe2->getStartPoint(ptS2); pPipe2->getEndPoint(ptE2); pPipe2->close(); } else { return false; } AcGeVector3d vt1 = ptE1 - ptS1, vt2 = ptE2 - ptS2; vt1.normalize(); vt2.normalize(); AcGeTol tol; tol.setEqualVector(1e-3); if (vt1.isParallelTo(vt2, tol)) // 共线 { return true; } return false; } // 管道长度是否大于倒角长度 bool CDrawDrainChamfer::IsOverChamferLen(AcDbObjectId &id, double dChamferLen) { TDbPipe *pPipe = NULL; acdbOpenObject(pPipe, id, AcDb::kForRead); if (pPipe != NULL) { AcGePoint3d ptS, ptE; pPipe->getStartPoint(ptS); pPipe->getEndPoint(ptE); pPipe->close(); if (ptS.distanceTo(ptE) > dChamferLen) { return true; } } return false; } // 根据管道流向确定需要修改的管道id和修改后管道的起点终点以及倒角的起点终点 // 如果map中点数组的长度为2,则直接使用两点设置对应管道起始点即可 // 长度为3,则1和2点用途同上,2和3两点用于生成一段新管道(倒角) void CDrawDrainChamfer::GetPipeMap(SSearchPipeList *pListAll, std::map &dataMap, double dChamferLen, PickSet &ssAll, std::vector &vecId) { if (pListAll->m_iType == 0) { TDbPipe *pPipe = NULL; acdbOpenObject(pPipe, pListAll->m_ID, AcDb::kForRead); if (pPipe != NULL) { AcGePoint3d pt; BOOL bVPipe = pPipe->IsVertical(); if (pPipe->GetFlowDir() == TPipeSys::kFromStart) { pPipe->getStartPoint(pt); } else { pPipe->getEndPoint(pt); } pPipe->close(); if (bVPipe) // 立管 { int nLen = pListAll->m_lstNode.Length(); for(int i = 0; i < nLen; i++) { GetPipeMap(pListAll->m_lstNode[i], dataMap, dChamferLen, ssAll, vecId); } } else { SSearchPipeList *pLst = NULL; GetFristPipeNode(pListAll, pLst); if (pLst != NULL) { int nNum = pLst->m_lstNode.Length(); bool bVertical = false; // 次管道是否有立管 //节点处是否有立管 for(int j = 0; j < nNum; j++) { SSearchPipeList *pLstTmp = pLst->m_lstNode[j]; if (IsVerticalPipe(pLstTmp->m_ID)) { bVertical = true; } } bool bValidM = IsValidPipe(ssAll, pListAll->m_ID); // 主管道是否在集合内 SSearchPipeList *pLstOut = NULL; // 与主管道共线的次管道分支 bool bOnLine = IsExistOnLine(pListAll->m_ID, pLst, pLstOut); // 是否有次管道与主管道共线 bool bAllValid = IsAllVaildPipe(ssAll, pLst); // 是否所有次管道都在选择集内 int nPipe = 0; // 修改的次管道个数 double dMin = dChamferLen; // 被修改的次管道最小长度(长度小于倒角长度) // 获得需要修改的次管道的最小长度 if (!bVertical) { GetMinPipeLen(pLst, ssAll, pListAll->m_ID, dMin); if (dMin > dChamferLen) { dMin = dChamferLen; } } if (bValidM) { for (int i = 0; i < nNum; i++) { SSearchPipeList *pLstTmp = pLst->m_lstNode[i]; if (!bVertical && IsValidPipe(ssAll, pLstTmp->m_ID)) { if (GetChamferInfo(pListAll->m_ID, pLstTmp->m_ID, dataMap, dMin)) { nPipe++; } } GetPipeMap(pLstTmp, dataMap, dChamferLen, ssAll, vecId); } } else { for (int i = 0; i < nNum; i++) { SSearchPipeList *pLstTmp = pLst->m_lstNode[i]; if (!bVertical && IsValidPipe(ssAll, pLstTmp->m_ID)) { if (bAllValid && bOnLine || !bAllValid) { if (GetChamferInfo(pListAll->m_ID, pLstTmp->m_ID, dataMap, dMin)) { nPipe++; } } } GetPipeMap(pLstTmp, dataMap, dChamferLen, ssAll, vecId); } } // 处理多余管道(与主管道共线的次管道) bool bDel = false; if (!bVertical && bValidM && bAllValid && bOnLine && pLstOut != NULL && nPipe == nNum - 1) // 存在与主管道共线次管道 { if (pLstOut->m_lstNode.Length() == 1 && pLstOut->m_lstNode[0]->m_lstNode.Length() == 0) { if (!IsOverChamferLen(pLstOut->m_ID, dChamferLen)) { vecId.push_back(pLstOut->m_ID); bDel = true; } } } if (!bOnLine && nNum != 0 && nPipe == nNum && !bVertical && bValidM && bAllValid|| bDel) //处理主管道 { std::map::iterator it; it = dataMap.find(pListAll->m_ID); if (it == dataMap.end()) // 管道没有被处理过 { TDbPipe *pPipe = NULL; AcGePoint3d ptS, ptE; acdbOpenObject(pPipe, pListAll->m_ID, AcDb::kForRead); if (pPipe != NULL) { if (pPipe->GetFlowDir() == TPipeSys::kFromStart) { pPipe->getStartPoint(ptS); pPipe->getEndPoint(ptE); } else { pPipe->getStartPoint(ptE); pPipe->getEndPoint(ptS); } pPipe->close(); } AcGeVector3d vt = ptE - ptS; vt.normalize(); // 取得修改的次管道和主管道的长度最小值 double dLen = ptS.distanceTo(ptE); if (dLen > dChamferLen) { dLen = dChamferLen; } if (dMin < dLen) { dLen = dMin; } AcGePoint3d pt = ptS + vt * dLen; AcGePoint3dArray arPt; arPt.append(pt); arPt.append(ptE); dataMap.insert(std::make_pair(pListAll->m_ID, arPt)); } else // 管道已被处理过 { AcGePoint3d pt1, pt2; pt1 = (*it).second[0]; pt2 = (*it).second[1]; AcGeVector3d vt = pt2 - pt1; vt.normalize(); double dLen = pt1.distanceTo(pt2); if(dLen > dChamferLen) { dLen = dChamferLen; } if (dMin < dLen) { dLen = dMin; } pt = pt1 + vt * dLen; (*it).second[0] = pt; } } } } } } else { int nLen = pListAll->m_lstNode.Length(); for(int i = 0; i < nLen; i++) { GetPipeMap(pListAll->m_lstNode[i], dataMap, dChamferLen, ssAll, vecId); } } } void CDrawDrainChamfer::ModifyPipe(std::map &dataMap, std::vector &vecId) { // 修改原管道和生成倒角 std::map::iterator it; AcGePoint3dArray arPt; for(it = dataMap.begin(); it != dataMap.end(); it++) { AcDbObjectId id = (*it).first; arPt.setLogicalLength(0); arPt = (*it).second; int nLen = arPt.length(); if (nLen == 2 || nLen == 3) { TDbPipe *pPipe = NULL; acdbOpenObject(pPipe, id, AcDb::kForWrite); if (pPipe != NULL) { if (nLen == 3) // 生成倒角 { TDbPipe *pPipe1 = new TDbPipe; // zxl 2013.05.30 modify // pPipe1->CopyPropertiesFrom(pPipe, 0); pPipe1 = (TDbPipe*)pPipe->clone(); pPipe1->SetStartPoint(arPt[1]); pPipe1->SetEndPoint(arPt[2]); pPipe1->SetFlowDir(TPipeSys::kFromStart); pPipe1->setLayer(pPipe->layer()); // zxl 2013.05.29 add if (pPipe1->IsLabelValid()) { pPipe1->EnableDrawLabel(FALSE); } AddToCurrentSpace(pPipe1, Adesk::kTrue); } if (arPt[0].distanceTo(arPt[1]) > 1e-3) // 原管道修改后的长度 { XPoint ptLoc = pPipe->GetLabelLocation();// zxl 2013.05.29 add pPipe->SetStartPoint(arPt[0]); pPipe->SetEndPoint(arPt[1]); pPipe->SetFlowDir(TPipeSys::kFromStart); pPipe->SetLabelLocation(ptLoc);// zxl 2013.05.29 add } else { pPipe->erase(); } pPipe->close(); } } } // 删除多余管道(与主管道共线的长度不大于倒角长度的末端管道) std::vector::iterator it1; for (it1 = vecId.begin(); it1 != vecId.end(); it1++) { TDbPipe *pPipe = NULL; acdbOpenObject(pPipe, *it1, AcDb::kForWrite); if (pPipe != NULL) { pPipe->erase(); pPipe->close(); } } } void CDrawDrainChamfer::GetFristPipeNode(SSearchPipeList *pLstIn, SSearchPipeList *&pLstOut) { if (pLstIn != NULL) { int nLen = pLstIn->m_lstNode.Length(); if (nLen == 1) { pLstOut = pLstIn->m_lstNode[0]; } else if (nLen == 2) { SSearchPipeList *pLst1 = pLstIn->m_lstNode[0]; SSearchPipeList *pLst2 = pLstIn->m_lstNode[1]; int nLen1 = pLst1->m_lstNode.Length(); int nLen2 = pLst2->m_lstNode.Length(); if ((nLen1 > 0 && nLen2 == 0) || (nLen2 > 0 && nLen1 == 0)) { if (nLen1 > 0) { pLstOut = pLst1; } else { pLstOut = pLst2; } } } } } void CDrawDrainChamfer::GetMinPipeLen(SSearchPipeList *pLst, PickSet &ssAll, const AcDbObjectId &idM, double &dMin) { if (pLst != NULL) { TDbPipe *pPipe1 = NULL, *pPipe2 = NULL; AcGePoint3d ptS1, ptS2, ptE1, ptE2; acdbOpenObject(pPipe2, idM, AcDb::kForRead); if (pPipe2 != NULL) { pPipe2->getStartPoint(ptS2); pPipe2->getEndPoint(ptE2); pPipe2->close(); } else { return; } AcGeVector3d vt2 = ptS2 - ptE2, vt1; AcGeTol tol; tol.setEqualVector(1e-3); int nNum = pLst->m_lstNode.Length(); for (int i = 0; i < nNum; i++) { SSearchPipeList *pLstTmp = pLst->m_lstNode[i]; if (IsValidPipe(ssAll, pLstTmp->m_ID)) { acdbOpenObject(pPipe1, pLstTmp->m_ID, AcDb::kForRead); if (pPipe1 != NULL) { pPipe1->getStartPoint(ptS1); pPipe1->getEndPoint(ptE1); pPipe1->close(); vt1 = ptS1 - ptE1; if (!vt1.isParallelTo(vt2, tol)) // 不共线,次管道需要修改 { if (i == 0) { dMin = ptS1.distanceTo(ptE1); } else if (dMin > ptS1.distanceTo(ptE1)) { dMin = ptS1.distanceTo(ptE1); } } } } } } } void CDrawDrainChamfer::MakeChamfer(SSearchPipeList *pListAll, PickSet &ssAll, double dChamferLen) { std::map dataMap; std::vector vecId; // 需处理的的末端管道 GetPipeMap(pListAll, dataMap, dChamferLen, ssAll, vecId); // 得到需要修改的管道的信息并存入Map中 ModifyPipe(dataMap, vecId); }