Files
envi-code/SourceCode/Code2026/tg_shs/shs_pipewire/DbDuct.cpp
T
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

2819 lines
71 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.
// DbDuct.cpp: implementation of the TDbDuct class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DbDuct.h"
#include "PipePrototype.h"
#include "DbPipe.h"
#include "DbDoubleLinePipe.h"
#include "PipeTools.h"
#include "DbPipeLabel.h"
#include "DbPipeValve.h"
#include "HDbEquipment.h"
#include "GlobalFunction.h"
#include "TDbDuctNode.h"
ACRX_DXF_DEFINE_MEMBERS(ATSDuct, ATSPipePrototype, AcDb::kDHL_CURRENT,
AcDb::kMReleaseCurrent, 1, ATS_VENTPIPE,
"ATS_VENTPIPE图形无法解析, 请下载上华软件|网址: www.shanghuasoft.com");
IMPLEMENT_TENTBASE(TDbDuct);
// sg modify 2008-1-14
// const Adesk::UInt8 TDbDuct::g_nVersion = 1; // 7.5
const Adesk::UInt8 TDbDuct::g_nVersion = 2; // 7.6
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
TDbDuct::TDbDuct():
m_dWidth(800), m_dHeight(500), m_dOldWidth(0), m_dOldHeight(0), m_dDuctWeight(0.35),
m_dVDAngle(0), m_nMaterial(0), m_dSpeedSubMid(0), m_dSpeedLength(0), m_dFlChuTou(100),
m_dFlThick(50), m_dCalWeight(0)
{
m_sysType = TPipeSys::kUnknownSys;
m_nSection = 0;
m_nSysDrawMod = 2;
m_eDQType = kMidMid;
m_eDQSide = TPipeSys::kStartPt;
m_nSpare = 0;
m_dSpare = 0.0;
}
/////////////////////////////////Get函数/////////////////////////////////////////
// 获取指定端坐标
XPoint TDbDuct::GetVertexPt(const TPipeSys::PtLoction nSide) const
{
XPoint pt(GetStartPoint());
if (nSide == TPipeSys::kEndPt)
{
pt = EndPoint();
}
return pt;
}
// 获取另一端坐标
XPoint TDbDuct::GetOtherPt(const TPipeSys::PtLoction nSide) const
{
TPipeSys::PtLoction nOther = (TPipeSys::PtLoction)(1-(int)nSide);
return GetVertexPt(nOther);
}
// 获取管线法向
XVector3D TDbDuct::GetDirection(const XPoint &pt, TPipeSys::PtLoction &nSide) const
{
XVector3D vt;
XCurveSegment seg = GetCurve(); // 管段
if (seg.Is(CURVE_LINE)) // 直线管段
{
double dDis1 = pt.Distance(StartPoint()),
dDis2 = pt.Distance(EndPoint());
if (dDis1 > (dDis2+1.0E-6))
{
vt = StartPoint() - EndPoint(); // S——>E
nSide = TPipeSys::kEndPt; // pt点接近管线终点
}
else
{
vt = EndPoint() - StartPoint(); // E——>S
nSide = TPipeSys::kStartPt; // pt点接近管线起点
}
return vt;
}
XPoint ptRet, ptStart, ptEnd; // 注:弧管起止点可能会相反
seg.ProjectToMe(pt, ptRet); // 保证点在管段上
XArc arc = seg.GetArc();
arc.GetStartPoint(ptStart);
arc.GetEndPoint(ptEnd);
// arc.GetPoints(ptStart, ptEnd); // 弧管上的起、止点坐标
AcGePoint3d ptOnCurve = ptRet.AsAcGePoint3d(), ptOnHit;
AcDbCurve *pCurve = GetBaseCurve();
pCurve->getClosestPointTo(ptOnCurve, ptOnHit);
ASSERT(pCurve);
AcGeVector3d vec; // S——>E
pCurve->getFirstDeriv(ptOnHit, vec); // 求切线向量
delete pCurve;
vt = XVector3D(vec);
double dDis1 = pt.Distance(ptStart),
dDis2 = pt.Distance(ptEnd);
BOOL bChange = ptStart.Distance(StartPoint())>1.0E-5; // 标志是否发生了反向
if (dDis1 > (dDis2+1.0E-6))
{
vt.Scale(-1); // E——>S
nSide = bChange?TPipeSys::kStartPt:TPipeSys::kEndPt; // pt点接近管线终点
}
else
{
nSide = bChange?TPipeSys::kEndPt:TPipeSys::kStartPt; // pt点接近管线起点
}
return vt;
}
//////////////////////////有关管段上附着的设备/////////////////////////////////
void TDbDuct::AddEquipment(const AcDbObjectId &id) // 增加节点
{
assertWriteEnabled();
if (!FindEquipment(id))
{
m_lstEquipment.Append(new AcDbSoftPointerId(id));
}
}
void TDbDuct::RemoveEquipment(const AcDbObjectId &id) // 移除节点
{
assertWriteEnabled();
if (m_lstEquipment.FindNode(&id, CompareObjectId))
{
m_lstEquipment.Remove();
}
}
BOOL TDbDuct::FindEquipment(const AcDbObjectId &id) const // 查找节点
{
TDbDuct *pThis = TDbDuct::cast(this);
BOOL bFind = (pThis->m_lstEquipment.FindNode(&id, CompareObjectId)!=NULL);
return bFind;
}
int TDbDuct::GetEquipNum() const // 获取连接的节点数量
{
return m_lstEquipment.Length();
}
// 获取节点ID
void TDbDuct::GetEquipments(DList<AcDbObjectId> &lstEquipment) const
{
int nCount = m_lstEquipment.Length();
for (int i=0; i<nCount; i++)
{
lstEquipment.Append(new AcDbObjectId(m_lstEquipment[i]));
}
}
// 获取节点位置
void TDbDuct::GetEquipPts(XPointList &lstPts) const
{
int nCount = m_lstEquipment.Length();
for (int i=0; i<nCount; i++)
{
AcDbObjectId idOp = m_lstEquipment[i];
OPENOBJ_BEGIN(idOp, AcDb::kForRead, TDbPipeNode, pNode);
if (pNode != NULL)
{
XPoint ptLoc = pNode->GetLocation();
lstPts.Append(new XPoint(ptLoc));
}
OPENOBJ_END();
}
}
// 判断管线与设备是否能在指定接口处,产生附着关系
BOOL TDbDuct::CanAttachEquipment(const THDbEquipment &equipment,
const int &nIFaceNum) const
{
BOOL bRet(FALSE);
XPoint ptProject;
const XPoint &ptLink = equipment.GetILocation(nIFaceNum);
if (getClosestPointTo(ptLink, ptProject, Adesk::kFalse) != Acad::eOk)
{
return bRet;
}
int nSection = GetSectionType();
BOOL bSys = GetModelType()==TPipeSys::kSystem ||
GetModelType()==TPipeSys::kPrinciple;
if (nSection == 1) // 圆管
{
double dDist = ptProject.Distance(ptLink);
bRet = fabs(dDist-m_dWidth/2.0)<1.0E-6;
if (bSys)
{
bRet = dDist < m_dHeight/2.0 + 1.0E-6;
}
}
else if (nSection == 0) // 方管
{
if (bSys)
{
CString sBlkName, sDesName;
GetBlkNameById(equipment.GetBlock2d(), sBlkName, sDesName);
XPoint ptTmp1(ptLink), ptTmp2(ptProject);
ptTmp1.z = ptTmp2.z = 0;
double dDist = ptTmp1.Distance(ptTmp2);
if (_tcsicmp(sDesName, _T("sysD")) == 0) // 下接风口
{
bRet = dDist < m_dHeight/2.0 + 1.0E-6;
}
else if (_tcsicmp(sDesName, _T("sysS")) == 0) // 侧接风口
{
bRet = dDist < m_dWidth/2.0 + 1.0E-6;
}
}
else
{
XPoly2D poly1, poly2;
XPointList lstPts1, lstPts2;
XVector3D vtDuct1 = EndPoint() - StartPoint(),
vtDuct2 = StartPoint() - EndPoint();
::GetDuctSidePts(ptProject, m_dWidth, m_dHeight, vtDuct1, lstPts1);
::GetDuctSidePts(ptProject, m_dWidth, m_dHeight, vtDuct2, lstPts2);
int nLen = lstPts1.Length(), i(0);
for (i=0; i<nLen; i++)
{
poly1.AppendNode(*lstPts1[i], 0);
}
nLen = lstPts2.Length();
for (i=0; i<nLen; i++)
{
poly2.AppendNode(*lstPts2[i], 0);
}
BOOL bRet1 = (ptLink&poly1)==PR_EDGE,
bRet2 = (ptLink&poly2)==PR_EDGE;
bRet = bRet1 || bRet2;
}
}
return bRet;
}
// 重新验证同自身全部附着的设备之间的关系,并调整配属, 在系统结束后处理
// 注:只处理设备,不处理掏洞节点
void TDbDuct::ValidateEquipmentShip()
{
int i(0),
nCount = m_lstEquipment.Length();
DList<AcDbObjectId> lstEquipment;
for (i=0; i<nCount; i++)
{
lstEquipment.Append(new AcDbObjectId(*m_lstEquipment[i]));
}
for (i=0; i<lstEquipment.Length(); i++)
{
AcDbObjectId idOp = *lstEquipment[i];
OPENOBJ_BEGIN(idOp, AcDb::kForRead, TDbPipeNode, pNode);
if (pNode == NULL)
{
RemoveEquipment(idOp);
continue;
}
if (pNode->isKindOf(TDbDuctNode::desc())) // 掏洞节点
{
continue;
}
if (pNode->isKindOf(THDbEquipment::desc())) // 设备
{
THDbEquipment *pEquipment = THDbEquipment::cast(pNode);
int nLen = pEquipment->GetInterfaceNum();
for (int j=0; j<nLen; j++)
{
AcDbObjectId ductId = pEquipment->GetIPipe(j);
if (ductId==objectId() && !CanAttachEquipment(*pEquipment, j))
{
RemoveEquipment(idOp); // 不存在相互连接关系
if (pEquipment->upgradeOpen() == Acad::eOk)
{
pEquipment->SetIPipe(j, AcDbObjectId::kNull);
pEquipment->downgradeOpen();
}
}
}
}
OPENOBJ_END();
}
}
///////////////////////////Override TDbEntity////////////////////////////////////
void TDbDuct::CopyPropertiesFrom(AcDbEntity* pSrc, unsigned gMatchFlag)
{
assertWriteEnabled();
TDbPipePrototype::CopyPropertiesFrom(pSrc, gMatchFlag);
TDbDuct *pDuct = TDbDuct::cast(pSrc);
if (pDuct != NULL)
{
m_nSysDrawMod = pDuct->m_nSysDrawMod;
m_nSection = pDuct->m_nSection;
m_dWidth = pDuct->m_dWidth;
m_dHeight = pDuct->m_dHeight;
m_dDuctWeight = pDuct->m_dDuctWeight;
m_dVDAngle = pDuct->m_dVDAngle;
m_nMaterial = pDuct->m_nMaterial;
m_sLabel = pDuct->m_sLabel;
m_eDQType = pDuct->m_eDQType;
m_eDQSide = pDuct->m_eDQSide;
m_dFlChuTou = pDuct->m_dFlChuTou;
m_dFlThick = pDuct->m_dFlThick;
m_dCalWeight = pDuct->m_dCalWeight;
}
}
Acad::ErrorStatus TDbDuct::subGetClassID(CLSID* pClsid) const
{
return Acad::eOk;
}
// 取动态属性显示数据
void TDbDuct::GetTips(DList<TObjInfoUnit> &lstInfo) const
{
if (IsVertical())
{
lstInfo.Append(new TObjInfoUnit(_T("对象类型"), _T("立管")));
}
else
{
lstInfo.Append(new TObjInfoUnit(_T("对象类型"), _T("管段")));
}
TDbPipePrototype::GetTips(lstInfo);
if (m_nSection == 0) // 矩形截面
{
lstInfo.Append(new TObjInfoUnit(_T("宽度"), Dist2Str(m_dWidth)));
lstInfo.Append(new TObjInfoUnit(_T("高度"), Dist2Str(m_dHeight)));
}
else if ((1 == m_nSection) || (2 == m_nSection)) // 圆、软管截面
{
lstInfo.Append(new TObjInfoUnit(_T("直径"), Dist2Str(m_dWidth)));
}
// 暂时无,8.0以后添加
// else if (m_nSection == 3) // 椭圆截面
// {
// lstInfo.Append(new TObjInfoUnit(_T("短轴长度"), Dist2Str(m_dWidth)));
// lstInfo.Append(new TObjInfoUnit(_T("长轴长度"), Dist2Str(m_dHeight)));
// }
// else if (m_nSection = 4) // 扁圆截面
// {
// lstInfo.Append(new TObjInfoUnit(_T("长度A"), Dist2Str(m_dWidth)));
// lstInfo.Append(new TObjInfoUnit(_T("长度B"), Dist2Str(m_dHeight)));
// }
double dVelocity = CalVelocity();
CString csTmp;
csTmp.Format(_T("%.2f"), dVelocity);
lstInfo.Append(new TObjInfoUnit(_T("风量"), Dist2Str(m_dCalWeight)));
lstInfo.Append(new TObjInfoUnit(_T("风速"), csTmp));
XStringList lstMaterial;
if (GetDuctMaterial(lstMaterial) && m_nMaterial>=0 &&
m_nMaterial<lstMaterial.Length())
{
lstInfo.Append(new TObjInfoUnit(_T("材料"),lstMaterial[m_nMaterial]));
}
}
// 取得夹点说明
Acad::ErrorStatus TDbDuct::GetGripText(int idx, CString &cs) const
{
Acad::ErrorStatus es = TDbPipePrototype::GetGripText(idx, cs);
return es;
}
///////////////////////////Override AcDbEntity///////////////////////////////////
Acad::ErrorStatus
TDbDuct::subGetOsnapPoints(AcDb::OsnapMode osnapMode, INT_PTR gsSelectionMark,
const AcGePoint3d &ptPick, const AcGePoint3d &lastPoint,
const AcGeMatrix3d &viewXform, AcGePoint3dArray &snapPoints,
AcDbIntArray &geomIds) const
{
assertReadEnabled();
Acad::ErrorStatus es = Acad::eOk;
if (!g_nPipeOsnap)
{
es = TDbCurveEntity::subGetOsnapPoints(osnapMode, gsSelectionMark, ptPick,
lastPoint, viewXform, snapPoints, geomIds);
}
else
{
if (IsVertical()) // 立管
{
switch(osnapMode) {
case AcDb::kOsModeCen:
case AcDb::kOsModeNode:
snapPoints.append(GetVerUpCenter());
snapPoints.append(GetVerLowCenter());
break;
default:
break;
}
}
else // 水平管,7.6版本以上增加边线的拾取
{
es = TEntityBase::GetOsnapPoints(osnapMode, gsSelectionMark, ptPick,
lastPoint, viewXform, snapPoints, geomIds);
}
}
return es;
}
// 取得所有的夹点,注:有关立管夹点的问题,在此修改
Acad::ErrorStatus TDbDuct::subGetGripPoints(AcGePoint3dArray& gripPoints,
AcDbIntArray& osnapModes,
AcDbIntArray& geomIds) const
{
assertReadEnabled();
Acad::ErrorStatus es = TDbPipePrototype::subGetGripPoints(gripPoints, osnapModes,
geomIds);
return es;
}
Acad::ErrorStatus TDbDuct::subMoveGripPointsAt(const AcDbIntArray& indices,
const AcGeVector3d& offset)
{
assertWriteEnabled();
Acad::ErrorStatus es = TDbPipePrototype::subMoveGripPointsAt(indices, offset);
if (es != Acad::eOk)
{
return es;
}
if (objectId().isValid()) // 管线的整体拖拽、夹点拖拽操作,要提供变化给节点
{
ApplyChangeToNode();
}
return es;
}
Acad::ErrorStatus TDbDuct::subMoveStretchPointsAt(const AcDbIntArray &indices,
const AcGeVector3d &offset)
{
assertWriteEnabled();
Acad::ErrorStatus es = TDbPipePrototype::subMoveStretchPointsAt(indices, offset);
if (es != Acad::eOk)
{
return es;
}
if (objectId().isValid())
{
ApplyChangeToNode();
}
return es;
}
// 提供管线的移动变化到节点,用于moveGripPointsAt、transformBy中
void TDbDuct::ApplyChangeToNode(BOOL bSXTT)
{
int i(0);
for (i = 0; i < 2; i++) // 首先处理管线两端的节点、设备
{
TPipeSys::PtLoction nSide = (TPipeSys::PtLoction)i;
XPoint ptSide = GetVertexPt(nSide); // 新坐标
OPENOBJ_BEGIN(GetNode(i), AcDb::kForRead, TDbPipeNode, pNode);
if (pNode != NULL)
{
if (pNode->isKindOf(TDbDuctNode::desc())) // 节点
{
TDbDuctNode *pDuctNode = TDbDuctNode::cast(pNode);
TDbDuctNode::DuctNodeType nType = pDuctNode->GetNodeType(); // 节点类型
if (nType == TDbDuctNode::kStem) // 堵头
{
if (pDuctNode->upgradeOpen() == Acad::eOk)
{
pDuctNode->SetLocation(ptSide); // 修改m_ptLocation
pDuctNode->SetILocation(0, ptSide);
pDuctNode->downgradeOpen();
}
}
else if (nType == TDbDuctNode::kTaoDong) // 掏洞
{
SetNode(i, AcDbObjectId::kNull); // 管线节点设置为空
if (pDuctNode->upgradeOpen() == Acad::eOk)
{
pDuctNode->erase(); // 掏洞节点直接被删除
pDuctNode->downgradeOpen();
}
}
else // 其他
{
int nIndex = pDuctNode->FindIdInLink(objectId());
if (nIndex != -1) // 存在连接关系
{
SetNode(i, AcDbObjectId::kNull); // 管线节点设置为空
if (pDuctNode->upgradeOpen() == Acad::eOk)
{
pDuctNode->SetIType(nIndex, 1); // 接口设置为空
pDuctNode->downgradeOpen();
}
}
}
}
else if (pNode->isKindOf(THDbEquipment::desc())) // 设备,8.0以后再做处理
{
}
}
OPENOBJ_END();
}
if (bSXTT) // 当前正在进行的命令是“生系统图”
{
return;
}
for (i = 0; i < m_lstEquipment.Length(); i++) // 再处理附着的设备及节点
{
AcDbObjectId id = *m_lstEquipment[i];
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbPipeNode, pNode);
if (pNode != NULL)
{
if (pNode->isKindOf(TDbDuctNode::desc())) // 掏洞节点
{
TDbDuctNode *pDuctNode = TDbDuctNode::cast(pNode);
if (pDuctNode->upgradeOpen() == Acad::eOk)
{
pDuctNode->RemoveInterface(objectId()); // 删除被掏洞接口
pDuctNode->SetNodeType(TDbDuctNode::kStem);
pDuctNode->downgradeOpen();
}
RemoveEquipment(id);
i--;
}
else if (pNode->isKindOf(THDbEquipment::desc())) // 设备
{
THDbEquipment *pEquipment = THDbEquipment::cast(pNode);
int nCount = pEquipment->GetInterfaceNum();
for (int j=0; j<nCount; j++)
{
AcDbObjectId ductId = pEquipment->GetIPipe(j);
if (ductId==objectId() && !CanAttachEquipment(*pEquipment, j)) // 断开
{
if (pEquipment->upgradeOpen() == Acad::eOk)
{
pEquipment->SetIPipe(j, AcDbObjectId::kNull);
pEquipment->downgradeOpen();
}
break;
RemoveEquipment(id);
i--;
}
}
}
}
OPENOBJ_END();
}
}
Acad::ErrorStatus TDbDuct::subTransformBy(const AcGeMatrix3d& xform)
{
assertWriteEnabled();
Acad::ErrorStatus es = TDbPipePrototype::subTransformBy(xform);
BOOL bApplyToNode(TRUE),
bSXTT(FALSE); // 是否提供变化给节点
if (!!objectId())
{
XString &sCmd = GetCurDocData()->m_sCurCommand;
if (_tcsicmp(sCmd, _T("MIRROR"))==0 || _tcsicmp(sCmd, _T("COPY"))==0 ||
_tcsicmp(sCmd, _T("COPYCLIP"))==0 || _tcsicmp(sCmd, _T("PASTECLIP"))==0)
{
bApplyToNode = FALSE; // 管线的复制、镜像操作,不提供变化给节点
}
bSXTT = _tcsicmp(sCmd, _T("sxtt"))==0;
}
if (objectId().isValid() && bApplyToNode)
{
ApplyChangeToNode(bSXTT); // 管线的移动、旋转操作,提供变化给节点
}
return es;
}
///////////////////////////////存储数据///////////////////////////////////////////
Acad::ErrorStatus TDbDuct::dwgInFields(AcDbDwgFiler* pFiler)
{
assertWriteEnabled();
Acad::ErrorStatus es = TDbPipePrototype::dwgInFields(pFiler);
if (es != Acad::eOk)
{
return es;
}
Adesk::UInt8 nVer;
pFiler->readItem(&nVer);
if (nVer > g_nVersion) // Version is too new
{
return Acad::eMakeMeProxy;
}
pFiler->readItem(&m_nSysDrawMod);
pFiler->readItem(&m_dWidth);
pFiler->readItem(&m_dHeight);
pFiler->readItem(&m_dDuctWeight);
pFiler->readItem(&m_dVDAngle);
pFiler->readItem(&m_nMaterial);
ReadString(pFiler, m_sLabel);
pFiler->readItem(&m_dSpeedSubMid);
pFiler->readItem(&m_dSpeedLength);
m_lstEquipment.Reset();
Adesk::UInt8 nCount = 0;
pFiler->readItem(&nCount);
for (Adesk::UInt8 i=0; i<nCount; i++)
{
AcDbSoftPointerId id;
pFiler->readItem(&id);
m_lstEquipment.Append(new AcDbSoftPointerId(id));
}
pFiler->readItem(&m_idDoteLayer);
if (nVer > 1) // 7.6
{
pFiler->readItem(&m_nSection);
pFiler->readItem(&m_dFlChuTou);
pFiler->readItem(&m_dFlThick);
Adesk::UInt8 nTmpNum = 0;
pFiler->readItem(&nTmpNum);
m_eDQType = (TDbDuct::DuiQiType)nTmpNum;
pFiler->readItem(&nTmpNum);
m_eDQSide = (TPipeSys::PtLoction)nTmpNum;
pFiler->readItem(&m_dCalWeight);
pFiler->readItem(&m_nSpare);
pFiler->readItem(&m_dSpare);
ReadString(pFiler, m_csSpare);
m_dVer = 7.6;
}
else // 7.5
{
m_nSection = IsCircleDuct()?1:0;
m_dFlChuTou = 100.0;
m_dFlThick = 50.0;
m_eDQType = (TDbDuct::DuiQiType)0;
m_eDQSide = (TPipeSys::PtLoction)0;
m_dCalWeight = 0;
m_nSpare = 0;
m_dSpare = 0.0;
m_csSpare = _T("");
m_dVer = 7.5;
}
return pFiler->filerStatus();
}
Acad::ErrorStatus TDbDuct::dwgOutFields(AcDbDwgFiler* pFiler) const
{
assertReadEnabled();
Acad::ErrorStatus es = TDbPipePrototype::dwgOutFields(pFiler);
if (es != Acad::eOk)
{
return es;
}
// if (g_nSaveTArchVer == 7) // 8.0使用
// {
// pFiler->writeItem((Adesk::UInt8)2);
// }
// else
// {
// pFiler->writeItem(g_nVersion);
// }
pFiler->writeItem(g_nVersion);
pFiler->writeItem(m_nSysDrawMod);
pFiler->writeItem(m_dWidth);
pFiler->writeItem(m_dHeight);
pFiler->writeItem(m_dDuctWeight);
pFiler->writeItem(m_dVDAngle);
pFiler->writeItem(m_nMaterial);
pFiler->writeItem((const TCHAR *)m_sLabel);
pFiler->writeItem(m_dSpeedSubMid);
pFiler->writeItem(m_dSpeedLength);
Adesk::UInt8 nCount = (Adesk::UInt8)m_lstEquipment.Length();
pFiler->writeItem(nCount);
for (Adesk::UInt8 i = 0; i < nCount; i++)
{
pFiler->writeItem(m_lstEquipment[i]);
}
pFiler->writeItem(m_idDoteLayer);
if (g_nSaveTArchVer > 6)
{
pFiler->writeItem(m_nSection);
pFiler->writeItem(m_dFlChuTou);
pFiler->writeItem(m_dFlThick);
pFiler->writeItem((Adesk::UInt8)m_eDQType);
pFiler->writeItem((Adesk::UInt8)m_eDQSide);
pFiler->writeItem(m_dCalWeight);
pFiler->writeItem(m_nSpare);
pFiler->writeItem(m_dSpare);
pFiler->writeItem((const TCHAR *)m_csSpare);
}
return pFiler->filerStatus();
}
Acad::ErrorStatus TDbDuct::dxfInFields(AcDbDxfFiler* pFiler)
{
assertWriteEnabled();
Acad::ErrorStatus es = TDbPipePrototype::dxfInFields(pFiler);
if (es != Acad::eOk)
return es;
if (!pFiler->atSubclassData(_T("TDbDuct")))
return Acad::eBadDxfSequence;
resbuf rb;
while ((es==Acad::eOk) && ((es=pFiler->readResBuf(&rb))==Acad::eOk))
{
switch (rb.restype) {
case AcDb::kDxfXTextString+1:
m_sLabel = rb.resval.rstring;
break;
case AcDb::kDxfXReal:
m_dWidth = rb.resval.rreal;
break;
case AcDb::kDxfXReal+1:
m_dHeight = rb.resval.rreal;
break;
case AcDb::kDxfXReal+2:
m_dTextHeight = rb.resval.rreal;
break;
case AcDb::kDxfXCoord:
m_ptLabel = rb.resval.rpoint;
break;
default:
pFiler->pushBackItem();
es = Acad::eEndOfFile;
break;
}
}
if (es != Acad::eEndOfFile)
return Acad::eInvalidResBuf;
return pFiler->filerStatus();
}
Acad::ErrorStatus TDbDuct::dxfOutFields(AcDbDxfFiler* pFiler) const
{
Acad::ErrorStatus es = TDbPipePrototype::dxfOutFields(pFiler);
assert(es == Acad::eOk);
es = pFiler->writeItem(AcDb::kDxfSubclass,_T("TDbDuct"));
assert(es == Acad::eOk);
pFiler->writeString(AcDb::kDxfXTextString+1, (const TCHAR*)m_sLabel);
pFiler->writeDouble(AcDb::kDxfXReal, m_dWidth);
pFiler->writeDouble(AcDb::kDxfXReal+1, m_dHeight);
pFiler->writeDouble(AcDb::kDxfXReal+2, m_dTextHeight);
pFiler->writePoint3d(AcDb::kDxfXCoord, m_ptLabel);
pFiler->writeUInt8(AcDb::kDxfInt8, IsVertical());
return es;
}
////////////////////////////////////处理实体/////////////////////////////////
// 处理管线打开
Acad::ErrorStatus TDbDuct::subOpen(AcDb::OpenMode mode)
{
Acad::ErrorStatus es = TDbPipePrototype::subOpen(mode);
if (es==Acad::eOk && g_nCmdReactor!=CMD_UPDATE)
{
if (mode==AcDb::kForWrite && database()==acdbCurDwg())
{
m_dOldHeight = m_dHeight;
m_dOldWidth = m_dWidth;
}
}
return es;
}
// 处理管线实体,注:在此处解决阀门比例问题
Acad::ErrorStatus TDbDuct::subClose()
{
Acad::ErrorStatus es = TDbPipePrototype::subClose();
if (es==Acad::eOk && isModified() && database()==acdbCurDwg())
{
for (int i=0; i<m_lstAttachment.Length(); i++) // 修改管径时同时修改阀门比例
{
OPENOBJ_BEGIN(*m_lstAttachment[i], AcDb::kForRead, TDbPipeValve, pAttach);
if (pAttach != NULL)
{
BOOL bCanAttach = CanAttach(*pAttach);
if (bCanAttach)
{
double dScale = pAttach->GetYScale(),
dNewScale = m_dWidth/1000;
if (fabs(dScale - dNewScale) > 0.001)
{
if (pAttach->upgradeOpen() == Acad::eOk)
{
pAttach->assertWriteEnabled();
pAttach->SetYScale(dNewScale);
pAttach->downgradeOpen();
}
}
}
}
OPENOBJ_END();
}
}
return es;
}
// 处理管线删除
Acad::ErrorStatus TDbDuct::subErase(Adesk::Boolean bErasing)
{
Acad::ErrorStatus es = TDbPipePrototype::subErase(bErasing); // 删除附件
if (es==Acad::eOk && bErasing==Adesk::kTrue && database()==acdbCurDwg())
{
int i(0);
for (i=0; i<2; i++)
{
AcDbObjectId id = GetNode(i);
OPENOBJ_BEGIN(id, AcDb::kForWrite, TDbDuctNode, pDuctNode);
if (pDuctNode != NULL) // 将风管节点中的本接口的接口类型设置为1(空)
{
int nIndex = pDuctNode->FindIdInLink(objectId());
if (nIndex != -1) // 存在连接关系
{
pDuctNode->SetIType(nIndex, 1);
}
if (pDuctNode->Is("TaoDong"))
{
int nMain = pDuctNode->GetMainDuctNum();
if (nMain != nIndex)
{
pDuctNode->erase(); // 当支管被删时,掏洞节点应同时被删
continue;
}
}
}
OPENOBJ_END();
}
for (i=0; i<m_lstEquipment.Length(); i++) // 解除与附着设备、接口的连接
{
AcDbObjectId &id = *m_lstEquipment[i];
OPENOBJ_BEGIN(id, AcDb::kForWrite, TDbPipeNode, pNode);
if (pNode != NULL)
{
if (pNode->isKindOf(TDbDuctNode::desc())) // 节点
{
TDbDuctNode *pDuctNode = TDbDuctNode::cast(pNode);
pDuctNode->RemoveInterface(objectId());
pDuctNode->SetNodeType(TDbDuctNode::kStem);
continue;
}
else if (pNode->isKindOf(THDbEquipment::desc())) // 设备
{
THDbEquipment *pEquipment = THDbEquipment::cast(pNode);
int nCount = pEquipment->GetInterfaceNum();
for (int j=0; j<nCount; j++)
{
const AcDbObjectId &ductId = pEquipment->GetIPipe(j);
if (ductId == objectId())
{
pEquipment->SetIPipe(j, AcDbObjectId::kNull);
break;
}
}
}
}
OPENOBJ_END();
}
}
return es;
}
////////////////////////////////////绘图部分/////////////////////////////////
Acad::ErrorStatus TDbDuct::ExplodeOrDraw2d(XExplodeDraw &dc) const
{
// cet 2016.10.17 add 图层关闭时,实体不显示,不进行绘制(打印时,也不会绘制)
AcDbLayerTableRecordPointer player(this->layerId(), AcDb::kForRead);
if (player.openStatus() == Acad::eOk && player->isOff())
{
return Acad::eOk;
}
Acad::ErrorStatus es = Acad::eOk;
if (!IsVisibleEntity(this)) // 查询管线系统的显示属性
{
return es;
}
BOOL bIsWeight = g_bPipeWeight; // 是否管线加粗(针对非垂直管线)
if (dc.IsFullExplode())
{
AcDbDatabase* pDb = database();
if (pDb != NULL)
{
AcDbDictionary* pRootDict = NULL;
es = pDb->getNamedObjectsDictionary(pRootDict, AcDb::kForRead);
assert(es == Acad::eOk);
AcDbObject* pObj = NULL;
es = pRootDict->getAt(g_sDbPsConfig, pObj, AcDb::kForRead);
if (es == Acad::eOk)
{
bIsWeight = ((TDbPsConfig *)pObj)->IsLineWeight();
pObj->close();
}
pRootDict->close();
}
}
if (IsVertical())
{
es = DrawVerDuct2d(dc); // 立管
}
else
{
es = DrawHorDuct2d(dc); // 非立管
}
if (es == Acad::eOk && IsShowPropertyText() && IsModel())
{
es = DrawPropertyText(dc); // 在管线中点位置显示管线的属性(针对非立管)
}
if (IsDrawLabel()) // 绘制非立管管径标注
{
DrawLabelText(dc);
}
return es;
}
Acad::ErrorStatus TDbDuct::DrawVerDuct2d(XExplodeDraw &dc) const // 立管
{
XPoint ptCenter(GetStartPoint().x, GetEndPoint().y);
if ((1 == m_nSysDrawMod) || (2 == m_nSection)) // 单线图或软管
{
dc << ptCenter;
return Acad::eOk;
}
XCurveSegment seg1, seg2; // 圆线
XPoly2D rectPoly, vDuctPoly; // 方线
// 1、判断截面形状,并获取绘制线
if (m_nSection == 1) // 圆截面
{
XCircle cirIn(ptCenter, m_dWidth/2);
seg1 = cirIn; // 圆外线
XVector3D vtTmp1(1, 1, 0), vtTmp2(-1, 1, 0);
vtTmp1.Normalize();
vtTmp2.Normalize();
vtTmp1.Scale(m_dWidth/2);
vtTmp2.Scale(m_dWidth/4);
XPoint pt1 = ptCenter + vtTmp1,
pt2 = ptCenter + vtTmp2,
pt3 = ptCenter - vtTmp1,
pt4 = pt2 + vtTmp2;
XArc arc(pt1, pt2, pt3);
seg2 = arc; // 圆内线
}
else if (m_nSection == 0) // 方截面
{
::GetSquare(ptCenter, GetVDAngle(), m_dWidth, m_dHeight, &rectPoly, &vDuctPoly);
}
// else if (m_nSection == 3) // 椭圆截面
// {
// }
// else if (m_nSection == 4) // 扁圆截面
// {
// }
// 2、判断绘制情况:(1)虚线、实线,(2)是否绘制方内线
int nDrawMod(0); // 实线,有内线
AcDbObjectId upNodeId = GetVerUpNode();
OPENOBJ_BEGIN(upNodeId, AcDb::kForRead, TDbPipeNode, pNode);
if (pNode != NULL)
{
if (pNode->isKindOf(THDbEquipment::desc()))
{
nDrawMod = 1; // 虚线,无内线
}
else if (pNode->isKindOf(TDbDuctNode::desc()))
{
TDbDuctNode *pDuctNode = TDbDuctNode::cast(pNode);
if (!pDuctNode->Is(_T("Stem")))
{
nDrawMod = 1;
}
}
}
OPENOBJ_END();
AcDbObjectId idLineTypeOld;
if (nDrawMod == 1) // 注:立管被遮挡
{
idLineTypeOld = dc.GetLineTypeId();
AcDbObjectId idDashType = InitLineType(_T("DASH"), database());
if (idDashType.isValid())
{
dc.SetLineType(idDashType);
}
}
double dWeight = GetPScale()*m_dDuctWeight;
if (m_nSection == 1) // 圆管
{
if (g_bPipeWeight && (nDrawMod==0))
{
DrawWeight(dc, dWeight, seg1, colorIndex(), linetypeScale());
}
else
{
dc << seg1;
}
if (nDrawMod == 0)
{
dc << seg2;
}
}
else if (m_nSection == 0) // 方管
{
if (g_bPipeWeight && (nDrawMod==0))
{
DrawWeight(dc, dWeight, rectPoly, colorIndex(), linetypeScale());
}
else
{
dc << rectPoly;
}
if (nDrawMod == 0)
{
dc << vDuctPoly;
}
}
if (nDrawMod == 1)
{
dc.SetLineType(idLineTypeOld);
}
return Acad::eOk;
}
Acad::ErrorStatus TDbDuct::DrawHorDuct2d(XExplodeDraw &dc) const // 水平管
{
XCurveSegment cvHide;
GetHideCurve(cvHide); // 考虑遮挡的当前曲线
DList<XCurveSegment> lstCurve; // 存储打断后的曲线(中心线)
if (g_bBreakPipe) // 打断
{
GetBrokenCurves(cvHide, lstCurve); // 获取打断后的曲线
}
else
{
lstCurve.Append(new XCurveSegment(cvHide));
}
int i(0),
nCount = lstCurve.Length();
double dWeight = GetPScale()*m_dDuctWeight;
TPipeSys::ModelType nModelType = GetModelType();
if (m_nSysDrawMod==1 || nModelType==TPipeSys::kSystem ||
nModelType==TPipeSys::kPrinciple) // 1、绘制中线的情况
{
for (i=0; i<nCount; i++) // 单线,系统图,在边线层画中心线
{
XCurveSegment &seg = *lstCurve[i];
BOOL bWeight = nModelType==TPipeSys::kSystem ||
nModelType==TPipeSys::kPrinciple;
if (g_bPipeWeight && bWeight) // 单线图不加粗
{
DrawWeight(dc, dWeight, seg, colorIndex(), linetypeScale());
}
else
{
dc << seg;
}
}
return Acad::eOk;
}
if (m_nSysDrawMod == 2) // 三线图,在中心线层绘制中心线
{
AcDbObjectId idLayerOld = dc.GetLayerId(), // 保留原来的值
idLineTypeOld = dc.GetLineTypeId();
AcDbObjectId idDoteLayer = m_idDoteLayer;
if (idDoteLayer.isValid())
{
dc.SetLayer(idDoteLayer);
}
dc.SetColorLayer(colorIndex(), idDoteLayer);
AcDbObjectId idDashType;
OPENOBJ_BEGIN(idDoteLayer, AcDb::kForRead, AcDbLayerTableRecord, pRec);
if (pRec != NULL)
{
idDashType = pRec->linetypeObjectId();
dc.SetLineType(idDashType);
}
OPENOBJ_END();
for (i = 0; i < nCount; i++)
{
XCurveSegment &seg = *lstCurve[i];
dc << seg; // 绘制中心线
}
dc.SetLayer(idLayerOld);
dc.SetColorLayer(colorIndex(), idLayerOld);
dc.SetLineType(idLineTypeOld);
}
XCurveSegment segUp, segDown;
XDirectionCurve segDir(cvHide.StartPoint(), cvHide.EndPoint(), cvHide.GetBulge());
segUp = segDir.Offset(m_dWidth/2, LS_FINITE);
segDown = segDir.Offset(-m_dWidth/2, LS_FINITE);
DList<XCurveSegment> lstCurve1;
if (g_bBreakPipe) // 2、绘制风管上线
{
GetBrokenCurves(segUp, lstCurve1);
}
else
{
lstCurve1.Append(new XCurveSegment(segUp));
}
nCount = lstCurve1.Length();
for (i=0; i<nCount; i++)
{
XCurveSegment &seg1 = *lstCurve1[i];
if (g_bPipeWeight)
{
DrawWeight(dc, dWeight, seg1, colorIndex(), linetypeScale());
}
else
{
dc << seg1;
}
}
DList<XCurveSegment> lstCurve2;
if (g_bBreakPipe) // 3、绘制风管下线
{
GetBrokenCurves(segDown, lstCurve2);
}
else
{
lstCurve2.Append(new XCurveSegment(segDown));
}
nCount = lstCurve2.Length();
for (i=0; i<lstCurve2.Length(); i++)
{
XCurveSegment &seg2 = *lstCurve2[i];
if (g_bPipeWeight)
{
DrawWeight(dc, dWeight, seg2, colorIndex(), linetypeScale());
}
else
{
dc << seg2;
}
}
return Acad::eOk;
}
Acad::ErrorStatus TDbDuct::DrawLabelText(XExplodeDraw &dc) const // 标注
{
XPoint ptOnThis;
if (ProjectToMe(m_ptLabel, ptOnThis))
{
double dRotation(0);
if (!IsVertical()) // 不是立管
{
if (Is(CURVE_LINE))
{
dRotation = Direction(ptOnThis);
}
else if (Is(CURVE_ARC))
{
XPoint ptCenter;
GetArc().Center(ptCenter);
dRotation = ads_angle(ptCenter, m_ptLabel) + PI/2;
}
dRotation = CT_std_angle(dRotation);
if (fabs(dRotation) < 1.0E-6)
{
dRotation = 0;
}
if (fabs(dRotation-PI/2) < 1.0E-6)
{
dRotation = PI/2;
}
if (fabs(dRotation-PI/2*3) < 1.0E-5)
{
dRotation = PI/2*3;
}
if ((dRotation>(PI/2+1.0E-6) && dRotation<(PI*3/2+1.0E-6)))
{
dRotation = CT_std_angle(dRotation + PI);
}
}
AcDbObjectId idLayerOld = dc.GetLayerId(),
idLayer = m_idLabelLayer;
// if (m_idLabelLayer.isValid())
// {
// dc.SetLayer(m_idLabelLayer);
// }
OPENOBJ_BEGIN(m_idLabelLayer, AcDb::kForRead, AcDbLayerTableRecord, pRec);
if (pRec != NULL)
{
dc.SetLayer(m_idLabelLayer);
}
OPENOBJ_END();
dc.SetColorLayer(colorIndex(), idLayer);
TDbText text;
text.setPropertiesFrom(this);
text.setLayer(m_idLabelLayer);
text.SetStyleId(m_idTextStyle);
text.SetText(GetLabelText());
text.SetRotation(dRotation);
text.SetLocation(XPoint(m_ptLabel.x, m_ptLabel.y, 0));
text.SetHeight(m_dTextHeight);
text.SetAlignment(XExplodeDraw::kMiddleCenter);
TPushProperty vProp(&text, dc);
if (dc.IsFullExplode())
{
text.ExplodeOrDraw2d(dc);
}
else
{
dc.DrawEntity(text);
}
dc.SetColorLayer(colorIndex(), idLayerOld);
dc.SetLayer(idLayerOld);
}
return Acad::eOk;
}
Acad::ErrorStatus TDbDuct::ExplodeOrDraw3d(XExplodeDraw &dc) const
{
// sg delete,防止三维下炸开会崩溃
// if (!dc.IsFullExplode()) // 如果是动态预演,则简单绘制
// {
// AcGiCommonDraw* dcCommon = ((XAcGiViewDraw &)dc).GetCommonDraw();
// if (dcCommon->isDragging())
// {
// XCurveSegment segTmp = (*this);
// dc << segTmp;
// return Acad::eOk;
// }
// }
if (GetModelType()==TPipeSys::kSystem || GetModelType()==TPipeSys::kPrinciple)
{
XCurveSegment segTmp = (*this);
dc << segTmp;
return Acad::eOk; // 系统和原理图
}
////////////////模型图////////////////
double dFThick = m_dFlThick * 0.5; // 获取管线两端法兰遮挡管线的宽度
if (fabs(dFThick) < 1.0E-5)
{
dFThick = 2; // 通常钢板厚度为4
}
XPoint ptS(GetStartPoint()), ptE(GetEndPoint());
TPipeSys::PtLoction nSide = TPipeSys::kStartPt;
XVector3D vtS = GetDirection(ptS, nSide), // 切线方向
vtE = GetDirection(ptE, nSide);
vtS.Normalize();
vtE.Normalize();
vtS.Scale(dFThick);
vtE.Scale(dFThick);
ptS = ptS + vtS; // 绘制时的起、止点,扣除了法兰遮挡
ptE = ptE + vtE;
BOOL bIsOk(TRUE);
DList<X3DFace> faces;
if (IsVertical()) // 立管
{
if (m_nSection == 1) // 圆管
{
if (!DrawColumn3d(ptS, vtS, ptE, vtS, faces))
{
return Acad::eInvalidInput;
}
}
else // 矩形
{
XPoly2D pts1, pts2;
::GetSquare(ptS, m_dVDAngle, m_dWidth, m_dHeight, &pts1, NULL); // 截面
::GetSquare(ptE, m_dVDAngle, m_dWidth, m_dHeight, &pts2, NULL);
if (pts1.Length()!=4 || pts2.Length()!=4)
{
return Acad::eInvalidInput;
}
X3DFace face = ::GetFace1(*pts1[0], *pts1[1], *pts1[2], *pts1[3]);
faces.Append(new X3DFace(face));
face = ::GetFace1(*pts2[0], *pts2[1], *pts2[2], *pts2[3]);
faces.Append(new X3DFace(face));
face = ::GetFace1(*pts1[0], *pts1[1], *pts2[1], *pts2[0]);
faces.Append(new X3DFace(face));
face = ::GetFace1(*pts1[3], *pts1[2], *pts2[2], *pts2[3]);
faces.Append(new X3DFace(face));
face = ::GetFace1(*pts1[0], *pts1[3], *pts2[3], *pts2[0]);
faces.Append(new X3DFace(face));
face = ::GetFace1(*pts1[1], *pts1[2], *pts2[2], *pts2[1]);
faces.Append(new X3DFace(face));
}
}
else if (Is(CURVE_ARC)) // 弧管
{
XPoint ptArc; // 弧中点,但在3D状态下不直接用,防止标高出错
XCurveSegment seg = GetCurve(); // 管段
XArc arcSeg = seg.GetArc();
arcSeg.MidPoint(ptArc);
XVector3D vecS(-vtS.x, -vtS.y, -vtS.z),
vecE(-vtE.x, -vtE.y, -vtE.z);
XPointList pts;
::GetTHSplitPts(ptS, ptE, vecS, vecE, g_nSplitNum, pts, 2, ptArc);
int nLen = pts.Length(); // 切割成若干小圆柱或立方体
if (nLen != g_nSplitNum+2)
{
return Acad::eInvalidInput;
}
AcGeCircArc3d arc(*pts[0], *pts[g_nSplitNum/2], *pts[g_nSplitNum+1]);
for (int i=0; i<g_nSplitNum+1; i++) // 循环处理弧段
{
AcGeLine3d tangentL1, tangentL2;
if (arc.tangent(pts[i]->AsAcGePoint3d(), tangentL1)==Adesk::kFalse ||
arc.tangent(pts[i+1]->AsAcGePoint3d(), tangentL2)==Adesk::kFalse)
{
return Acad::eInvalidInput;
}
BOOL bSHow1 = i==0,
bSHow2 = i==g_nSplitNum;
AcGeVector3d vt1 = tangentL1.direction(),
vt2 = tangentL2.direction();
if (m_nSection == 1) // 圆管
{
XVector3D __vt2(vt2);
bIsOk = DrawColumn3d(*pts[i], XVector3D(vt1), *pts[i+1],
__vt2, faces, bSHow1, bSHow2);
}
else // 矩形
{
XVector3D __vt2(vt2);
bIsOk = DrawCube3d(*pts[i], XVector3D(vt1), *pts[i+1],
__vt2, faces, bSHow1, bSHow2);
}
if (!bIsOk)
{
return Acad::eInvalidInput;
}
}
}
else // 直管
{
if (m_nSection == 1) // 圆管
{
bIsOk = DrawColumn3d(ptS, vtS, ptE, vtS, faces);
}
else // 矩形
{
bIsOk = DrawCube3d(ptS, vtS, ptE, vtS, faces);
}
if (!bIsOk)
{
return Acad::eInvalidInput;
}
}
int nCount = faces.Length();
for (int k=0; k<nCount; k++)
{
X3DFace face = *faces[k];
dc << face;
}
return Acad::eOk;
}
BOOL TDbDuct::DrawCube3d(XPoint pt1, XVector3D vt1, XPoint pt2, XVector3D &vt2,
DList<X3DFace> &faces, BOOL bShow1, BOOL bShow2) const
{
XPointList pts1, pts2;
::GetDuctSidePts(pt1, m_dWidth, m_dHeight, vt1, pts1);
::GetDuctSidePts(pt2, m_dWidth, m_dHeight, vt2, pts2);
if (pts1.Length()!=4 || pts2.Length()!=4)
{
return FALSE;
}
X3DFace face;
face = ::GetFace1(*pts1[0], *pts1[1], *pts2[1], *pts2[0], bShow1, TRUE, bShow2);
faces.Append(new X3DFace(face));
face = ::GetFace1(*pts1[0], *pts1[3], *pts2[3], *pts2[0], bShow1, TRUE, bShow2);
faces.Append(new X3DFace(face));
face = ::GetFace1(*pts1[3], *pts1[2], *pts2[2], *pts2[3], bShow1, TRUE, bShow2);
faces.Append(new X3DFace(face));
face = ::GetFace1(*pts1[1], *pts1[2], *pts2[2], *pts2[1], bShow1, TRUE, bShow2);
faces.Append(new X3DFace(face));
if (bShow1) // 起点面
{
face = ::GetFace1(*pts1[0], *pts1[1], *pts1[2], *pts1[3]);
faces.Append(new X3DFace(face));
}
if (bShow2) // 终点面
{
face = ::GetFace1(*pts2[0], *pts2[1], *pts2[2], *pts2[3]);
faces.Append(new X3DFace(face));
}
return TRUE;
}
BOOL TDbDuct::DrawColumn3d(XPoint pt1, XVector3D vt1, XPoint pt2, XVector3D &vt2,
DList<X3DFace> &faces, BOOL bShow1, BOOL bShow2) const
{
BOOL bIsOk = ::GetColumn3DFaces(pt1, m_dWidth/2.0, vt1, pt2, m_dWidth/2.0,
vt2, faces, g_nSplitNum, 4, bShow1, bShow2, bShow1, bShow2);
return bIsOk;
}
///////////////////////////Override TDbPipePrototype//////////////////////////
XExtent TDbDuct::GetExtent() const
{
if (IsVertical())
{
if (m_nSection == 1) // 圆
{
return XExtent(m_dWidth, m_dWidth);
}
if (m_nSection == 0) // 方
{
return XExtent(m_dWidth, m_dHeight);
}
}
return TDbPipePrototype::GetExtent();
}
XExtent TDbDuct::GetOldExtent() const
{
if (IsVertical()) // 立管
{
if (m_nSection == 1) // 圆
{
return XExtent(m_dOldWidth, m_dOldWidth);
}
if (m_nSection == 0) // 方
{
return XExtent(m_dOldWidth, m_dOldHeight);
}
}
return TDbPipePrototype::GetOldExtent(); // 非立管
}
int TDbDuct::GetExtend(XPoint &low, XPoint &up) const
{
if (!IsVertical()) // 非立管
{
return TDbPipePrototype::GetExtend(low, up);
}
low = up = StartPoint(); // 立管
XExtent ex = GetExtent();
ex /= 2;
low -= ex;
up += ex;
return RTNORM;
}
XString TDbDuct::GetLabelText() const
{
XString sLabel = m_sLabel;
return sLabel;
}
void TDbDuct::ApplyDnDiameterChangeToLabel()
{
for (int i=0; i<m_lstAttachment.Length(); i++)
{
OPENOBJ_BEGIN(*m_lstAttachment[i], AcDb::kForRead, TDbPipeLabel, pLabel);
if (pLabel != NULL)
{
double dWide = GetWidth(),
dHigh = GetHeight();
if (pLabel->GetPipeType()!=TDbPipeLabel::kDuct ||
dWide!=pLabel->GetPipeWidth() || dHigh!= pLabel->GetPipeHeight())
{
if (pLabel->upgradeOpen() == Acad::eOk)
{
pLabel->assertWriteEnabled();
pLabel->SetPipeType(TDbPipeLabel::kDuct);
pLabel->SetPipeWidth(dWide);
pLabel->SetPipeHeight(dHigh);
pLabel->downgradeOpen();
}
}
}
OPENOBJ_END();
}
}
void TDbDuct::ResetDrawSpeed()
{
assertWriteEnabled();
double dSpeedLength(0), // 初始化
dSpeedSubMid(0);
OPENOBJ_BEGIN(GetNode(1), AcDb::kForRead, TDbDuctNode, pNode);
if (pNode != NULL)
{
if (pNode->IsHidePipe())
{
double dWidth = m_dFlThick*0.5; // 是否节点遮挡管线
if (dWidth > 1.0E-3)
{
dSpeedLength -= dWidth;
dSpeedSubMid -= dWidth/2;
}
}
}
OPENOBJ_END();
OPENOBJ_BEGIN(GetNode(0), AcDb::kForRead, TDbDuctNode, pNode);
if (pNode != NULL)
{
if (pNode->IsHidePipe())
{
double dWidth = m_dFlThick*0.5; // 是否节点遮挡管线
if (dWidth > 1.0E-3)
{
dSpeedLength -= dWidth;
dSpeedSubMid += dWidth/2;
}
}
}
OPENOBJ_END();
if (fabs(dSpeedLength)>1.0E-3 || fabs(dSpeedSubMid)>1.0E-3)
{
XCurveSegment cv = GetCurve();
cv.SetElevation(0); // 设置为二维,z=0
if (cv.Is(CURVE_ARC)) // 注:本版本弧管不支持加速
{
m_dSpeedLength = 0;
m_dSpeedSubMid = 0;
}
else
{
double dLength = cv.GetLength();
m_dSpeedLength = dLength + dSpeedLength;
m_dSpeedSubMid = dLength/2 + dSpeedSubMid;
}
}
else
{
m_dSpeedLength = 0;
m_dSpeedSubMid = 0;
}
}
//////////////////////////Renew TDbPipePrototype///////////////////////////////
// 判断立管的上节点是否连接了非立管
BOOL TDbDuct::IsUpPipesOk() const
{
if (!IsVertical())
{
return FALSE;
}
AcDbObjectId upNodeId = GetVerUpNode(); // 上节点
OPENOBJ_BEGIN(upNodeId, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode != NULL)
{
int nLen = pNode->GetInterfaceNum();
if (nLen > 1) // 至少连接了一个立管
{
for (int i=0; i<nLen; i++)
{
if (pNode->GetIPipe(i) != objectId())
{
OPENOBJ_BEGIN(pNode->GetIPipe(i), AcDb::kForRead, TDbDuct, pDuct);
if (pDuct!=NULL && !pDuct->IsVertical())
{
return TRUE;
}
OPENOBJ_END();
}
}
}
}
OPENOBJ_END();
return FALSE;
}
// 立管上节点连接的管线中,非立管的连接点
void TDbDuct::GetUpPipesPt(XPointList &pts) const
{
pts.Reset();
if (!IsUpPipesOk())
{
return;
}
AcDbObjectId upNodeId = GetVerUpNode();
OPENOBJ_BEGIN(upNodeId, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode != NULL)
{
int nLen = pNode->GetInterfaceNum();
for (int i=0; i<nLen; i++)
{
XVector3D vt = pNode->GetIDirection(i);
vt.Normalize();
if (fabs(vt.x)>1.0E-6 || fabs(vt.y)>1.0E-6)
{
XPoint ptTmp = pNode->GetILocation(i);
pts.Append(new XPoint(ptTmp));
}
}
}
OPENOBJ_END();
}
// 立管上节点连接的管线中,非立管的管径
AcGeDoubleArray TDbDuct::GetUpPipesWidth() const
{
AcGeDoubleArray widths;
if (!IsUpPipesOk())
{
return widths;
}
AcDbObjectId upNodeId = GetVerUpNode();
OPENOBJ_BEGIN(upNodeId, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode != NULL)
{
int nLen = pNode->GetInterfaceNum();
for (int i=0; i<nLen; i++)
{
XVector3D vt = pNode->GetIDirection(i);
vt.Normalize();
if (fabs(vt.x)>1.0E-6 || fabs(vt.y)>1.0E-6)
{
widths.append(pNode->GetIWidth(i));
}
}
}
OPENOBJ_END();
return widths;
}
// 非立管的向量
void TDbDuct::GetUpPipesVec(DList<XVector3D> &vts) const
{
if (!IsUpPipesOk())
{
return;
}
AcDbObjectId upNodeId = GetVerUpNode();
OPENOBJ_BEGIN(upNodeId, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode != NULL)
{
int nLen = pNode->GetInterfaceNum();
for (int i=0; i<nLen; i++)
{
XVector3D vt = pNode->GetIDirection(i);
if (fabs(vt.x)>1.0E-6 || fabs(vt.y)>1.0E-6)
{
vts.Append(new XVector3D(vt));
}
}
}
OPENOBJ_END();
}
//////////////////////////增加连接件到当前数据库///////////////////////////////
// 增加节点到当前数据库,ids-该节点自动连接的管线
AcDbObjectId TDbDuct::AddNodeToDb(const XPoint &ptAt, const DList<AcDbObjectId> &ids,
const AcDbIntArray &types, const int &nMainDuct)
{
int nLen = ids.Length();
if (nLen < 1)
{
return AcDbObjectId::kNull;
}
Adesk::UInt8 nMode = 0; // 传给实体
double dParam1(1.0), dParam2(0.0);
TDbDuctNode::DuctNodeType nType =
::GetNodeType(AcDbObjectId::kNull, ptAt, types, ids); // 节点类型
int nLink = ::GetDNodeConfig(nType, nMode, dParam1, dParam2); // 获取绘制参数
if (nType==TDbDuctNode::kTaoDong && nLink!=13)
{
BOOL bVDuct1 = ::IsVerDuct(AcDbObjectId::kNull, ids[0], types[0]),
bVDuct2 = ::IsVerDuct(AcDbObjectId::kNull, ids[1], types[1]);
if (bVDuct1 || bVDuct2)
{
nMode = 13; // 立管一律用样式13
}
}
TDbDuctNode* pNode = new TDbDuctNode;
pNode->SetNodeType(nType);
Adesk::UInt8 nDrawMod = GetSysDrawMod();
if (nDrawMod==1 && (GetModelType()==TPipeSys::kSystem ||
GetModelType()==TPipeSys::kPrinciple))
{
nDrawMod = 4; // 系统图
}
pNode->SetSysDrawMod(nDrawMod);
pNode->SetDrawMod(nMode); // 注:主要考虑到打断新生成的三、四通
pNode->SetDrawParam(dParam1);
pNode->SetDrawParam2(dParam2);
pNode->SetXMWNum((Adesk::UInt8)dParam2);
pNode->SetMainDuctNum(nMainDuct);
pNode->SetLocation(ptAt); // 死机处
pNode->SetLinkType((Adesk::UInt8)nLink);
pNode->UpdateInterface(GetSysType(), ptAt, ids, types);
TCHAR *layer;
layer = this->layer();
TCHAR szLayer[256]; // 图层
_tcscpy(szLayer, layer);
pNode->setLayer(szLayer);
pNode->setColor(AcCmColor());
pNode->setLinetype(this->linetype()); // 线型
pNode->SetDoteLayer(m_idDoteLayer);
pNode->SetFlangeLayer(::InitLayer(GetDuctFLLayerName(this->GetSysType()), database()));
AcDbObjectId id = AddToCurrentSpace(pNode, Adesk::kTrue);
delete []layer;
return id;
}
// 获取风管法兰图层名
CString GetDuctFLLayerName(const TPipeSys::SysType st)
{
int nIndex = (int)st - 50;
if (nIndex<0 || nIndex>5)
{
return CString();
}
CString csLayer[] = {LAYER_DUCT_SUPPLYFL, LAYER_DUCT_RETURNFL, LAYER_DUCT_FRESHFL,
LAYER_DUCT_VENTFL, LAYER_DUCT_SMOKEPREVENTIONFL, LAYER_DUCT_PRESSURESUPPLYFL};
return csLayer[nIndex];
}
/////////////////////打断、遮挡、连接、自动生成节点////////////////////////////
// 判断是否可以连接
// 注:风管中,要找的是起止节点是否连接的是同一个节点
BOOL TDbDuct::CanMergeWith(const TDbDuct &other, int* iPosThis, int* iPosOther) const
{
if (GetSysType() != other.GetSysType()) // 1、系统类型相同
{
return FALSE;
}
int bLine1 = Is(CURVE_LINE),
bLine2 = other.Is(CURVE_LINE);
if (bLine1 != bLine2) // 2. 几何特征判断
{
return FALSE;
}
if (m_nSection!=other.m_nSection || fabs(m_dWidth-other.GetWidth())>_distSnap
|| fabs(m_dHeight-other.GetHeight())>_distSnap) // 3、截面相同,宽、高相同
{
return FALSE;
}
const AcDbObjectId thisStartId = GetNode(0),
thisEndId = GetNode(1),
otherStartId = other.GetNode(0),
otherEndId = other.GetNode(1);
double nSweepAng(0.0);
AcDbObjectId mergeNodeId;
int nPosFlag(0), nThis(-1), nOther(-1); // 0-起点;1-终点
if (thisStartId == otherStartId)
{
nThis = nOther = 0;
mergeNodeId = thisStartId;
nPosFlag = 1; // Merge at both StartPoint
nSweepAng = GetBulge() - other.GetBulge();
}
else if (thisStartId == otherEndId)
{
nThis = 0;
nOther = 1;
mergeNodeId = thisStartId;
nPosFlag = 2; // Merge at this StartPoint() and that EndPoint()
nSweepAng = GetBulge() + other.GetBulge();
}
else if (thisEndId == otherStartId)
{
nThis = 1;
nOther = 0;
mergeNodeId = thisEndId;
nPosFlag = 4; // Merge at this EndPoint() and that StartPoint()
nSweepAng = GetBulge() + other.GetBulge();
}
else if (thisEndId == otherEndId)
{
nThis = nOther = 1;
mergeNodeId = thisEndId;
nPosFlag = 3; // Merge at both EndPoint()
nSweepAng = GetBulge() - other.GetBulge();
}
if (mergeNodeId.isNull())
{
return TDbPipePrototype::CanMergeWith(other, iPosThis, iPosOther);
}
TDbPipeNode *pNode = NULL;
if (acdbOpenObject(pNode, mergeNodeId, AcDb::kForRead) == Acad::eOk)
{
if (pNode->isKindOf(TDbDuctNode::desc())) // 节点
{
int nLen = pNode->GetInterfaceNum();
if (nLen > 2)
{
pNode->Close();
return FALSE;
}
TDbDuctNode *pDuctNode = TDbDuctNode::cast(pNode);
TDbDuctNode::DuctNodeType nType = pDuctNode->GetNodeType();
if ((nType == TDbDuctNode::kYiZiElbow) || (nType ==
TDbDuctNode::kFlange) || (nType == TDbDuctNode::kTaoDong))
{
pDuctNode->Close();
return FALSE;
}
pDuctNode->Close();
}
else // 设备
{
pNode->Close();
return TDbPipePrototype::CanMergeWith(other, iPosThis, iPosOther);
}
}
// 注:以下部分只对TDbDuctNode有效
if (!nPosFlag || GreatEqual(fabs(nSweepAng), 2*PI, _angSnap))
{
return FALSE;
}
AcGeVector3d vtDuctThis, vtDuctOther;
if (getFirstDeriv((nThis?EndPoint():StartPoint()), vtDuctThis)!=Acad::eOk ||
other.getFirstDeriv((nOther?other.EndPoint():other.StartPoint()),
vtDuctOther)!=Acad::eOk)
{
return FALSE;
}
if (::IsParallel(vtDuctOther, vtDuctThis) == 0)
{
return FALSE;
}
if (iPosThis)
{
*iPosThis = nThis;
}
if (iPosOther)
{
*iPosOther = nOther;
}
return TRUE;
}
BOOL TDbDuct::MergeWith(TDbDuct &other)
{
assertWriteEnabled();
int nThis(-1), nOther(-1);
BOOL bMerge = CanMergeWith(other, &nThis, &nOther); // 判断是否可以合并
if (!bMerge)
{
return bMerge;
}
BOOL bLabel = m_ptLabel!=XPoint(); // 管线标注
if (!m_bDrawLabel)
{
m_bDrawLabel = other.m_bDrawLabel;
}
double dDist2Pipe = 200,
dScale2Start = 0.5;
if (bLabel)
{
GetLabelLocation(dDist2Pipe, dScale2Start);
}
// 注:由于考虑对齐方式,需要对第二根管线进行处理,偏移其中心线
XCurveSegment seg(StartPoint(), EndPoint(), GetBulge());
XPoint ptNewStart, ptNewEnd;
seg.ProjectToMe(other.StartPoint(), ptNewStart);
seg.ProjectToMe(other.EndPoint(), ptNewEnd);
if (nThis==0 && nOther==0) // 合并
{
StartPoint() = ptNewEnd;
m_nodeStart = other.m_nodeEnd;
SetBulge(GetBulge() - other.GetBulge());
}
else if (nThis==0 && nOther==1)
{
StartPoint() = ptNewStart;
m_nodeStart = other.m_nodeStart;
SetBulge(GetBulge() + other.GetBulge());
}
else if (nThis==1 && nOther==0)
{
EndPoint() = ptNewEnd;
m_nodeEnd = other.m_nodeEnd;
SetBulge(GetBulge() + other.GetBulge());
}
else if (nThis==1 && nOther==1)
{
EndPoint() = ptNewStart;
m_nodeEnd = other.m_nodeStart;
SetBulge(GetBulge() - other.GetBulge());
}
int i(0);
for (i=0; i<other.m_lstAttachment.Length(); i++)
{
AddAttachment(*other.m_lstAttachment[i]);
}
for (i=0; i<other.m_lstHidePipe.Length(); i++)
{
AddHidePipe(*other.m_lstHidePipe[i]);
}
for (i=0; i<other.m_lstEquipment.Length(); i++)
{
AddEquipment(*other.m_lstEquipment[i]);
}
if (bLabel) // 管线标注
{
ResetLabelLocation(dDist2Pipe, dScale2Start);
}
other.assertWriteEnabled();
other.ResetAllShip();
for (i=0; i<other.m_lstEquipment.Length(); i++)
{
other.RemoveEquipment(*other.m_lstEquipment[i]);
}
return bMerge;
}
// 考虑遮挡的当前曲线,二维,z=0
void TDbDuct::GetHideCurve(XCurveSegment& cvHide) const
{
XCurveSegment cvHideTemp = GetCurve();
cvHideTemp.SetElevation(0); // 设置为二维,z=0
// 改为将数据写入数据库加速二维显示速度
if (fabs(m_dSpeedLength)>1.0E-3 && fabs(m_dSpeedSubMid)>1.0E-3)
{
double dChordLength = cvHideTemp.GetChordLength(m_dSpeedLength);
XPointDir2d ptSubMid;
cvHideTemp.Polar(m_dSpeedSubMid, ptSubMid);
cvHideTemp.GetSubSegment(ptSubMid, dChordLength, cvHide);
return;
}
cvHide = cvHideTemp;
}
// 打断部分的宽度
double TDbDuct::GetBreakWidth() const
{
double dWidth(2);
TDbPsConfig* pConfig = GetDwgPsGlobal(AcDb::kForRead);
if (pConfig != NULL)
{
dWidth = pConfig->GetBreakWidth();
if (pConfig->IsLineWeight())
{
dWidth += m_dDuctWeight;
}
pConfig->close();
}
dWidth *= GetPScale();
return dWidth;
}
// 通过管件附件打断的曲线,二维,z=0
void TDbDuct::GetBrokenCurves(const XCurveSegment &cv,
DList<XCurveSegment> &lstCurve) const
{
int nAttach = m_lstAttachment.Length(),
nHide = m_lstHidePipe.Length();
if (nAttach<=0 && nHide<=0) // 没有管件附件,也没有遮挡关系
{
lstCurve.Append(new XCurveSegment(cv));
return;
}
XVector3D vtDir(cv.EndPoint() - cv.StartPoint()); // 以直线段初始化方向
AcGeVector3d vtAttachment(vtDir); // 管线附件在基线上的方向
vtAttachment.z = 0;
vtAttachment.normalize();
AcGePoint3dArray arPoint(20); // 剪裁点
DList<XPoint> lstLocation; // 交点或者附件所在点
DList<XCurveSegment> lstBreakCurve; // 被剪裁的线段
double dDisThis = cv.GetLength(); // 管线长
int i(0);
for (i=0; i<nAttach; i++) // 取得临时管线附件和管件附件的在管线上的端点
{
const AcDbObjectId &id = m_lstAttachment[i];
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbPipeAttachment, pAttachment);
if (pAttachment != NULL)
{
if (pAttachment->IsCheckSysType() && pAttachment->GetSysType()!=GetSysType())
{
continue;
}
double dWidth = pAttachment->GetWidth()/2,
dScale = pAttachment->GetScale();
dWidth *= dScale;
TDbPipeValve* pValve = NULL;
if (pValve = TDbPipeValve::cast(pAttachment))
{
if(pValve->HasFlange()) // 如果是带法兰的阀门,宽度要增加法兰厚度
dWidth += pValve->GetFlangeWidth()*pValve->GetScale()
*GetPScale()/100/2;
}
if (dWidth > 1.0E-3)
{
XPoint ptLocation(pAttachment->GetLocation());
cv.ProjectToMe(ptLocation, ptLocation);
ptLocation.z = 0;
lstLocation.Append(new XPoint(ptLocation));
DisposeBreak(cv, arPoint, ptLocation, dWidth, dDisThis, vtAttachment,
lstBreakCurve); // 获得被打断部分的曲线,和打断点
}
}
OPENOBJ_END();
}
int j(0);
for(j=0; j<nHide; j++) // 管线的遮挡关系
{
OPENOBJ_BEGIN(m_lstHidePipe[j], AcDb::kForRead, TDbPipePrototype, pPipe);
if (pPipe!=NULL && IsVisibleEntity(pPipe))
{
AcGeVector3d vt1 = pPipe->Direction3d().AsAcGeVector3d(),
vt2 = this->Direction3d().AsAcGeVector3d();
double dAngle = vt1.angleTo(vt2);
double dBreakWidth = pPipe->GetBreakWidth(),
dWidth(0);
if (pPipe->isKindOf(TDbDuct::desc())) // 方风管
{
TDbDuct *pDuct = (TDbDuct*)pPipe;
dWidth = pDuct->GetWidth();
if ((1 == m_nSysDrawMod) || (2 == m_nSection) ||
pDuct->GetModelType()==TPipeSys::kSystem ||
pDuct->GetModelType()==TPipeSys::kPrinciple)
{
dWidth = 0;
}
}
else if (pPipe->isKindOf(TDbDoubleLinePipe::desc())) // TWT双线管
{
TDbDoubleLinePipe *pDLine = (TDbDoubleLinePipe*)pPipe;
dWidth = pDLine->GetDnDiameter();
}
// 注:打断宽度,不同于水管
dBreakWidth = (dBreakWidth + dWidth/sin(dAngle))/2.0;
if (dBreakWidth > 1.0E-3)
{
XCurveSegment cvPipe = *pPipe;
cvPipe.SetElevation(0); // 设置标高为0
XPoint ptIntersect, ptTemp;
if (cv.Intersection(cvPipe, ptIntersect, ptTemp))
{
ptIntersect.z = 0;
lstLocation.Append(new XPoint(ptIntersect));
DisposeBreak(cv, arPoint, ptIntersect, dBreakWidth, dDisThis,
vtAttachment, lstBreakCurve); // 获得被打断部分的曲线,和打断点
}
}
}
OPENOBJ_END();
}
// 按定位点到起点的距离快速排序(由小到大)
int nCount = arPoint.length();
if (nCount > 1)
{
DList<double> lstDist; // 打断点在曲线段上的距离
for (i=0; i<nCount; i++) // 为提高效率先计算出距离
{
XPoint ptTmp = arPoint[i];
double dDist = cv.PathDistance(arPoint[i]);
lstDist.Append(new double(dDist));
}
for (i=0; i<nCount-1; i++)
{
for (j=0; j<nCount-1-i; j++)
{
if (*lstDist[j]>*lstDist[j+1]) //Swap
{
lstDist.Swap(j, j+1);
arPoint.swap(j, j+1);
}
}
}
}
nCount = arPoint.length();
// 得到管线基线,并用管线附件打断管线成AcDbCurve
AcDbVoidPtrArray arSeg; // 裁剪后的曲线段,包括显示和不显示的管线
TDbPipePrototype pipeCv;
(XCurveSegment&)pipeCv = cv;
AcDbCurve* pCurve = pipeCv.GetBaseCurve();
Acad::ErrorStatus es2 = pCurve->getSplitCurves(arPoint, arSeg); // 裁剪
if (pCurve && es2==Acad::eInvalidInput) // 要裁剪的部分不在管线上,或不存在
{
AcGeMatrix3d mat;
mat.setToScaling(0.1);
pCurve->transformBy(mat);
// 可能由于坐标过大导致返回eInvalidInput,管线无法打断
AcGePoint3dArray arPoint2(20);
int k(0);
for (k=0; k<nCount; k++)
{
AcGePoint3d ptCur = arPoint[k];
ptCur.transformBy(mat);
pCurve->getClosestPointTo(ptCur, ptCur);
arPoint2.append(ptCur);
}
es2 = pCurve->getSplitCurves(arPoint2, arSeg);
if (es2 != Acad::eOk) // 不能打断
{
lstCurve.Append(new XCurveSegment(cv));
if (pCurve != NULL)
{
delete pCurve;
}
return;
}
mat.invert();
nCount = arSeg.length();
for (k=0; k<nCount; k++)
{
AcDbCurve *pCurve0 = (AcDbCurve *)arSeg[k];
pCurve0->transformBy(mat);
}
}
else if (pCurve == NULL || es2 != Acad::eOk) // 基线不存在,导致无法打断
{
lstCurve.Append(new XCurveSegment(cv));
if (pCurve != NULL)
{
delete pCurve;
}
return;
}
delete pCurve;
nCount = arSeg.length(); // 打断后,总段数
int nLocation = lstLocation.Length(); // 打断点个数
if (nCount == nLocation*2 + 1) // 正常情况,奇偶性
{
for (int k=0; k<nCount; k=k+2)
{
AcDbCurve *pCurve0 = (AcDbCurve *)arSeg[k];
TDbPipePrototype pipe;
pipe.SetBaseCurve(pCurve0); // 设置基线
delete pCurve0;
// 判断有没有反方向绘制的线段
XCurveSegment *pSeg = new XCurveSegment(pipe.GetCurve()); // 显示的管线
XPoint ptCurveS = pSeg->StartPoint(),
ptCurveE = pSeg->EndPoint();
BOOL bStartInside = FALSE,
bEndInside = FALSE;
for (int m=0; m<lstBreakCurve.Length(); m++)
{
XCurveSegment segTmp = *lstBreakCurve[m]; // 不显示的管线
if (segTmp.Is(CURVE_LINE))
{
XLine lineTmp = segTmp;
int nRet1 = ptCurveS&lineTmp,
nRet2 = ptCurveE&lineTmp;
if (nRet1 == PR_INSIDE)
{
bStartInside = TRUE;
}
if (nRet2 == PR_INSIDE)
{
bEndInside = TRUE;
}
}
}
if (!bStartInside || !bEndInside)
{
lstCurve.Append(pSeg);
}
}
}
else // 非正常情况,比如附件的遮挡范围超出基线
{
for (int k=0; k<nCount; k++)
{
AcDbCurve *pCurve0 = (AcDbCurve *)arSeg[k]; // 转换成AcDbCurve
TDbPipePrototype pipe;
pipe.SetBaseCurve(pCurve0);
delete pCurve0;
// 转换成XCurveSegment,并判断是否是附件的基线
XCurveSegment *pSeg = new XCurveSegment(pipe.GetCurve());
XPoint ptS = pSeg->StartPoint(),
ptE = pSeg->EndPoint();
BOOL bAppend = TRUE;
for (int j=0; j<nLocation; j++)
{
XPoint &pt = *lstLocation[j];
pt.z = 0;
int nResult = pt&(*pSeg);
if (nResult==PR_EDGE || nResult==PR_INSIDE)
{
bAppend = FALSE;
delete pSeg;
break;
}
}
if (bAppend) // 添加显示的曲线段
{
lstCurve.Append(pSeg);
}
}
}
if (lstCurve.Length() <= 0)
{
lstCurve.Append(new XCurveSegment(cv));
}
return;
}
// 处理打断,得到打断点数组arPoint,和不显示的管段的链表lstBreakCurve
void TDbDuct::DisposeBreak(const XCurveSegment &cv, AcGePoint3dArray &arPoint,
const XPoint ptLoc, double dWidth,
double dDistance, const AcGeVector3d &vtDir,
DList<XCurveSegment> &lstBreakCurve) const
{
if (Is(CURVE_ARC))
{
XArc arc2 = cv.GetArc();
XPoint pt3, pt4, ptMid;
arc2.GetStartPoint(pt3);
arc2.GetEndPoint(pt4);
// arc2.GetPoints(pt3, pt4);
arc2.MidPoint(ptMid);
pt3.z = 0;
pt4.z = 0;
ptMid.z = 0;
XArc arc(pt3, ptMid, pt4); // 先把arc标高设为0
AcDbArc *pArc = new AcDbArc;
pArc->setCenter(arc.GetCenterPt());
pArc->setRadius(arc.GetRadius());
pArc->setStartAngle(arc.GetStarAngle());
pArc->setEndAngle(arc.GetEndAngle());
XPoint pt1, pt2;
double dParam(0);
pArc->getParamAtPoint(ptLoc, dParam);
pArc->getPointAtParam(dParam+dWidth/arc.GetRadius(), pt1);
pArc->getPointAtParam(dParam-dWidth/arc.GetRadius(), pt2);
delete pArc;
cv.ProjectToMe(pt1, pt1);
cv.ProjectToMe(pt2, pt2);
pt1.z = 0;
pt2.z = 0;
arPoint.append((AcGePoint3d)pt1);
arPoint.append((AcGePoint3d)pt2);
}
else
{
XVector3D vtAdd = vtDir * dWidth;
XPoint ptStart = ptLoc - vtAdd,
ptEnd = ptLoc + vtAdd;
double dStart = cv.PathDistance(ptStart),
dEnd = cv.PathDistance(ptEnd);
if (fabs(StartPoint().z-EndPoint().z) < 0.01)
{
getClosestPointTo(ptStart, ptStart);
getClosestPointTo(ptEnd, ptEnd);
}
ptStart.z = 0;
ptEnd.z = 0;
if (dStart>1.0E-5 && dStart<dDistance-1.0E-5)
{
arPoint.append((AcGePoint3d)ptStart);
}
if (dEnd>1.0E-5 && dEnd<dDistance-1.0E-5)
{
arPoint.append((AcGePoint3d)ptEnd);
}
XLine line(ptStart, ptEnd, LS_FINITE);
XCurveSegment seg;
seg = line;
lstBreakCurve.Append(new XCurveSegment(seg));
}
}
//////////////////////////////////其他/////////////////////////////////////////
// 交换风管的起止点和连接的接点ID
void TDbDuct::SwitchVane()
{
TchPrivate::Exchange(StartPoint(), EndPoint());
TchPrivate::Exchange(m_nodeStart, m_nodeEnd);
}
double TDbDuct::CalVelocity() const // 计算风速
{
double dVelocity(0.0);
if (m_nSection == 0) // 矩形
{
if ((m_dWidth > 1.0E-6) && (m_dHeight > 1.0E-6))
{
dVelocity = m_dCalWeight/(3.6E-3 * m_dWidth * m_dHeight);
}
}
else if (m_nSection == 1) // 圆形
{
if (m_dWidth > 1.0E-6)
{
dVelocity = m_dCalWeight/(9.0E-4 * PI * pow(m_dWidth, 2));
}
}
CString csTmp;
csTmp.Format(_T("%.2f"), dVelocity);
dVelocity = _tstof(csTmp);
return dVelocity;
}
//////////////////////////////////////////////////////////////////////////
void InitDbDuct(BOOL bTrue)
{
if (bTrue)
{
TDbDuct::rxInit();
TDbDuct::InitMatchProtocol(TRUE);
}
else
{
TDbDuct::InitMatchProtocol(FALSE);
deleteAcRxClass(TDbDuct::desc());
}
}
/////////////////////////////////////////////////////////////////////////////////
// 所需要的全局函数
/////////////////////////////////////////////////////////////////////////////////
/*============================================================================*
* 函 数 名: GetSquare
* 功能描述: 获取矩形风管的截面
——>dAngle
pt4------dWide-----pt1 |
| | |
| | |
ptTmp2----ptCen----ptTmp1 dHigh
| | |
| | |
pt3----------------pt2 |
==============================================================================*/
void GetSquare(const XPoint &ptCen, const double &dAngle, const double &dWide,
const double &dHigh, XPoly2D* poly, XPoly2D* vDuctPoly)
{
XPoint ptTmp1, ptTmp2, pt1, pt2, pt3, pt4, pt5;
ads_polar(ptCen, dAngle, 0.5*dWide, ptTmp1);
ads_polar(ptCen, dAngle, -0.5*dWide, ptTmp2);
ads_polar(ptTmp1, dAngle+PI/2, 0.5*dHigh, pt1);
ads_polar(ptTmp1, dAngle-PI/2, 0.5*dHigh, pt2);
ads_polar(ptTmp2, dAngle-PI/2, 0.5*dHigh, pt3);
ads_polar(ptTmp2, dAngle+PI/2, 0.5*dHigh, pt4);
poly->Reset();
poly->SetFlag(1);
poly->AppendNode(pt1);
poly->AppendNode(pt2);
poly->AppendNode(pt3);
poly->AppendNode(pt4);
if (vDuctPoly != NULL) { // 注:立管用
double dAng = ads_angle(ptCen, pt4),
dDist = pt4.Distance(ptCen);
ads_polar(ptCen, dAng, 0.5*dDist, pt5);
vDuctPoly->Reset();
vDuctPoly->SetFlag(0);
vDuctPoly->AppendNode(pt1);
vDuctPoly->AppendNode(pt5);
vDuctPoly->AppendNode(pt3);
}
}
/*============================================================================*
* 函 数 名: GetWidths
* 功能描述: 获取一组风管的管径
==============================================================================*/
AcGeDoubleArray GetWidths(AcDbObjectId id, const DList<AcDbObjectId> &ids,
const AcDbIntArray &aryTypes)
{
AcGeDoubleArray widthArray;
int nLen = ids.Length();
for (int i=0; i<nLen; i++)
{
double dWidth(0);
int nType = aryTypes[i];
if ((nType == 1) || (nType == 2)) // 此时的id一定不为空
{
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode == NULL)
{
return widthArray;
}
int nIndex = pNode->FindIdInLink(ids[i]);
if (nIndex != -1) // 存在连接关系
{
dWidth = pNode->GetIWidth(nIndex);
}
OPENOBJ_END();
}
else
{
OPENOBJ_BEGIN(ids[i], AcDb::kForRead, TDbDuct, pDuct);
if (pDuct != NULL)
{
dWidth = pDuct->GetWidth();
}
OPENOBJ_END();
}
widthArray.append(dWidth);
}
return widthArray;
}
/*============================================================================*
* 函 数 名: GetHeights
* 功能描述: 获取一组风管的高度
==============================================================================*/
AcGeDoubleArray GetHeights(AcDbObjectId id, const DList<AcDbObjectId> &ids,
const AcDbIntArray &aryTypes)
{
AcGeDoubleArray heightArray;
int nLen = ids.Length();
for (int i=0; i<nLen; i++)
{
double dHeight(0);
int nType = aryTypes[i];
if ((nType == 1) || (nType == 2)) // 此时的id一定不为空
{
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode == NULL)
{
return heightArray;
}
int nIndex = pNode->FindIdInLink(ids[i]);
if (nIndex != -1) // 存在连接关系
{
dHeight = pNode->GetIHeight(nIndex);
}
OPENOBJ_END();
}
else
{
OPENOBJ_BEGIN(ids[i], AcDb::kForRead, TDbDuct, pDuct);
if (pDuct != NULL)
{
dHeight = pDuct->GetHeight();
}
OPENOBJ_END();
}
heightArray.append(dHeight);
}
return heightArray;
}
/*============================================================================*
* 函 数 名: GetSegs
* 功能描述: 获取一组风管的中心线
==============================================================================*/
void GetSegs(AcDbObjectId id, XPoint ptLoc, const DList<AcDbObjectId> &ids,
const AcDbIntArray &aryTypes, DList<XCurveSegment> &lstSeg)
{
int nLen = ids.Length();
for (int i=0; i<nLen; i++)
{
XPoint pt1;
XVector3D vt;
int nType = aryTypes[i];
if ((nType == 1) || (nType == 2)) // 此时的id一定不为空
{
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode == NULL)
{
return;
}
int nIndex = pNode->FindIdInLink(ids[i]);
if (nIndex != -1) // 存在连接关系
{
pt1 = pNode->GetILocation(nIndex);
vt = pNode->GetIDirection(nIndex);
}
OPENOBJ_END();
}
else
{
OPENOBJ_BEGIN(ids[i], AcDb::kForRead, TDbDuct, pDuct);
if (pDuct != NULL)
{
TPipeSys::PtLoction nSide = TPipeSys::kStartPt;
vt = pDuct->GetDirection(ptLoc, nSide);
pt1 = pDuct->GetVertexPt(nSide);
}
OPENOBJ_END();
}
vt.Normalize();
vt.Scale(100);
XPoint pt2 = pt1 + vt;
lstSeg.Append(new XCurveSegment(pt1, pt2, 0, LS_FINITE));
}
}
/*============================================================================*
* 函 数 名: GetVectors
* 功能描述: 获取一组风管的法向
* 备 注: 离指定点较近的端点——>较远的端点
==============================================================================*/
void GetVectors(AcDbObjectId id, XPoint ptLoc, const DList<AcDbObjectId> &ids,
const AcDbIntArray &aryTypes, DList<XVector3D> &lstVt)
{
int nLen = ids.Length();
for (int i=0; i<nLen; i++)
{
XVector3D vt;
int nType = aryTypes[i];
if ((nType == 1) || (nType == 2)) // 此时的id一定不为空
{
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode == NULL)
{
return;
}
int nIndex = pNode->FindIdInLink(ids[i]);
if (nIndex != -1) // 存在连接关系
{
vt = pNode->GetIDirection(nIndex);
}
OPENOBJ_END();
}
else
{
OPENOBJ_BEGIN(ids[i], AcDb::kForRead, TDbDuct, pDuct);
if (pDuct != NULL)
{
TPipeSys::PtLoction nSide = TPipeSys::kStartPt;
vt = pDuct->GetDirection(ptLoc, nSide);
}
OPENOBJ_END();
}
lstVt.Append(new XVector3D(vt));
}
}
/*============================================================================*
* 函 数 名: GetAngles
* 功能描述: 获取一组风管的法向
* 备 注: 与GetVectors一致
==============================================================================*/
AcGeDoubleArray GetAngles(AcDbObjectId id, XPoint ptLoc, const DList<AcDbObjectId> &ids,
const AcDbIntArray &aryTypes)
{
DList<XVector3D> lstVts;
::GetVectors(id, ptLoc, ids, aryTypes, lstVts);
AcGeDoubleArray angleArray;
int nLen = lstVts.Length();
for (int i=0; i<nLen; i++)
{
double dAng = ads_angle(XPoint(), *lstVts[i]);
angleArray.append(dAng);
}
return angleArray;
}
/*============================================================================*
* 函 数 名: GetPtLocations
* 功能描述: 获取一组风管中,离指定点较近的端点的位置(是起点,还是终点)
==============================================================================*/
void GetPtLocations(AcDbObjectId id, XPoint ptLoc, const DList<AcDbObjectId> &ids,
const AcDbIntArray &aryTypes, DList<TPipeSys::PtLoction> &lstLoc)
{
int nLen = ids.Length();
for (int i=0; i<nLen; i++)
{
int nType = aryTypes[i];
TPipeSys::PtLoction nSide = TPipeSys::kStartPt;
if ((nType == 1) || (nType == 2))
{
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode == NULL)
{
return;
}
int nIndex = pNode->FindIdInLink(ids[i]);
if (nIndex != -1) // 存在连接关系
{
TPipeSys::FlowLet nLet = pNode->GetIFlowDir(nIndex);
if (nLet == TPipeSys::kInlet)
{
nSide = TPipeSys::kEndPt;
}
}
OPENOBJ_END();
}
else
{
OPENOBJ_BEGIN(ids[i], AcDb::kForRead, TDbDuct, pDuct);
if (pDuct != NULL)
{
pDuct->GetDirection(ptLoc, nSide);
}
OPENOBJ_END();
}
lstLoc.Append(new TPipeSys::PtLoction(nSide));
}
}
/*============================================================================*
* 函 数 名: IsCircleDuct
* 功能描述: 获取某风管是否是圆风管
==============================================================================*/
BOOL IsCircleDuct(AcDbObjectId idNode, AcDbObjectId id, int nType)
{
int nSection(0);
if ((nType == 1) || (nType == 2))
{
OPENOBJ_BEGIN(idNode, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode != NULL)
{
int nIndex = pNode->FindIdInLink(id);
if (nIndex != -1) // 存在连接关系
{
nSection = pNode->GetISection(nIndex);
}
}
OPENOBJ_END();
return (nSection==1);
}
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuct, pDuct);
if (pDuct != NULL)
{
nSection = pDuct->GetSectionType();
}
OPENOBJ_END();
return (nSection == 1);
}
/*============================================================================*
* 函 数 名: IsVerDuct
* 功能描述: 获取某风管是否是立管
==============================================================================*/
BOOL IsVerDuct(AcDbObjectId idNode, AcDbObjectId id, int nType)
{
BOOL bIsVDuct(FALSE);
if ((nType == 1) || (nType == 2))
{
OPENOBJ_BEGIN(idNode, AcDb::kForRead, TDbDuctNode, pNode);
if (pNode != NULL)
{
int nIndex = pNode->FindIdInLink(id);
if (nIndex != -1) // 存在连接关系
{
XVector3D vt = pNode->GetIDirection(nIndex);
vt.Normalize();
bIsVDuct = fabs(vt.x)<1.0E-6 && fabs(vt.y)<1.0E-6;
}
}
OPENOBJ_END();
return bIsVDuct;
}
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDuct, pDuct);
if (pDuct != NULL)
{
TPipeSys::ModelType nMode = pDuct->GetModelType();
if (nMode == TPipeSys::kModel) // 模型图
{
bIsVDuct = pDuct->IsVertical();
}
else if (nMode == TPipeSys::kSystem) // 系统图
{
XVector3D vt = pDuct->EndPoint() - pDuct->StartPoint();
vt.Normalize();
bIsVDuct = fabs(vt.z)>0.001;
}
}
OPENOBJ_END();
return bIsVDuct;
}