#include "stdafx.h" #include "DuctPipeLink.h" #include "GlobalFunction.h" #include "TDbDuctNode.h" #include "HDbEquipment.h" static int ComparePoint(const XPoint* p1, const void* p2) { if (*p1 == *(const XPoint *)p2) return 0; return 1; } /*============================================================================* * 类 名: TDsNode ==============================================================================*/ TDsNode::~TDsNode() { ClearSS(); // 清空 } ////////// Set函数,同时修改连接、实体系统,只对TDbDuctNode有效 ////////// void TDsNode::SetLocation(const XPoint &ptLoc) // 位置坐标 { m_node.ptLocation = ptLoc; OPENOBJ_BEGIN(m_node.id, AcDb::kForWrite, TDbDuctNode, pNode); if (pNode != NULL) { pNode->SetLocation(ptLoc); } OPENOBJ_END(); } void TDsNode::SetMainDuct(const int &nMain) // 主风管标号 { m_nMain = nMain; OPENOBJ_BEGIN(m_node.id, AcDb::kForWrite, TDbDuctNode, pNode); if (pNode != NULL) { pNode->SetMainDuctNum(nMain); } OPENOBJ_END(); } ////////// 7.6新增辅助处理机制函数 ////////// void TDsNode::ClearSS() // 清空一系列辅助处理的数组或链表 { ids.Reset(); vs.Reset(); ss.Reset(); ps.Reset(); if (!mods.isEmpty()) { mods.removeSubArray(0, mods.logicalLength()-1); } if (!ws.isEmpty()) { ws.removeSubArray(0, ws.logicalLength()-1); } if (!hs.isEmpty()) { hs.removeSubArray(0, hs.logicalLength()-1); } if (!as.isEmpty()) { as.removeSubArray(0, as.logicalLength()-1); } } int TDsNode::SetInfo() // 获取节点连接情况的信息,初始化成员变量 { int nLen1 = Length(), nLen2 = m_types.logicalLength(); if (nLen1 != nLen2) { return -1; // 1、两个主要链表数量不一致 } ClearSS(); // 2、清空 OPENOBJ_BEGIN(m_node.id, AcDb::kForRead, TDbPipeNode, pNode); if (pNode != NULL) { if (pNode->isKindOf(TDbDuctNode::desc())) // 3、判断实体类型 { TDbDuctNode *pDuctNode = TDbDuctNode::cast(pNode); pDuctNode->GetAllLinkDucts(ids); // 4、首先读取实体中已存在的ID及类型 mods = pDuctNode->GetAllTypes(); } else { return 0; // 设备 } } OPENOBJ_END(); for (int i=0; iFindIdInLink(linkId); } OPENOBJ_END(); if (nIndex != -1) // 找到,此时节点ID一定会存在 { mods[nIndex] = nType; } } OPENOBJ_BEGIN(m_node.id, AcDb::kForRead, TDbDuctNode, pNode); if (pNode != NULL) { int nIndex = pNode->FindIdInLink(linkId); if (nIndex != -1) { int nOldType = pNode->GetIType(nIndex); if (nOldType==1 && nOldType!=nType) // 主要考虑复制后的节点连管线 { if (pNode->upgradeOpen() == Acad::eOk) { pNode->SetIType(nIndex, nType); pNode->downgradeOpen(); } } } } OPENOBJ_END(); } ws = ::GetWidths(m_node.id, ids, mods); // 6、获取TDbDuctNode需要的处理数据 hs = ::GetHeights(m_node.id, ids, mods); as = ::GetAngles(m_node.id, m_node.ptLocation, ids, mods); ::GetSegs(m_node.id, m_node.ptLocation, ids, mods, ss); ::GetVectors(m_node.id, m_node.ptLocation, ids, mods, vs); ::GetPtLocations(m_node.id, m_node.ptLocation, ids, mods, ps); return 1; } BOOL TDsNode::AssureArrayNum(int nNum) // 保证数组或链表长度正确 { int nLen1 = ids.Length(), nLen2 = vs.Length(), nLen3 = ss.Length(), nLen4 = ps.Length(), nLen5 = mods.logicalLength(), nLen6 = ws.logicalLength(), nLen7 = hs.logicalLength(), nLen8 = as.logicalLength(); if (nLen1!=nNum || nLen2!=nNum || nLen3!=nNum || nLen4!=nNum || nLen5!=nNum || nLen6!=nNum || nLen7!=nNum || nLen8!=nNum) { return FALSE; } return TRUE; } TDbDuctNode::DuctNodeType TDsNode::GetNewNType() // 获取新节点类型 { int nLen1 = ids.Length(), nLen2 = mods.logicalLength(); if (nLen1 != nLen2) { return TDbDuctNode::kOther; } if (!AssureArrayNum(nLen1)) { return TDbDuctNode::kOther; } return ::GetNodeType(m_node.id, m_node.ptLocation, mods, ids); } int TDsNode::GetOldIFNum(TDbDuctNode::DuctNodeType &nType) // 获取原接口数量及类型 { OPENOBJ_BEGIN(m_node.id, AcDb::kForRead, TDbDuctNode, pNode); if (pNode != NULL) { nType = pNode->GetNodeType(); return pNode->GetInterfaceNum(); } OPENOBJ_END(); return 0; } int TDsNode::FindSide(const TDsSide &pSide) // 查找是否与指定边有连接关系 { int nNum = Length(); for (int i=0; iCanLinkSide(side.GetId(), nPos); } OPENOBJ_END(); return bFind; } int nRet = this->FindSide(side), nNum = (nRet<0)?0:m_types[nRet]; XPoint ptVertex = side.GetPt((TPipeSys::PtLoction)nPos, nNum); bFind = m_node.EqualLocation(ptVertex); return bFind; } // 删除、替换接口,同TPsNode里的RemovePipeFromDb、ReplacePipeFromDb void TDsNode::RemoveInterface(const AcDbObjectId sideId) { OPENOBJ_BEGIN(m_node.id, AcDb::kForWrite, TDbDuctNode, pNode); if (pNode != NULL) { pNode->RemoveInterface(sideId); // 同时更新了两种接口 DList linkIds; pNode->GetAllLinkDucts(linkIds); AcDbIntArray types = pNode->GetAllTypes(); TDbDuctNode::DuctNodeType nType = // 获取节点的最新绘制类型 ::GetNodeType(m_node.id, pNode->GetLocation(), types, linkIds); pNode->SetNodeType(nType); } OPENOBJ_END(); } void TDsNode::ReplaceInterface(const AcDbObjectId &idOld, const AcDbObjectId &idNew) { OPENOBJ_BEGIN(m_node.id, AcDb::kForWrite, TDbDuctNode, pNode); if (pNode != NULL) { pNode->ReplaceInterface(idOld, idNew); } OPENOBJ_END(); } void TDsNode::UpdateLinkage(const TPipeSys::SysType st) // 根据节点对st类型管段的连接 { int nRet = SetInfo(); // 获取节点信息 if (nRet == -1) // 产生错误的情况 { return; } TDbDuctNode::DuctNodeType nType = GetNewNType(); // 获取最新绘制类型 OPENOBJ_BEGIN(m_node.id, AcDb::kForWrite, TDbPipeNode, pNode); if (pNode != NULL) { if (pNode->isKindOf(TDbDuctNode::desc())) // 节点 { TDbDuctNode *pDuctNode = TDbDuctNode::cast(pNode); pDuctNode->SetMainDuctNum(m_nMain); pDuctNode->UpdateInterface(st, m_node.ptLocation, ids, mods); pDuctNode->SetNodeType(nType); } else // 设备 { DList linkIds; linkIds.Reset(); int nLen = Length(); for (int i=0; iUpdateLinkage(m_node.ptLocation, st, linkIds); } } OPENOBJ_END(); } BOOL TDsNode::IsVisibal() const { BOOL bVisbal(FALSE); OPENOBJ_BEGIN(m_node.id, AcDb::kForRead, TDbPipeNode, pNode); if (pNode != NULL) { if (pNode->IsVisible() && pNode->visibility() == AcDb::kVisible) { bVisbal = TRUE; } } OPENOBJ_END(); return bVisbal; } /*============================================================================* * 类 名: TDsSide ==============================================================================*/ ////////// 构造函数 ////////// TDsSide::TDsSide(const AcDbObjectId &id): m_pStartNode(NULL), m_pEndNode(NULL), m_duct(id, XPoint(), XPoint()) { OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuct, pDuct); if (pDuct != NULL) { (XDirectionCurve &)(*this) = (XDirectionCurve &)(*pDuct); XPoint ptMin, ptMax; pDuct->GetExtend(ptMin, ptMax); m_duct.rect.lowLeft = ptMin; m_duct.rect.upRight = ptMax; } OPENOBJ_END(); } TDsSide::TDsSide(const TEntRect &duct): m_pStartNode(NULL), m_pEndNode(NULL), m_duct(duct) { OPENOBJ_BEGIN(m_duct.id, AcDb::kForRead, TDbDuct, pDuct); if (pDuct != NULL) { (XDirectionCurve &)(*this) = (XDirectionCurve &)(*pDuct); } OPENOBJ_END(); } ////////// 专用于节点直接相连函数 ////////// // 用于构造节点直接相连的情况,注:需要考虑start、end的情况 TDsSide::TDsSide(const AcDbObjectId &startId, const AcDbObjectId &endId): m_pStartNode(NULL), m_pEndNode(NULL), m_duct(AcDbObjectId::kNull, XPoint(), XPoint()) { XPoint ptStart, ptEnd; OPENOBJ_BEGIN(startId, AcDb::kForRead, TDbPipeNode, pNode); if (pNode != NULL) { ptStart = pNode->GetLocation(); } OPENOBJ_END(); OPENOBJ_BEGIN(endId, AcDb::kForRead, TDbPipeNode, pNode); if (pNode != NULL) { ptEnd = pNode->GetLocation(); } OPENOBJ_END(); (XDirectionCurve &)(*this) = XDirectionCurve(ptStart, ptEnd); } BOOL TDsSide::FindSide(AcDbObjectId id1, AcDbObjectId id2) { if ((!m_duct.id.isNull()) || (m_pStartNode==NULL)) { return FALSE; // ID一定不存在 } if (m_pEndNode != NULL) // 两个节点都存在 { AcDbObjectId idTmp1 = m_pStartNode->GetId(), idTmp2 = m_pEndNode->GetId(); if ((idTmp1==id1 && idTmp2==id2) || (idTmp1==id2 && idTmp2==id1)) { return TRUE; } } else // 起点存在,终点不存在 { AcDbObjectId id = m_pStartNode->GetId(); if ((id==id1) || (id==id2)) { return TRUE; } } return FALSE; } ////////// 重合部分的处理函数 ////////// BOOL TDsSide::IsFullDupSide(const TDsSide &side) const // 判断是否为全遮挡边 { if (m_duct.id != side.m_duct.id) { if ((XDirectionCurve &)side == (XDirectionCurve &)*this) { return TRUE; } } return FALSE; } ////////// Get函数 ////////// XPoint TDsSide::GetPt(const TPipeSys::PtLoction nSide, int nMod) const // 获取端点 { if (nMod == 0) // 正常接口 { OPENOBJ_BEGIN(GetId(), AcDb::kForRead, TDbDuct, pDuct); if (pDuct != NULL) { return pDuct->GetVertexPt(nSide); } OPENOBJ_END(); } if (nMod == 2) // 连接节点 { XPoint pt = (nSide==TPipeSys::kEndPt)?StartPoint():EndPoint(); return pt; } // 空接口,注:考虑以下处理是否有必要,或直接返回空 TDsNode *pFind = (nSide==TPipeSys::kEndPt)?m_pStartNode:m_pEndNode; if (pFind->IsDbObject()) // 要获取端的节点ID有效,注:是否包括ID为空 { int nRet = pFind->FindSide(*this); if (nRet != -1) { OPENOBJ_BEGIN(pFind->GetId(), AcDb::kForRead, TDbPipeNode, pNode); if (pNode != NULL) { return pNode->GetILocation(nRet); } OPENOBJ_END(); } } return XPoint(); } ////////// 处理函数 ////////// BOOL TDsSide::MergeWith(TDsSide &other, const TDsNode &merge) // 对数据库对象进行合并 { if (!IsDbObject() || !other.IsDbObject()) { return FALSE; } ASSERT(m_pStartNode==&merge || m_pEndNode==&merge); ASSERT(other.m_pStartNode==&merge || other.m_pEndNode==&merge); OPENOBJ_BEGIN(GetId(), AcDb::kForWrite, TDbDuct, pThisDuct); if (pThisDuct == NULL) { return FALSE; } OPENOBJ_BEGIN(other.GetId(), AcDb::kForWrite, TDbDuct, pOtherDuct); if (pOtherDuct == NULL) { return FALSE; } if (pThisDuct->MergeWith(*pOtherDuct)) // 调用duct中重写的函数 { (XDirectionCurve &)*this = *pThisDuct; // 修改TDsSide的StartPoint()、EndPoint() XPoint ptNew; TDsNode* pNotLinkNode = // other上,不是连接点的端点 other.m_pStartNode==&merge?other.m_pEndNode:other.m_pStartNode; if (m_pStartNode == &merge) // 判断连接点在this上的位置 { m_pStartNode = pNotLinkNode; ptNew = pThisDuct->StartPoint(); } else { m_pEndNode = pNotLinkNode; ptNew = pThisDuct->EndPoint(); } TDsNode &rNode = *pNotLinkNode; // 对other的引用改为对this的引用 for (int n=0; nReplaceInterface(other.GetId(), GetId()); // 注:此处有问题,打不开管线 } OPENOBJ_END(); } } rNode.SetLocation(ptNew); return TRUE; } OPENOBJ_END(); OPENOBJ_END(); return FALSE; } // 更新管线对节点的连接,针对DList // 思路:修改管线端点的位置,保证连接关系正确 void TDsSide::UpdateLinkage(const XPoint ptNew, const TPipeSys::PtLoction nSide) { if (m_duct.id.isNull()) // 注:连接节点的时候先不考虑改 { return; } int n = (int)nSide; AcDbObjectId nodeId = (n==0)?m_pStartNode->GetId():m_pEndNode->GetId(); OPENOBJ_BEGIN(GetId(), AcDb::kForWrite, TDbDuct, pDuct); if (pDuct != NULL) { XPoint ptMid = pDuct->MidPoint(); if (n == 0) { StartPoint() = ptNew; // 1、更新连接系统 pDuct->StartPoint() = ptNew; // 2、更新实体系统 } else { EndPoint() = ptNew; pDuct->EndPoint() = ptNew; } double dBulge = pDuct->GetBulge(); if (fabs(dBulge) > 1.0E-5) { XArc arc(pDuct->StartPoint(), ptMid, pDuct->EndPoint()); dBulge = arc.Bulge(); XPoint pt1, pt2; arc.GetStartPoint(pt1); arc.GetEndPoint(pt2); // arc.GetPoints(pt1, pt2); if (pt1.Distance(pDuct->StartPoint()) > PS_SNAP) // 交换了起点、终点 { dBulge *= -1; } pDuct->SetBulge(dBulge); } pDuct->SetNode(n, nodeId); pDuct->ResetDrawSpeed(); } OPENOBJ_END(); OPENOBJ_BEGIN(nodeId, AcDb::kForWrite, TDbDuctNode, pNode); if (pNode != NULL) // 3、更新连接的节点 { int nIndex = pNode->FindIdInLink(GetId()); if (nIndex != -1) // 存在连接关系 { pNode->SetILocation(nIndex, ptNew); } } OPENOBJ_END(); } /*============================================================================* * 类 名: TDuctLinkSys ==============================================================================*/ /////////////初始化TDuctLinkSys系统,同TSearchPipeSys里的InitStart///////////// void TDuctLinkSys::InitSystem(TPipeSys::SysType st, const DList &lstDucts, const DList &lstNodes, const XPointList &lstBreaks) // 系统入口 { int nCount = lstNodes.Length(), i(0); for (i=0; iIsAutoLiving()) // 自动生成 { if (IsDupNode(node)) // 完全重合 { m_lstDupNode.Append(new AcDbObjectId(node.id)); } else { TDsNode *pNewNode = new TDsNode(node, TRUE); m_lstAllNode.Append(pNewNode); if (pNode->isKindOf(TDbDuctNode::desc())) // 打断点 { TDbDuctNode *pDuctNode = TDbDuctNode::cast(pNode); pNewNode->m_nMain = pDuctNode->GetMainDuctNum(); // 主风标号 } } } else // TDbDuctNode、THDbEquipment都可见 { TDsNode *pNewNode = new TDsNode(node, FALSE); if (m_lstAllNode.Length()!=0 && pNode->isKindOf(THDbEquipment::desc())) { m_lstAllNode[0]; // 设备优先 m_lstAllNode.Insert(pNewNode); } else { m_lstAllNode.Append(pNewNode); } if (pNode->isKindOf(TDbDuctNode::desc())) // 获取主风管标号 { TDbDuctNode *pDuctNode = TDbDuctNode::cast(pNode); pNewNode->m_nMain = pDuctNode->GetMainDuctNum(); } } OPENOBJ_END(); } nCount = lstDucts.Length(); acedSetStatusBarProgressMeter(_T("管线关系处理中..."), 0, nCount); for (i=0; iGetSysType()==st && pDuct->GetLength()>_distSnap) { if (!m_bOptimize && IsFullDupDuct(pDuct)) // 1、判断完全重合边 { m_lstDupDuct.Append(new AcDbObjectId(duct.id)); return; } TDsSide *pSide = new TDsSide(duct); // 2、创建边 m_lstAllSide.Append(pSide); for (int n = 0; n < 2; n++) // 3、首先处理管线两端连接的节点 { TDsNode *pNode = FindDsNode(*pSide, (TPipeSys::PtLoction)n); // 只读打开 if (pNode == NULL) // 查找pSide指定端的节点,是否在m_lstAllNode中 { pNode = new TDsNode(pSide->GetPt((TPipeSys::PtLoction)n, 0)); // 只读打开 m_lstAllNode.Append(pNode); // 不存在,新建 AcDbObjectId nodeId = pDuct->GetNode(n); // 节点Id OPENOBJ_BEGIN(nodeId, AcDb::kForRead, TDbPipeNode, pDbNode); if (pDbNode != NULL) { if (pDbNode->CanLinkSide(pSide->GetId(), n)) // 只读打开 { pNode->m_node.ptLocation = pDbNode->GetLocation(); pNode->m_node.id = nodeId; pNode->m_bAutoLiving = pDbNode->IsAutoLiving(); if (pDbNode->isKindOf(TDbDuctNode::desc())) { TDbDuctNode *pDbDuctNode = TDbDuctNode::cast(pDbNode); pNode->m_nMain = pDbDuctNode->GetMainDuctNum(); } } } OPENOBJ_END(); } pNode->Append(pSide); // 更新节点连接的边,Append到DStack pNode->m_types.append(0); // 正常接口 if (n == 0) // 更新边连接的节点 { pSide->m_pStartNode = pNode; } else { pSide->m_pEndNode = pNode; } if (pDuct->upgradeOpen() == Acad::eOk) { pDuct->SetNode(n, pNode->GetId()); // 注:为新修改的Merge做准备 pDuct->downgradeOpen(); } } } OPENOBJ_END(); } // 查找和pSide连接的指定节点,是否在m_lstAllNode中;同TSearchPipeSys里的FindPsNodeAt TDsNode* TDuctLinkSys::FindDsNode(const TDsSide &side, TPipeSys::PtLoction nSide) { TDsNode *pFind = NULL; int nCount = m_lstAllNode.Length(); for (int i=0; iFindNode(side, nSide)) // 判断能否与管线相连 { pFind = node; break; } } return pFind; } /////////////////////初始化系统2,lstDudts中没有管线的情况///////////////////// // 注:当找不到管线与节点的连接关系时,变换思路,从节点入手,找管线 void TDuctLinkSys::InitSystem2(TPipeSys::SysType st, const DList &lstNodes, const XPointList &lstBreaks) { int i(0), nCount = lstNodes.Length(); acedSetStatusBarProgressMeter(_T("管线关系处理中..."), 0, nCount); for (i=0; iHasInterface(st))) { return; } if (!m_bOptimize && IsDupNode(pDbNode->GetLocation())) // 1、完全重合节点 { m_lstDupNode.Append(new AcDbObjectId(node.id)); return; } TDsNode *pNode = new TDsNode(node, pDbNode->IsAutoLiving()); // 2、创建节点 m_lstAllNode.Append(pNode); if (pDbNode->isKindOf(THDbEquipment::desc())) { return; // 3、设备的处理放到DelSoleNodeFromDb函数中 } TDbDuctNode *pDuctNode = TDbDuctNode::cast(pDbNode); if (pDuctNode == NULL) // 以下部分全部是节点 { return; } int nLen = pDuctNode->GetInterfaceNum(); for (int m=0; mGetISysType(m); if (sysType != st) // 系统类型不符合 { continue; } AcDbObjectId id = pDuctNode->GetIPipe(m); if (id.isErased() || id.isNull()) // 有或者即将有空接口 { if (nLen == 1) { break; // 只有一个接口——堵头 } TDsSide *pSide = FindSideById(id); if (pSide == NULL) // 不存在,则新建 { pSide = new TDsSide(id); m_lstAllSide.Append(pSide); } pNode->Append(pSide); pNode->m_types.append(1); // 空接口 if (pDuctNode->GetIFlowDir(m) == TPipeSys::kInlet) // 接口流动方向 { pSide->m_pEndNode = pNode; // 进口——对应终点 } else { pSide->m_pStartNode = pNode; // 出口——对应起点 } continue; } BOOL bLinkNode(TRUE); // 连接节点 OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuct, pDuct); if (pDuct != NULL) { bLinkNode = FALSE; // 连接管线 } OPENOBJ_END(); TDsSide *pSide = NULL; if (bLinkNode) // 连接节点 { pSide = FindSideById(node.id, id); // 查看连接这两节点的虚拟边是否存在 if (pSide != NULL) // 存在 { pSide->m_pEndNode = pNode; } else // 不存在 { pSide = new TDsSide(node.id, id); // 两个节点直接相连,忽略管线长 m_lstAllSide.Append(pSide); pSide->m_pStartNode = pNode; } pNode->Append(pSide); // 更新节点连接的边,Append到DStack pNode->m_types.append(2); continue; } pSide = FindSideById(id); // 连接管线 if (pSide == NULL) // 找不到 { pSide = new TDsSide(id); m_lstAllSide.Append(pSide); } for (int n=0; n<2; n++) // 再由管线更新相连关系,所有的更新关系到节点结束 { TDsNode *pSideNode = FindDsNode(*pSide, (TPipeSys::PtLoction)n); // 只读打开 if (pSideNode == NULL) // 查找pSide指定端的节点,是否在m_lstAllNode中 { pSideNode = new TDsNode(pSide->GetPt((TPipeSys::PtLoction)n, 0)); m_lstAllNode.Append(pSideNode); // 不存在 AcDbObjectId nodeId; OPENOBJ_BEGIN(pSide->GetId(), AcDb::kForRead, TDbDuct, pDuct); if (pDuct != NULL) { nodeId = pDuct->GetNode(n); } OPENOBJ_END(); if (nodeId != node.id) // 避免重复打开实体 { OPENOBJ_BEGIN(nodeId, AcDb::kForRead, TDbPipeNode, pNewNode); if (pNewNode != NULL) { if (pNewNode->CanLinkSide(pSide->GetId(), n)) { pSideNode->m_node.ptLocation = pNewNode->GetLocation(); pSideNode->m_node.id = nodeId; pSideNode->m_bAutoLiving = pNewNode->IsAutoLiving(); if (pNewNode->isKindOf(TDbDuctNode::desc())) { TDbDuctNode *pDuctNode = TDbDuctNode::cast(pNewNode); pSideNode->m_nMain = pDuctNode->GetMainDuctNum(); } } } OPENOBJ_END(); } } pSideNode->Append(pSide); // 更新节点连接的边,Append到DStack pSideNode->m_types.append(0); if (n == 0) // 更新边连接的节点 { pSide->m_pStartNode = pSideNode; } else { pSide->m_pEndNode = pSideNode; } } } OPENOBJ_END(); } // 在m_lstAllSide中查找,是否存在该边,专用与两节点直接连接,与FindDsNode功能一致 TDsSide* TDuctLinkSys::FindSideById(AcDbObjectId id1, AcDbObjectId id2) { TDsSide *pFind = NULL; int nCount = m_lstAllSide.Length(); for (int i=0; iFindSide(id1, id2)) { pFind = side; break; } } return pFind; } ///////////////////////////////合并、打断处理////////////////////////////////// void TDuctLinkSys::MergeDucts(XPointList &lstCorners, PickSet &ssDel) // 合并 { int nLen = m_lstAllNode.Length(); for (int i=0; i=0 && nPoserase(); } OPENOBJ_END(); } lstCorners.Remove(nCornerPos); // 减变化的位置 return TRUE; } return FALSE; } void TDuctLinkSys::BreakDucts(XPointList &lstCorners) // 在给定位置打断管段 { int nLen = m_lstAllNode.Length(); for (int i=0; iIsDbObject() || side->GetId().isNull()) { continue; // 只对连接管线的进行处理 } if (node.m_node.Intersect(side->m_duct)) { if ((side->m_pStartNode==NULL) || (side->m_pEndNode==NULL)) { adsout << _T("\n严重警告: 管线的位置关系发生错乱! "); throw side; continue; } if (DealTaoDong(*side, node)) { continue; // 判断是否是掏洞的情况,如果是则不打断 } OPENOBJ_BEGIN(node.GetId(), AcDb::kForRead, TDbDuctNode, pDBNode); if (pDBNode != NULL) { TDbDuctNode::DuctNodeType nType = pDBNode->GetNodeType(); if (nType==TDbDuctNode::k3Corner || nType==TDbDuctNode::k4Corner || nType==TDbDuctNode::kTapered || nType==TDbDuctNode::kTianYuanDiFang) { continue; // 注:不需要打断,特殊样式时,节点位置在实体外 } } OPENOBJ_END(); ASSERT(side->IsDbObject()); OPENOBJ_BEGIN(side->GetId(), AcDb::kForWrite, TDbDuct, pDuct); if (pDuct != NULL) { AcDbObjectId idNewPipe = pDuct->BreakAt(node.GetLocation(), PS_SNAP); if (idNewPipe.isValid()) // 注:调用TDbPipePrototype中的函数 { UpdateBreak(pDuct, *side, node, idNewPipe); } } OPENOBJ_END(); } } } // 处理掏洞的情况 BOOL TDuctLinkSys::DealTaoDong(TDsSide &side, TDsNode &node) { OPENOBJ_BEGIN(node.GetId(), AcDb::kForRead, TDbDuctNode, pDBNode); if (pDBNode!=NULL && pDBNode->Is(_T("TaoDong"))) // 节点存在,并且是掏洞 { return TRUE; } OPENOBJ_END(); if (node.Length() != 1) { return FALSE; // 1、判断节点中已连管线数量,保证产生的三通,应已连了支管 } Adesk::UInt8 n3TType(2); double dTmp1(1), dTmp2(PI/6); ::GetDNodeConfig(TDbDuctNode::kTaoDong, n3TType, dTmp1, dTmp2); if ((n3TType!=13) && (n3TType!=14) && (n3TType!=15)) { return FALSE; // 2、获取参数,判断是否是掏洞 } OPENOBJ_BEGIN(side.GetId(), AcDb::kForRead, TDbDuct, pDuct); if (pDuct == NULL) { return FALSE; } XPoint ptLoc = node.GetLocation(), ptOnCurve; if (pDuct->getClosestPointTo(ptLoc, ptOnCurve) != Acad::eOk) { return FALSE; } if (ptLoc.Distance(ptOnCurve) > PS_SNAP) { return FALSE; } XCurveSegment seg = pDuct->GetCurve(); if ((ptLoc&seg) != PR_INSIDE) // 会产生打断,又是掏洞 { return FALSE; } node.Append(&side); node.m_types.append(3); // 掏洞 OPENOBJ_END(); return TRUE; } // 更新打断管线的连接;并判断新管段是否有重合的管段,有则删除;同时更新连接关系 // pDuct、side:被打断管线;node:打断点 // 注:此处的算法是原终点处的节点保持不动,连接到新管线的终点;新节点连接到被打断管线的终点 void TDuctLinkSys::UpdateBreak(TDbDuct* pDuct, TDsSide &side, TDsNode &node, AcDbObjectId &newDuctId) { (XDirectionCurve &)(side) = (XDirectionCurve &)(*pDuct); TDsNode &updEndNode = *side.m_pEndNode; // 注:由于风向影响,应该先考虑被打断的管段 if (IsFullDupDuct(side)) // 1、被打断的管段 { TDsNode &updStartNode = *side.m_pStartNode; for (int n=0; nerase(); } else { node.Append(&side); // 更新连接系统 node.m_types.append(0); side.m_pEndNode = &node; XRectAngle oldDuctRect(pDuct->GetStartPoint(), pDuct->GetEndPoint()); side.m_duct.rect = oldDuctRect; // 更新Rect pDuct->SetNode(1, node.GetId()); // 更新实体 } OPENOBJ_BEGIN(newDuctId, AcDb::kForRead, TDbDuct, pNewDuct); // 2、新打断的管段 if (pNewDuct == NULL) { return; } if (IsFullDupDuct(pNewDuct)) // 是重合管段 { if (pNewDuct->upgradeOpen() == Acad::eOk) { pNewDuct->erase(); pNewDuct->downgradeOpen(); } for (int n=0; nGetExtend(ptMin, ptMax); TEntRect pipeRect(newDuctId, ptMin, ptMax); TDsSide* pNewSide = new TDsSide(pipeRect); m_lstAllSide.Append(pNewSide); // 添加新管线 pNewSide->m_pStartNode = &node; pNewSide->m_pEndNode = &updEndNode; for (int n=0; nupgradeOpen() == Acad::eOk) { pNewDuct->SetNode(0, node.GetId()); pNewDuct->SetNode(1, updEndNode.GetId()); pNewDuct->downgradeOpen(); } } OPENOBJ_END(); } //////////////////////删除独立的节点///////////////////////// void TDuctLinkSys::DelSoleNodeFromDb(TPipeSys::SysType st, const XRectAngle *box) { for (int i=0; iIsVisible()) // 可见节点 { XPoint ptMin, ptMax; if (pNode->GetExtents(ptMin, ptMax) == Acad::eOk) { ptMax.z = ptMin.z = 0; if (!ExtendInBox02d(ptMin, ptMax, *box)) // 不在区域内 { continue; } } } else // 不可见节点 { XPoint ptLocation = pNode->GetLocation(); if (!PointInBox02d(ptLocation, *box)) // 不在区域内 { continue; } } } OPENOBJ_END(); } OPENOBJ_BEGIN(id, AcDb::kForWrite, THDbEquipment, pEquipment); if (pEquipment != NULL) // 3、先处理设备,不保留空接口,不连管线,则置空 { int nEquipNum = pEquipment->GetInterfaceNum(); for (int k=0; kGetIPipe(k); if (pEquipment->CanLinkSide(idPipe, 0)) { continue; } else if (pEquipment->CanLinkSide(idPipe, 1)) { continue; } OPENOBJ_BEGIN(idPipe, AcDb::kForRead, TDbDuct, pDuct); if ((pDuct==NULL) || (pDuct->FindEquipment(node.GetId()))) { continue; } pEquipment->SetIPipe(k, AcDbObjectId::kNull); // 置空 OPENOBJ_END(); } continue; } OPENOBJ_END(); int nLenNew = node.Length(); if (nLenNew != 0) // 4、判断现接口数量,为0才删除 { continue; } // 5、删除节点,注:以下情况只针对TDbDuctNode OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuctNode, pNode); // 不是暖通设备和风系统连接件,也不含有st类型的接口 if ((pNode==NULL) || (!pNode->HasInterface(st))) { m_lstAllNode.Remove(); // 注:st从m_lstInterface里读取的,而非最新情况 i--; continue; } DList oldIds; pNode->GetAllLinkDucts(oldIds); // 原接口ID BOOL bOnlySt = pNode->IsSoleType(st); // 是否只连接st类型的管线 if ((oldIds.Length() < 2) && bOnlySt) // 只有一种系统类型的堵头 { BOOL bDel(TRUE); // 是否删除的标记 if (box != NULL) // 判断旧的连接关系是否在更新区域内部 { int nOldLen = oldIds.Length(); for (int k=0; kGetExtend(ptMin, ptMax) != RTNORM) { continue; } ptMin.z = ptMax.z = 0; if (!ExtendInBox02d(ptMin, ptMax, *box)) { bDel = FALSE; // 不在区域内,不删 } } OPENOBJ_END(); } } if (bDel && (pNode->upgradeOpen() == Acad::eOk)) { pNode->erase(); pNode->downgradeOpen(); m_lstAllNode.Remove(); i--; continue; } } OPENOBJ_END(); } } //////////////////对管线、节点的关系判断部分///////////////// // 根据不同的节点类型,确定要更新的管线和节点,并生成更新信息链表 void TDuctLinkSys::JudgeNodeType(PickSet &ssDel) { for (int i=0; iGetStartPoint(), pDuct->GetEndPoint()); double dDist1 = ptLoc.Distance(pDuct->StartPoint()), dDist2 = ptLoc.Distance(pDuct->EndPoint()); nSide = (dDist1>dDist2+1.0E-6)?TPipeSys::kEndPt:nSide; } OPENOBJ_END(); if (nOld == 0) { ptLink = ptLoc; } else if (nOld == 1) { node.SetLocation(ptLink); } BuildUpdateDuct(*node.ids[0], ptLink, nSide, node.mods[0]); // 注:连接点在链表中 } else if (nNewType == TDbDuctNode::kElbow) // 弯头 { BOOL bConfig = (nOld!=2) || (nOld==2 && nNewType!=nOldType); bIsOk = CalElbowPts(node, bConfig, FALSE); } else if (nNewType == TDbDuctNode::kKouElbow) // 扣弯 { BOOL bConfig = (nOld!=2) || (nOld==2 && nNewType!=nOldType); bIsOk = CalElbowPts(node, bConfig, TRUE); } else if (nNewType==TDbDuctNode::kTapered || nNewType==TDbDuctNode::kTianYuanDiFang) // 变径,天圆地方 { BOOL bConfig = (nOld!=2) || (nOld==2 && nNewType!=nOldType); bIsOk = CalTaperedPts(node, bConfig); } else if (nNewType == TDbDuctNode::kYiZiElbow) // 乙字弯 { BOOL bConfig = (nOld!=2) || (nOld==2 && nNewType!=nOldType); bIsOk = CalYiZiElbowPts(node, bConfig); } else if (nNewType == TDbDuctNode::kTaoDong) // 掏洞 { BOOL bConfig = (nOld!=2) || (nOld==2 && nNewType!=nOldType); bIsOk = CalTaoDongPts(node, bConfig); } else if (nNewType == TDbDuctNode::k3Corner) // 三通 { BOOL bConfig = (nOld!=3) || (nOld==3 && nNewType!=nOldType); bIsOk = Cal3TPts(node, bConfig); } else if (nNewType == TDbDuctNode::k4Corner) // 四通 { BOOL bConfig = (nOld!=4) || (nOld==4 && nNewType!=nOldType); bIsOk = Cal4TPts(node, bConfig); } else if (nNewType==TDbDuctNode::kOther) // 其他:(1)预留的接口,(2)需要合并 { int nLength = node.Length(); if (nLength != 2) // 暂时不处理的情况 { m_lstAllNode.Remove(i); i--; continue; } if (::IsParallel(*node.vs[0], *node.vs[1]) == 0) // 平行且管径相同,合并 { continue; } XPointList ptCorners; ptCorners.Append(new XPoint(node.GetLocation())); bIsOk = MergeDuctAt(i, ptCorners, ssDel); if (bIsOk) { i--; } } if (!bIsOk) { // mcl add, 对于无法连接的节点进行坏节点标记,及隐藏,下次不再处理 AcDbObjectId idBad = m_lstAllNode[i]->GetId(); OPENOBJ_BEGIN(idBad, AcDb::kForWrite, TDbDuctNode, pNode); if (NULL != pNode) { pNode->SetVisible(FALSE); pNode->setVisibility(AcDb::kInvisible); } OPENOBJ_END(); node.SetBad(TRUE); m_lstAllNode.Remove(i); // adsout << _T("\n严重警告: 节点与管线连接关系发生错误,建议修改或重新绘制! "); throw &node; continue; } } } ///////////////弯头、扣弯///////////////////// BOOL TDuctLinkSys::CalElbowPts(TDsNode &node, const BOOL bConfig, const BOOL bKouElbow) { if (!node.AssureArrayNum(2)) { return FALSE; // 1、判断节管数量是否正确 } Adesk::UInt8 nMode = 0; // 2、获得曲率半径、绘制样式、虾米节数量 double dRate(1.0), dTmp(1.0); ::GetDNodeConfig(TDbDuctNode::kElbow, nMode, dRate, dTmp); OPENOBJ_BEGIN(node.GetId(), AcDb::kForWrite, TDbDuctNode, pNode); if (pNode != NULL) { nMode = bConfig?nMode:pNode->GetDrawMod(); dRate = bConfig?dRate:pNode->GetDrawParam(); dTmp = bConfig?dTmp:pNode->GetXMWNum(); pNode->SetDrawMod(nMode); // 3、注:保征参数正确 pNode->SetDrawParam(dRate); pNode->SetXMWNum((Adesk::UInt8)dTmp); } OPENOBJ_END(); double dDist(50); // 4、缩进距离,考虑曲率半径 BOOL bCircle1 = ::IsCircleDuct(node.GetId(), *node.ids[0], node.mods[0]), bCircle2 = ::IsCircleDuct(node.GetId(), *node.ids[1], node.mods[1]); if (bKouElbow && !bCircle1 && !bCircle2) // 方方相连,形成扣弯 { BOOL bIsVDuct1 = ::IsVerDuct(node.GetId(), *node.ids[0], node.mods[0]), bIsVDuct2 = ::IsVerDuct(node.GetId(), *node.ids[1], node.mods[1]); int nVDuctNum(0); if (!bIsVDuct1 && bIsVDuct2) { nVDuctNum = 1; } double dAngle1(0); if (node.ids[nVDuctNum]->isErased() || node.ids[nVDuctNum]->isNull()) { OPENOBJ_BEGIN(node.GetId(), AcDb::kForRead, TDbDuctNode, pNode); if (pNode != NULL) { dAngle1 = pNode->GetIVDAngle(nVDuctNum); } OPENOBJ_END(); } else { OPENOBJ_BEGIN(*node.ids[nVDuctNum], AcDb::kForRead, TDbDuct, pDuct); if (pDuct != NULL) { dAngle1 = pDuct->GetVDAngle(); } OPENOBJ_END(); } int nOther = nVDuctNum==0?1:0; double dAngle2 = ads_angle(XPoint(), *node.vs[nOther]), dAng = CT_std_angle(dAngle1-dAngle2); if (fabs(dAng-PI/2)GetDrawMod(); dAngle = bConfig?dAngle:pNode->GetDrawParam(); dLen = bConfig?dLen:pNode->GetDrawParam2(); pNode->SetDrawMod(nMode); // 3、注:保征参数正确 pNode->SetDrawParam(dAngle); pNode->SetDrawParam2(dLen); } OPENOBJ_END(); double dDist(400); // 4、计算缩进距离 if (nMode == 2) // 方式3——由用户输入长度 { dDist = dLen; } else if (nMode == 1) // 方式1——给定一个角度 { double dTmp1 = fabs(node.ws[0]-node.ws[1]), // 管线宽度差 dTmp2 = fabs(node.hs[0]-node.hs[1]), // 管线高度差 dTemp = max(dTmp1, dTmp2) * 0.5; // 注:从宽度、高度差中取一个较大的 dDist = dTemp/tan(dAngle/2); // 角度 } else if (nMode == 0) // 方式2——平均管径的一半 { dDist = (node.ws[0]+node.ws[1])/2; // 平均管径 } dDist *= 0.5; XVector3D vt1 = *node.vs[0], vt2 = *node.vs[1]; vt1.Normalize(); vt2.Normalize(); vt1.Scale(dDist); vt2.Scale(dDist); XPoint pt1, pt2; node.ss[0]->ProjectToMe(node.GetLocation(), pt1); node.ss[1]->ProjectToMe(node.GetLocation(), pt2); XPoint pt3 = pt1 + vt1, pt4 = pt2 + vt2; // 5、获得变径缩进点 BuildUpdateDuct(*node.ids[0], pt3, *node.ps[0], node.mods[0]); // 6、生成更新信息 BuildUpdateDuct(*node.ids[1], pt4, *node.ps[1], node.mods[1]); return TRUE; } /////////////////乙字弯/////////////////////// BOOL TDuctLinkSys::CalYiZiElbowPts(TDsNode &node, const BOOL bConfig) { if (!node.AssureArrayNum(2)) { return FALSE; // 1、判断节管数量是否正确 } Adesk::UInt8 nType = 1; // 2、获得绘制样式、角度、曲率半径 double dAngle(PI/6), dRate(1.0); ::GetDNodeConfig(TDbDuctNode::kYiZiElbow, nType, dAngle, dRate); OPENOBJ_BEGIN(node.GetId(), AcDb::kForWrite, TDbDuctNode, pNode); if (pNode != NULL) { nType = bConfig?nType:pNode->GetDrawMod(); dAngle = bConfig?dAngle:pNode->GetDrawParam(); dRate = bConfig?dRate:pNode->GetDrawParam2(); pNode->SetDrawMod(nType); // 3、注:保征参数正确 pNode->SetDrawParam(dAngle); pNode->SetDrawParam2(dRate); } OPENOBJ_END(); XPoint ptTmp; node.ss[0]->ProjectToMe(node.ss[1]->EndPoint(), ptTmp); double dH = fabs(ptTmp.Distance(node.ss[1]->EndPoint())), // 距离H dDist(0); // 4、计算缩进距离 if (nType == 0) // 双弧 { dDist = dH/(2*tan(dAngle/2)); } else { double dWidth1 = node.ws[0], dWidth2 = node.ws[1]; if (fabs(node.hs[0])>1.0E-5 && fabs(node.hs[1])>1.0E-5 && fabs(ptTmp.z-node.ss[1]->EndPoint().z)>1.0E-5) // 方风管变高 { dWidth1 = node.hs[0]; dWidth2 = node.hs[1]; } if (nType == 1) // 斜接 { double dL1 = dWidth1 * dRate * sin(dAngle), // 长度 dL2 = dWidth2 * dRate * sin(dAngle); double dH1 = dWidth1 * dRate * (1 - cos(dAngle)), // 距离 dH2 = dWidth2 * dRate * (1 - cos(dAngle)); double dH3 = dH - dH1 - dH2, dL3 = dH3/tan(dAngle); dDist = (dL1 + dL2 + dL3) * 0.5; } else // 角接 { double dL = dH/tan(dAngle); dDist = (dL + dWidth1 + dWidth2) * 0.5; } } XPoint pt1, pt2, ptNew1, ptNew2; node.ss[0]->ProjectToMe(node.GetLocation(), pt1); node.ss[1]->ProjectToMe(node.GetLocation(), pt2); ads_polar(pt1, node.as[0], dDist, ptNew1); // 5、获得缩进点 ads_polar(pt2, node.as[1], dDist, ptNew2); BuildUpdateDuct(*node.ids[0], ptNew1, *node.ps[0], node.mods[0]); // 6、生成更新信息 BuildUpdateDuct(*node.ids[1], ptNew2, *node.ps[1], node.mods[1]); return TRUE; } //////////////////三通//////////////////////// BOOL TDuctLinkSys::Cal3TPts(TDsNode &node, const BOOL bConfig) { if (!node.AssureArrayNum(3)) { return FALSE; // 1、判断节管数量是否正确 } Adesk::UInt8 nMod = 2; // 2、获得曲率半径、绘制样式 double dRate(1.0), dTmp(PI/6); ::GetDNodeConfig(TDbDuctNode::k3Corner, nMod, dRate, dTmp); AcDbObjectId idNode = node.GetId(); OPENOBJ_BEGIN(idNode, AcDb::kForWrite, TDbDuctNode, pNode); if (pNode != NULL) { nMod = bConfig?nMod:pNode->GetDrawMod(); dRate = bConfig?dRate:pNode->GetDrawParam(); dTmp = bConfig?dTmp:pNode->GetDrawParam2(); pNode->SetDrawMod(nMod); // 3、注:保征参数正确 pNode->SetDrawParam(dRate); pNode->SetDrawParam2(dTmp); } OPENOBJ_END(); XPoint pt3T = node.GetLocation(); TCalCornerPts cal(pt3T, idNode, 3); if (!cal.SetIdAndType(node.ids, node.mods)) // 4、调用三通点计算类 { return FALSE; } cal.SetParam(dRate, nMod); int nMain = cal.GetMainNum(); // 5、获取主风管标号 if (nMain==-1 || nMain<0 || nMain>3) { return FALSE; } int nIndex = FindNodeByPt(pt3T); // 6、修正主风管标号 if (nIndex != -1) { TDsNode &node = *m_lstAllNode[nIndex]; node.SetMainDuct(nMain); // 注:传递或准备传递给实体 } XPointList lstMidPtOff; ::GetDuctTrueMidPts(idNode, pt3T, node.ids, node.mods, lstMidPtOff); if (lstMidPtOff.Length() != 3) // 7、获取中心点在各支管上的投影位置 { return FALSE; } int nVDuct1(-1), nVDuct2(-1); // 8、获取连接的立管标号 ::Get3TVDuctNums(idNode, node.ids, node.mods, nVDuct1, nVDuct2); if ((nVDuct1 > -1) && (nVDuct2 > -1)) // 连1个水平管,2个立管的情况 { int nHDuct(0), nTmp(5); ::GetAnotherPipe(nVDuct1, nVDuct2, nHDuct, nTmp); // 获取立管编号 double dHDHigh(0); OPENOBJ_BEGIN(*node.ids[nHDuct], AcDb::kForRead, TDbDuct, pDuct); if (pDuct != NULL) { dHDHigh = (pDuct->IsCircleDuct())?pDuct->GetWidth():pDuct->GetHeight(); } OPENOBJ_END(); double dVDis = dHDHigh * 0.5, // 立管缩进 dHDis = dHDHigh * dRate + 50; // 水平管缩进 AcGeVector3d vec1 = node.vs[nHDuct]->AsAcGeVector3d(), vec2 = node.vs[nVDuct1]->AsAcGeVector3d(), vec3 = node.vs[nVDuct2]->AsAcGeVector3d(); XPoint pt1 = *lstMidPtOff[nHDuct] + XVector3D(vec1.normalize()*dHDis), pt2 = *lstMidPtOff[nVDuct1] + XVector3D(vec2.normalize()*dVDis), pt3 = *lstMidPtOff[nVDuct2] + XVector3D(vec3.normalize()*dVDis); // 9、生成更新信息 BuildUpdateDuct(*node.ids[nHDuct], pt1, *node.ps[nHDuct], node.mods[nHDuct]); BuildUpdateDuct(*node.ids[nVDuct1], pt2, *node.ps[nVDuct1], node.mods[nVDuct1]); BuildUpdateDuct(*node.ids[nVDuct2], pt3, *node.ps[nVDuct2], node.mods[nVDuct2]); return TRUE; } if (nVDuct1 > -1) // 连2个水平管,1个立管的情况 { double dDis = node.ws[nVDuct1] * dRate + 50; // 缩进 for (int j=0; j<3; j++) // 9、生成更新信息 { AcGeVector3d vec = node.vs[j]->AsAcGeVector3d(); XPoint pt = *lstMidPtOff[j] + XVector3D(vec.normalize()*dDis); BuildUpdateDuct(*node.ids[j], pt, *node.ps[j], node.mods[j]); } return TRUE; } AcDbIntArray branchs = ::GetCornerBranchNums(idNode, pt3T, node.ids, node.mods, nMain); if (branchs.logicalLength() != 2) // 9、获取支管编号,逆时针顺序 { return FALSE; } XPoint ptM, pt1, pt2; // 10、计算连接点的位置 if ((nMod==4) || (nMod==5) || (nMod==12)) // Y系列 { ptM = cal.Cal3TMainDuctPt(nMain, branchs[0], branchs[1]); pt1 = cal.Cal3TPoint(branchs[0], nMain, branchs[1]); pt2 = cal.Cal3TPoint(branchs[1], nMain, branchs[0]); } else if (nMod == 6) // 平行 { ptM = cal.Cal3TMainDuctPt(nMain, branchs[0], branchs[1]); pt1 = cal.Cal3TMainDuctPt(branchs[0], branchs[0], branchs[1]); pt2 = cal.Cal3TMainDuctPt(branchs[1], branchs[0], branchs[1]); } else if ((nMod==9) || (nMod==10)) // 斜插管 { cal.Cal3TPoint9(nMain, branchs[0], dTmp, ptM, pt1, pt2); } else if (nMod == 11) // 叉型 { ptM = cal.Cal3TMainDuctPt(nMain, branchs[0], branchs[1]); pt1 = cal.Cal3TPoint11(branchs[0]); pt2 = cal.Cal3TPoint11(branchs[1]); } else // 其他 { ptM = cal.Cal3TMainDuctPt(nMain, branchs[0], branchs[1]); XVector3D vtMain = *node.vs[nMain], vt1 = *node.vs[branchs[0]], vt2 = *node.vs[branchs[1]]; if (::IsParallel(vtMain, vt1) != 0) // vt1与主风平行 { pt1 = cal.Cal3TMainDuctPt(branchs[0], nMain, branchs[1]); pt2 = cal.Cal3TPoint(branchs[1], nMain, branchs[0]); } else if (::IsParallel(vtMain, vt2) != 0) // vt2与主风平行 { pt1 = cal.Cal3TPoint(branchs[0], nMain, branchs[1]); pt2 = cal.Cal3TMainDuctPt(branchs[1], nMain, branchs[0]); } else // 没有与主风平行的管线 { pt1 = cal.Cal3TPoint(branchs[0], nMain, branchs[1]); pt2 = cal.Cal3TPoint(branchs[1], nMain, branchs[0]); } } if (ptM==XPoint() || pt1==XPoint() || pt2==XPoint()) { return FALSE; } BuildUpdateDuct(*node.ids[nMain], ptM, *node.ps[nMain], node.mods[nMain]); // 11、生成更新信息 BuildUpdateDuct(*node.ids[branchs[0]], pt1, *node.ps[branchs[0]], node.mods[branchs[0]]); BuildUpdateDuct(*node.ids[branchs[1]], pt2, *node.ps[branchs[1]], node.mods[branchs[1]]); return TRUE; } //////////////////掏洞//////////////////////// BOOL TDuctLinkSys::CalTaoDongPts(TDsNode &node, const BOOL bConfig) { if (!node.AssureArrayNum(2)) { return FALSE; // 1、判断接管数是否正确 } Adesk::UInt8 nMod = 13; // 2、从CONFIG里获取绘制参数:样式、曲率半径 double dRate(1), dTmp2(0); ::GetDNodeConfig(TDbDuctNode::kTaoDong, nMod, dRate, dTmp2); if ((nMod!=13) && (nMod!=14) && (nMod!=15)) { nMod = 13; } int nMain = node.mods[0]==3?0:1, // 3、设置主风管标号:被掏洞管标号 nOther = 1 - nMain; // 支管标号 AcDbObjectId idNode = node.GetId(); BOOL bVDuct1 = ::IsVerDuct(idNode, *node.ids[nMain], node.mods[nMain]), bVDuct2 = ::IsVerDuct(idNode, *node.ids[nOther], node.mods[nOther]); if (bVDuct1 || bVDuct2) { nMod = 13; // 立管一律用样式13 } OPENOBJ_BEGIN(node.GetId(), AcDb::kForWrite, TDbDuctNode, pNode); if (pNode != NULL) { nMod = bConfig?nMod:pNode->GetDrawMod(); dRate = bConfig?dRate:pNode->GetDrawParam(); pNode->SetDrawMod(nMod); // 4、保证参数正确 pNode->SetDrawParam(dRate); } OPENOBJ_END(); int nIndex = FindNodeByPt(node.GetLocation()); if (nIndex != -1) { TDsNode &node = *m_lstAllNode[nIndex]; node.SetMainDuct(nMain); // 注:传递或准备传递给实体 } double dDist = node.ws[nMain]*0.5; if (bVDuct1 || bVDuct2) { dDist = node.hs[nMain]*0.5; } XVector3D vt = *node.vs[nOther]; vt.Normalize(); if (nMod != 13) { XPoint pt1, pt2, ptTmp1, ptTmp2, ptCen, ptLoc = node.GetLocation(); double dMAng = node.as[nMain], dBAng = node.as[nOther]; AcGeVector3d vt1 = node.vs[nMain]->AsAcGeVector3d(), vt2 = node.vs[nOther]->AsAcGeVector3d(); double dScale = vt1.dotProduct(vt2); dScale = (dScale>-1.0E-5)?1:(-1); ads_polar(ptLoc, dMAng, 10000*dScale, pt1); ads_polar(ptLoc, dBAng, 10000, pt2); double dRadius = node.ws[nOther]*(dRate-0.5) + 50 + dDist; ::AT_cal_fillet(pt1, ptLoc, pt2, dRadius, ptTmp1, ptCen, ptTmp2, TRUE); dDist = ptLoc.Distance(ptTmp2); } vt.Scale(dDist); XPoint ptNew = node.GetLocation() + vt; BuildUpdateDuct(*node.ids[nOther], ptNew, *node.ps[nOther], node.mods[nOther]); // 5、生成更新信息 return TRUE; } //////////////////四通//////////////////////// BOOL TDuctLinkSys::Cal4TPts(TDsNode &node, const BOOL bConfig) { if (!node.AssureArrayNum(4)) { return FALSE; // 1、判断节管数量是否正确 } Adesk::UInt8 nMod = 0; // 2、获得曲率半径、绘制样式 double dRate(1.0), dTmp(PI/6); ::GetDNodeConfig(TDbDuctNode::k4Corner, nMod, dRate, dTmp); OPENOBJ_BEGIN(node.GetId(), AcDb::kForWrite, TDbDuctNode, pNode); if (pNode != NULL) { nMod = bConfig?nMod:pNode->GetDrawMod(); dRate = bConfig?dRate:pNode->GetDrawParam(); dTmp = bConfig?dTmp:pNode->GetDrawParam2(); pNode->SetDrawMod(nMod); // 3、注:保征参数正确 pNode->SetDrawParam(dRate); pNode->SetDrawParam2(dTmp); } OPENOBJ_END(); TCalCornerPts cal(node.GetLocation(), node.GetId(), 4); if (!cal.SetIdAndType(node.ids, node.mods)) // 4、调用四通点计算类 { return FALSE; } cal.SetParam(dRate, nMod); int nMain = cal.GetMainNum(); // 5、获取主风管标号 if (nMain==-1 || nMain<0 || nMain>4) { return FALSE; } int nIndex = FindNodeByPt(node.GetLocation()); // 6、修正主风管标号 if (nIndex != -1) { TDsNode &node = *m_lstAllNode[nIndex]; node.SetMainDuct(nMain); // 注:传递或准备传递给实体 } AcDbIntArray branchs = ::GetCornerBranchNums(node.GetId(), node.GetLocation(), node.ids, node.mods, nMain); if (branchs.logicalLength() != 3) // 7、获取支管编号,逆时针顺序 { return FALSE; } XPoint ptM, pt1, pt2, pt3; // 8、根据类型获取缩进点的位置 if ((nMod == 6) || (nMod == 7)) { cal.Cal4TPoint7(nMain, branchs[0], branchs[1], dTmp, ptM, pt2, pt1, pt3); // 圆管四通 } else // 方管四通 { ptM = cal.Cal4TPoint(nMain, branchs[0], branchs[2], TRUE); pt1 = cal.Cal4TPoint(branchs[1], branchs[0], branchs[2], TRUE); pt2 = cal.Cal4TPoint(branchs[0], nMain, branchs[1], FALSE); pt3 = cal.Cal4TPoint(branchs[2], nMain, branchs[1], FALSE); } if (ptM==XPoint() || pt1==XPoint() || pt2==XPoint() || pt3==XPoint()) { return FALSE; } BuildUpdateDuct(*node.ids[nMain], ptM, *node.ps[nMain], node.mods[nMain]); // 9、生成更新信息 BuildUpdateDuct(*node.ids[branchs[0]], pt2, *node.ps[branchs[0]], node.mods[branchs[0]]); BuildUpdateDuct(*node.ids[branchs[1]], pt1, *node.ps[branchs[1]], node.mods[branchs[1]]); BuildUpdateDuct(*node.ids[branchs[2]], pt3, *node.ps[branchs[2]], node.mods[branchs[2]]); return TRUE; } // 构造更新信息 void TDuctLinkSys::BuildUpdateDuct(const AcDbObjectId &id, const XPoint &pt, const TPipeSys::PtLoction nPtLoc, int nType) { if ((nType == 1) || (nType == 2)) { return; } BOOL bRet(FALSE); int nCount = m_lstAllSide.Length(); for (int i=0; iGetSysType(); pDuct->GetExtend(ptMin, ptMax); } OPENOBJ_END(); TEntRect pipeRect(id, ptMin, ptMax); AddDuct(pipeRect, st); } UpdateDuctInfo *pipeInfo = new UpdateDuctInfo; pipeInfo->id = id; pipeInfo->nSide = nPtLoc; pipeInfo->pt = pt; if (!m_lstUpdate.FindNode(pipeInfo, CompareUpdateInfo)) { m_lstUpdate.Append(new UpdateDuctInfo(*pipeInfo)); } if (pipeInfo != NULL) { delete pipeInfo; pipeInfo = NULL; } } //////////////////////将节点加入数据库//////////////////////// void TDuctLinkSys::AddAutoNodeToDb(const XRectAngle* box) { for (int i=0; iGetId(), AcDb::kForRead, TDbDuct, pDuct); if (pDuct != NULL) { AcDbObjectId idNew = pDuct->AddNodeToDb(node.GetLocation(), node.ids, node.mods, node.GetMainDuct()); node.m_node.id = idNew; // 更新连接关系 } OPENOBJ_END(); } } } //////////////是否完全重合的管线、节点部分/////////////////// BOOL TDuctLinkSys::IsFullDupDuct(const XCurveSegment* pSeg) const { int nCount = m_lstAllSide.Length(); for (int i=0; iGetLocation(); pt2d.z = 0; if ((pt2d&box) == PR_INSIDE) { pNode->erase(); // 删除原节点 bRet = TRUE; } } OPENOBJ_END(); return bRet; } void TDuctLinkSys::DelDupDuctFromDb(const XRectAngle &box) { for (int i=0; iGetExtend(ptMin, ptMax)) { XRectAngle boxDuct(ptMin, ptMax); if ((boxDuct&box) == PR_INSIDE) { pDuct->erase(); bRet = TRUE; } } } OPENOBJ_END(); return bRet; } /////////////////对管线、节点的关系更新部分/////////////////// // 更新管线的连接信息 void TDuctLinkSys::UpdateDuctLinkage() { int nCount = m_lstUpdate.Length(); for (int i=0; iUpdateLinkage(info.pt, info.nSide); } } // 更新节点的连接信息 void TDuctLinkSys::UpdateNodeLinkage(TPipeSys::SysType st, const XRectAngle* box) { int nCount = m_lstAllNode.Length(); for (int i=0; iIsVisible()) // 可见 { XPoint ptMin, ptMax; if (pNode->GetExtents(ptMin, ptMax) == Acad::eOk) { if (ExtendInBox02d(ptMin, ptMax, *box)) { bInBox = TRUE; // 在范围内 } } else { adsout << _T("\n严重警告: 发生绘制错误, 无法继续绘制!"); throw &node; continue; } } else // 不可见的节点的判断 { XPoint ptLocation = pNode->GetLocation(); if (PointInBox02d(ptLocation, *box)) { bInBox = TRUE; } } } OPENOBJ_END(); } } else { bInBox = TRUE; } if (bInBox) { node.UpdateLinkage(st); // 更新接点连接关系 } } } // 更新管线上附着的节点关系 void TDuctLinkSys::ValidateClingNode() { int nLen = m_lstAllSide.Length(), i(0); for (i=0; iValidateEquipmentShip(); // 只处理设备关系 } OPENOBJ_END(); } nLen = m_lstAllNode.Length(); for (i=0; iGetInterfaceNum(); if (pNode->isKindOf(TDbDuctNode::desc())) { TDbDuctNode *pDbNode = TDbDuctNode::cast(pNode); for (int j=0; jGetIType(j) == 3) // 掏洞 { OPENOBJ_BEGIN(pDbNode->GetIPipe(j), AcDb::kForWrite, TDbDuct, pDuct); if (pDuct != NULL) { pDuct->AddEquipment(node.GetId()); } OPENOBJ_END(); } } continue; } if (pNode->isKindOf(THDbEquipment::desc())) { THDbEquipment *pEquipment = THDbEquipment::cast(pNode); for (int j=0; jGetIPipe(j); if (id.isNull()) { continue; } BOOL bCanLink1 = pEquipment->CanLinkSide(id, 0), bCanLink2 = pEquipment->CanLinkSide(id, 1); if (bCanLink1 || bCanLink2) { continue; } OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuct, pDuct); if (pDuct == NULL) { continue; } if (pDuct->CanAttachEquipment(*pEquipment, j)) { if (!pDuct->FindEquipment(node.GetId())) { if (pDuct->upgradeOpen() == Acad::eOk) { pDuct->AddEquipment(node.GetId()); pDuct->downgradeOpen(); } } } else // 断开 { if (pEquipment->upgradeOpen() == Acad::eOk) { pEquipment->SetIPipe(j, AcDbObjectId::kNull); pEquipment->downgradeOpen(); } if (pDuct->FindEquipment(node.GetId())) { if (pDuct->upgradeOpen() == Acad::eOk) { pDuct->RemoveEquipment(node.GetId()); pDuct->downgradeOpen(); } } } OPENOBJ_END(); } } OPENOBJ_END(); } } ////////////////////////////其他////////////////////////////// // 通过ID查找pSide是否在m_lstAllSide内,以获得pSide的连接关系 TDsSide* TDuctLinkSys::FindSideById(AcDbObjectId ductId) { TDsSide *pFind = NULL; int nCount = m_lstAllSide.Length(); for (int i=0; iGetId() == ductId) { pFind = side; break; } } return pFind; } // 通过pt查找pNode是否在m_lstAllNode内 int TDuctLinkSys::FindNodeByPt(const XPoint &ptLoc) const { int nIndex(-1); int nCount = m_lstAllNode.Length(); for (int i=0; i &ducts, const AcDbIntArray &aryTypes) { int nLen1 = ducts.Length(), nLen2 = aryTypes.logicalLength(); if ((nLen1!=nNum) || (nLen1!=nLen2)) { return FALSE; } ClearSS(); for (int i=0; iFindIdInLink(*ids[i]); if (nIndex != -1) // 存在连接关系 { dFlLen = pNode->GetFlangeDis(); dFlThick = pNode->GetFlangeThick(); } OPENOBJ_END(); } else { OPENOBJ_BEGIN(*ids[i], AcDb::kForRead, TDbDuct, pDuct); if (pDuct != NULL) { dFlLen = pDuct->GetFlChuTou(); dFlThick = pDuct->GetFlThick(); } OPENOBJ_END(); } flcs.append(dFlLen); flhs.append(dFlThick); } } int TCalCornerPts::GetBigNum(int nNum1, int nNum2) // 获取较大管径的角标 { if (fabs(ws[nNum1]-ws[nNum2])<1.0E-3) { return hs[nNum1]>(hs[nNum2]-1.0E-3)?nNum1:nNum2; } return ws[nNum1]>(ws[nNum2]+1.0E-3)?nNum1:nNum2; } // 获取numArray中,最大数的索引号,注:当最大值对应多个索引号时,全部返回 AcDbIntArray TCalCornerPts::GetMaxNumIndexs(const AcGeDoubleArray &numArray) { double dMax(0); int i(0), nIndex(0), nLen = numArray.logicalLength(); for (i=0; i(dMax+1.0E-6)) { dMax = dNum; nIndex = i; } } AcDbIntArray indexArray; indexArray.append(nIndex); for (i=0; iProjectToMe(ptTmp1, ptTmp2); return ptTmp2; // 交点 } ////////////////////////////////////////////////////////////// // 计算三通(试用于除9、10样式以外的三通)中主风管的缩进位置 XPoint TCalCornerPts::Cal3TMainDuctPt(int nMain, int nB1, int nB2) { if (nMod == 11) // 60度叉型 { double dA1 = (dRate*ws[nB1]+50) * (1-cos(PI/3)), dA2 = (dRate*ws[nB2]+50) * (1-cos(PI/3)); double dB1 = (0.5*ws[nB1]+flcs[nB1])*sin(PI/3) + 50*cos(PI/3), dB2 = (0.5*ws[nB2]+flcs[nB2])*sin(PI/3) + 50*cos(PI/3); double dDist1 = dA1 + dB1*tan(PI/3), // 主管分别距离两支管中心线的距离 dDist2 = dA2 + dB2*tan(PI/3); XPoint ptInt1 = GetIntPt(nMain, nB1), // 主管与支管1、主管与支管2中心线交点 ptInt2 = GetIntPt(nMain, nB2); if ((ptInt1==XPoint()) || (ptInt2==XPoint())) { return XPoint(); // 不相交 } ptInt1 = GetFlLocPt(nMain, dDist1, ptInt1); ptInt2 = GetFlLocPt(nMain, dDist2, ptInt2); XPoint ptTmp; ss[nMain]->ProjectToMe(pt, ptTmp); return ::GetFarPt(ptTmp, ptInt1, ptInt2); } double dDist(ws[nB1]*dRate + 50); if ((nMod==4) || (nMod==5) || (nMod==12)) // Y型系列 { dDist = max(ws[nB1], ws[nB2]) * dRate + 50; } else if (nMod == 6) // 平行型 { XPoint ptTmp; ss[nB1]->ProjectToMe(ss[nB2]->StartPoint(), ptTmp); // 两支管间距 dDist = ss[nB2]->StartPoint().Distance(ptTmp) * 0.5; } else // 普通 { XVector3D vtMain = *vs[nMain], vtP = *vs[nB2]; int nPNum = (::IsParallel(vtMain, vtP)!=0)?nB2:nB1, // 平行 nONum = (nPNum==nB2)?nB1:nB2; // 不平行 vtP = *vs[nPNum]; XVector3D vtO = *vs[nONum]; if (::IsParallel(vtMain, vtP) != 0) // 真的平行 { double dAngle = vtMain.AsAcGeVector3d().angleTo(vtO.AsAcGeVector3d()); if (fabs(dAngle - PI/2) < 1.0E-5) // 直角 { dDist = ws[nONum]*dRate + 50; } else // 保证法兰不相交 { dAngle = (dAngle>PI/2+1.0E-5)?(PI-dAngle):dAngle; dDist = GetDistFl(nMain, nONum, dAngle); } } else // 三个都不平行 { double dAng1 = vtMain.AsAcGeVector3d().angleTo(vtP.AsAcGeVector3d()), dAng2 = vtMain.AsAcGeVector3d().angleTo(vtO.AsAcGeVector3d()); if (dAng1 < (PI/2.0-1.0E-3)) // 锐角 { dAng1 = GetDistFl(nMain, nPNum, dAng1); // 保证法兰不相交 } else // 直角、钝角 { dAng1 = ws[nPNum]*dRate + 50; } if (dAng2 < (PI/2.0-1.0E-3)) // 锐角 { dAng2 = GetDistFl(nMain, nONum, dAng2); // 保证法兰不相交 } else // 直角、钝角 { dAng2 = ws[nONum]*dRate + 50; } dDist = max(dAng1, dAng2); } } return GetFlLocPt(nMain, dDist, *ps[nMain]); } // 计算三通中支风管缩进点的位置 XPoint TCalCornerPts::Cal3TPoint(int nSelf, int nMain, int nOther) { AcGeDoubleArray aryDist; AcGeVector3d vecSelf = vs[nSelf]->AsAcGeVector3d(); // 法向 for (int i=0; i<2; i++) { int nNum = i==0?nMain:nOther; AcGeVector3d vec = vs[nNum]->AsAcGeVector3d(); double dAngle = vecSelf.angleTo(vec), // 得到0~PI内的夹角 dDist(0); if (dAngle < (PI/2.0-1.0E-3)) // 锐角 { dDist = GetDistFl(nSelf, nNum, dAngle); // 保证法兰不相交 } else // 直角、钝角 { dDist = 0.5*(ws[nSelf]+ws[nMain])*dRate + 50; } aryDist.append(dDist); } if (aryDist.logicalLength() != 2) { return XPoint(); } double dDist = max(aryDist[0], aryDist[1]); return GetFlLocPt(nSelf, dDist, *ps[nSelf]); // 获得缩进点 } // 计算斜插三通样式中主、支风管缩进点的位置 void TCalCornerPts::Cal3TPoint9(int nMain, int nB1, double dAng, XPoint &ptM, XPoint &ptB1, XPoint &ptB2) { int nB2(-1), nTmp(5); ::GetAnotherPipe(nMain, nB1, nB2, nTmp); nTmp = ::IsParallel(*vs[nMain], *vs[nB1])?nB2:nB1; // 与主管不平行管线 int nOther = (nTmp==nB1)?nB2:nB1; // 与主管平行管线 AcGeVector3d vtO = vs[nOther]->AsAcGeVector3d(), vtT = vs[nTmp]->AsAcGeVector3d(); double dCurrent = vtO.angleTo(vtT); if ((dCurrentPI*11/18+1.0E-5)) { ptM = Cal3TMainDuctPt(nMain, nB1, nB2); if (nTmp == nB2) // vt1与主风平行 { ptB1 = Cal3TMainDuctPt(nB1, nMain, nB2); ptB2 = Cal3TPoint(nB2, nMain, nB1); } else // vt2与主风平行 { ptB1 = Cal3TPoint(nB1, nMain, nB2); ptB2 = Cal3TMainDuctPt(nB2, nMain, nB1); } return; } double dTmp1 = GetDistFl(nTmp, nOther, dAng), // 保证法兰不相交 dTmp2 = GetDistFl(nOther, nTmp, dAng), dTmp3 = ws[nTmp]*dRate + 50; double dDist1 = dTmp1*sin(dAng)+dTmp3*cos(dAng), // 不平行管缩进 dDist2 = dTmp2 - dTmp1*cos(dAng) - dTmp3*(1-sin(dAng)); // 平行管缩进 double dShort = max(flcs[nTmp], flcs[nOther])/tan(dAng*0.5) + 50, // 短线 dTmp4 = dShort + ws[nTmp]/sin(dAng) + 0.5*(flhs[nMain] + flhs[nOther]); if ((dTmp4 > dTmp2 + 1.0E-6) && (nMod == 9)) // 无法相交 { dTmp2 = dTmp4 + dShort; } double dDistM = dTmp2 - dDist2; // 主管缩进 ptM = GetFlLocPt(nMain, dDistM, *ps[nMain]); if (nTmp == nB2) { TchPrivate::Exchange(dDist1, dDist2); } ptB1 = GetFlLocPt(nB1, dDist1, *ps[nB1]); ptB2 = GetFlLocPt(nB2, dDist2, *ps[nB2]); } // 计算叉型三通样式中支风管缩进点的位置 XPoint TCalCornerPts::Cal3TPoint11(int nSelf) { double dDist = (dRate*ws[nSelf]+50) + (0.5*ws[nSelf]+flcs[nSelf]); dDist = dDist*sin(PI/3) + 50*cos(PI/3); return GetFlLocPt(nSelf, dDist, *ps[nSelf]); } ////////////////////////////////////////////////////////////// // 计算四通(试用于除6、7样式以外的四通)中主风管、支风管的缩进位置 XPoint TCalCornerPts::Cal4TPoint(int nSelf, int nNum1, int nNum2, BOOL bMain) { XPointList ptLst; for (int i=0; i<2; i++) { int nNum = i==0?nNum1:nNum2; // 相临风管标号 double dAngle = CT_acute_angle(as[nSelf] - as[nNum]), dDist = GetDistFl(nSelf, nNum, dAngle); // 保证法兰不相交 if (dAngle > (PI/2 - 1.0E-3)) // 夹角大于等于90度 { int nTmp = bMain?nNum:nSelf; dDist = ws[nTmp]*(dRate-0.5) + ws[nNum]*0.5 + 50; } XPoint ptInt = GetIntPt(nSelf, nNum), ptTmp; // 处理中心线交于不止一点 if (ptInt == XPoint()) { return XPoint(); } ads_polar(ptInt, as[nSelf], dDist, ptTmp); ptLst.Append(new XPoint(ptTmp)); } if (ptLst.Length() != 2) { return XPoint(); } XPoint ptLoc = *ps[nSelf]; // 中心点在各管线中心线上的投影 return ::GetFarPt(ptLoc, *ptLst[0], *ptLst[1]); } // 计算圆管四通样式中的主、支风管缩进点位置 void TCalCornerPts::Cal4TPoint7(int nMain, int nB1, int nB2, double dAng, XPoint &ptM, XPoint &pt1, XPoint &pt2, XPoint &pt3) { int nB3(-1); ::GetAnotherPipe(nMain, nB1, nB2, nB3); // 获取支管3的编号 AcGeVector3d vtMain = vs[nMain]->AsAcGeVector3d(), vtB1 = vs[nB1]->AsAcGeVector3d(), vtB3 = vs[nB3]->AsAcGeVector3d(); if (nMod == 6) // 不带弯头的圆管四通 { if (vtMain.isPerpendicularTo(vtB1)==Adesk::kTrue || // 主管与支1垂直 vtMain.isPerpendicularTo(vtB3)==Adesk::kTrue || // 主管与支3垂直 vtB1.isParallelTo(vtB3)==Adesk::kTrue) // 支1与支3平行 { ptM = Cal4TPoint(nMain, nB1, nB3, TRUE); // 同方管四通缩进 pt2 = Cal4TPoint(nB2, nB1, nB3, TRUE); pt1 = Cal4TPoint(nB1, nMain, nB2, FALSE); pt3 = Cal4TPoint(nB3, nMain, nB2, FALSE); return; } } double dAng1 = CT_acute_angle(as[nB1]-as[nB2]), dAng3 = CT_acute_angle(as[nB3]-as[nB2]); if (nMod == 7) { dAng1 = dAng; // 注:可备8.0允许输入两个角度使用 dAng3 = dAng; } double dTmp1 = GetDistFl(nB1, nB2, dAng1), // 保证法兰不相交的距离 dTmp3 = GetDistFl(nB3, nB2, dAng3); XPoint ptInt1 = GetIntPt(nB1, nB2), // 支管1与支管2、支管3与支管2中心线交点 ptInt3 = GetIntPt(nB3, nB2); if ((ptInt1==XPoint()) || (ptInt3==XPoint())) { return; // 不相交 } double dRadius1 = ws[nB1]*dRate + 50, // 弯头的曲率半径 dRadius3 = ws[nB3]*dRate + 50; double dDist1 = (nMod==6)?dTmp1:(dTmp1*sin(dAng1)+dRadius1*cos(dAng1)), dDist3 = (nMod==6)?dTmp3:(dTmp3*sin(dAng3)+dRadius3*cos(dAng3)); pt1 = GetFlLocPt(nB1, dDist1, ptInt1); // 支管1、3的缩进点 pt3 = GetFlLocPt(nB3, dDist3, ptInt3); ptInt1 = GetIntPt(nB2, nB1); // 支管2与支管1、3中心线交点 ptInt3 = GetIntPt(nB2, nB3); double dD1 = GetDistFl(nB2, nB1, dAng1), // 支管2距与支管1、3中心线交点的距离 dD2 = GetDistFl(nB2, nB3, dAng3), dD3(dD1), dD4(dD2); // dD1、dD2会被修改,备份一份 if (nMod == 7) // 带弯头的圆管四通 { dD1 = dD1 - dTmp1*cos(dAng1) - dRadius1*(1-sin(dAng1)); dD2 = dD2 - dTmp3*cos(dAng3) - dRadius3*(1-sin(dAng3)); } XPoint ptTmp1 = GetFlLocPt(nB2, dD1, ptInt1), ptTmp2 = GetFlLocPt(nB2, dD2, ptInt3); XPoint ptFar = ::GetFarPt(pt, ss[nB2]->GetStartPoint(), ss[nB2]->GetEndPoint()); pt2 = ::GetNearPt(ptFar, ptTmp1, ptTmp2); // 取一个较远点,作为支管2的缩进点 double dD5 = (pt2==ptTmp1)?0:(ptTmp1.Distance(ptTmp2)), // 小短线距离修正 dD6 = (pt2==ptTmp1)?(ptTmp1.Distance(ptTmp2)):0; ads_polar(ptTmp1, as[nB2], -dD3, ptTmp1); ads_polar(ptTmp2, as[nB2], -dD4, ptTmp2); ptInt1 = ::GetFarPt(ptFar, ptTmp1, ptTmp2); // 主管默认缩进点 double dShort1 = max(flcs[nB2], flcs[nB1])/tan(dAng1*0.5)+50+dD5, // 短线 dShort3 = max(flcs[nB2], flcs[nB3])/tan(dAng3*0.5)+50+dD6; dDist1 = dShort1+ws[nB1]/sin(dAng1)+0.5*(flhs[nMain]+flhs[nB2]); dDist3 = dShort3+ws[nB3]/sin(dAng3)+0.5*(flhs[nMain]+flhs[nB2]); double dDist = ptInt1.Distance(pt2); dDist = (dDist1>dDist+1.0E-3)?(dDist1+dShort1):dDist; dDist = (dDist3>dDist+1.0E-3)?(dDist3+dShort3):dDist; ads_polar(pt2, as[nB2], -dDist, ptInt3); ss[nMain]->ProjectToMe(ptInt3, ptM); // 修正后的主管缩进点 } //End TCalCornerPts /////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// // 所需要的全局函数 ///////////////////////////////////////////////////////////////////////////////// /*----------------------------------------------------------------------------* * 函数名称: GetNodeType * 功能描述: 通过与节点连接的管线数量,判断并返回节点类型 * 参 数: [in] id:被判断节点的ID [in] ptLoc:节点的位置 [in] aryType:节点最新连接的管线类型 [in] lstDuct:节点最新连接的管线 * 返 回 值: 返回节点类型 * 历 史: * 备 注: -----------------------------------------------------------------------------*/ TDbDuctNode::DuctNodeType GetNodeType(const AcDbObjectId id, const XPoint &ptLoc, const AcDbIntArray &types, const DList &ids) { int nLen = ids.Length(); if (nLen == 1) { return TDbDuctNode::kStem; // 一般堵头 } else if (nLen == 3) { return TDbDuctNode::k3Corner; // 三通 } else if (nLen == 4) { return TDbDuctNode::k4Corner; // 四通 } else if (nLen != 2) { return TDbDuctNode::kOther; // 其他 } DList lstVts; ::GetVectors(id, ptLoc, ids, types, lstVts); if (lstVts.Length() != 2) { return TDbDuctNode::kOther; // 其他 } if (::IsParallel(*lstVts[0], *lstVts[1]) != 0) // 平行或相反 { BOOL bCircle1 = ::IsCircleDuct(id, ids[0], types[0]), bCircle2 = ::IsCircleDuct(id, ids[1], types[1]); if (bCircle1 != bCircle2) { return TDbDuctNode::kTianYuanDiFang; // 天圆地方 } DList lstSegs; ::GetSegs(id, ptLoc, ids, types, lstSegs); AcGeDoubleArray widths = ::GetWidths(id, ids, types), highs = ::GetHeights(id, ids, types); if (widths.logicalLength()!=2 || highs.logicalLength()!=2 || lstSegs.Length()!=2) { return TDbDuctNode::kOther; } BOOL bIsVDuct1 = ::IsVerDuct(id, ids[0], types[0]), bIsVDuct2 = ::IsVerDuct(id, ids[1], types[1]); if (bIsVDuct1 && bIsVDuct2) // 连接两个立管 { if (fabs(widths[0]-widths[1])<1.0E-3 && fabs(highs[0]-highs[1])<1.0E-3) { return TDbDuctNode::kOther; } return TDbDuctNode::kTapered; // 变径 } double dEleMid1 = lstSegs[0]->StartPoint().z, dEleMid2 = lstSegs[1]->StartPoint().z, dEleUp1 = bCircle1?(dEleMid1+widths[0]/2):(dEleMid1+highs[0]/2), dEleUp2 = bCircle2?(dEleMid2+widths[1]/2):(dEleMid2+highs[1]/2), dEleLow1 = bCircle1?(dEleMid1-widths[0]/2):(dEleMid1-highs[0]/2), dEleLow2 = bCircle2?(dEleMid2-widths[1]/2):(dEleMid2-highs[1]/2); BOOL bSame1 = fabs(dEleMid1-dEleMid2) < 1.0E-6, bSame2 = fabs(dEleUp1-dEleUp2) < 1.0E-6, bSame3 = fabs(dEleLow1-dEleLow2) < 1.0E-6; XCurveSegment segUp1 = lstSegs[0]->Offset(-widths[0]/2, LS_FINITE), segUp2 = lstSegs[1]->Offset(widths[1]/2, LS_FINITE), segLow1 = lstSegs[0]->Offset(widths[0]/2, LS_FINITE), segLow2 = lstSegs[1]->Offset(-widths[1]/2, LS_FINITE), segMid1 = *lstSegs[0], segMid2 = *lstSegs[1]; segUp1.SetElevation(0); segUp2.SetElevation(0); segLow1.SetElevation(0); segLow2.SetElevation(0); segMid1.SetElevation(0); segMid2.SetElevation(0); BOOL bIsLine1 = ::Is2SegOnSeg(segUp1, segUp2), bIsLine2 = ::Is2SegOnSeg(segLow1, segLow2), bIsLine3 = ::Is2SegOnSeg(segMid1, segMid2); if (bSame1 && bSame2 && bSame3) // 三个标高都相等,三种情况都有可能 { if (bIsLine1 && bIsLine2 && bIsLine3) // 三条共线边 { return TDbDuctNode::kOther; } else if (bIsLine1 || bIsLine2 || bIsLine3) // 一条共线边 { return TDbDuctNode::kTapered; } return TDbDuctNode::kYiZiElbow; } else if (bSame1 || bSame2 || bSame3) // 只有一个标高相等,不可能是法兰 { if (bIsLine1 || bIsLine2 || bIsLine3) { return TDbDuctNode::kTapered; } return TDbDuctNode::kYiZiElbow; } else // 没有相等的标高,乙字弯或者其他 { if (bIsLine3) // 中心线共线 { return TDbDuctNode::kYiZiElbow; } else if (bIsLine1 || bIsLine2) { return TDbDuctNode::kTapered; } return TDbDuctNode::kOther; } } else // 相交 { if ((types[0] == 3) || (types[1] == 3)) { return TDbDuctNode::kTaoDong; } if (fabs(lstVts[0]->z)<0.001 && fabs(lstVts[1]->z)<0.001) { return TDbDuctNode::kElbow; // 弯头 } return TDbDuctNode::kKouElbow; // 扣弯 } } /*============================================================================* * 函 数 名: GetCornerBranchNums * 功能描述: 找出三、四通的支风管标号 * 备 注: 以主风管为起点,逆时针旋转依次得到标号 ==============================================================================*/ AcDbIntArray GetCornerBranchNums(const AcDbObjectId id, const XPoint &ptLoc, const DList &ids, const AcDbIntArray &types, const int &nMain) { AcDbIntArray branchArray; DList lstVt; ::GetVectors(id, ptLoc, ids, types, lstVt); // 法向 if (lstVt.Length() != ids.Length()) { return branchArray; } AcGeVector3d vtMain = lstVt[nMain]->AsAcGeVector3d(), vtTmp = vtMain.perpVector(), refVec = vtMain.crossProduct(vtTmp); // 参考向量 double dMaxAng(0), dMinAng(0); int nLen = ids.Length(), nMax(0), nMin(0); for (int i=0; iAsAcGeVector3d(); double dTmpAng = vtMain.angleTo(vt, refVec); if (fabs(dMaxAng)<1.0E-6 || dTmpAng>(dMaxAng+1.0E-6)) { dMaxAng = dTmpAng; nMax = i; } else if (fabs(dMaxAng)>1.0E-6 && fabs(dTmpAng-dMaxAng)<1.0E-6 && nLen==3) { nMin = i; // 以下代码特殊处理“平行三通”中的支管问题 DList lstSegs; ::GetSegs(id, ptLoc, ids, types, lstSegs); XPoint ptMax, ptMin; lstSegs[nMax]->ProjectToMe(ptLoc, ptMax); lstSegs[nMin]->ProjectToMe(ptLoc, ptMin); if (::IsParallel(XVector3D(vtTmp), XVector3D(ptMax-ptMin)) == 1) { TchPrivate::Exchange(nMax, nMin); } continue; } if (fabs(dMinAng)<1.0E-6 || dTmpAng<(dMinAng-1.0E-6)) { dMinAng = dTmpAng; nMin = i; } } } branchArray.append(nMin); branchArray.append(nMax); if (nLen == 4) { int nTmp(-1); ::GetAnotherPipe(nMain, nMin, nMax, nTmp); branchArray.insertAt(1, nTmp); } return branchArray; } /*============================================================================* * 函 数 名: GetVDuctNums * 功能描述: 找出三通连接的立管标号 ==============================================================================*/ void Get3TVDuctNums(AcDbObjectId id, const DList &ids, const AcDbIntArray &types, int &nVDuct1, int &nVDuct2) { if ((ids.Length() != 3) || (types.logicalLength() != 3)) { return; } int nSum(0); for (int j=0; j<3; j++) { if (::IsVerDuct(id, ids[j], types[j])) { nSum += (2*j+1); } } if (nSum==9 || nSum==0) { return; // 没有立管或三根立管 } if (nSum==4 || nSum==6 || nSum==8) // 连1个水平管,2个立管的情况 { int nHDuct = (nSum-8)/(-2), nTmp(5); ::GetAnotherPipe(nHDuct, nVDuct1, nVDuct2, nTmp); // 获取立管编号 return; } nVDuct1 = (nSum-1)/2; // 连2个水平管,1个立管的情况 }