3333 lines
83 KiB
C++
3333 lines
83 KiB
C++
#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个立管的情况
|
||
} |