Files
envi-code/SourceCode/Code2026/tg_shs/shs_pipewire/DuctPipeLink.cpp
T
2026-09-28 15:28:50 +08:00

3333 lines
83 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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; i<Length(); i++) // 5、添加新产生或有变化的连接关系
{
int nType = m_types[i]; // 连接关系
TDsSide &side = *(*this)[i];
AcDbObjectId linkId = side.GetId(); // 接口ID
if ((nType==2) && (linkId.isNull() || linkId.isErased()))
{
continue; // 注:暂时过滤掉空接口,否则有错误
}
if (ids.FindNode(&linkId, CompareObjectId) == NULL) // 新产生的连接关系
{
ids.Append(new AcDbObjectId(linkId));
mods.append(nType);
continue;
}
if (linkId.isErased() || linkId.isNull()) // 有变化,判断是否是被删除的管线或节点
{
int nIndex(-1);
OPENOBJ_BEGIN(m_node.id, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode != NULL) // 此时的ID一定存在
{
nIndex = pNode->FindIdInLink(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; i<nNum; i++)
{
TDsSide &side = *(*this)[i];
if (side == pSide)
{
return i;
}
}
return -1;
}
////////// 处理函数 //////////
// 判断节点是否可以连接边的指定端点,同TPsNode里的CanLinkSide
BOOL TDsNode::FindNode(const TDsSide &side, const int &nPos)
{
BOOL bFind(FALSE);
if (!IsAutoLiving() && IsDbObject() && side.IsDbObject())
{
OPENOBJ_BEGIN(m_node.id, AcDb::kForRead, TDbPipeNode, pNode);
if (pNode != NULL)
{
bFind = pNode->CanLinkSide(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<AcDbObjectId> 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<AcDbObjectId> linkIds;
linkIds.Reset();
int nLen = Length();
for (int i=0; i<nLen; i++)
{
TDsSide &side = *(*this)[i];
AcDbObjectId ductId = side.GetId();
linkIds.Append(new AcDbObjectId(ductId));
}
pNode->UpdateLinkage(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; n<rNode.Length(); n++)
{
if (rNode[n] == &other)
{
rNode.Replace(this); // 替换
OPENOBJ_BEGIN(rNode.GetId(), AcDb::kForWrite, TDbPipeNode, pNode);
if (pNode != NULL)
{
pNode->ReplaceInterface(other.GetId(), GetId()); // 注:此处有问题,打不开管线
}
OPENOBJ_END();
}
}
rNode.SetLocation(ptNew);
return TRUE;
}
OPENOBJ_END();
OPENOBJ_END();
return FALSE;
}
// 更新管线对节点的连接,针对DList<TDuctLinkSys::UpdateDuctInfo>
// 思路:修改管线端点的位置,保证连接关系正确
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<TEntRect> &lstDucts,
const DList<TNodeLocation> &lstNodes,
const XPointList &lstBreaks) // 系统入口
{
int nCount = lstNodes.Length(), i(0);
for (i=0; i<nCount; i++) // 1、构造节点
{
const TNodeLocation &node = lstNodes[i];
OPENOBJ_BEGIN(node.id, AcDb::kForRead, TDbPipeNode, pNode);
if (pNode == NULL)
{
continue;
}
if (pNode->IsAutoLiving()) // 自动生成
{
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; i<nCount; i++)
{
acedSetStatusBarProgressMeterPos(i);
AddDuct(lstDucts[i], st); // 2、构造边,同时建立边与节点的关系
}
acedRestoreStatusBar();
nCount = lstBreaks.Length();
for (i=0; i<nCount; i++)
{
const XPoint &ptBreak = lstBreaks[i];
if (!IsDupNode(ptBreak))
{
TDsNode *pNode = new TDsNode(ptBreak);
m_lstAllNode.Append(pNode); // 3、添加打断节点
}
}
}
// 构造处理系统里的边,同时建立边、节点之间的连接关系;同TSearchPipeSys里的AddPipe
void TDuctLinkSys::AddDuct(const TEntRect &duct, TPipeSys::SysType st)
{
OPENOBJ_BEGIN(duct.id, AcDb::kForRead, TDbDuct, pDuct);
if (pDuct!=NULL && pDuct->GetSysType()==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<TDsSide>
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; i<nCount; i++)
{
TDsNode *node = m_lstAllNode[i];
if (node->FindNode(side, nSide)) // 判断能否与管线相连
{
pFind = node;
break;
}
}
return pFind;
}
/////////////////////初始化系统2,lstDudts中没有管线的情况/////////////////////
// 注:当找不到管线与节点的连接关系时,变换思路,从节点入手,找管线
void TDuctLinkSys::InitSystem2(TPipeSys::SysType st,
const DList<TNodeLocation> &lstNodes,
const XPointList &lstBreaks)
{
int i(0),
nCount = lstNodes.Length();
acedSetStatusBarProgressMeter(_T("管线关系处理中..."), 0, nCount);
for (i=0; i<nCount; i++)
{
acedSetStatusBarProgressMeterPos(i);
AddNode(lstNodes[i], st); // 1、构造节点,同时建立与边的关系
}
acedRestoreStatusBar();
nCount = lstBreaks.Length();
for (i=0; i<nCount; i++)
{
const XPoint &ptBreak = lstBreaks[i];
if (!IsDupNode(ptBreak))
{
TDsNode *pNode = new TDsNode(ptBreak);
m_lstAllNode.Append(pNode); // 2、添加打断节点
}
}
}
// 根据节点,构造管线处理系统里的边和连接关系
void TDuctLinkSys::AddNode(const TNodeLocation &node, TPipeSys::SysType st)
{
OPENOBJ_BEGIN(node.id, AcDb::kForRead, TDbPipeNode, pDbNode);
if ((pDbNode==NULL) || (!pDbNode->HasInterface(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; m<nLen; m++) // 4、获取连接的管线、空接口或节点
{
TPipeSys::SysType sysType = pDuctNode->GetISysType(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<TDsSide>
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<TDsSide>
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; i<nCount; i++)
{
TDsSide *side = m_lstAllSide[i];
if (side->FindSide(id1, id2))
{
pFind = side;
break;
}
}
return pFind;
}
///////////////////////////////合并、打断处理//////////////////////////////////
void TDuctLinkSys::MergeDucts(XPointList &lstCorners, PickSet &ssDel) // 合并
{
int nLen = m_lstAllNode.Length();
for (int i=0; i<nLen; i++)
{
if (MergeDuctAt(i, lstCorners, ssDel))
{
i--;
nLen--;
}
}
}
// 在第nPos个位置合并管段,返回: kTrue——合并进行; kFalse——没有合并
// 条件:(1)点的坐标在lstCorners中,lstCorners为管线的真实起、止点
// (2)连接了两个系统类型、几何类型都相同的管线,且不在管线内部
// (3)管线在该点的切线方向平行
BOOL TDuctLinkSys::MergeDuctAt(int nPos, XPointList &lstCorners, PickSet &ssDel)
{
ASSERT(nPos>=0 && nPos<m_lstAllNode.Length());
TDsNode &node = *m_lstAllNode[nPos];
if (node.Length() != 2) // 连接两根管线
{
return FALSE;
}
int nCount = m_lstAllSide.Length();
XPoint ptToBeMerged = node.GetLocation(); // 合并点
for (int i=0; i<nCount; i++)
{
TDsSide &side = *m_lstAllSide[i];
if (!side.IsDbObject() || side.GetId().isNull())
{
continue; // 删除、空接口、接节点
}
if ((ptToBeMerged&side) == PR_INSIDE)
{
return FALSE; // 在某管段内不能合并
}
}
if (!lstCorners.FindNode(&ptToBeMerged, ComparePoint))
{
return FALSE; // 仅仅合并lstCorners中的管线
}
int nCornerPos = lstCorners.CurPosition(); // 备删除用
TDsSide &side1 = *node[0],
&side2 = *node[1];
if (!(side1.IsDbObject() && side2.IsDbObject()) || side1.GetId().isNull()
|| side2.GetId().isNull())
{
return FALSE;
}
if (side1.MergeWith(side2, node)) // 注:乙字弯、法兰除外
{
side1.m_duct += side2.m_duct; // 修改TDsSide的TEntRect
ssDel += side2.GetId(); // 实体本身以后再删除
for (int i=0; i<m_lstAllSide.Length(); i++) // 要在处理系统中将该边删掉
{
if (m_lstAllSide[i] == &side2)
{
m_lstAllSide.Remove();
break;
}
}
m_lstAllNode.Remove(nPos); // 消除本节点
if (node.IsDbObject()) // 同时删除节点实体本身
{
OPENOBJ_BEGIN(node.GetId(), AcDb::kForWrite, TDbPipeNode, pNode);
if (pNode != NULL)
{
pNode->erase();
}
OPENOBJ_END();
}
lstCorners.Remove(nCornerPos); // 减变化的位置
return TRUE;
}
return FALSE;
}
void TDuctLinkSys::BreakDucts(XPointList &lstCorners) // 在给定位置打断管段
{
int nLen = m_lstAllNode.Length();
for (int i=0; i<nLen; i++)
{
BreakDuctAt(i, lstCorners);
}
}
// 条件:(1)点的坐标在lstCorners中,(2)在管线内部,(3)只处理节点
void TDuctLinkSys::BreakDuctAt(int nPos, XPointList &lstCorners)
{
TDsNode &node = *m_lstAllNode[nPos];
if (m_bOptimize) // 优化,只处理连接一根管线的节点
{
if (node.Length() != 1)
{
return;
}
}
TADSGePoint3d __pt(node.GetLocation());
if (!lstCorners.FindNode(&__pt, ComparePoint))
{
return; // node是否在lstCorners里
}
int nCount = m_lstAllSide.Length();
for (int i=0; i<nCount; i++)
{
TDsSide *side = m_lstAllSide[i];
if (!side->IsDbObject() || 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; n<updStartNode.Length(); n++)
{
if (updStartNode[n] == &side)
{
updStartNode.Remove();
updStartNode.m_types.removeAt(n);
updStartNode.RemoveInterface(side.GetId());
break;
}
}
pDuct->erase();
}
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; n<updEndNode.Length(); n++)
{
if (updEndNode[n] == &side)
{
updEndNode.Remove();
updEndNode.m_types.removeAt(n);
updEndNode.RemoveInterface(side.GetId()); // 删除Interface
break;
}
}
}
else // 非重合管段
{
XPoint ptMin, ptMax;
pNewDuct->GetExtend(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; n<updEndNode.Length(); n++)
{
if (updEndNode[n] == &side)
{
updEndNode.Replace(pNewSide);
updEndNode.m_types[n] = 0;
updEndNode.ReplaceInterface(side.GetId(), newDuctId); // 替换接口
break;
}
}
node.Append(pNewSide);
node.m_types.append(0);
if (pNewDuct->upgradeOpen() == 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; i<m_lstAllNode.Length(); i++)
{
TDsNode &node = *m_lstAllNode[i];
if (!node.IsDbObject()) // 1、判断节点ID是否存在
{
continue; // 不存在,一定不是独立节点
}
AcDbObjectId id = node.GetId();
if (box != NULL) // 2、判断节点是否在更新区域内
{
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbPipeNode, pNode);
if (pNode != NULL)
{
if (pNode->IsVisible()) // 可见节点
{
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; k<nEquipNum; k++)
{
const AcDbObjectId &idPipe = pEquipment->GetIPipe(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<AcDbObjectId> 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; k<nOldLen; k++)
{
OPENOBJ_BEGIN(*oldIds[k], AcDb::kForRead, TDbDuct, pDuct);
if (pDuct != NULL)
{
XPoint ptMin, ptMax;
if (pDuct->GetExtend(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; i<m_lstAllNode.Length(); i++)
{
TDsNode &node = *m_lstAllNode[i];
int nRet = node.SetInfo(); // 获取连管信息
if (nRet == -1) // 出现错误
{
m_lstAllNode.Remove(i);
i--;
continue;
}
else if (nRet == 0) // 设备
{
continue;
}
// 先去除坏的节点,mcl add,08.10.6
if (node.IsBad())
{
m_lstAllNode.Remove(i);
i--;
continue;
}
TDbDuctNode::DuctNodeType nNewType = node.GetNewNType(), // 新节点类型
nOldType = TDbDuctNode::kStem; // 原节点类型
int nOld = node.GetOldIFNum(nOldType); // 获取原接口数量及类型
BOOL bIsOk(TRUE);
if (nNewType == TDbDuctNode::kStem) // 一般堵头
{
XPoint ptLink, ptLoc = node.GetLocation(); // 连接点
TPipeSys::PtLoction nSide = TPipeSys::kStartPt;
OPENOBJ_BEGIN(*node.ids[0], AcDb::kForRead, TDbDuct, pDuct);
if (pDuct != NULL)
{
ptLink = ::GetNearPt(ptLoc, pDuct->GetStartPoint(), 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)<PS_SNAP || fabs(dAng-1.5*PI)<PS_SNAP)
{
dDist += max(node.hs[0], node.hs[1]) * dRate;
}
else
{
dDist += max(node.ws[0], node.ws[1]) * dRate;
}
}
else // 其他情况
{
dDist += max(node.ws[0], node.ws[1]) * dRate;
}
XVector3D vt1 = *node.vs[0],
vt2 = *node.vs[1];
vt1.Normalize();
vt2.Normalize();
XPoint ptInt, pt1, pt2, ptTmp, ptCen;
if (bKouElbow) // 5、如果是变高弯头,直接计算缩进点即可
{
ptInt = node.GetLocation();
vt1.Scale(dDist);
vt2.Scale(dDist);
pt1 = ptInt + vt1;
pt2 = ptInt + vt2;
}
else // 如果是普通弯头,先修改其位置点坐标,再按照内侧线缩进
{
XCurveSegment cvDuct1 = *node.ss[0],
cvDuct2 = *node.ss[1];
cvDuct1.SetLineFlag(LS_INFINITE);
cvDuct2.SetLineFlag(LS_INFINITE);
if (cvDuct1.Intersection(cvDuct2, ptInt, ptTmp) != 1) // 管线平行
{
return FALSE;
}
ptInt = ::GetNearPt(node.GetLocation(), ptInt, ptTmp); // 节点位置
int nIndex = FindNodeByPt(node.GetLocation());
if (nIndex != -1)
{
TDsNode &node = *m_lstAllNode[nIndex];
node.SetLocation(ptInt);
}
vt1.Scale(node.ws[0]*10);
vt2.Scale(node.ws[1]*10);
XPoint ptTmp1 = ptInt + vt1,
ptTmp2 = ptInt + vt2;
::AT_cal_fillet(ptTmp1, ptInt, ptTmp2, dDist, pt1, ptCen, pt2);
cvDuct2.ProjectToMe(pt2, pt2);
}
BuildUpdateDuct(*node.ids[0], pt1, *node.ps[0], node.mods[0]); // 6、生成更新信息
BuildUpdateDuct(*node.ids[1], pt2, *node.ps[1], node.mods[1]);
return TRUE;
}
///////////////变径、天圆地方/////////////////
BOOL TDuctLinkSys::CalTaperedPts(TDsNode &node, const BOOL bConfig)
{
if (!node.AssureArrayNum(2))
{
return FALSE; // 1、判断节管数量是否正确
}
Adesk::UInt8 nMode = 1; // 2、获得绘制样式、角度、长度
double dAngle(PI/6), dLen(0.0);
::GetDNodeConfig(TDbDuctNode::kTapered, nMode, dAngle, dLen);
OPENOBJ_BEGIN(node.GetId(), AcDb::kForWrite, TDbDuctNode, pNode);
if (pNode != NULL)
{
nMode = bConfig?nMode:pNode->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; i<nCount; i++)
{
TDsSide &side = *m_lstAllSide[i];
if (side.GetId() == id)
{
bRet = TRUE;
break;
}
}
if (!bRet) // 找不到的情况
{
XPoint ptMin, ptMax;
TPipeSys::SysType st = TPipeSys::kAcSupplyAir;
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuct, pDuct);
if (pDuct != NULL)
{
st = pDuct->GetSysType();
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; i<m_lstAllNode.Length(); i++)
{
TDsNode &node = *m_lstAllNode[i];
if ((node.Length() == 0) || (node.IsDbObject()))
{
continue; // 孤立节点,或者ID已经存在
}
if (node.IsBad())// mcl add, 08.10.6
{
continue;
}
BOOL bAdd(TRUE);
if (box != NULL) // 判断节点是否在box内
{
XPoint pt2d = node.GetLocation();
pt2d.z = 0;
if ((pt2d&(*box)) != PR_INSIDE)
{
bAdd = FALSE;
}
}
if (bAdd) // 需要添加的节点
{
TDsSide *side = node.Head();
OPENOBJ_BEGIN(side->GetId(), 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; i<nCount; i++)
{
if (m_lstAllSide[i].IsFullDupSide(pSeg))
return TRUE;
}
return FALSE;
}
BOOL TDuctLinkSys::IsFullDupDuct(const TDsSide &side) const
{
int nCount = m_lstAllSide.Length();
for (int i=0; i<nCount; i++)
{
if (m_lstAllSide[i].IsFullDupSide(side))
return TRUE;
}
return FALSE;
}
BOOL TDuctLinkSys::IsDupNode(const TNodeLocation &node) const
{
int nCount = m_lstAllNode.Length();
for (int i=0; i<nCount; i++)
{
if (m_lstAllNode[i].IsDupLocation(node)) // 只对隐式节点
return TRUE;
}
return FALSE;
}
BOOL TDuctLinkSys::IsDupNode(const XPoint &ptLoc) const
{
int nCount = m_lstAllNode.Length();
for (int i=0; i<nCount; i++)
{
if (m_lstAllNode[i].IsDupLocation(ptLoc))
return TRUE;
}
return FALSE;
}
///////////////////删除完全重合节点、管线////////////////////
void TDuctLinkSys::DelDupNodeFromDb(const XRectAngle &box)
{
for (int i=0; i<m_lstDupNode.Length(); i++)
{
if (DelNodeFromDb(*m_lstDupNode[i], box))
{
m_lstDupNode.Remove();
i--;
}
}
}
BOOL TDuctLinkSys::DelNodeFromDb(const AcDbObjectId &id, const XRectAngle &box)
{
BOOL bRet(FALSE);
OPENOBJ_BEGIN(id, AcDb::kForWrite, TDbPipeNode, pNode);
if (pNode != NULL)
{
XPoint pt2d = pNode->GetLocation();
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; i<m_lstDupDuct.Length(); i++)
{
if (DelDuctFromDb(*m_lstDupDuct[i], box))
{
m_lstDupDuct.Remove();
i--;
}
}
}
BOOL TDuctLinkSys::DelDuctFromDb(const AcDbObjectId &id, const XRectAngle &box)
{
BOOL bRet(FALSE);
OPENOBJ_BEGIN(id, AcDb::kForWrite, TDbDuct, pDuct);
if (pDuct != NULL)
{
XPoint ptMin, ptMax;
if (pDuct->GetExtend(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; i<nCount; i++)
{
UpdateDuctInfo info = *m_lstUpdate[i];
TDsSide *pSide = FindSideById(info.id);
if (pSide == NULL) // 注:确保连接关系正确
{
continue;
}
pSide->UpdateLinkage(info.pt, info.nSide);
}
}
// 更新节点的连接信息
void TDuctLinkSys::UpdateNodeLinkage(TPipeSys::SysType st, const XRectAngle* box)
{
int nCount = m_lstAllNode.Length();
for (int i=0; i<nCount; i++)
{
TDsNode &node = *m_lstAllNode[i];
if (!node.IsDbObject()) // ID不存在
{
continue;
}
if (node.IsBad()) // mcl add, 08.10.6
{
continue;
}
BOOL bInBox(FALSE);
if (box != NULL)
{
if (node.IsAutoLiving()) // 自动生成
{
if (PointInBox02d(node.GetLocation(), *box))
{
bInBox = TRUE; // 在范围内
}
}
else // 非自动生成
{
OPENOBJ_BEGIN(node.GetId(), AcDb::kForRead, TDbPipeNode, pNode);
if (pNode != NULL)
{
if (pNode->IsVisible()) // 可见
{
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; i<nLen; i++) // 一、更新管线:验证管线与附属设备、连接件的配属关系
{
const TDsSide &side = *m_lstAllSide[i];
OPENOBJ_BEGIN(side.GetId(), AcDb::kForWrite, TDbDuct, pDuct);
if (pDuct != NULL)
{
pDuct->ValidateEquipmentShip(); // 只处理设备关系
}
OPENOBJ_END();
}
nLen = m_lstAllNode.Length();
for (i=0; i<nLen; i++) // 二、更新设备:验证管线和附属设备的配属关系
{
TDsNode &node = *m_lstAllNode[i];
OPENOBJ_BEGIN(node.GetId(), AcDb::kForRead, TDbPipeNode, pNode);
if (pNode == NULL)
{
continue;
}
int nCount = pNode->GetInterfaceNum();
if (pNode->isKindOf(TDbDuctNode::desc()))
{
TDbDuctNode *pDbNode = TDbDuctNode::cast(pNode);
for (int j=0; j<nCount; j++)
{
if (pDbNode->GetIType(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; j<nCount; j++)
{
AcDbObjectId id = pEquipment->GetIPipe(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; i<nCount; i++)
{
TDsSide *side = m_lstAllSide[i];
if (side->GetId() == 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<nCount; i++)
{
const TDsNode &node = m_lstAllNode[i];
if (ptLoc.Distance(node.GetLocation()) < PS_SNAP)
{
nIndex = i;
break;
}
}
return nIndex;
}
//End TDuctLinkSys
///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// TCalCornerPts
//////////////////////////////////////////////////////////////////////////////
BOOL TCalCornerPts::SetIdAndType(const DList<AcDbObjectId> &ducts,
const AcDbIntArray &aryTypes)
{
int nLen1 = ducts.Length(),
nLen2 = aryTypes.logicalLength();
if ((nLen1!=nNum) || (nLen1!=nLen2))
{
return FALSE;
}
ClearSS();
for (int i=0; i<nNum; i++)
{
ids.Append(new AcDbObjectId(ducts[i]));
types.append(aryTypes[i]);
}
ws = ::GetWidths(id, ids, types);
hs = ::GetHeights(id, ids, types);
as = ::GetAngles(id, pt, ids, types);
::GetSegs(id, pt, ids, types, ss);
::GetVectors(id, pt, ids, types, vs);
::GetDuctTrueMidPts(id, pt, ids, types, ps);
SetFlange();
return TRUE;
}
void TCalCornerPts::ClearSS()
{
ids.Reset();
vs.Reset();
ss.Reset();
ps.Reset();
if (!types.isEmpty())
{
types.removeSubArray(0, types.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);
}
if (!flcs.isEmpty())
{
flcs.removeSubArray(0, flcs.logicalLength()-1);
}
if (!flhs.isEmpty())
{
flhs.removeSubArray(0, flhs.logicalLength()-1);
}
}
void TCalCornerPts::SetFlange()
{
for (int i=0; i<nNum; i++)
{
double dFlThick(0), dFlLen(0);
if ((types[i] == 1) || (types[i] == 2)) // 此时的id一定不为空
{
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode == NULL)
{
return;
}
int nIndex = pNode->FindIdInLink(*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<nLen; i++) // 第一轮循环,找出最大的
{
double dNum = numArray[i];
if (fabs(dMax)<1.0E-6 || dNum>(dMax+1.0E-6))
{
dMax = dNum;
nIndex = i;
}
}
AcDbIntArray indexArray;
indexArray.append(nIndex);
for (i=0; i<nLen; i++) // 第二轮循环,找出所有与最大值相等的
{
double dNum = numArray[i];
if (i!=nIndex && fabs(dNum-dMax)<1.0E-6)
{
indexArray.append(i);
}
}
return indexArray;
}
// 找出三、四通的主风管标号
int TCalCornerPts::GetMainNum()
{
BOOL bFlag(FALSE); // 是否跳出外层循环
int i(0), nMain(0), nTmp(0),
nOther1(-1), nOther2 = nNum==3?5:-1;
for (i=0; i<nNum&&!bFlag; i++)
{
for (int j=i+1; j<nNum; j++)
{
if (::IsParallel(*vs[i], *vs[j]) == 0) // 不平行
{
continue;
}
bFlag = TRUE;
nTmp = GetBigNum(i, j); // 平行管径较大者
::GetAnotherPipe(i, j, nOther1, nOther2); // 找出另外的管线标号
if (nNum == 3)
{
nMain = nTmp; // 其他型
if (nMod==4 || nMod==5 || nMod==11 || nMod==12) // Y、T型
{
nMain = nOther1;
}
else if (nMod == 6) // 平行
{
nMain = GetBigNum(nMain, nOther1); // 所有管径中最大的
}
break;
}
if (::IsParallel(*vs[nOther1], *vs[nOther2]) == 0) // 不平行
{
nMain = nTmp;
break;
}
int nTmp2 = GetBigNum(nOther1, nOther2);
nMain = GetBigNum(nTmp, nTmp2);
break;
}
}
if (!bFlag) // 没有平行管线
{
if (nNum == 3)
{
if ((nMod==6) || (nMod==9) || (nMod==10)) // 不允许,没有平行管线
{
return -1;
}
}
AcDbIntArray indexArray = GetMaxNumIndexs(ws); // 比较所有管线的宽度值
int nLen = indexArray.logicalLength();
if (nLen == 1)
{
return indexArray[0];
}
AcGeDoubleArray tmpArray;
for (i=0; i<nLen; i++)
{
int nIndex = indexArray[i];
tmpArray.append(hs[nIndex]);
}
indexArray.removeSubArray(0, nLen-1);
indexArray = GetMaxNumIndexs(tmpArray); // 比较等宽度的管线中,高度值
nMain = (indexArray.logicalLength()==1)?indexArray[0]:0;
}
return nMain;
}
// 计算法兰正好不相交的长度
double TCalCornerPts::GetDistFl(int nNum1, int nNum2, double dAngle)
{
double dFl = max(flcs[nNum1], flcs[nNum2]); // 较大的法兰出头长
double dW1 = ws[nNum1]*0.5 + dFl,
dW2 = ws[nNum2]*0.5 + dFl;
double dSin = sin(dAngle); // 夹角的正弦
double dDist = dW1*dW1 + dW2*dW2 + 2*dW1*dW2*sqrt(1-dSin*dSin);
dDist = sqrt(dDist/(dSin*dSin) - dW1*dW1);
return (dDist + 50);
}
XPoint TCalCornerPts::GetFlLocPt(int nNum, double dDist, XPoint pt)
{
XVector3D vt = *vs[nNum];
vt.Normalize();
vt.Scale(dDist);
return (pt + vt);
}
XPoint TCalCornerPts::GetIntPt(int nNum1, int nNum2)
{
XPoint pt1 = *ps[nNum1], // 中心点在支管上的投影点
pt2 = *ps[nNum2];
pt1.z = pt2.z = 0;
XPoint ptTmp1, ptTmp2;
ads_polar(pt1, as[nNum1], 5*ws[nNum1], ptTmp1);
ads_polar(pt2, as[nNum2], 5*ws[nNum2], ptTmp2);
XLine line1(pt1, ptTmp1, LS_INFINITE),
line2(pt2, ptTmp2, LS_INFINITE);
if (line1.Intersection(&line2, ptTmp1) != 1) // 无交点
{
return XPoint();
}
ss[nNum1]->ProjectToMe(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 ((dCurrent<PI*4/9-1.0E-5) || (dCurrent>PI*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<AcDbObjectId> &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<XVector3D> 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<XCurveSegment> 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<AcDbObjectId> &ids,
const AcDbIntArray &types, const int &nMain)
{
AcDbIntArray branchArray;
DList<XVector3D> 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; i<nLen; i++)
{
if (i != nMain)
{
AcGeVector3d vt = lstVt[i]->AsAcGeVector3d();
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<XCurveSegment> 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<AcDbObjectId> &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个立管的情况
}