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

548 lines
17 KiB
C++

#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<AcDbObjectId> vecCanalId;
std::vector<std::pair<XPoint, XPoint> > vecOrigin;
if (!CanalInersect(vecCanalId, vecOrigin))
{
return Acad::eOk;
}
// 根据方沟样式调整交点
std::vector<std::pair<XPoint, XPoint> > 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<AcDbObjectId> vecCanalId;
std::vector<std::pair<XPoint, XPoint> > 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<AcDbObjectId> &vecCanalId, std::vector<std::pair<XPoint, XPoint> > &vecInt) const
{
// 获得方沟中心线
int nNum = m_pPipeFitting->GetInterfaceNum();
std::map<AcDbObjectId, XCurveSegment> mapCanal;
std::map<AcDbObjectId, double> 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<double, AcDbObjectId> mapAngle;
std::map<AcDbObjectId, std::pair<XCurveSegment, XCurveSegment> > mapSide;
AcGeVector3d vtX = AcGeVector3d::kXAxis;
vtX.rotateBy(Ucs2Wcs(0.0), AcGeVector3d::kZAxis);
XPoint ptLoc = m_pPipeFitting->GetLocation();
ptLoc.z = 0.0;
std::map<AcDbObjectId, XCurveSegment>::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<double, AcDbObjectId>::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<AcDbObjectId> &vecCanalId, std::vector<std::pair<XPoint, XPoint> > &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<AcDbObjectId> &vecCanalId, std::vector<std::pair<XPoint, XPoint> > &vecOriginInt, std::vector<std::pair<XPoint, XPoint> > &vecModifiedInt) const
{
// 获得方沟信息
double dWeight = 0.0;
Adesk::UInt16 nColor = 0;
double dLinetypeScale = 0.0;
std::set<Adesk::UInt16> setType; // 连接样式
std::set<double> setRadius; // 倒角半径
bool bArc = false, bLine = false;
std::vector<XCurveSegment> 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);
}
}