#include "stdafx.h" #include "DbGouge.h" #include "PipeTools.h" #include "DbTrenchFitting.h" extern void DrawWeight(XExplodeDraw &dc,double dWeight,XCurveSegment &seg,int nColorIndex, double nScale); ACRX_DXF_DEFINE_MEMBERS(ATSCableTrench, ATSPipeCanal, AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, 1, ATS_TRENCH, "ATS_TRENCH图形无法解析, 请下载上华软件|网址: www.shanghuasoft.com"); IMPLEMENT_TENTBASE(TDbCableTrench); static AcGePoint3d Mid(AcGePoint3d ptGe1, AcGePoint3d ptGe2) { return AcGePoint3d((ptGe1.x + ptGe2.x) / 2.0,(ptGe1.y + ptGe2.y) / 2.0,(ptGe1.z + ptGe2.z) / 2.0); } void InitTDbCableTrench(BOOL bTrue) { if(bTrue) { TDbCableTrench::rxInit(); TDbCableTrench::InitMatchProtocol(TRUE); } else { TDbCableTrench::InitMatchProtocol(FALSE); deleteAcRxClass(TDbCableTrench::desc()); } } const Adesk::UInt8 TDbCableTrench::g_nVersion = 1; TDbCableTrench::TDbCableTrench() { m_dGougeLineW = 0.0; m_nBracketMode = 0; m_dBracketLen = 250.0; m_dBracketDis = 1000.0; m_dBracketLineW = 0.0; m_nCornerType = 0; m_sSpare = _T(""); m_sTrenchNo = _T(""); m_dSpare = 0; m_nSpare = 0; } TDbCableTrench::~TDbCableTrench() { } Acad::ErrorStatus TDbCableTrench::subGetClassID(CLSID* pClsid) const { return Acad::eOk; } Acad::ErrorStatus TDbCableTrench::dwgInFields (AcDbDwgFiler* pFiler) { assertWriteEnabled(); Acad::ErrorStatus es = TDbPipeCanal::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_dGougeLineW); pFiler->readItem(&m_nBracketMode); pFiler->readItem(&m_dBracketLen); pFiler->readItem(&m_dBracketDis); pFiler->readItem(&m_dBracketLineW); //备用 pFiler->readItem(&m_nSpare); pFiler->readItem(&m_dSpare); ReadString(pFiler,m_sSpare); ReadString(pFiler,m_sTrenchNo); return Acad::eOk; } Acad::ErrorStatus TDbCableTrench::dwgOutFields(AcDbDwgFiler*pFiler) const { assertReadEnabled(); Acad::ErrorStatus es = TDbPipeCanal::dwgOutFields(pFiler); if(es != Acad::eOk) return es; pFiler->writeItem(g_nVersion); pFiler->writeItem(m_dGougeLineW); pFiler->writeItem(m_nBracketMode); pFiler->writeItem(m_dBracketLen); pFiler->writeItem(m_dBracketDis); pFiler->writeItem(m_dBracketLineW); pFiler->writeItem(m_nSpare); pFiler->writeItem(m_dSpare); pFiler->writeString(m_sSpare); pFiler->writeString(m_sTrenchNo); return Acad::eOk; } Acad::ErrorStatus TDbCableTrench::dxfInFields (AcDbDxfFiler* pFiler) { assertWriteEnabled(); Acad::ErrorStatus es=Acad::eOk; es=TDbPipeCanal::dxfInFields(pFiler); if(es!=Acad::eOk) return es; if (!pFiler->atSubclassData(_T("TDbCableTrench"))) { return Acad::eBadDxfSequence; } return Acad::eOk; } Acad::ErrorStatus TDbCableTrench::dxfOutFields(AcDbDxfFiler* pFiler) const { Acad::ErrorStatus es=Acad::eOk; es=TDbPipeCanal::dxfOutFields(pFiler); assert(es==Acad::eOk); es=pFiler->writeItem(AcDb::kDxfSubclass,_T("TDbCableTrench")); assert(es==Acad::eOk); return Acad::eOk; } void TDbCableTrench::CopyPropertiesFrom(AcDbEntity *pSrc,unsigned gMatchFlag) { assertWriteEnabled(); TDbPipeCanal::CopyPropertiesFrom(pSrc, gMatchFlag); TDbCableTrench *pGouge = TDbCableTrench::cast(pSrc); if(pGouge) { m_dGougeLineW = pGouge->m_dGougeLineW; m_nBracketMode = pGouge->m_nBracketMode; m_dBracketLen = pGouge->m_dBracketLen; m_dBracketDis = pGouge->m_dBracketDis; m_dBracketLineW = pGouge->m_dBracketLineW; m_nCornerType = pGouge->m_nCornerType; } } BOOL TDbCableTrench::CanMergeWith(const TDbPipePrototype &other, int *iPosThis, int *iPosOther) const { if (GetSysType() != other.GetSysType()) // 1、系统类型相同 { return FALSE; } // 是否等宽 // 是否向量平行 TDbCableTrench* pTrench = (TDbCableTrench*)&other; if (pTrench != NULL) { // 向量 AcGeVector3d vtHor = pTrench->EndPoint() - pTrench->StartPoint(); AcGeVector3d vtHor2 = EndPoint() - StartPoint(); if (!vtHor.isParallelTo(vtHor2)) { return FALSE; } // 宽 double dWidth = pTrench->m_nWidth; double dHeight = pTrench->GetGougeHeight(); if (fabs(dWidth-m_nWidth) < 1e-3 && fabs(m_nHeight-dHeight) < 1e-3) { return TDbPipePrototype::CanMergeWith(other,iPosThis,iPosOther); } } return FALSE; } // 自动增加节点到当前数据库,ids-该节点自动连接的管线 AcDbObjectId TDbCableTrench::AddAutoNodeToDb(const XPoint &ptAt, const DList &ids) const { //modify liaoy 2016-8-9 TDbTrenchFitting *pFitting=new TDbTrenchFitting; pFitting->SetVisible(FALSE); for(int i=0; iAddInterface(iFace); } pFitting->UpdateLinkage(ptAt, GetSysType(), ids); TCHAR *layer; layer = this->layer(); TCHAR szLayer[256]; _tcscpy(szLayer, layer); pFitting->setLayer(szLayer); return pFitting->AddToCSpace(Adesk::kTrue); /* AcDbObjectId id; if(ids.Length()) { TDbTrenchFitting *pFitting = new TDbTrenchFitting; pFitting->UpdateLinkage(ptAt, GetSysType(), ids); TCHAR *layer; layer = this->layer(); TCHAR szLayer[256]; _tcscpy(szLayer, layer); pFitting->setLayer(szLayer); id=AddToCurrentSpace(pFitting, Adesk::kTrue); delete [] layer; } return id; */ //modify end } Acad::ErrorStatus TDbCableTrench::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; } XAcGiViewDraw &viewDraw = (XAcGiViewDraw &)dc; //垂直管线 XVector3D vtLocation=EndPoint()-StartPoint(); if(fabs(vtLocation.x)<1.0E-6 && fabs(vtLocation.y)<1.0E-6) { //垂直管线 return Acad::eOk; } //绘制电缆沟上线和下线 ExplodeOrDrawPipeCanal(dc); return Acad::eOk; } //调整电缆沟位置 void TDbCableTrench::ExplodeOrDrawPipeCanal(XExplodeDraw &dc) const { switch(m_nCanalType) { case Canal_Corner1: ExplodeOrDrawCanalType1(dc); break; case Canal_Corner2: case Canal_Corner3: case Canal_Corner4: case Canal_Corner5: ExplodeOrDrawCanalType2(dc); break; default: break; } } void TDbCableTrench::ExplodeOrDrawCanalType1(XExplodeDraw &dc) const { //得到电缆沟两端节点 AcDbObjectId idNode1(NULL), idNode2(NULL); idNode1 = GetNode(0); idNode2 = GetNode(1); if (!idNode1.isValid() || !idNode2.isValid()) { return; } AcGePoint3d pt1,pt2,pt3,pt4; //分别得到电缆沟的一端上两点 AcArray map1,map2; GetCannalPts(idNode1,pt1,pt2,map1); GetCannalPts(idNode2,pt3,pt4,map2); XCurveSegment cenCurve = GetCurve(); XCurveSegment segUp,segDown; XDirectionCurve segDir(cenCurve.StartPoint(), cenCurve.EndPoint(), cenCurve.GetBulge()); segUp = segDir.Offset(m_nWidth/2, LS_FINITE); segDown = segDir.Offset(-m_nWidth/2, LS_FINITE); segUp.SetPoints(pt1,pt3); segDown.SetPoints(pt2,pt4); double dWeight = GetPScale()*m_dGougeLineW; if (dWeight > 1e-3) { DrawWeight(dc, dWeight, segUp, colorIndex(), linetypeScale()); //绘制电缆沟支架 DrawWeight(dc, dWeight, segDown, colorIndex(), linetypeScale()); } else { dc << segUp; dc << segDown; } for (int i = 0; i < map1.length(); ++i) { XCurveSegment segCorn(map1[i].pair.second,map1[i].pair.first,map1[i].dAng); if(dWeight > 1e-3) DrawWeight(dc, dWeight, segCorn, colorIndex(), linetypeScale()); else dc << segCorn; } for (int j = 0; j < map2.length(); ++j) { XCurveSegment segCorn(map2[j].pair.second,map2[j].pair.first,map2[j].dAng); if(dWeight > 1e-3) DrawWeight(dc, dWeight, segCorn, colorIndex(), linetypeScale()); else dc << segCorn; } // 是否需要绘制连接线 if (IsHasMorePipes(idNode1)) { XCurveSegment segCnt; segCnt.SetPoints(pt1,pt2); if (dWeight > 1e-3) DrawWeight(dc, dWeight, segCnt, colorIndex(), linetypeScale()); else dc << segCnt; } if (IsHasMorePipes(idNode2)) { XCurveSegment segCnt; segCnt.SetPoints(pt3,pt4); if(dWeight > 1e-3) DrawWeight(dc, dWeight, segCnt, colorIndex(), linetypeScale()); else dc << segCnt; } //绘制电缆沟支架 DrawBrackets(dc,cenCurve); } ////////////////////////////////////////////////////////////////////////// void CurveSegmentOffset(const XCurveSegment& seg,double dWidth,XCurveSegment& segUp, XCurveSegment& segDown) { XDirectionCurve segDir(seg.StartPoint(), seg.EndPoint(), seg.GetBulge()); segUp = segDir.Offset(dWidth/2, LS_FINITE); segDown = segDir.Offset(-dWidth/2, LS_FINITE); } void TDbCableTrench::SortPipeCanalTrench(const AcGePoint3d &ptOr,const AcDbObjectIdArray &arIds,AcArray>& arPairSeg) const { AcDbObjectId idSelf = GetSelfObjectId(); AcGeMatrix3d mat; ads_matrix matAds; GetOffsetMatrix(idSelf, mat); AcArray> arPairSegTmp; for (int i = 0; i < arIds.length(); ++i) { if (idSelf == arIds[i]) { XCurveSegment seg; seg = GetCurve(); XCurveSegment segUp, segDown; CurveSegmentOffset(seg,GetWidth(),segUp,segDown); arPairSegTmp.append(std::make_pair(arIds[i],segUp)); arPairSegTmp.append(std::make_pair(arIds[i],segDown)); } else { if (arIds[i].isValid()) { //防止在三维状态下在实体内部自己打开自己 OPENOBJ_BEGIN(arIds[i], AcDb::kForRead, TDbPipeCanal, pCanal); if (pCanal != NULL) { XCurveSegment seg; seg = pCanal->GetCurve(); memcpy(matAds, &mat, sizeof(AcGeMatrix3d)); seg.TransformBy(matAds); XCurveSegment segUp, segDown; CurveSegmentOffset(seg,GetWidth(),segUp,segDown); arPairSegTmp.append(std::make_pair(arIds[i],segUp)); arPairSegTmp.append(std::make_pair(arIds[i],segDown)); } OPENOBJ_END(); } } } XPoint pt = ptOr; std::map> map; double dPar = 0.0; std::vector vecT; AcDbCircle circle(ptOr,AcGeVector3d::kZAxis,m_nWidth/5); for (int j = 0; j < arPairSegTmp.length(); ++j) { AcGePoint3d ptNear; circle.getClosestPointTo(arPairSegTmp[j].second.MidPoint(),AcGeVector3d::kZAxis,ptNear); circle.getParamAtPoint(ptNear,dPar); map[dPar] = arPairSegTmp[j]; vecT.push_back(dPar); } std::sort(vecT.begin(),vecT.end()); for (UINT k = 0; k < vecT.size(); ++k) { double dT = vecT[k]; arPairSeg.append(map[dT]); } } void TDbCableTrench::GetCorner2InterPtsTrench(const std::pair &seg1,const const std::pair &seg2,const AcGePoint3d &pt,int nSegCount,AcGePoint3dArray &arPts,AcArray &map1) const { BOOL bEqulaWidth = FALSE; double dCornerR1(-1),dCornerR2(-1); OPENOBJ_BEGIN(seg1.first,AcDb::kForRead,TDbCableTrench,pTrench); if (pTrench) { dCornerR1 = pTrench->GetCornerRadius(); } OPENOBJ_END(); OPENOBJ_BEGIN(seg2.first,AcDb::kForRead,TDbCableTrench,pTrench); if (pTrench) { dCornerR2 = pTrench->GetCornerRadius(); } OPENOBJ_END(); if (dCornerR1 > 0 && dCornerR2 > 0 && fabs(dCornerR1 - dCornerR2) > TOL)//不等拐角半径 { //以拐角半径大的为准 GetCorner2InterPtsTrench(seg1.second,seg2.second,pt,nSegCount,max(dCornerR1,dCornerR2),arPts,map1); } else { GetCorner2InterPtsTrench(seg1.second,seg2.second,pt,nSegCount,GetCornerRadius(),arPts,map1); } } void TDbCableTrench::GetCorner2InterPtsTrench(const XCurveSegment &seg1,const XCurveSegment &seg2,const AcGePoint3d &pt,int nSegCount,double dSpare,AcGePoint3dArray &arPts,AcArray &map1) const { XPoint ptInter = pt; AcGeVector3d vtDir1,vtDir2; AcGePoint3d ptIns1,ptIns2; BOOL bMoreLen = FALSE; //用来判断弯头的弧线是朝内还是朝外 AcGeVector3d vtT; XCurveSegment seg1T,seg2T; AcGePoint3d ptSegS1,ptSegE1,ptSegS2,ptSegE2; //将曲线Z坐标置0 ptSegS1 = seg1.StartPoint(); ptSegS2 = seg2.StartPoint(); ptSegE1 = seg1.EndPoint(); ptSegE2 = seg2.EndPoint(); ptSegS1.z = 0; ptSegS2.z = 0; ptSegE1.z = 0; ptSegE2.z = 0; seg1T.SetPoints(ptSegS1,ptSegE1); seg2T.SetPoints(ptSegS2,ptSegE2); if (seg1T.StartPoint().Distance(ptInter) > seg1T.EndPoint().Distance(ptInter)) { vtDir1 = seg1T.EndPoint() - seg1T.StartPoint(); vtT = seg1T.StartPoint() - pt; } else { vtDir1 = seg1T.StartPoint() - seg1T.EndPoint(); vtT = seg1T.EndPoint() - pt; } if (vtT.length() > seg1T.GetLength()) bMoreLen = TRUE; XPoint ptT1,ptT2; vtDir1.normalize(); //判断是否是无交点的拐角 if (seg1T.Intersection(seg2T,ptT1,ptT2) == 0) // ptIns1 = pt - vtDir1*m_nWidth*tan(PI/8); ptIns1 = pt - vtDir1*(m_nWidth+dSpare-m_nWidth*tan(PI/8)); else ptIns1 = pt - vtDir1*dSpare; arPts.append(ptIns1); if (seg2T.StartPoint().Distance(ptInter) > seg2T.EndPoint().Distance(ptInter)) vtDir2 = seg2T.EndPoint() - seg2T.StartPoint(); else vtDir2 = seg2T.StartPoint() - seg2T.EndPoint(); vtDir2.normalize(); //判断是否是无交点的拐角 if (seg1T.Intersection(seg2T,ptT1,ptT2) == 0) // ptIns2 = pt - vtDir2*m_nWidth*tan(PI/8); ptIns2 = pt - vtDir2*(m_nWidth+dSpare-m_nWidth*tan(PI/8)); else ptIns2 = pt - vtDir2*dSpare; arPts.append(ptIns2); std::pair pair; pair.first = ptIns1; pair.second = ptIns2; CornerLine corner; corner.pair = pair; if (m_nCanalType == Canal_Corner2 || m_nCanalType == Canal_Corner3) { corner.dAng = 0.0; } else { if (nSegCount > 4) { corner.dAng = vtDir1.angleTo(vtDir2) - PI; } else { if (bMoreLen) corner.dAng = PI - vtDir1.angleTo(vtDir2); else corner.dAng = vtDir1.angleTo(vtDir2) - PI; } } map1.append(corner); } void TDbCableTrench::GetInterPtsTrench(const AcArray> &arSeg,AcArray &arPts,AcArray &map1) const { BOOL bIsInter = FALSE; XPoint ptInter1,ptInter2; if (arSeg.length() > 1) { int nNext = 0; for (int i = 0; i < arSeg.length(); i++) { if (i != arSeg.length() - 1) nNext = i + 1; else nNext = 0; AcGeVector3d vt1 = arSeg[i].second.StartPoint() - arSeg[i].second.EndPoint(); AcGeVector3d vt2 = arSeg[nNext].second.StartPoint() - arSeg[nNext].second.EndPoint(); if (vt1.isParallelTo(vt2)) continue; AcGePoint3dArray arPtsT; AcGePoint3d ptS = arSeg[i].second.StartPoint(); AcGePoint3d ptST = arSeg[nNext].second.StartPoint(); AcGePoint3d ptE = arSeg[i].second.EndPoint(); AcGePoint3d ptET = arSeg[nNext].second.EndPoint(); ptS.z = 0.0; ptE.z = 0.0; ptST.z = 0.0; ptET.z = 0.0; AcDbLine line1(ptS,ptE); AcDbLine line2(ptST,ptET); line1.intersectWith(&line2,AcDb::kOnBothOperands,arPtsT); if (arPtsT.length() > 0) { if(m_nCanalType == Canal_Corner1) arPts.append(arPtsT[0]); else if (m_nCanalType == Canal_Corner2 || m_nCanalType == Canal_Corner3 || m_nCanalType == Canal_Corner4 || m_nCanalType == Canal_Corner5) { //得到类型2的交点 GetCorner2InterPtsTrench(arSeg[i],arSeg[nNext],arPtsT[0],arSeg.length(),arPts,map1); } } else { if (arSeg.length() == 4) { arPtsT.removeAll(); if (line1.intersectWith(&line2,AcDb::kExtendBoth,arPtsT) == Acad::eOk) { if(m_nCanalType == Canal_Corner1 || m_nCanalType == Canal_Corner3 || m_nCanalType == Canal_Corner4) arPts.append(arPtsT[0]); else if (m_nCanalType == Canal_Corner2 || m_nCanalType == Canal_Corner5) { //得到类型2的交点 GetCorner2InterPtsTrench(arSeg[i],arSeg[nNext],arPtsT[0],arSeg.length(),arPts,map1); } } } } } } } void TDbCableTrench::GetCannalPtsTrench(const AcDbObjectId &id,AcGePoint3d &pt1,AcGePoint3d &pt2,AcArray &map1) const { if (id.isValid()) { //通过节点得到几段线 AcDbObjectIdArray arCanal; OPENOBJ_BEGIN(id, AcDb::kForRead, TDbPipeNode, pNode); if(pNode) { int num = pNode->GetInterfaceNum(); if (num > 0) { for (int i = 0; i < num; ++i) { TPipeInterface inter; // pNode->GetInterface(i,inter); AcDbObjectId id = pNode->GetIPipe(i); arCanal.append(id); } if (num > 3) { FilterCannal(arCanal); } //将线按逆时针排序 AcArray> arPairSeg; SortPipeCanalTrench(pNode->GetLocation(),arCanal,arPairSeg); AcArray > arSeg; for (int i = 0;i < arPairSeg.length();i++) arSeg.append(arPairSeg[i].second); //求出排序后线的交点 AcArray arPts; GetInterPtsTrench(arPairSeg,arPts,map1); //调整方沟位置 ChangePipeCanalPosition(arPts,pNode->GetLocation(),arSeg.length(),pt1,pt2); // 如果连接点为2则判断是否要添加变径条件:1,vt 2,width if (num == 2 && arPts.length() == 0) { double dLen = 0.0;//变径长度 = b1+b2 if (MakesureCreateReducer(arCanal,dLen)) ChangePipeCanalPosition(arCanal,id,pNode->GetLocation(),dLen,pt1,pt2,map1); } } } OPENOBJ_END(); } } ////////////////////////////////////////////////////////////////////////// void TDbCableTrench::ExplodeOrDrawCanalType2(XExplodeDraw &dc) const { //得到电缆沟两端节点 AcDbObjectId idNode1(NULL), idNode2(NULL); idNode1 = GetNode(0); idNode2 = GetNode(1); if (!idNode1.isValid() || !idNode2.isValid()) { return; } AcGePoint3d pt1,pt2,pt3,pt4; //分别得到电缆沟的一端上两点 AcArray map1,map2; //GetCannalPts(idNode1,pt1,pt2,map1); //GetCannalPts(idNode2,pt3,pt4,map2); GetCannalPtsTrench(idNode1,pt1,pt2,map1); GetCannalPtsTrench(idNode2,pt3,pt4,map2); double dWeight = GetPScale()*m_dGougeLineW; XCurveSegment cenCurve = GetCurve(); XCurveSegment segUp,segDown; XDirectionCurve segDir(cenCurve.StartPoint(), cenCurve.EndPoint(), cenCurve.GetBulge()); segUp = segDir.Offset(m_nWidth/2, LS_FINITE); segDown = segDir.Offset(-m_nWidth/2, LS_FINITE); segUp.SetPoints(pt1,pt3); segDown.SetPoints(pt2,pt4); double dAng = 0.0; if (dWeight > 1e-3) { DrawWeight(dc, dWeight, segUp, colorIndex(), linetypeScale()); DrawWeight(dc, dWeight, segDown, colorIndex(), linetypeScale()); } else { dc << segUp; dc << segDown; } DrawBrackets(dc,cenCurve); for (int i = 0; i < map1.length(); ++i) { XCurveSegment segCorn(map1[i].pair.second,map1[i].pair.first,map1[i].dAng); if (dWeight > 1e-3) DrawWeight(dc, dWeight, segCorn, colorIndex(), linetypeScale()); else dc << segCorn; } for (int j = 0; j < map2.length(); ++j) { XCurveSegment segCorn(map2[j].pair.second,map2[j].pair.first,map2[j].dAng); if(dWeight > 1e-3) DrawWeight(dc, dWeight, segCorn, colorIndex(), linetypeScale()); else dc << segCorn; } // 是否需要绘制连接线 if (IsHasMorePipes(idNode1)) { XCurveSegment segCnt; segCnt.SetPoints(pt1,pt2); if(dWeight > 1e-3) DrawWeight(dc, dWeight, segCnt, colorIndex(), linetypeScale()); else dc << segCnt; } if (IsHasMorePipes(idNode2)) { XCurveSegment segCnt; segCnt.SetPoints(pt3,pt4); if(dWeight > 1e-3) DrawWeight(dc, dWeight, segCnt, colorIndex(), linetypeScale()); else dc << segCnt; } } // 根据连接点点过滤相连接的电缆沟 BOOL TDbCableTrench::IsHasMorePipes(const AcDbObjectId& idNode) const { int num = GetNodeCntPipeNumber(idNode); if (num > 1)// 有连接 { return FALSE; } return TRUE; } // 节点连接的管子个数 int TDbCableTrench::GetNodeCntPipeNumber(const AcDbObjectId& idNode) const { int nNum = 0; if (idNode.isValid()) { OPENOBJ_BEGIN(idNode, AcDb::kForRead, TDbPipeNode, pNode); if(pNode) { nNum = pNode->GetInterfaceNum(); } OPENOBJ_END(); } return nNum; } // 绘制电缆沟支架 Acad::ErrorStatus TDbCableTrench::DrawBrackets(XExplodeDraw &dc,XCurveSegment& cenSeg) const { AcArray > arBracket; switch(m_nBracketMode) { case eGNull: { break; } case eGCover: // 支架长度等于沟宽 case eGLSide: case eGRSide: { MakeCurvesOfCableGougeSide(arBracket,cenSeg); break; } case eGOrder: { MakeCurvesOfCableGougeOrder(arBracket,cenSeg); break; } case eGInter: { MakeCurvesOfCableGougeInter(arBracket,cenSeg); break; } default: break; } // 绘制 if (arBracket.length() > 0) { double dWeight = GetPScale() * m_dBracketLineW; for (int i = 0;i < arBracket.length();i++) { if (dWeight > 1e-3) DrawWeight(dc, dWeight , arBracket[i], colorIndex(), linetypeScale()); else dc << arBracket[i]; } } return Acad::eOk; } // 单边 BOOL TDbCableTrench::MakeCurvesOfCableGougeSide(AcArray >& arBracket,XCurveSegment& cenSeg) const { arBracket.setLogicalLength(0); //得到电缆沟两端节点 AcDbObjectId idNode1(NULL), idNode2(NULL); idNode1 = GetNode(0); idNode2 = GetNode(1); if (!idNode1.isValid() || !idNode2.isValid()) { return FALSE; } AcGeVector3d vtHor = cenSeg.EndPoint() - cenSeg.StartPoint(); AcGeVector3d vtVer = vtHor; vtVer.rotateBy(PI / 2,AcGeVector3d::kZAxis); vtHor.normalize(); vtVer.normalize(); // 预览还是创建 if (idNode1 != AcDbObjectId::kNull && idNode2 != AcDbObjectId::kNull) // 创建 { AcGePoint3d pt1,pt2,pt3,pt4; //分别得到电缆沟的一端上两点 AcArray map1,map2; GetCannalPts(idNode1,pt1,pt2,map1); GetCannalPts(idNode2,pt3,pt4,map2); AcGePoint3d ptS,ptE; if (m_nBracketMode == eGLSide || m_nBracketMode == eGCover) { ptS = pt2; ptE = pt4; int nNum = GetNodeCntPipeNumber(idNode2); if (map2.length() > 0 && (nNum > 0 && nNum < 3)) DrawBracketOfCorner(ptE,map2,arBracket,idNode2); } else if (m_nBracketMode == eGRSide) { ptS = pt1; ptE = pt3; int nNum = GetNodeCntPipeNumber(idNode2); if (map2.length() > 0 && (nNum > 0 && nNum < 3)) DrawBracketOfCorner(ptE,map2,arBracket,idNode2); } else { return FALSE; } // 修复开始和结束点 if (!IsHasMorePipes(idNode1)) // 存在连接 ReConstructBracketLine(ptS,ptE,idNode1); if (!IsHasMorePipes(idNode2)) ReConstructBracketLine(ptS,ptE,idNode2); if (m_nBracketMode == eGRSide) vtVer *= -1; DrawBracketsFun(vtHor,-vtVer,ptS,ptE,arBracket); } else// 预览 { AcGePoint3d ptS = cenSeg.StartPoint(); AcGePoint3d ptE = cenSeg.EndPoint(); if (m_nBracketMode == eGLSide || m_nBracketMode == eGCover) { ptS += vtVer * m_nWidth / 2; ptE += vtVer * m_nWidth / 2; DrawBracketsFun(vtHor,-vtVer,ptS,ptE,arBracket); } else if (m_nBracketMode == eGRSide) { ptS -= vtVer * m_nWidth / 2; ptE -= vtVer * m_nWidth / 2; DrawBracketsFun(vtHor,vtVer,ptS,ptE,arBracket); } } return TRUE; } // 对立 BOOL TDbCableTrench::MakeCurvesOfCableGougeOrder(AcArray >& arBracket,XCurveSegment& cenSeg) const { arBracket.setLogicalLength(0); //得到电缆沟两端节点 AcDbObjectId idNode1(NULL), idNode2(NULL); idNode1 = GetNode(0); idNode2 = GetNode(1); if (!idNode1.isValid() || !idNode2.isValid()) { return FALSE; } AcGeVector3d vtHor = cenSeg.EndPoint() - cenSeg.StartPoint(); AcGeVector3d vtVer = vtHor; vtVer.rotateBy(PI / 2,AcGeVector3d::kZAxis); vtHor.normalize(); vtVer.normalize(); // 预览还是创建 if (idNode1 != AcDbObjectId::kNull && idNode2 != AcDbObjectId::kNull) // 创建 { AcGePoint3d pt1,pt2,pt3,pt4; //分别得到电缆沟的一端上两点 AcArray map1,map2; GetCannalPts(idNode1,pt1,pt2,map1); GetCannalPts(idNode2,pt3,pt4,map2); AcGePoint3d ptS = pt1; AcGePoint3d ptE = pt3; int nNum = GetNodeCntPipeNumber(idNode2); if (map2.length() > 0 && (nNum > 0 && nNum < 3)) DrawBracketOfCorner(ptE,map2,arBracket,idNode2); // 修复开始和结束点 if (!IsHasMorePipes(idNode1)) // 存在连接 ReConstructBracketLine(ptS,ptE,idNode1); if (!IsHasMorePipes(idNode2)) ReConstructBracketLine(ptS,ptE,idNode2); DrawBracketsFun(vtHor,vtVer,ptS,ptE,arBracket); AcDbLine l1(ptS,ptE); ptS = pt2; ptE = pt4; nNum = GetNodeCntPipeNumber(idNode2); if (map2.length() > 0 && (nNum > 0 && nNum < 3)) DrawBracketOfCorner(ptE,map2,arBracket,idNode2); // 修复开始和结束点 if (!IsHasMorePipes(idNode1)) // 存在连接 ReConstructBracketLine(ptS,ptE,idNode1); if (!IsHasMorePipes(idNode2)) ReConstructBracketLine(ptS,ptE,idNode2); AcGePoint3d ptS1,ptTemp; l1.getStartPoint(ptS1); l1.getClosestPointTo(ptS,ptTemp,Adesk::kTrue); int dDist = ptS1.distanceTo(ptTemp); if (dDist != 0) { AcGeVector3d vtTemp = ptE - ptS; AcGeVector3d vtTemp1 = ptS1 - ptS; int dDist1 = 0; if (vtTemp1.angleTo(vtTemp) <= PI/2) { dDist1 = dDist%(int)m_dBracketDis; } else dDist1 = m_dBracketDis - dDist%(int)m_dBracketDis; vtTemp.normalize(); ptS += dDist1*vtTemp; } DrawBracketsFun(vtHor,-vtVer,ptS,ptE,arBracket); } else//预览 { AcGePoint3d ptS,ptE; ptS = cenSeg.StartPoint() + vtVer * m_nWidth / 2; ptE = cenSeg.EndPoint() + vtVer * m_nWidth / 2; DrawBracketsFun(vtHor,-vtVer,ptS,ptE,arBracket); ptS = cenSeg.StartPoint() - vtVer * m_nWidth / 2; ptE = cenSeg.EndPoint() - vtVer * m_nWidth / 2; DrawBracketsFun(vtHor,vtVer,ptS,ptE,arBracket); } return TRUE; } // 交错 BOOL TDbCableTrench::MakeCurvesOfCableGougeInter(AcArray >& arBracket,XCurveSegment& cenSeg) const { arBracket.setLogicalLength(0); //得到电缆沟两端节点 AcDbObjectId idNode1(NULL), idNode2(NULL); idNode1 = GetNode(0); idNode2 = GetNode(1); if (!idNode1.isValid() || !idNode2.isValid()) { return FALSE; } AcGeVector3d vtHor = cenSeg.EndPoint() - cenSeg.StartPoint(); AcGeVector3d vtVer = vtHor; vtVer.rotateBy(PI / 2,AcGeVector3d::kZAxis); vtHor.normalize(); vtVer.normalize(); // 预览还是创建 if (idNode1 != AcDbObjectId::kNull && idNode2 != AcDbObjectId::kNull) // 创建 { AcGePoint3d pt1,pt2,pt3,pt4; //分别得到电缆沟的一端上两点 AcArray map1,map2; GetCannalPts(idNode1,pt1,pt2,map1); GetCannalPts(idNode2,pt3,pt4,map2); AcGePoint3d ptS = pt2; AcGePoint3d ptE = pt4; int nNum = GetNodeCntPipeNumber(idNode2); if (map2.length() > 0 && (nNum > 0 && nNum < 3)) DrawBracketOfCorner(ptE,map2,arBracket,idNode2); // 修复开始和结束点 if (!IsHasMorePipes(idNode1)) // 存在连接 ReConstructBracketLine(ptS,ptE,idNode1); if (!IsHasMorePipes(idNode2)) ReConstructBracketLine(ptS,ptE,idNode2); DrawBracketsFun(vtHor,-vtVer,ptS,ptE,arBracket); // 下边 AcGePoint3d ptST = ptS;// 用于校正另一边便宜间距的一半 ptS = pt1; ptE = pt3; nNum = GetNodeCntPipeNumber(idNode2); if (map2.length() > 0 && (nNum > 0 && nNum < 3)) DrawBracketOfCorner(ptE,map2,arBracket,idNode2); // 修复开始和结束点 if (!IsHasMorePipes(idNode1)) // 存在连接 ReConstructBracketLine(ptS,ptE,idNode1); if (!IsHasMorePipes(idNode2)) ReConstructBracketLine(ptS,ptE,idNode2); // 偏移 AcGePoint3d ptS2T = ptS + vtVer * m_nWidth; double dDist = ptS2T.distanceTo(ptST); double dOff = 0.0; if (dDist < 1e-2) { dOff = m_dBracketDis / 2; } else { // 剩余 int nSpareNum = 0; if (m_dBracketDis != 0) nSpareNum = int(dDist / m_dBracketDis); double dSpare = m_dBracketDis * nSpareNum; dSpare = dDist - dSpare; if (dSpare < (m_dBracketDis / 2)) { dOff = m_dBracketDis / 2 - dSpare; } else { dOff = m_dBracketDis * 3 / 2 - dSpare; } } ptS += vtHor * dOff; DrawBracketsFun(vtHor,vtVer,ptS,ptE,arBracket); } else//预览 { AcGePoint3d ptS,ptE; ptS = cenSeg.StartPoint() + vtVer * m_nWidth / 2; ptE = cenSeg.EndPoint() + vtVer * m_nWidth / 2; DrawBracketsFun(vtHor,-vtVer,ptS,ptE,arBracket); ptS = cenSeg.StartPoint() - vtVer * m_nWidth / 2; ptE = cenSeg.EndPoint() - vtVer * m_nWidth / 2; ptS += vtHor * m_dBracketDis / 2; DrawBracketsFun(vtHor,vtVer,ptS,ptE,arBracket); } return TRUE; } // 得到相连的另一条沟的宽度和倒角半径 void TDbCableTrench::GetAnotherTrenchParam(const AcGeVector3d& vtHor,const AcDbObjectId& idNode,double& dWidth,double& dRadius) const { if (!idNode.isValid()) { return; } dWidth = 0.0; dRadius = 0.0; AcDbObjectId id; AcDbObjectIdArray arId; OPENOBJ_BEGIN(idNode, AcDb::kForRead, TDbPipeNode, pNode); if(pNode) { int nNum = pNode->GetInterfaceNum(); if (nNum == 2) { for (int i = 0;i < nNum;i++) { id = pNode->GetIPipe(i); arId.append(id); } } } OPENOBJ_END(); if (arId.length() != 2) return; // 读取另一条沟的数据 AcGeVector3d vt; for (int i = 0;i < arId.length();i++) { if (arId[i].isValid()) { OPENOBJ_BEGIN(arId[i], AcDb::kForRead, TDbCableTrench, pTrench); if(pTrench) { vt = pTrench->StartPoint() - pTrench->EndPoint(); if (!vt.isParallelTo(vtHor)) { dWidth = pTrench->m_nWidth; dRadius = pTrench->m_dSpare; break; } } OPENOBJ_END(); } } } // 重新构建绘制支架的线 BOOL TDbCableTrench::ReConstructBracketLine(AcGePoint3d& ptS,AcGePoint3d& ptE,const AcDbObjectId& idNode) const { if (!idNode.isValid()) { return FALSE; } AcGePoint3d ptNode; OPENOBJ_BEGIN(idNode, AcDb::kForRead, TDbPipeNode, pNode); if(pNode) { ptNode = pNode->GetLocation(); } OPENOBJ_END(); // 挑出距离节点较近的点 double dLn1 = ptS.distanceTo(ptNode); double dLn2 = ptE.distanceTo(ptNode); if (dLn1 > dLn2)//ptE { AcGeVector3d vtHor = ptE - ptS; vtHor.normalize(); AcGePointOnCurve3d ptT; AcGeLine3d line(ptNode,vtHor); line.getClosestPointTo(ptE,ptT); AcGeVector3d vtT = ptT.point3d() - ptNode; vtT.normalize(); if (vtT.isCodirectionalTo(vtHor))//同向:一端较长的边 { ptE -= vtHor * MINDIST; } else// 短线 { switch(m_nCanalType) { case Canal_Corner1://直角 { double dWidth = 0.0,dRadius = 0.0; GetAnotherTrenchParam(vtHor,idNode,dWidth,dRadius); if (dWidth < 500) ptE -= vtHor * (MINDIST - dWidth); break; } case Canal_Corner2://双倒角 case Canal_Corner3://单倒角 { double dWidth = 0.0,dRadius = 0.0; GetAnotherTrenchParam(vtHor,idNode,dWidth,dRadius); dWidth += dRadius; if (dWidth < 500) ptE -= vtHor * (MINDIST - dWidth); break; } default: break; } } } else//ptS { AcGeVector3d vtHor = ptS - ptE; vtHor.normalize(); AcGePointOnCurve3d ptT; AcGeLine3d line(ptNode,vtHor); line.getClosestPointTo(ptS,ptT); AcGePoint3d pp = ptT.point3d(); AcGeVector3d vtT = ptT.point3d() - ptNode; vtT.normalize(); if (vtT.isCodirectionalTo(vtHor))//同向:一端较长的边 { ptS -= vtHor * MINDIST; } else// 短线 { switch(m_nCanalType) { case Canal_Corner1://直角 { double dWidth = 0.0,dRadius = 0.0; GetAnotherTrenchParam(vtHor,idNode,dWidth,dRadius); if (dWidth < 500) ptS -= vtHor * (MINDIST - dWidth); break; } case Canal_Corner2://双倒角 case Canal_Corner3://单倒角 { double dWidth = 0.0,dRadius = 0.0; GetAnotherTrenchParam(vtHor,idNode,dWidth,dRadius); dWidth += dRadius; if (dWidth < 500) ptS -= vtHor * (MINDIST - dWidth); break; } default: break; } } } return TRUE; } // 绘制拐角处支架 void TDbCableTrench::DrawBracketOfCorner(const AcGePoint3d& ptRef,AcArray& mapPt,AcArray >& arBracket,const AcDbObjectId& idNode) const { // if (mapPt.length() < 1) // return; // // CornerLine cnrLine; // if (!GetCornerPtMap(ptRef,mapPt,cnrLine)) // return; // // AcGePoint3d ptS = cnrLine.pair.first; // AcGePoint3d ptE = cnrLine.pair.second; // // AcGePoint3d ptLoc; // OPENOBJ_BEGIN(idNode, AcDb::kForRead, TDbPipeNode, pNode); // if(pNode) // { // ptLoc = pNode->GetLocation(); // } // OPENOBJ_END(); // // AcDbLine line(ptS,ptE); // AcGePoint3d ptT; // line.getClosestPointTo(ptLoc,ptT,Adesk::kTrue); // // AcGeVector3d vtHor = ptE - ptS; // AcGeVector3d vtVer = ptLoc - ptT; // vtVer.normalize(); // vtHor.normalize(); // // ptS += vtHor * MINDIST; // ptE -= vtHor * MINDIST; // // // DrawBracketsFun(vtHor,vtVer,ptS,ptE,arBracket); } // 得到指定连接点的拐角点组 BOOL TDbCableTrench::GetCornerPtMap(const AcGePoint3d& ptRef,AcArray& mapPt,CornerLine& temOut) const { if (mapPt.length() < 1) return FALSE; AcGePoint3d ptT; for (int i = 0;i < mapPt.length();i++) { temOut = mapPt[i]; ptT = temOut.pair.first; if (ptT.distanceTo(ptRef) < 1e-3) { return TRUE; } ptT = temOut.pair.second; if (ptT.distanceTo(ptRef) < 1e-3) { return TRUE; } } return FALSE; } // 绘制支架 void TDbCableTrench::DrawBracketsFun(const AcGeVector3d& vtHor,const AcGeVector3d& vtVer,const AcGePoint3d& ptStart,const AcGePoint3d& ptEnd,AcArray >& arBracket) const { double dLen = ptStart.distanceTo(ptEnd); DrawBracketsFun(vtHor,vtVer,ptStart,dLen,arBracket); } void TDbCableTrench::DrawBracketsFun(const AcGeVector3d& vtHor,const AcGeVector3d& vtVer,const AcGePoint3d& ptStart,double dLen,AcArray >& arBracket) const { double dBLen = m_dBracketLen; if (m_nBracketMode == eGCover) dBLen = m_nWidth; XCurveSegment segTemp; AcGePoint3d ptT = ptStart,pt2; double dT = 0.0; while (TRUE) { dT = ptT.distanceTo(ptStart); if (dT < dLen) { pt2 = ptT + vtVer * dBLen; segTemp.SetPoints(ptT,pt2); arBracket.append(segTemp); } else { break; } ptT += vtHor * m_dBracketDis; } } Acad::ErrorStatus TDbCableTrench::ExplodeOrDraw3d(XExplodeDraw &dc) const { //得到电缆沟两端节点 //得到方沟两端节点 AcDbObjectId idNode1(NULL), idNode2(NULL); AcDbObjectIdArray arIds; idNode1 = GetNode(0); idNode2 = GetNode(1); if (!idNode1.isValid() || !idNode2.isValid()) { return Acad::eInvalidInput; } arIds.append(idNode1); arIds.append(idNode2); AcGePoint3d pt1,pt2,pt3,pt4,ptS,ptE; XCurveSegment cvHide,segUp, segDown; cvHide = GetCurve(); XDirectionCurve segDir(cvHide.StartPoint(), cvHide.EndPoint(), cvHide.GetBulge()); segUp = segDir.Offset(m_nWidth/2, LS_FINITE); segDown = segDir.Offset(-m_nWidth/2, LS_FINITE); pt1 = segUp.StartPoint(); pt3 = segUp.EndPoint(); pt2 = segDown.StartPoint(); pt4 = segDown.EndPoint(); ptS = cvHide.StartPoint(); ptE = cvHide.EndPoint(); double dW = m_nWidth; double dH = m_nHeight; AcGeVector3d vtNorm = AcGeVector3d::kZAxis; AcGeVector3d vtDir = pt3 - pt1; AcArray map; if (!vtDir.isPerpendicularTo(AcGeVector3d::kZAxis)) { AcGeVector3d vtT = vtDir.orthoProject(AcGeVector3d::kZAxis); vtT.rotateBy(PI/2,AcGeVector3d::kZAxis); AcGeVector3d vtT2 = vtDir.crossProduct(vtT); vtNorm = vtT2; vtNorm.normalize(); } else { //分别得到方沟的一端上两点 GetCannalPts(idNode1,pt1,pt2); GetCannalPts(idNode2,pt3,pt4); } // 下降电缆沟 double dDeep = GetHeight(); pt1 -= vtNorm * dDeep; pt2 -= vtNorm * dDeep; pt3 -= vtNorm * dDeep; pt4 -= vtNorm * dDeep; ptS -= vtNorm * dDeep; ptE -= vtNorm * dDeep; AcGePoint3d *pVerList = NULL; int nRow = 0; int nCol = 0; nRow = 5; nCol = 2; pVerList = new AcGePoint3d[nRow*nCol]; if (pVerList != NULL) { pVerList[0] = pt1 + m_nHeight*vtNorm; pVerList[1] = pt3 + m_nHeight*vtNorm; pVerList[2] = pt1; pVerList[3] = pt3; pVerList[4] = ptS; pVerList[5] = ptE; pVerList[6] = pt2; pVerList[7] = pt4; pVerList[8] = pt2 + m_nHeight*vtNorm; pVerList[9] = pt4 + m_nHeight*vtNorm; dc.DrawMesh(nRow, nCol, pVerList,NULL); delete []pVerList; } return Acad::eOk; } //宽度 void TDbCableTrench::SetGougeWidth(double dWidth) { SetWidth(dWidth); } //高度 void TDbCableTrench::SetGougeHeight(double dHeight) { assertWriteEnabled(); SetHeight(dHeight); } //倒角半径 void TDbCableTrench::SetCornerRadius(double dRadius) { assertWriteEnabled(); SetSpare(dRadius); } //电缆沟线宽 void TDbCableTrench::SetGougeLineWidth(double dLineW) { assertWriteEnabled(); m_dGougeLineW = dLineW; } //电缆沟支架形式 void TDbCableTrench::SetGougeMode(Adesk::UInt16 nType) { assertWriteEnabled(); m_nBracketMode = nType; } //支架长度 void TDbCableTrench::SetBracketLen(double dLen) { assertWriteEnabled(); m_dBracketLen = dLen; } //支架间距 void TDbCableTrench::SetBracketDis(double dDis) { assertWriteEnabled(); m_dBracketDis = dDis; } //支架线宽 void TDbCableTrench::SetBracketLineWidth(double dLineW) { assertWriteEnabled(); m_dBracketLineW = dLineW; } //宽度 double TDbCableTrench::GetGougeWidth() { return GetWidth(); } //高度 double TDbCableTrench::GetGougeHeight() { return GetHeight(); } //电缆沟线宽 double TDbCableTrench::GetGougeLineWidth() { return m_dGougeLineW; } //电缆沟支架形式 Adesk::UInt16 TDbCableTrench::GetGougeMode() { return m_nBracketMode; } //支架长度 double TDbCableTrench::GetBracketLen() { return m_dBracketLen; } //支架间距 double TDbCableTrench::GetBracketDis() { return m_dBracketDis; } //支架线宽 double TDbCableTrench::GetBracketLineWidth() { return m_dBracketLineW; } //拐角类别 void TDbCableTrench::SetCornerType(Adesk::UInt16 nType) { assertWriteEnabled(); switch(nType) { case 0: SetCanalType(Canal_Corner1); break; case 1: SetCanalType(Canal_Corner3); break; case 2: SetCanalType(Canal_Corner2); break; default: break; } } Adesk::UInt16 TDbCableTrench::GetCornerType() { Adesk::UInt16 nType = GetCanalType(); switch(nType) { case Canal_Corner1: nType = 0; break; case Canal_Corner2: nType = 2; break; case Canal_Corner3: nType = 1; break; default: break; } return nType; } //倒角半径 double TDbCableTrench::GetCornerRadius() const { return GetSpare(); } Acad::ErrorStatus TDbCableTrench::subGetOsnapPoints(AcDb::OsnapMode osnapMode, INT_PTR gsSelectionMark, const AcGePoint3d& ptPick, const AcGePoint3d& lastPoint, const AcGeMatrix3d& viewXform, AcGePoint3dArray& snapPoints, AcDbIntArray& geomIds) const { switch(osnapMode) { case AcDb::kOsModeEnd: { AcDbObjectId idNode1(NULL), idNode2(NULL); idNode1 = GetNode(0); idNode2 = GetNode(1); if (idNode1.isValid() && idNode2.isValid()) { AcGePoint3d pt1,pt2,pt3,pt4; //分别得到电缆沟的一端上两点 AcArray map1,map2; GetCannalPts(idNode1,pt1,pt2,map1); GetCannalPts(idNode2,pt3,pt4,map2); snapPoints.append(pt1); snapPoints.append(pt2); snapPoints.append(pt3); snapPoints.append(pt4); snapPoints.append(StartPoint()); snapPoints.append(EndPoint()); } break; } case AcDb::kOsModeMid: { AcDbObjectId idNode1(NULL), idNode2(NULL); idNode1 = GetNode(0); idNode2 = GetNode(1); if (idNode1.isValid() && idNode2.isValid()) { AcGePoint3d ptMid = Mid(GetStartPoint(),GetEndPoint()); snapPoints.append(ptMid); if (!IsHasMorePipes(idNode1)) { OPENOBJ_BEGIN(idNode1, AcDb::kForRead, TDbPipeNode, pNode); if(pNode) { ptMid = pNode->GetLocation(); snapPoints.append(ptMid); } OPENOBJ_END(); } if (!IsHasMorePipes(idNode2)) { OPENOBJ_BEGIN(idNode2, AcDb::kForRead, TDbPipeNode, pNode); if(pNode) { ptMid = pNode->GetLocation(); snapPoints.append(ptMid); } OPENOBJ_END(); } } break; } case AcDb::kOsModePerp: { AcGePoint3d ptVerFoot; if (GetVerticalFootPoint(ptPick, lastPoint, ptVerFoot)) { snapPoints.append(ptVerFoot); } break; } case AcDb::kOsModeNear: { AcGePoint3d ptNear; if (GetNearestPoint(ptPick, ptNear)) { snapPoints.append(ptNear); } break; } case AcDb::kOsModeNode: break; } return Acad::eOk; } // 获取垂足点 BOOL TDbCableTrench::GetVerticalFootPoint(const AcGePoint3d& pickPoint,const AcGePoint3d& lastPoint,AcGePoint3d& ptVerFoot) const { AcDbObjectId idNode1(NULL), idNode2(NULL); idNode1 = GetNode(0); idNode2 = GetNode(1); if (!idNode1.isValid() || !idNode2.isValid()) { return FALSE; } AcGePoint3d pt1,pt2,pt3,pt4; //分别得到电缆沟的一端上两点 AcArray map1,map2; GetCannalPts(idNode1,pt1,pt2,map1); GetCannalPts(idNode2,pt3,pt4,map2); AcArray cplCurve; AcDbLine *pLine = NULL; if (!IsHasMorePipes(idNode1)) { pLine = new AcDbLine; pLine->setStartPoint(pt1); pLine->setEndPoint(pt2); cplCurve.append(pLine); } pLine = new AcDbLine; pLine->setStartPoint(pt1); pLine->setEndPoint(pt3); cplCurve.append(pLine); if (!IsHasMorePipes(idNode2)) { pLine = new AcDbLine; pLine->setStartPoint(pt4); pLine->setEndPoint(pt3); cplCurve.append(pLine); } pLine = new AcDbLine; pLine->setStartPoint(pt4); pLine->setEndPoint(pt2); cplCurve.append(pLine); for (int t = 0;t < map1.length();t++) { pLine = new AcDbLine; pLine->setStartPoint(map1[t].pair.first); pLine->setEndPoint(map1[t].pair.second); cplCurve.append(pLine); } for (int j = 0;j < map2.length();j++) { pLine = new AcDbLine; pLine->setStartPoint(map2[j].pair.first); pLine->setEndPoint(map2[j].pair.second); cplCurve.append(pLine); } BOOL bFind = FALSE; if (cplCurve.length() > 0) { double dDisToLine = 0.0; double dDisOld = 100000.0; AcGePoint3d ptOnLine; int nIndex = -1; // 挑选离pick点最近的线 for (int i = 0;i < cplCurve.length();i++) { if (cplCurve[i]->getClosestPointTo(pickPoint, ptOnLine,Adesk::kTrue) == Acad::eOk) { dDisToLine = pickPoint.distanceTo(ptOnLine); if (dDisOld > dDisToLine) { dDisOld = dDisToLine; nIndex = i; } } } // 找到第一次取的点到该线的垂点 if (nIndex != -1) { if (cplCurve[nIndex]->getClosestPointTo(lastPoint, ptOnLine,Adesk::kTrue) == Acad::eOk) { ptVerFoot = ptOnLine; bFind = TRUE; } } } FreeBuffer(cplCurve); return bFind; } // 获取最近点 BOOL TDbCableTrench::GetNearestPoint(const AcGePoint3d& pickPoint,AcGePoint3d& ptNear) const { AcDbObjectId idNode1(NULL), idNode2(NULL); idNode1 = GetNode(0); idNode2 = GetNode(1); if (!idNode1.isValid() || !idNode2.isValid()) { return FALSE; } AcGePoint3d pt1,pt2,pt3,pt4; //分别得到电缆沟的一端上两点 AcArray map1,map2; GetCannalPts(idNode1,pt1,pt2,map1); GetCannalPts(idNode2,pt3,pt4,map2); AcArray cplCurve; AcDbLine *pLine = NULL; if (!IsHasMorePipes(idNode1)) { pLine = new AcDbLine; pLine->setStartPoint(pt1); pLine->setEndPoint(pt2); cplCurve.append(pLine); } pLine = new AcDbLine; pLine->setStartPoint(pt1); pLine->setEndPoint(pt3); cplCurve.append(pLine); if (!IsHasMorePipes(idNode2)) { pLine = new AcDbLine; pLine->setStartPoint(pt4); pLine->setEndPoint(pt3); cplCurve.append(pLine); } pLine = new AcDbLine; pLine->setStartPoint(pt4); pLine->setEndPoint(pt2); cplCurve.append(pLine); for (int t = 0;t < map1.length();t++) { pLine = new AcDbLine; pLine->setStartPoint(map1[t].pair.first); pLine->setEndPoint(map1[t].pair.second); cplCurve.append(pLine); } for (int j = 0;j < map2.length();j++) { pLine = new AcDbLine; pLine->setStartPoint(map2[j].pair.first); pLine->setEndPoint(map2[j].pair.second); cplCurve.append(pLine); } BOOL bFind = FALSE; if (cplCurve.length() > 0) { double dDisToLine = 0.0; double dDisOld = 100000.0; AcGePoint3d ptOnLine; // 挑选离pick点最近的线 for (int i = 0;i < cplCurve.length();i++) { if (cplCurve[i]->getClosestPointTo(pickPoint, ptOnLine) == Acad::eOk) { dDisToLine = pickPoint.distanceTo(ptOnLine); if (dDisOld > dDisToLine) { dDisOld = dDisToLine; ptNear = ptOnLine; bFind = TRUE; } } } } FreeBuffer(cplCurve); return bFind; } // 释放内存 void TDbCableTrench::FreeBuffer(AcArray& cplCurve) const { for (int i = 0;i < cplCurve.length();i++) { delete cplCurve[i]; } } //电缆编号 void TDbCableTrench::SetTrenchNo(LPCTSTR lpNo) { if (lpNo != NULL) m_sTrenchNo = lpNo; } //得到电缆编号 void TDbCableTrench::GetTrenchNo(CString &sNo) { sNo = m_sTrenchNo; } CString TDbCableTrench::GetXml(const AcGeMatrix3d& mat) const { CString csXml; int nValue(0); double dValue(0.0); int nSizePreci(3), nPtPreci(6); // 尺寸、位置精度 TXmlTree xmlTree; CString csText; CString csX, csY, csZ; AcDbObjectId idNode1(NULL), idNode2(NULL); AcDbObjectIdArray arIds; idNode1 = GetNode(0); idNode2 = GetNode(1); if (!idNode1.isValid() || !idNode2.isValid()) { return csXml; } arIds.append(idNode1); arIds.append(idNode2); AcGePoint3d pt1,pt2,pt3,pt4,ptS,ptE; XCurveSegment cvHide,segUp, segDown; cvHide = GetCurve(); XDirectionCurve segDir(cvHide.StartPoint(), cvHide.EndPoint(), cvHide.GetBulge()); segUp = segDir.Offset(m_nWidth/2, LS_FINITE); segDown = segDir.Offset(-m_nWidth/2, LS_FINITE); pt1 = segUp.StartPoint(); pt3 = segUp.EndPoint(); pt2 = segDown.StartPoint(); pt4 = segDown.EndPoint(); ptS = cvHide.StartPoint(); ptE = cvHide.EndPoint(); double dW = m_nWidth; double dH = m_nHeight; AcGeVector3d vtNorm = AcGeVector3d::kZAxis; AcGeVector3d vtDir = pt3 - pt1; AcArray map; if (!vtDir.isPerpendicularTo(AcGeVector3d::kZAxis)) { AcGeVector3d vtT = vtDir.orthoProject(AcGeVector3d::kZAxis); vtT.rotateBy(PI/2,AcGeVector3d::kZAxis); AcGeVector3d vtT2 = vtDir.crossProduct(vtT); vtNorm = vtT2; vtNorm.normalize(); } else { //分别得到方沟的一端上两点 GetCannalPts(idNode1,pt1,pt2); GetCannalPts(idNode2,pt3,pt4); } // 下降电缆沟 double dDeep = GetHeight(); pt1 -= vtNorm * dDeep; pt2 -= vtNorm * dDeep; pt3 -= vtNorm * dDeep; pt4 -= vtNorm * dDeep; ptS -= vtNorm * dDeep; ptE -= vtNorm * dDeep; AcGePoint3d *pVerList = NULL; int nRow = 0; int nCol = 0; nRow = 5; nCol = 2; pVerList = new AcGePoint3d[nRow*nCol]; if (pVerList != NULL) { pVerList[0] = pt1 + m_nHeight*vtNorm; pVerList[1] = pt3 + m_nHeight*vtNorm; pVerList[2] = pt1; pVerList[3] = pt3; pVerList[4] = ptS; pVerList[5] = ptE; pVerList[6] = pt2; pVerList[7] = pt4; pVerList[8] = pt2 + m_nHeight*vtNorm; pVerList[9] = pt4 + m_nHeight*vtNorm; POSITION posRoot = xmlTree.Insert(_T("TCH_GOUGE"), NULL, NULL); { xmlTree.SetAttribute(posRoot, _T("name"), _T("电缆沟")); xmlTree.SetAttribute(posRoot, _T("comment"), _T("上华对象名称")); } // 点组 POSITION nowPos; for (int i = 0; i<(nRow*nCol); i++) { CString strName, strCName; strName.Format(_T("pt_%d"), i); strCName.Format(_T("点_%d"), i); nowPos = xmlTree.Insert(strName, posRoot,NULL); { xmlTree.SetAttribute(nowPos, _T("name"),strCName); xmlTree.SetAttribute(nowPos, _T("comment"), strCName); AcGePoint3d pt = pVerList[i]; csX.Format(_T("%.6f"),pt.x); csY.Format(_T("%.6f"),pt.y); csZ.Format(_T("%.6f"),pt.z); csText.Format(_T("%s,%s,%s"),csX,csY,csZ); xmlTree.SetItemText(nowPos,csText); } } // 宽度 nowPos = xmlTree.Insert(_T("Width"),posRoot,NULL); { xmlTree.SetAttribute(nowPos, _T("name"), _T("宽度")); xmlTree.SetAttribute(nowPos, _T("comment"), _T("宽度")); csText.Format(_T("%.3f"),m_nWidth); xmlTree.SetItemText(nowPos,csText); } // 高度 nowPos = xmlTree.Insert(_T("Height"),posRoot,NULL); { xmlTree.SetAttribute(nowPos, _T("name"), _T("高度")); xmlTree.SetAttribute(nowPos, _T("comment"), _T("高度")); csText.Format(_T("%.3f"),m_nHeight); xmlTree.SetItemText(nowPos,csText); } // id nowPos = xmlTree.Insert(_T("Object_ID"),posRoot,NULL); { xmlTree.SetAttribute(nowPos, _T("name"), _T("ID")); xmlTree.SetAttribute(nowPos, _T("comment"), _T("电缆沟ID")); csText.Format(_T("%ld"), objectId().asOldId()); xmlTree.SetItemText(nowPos, csText); } delete []pVerList; } csXml = xmlTree.GetXml(); int nIndex = -1; nIndex = csXml.Find(_T("")); if (nIndex != -1) { CString sTemp = TDbCurveEntity::GetXml(mat); csXml.Insert(nIndex, sTemp); } return csXml; } bool TDbCableTrench::GetSection(const AcDbFace &face, const AcGeVector3d &vtPlaneSecDir, std::vector §ionRecord, AcDbVoidPtrArray& arFillPtrs) const { // 基本参数 AcDbObjectId idObj = this->objectId(); AcDbObjectId idLayer = this->layerId(); TGGeSectionPlane section_pln(face, vtPlaneSecDir); // 构造一个辅助剖面 AcDbVoidPtrArray arFaces; XExplodeStream dc(arFaces); ExplodeOrDraw3d(dc); double dElevation = 0; AcDbEntity* pEnt = NULL; AcDbFace* pFace = NULL; int i = 0; for(i = 0; i < arFaces.length(); ++i) { pEnt = (AcDbEntity*)arFaces[i]; if (NULL == pEnt) continue; pFace = AcDbFace::cast(pEnt); if (pFace) { TGGeSectionPlane pln(*pFace, vtPlaneSecDir); TGGePoly2D poly; dElevation = SectionUtility::Projection_plane2plane(section_pln, pln, poly); if (poly.Length() > 0) { sectionRecord.push_back(TObjSectionRecord(idObj, idLayer, TObjSectionRecord::eTCH_WALL, dElevation, poly)); } } delete pEnt; } return true; } // 剖切用,返回Z坐标最高、最低点 Acad::ErrorStatus TDbCableTrench::GetExtents(TADSGePoint3d &ptLow, TADSGePoint3d &ptUp) const { AcDbObjectId idNode1(NULL), idNode2(NULL); AcDbObjectIdArray arIds; idNode1 = GetNode(0); idNode2 = GetNode(1); if (!idNode1.isValid() || !idNode2.isValid()) { return Acad::eInvalidInput; } arIds.append(idNode1); arIds.append(idNode2); AcGePoint3d pt1,pt2,pt3,pt4,ptS,ptE; XCurveSegment cvHide,segUp, segDown; cvHide = GetCurve(); ptUp = cvHide.StartPoint(); ptLow = ptUp; ptLow.z -= m_nHeight; return Acad::eOk; } int TDbCableTrench::GetBodyBox(AcDbExtents& ext) { //得到电缆沟两端节点 //得到方沟两端节点 AcDbObjectId idNode1(NULL), idNode2(NULL); AcDbObjectIdArray arIds; idNode1 = GetNode(0); idNode2 = GetNode(1); if (!idNode1.isValid() || !idNode2.isValid()) { return Acad::eInvalidInput; } arIds.append(idNode1); arIds.append(idNode2); AcGePoint3d pt1,pt2,pt3,pt4,ptS,ptE; XCurveSegment cvHide,segUp, segDown; cvHide = GetCurve(); XDirectionCurve segDir(cvHide.StartPoint(), cvHide.EndPoint(), cvHide.GetBulge()); segUp = segDir.Offset(m_nWidth/2, LS_FINITE); segDown = segDir.Offset(-m_nWidth/2, LS_FINITE); pt1 = segUp.StartPoint(); pt3 = segUp.EndPoint(); pt2 = segDown.StartPoint(); pt4 = segDown.EndPoint(); ptS = cvHide.StartPoint(); ptE = cvHide.EndPoint(); double dW = m_nWidth; double dH = m_nHeight; AcGeVector3d vtNorm = AcGeVector3d::kZAxis; AcGeVector3d vtDir = pt3 - pt1; AcArray map; if (!vtDir.isPerpendicularTo(AcGeVector3d::kZAxis)) { AcGeVector3d vtT = vtDir.orthoProject(AcGeVector3d::kZAxis); vtT.rotateBy(PI/2,AcGeVector3d::kZAxis); AcGeVector3d vtT2 = vtDir.crossProduct(vtT); vtNorm = vtT2; vtNorm.normalize(); } else { //分别得到方沟的一端上两点 GetCannalPts(idNode1,pt1,pt2); GetCannalPts(idNode2,pt3,pt4); } // 下降电缆沟 double dDeep = GetHeight(); pt1 -= vtNorm * dDeep; pt2 -= vtNorm * dDeep; pt3 -= vtNorm * dDeep; pt4 -= vtNorm * dDeep; ptS -= vtNorm * dDeep; ptE -= vtNorm * dDeep; /* AcGePoint3d *pVerList = NULL; int nRow = 0; int nCol = 0; nRow = 5; nCol = 2; pVerList = new AcGePoint3d[nRow*nCol]; */ AcGePoint3d pVerList[10]; pVerList[0] = pt1 + m_nHeight*vtNorm; pVerList[1] = pt3 + m_nHeight*vtNorm; pVerList[2] = pt1; pVerList[3] = pt3; pVerList[4] = ptS; pVerList[5] = ptE; pVerList[6] = pt2; pVerList[7] = pt4; pVerList[8] = pt2 + m_nHeight*vtNorm; pVerList[9] = pt4 + m_nHeight*vtNorm; double dMaxX = pVerList[0].x; double dMaxY = pVerList[0].y; double dMaxZ = pVerList[0].z; double dMinX = dMaxX; double dMinY = dMaxY; double dMinZ = dMaxZ; for (int i = 0; i < 10; ++i) { if (dMaxX < pVerList[i].x) dMaxX = pVerList[i].x; if (dMaxY < pVerList[i].y) dMaxY = pVerList[i].y; if (dMaxZ < pVerList[i].z) dMaxZ = pVerList[i].z; if (dMinX > pVerList[i].x) dMinX = pVerList[i].x; if (dMinY > pVerList[i].y) dMinY = pVerList[i].y; if (dMinZ > pVerList[i].z) dMinZ = pVerList[i].z; } AcGePoint3d ptMax(dMaxX,dMaxY,dMaxZ); AcGePoint3d ptMin(dMinX,dMinY,dMinZ); ext.set(ptMin,ptMax); return 1; }