// 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 &lstEquipment) const { int nCount = m_lstEquipment.Length(); for (int i=0; iGetLocation(); 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 lstEquipment; for (i=0; iisKindOf(TDbDuctNode::desc())) // 掏洞节点 { continue; } if (pNode->isKindOf(THDbEquipment::desc())) // 设备 { THDbEquipment *pEquipment = THDbEquipment::cast(pNode); int nLen = pEquipment->GetInterfaceNum(); for (int j=0; jGetIPipe(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 &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_nMaterialisKindOf(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; jGetIPipe(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; ireadItem(&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; iGetYScale(), 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; iisKindOf(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; jGetIPipe(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 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; ilinetypeObjectId(); 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 lstCurve1; if (g_bBreakPipe) // 2、绘制风管上线 { GetBrokenCurves(segUp, lstCurve1); } else { lstCurve1.Append(new XCurveSegment(segUp)); } nCount = lstCurve1.Length(); for (i=0; i lstCurve2; if (g_bBreakPipe) // 3、绘制风管下线 { GetBrokenCurves(segDown, lstCurve2); } else { lstCurve2.Append(new XCurveSegment(segDown)); } nCount = lstCurve2.Length(); for (i=0; i(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 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; iAsAcGePoint3d(), 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 &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 &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; iGetPipeType()!=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; iGetIPipe(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; iGetIDirection(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; iGetIDirection(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 &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; iGetIDirection(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 &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; i1.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 &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 lstLocation; // 交点或者附件所在点 DList lstBreakCurve; // 被剪裁的线段 double dDisThis = cv.GetLength(); // 管线长 int i(0); for (i=0; iIsCheckSysType() && 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; jDirection3d().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 lstDist; // 打断点在曲线段上的距离 for (i=0; i*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; kgetClosestPointTo(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; ktransformBy(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; kStartPoint(), ptCurveE = pSeg->EndPoint(); BOOL bStartInside = FALSE, bEndInside = FALSE; for (int m=0; mStartPoint(), ptE = pSeg->EndPoint(); BOOL bAppend = TRUE; for (int j=0; j &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 && dStart1.0E-5 && dEnd 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 &ids, const AcDbIntArray &aryTypes) { AcGeDoubleArray widthArray; int nLen = ids.Length(); for (int i=0; iFindIdInLink(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 &ids, const AcDbIntArray &aryTypes) { AcGeDoubleArray heightArray; int nLen = ids.Length(); for (int i=0; iFindIdInLink(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 &ids, const AcDbIntArray &aryTypes, DList &lstSeg) { int nLen = ids.Length(); for (int i=0; iFindIdInLink(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 &ids, const AcDbIntArray &aryTypes, DList &lstVt) { int nLen = ids.Length(); for (int i=0; iFindIdInLink(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 &ids, const AcDbIntArray &aryTypes) { DList lstVts; ::GetVectors(id, ptLoc, ids, aryTypes, lstVts); AcGeDoubleArray angleArray; int nLen = lstVts.Length(); for (int i=0; i &ids, const AcDbIntArray &aryTypes, DList &lstLoc) { int nLen = ids.Length(); for (int i=0; iFindIdInLink(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; }