Files
envi-code/SourceCode/Code2026/CoreLibrary/AuxTools.cpp
T

1257 lines
31 KiB
C++
Raw Normal View History

2026-10-04 00:04:20 +08:00
#include "stdafx.h"
2026-09-28 15:28:50 +08:00
#include "AuxTools.h"
#include "math.h"
#include "KTCADUtilityEx.h"
#define ZERO_AIR 1.0e-6
namespace
{
AcGeCircArc3d getArc(ads_point spt, ads_point ept, double dang)
{
ads_real ddis = ads_distance(spt, ept) / 2.0;
ads_real dangTmp = fabs(dang / 2.0);
double dRadius = ddis / sin(dangTmp), dstartAngle, dendAngle;
ads_real dcosr = fabs(dRadius * cos(dangTmp));
ads_point ptc1, ptc2, mpt, ptCenter;
mpt[X] = spt[X] + ept[X];
mpt[Y] = spt[Y] + ept[Y];
mpt[Z] = spt[Z] + ept[Z];
mpt[X] *= .5;
mpt[Y] *= .5;
mpt[Z] *= .5;
ads_polar(mpt, ads_angle(spt, ept) - PI / 2.0, dcosr, ptc1);
ads_polar(mpt, ads_angle(spt, ept) + PI / 2.0, dcosr, ptc2);
if (dang > 0)
{
if (fabs(dang) > PI)
{
ptCenter[X] = ptc1[X];
ptCenter[Y] = ptc1[Y];
ptCenter[Z] = ptc1[Z];
}
else
{
ptCenter[X] = ptc2[X];
ptCenter[Y] = ptc2[Y];
ptCenter[Z] = ptc2[Z];
}
dstartAngle = ads_angle(ptCenter, spt);
dendAngle = ads_angle(ptCenter, ept);
}
else
{
if (fabs(dang) > PI)
{
ptCenter[X] = ptc2[X];
ptCenter[Y] = ptc2[Y];
ptCenter[Z] = ptc2[Z];
}
else
{
ptCenter[X] = ptc1[X];
ptCenter[Y] = ptc1[Y];
ptCenter[Z] = ptc1[Z];
}
dstartAngle = ads_angle(ptCenter, ept);
dendAngle = ads_angle(ptCenter, spt);
}
return AcGeCircArc3d(asPnt3d(ptCenter), AcGeVector3d::kZAxis, AcGeVector3d::kXAxis, dRadius, dstartAngle, dendAngle);
}
}
AcGePoint3d TAuxTools::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);
}
int TAuxTools::GetEllipseFromCircle( AcGePoint3d ptCenter, double dDia, AcGeVector3d vtOrigNormal,
AcGeVector3d vtNewNormal, AcDbPolyline &polyLine, AcGeVector3d vtGet)
{
vtOrigNormal.normalize();
vtNewNormal.normalize();
double dRadius = dDia * 0.5;
2026-10-04 00:04:20 +08:00
AcGePlane planStd; // 椭圆投影所在标准面
2026-09-28 15:28:50 +08:00
planStd.set(ptCenter, vtNewNormal);
AcGePoint3d ptPrj = AcGePoint3d::kOrigin.orthoProject(planStd);
planStd.set(ptPrj, vtNewNormal);
double dEle = ptPrj.asVector().length();
if (!ptPrj.asVector().isCodirectionalTo(planStd.normal()))
{
dEle *= -1.0;
}
2026-10-04 00:04:20 +08:00
if (vtNewNormal.isParallelTo(vtOrigNormal)) // 平行,还是圆
2026-09-28 15:28:50 +08:00
{
AcGePoint3d ptStart, ptEnd;
2026-10-04 00:04:20 +08:00
if (vtGet.length() < 1e-6) // 整个圆
2026-09-28 15:28:50 +08:00
{
AcGeVector3d vtPerl = vtOrigNormal.perpVector();
ptStart = ptCenter + dRadius * vtPerl;
ptEnd = ptCenter - dRadius * vtPerl;
polyLine.addVertexAt(0, ptStart.convert2d(planStd), 1.0);
polyLine.addVertexAt(1, ptEnd.convert2d(planStd), 1.0);
polyLine.setClosed(Adesk::kTrue);
}
2026-10-04 00:04:20 +08:00
else // 半个圆
2026-09-28 15:28:50 +08:00
{
AcGeVector3d vtPerl = vtGet.orthoProject(vtNewNormal);
vtPerl.rotateBy(-PI / 2, vtNewNormal);
vtPerl.normalize();
ptStart = ptCenter + dRadius * vtPerl;
ptEnd = ptCenter - dRadius * vtPerl;
polyLine.addVertexAt(0, ptStart.convert2d(planStd), 1);
polyLine.addVertexAt(1, ptEnd.convert2d(planStd), 0);
}
polyLine.setElevation(dEle);
polyLine.setNormal(vtNewNormal);
return 0;
}
2026-10-04 00:04:20 +08:00
else if (vtNewNormal.isPerpendicularTo(vtOrigNormal)) // 垂直情况, 为直线
2026-09-28 15:28:50 +08:00
{
AcGeVector3d vtCrossPerl = vtOrigNormal.crossProduct(vtNewNormal);
AcGePoint3d ptStart, ptEnd;
ptStart = ptCenter + dRadius * vtCrossPerl;
ptEnd = ptCenter - dRadius * vtCrossPerl;
polyLine.addVertexAt(0, ptStart.convert2d(planStd));
polyLine.addVertexAt(1, ptEnd.convert2d(planStd));
polyLine.setElevation(dEle);
polyLine.setNormal(vtNewNormal);
return 1;
}
2026-10-04 00:04:20 +08:00
else // 普通投影为椭圆情况
2026-09-28 15:28:50 +08:00
{
2026-10-04 00:04:20 +08:00
// 长/短轴向量
2026-09-28 15:28:50 +08:00
AcGeVector3d vtLong = vtOrigNormal.crossProduct(vtNewNormal);
vtLong.normalize();
AcGeVector3d vtShort = vtLong;
vtShort.rotateBy(PI * 0.5, vtOrigNormal);
AcGeVector3d vtPerp = vtOrigNormal.crossProduct(vtNewNormal);
vtPerp.normalize();
double dMinAngle = GetMinDiffAngle();
// dMinAngle *= 0.5;
int nPart = (int)(PI / dMinAngle) +1;
dMinAngle = PI / nPart;
AcGePoint3d ptNow;
AcGePoint3dArray arptsEdge;
if (vtGet.length() < 1e-6)
{
ptNow = ptCenter + vtPerp * dDia * 0.5;
for(int i = 0; i <= nPart*2; i++)
{
polyLine.addVertexAt(i, ptNow.convert2d(planStd));
ptNow.rotateBy(dMinAngle, vtOrigNormal, ptCenter);
}
}
else
{
vtGet = vtGet.orthoProject(vtNewNormal);
2026-10-04 00:04:20 +08:00
if (vtGet.angleTo(vtShort) < PI*0.5) // C 端部分
2026-09-28 15:28:50 +08:00
{
ptNow = ptCenter + vtPerp * dDia * 0.5;
for(int i = 0; i <= nPart; i++)
{
polyLine.addVertexAt(i, ptNow.convert2d(planStd));
ptNow.rotateBy(dMinAngle, vtOrigNormal, ptCenter);
}
}
2026-10-04 00:04:20 +08:00
else // D 端部分
2026-09-28 15:28:50 +08:00
{
ptNow = ptCenter - vtPerp * dDia * 0.5;
for(int i = 0; i <= nPart; i++)
{
polyLine.addVertexAt(i, ptNow.convert2d(planStd));
ptNow.rotateBy(dMinAngle, vtOrigNormal, ptCenter);
}
}
}
}
polyLine.setElevation(dEle);
polyLine.setNormal(vtNewNormal);
return 2;
}
void TAuxTools::GetArcPoint(AcDbPolyline &polyLine, AcGePoint3dArray &ptArcArr)
{
// if (polyLine.numVerts() != 4)
// return;
//
double dBugle(0.0);
polyLine.getBulgeAt(0, dBugle);
2026-10-04 00:04:20 +08:00
if (EQUAL_ZERO(dBugle - 1.0))// Polyline线是半个圆,或者圆
2026-09-28 15:28:50 +08:00
{
double dPar1, dPar2;
AcGePoint3d pt0, pt1, pt2, pt3, ptMid;
polyLine.getPointAt(0, pt0);
polyLine.getPointAt(1, pt1);
polyLine.getPointAt(2, pt2);
polyLine.getPointAt(3, pt3);
polyLine.getParamAtPoint(pt0, dPar1);
polyLine.getParamAtPoint(pt1, dPar2);
polyLine.getPointAtParam((dPar1 + dPar2)*0.5, ptMid);
ptArcArr.append(pt0);
ptArcArr.append(ptMid);
ptArcArr.append(pt1);
polyLine.getParamAtPoint(pt1, dPar1);
polyLine.getParamAtPoint(pt2, dPar2);
polyLine.getPointAtParam((dPar1 + dPar2)*0.5, ptMid);
ptArcArr.append(ptMid);
ptArcArr.append(pt2);
polyLine.getParamAtPoint(pt2, dPar1);
polyLine.getParamAtPoint(pt3, dPar2);
polyLine.getPointAtParam((dPar1 + dPar2)*0.5, ptMid);
ptArcArr.append(ptMid);
ptArcArr.append(pt3);
if (polyLine.isClosed())
{
polyLine.getParamAtPoint(pt3, dPar1);
polyLine.getEndParam(dPar2);
polyLine.getPointAtParam((dPar1 + dPar2)*0.5, ptMid);
ptArcArr.append(ptMid);
ptArcArr.append(pt0);
}
}
else
{
AcGePoint3d pt1;
for(int i = 0; i < polyLine.numVerts(); i++)
{
polyLine.getPointAt(i, pt1);
ptArcArr.append(pt1);
}
}
}
BOOL TAuxTools::GetPrjPtsFromCircle(AcGePoint3dArray& ptArr, AcGePoint3dArray& arPtJudge)
{
AcGeCircArc3d cir;
//XCircle cir;
AcGeVector3d vtTmp1, vtTmp2, vtCirNor;
AcGePoint3d ptCirCen, ptIn, ptU, ptD;
AcGePoint3dArray arPtSides;
AcGePlane plan;
int iRes(-1);
AcDbPolyline* pLine = new AcDbPolyline;
if (NULL == pLine)
return TRUE;
for (int i = 0; i < ptArr.length(); )
{
cir.set(ptArr[i], ptArr[i + 1], ptArr[i + 2]);
ptCirCen = cir.center();
vtTmp1 = ptArr[i + 1] - ptCirCen;
vtTmp2 = ptArr[i + 2] - ptCirCen;
2026-10-04 00:04:20 +08:00
// 分节圆法向
2026-09-28 15:28:50 +08:00
vtCirNor = vtTmp1.crossProduct(vtTmp2);
plan.set(ptCirCen, TAuxTools::GetUcsZvt());
iRes = TAuxTools::GetEllipseFromCircle(ptCirCen, cir.radius() * 2, vtCirNor, TAuxTools::GetUcsZvt(), *pLine, vtCirNor);
if (-1 == iRes)
{
if (NULL != pLine)
delete pLine;
return FALSE;
}
pLine->getPointAt(0, ptU);
pLine->getPointAt(pLine->numVerts() - 1, ptD);
plan.set(arPtJudge[i / 3], TAuxTools::GetUcsZvt());
ptU = ptU.orthoProject(plan);
ptD = ptD.orthoProject(plan);
if (ptD.distanceTo(arPtJudge[i / 3]) <= ptU.distanceTo(arPtJudge[i / 3]))
{
2026-10-04 00:04:20 +08:00
// 总是先添加距离ptArrCen[ i / 3]近的点
2026-09-28 15:28:50 +08:00
arPtSides.append(ptD);
arPtSides.append(ptU);
}
else
{
arPtSides.append(ptU);
arPtSides.append(ptD);
}
pLine->reset(Adesk::kFalse, iRes);
2026-10-04 00:04:20 +08:00
i = i + 3;// 每3个点确定一个面
2026-09-28 15:28:50 +08:00
}
if (NULL == pLine)
delete pLine;
arPtJudge.setLogicalLength(0);
arPtJudge.append(arPtSides);
return TRUE;
}
int TAuxTools::GetEllipsePtsFromCircle(AcGePoint3dArray& arPtsOnCurve, AcGePoint3d ptCenter, double dDia, AcGeVector3d vtOrigNormal,
AcGeVector3d vtNewNormal, AcDbPolyline &polyLine, AcGeVector3d vtGet/* = AcGeVector3d::kIdentity*/)
{
int iRes = TAuxTools::GetEllipseFromCircle(ptCenter, dDia, vtOrigNormal, vtNewNormal, polyLine, vtGet);
if (iRes != -1)
{
AcGePoint3d ptTemp, ptTemp1, ptTemp2;
double dPam1, dPam2;
AcGeVector3d vtDir;
AcGePlane plan;
switch (iRes)
{
default:
2026-10-04 00:04:20 +08:00
case 2:// 投影为椭圆
2026-09-28 15:28:50 +08:00
TAuxTools::GetArcPoint(polyLine, arPtsOnCurve);
break;
2026-10-04 00:04:20 +08:00
case 1:// 投影为直线
2026-09-28 15:28:50 +08:00
polyLine.getPointAt(0, ptTemp);
arPtsOnCurve.append(ptTemp);
polyLine.getPointAt(1, ptTemp);
arPtsOnCurve.append(ptTemp);
arPtsOnCurve.append(ptTemp);
break;
2026-10-04 00:04:20 +08:00
case 0:// 投影为圆
if (polyLine.isClosed())// 整个圆
2026-09-28 15:28:50 +08:00
{
polyLine.getPointAt(0, ptTemp1);
polyLine.getPointAt(1, ptTemp2);
polyLine.getParamAtPoint(ptTemp1, dPam1);
polyLine.getParamAtPoint(ptTemp2, dPam2);
polyLine.getPointAtParam((dPam1+dPam2)*0.5, ptTemp);
arPtsOnCurve.append(ptTemp1);
arPtsOnCurve.append(ptTemp);
arPtsOnCurve.append(ptTemp2);
vtDir = ptTemp1 - ptTemp2;
plan.set(TAuxTools::Mid(ptTemp1, ptTemp2), vtDir.rotateBy(PI * 0.5, vtNewNormal));
ptTemp.mirror(plan);
arPtsOnCurve.append(ptTemp);
arPtsOnCurve.append(ptTemp1);
}
2026-10-04 00:04:20 +08:00
else// 半个圆
2026-09-28 15:28:50 +08:00
{
polyLine.getPointAt(0, ptTemp1);
polyLine.getPointAt(1, ptTemp2);
polyLine.getParamAtPoint(ptTemp1, dPam1);
polyLine.getParamAtPoint(ptTemp2, dPam2);
polyLine.getPointAtParam((dPam1+dPam2)*0.5, ptTemp);
arPtsOnCurve.append(ptTemp1);
arPtsOnCurve.append(ptTemp);
arPtsOnCurve.append(ptTemp2);
}
break;
}
}
return iRes;
}
BOOL TAuxTools::MergerPline(AcDbPolyline* pPl,AcDbPolyline* pSrc)
{
AcGePoint3d ptStart,ptStart2;
AcGePoint3d ptEnd,ptEnd2;
pPl->getStartPoint(ptStart);
pPl->getEndPoint(ptEnd);
pSrc->getStartPoint(ptStart2);
pSrc->getEndPoint(ptEnd2);
AcGePoint2d pt2d;
double dBulge = -1;
2026-10-04 00:04:20 +08:00
if (ptStart.distanceTo(ptStart2) < 1.e-3) //sta 重合
2026-09-28 15:28:50 +08:00
{
int nVerts = pSrc->numVerts();
for (int i = 1;i < nVerts; i++)
{
pSrc->getPointAt(i, pt2d);
pSrc->getBulgeAt(i - 1, dBulge);
pPl->addVertexAt(0, pt2d, -dBulge);
}
}
else if (ptStart.distanceTo(ptEnd2) < 1.e-3) //end
{
int nVerts = pSrc->numVerts() - 1;
for (int i = nVerts; i > 0; i--)
{
pSrc->getPointAt(i - 1, pt2d);
pSrc->getBulgeAt(i - 1, dBulge);
pPl->addVertexAt(0, pt2d, dBulge);
}
}
2026-10-04 00:04:20 +08:00
else if (ptEnd.distanceTo(ptStart2) < 1.e-3) //sta 重合
2026-09-28 15:28:50 +08:00
{
int nVerts = pPl->numVerts();
for (int i = 1; i < (int)pSrc->numVerts(); i++)
{
pSrc->getPointAt(i, pt2d);
pSrc->getBulgeAt(i - 1, dBulge);
if (1 == i)
{
pPl->setBulgeAt(nVerts - 1, dBulge);
}
pPl->addVertexAt(nVerts, pt2d, dBulge);
nVerts++;
}
}
else if (ptEnd.distanceTo(ptEnd2) < 1.e-3) //end
{
int nVerts = pPl->numVerts();
for (int i = pSrc->numVerts() - 1; i > -1; i--)
{
pSrc->getPointAt(i, pt2d);
pSrc->getBulgeAt(i - 1, dBulge);
pPl->addVertexAt(nVerts, pt2d, -dBulge);
nVerts++;
}
}
2026-10-04 00:04:20 +08:00
// Lixl处理两条PLine线不同高度的情况
2026-09-28 15:28:50 +08:00
else
{
ptStart2.z = ptStart.z;
ptEnd2.z = ptEnd.z;
int nVerts = pPl->numVerts();
int nPlVerts = nVerts - 1;
if (ptEnd.distanceTo(ptStart2) < 1.e-3)
{
for (int i = 0; i < (int)pSrc->numVerts(); i++)
{
pSrc->getPointAt(i, pt2d);
pSrc->getBulgeAt(i, dBulge);
pPl->addVertexAt(nVerts, pt2d, dBulge);
nVerts++;
}
pPl->setBulgeAt(nPlVerts, 0);
}
else if (ptEnd.distanceTo(ptEnd2) < 1.e-3)
{
for (int i = pSrc->numVerts()-1; i >= 0; i--)
{
pSrc->getPointAt(i, pt2d);
pSrc->getBulgeAt(i-1, dBulge);
if (0 == i)
dBulge = 0.0;
pPl->addVertexAt(nVerts, pt2d, -dBulge);
nVerts++;
}
pPl->setBulgeAt(nPlVerts, 0);
}
}
return TRUE;
}
int TAuxTools::PositionOnLine(AcGePoint3d ptSta, AcGePoint3d ptEnd, AcGePoint3d ptBase)
{
AcGeVector3d vt = ptSta - ptEnd;
vt.normalize();
double dBS = ptBase.distanceTo(ptSta);
double dBE = ptBase.distanceTo(ptEnd);
double dSE = ptEnd.distanceTo(ptSta);
2026-10-04 00:04:20 +08:00
//在两个点中间位置
2026-09-28 15:28:50 +08:00
if (((dBS + dBE) - dSE) < 1.e-3 )
{
return 0;
}
else
{
2026-10-04 00:04:20 +08:00
//在S端左侧
2026-09-28 15:28:50 +08:00
if (dBS < dBE)
{
return 1;
}
2026-10-04 00:04:20 +08:00
//在E端右侧
2026-09-28 15:28:50 +08:00
else
{
return 2;
}
}
return -1;
}
BOOL TAuxTools::isCodirectionalPt(AcGePoint3d ptSta, AcGePoint3d ptEnd, AcGeVector3d vtBase)
{
AcGeVector3d vt = ptSta - ptEnd;
return vt.isCodirectionalTo(vtBase);
}
AcGePlane TAuxTools::GetHidePlane(AcGePoint3d pt1, AcGePoint3d pt2, AcGePoint3d pt3,
AcGeVector3d vtNormal, double &dEle)
{
AcGePlane plan(pt1, pt2, pt3);
AcGePoint3d ptOrth = AcGePoint3d::kOrigin.orthoProject(plan);
plan.set(ptOrth, vtNormal);
dEle = ptOrth.asVector().length();
if (!ptOrth.asVector().isCodirectionalTo(vtNormal))
dEle *= -1.0;
return plan;
}
BOOL TAuxTools::InsertBlock(AcDbVoidPtrArray& entitySet,AcDbObjectId idBlock, AcGePoint3d ptBase, AcGeScale3d ScaleFactor,double dAngle)
{
AcDbBlockReference blcRfr;
blcRfr.setNormal(AcGeVector3d::kZAxis);
blcRfr.setBlockTableRecord(idBlock);
blcRfr.setPosition(ptBase);
blcRfr.setRotation(dAngle);
blcRfr.setScaleFactors(ScaleFactor);
blcRfr.explode(entitySet);
return TRUE;
}
BOOL TAuxTools::GetIntersectWith(AcGePoint3d pt1,AcGePoint3d pt2,AcGePoint3d pt3,AcGePoint3d pt4,AcGePoint3d& ptIntersect)
{
AcGeLine3d line1,line2;
line1.set(pt1,pt2);
line2.set(pt3,pt4);
return line1.intersectWith(line2, ptIntersect);
}
int TAuxTools::Getquadrant(AcGePoint3d ptCenter, AcGePoint3d pt, AcGeVector3d vtMain, AcGeVector3d vtNormal)
{
AcGeVector3d vtBr = pt - ptCenter;
double dAngle = vtMain.angleTo(vtBr, vtNormal);
if (dAngle >= PI * 0.5 && dAngle < PI)
{
return 2;
}
else if (dAngle >= PI && dAngle < PI * 1.5)
{
return 3;
}
else if (dAngle >= PI * 1.5 && dAngle < PI * 2 )
{
return 4;
}
return 1;
}
2026-10-04 00:04:20 +08:00
// 用户X坐标向量
2026-09-28 15:28:50 +08:00
AcGeVector3d TAuxTools::GetUcsXvt()
{
AcGeVector3d vtX = AcGeVector3d::kXAxis;
AcDbDatabase* pDb = acdbCurDwg();
if (NULL != pDb)
vtX = pDb->ucsxdir();
return vtX;
}
AcGeVector3d TAuxTools::GetUcsYvt()
{
AcGeVector3d vtY = AcGeVector3d::kYAxis;
AcDbDatabase* pDb = acdbCurDwg();
if (NULL != pDb)
vtY = pDb->ucsydir();
return vtY;
}
AcGeVector3d TAuxTools::GetUcsZvt()
{
AcGeVector3d vtZ = AcGeVector3d::kZAxis;
AcDbDatabase* pDb = acdbCurDwg();
if (NULL != pDb)
vtZ = pDb->ucsxdir().crossProduct(pDb->ucsydir());
return vtZ;
}
2026-10-04 00:04:20 +08:00
// 圆管沿程阻力 dFricCoef摩擦系数 管径(mm)、管长(m)、密度(kg/m^3)和流速(m/s)计算沿程阻力(Pa)
2026-09-28 15:28:50 +08:00
double TAuxTools::CalCircleFricLoss(double dFricCoef, double dDia, double dLength,
double dDensity, double dVelocity)
{
if ((dFricCoef < ZERO_AIR) || (dDia < ZERO_AIR) || (dLength < 0)
|| (dDensity < ZERO_AIR) || (dVelocity < 0))
return 0.0;
return dFricCoef * dLength * dDensity * pow(dVelocity, 2) / (0.002 * dDia);
}
2026-10-04 00:04:20 +08:00
// 根据粗糙度(mm)、流速当量直径(mm)和雷诺数计算摩擦系数, 用柯列勃洛克-怀特公式计算
2026-09-28 15:28:50 +08:00
double TAuxTools::CalFricCoef(double dRough, double dCalDia, double dRe)
{
if ((dRough < 0.0) || (dCalDia < ZERO_AIR) || (dRe < ZERO_AIR))
return ZERO_AIR;
if (dRe < 2000)
return 64 / dRe;
2026-10-04 00:04:20 +08:00
double dA, dB; // 系数a, b
2026-09-28 15:28:50 +08:00
dA = dRough / (3.7 * dCalDia);
dB = 2.51 / dRe;
2026-10-04 00:04:20 +08:00
double dNewX, dOldX; // 用于迭代计算的新旧数据 =1/(FricCoef)^0.5
dNewX = 5.0; // 初始值为5
2026-09-28 15:28:50 +08:00
2026-10-04 00:04:20 +08:00
double e = 1.0; // 两次迭代之差
2026-09-28 15:28:50 +08:00
double t = 0.0;
2026-10-04 00:04:20 +08:00
int nFlag = 0; // 控制最大迭代次数
2026-09-28 15:28:50 +08:00
while ((e > 0.0001) && (nFlag < 100))
{
dOldX = dNewX;
t = dA + dB * dOldX;
if (t < ZERO_AIR)
2026-10-04 00:04:20 +08:00
return 0.0; // 认为无解
2026-09-28 15:28:50 +08:00
dNewX = dOldX - (dOldX + 2 * log10(t)) * (t) * log(10.0) / ((t) * log(10.0) + 2 * dB);
e = fabs(dNewX - dOldX);
nFlag++;
}
if (nFlag >= 100)
2026-10-04 00:04:20 +08:00
return 0.0; // 认为无解
2026-09-28 15:28:50 +08:00
return 1 / pow(dNewX, 2);
}
2026-10-04 00:04:20 +08:00
// 根据管宽(mm)和管高(mm)计算流速当量直径(mm)
2026-09-28 15:28:50 +08:00
double TAuxTools::CalVelDia(double dWidth, double dHeight)
{
if ((dWidth < ZERO_AIR) || (dHeight < ZERO_AIR))
return 0.0;
return 2 * dWidth * dHeight / (dWidth + dHeight);
}
2026-10-04 00:04:20 +08:00
// 流速(m/s)、流速当量直径(mm)和黏度(m^2/s)计算雷诺数
2026-09-28 15:28:50 +08:00
double TAuxTools::CalRe(double dVelocity, double dVelDia, double dMoveVis)
{
if ((dVelocity < 0.0) || (dVelDia < ZERO_AIR) || (dMoveVis < 1.0e-10))
return ZERO_AIR;
return dVelocity * 0.001 * dVelDia / dMoveVis;
}
double TAuxTools::CalDesity(double dTemperature)
{
double dDensity[15] = {1.293, 1.270, 1.248, 1.226, 1.205,
1.185, 1.165, 1.146, 1.128, 1.093,
1.060, 1.029, 1.000, 0.973, 0.947};
double dTem[15] = {0, 5, 10, 15, 20,
25, 30, 35, 40, 50,
60, 70, 80, 90, 100};
return CalTable(dTem, (double*)dDensity, dTemperature, 15);
}
double TAuxTools::CalMoveVis(double dTemperature)
{
double dMovVis[18] = {13.7, 14.7, 15.7, 16.6, 17.6,
18.6, 19.6, 20.5, 21.7, 22.9,
23.6, 26.2, 28.5, 30.6, 33.2,
35.8, 42.8, 49.9};
double dTem[18] = {0, 10, 20, 30, 40,
50, 60, 70, 80, 90,
100, 120, 140, 160, 180,
200, 250, 300};
return CalTable(dTem, (double*)dMovVis, dTemperature, 18) * 1.0e-6;
}
/*----------------------------------------------------------------------------*
2026-10-04 00:04:20 +08:00
* 功能描述: 用插值法从一维表格中取值
* 备 注: dAbscissa为表头;共m列数据;dX表示列值;表头升序
2026-09-28 15:28:50 +08:00
-----------------------------------------------------------------------------*/
double TAuxTools::CalTable(double dAbscissa[], double *pTable, double dX, int m)
{
if (dX < dAbscissa[0])
dX = dAbscissa[0];
else if (dX > dAbscissa[m - 1])
dX = dAbscissa[m - 1];
for(int i = 0; i < m; i++)
{
2026-10-04 00:04:20 +08:00
if (dAbscissa[i] == dAbscissa[i - 1]) // 与前一个表头相等
2026-09-28 15:28:50 +08:00
continue;
2026-10-04 00:04:20 +08:00
if (dX == dAbscissa[i]) // 等于某个表头
2026-09-28 15:28:50 +08:00
return pTable[i];
2026-10-04 00:04:20 +08:00
else if (dX < dAbscissa[i]) // 小于某个表头,用查值
2026-09-28 15:28:50 +08:00
return (pTable[i] - pTable[i - 1])*(dX - dAbscissa[i - 1])
/ (dAbscissa[i] - dAbscissa[i - 1]) + pTable[i - 1];
}
return 0.0;
}
//////////////////////////////////////////////////////////////////////////
2026-10-04 00:04:20 +08:00
// 获得字体样式表
2026-09-28 15:28:50 +08:00
void TAuxTools::GetAllTextStyleNameArray(CStringArray& arTextStyle)
{
AcDbTextStyleTable* pTextStyleTbl = NULL;
AcDbTextStyleTableRecord* pTextStyleTblRec = NULL;
if (acdbHostApplicationServices()->workingDatabase() \
->getTextStyleTable(pTextStyleTbl, AcDb::kForRead) == Acad::eOk)
{
2026-10-04 00:04:20 +08:00
// 文字样式表记录
2026-09-28 15:28:50 +08:00
AcDbTextStyleTableIterator* pIterator = NULL;
if (pTextStyleTbl->newIterator(pIterator) == Acad::eOk)
{
for (pIterator->start(); !pIterator->done(); pIterator->step())
{
if (pIterator->getRecord(pTextStyleTblRec, AcDb::kForRead) == Acad::eOk)
{
LPCTSTR pszName = NULL;
pTextStyleTblRec->getName(pszName);
arTextStyle.Add(pszName);
pTextStyleTblRec->close();
}
}
delete pIterator;
}
pTextStyleTbl->close();
}
}
double TAuxTools::GetMinDiffAngle()
{
return PI/12;
}
void TAuxTools::BuildMinRectangle(const AcGePoint3dArray& arpt, AcDbExtents& ext)
{
int iLen = arpt.length();
if (0 == iLen)
{
return;
}
double dMaxX = arpt[0].x;
double dMaxY = arpt[0].y;
double dMaxZ = arpt[0].z;
double dMinX = dMaxX;
double dMinY = dMaxY;
double dMinZ = dMaxZ;
for (int i = 0; i < iLen; ++i)
{
if (dMaxX < arpt[i].x)
{
dMaxX = arpt[i].x;
}
if (dMaxY < arpt[i].y)
{
dMaxY = arpt[i].y;
}
if (dMaxZ < arpt[i].z)
{
dMaxZ = arpt[i].z;
}
if (dMinX > arpt[i].x)
{
dMinX = arpt[i].x;
}
if (dMinY > arpt[i].y)
{
dMinY = arpt[i].y;
}
if (dMinZ > arpt[i].z)
{
dMinZ = arpt[i].z;
}
}
AcGePoint3d ptMax(dMaxX,dMaxY,dMaxZ);
AcGePoint3d ptMin(dMinX,dMinY,dMinZ);
ext.set(ptMin,ptMax);
}
BOOL TAuxTools::IsAutoWorkOffset()
{
BOOL bAuto(FALSE);
//GetGlobalContext(HVAC_AUTOOFFSET, bAuto);
return bAuto;
}
BOOL TAuxTools::IsAutoWorkConnect()
{
BOOL bAuto(FALSE);
//GetGlobalContext(HVAC_AUTOCONNECT, bAuto);
return bAuto;
}
BOOL TAuxTools::IsAutoWorkSize()
{
BOOL bAuto(FALSE);
//GetGlobalContext(HVAC_AUTOSIZE, bAuto);
return bAuto;
}
void TAuxTools::BuildRecFace(const AcGePoint3d& pt, const double dWidth, const double dThick,
const AcGeVector3d& vtNormal, const AcGeVector3d& vtFaceNormal, AcDbVoidPtrArray& dbPtArr)
{
2026-10-04 00:04:20 +08:00
// 获得侧方向
2026-09-28 15:28:50 +08:00
AcGeVector3d vtSide = vtFaceNormal;
vtSide.rotateBy(PI / 2.0, vtNormal);
vtSide.normalize();
2026-10-04 00:04:20 +08:00
// 添加面
2026-09-28 15:28:50 +08:00
double dHalfWidth = dWidth / 2.0;
double dHalfThick = dThick / 2.0;
AcGePoint3d arpt[4];
arpt[0] = pt + vtSide * dHalfWidth + vtNormal * dHalfThick;
arpt[1] = pt + vtSide * dHalfWidth - vtNormal * dHalfThick;
arpt[2] = pt - vtSide * dHalfWidth - vtNormal * dHalfThick;
arpt[3] = pt - vtSide * dHalfWidth + vtNormal * dHalfThick;
dbPtArr.append(new AcDbFace(arpt[0], arpt[1], arpt[2], arpt[3]));
}
void TAuxTools::BuildCirFace(const AcGePoint3d& pt, const double dDiameter, const AcGeVector3d& vtNormal,
const AcGeVector3d& vtFaceNormal, AcDbVoidPtrArray& dbPtArr)
{
2026-10-04 00:04:20 +08:00
// 获得侧方向
2026-09-28 15:28:50 +08:00
AcGeVector3d vtRot = vtNormal;
vtRot.normalize();
double dRadius = dDiameter / 2.0;
AcGePoint3d arpt[6];
for (int i = 0; i < 6; ++i)
{
arpt[i] = pt + vtRot * dRadius;
vtRot.rotateBy(PI / 3.0, vtFaceNormal);
}
dbPtArr.append(new AcDbFace(arpt[0], arpt[1], arpt[2], arpt[3]));
dbPtArr.append(new AcDbFace(arpt[3], arpt[4], arpt[5], arpt[0]));
}
2026-10-04 00:04:20 +08:00
// 获取面标高, 零点距到零点投影到该面的垂点的长度
2026-09-28 15:28:50 +08:00
double TAuxTools::GetPlaneEle( const AcGePlane &plan )
{
AcGePoint3d ptOrth = AcGePoint3d::kOrigin.orthoProject(plan);
double dEle = ptOrth.asVector().length();
AcGeVector3d vtZAxis(TAuxTools::GetUcsZvt());
if (!ptOrth.asVector().isCodirectionalTo(plan.normal()))
dEle *= -1.0;
return dEle;
}
2026-10-04 00:04:20 +08:00
// 通过id获取文字样式名
2026-09-28 15:28:50 +08:00
TCHAR* TAuxTools::GetFontStyle(AcDbObjectId idTextStyle)
{
AcDbTextStyleTableRecord* pTTR;
if (acdbOpenObject(pTTR, idTextStyle, AcDb::kForRead) != Acad::eOk)
return NULL;
TCHAR* pName = NULL;
if (pTTR->getName(pName) != Acad::eOk)
{
pTTR->close();
return NULL;
}
pTTR->close();
return pName;
}
2026-10-04 00:04:20 +08:00
// 判断点pt3与pt1和pt2的位置关系。0-不共线;1--在pt1外;2--同pt1;3--在pt1和pt2之间;4--同pt2;5--在pt2外
2026-09-28 15:28:50 +08:00
int TAuxTools::CalPosBy3Point(const AcGePoint3d& pt1, const AcGePoint3d& pt2, const AcGePoint3d& pt3)
{
if (pt3 == pt1)
return 2;
if (pt3 == pt2)
return 4;
AcGeVector3d vt13, vt23;
vt13 = pt3 - pt1;
vt23 = pt3 - pt2;
2026-10-04 00:04:20 +08:00
if (!vt13.isParallelTo(vt23)) // 不共线
2026-09-28 15:28:50 +08:00
return 0;
if (vt13.isCodirectionalTo(vt23))
{
if (pt3.distanceTo(pt1) < pt3.distanceTo(pt2))
return 1;
else
return 5;
}
else
{
return 3;
}
return -1;
}
BOOL TAuxTools::Is2DView()
{
BOOL b2D(FALSE);
struct resbuf rb = {NULL, RT3DPOINT, 0};
acedGetVar(_T("VIEWDIR"), &rb);
AcGeVector3d vtDir = asVec3d(rb.resval.rpoint);
if ((vtDir.isCodirectionalTo(AcGeVector3d::kZAxis)
&& TAuxTools::GetUcsZvt().isCodirectionalTo(AcGeVector3d::kZAxis)))
{
b2D = TRUE;
}
return b2D;
}
void TAuxTools::DoubleToString( double dValue, int nPreci, CString &csValue )
{
CString csPreci;
csPreci.Format(_T("%d"), nPreci);
csValue.Format(_T("%.") + csPreci + _T("f"), dValue);
}
AcDbObjectId TAuxTools::GetProjBlockId(const AcDbObjectId& idSrc, AcGeVector3d vtNor,
AcGeVector3d vtMain, AcGeVector3d vtPlaneSec,
AcGeScale3d& scale, AcDbExtents* pExt)
{
2026-10-04 00:04:20 +08:00
// 图块正方向
2026-09-28 15:28:50 +08:00
AcGeVector3d vtFront = vtNor.crossProduct(vtMain);
2026-10-04 00:04:20 +08:00
// 正方向与投影方向的角度
2026-09-28 15:28:50 +08:00
double dProjAng = vtFront.angleTo(vtPlaneSec, vtNor);
2026-10-04 00:04:20 +08:00
// 是否镜像
2026-09-28 15:28:50 +08:00
BOOL bMirror = (PI / 2 < dProjAng && PI * 1.5 > dProjAng);
2026-10-04 00:04:20 +08:00
// 旋转轴
2026-09-28 15:28:50 +08:00
AcGeVector3d vtAxis = vtPlaneSec.crossProduct(vtNor);
2026-10-04 00:04:20 +08:00
// 旋转角度
2026-09-28 15:28:50 +08:00
double dAngle = vtNor.angleTo(vtPlaneSec, bMirror ? -vtAxis : vtAxis);
2026-10-04 00:04:20 +08:00
// 矩阵
2026-09-28 15:28:50 +08:00
AcGeMatrix3d matNor, matHorz, matMirr;
matNor.setToRotation(dAngle, vtAxis, AcGePoint3d::kOrigin);
matHorz.setToRotation(-dProjAng, AcGeVector3d::kZAxis, AcGePoint3d::kOrigin);
matMirr.setToRotation(PI, AcGeVector3d::kXAxis, AcGePoint3d::kOrigin);
2026-10-04 00:04:20 +08:00
// 新图块ID
2026-09-28 15:28:50 +08:00
AcDbObjectId idNew = AcDbObjectId::kNull;
2026-10-04 00:04:20 +08:00
// 原始图块旋转之后的尺寸
2026-09-28 15:28:50 +08:00
AcGeScale3d scaOrg(1, 1, 1);
2026-10-04 00:04:20 +08:00
// 生成图块名
2026-09-28 15:28:50 +08:00
CString csBlkName;
OPENOBJ_BEGIN(idSrc, AcDb::kForRead, AcDbBlockTableRecord, pBlkRec);
if(NULL != pBlkRec)
{
TCHAR* pName = NULL;
pBlkRec->getName(pName);
csBlkName.Format(_T("%s_%d%d%d%.6f%.6f%.6f"), pName, bMirror, (int)(dAngle * 180 / PI),
(int)(dProjAng * 180 / PI), vtAxis.x, vtAxis.y, vtAxis.z);
}
else
{
return AcDbObjectId::kNull;
}
OPENOBJ_END();
AcDbBlockTable* pBlkTbl = NULL;
acdbCurDwg()->getBlockTable(pBlkTbl, AcDb::kForWrite);
if(NULL == pBlkTbl)
return AcDbObjectId::kNull;
AcGePoint3d ptMax, ptMin;
2026-10-04 00:04:20 +08:00
if(pBlkTbl->has(csBlkName)) // 块存在
2026-09-28 15:28:50 +08:00
{
pBlkTbl->getAt(csBlkName, idNew);
OPENOBJ_BEGIN(idNew, AcDb::kForRead, AcDbBlockTableRecord, pBlkOld);
if(NULL != pBlkOld)
{
AcDbExtents ext;
ext.addBlockExt(pBlkOld);
ptMax = ext.maxPoint();
ptMin = ext.minPoint();
scaOrg.set(ptMax.x - ptMin.x, ptMax.y - ptMin.y, ptMax.z - ptMin.z);
}
OPENOBJ_END();
}
else
{
2026-10-04 00:04:20 +08:00
// 插入新图块
2026-09-28 15:28:50 +08:00
AcDbBlockTableRecord* pBlkNew = new AcDbBlockTableRecord;
pBlkTbl->add(idNew, pBlkNew);
pBlkNew->setName(csBlkName);
AcDbBlockReference* pBlkRef = new AcDbBlockReference(AcGePoint3d::kOrigin , idSrc);
pBlkRef->transformBy(matNor);
pBlkRef->transformBy(matHorz);
if(bMirror)
pBlkRef->transformBy(matMirr);
AcDbVoidPtrArray ptrArr;
pBlkRef->explode(ptrArr);
for(int i = 0; i < ptrArr.length(); i++)
{
AcDbEntity* pEnt = AcDbEntity::cast((AcDbEntity*)ptrArr[i]);
if(NULL != pEnt)
{
pBlkNew->appendAcDbEntity(pEnt);
pEnt->close();
}
}
delete pBlkRef;
2026-10-04 00:04:20 +08:00
// 取得图块尺寸
2026-09-28 15:28:50 +08:00
AcDbExtents ext;
ext.addBlockExt(pBlkNew);
ptMax = ext.maxPoint();
ptMin = ext.minPoint();
scaOrg.set(ptMax.x - ptMin.x, ptMax.y - ptMin.y, ptMax.z - ptMin.z);
2026-10-04 00:04:20 +08:00
// 设置图块插入点
2026-09-28 15:28:50 +08:00
//AcGePoint3d ptOrigin = Mid(ptMax, ptMin);
//ptOrigin.y = ptMin.y;
//pBlkNew->setOrigin(ptOrigin);
pBlkNew->close();
}
2026-10-04 00:04:20 +08:00
// 计算新图块比例
2026-09-28 15:28:50 +08:00
AcDbObjectId idTemp;
AcDbBlockTableRecord* pBlkSca = new AcDbBlockTableRecord;
pBlkTbl->add(idTemp, pBlkSca);
pBlkTbl->close();
AcDbBlockReference* pBlkRefSca = new AcDbBlockReference(AcGePoint3d::kOrigin , idSrc);
pBlkRefSca->setScaleFactors(scale);
pBlkRefSca->transformBy(matNor);
pBlkRefSca->transformBy(matHorz);
if(bMirror)
pBlkRefSca->transformBy(matMirr);
AcDbVoidPtrArray ptrArr;
pBlkRefSca->explode(ptrArr);
for(int i = 0; i < ptrArr.length(); i++)
{
AcDbEntity* pEnt = AcDbEntity::cast((AcDbEntity*)ptrArr[i]);
if(NULL != pEnt)
{
pBlkSca->appendAcDbEntity(pEnt);
pEnt->close();
}
}
delete pBlkRefSca;
2026-10-04 00:04:20 +08:00
// 取得新图块尺寸
2026-09-28 15:28:50 +08:00
AcDbExtents extSca;
extSca.addBlockExt(pBlkSca);
ptMax = extSca.maxPoint();
ptMin = extSca.minPoint();
if(NULL != pExt)
pExt->addExt(extSca);
scale.set((ptMax.x - ptMin.x) / scaOrg[X],
(ptMax.y - ptMin.y) / scaOrg[Y],
(ptMax.z - ptMin.z) / scaOrg[Z]);
pBlkSca->erase();
pBlkSca->close();
return idNew;
}
BOOL TAuxTools::IsIncline(AcGeVector3d& vt)
{
AcDbDatabase* pDb = acdbCurDwg();
if (NULL == pDb)
return FALSE;
AcGeVector3d vtZAxis(pDb->ucsxdir().crossProduct(pDb->ucsydir()));
return !vt.isParallelTo(vtZAxis) && !vt.isPerpendicularTo(vtZAxis);
}
void TAuxTools::Matrix3D2String( const AcGeMatrix3d &mat, CString &str )
{
#if ARX <= 15
std::ostringstream stream;
#else
std::wostringstream stream;
#endif
for (int ln = 0; ln < 4; ++ln)
{
for (int col = 0; col < 4; ++col)
{
stream<<mat.entry[ln][col];
#if ARX <= 15
stream << " ";
#else
stream << L" ";
#endif
}
}
str = stream.str().c_str();
}
double TAuxTools::CalCurvature(const AcGePoint3d& pt1, const AcGePoint3d& pt2,
const AcGePoint3d& pt3, const AcGeVector3d* pVtNor)
{
AcGeVector3d vtUseZAixs = AcGeVector3d::kIdentity;
if(NULL == pVtNor)
{
AcDbDatabase* pDb = acdbCurDwg();
if (NULL != pDb)
vtUseZAixs = pDb->ucsxdir().crossProduct(pDb->ucsydir());
}
else
{
vtUseZAixs = *pVtNor;
}
AcGeCircArc3d arc(pt1, pt2, pt3);
double dBulge = tan((arc.endAng() - arc.startAng()) * 0.25);
AcGeVector3d vtMid = pt2 - pt1;
AcGeVector3d vtEnd = pt3 - pt1;
AcGeVector3d vtCross = vtMid.crossProduct(vtEnd);
if (!vtCross.isCodirectionalTo(vtUseZAixs))
dBulge *= -1;
return dBulge;
}
LPCTSTR TAuxTools::GetBlkNameById (AcDbObjectId id)
{
AcDbObject* pObj = NULL;
if (Acad::eOk != acdbOpenObject(pObj, id, AcDb::kForRead))
{
return NULL;
}
if (!pObj->isKindOf(AcDbBlockTableRecord::desc()))
{
pObj->close();
return NULL;
}
AcDbBlockTableRecord* pRec = AcDbBlockTableRecord::cast(pObj);
ACHAR* pCh = NULL;
pRec->getName(pCh);
pRec->close();
pObj->close();
return pCh;
}
2026-10-04 00:04:20 +08:00
// add by dyc on 2014-01-21 解决Y型三通在比较大坐标值情况下以后后变成T型问题,求两圆交点
2026-09-28 15:28:50 +08:00
BOOL TAuxTools::CircleInsertWith(const AcGeCircArc3d& circleS, const AcGeCircArc3d& circleE,
AcGePoint3d& ptInter1, AcGePoint3d& ptInter2)
{
AcGePoint3d ptCentS = circleS.center();
AcGePoint3d ptCentE = circleE.center();
double dRS = circleS.radius();
double dRE = circleE.radius();
double dSumR = dRS + dRE;
double dDistanceES = ptCentS.distanceTo(ptCentE);
AcGeVector3d vtES = ptCentE - ptCentS;
BOOL bInsert = FALSE;
vtES.normalize();
AcGePoint3d ptInsert;
if(dDistanceES > dSumR)
return bInsert;
else if(fabs(dDistanceES - dSumR) <= 1e-6)
{
ptInsert = ptCentS + vtES * dRS;
ptInter1 = ptInter2 = ptInsert;
bInsert = TRUE;
}
else
{
double dLeftLength = (pow(dRS, 2) - pow(dRE, 2) + pow(dDistanceES, 2)) / (2 * dDistanceES);
double dUpLength = sqrt(pow(dRS, 2) - pow(dLeftLength, 2));
double dDownLength = dUpLength;
ptInsert = ptCentS + vtES * dLeftLength;
vtES.rotateBy(PI * 0.5, AcGeVector3d::kZAxis);
ptInter1 = ptInsert + vtES * dUpLength;
ptInter2 = ptInsert - vtES * dDownLength;
bInsert = TRUE;
}
return bInsert;
}
int TAuxTools::StrTokenize(LPCTSTR pszSrc, LPCTSTR pszDelimit, CStringArray& arSubs)
{
if(NULL == pszSrc || NULL == pszDelimit)
return 0;
CString sText = pszSrc;
LPTSTR pszSub = _tcstok(sText.GetBuffer(0), pszDelimit);
while(NULL != pszSub)
{
arSubs.Add(pszSub);
pszSub = _tcstok(NULL, pszDelimit);
}
sText.ReleaseBuffer();
return (int)arSubs.GetSize();
}
BOOL TAuxTools::IsVerticalLine(AcGePoint3d pt1, AcGePoint3d pt2)
{
AcGeVector3d vt = pt2 - pt1;
return fabs(vt.x) < 1.0E-6 && fabs(vt.y) < 1.0E-6;
}
void TAuxTools::Poly2CurveSeg(AcDbPolyline* pLine, std::vector<AcGeCurve3d*>& segComs)
{
if (NULL == pLine)
return;
AcGePoint3d pt1, pt2;
double dBugle(0.0), dAng(0.0);
for (int i = 0; i <= (int)pLine->numVerts() - 2; i++)
{
pLine->getPointAt(i, pt1);
pLine->getBulgeAt(i, dBugle);
pLine->getPointAt(i + 1, pt2);
2026-10-04 00:04:20 +08:00
// 直线
2026-09-28 15:28:50 +08:00
if (EQUAL_ZERO(dBugle))
{
segComs.push_back(new AcGeLine3d(pt1, pt2));
}
2026-10-04 00:04:20 +08:00
// 此段为弧线
2026-09-28 15:28:50 +08:00
else
{
2026-10-04 00:04:20 +08:00
// 计算角度
2026-09-28 15:28:50 +08:00
dAng = atan(dBugle) * 4;
segComs.push_back(new AcGeCircArc3d(getArc(asDblArray(pt1), asDblArray(pt2), dAng)));
}
}
if (pLine->isClosed())
{
dBugle = 0.0;
pLine->getPointAt(pLine->numVerts() - 1, pt1);
pLine->getPointAt(0, pt2);
pLine->getBulgeAt(pLine->numVerts() - 1, dBugle);
if (EQUAL_ZERO(dBugle))
segComs.push_back(new AcGeLine3d(pt1, pt2));
else
{
dAng = atan(dBugle) * 4;
segComs.push_back(new AcGeCircArc3d(getArc(asDblArray(pt1), asDblArray(pt2), dAng)));
}
}
}
double TAuxTools::GetBulge(AcGePoint3d ptStart, AcGePoint3d ptMid, AcGePoint3d ptEnd)
{
AcGeCircArc3d arc(ptStart, ptMid, ptEnd);
double dSubAngle = arc.endAng() - arc.startAng();
double dBulge = tan(dSubAngle * 0.25);
AcGeVector3d vtMid = ptMid - ptStart;
AcGeVector3d vtE = ptEnd - ptStart;
AcGeVector3d vtCross = vtMid.crossProduct(vtE);
if (!vtCross.isCodirectionalTo(TAuxTools::GetUcsZvt()))
dBulge *= -1;
return dBulge;
}