#include "StdAfx.h" #include "DbCanalFitting.h" #include "DbPipeFitting.h" #include "DbPipeCanal.h" extern double g_dPointToOriginLimitDist; extern BOOL IsShowPipeCanalLineWeight(AcDbDatabase *pDb = NULL); extern void DrawWeight(XExplodeDraw &dc,double dWeight,XCurveSegment &seg,int nColorIndex, double nScale); TDbCanalFitting::TDbCanalFitting(const TDbPipeFitting *pFitting): m_pPipeFitting(pFitting) { } TDbCanalFitting::~TDbCanalFitting() { } Acad::ErrorStatus TDbCanalFitting::ExplodeOrDraw2d(XExplodeDraw &dc) const { // 方沟间交点 std::vector vecCanalId; std::vector > vecOrigin; if (!CanalInersect(vecCanalId, vecOrigin)) { return Acad::eOk; } // 根据方沟样式调整交点 std::vector > vecInt(vecOrigin); ModifyCanalInts(vecCanalId, vecInt); // 绘制连接件 DrawFitting(dc, vecCanalId, vecOrigin, vecInt); return Acad::eOk; } Acad::ErrorStatus TDbCanalFitting::ExplodeOrDraw3d(XExplodeDraw &dc) const { return Acad::eOk; } bool TDbCanalFitting::IntersectWith(const AcDbObjectId &idLinkedCanal, AcGePoint3d &ptLeft, AcGePoint3d &ptRight) const { std::vector vecCanalId; std::vector > vecInt; bool bRet = CanalInersect(vecCanalId, vecInt); for (int i = 0; i < vecCanalId.size() && bRet; ++i) { if (vecCanalId[i] == idLinkedCanal) { ptLeft = vecInt[i].first; ptRight = vecInt[i].second; return true; } } return false; } bool TDbCanalFitting::CanalInersect(std::vector &vecCanalId, std::vector > &vecInt) const { // 获得方沟中心线 int nNum = m_pPipeFitting->GetInterfaceNum(); std::map mapCanal; std::map mapWidth; for (int i = 0; i < nNum; ++i) { const AcDbObjectId &id = m_pPipeFitting->GetIPipe(i); OPENOBJ_BEGIN(id, AcDb::kForRead, TDbPipeCanal, pCanal); if (pCanal != NULL) { XCurveSegment cenCurve = pCanal->GetCurve(); mapCanal.insert(std::make_pair(id, cenCurve)); mapWidth.insert(std::make_pair(id, pCanal->GetWidth())); } OPENOBJ_END(); } if (mapCanal.size() < 2) { return false; } // 以连接件插入点为原点,逆时针排列方沟,并获得方沟逆时针方向的左右边线 std::map mapAngle; std::map > mapSide; AcGeVector3d vtX = AcGeVector3d::kXAxis; vtX.rotateBy(Ucs2Wcs(0.0), AcGeVector3d::kZAxis); XPoint ptLoc = m_pPipeFitting->GetLocation(); ptLoc.z = 0.0; std::map::iterator it, itEnd = mapCanal.end(); for (it = mapCanal.begin(); it != itEnd; ++it) { XCurveSegment &seg = it->second; if (seg.Is(CURVE_LINE)) // 直线 { seg.SetElevation(0.0); XPoint ptMid = seg.MidPoint(); ptMid.z = 0.0; AcGeVector3d vtDir = ptMid - ptLoc; double dAngle = vtX.angleTo(vtDir, AcGeVector3d::kZAxis); if (fabs(dAngle - PI * 2) < 0.001) { dAngle = 0.0; } mapAngle.insert(std::make_pair(dAngle, it->first)); // 左右边线 vtDir.rotateBy(PI * 0.5, AcGeVector3d::kZAxis); vtDir.normalize(); XCurveSegment segLeft, segRight; segLeft.SetPoints(seg.StartPoint() + vtDir * mapWidth[it->first] * 0.5, seg.EndPoint() + vtDir * mapWidth[it->first] * 0.5); segRight.SetPoints(seg.StartPoint() - vtDir * mapWidth[it->first] * 0.5, seg.EndPoint() - vtDir * mapWidth[it->first] * 0.5); segLeft.SetLineFlag(LS_INFINITE); segRight.SetLineFlag(LS_INFINITE); mapSide.insert(std::make_pair(it->first, std::make_pair(segLeft, segRight))); } else if (seg.Is(CURVE_ARC))// 弧线 { XArc arc = seg.GetArc(); XPoint ptCenter = arc.GetCenterPt(); XPoint ptS, ptE, ptMid; arc.GetStartPoint(ptS); arc.GetEndPoint(ptE); ptMid = arc.MidPoint(); ptS.z = 0.0; ptE.z = 0.0; ptMid.z = 0.0; ptCenter.z = 0.0; AcGeVector3d vtDir = ptCenter - ptLoc; vtDir.normalize(); XCurveSegment segLeft, segRight; double dWidth = mapWidth[it->first] * 0.5; if (ptLoc.Distance2d(seg.StartPoint()) < 0.001) // 起点 { segLeft = XArc(ptS + vtDir * dWidth, ptMid + vtDir * dWidth, ptE + vtDir * dWidth); segRight = XArc(ptS - vtDir * dWidth, ptMid - vtDir * dWidth, ptE - vtDir * dWidth); vtDir.rotateBy(-PI * 0.5, AcGeVector3d::kZAxis); } else // 终点 { segLeft = XArc(ptS - vtDir * dWidth, ptMid - vtDir * dWidth, ptE - vtDir * dWidth); segRight = XArc(ptS + vtDir * dWidth, ptMid + vtDir * dWidth, ptE + vtDir * dWidth); vtDir.rotateBy(PI * 0.5, AcGeVector3d::kZAxis); } double dAngle = vtX.angleTo(vtDir, AcGeVector3d::kZAxis); if (fabs(dAngle - PI * 2) < 0.001) { dAngle = 0.0; } mapAngle.insert(std::make_pair(dAngle, it->first)); mapSide.insert(std::make_pair(it->first, std::make_pair(segLeft, segRight))); } } // 有的方沟没有获得角度值 if (mapCanal.size() != mapAngle.size()) { return false; } // 按顺序求相连方沟交点 std::map::iterator itAngle, itTemp, itPre, itAngleEnd = mapAngle.end(); for (itAngle = mapAngle.begin(); itAngle != itAngleEnd; ++itAngle) { AcDbObjectId id = itAngle->second; AcDbObjectId idLeft = AcDbObjectId::kNull; AcDbObjectId idRight = AcDbObjectId::kNull; itTemp = itAngle; ++itTemp; if (itTemp == itAngleEnd) { idLeft = mapAngle.begin()->second; } else { idLeft = itTemp->second; } if (itAngle == mapAngle.begin()) { idRight = mapAngle.rbegin()->second; } else { idRight = itPre->second; } itPre = itAngle; // 求交 XCurveSegment segLeft = mapSide[id].first; XCurveSegment segRight = mapSide[id].second; AcDbCurve *pLeftCurve1 = segLeft.AsAcDbCurve(); AcDbCurve *pRightCurve1 = segRight.AsAcDbCurve(); AcDbCurve *pLeftCurve2 = mapSide[idLeft].second.AsAcDbCurve(); AcDbCurve *pRightCurve2 = mapSide[idRight].first.AsAcDbCurve(); if (pLeftCurve1 == NULL || pRightCurve1 == NULL || pLeftCurve2 == NULL || pRightCurve2 == NULL) { delete pLeftCurve1; delete pRightCurve1; delete pLeftCurve2; delete pRightCurve2; return false; } // 距离原点太远时可能计算出错, 将管道移动到原点附近计算 AcGeMatrix3d mat = AcGeMatrix3d::kIdentity; AcGeVector3d vtMove = segLeft.StartPoint(); if (fabs(vtMove.x) > g_dPointToOriginLimitDist || fabs(vtMove.y) > g_dPointToOriginLimitDist || fabs(vtMove.z) > g_dPointToOriginLimitDist) { mat.setToTranslation(vtMove * -1); pLeftCurve1->transformBy(mat); pRightCurve1->transformBy(mat); pLeftCurve2->transformBy(mat); pRightCurve2->transformBy(mat); } AcGePoint3dArray arrLeft, arrRight; pLeftCurve1->intersectWith(pLeftCurve2, AcDb::kExtendBoth, arrLeft); pRightCurve1->intersectWith(pRightCurve2, AcDb::kExtendBoth, arrRight); delete pLeftCurve1; delete pRightCurve1; delete pLeftCurve2; delete pRightCurve2; XPoint pt1 = ptLoc.Distance2d(segLeft.StartPoint()) > ptLoc.Distance2d(segLeft.EndPoint()) ? segLeft.EndPoint() : segLeft.StartPoint(); XPoint pt3 = ptLoc.Distance2d(segRight.StartPoint()) > ptLoc.Distance2d(segRight.EndPoint()) ? segRight.EndPoint() : segRight.StartPoint(); double dDist = -1; for(int i = 0; i < arrLeft.length(); ++i) { AcGePoint3d pt = arrLeft.at(i); pt.transformBy(mat.inverse()); double dTemp = ptLoc.Distance2d(pt); if (dDist < 0.0 || dTemp < dDist) { dDist = dTemp; pt1 = pt; } } dDist = -1; for(int i = 0; i < arrRight.length(); ++i) { AcGePoint3d pt = arrRight.at(i); pt.transformBy(mat.inverse()); double dTemp = ptLoc.Distance2d(pt); if (dDist < 0.0 || dTemp < dDist) { dDist = dTemp; pt3 = pt; } } vecInt.push_back(std::make_pair(pt3, pt1)); vecCanalId.push_back(id); } return true; } void TDbCanalFitting::ModifyCanalInts(std::vector &vecCanalId, std::vector > &vecInt) const { XPoint ptLoc = m_pPipeFitting->GetLocation(); for (int i = 0; i < vecCanalId.size(); ++i) { OPENOBJ_BEGIN(vecCanalId[i], AcDb::kForRead, TDbPipeCanal, pCanal); if (pCanal != NULL) { Adesk::UInt16 nLinkType = pCanal->GetCanalType(); if (nLinkType != 0) { XCurveSegment cenCurve = pCanal->GetCurve(); int nPos = pCanal->StartPoint().Distance2d(ptLoc) < 0.001 ? 0 : 1; int nLinkNum = m_pPipeFitting->GetInterfaceNum() - 1; // 方沟端点连接的方沟个数 bool bLink = pCanal->LinkedPipeCanalNum(nPos == 0 ? 1 : 0) > 0; // 另一端是否连接着方沟 bool bCanCreate = bLink && cenCurve.GetLength() > pCanal->GetSpare() * 2 + 0.001 || !bLink && cenCurve.GetLength() > pCanal->GetSpare() + 0.001; // 是否可以创建倒角 if (cenCurve.Is(CURVE_LINE)) // 直线 { XPoint ptMid = cenCurve.MidPoint(); AcGeVector3d vtDir = ptMid - ptLoc; vtDir.z = 0.0; vtDir.normalize(); XPoint ptTemp1 = vecInt[i].first, ptTemp2 = vecInt[i].second; XPoint pt1; if (bCanCreate) pt1 = vecInt[i].first + vtDir * pCanal->GetSpare(); XPoint pt2; if (bCanCreate) pt2 = vecInt[i].second + vtDir * pCanal->GetSpare(); if (nLinkNum == 1 && bCanCreate) // 弯头 { int nPos = ptLoc.Distance2d(pCanal->StartPoint()) < 0.001 ? 0 : 1; int nRet = pCanal->NeedModifyInt(nPos, m_pPipeFitting); if (nRet == 1) { if (nPos == 0) { pt1 = ptTemp1; } else { pt2 = ptTemp2; } } else if (nRet == 2) { if (nPos == 0) { pt2 = ptTemp2; } else { pt1 = ptTemp1; } } } vecInt[i] = std::make_pair(pt1, pt2); } else // 弧线 { XPoint ptMid = cenCurve.MidPoint(); AcGeVector3d vtDir = ptMid - ptLoc; vtDir.z = 0.0; vtDir.normalize(); XPoint ptTemp1 = vecInt[i].first, ptTemp2 = vecInt[i].second; XArc arc = cenCurve.GetArc(); XPoint ptCenter = arc.GetCenterPt(); ptCenter.z = 0.0; double dRadius1 = ptTemp1.Distance2d(ptCenter); AcGeVector3d vtDir1 = ptTemp1 - ptCenter; vtDir1.z = 0.0; vtDir1.normalize(); double dAngle1 = pCanal->GetSpare() / dRadius1; vtDir1.rotateBy(dAngle1 * (nPos == 0 ? 1 : -1), AcGeVector3d::kZAxis); XPoint pt1 = bCanCreate ? ptCenter + vtDir1 * dRadius1 : ptTemp1; double dRadius2 = ptTemp2.Distance2d(ptCenter); AcGeVector3d vtDir2 = ptTemp2 - ptCenter; vtDir2.z = 0.0; vtDir2.normalize(); double dAngle2 = pCanal->GetSpare() / dRadius2; vtDir2.rotateBy(dAngle2 * (nPos == 0 ? 1 : -1), AcGeVector3d::kZAxis); XPoint pt2 = bCanCreate ? ptCenter + vtDir2 * dRadius2 : ptTemp2; if (nLinkNum == 1 && bCanCreate) // 弯头 { int nRet = pCanal->NeedModifyInt(nPos, m_pPipeFitting); if (nRet == 1) { if (nPos == 0) { pt1 = ptTemp1; } else { pt2 = ptTemp2; } } else if (nRet == 2) { if (nPos == 0) { pt2 = ptTemp2; } else { pt1 = ptTemp1; } } } vecInt[i] = std::make_pair(pt1, pt2); } } } OPENOBJ_END(); } } void TDbCanalFitting::DrawFitting(XExplodeDraw &dc, std::vector &vecCanalId, std::vector > &vecOriginInt, std::vector > &vecModifiedInt) const { // 获得方沟信息 double dWeight = 0.0; Adesk::UInt16 nColor = 0; double dLinetypeScale = 0.0; std::set setType; // 连接样式 std::set setRadius; // 倒角半径 bool bArc = false, bLine = false; std::vector vecSeg; for (int i = 0; i < vecCanalId.size(); ++i) { OPENOBJ_BEGIN(vecCanalId[i], AcDb::kForRead, TDbPipeCanal, pCanal); if (pCanal != NULL) { dWeight = pCanal->GetPipeWeight() * pCanal->GetPScale(); nColor = pCanal->colorIndex(); dLinetypeScale = pCanal->linetypeScale(); Adesk::UInt16 nLinkType = pCanal->GetCanalType(); setType.insert(nLinkType); if (nLinkType != 0) { XCurveSegment cenCurve = pCanal->GetCurve(); vecSeg.push_back(cenCurve); if (cenCurve.Is(CURVE_LINE)) // 直线 { bLine = true; } else // 弧线 { bArc = true; } } } OPENOBJ_END(); } if (!IsShowPipeCanalLineWeight(m_pPipeFitting->database())) { dWeight = 0.0; } // 绘制 Adesk::UInt16 nLinkType = *setType.begin(); if (setType.size() == 1 && (bArc && !bLine && nLinkType != 3 && nLinkType != 4 || !bArc && bLine) && // 方沟样式统一 并且方沟都为直线或弧线(弧线方沟弧形连接时,直接直线相连) (nLinkType == 2 && vecModifiedInt.size() == 2 || // 样式3相连方沟个数大于2个时,绘制方式与样式2相同 nLinkType == 3 || nLinkType == 4)) { XCurveSegment seg; if (nLinkType == 4 || nLinkType == 3 && vecModifiedInt.size() != 2) // 弧线连接 { if (bLine) // 直线方沟 { for (int i = 0; i < vecModifiedInt.size(); ++i) { if (i != vecModifiedInt.size() - 1) { DrawArcLinkCurve(dc, vecOriginInt[i].second, vecSeg[i], vecSeg[i + 1], vecModifiedInt[i].second, vecModifiedInt[i + 1].first, dWeight, nColor, dLinetypeScale); } else { DrawArcLinkCurve(dc, vecOriginInt[i].second, vecSeg[i], vecSeg[0], vecModifiedInt[i].second, vecModifiedInt[0].first, dWeight, nColor, dLinetypeScale); } } } } else if (vecModifiedInt.size() == 2 && (nLinkType == 3 || nLinkType == 2)) // 弯头 { if (nLinkType == 2) // 直线连接 { if (vecModifiedInt[0].second.Distance2d(vecModifiedInt[1].first) > 0.001) { seg.SetPoints(vecModifiedInt[0].second, vecModifiedInt[1].first); DrawWeight(dc, dWeight, seg, nColor, dLinetypeScale); } if (vecModifiedInt[0].first.Distance2d(vecModifiedInt[1].second) > 0.001) { seg.SetPoints(vecModifiedInt[1].second, vecModifiedInt[0].first); DrawWeight(dc, dWeight, seg, nColor, dLinetypeScale); } } else // 弧线连接 { DrawArcLinkCurve(dc, vecOriginInt[0].first, vecSeg[0], vecSeg[1], vecModifiedInt[1].second, vecModifiedInt[0].first, dWeight, nColor, dLinetypeScale); DrawArcLinkCurve(dc, vecOriginInt[0].second, vecSeg[0], vecSeg[1], vecModifiedInt[0].second, vecModifiedInt[1].first, dWeight, nColor, dLinetypeScale); } } } else // 方沟样式不统一, 直线连接相连交点 { XCurveSegment seg; for (int i = 0; i < vecModifiedInt.size(); ++i) { if (i == vecModifiedInt.size() - 1) { if (vecModifiedInt[i].second.Distance2d(vecModifiedInt[0].first) < 0.001) { continue; } seg.SetPoints(vecModifiedInt[i].second, vecModifiedInt[0].first); } else { if (vecModifiedInt[i].second.Distance2d(vecModifiedInt[i + 1].first) < 0.001) { continue; } seg.SetPoints(vecModifiedInt[i].second, vecModifiedInt[i + 1].first); } DrawWeight(dc, dWeight, seg, nColor, dLinetypeScale); } } } void TDbCanalFitting::DrawArcLinkCurve(XExplodeDraw &dc, XPoint ptInt, XCurveSegment segLeft, XCurveSegment segRight, XPoint ptLeft, XPoint ptRight, double dWeight, Adesk::UInt16 nColor, double dLinetypeScale) const { if (!segLeft.Is(CURVE_LINE) || !segRight.Is(CURVE_LINE)) { return; } AcGeVector3d vtLeft = ptInt - ptLeft; AcGeVector3d vtRight = ptInt - ptRight; AcGeTol tol; tol.setEqualVector(0.001); if (vtLeft.isParallelTo(vtRight, tol)) { XCurveSegment seg; seg = XLine(ptLeft, ptRight); DrawWeight(dc, dWeight, seg, nColor, dLinetypeScale); return; } XCurveSegment seg; double dDist1 = ptInt.Distance2d(ptLeft); double dDist2 = ptInt.Distance2d(ptRight); double dMinDist = dDist1 > dDist2 ? dDist2 : dDist1; if (dMinDist > 0.001) { AcGeVector3d vtTemp1 = ptLeft - ptInt; AcGeVector3d vtTemp2 = ptRight - ptInt; double dAngle = vtTemp1.angleTo(vtTemp2, AcGeVector3d::kZAxis); XPoint pt0 = ptInt + vtTemp1.normalize() * dMinDist; XPoint pt1 = ptInt + vtTemp2.normalize() * dMinDist; double dLen = dMinDist / cos(dAngle * 0.5); AcGeVector3d vtTemp = vtTemp1; vtTemp.rotateBy(dAngle * 0.5, AcGeVector3d::kZAxis); XPoint ptCenter = ptInt + vtTemp.normalize() * dLen; XPoint ptMid = ptCenter - vtTemp.normalize() * ptCenter.Distance2d(pt0); if (dAngle > PI) { dAngle = PI * 2 - dAngle; dLen = dMinDist / cos(dAngle * 0.5); vtTemp = vtTemp1; vtTemp.rotateBy(-dAngle * 0.5, AcGeVector3d::kZAxis); ptCenter = ptInt + vtTemp.normalize() * dLen; ptMid = ptCenter - vtTemp.normalize() * ptCenter.Distance2d(pt0); } XArc arc(pt1, ptMid, pt0); seg = arc; DrawWeight(dc, dWeight, seg, nColor, dLinetypeScale); } // 倒角半径大于最小值,补充缺失的部分 if (dDist1 > dMinDist + 0.001) { AcGeVector3d vtTemp = ptLeft - ptInt; XPoint ptTemp = ptInt + vtTemp.normalize() * dMinDist; seg = XLine(ptTemp, ptLeft); DrawWeight(dc, dWeight, seg, nColor, dLinetypeScale); } // 倒角半径大于最小值,补充缺失的部分 if (dDist2 > dMinDist + 0.001) { AcGeVector3d vtTemp = ptRight - ptInt; XPoint ptTemp = ptInt + vtTemp.normalize() * dMinDist; seg = XLine(ptTemp, ptRight); DrawWeight(dc, dWeight, seg, nColor, dLinetypeScale); } }