Files
envi-code/SourceCode/Code2026/CoreLibrary/AuxTools.cpp
T
2026-09-28 15:28:50 +08:00

1258 lines
31 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "stdafx.h"
#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;
AcGePlane planStd; // 椭圆投影所在标准面
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;
}
if (vtNewNormal.isParallelTo(vtOrigNormal)) // 平行,还是圆
{
AcGePoint3d ptStart, ptEnd;
if (vtGet.length() < 1e-6) // 整个圆
{
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);
}
else // 半个圆
{
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;
}
else if (vtNewNormal.isPerpendicularTo(vtOrigNormal)) // 垂直情况, 为直线
{
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;
}
else // 普通投影为椭圆情况
{
// 长/短轴向量
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);
if (vtGet.angleTo(vtShort) < PI*0.5) // C 端部分
{
ptNow = ptCenter + vtPerp * dDia * 0.5;
for(int i = 0; i <= nPart; i++)
{
polyLine.addVertexAt(i, ptNow.convert2d(planStd));
ptNow.rotateBy(dMinAngle, vtOrigNormal, ptCenter);
}
}
else // D 端部分
{
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);
if (EQUAL_ZERO(dBugle - 1.0))// Polyline线是半个圆,或者圆
{
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;
// 分节圆法向
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]))
{
// 总是先添加距离ptArrCen[ i / 3]近的点
arPtSides.append(ptD);
arPtSides.append(ptU);
}
else
{
arPtSides.append(ptU);
arPtSides.append(ptD);
}
pLine->reset(Adesk::kFalse, iRes);
i = i + 3;// 每3个点确定一个面
}
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:
case 2:// 投影为椭圆
TAuxTools::GetArcPoint(polyLine, arPtsOnCurve);
break;
case 1:// 投影为直线
polyLine.getPointAt(0, ptTemp);
arPtsOnCurve.append(ptTemp);
polyLine.getPointAt(1, ptTemp);
arPtsOnCurve.append(ptTemp);
arPtsOnCurve.append(ptTemp);
break;
case 0:// 投影为圆
if (polyLine.isClosed())// 整个圆
{
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);
}
else// 半个圆
{
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;
if (ptStart.distanceTo(ptStart2) < 1.e-3) //sta 重合
{
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);
}
}
else if (ptEnd.distanceTo(ptStart2) < 1.e-3) //sta 重合
{
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++;
}
}
// Lixl处理两条PLine线不同高度的情况
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);
//在两个点中间位置
if (((dBS + dBE) - dSE) < 1.e-3 )
{
return 0;
}
else
{
//在S端左侧
if (dBS < dBE)
{
return 1;
}
//在E端右侧
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;
}
// 用户X坐标向量
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;
}
// 圆管沿程阻力 dFricCoef摩擦系数 管径(mm)、管长(m)、密度(kg/m^3)和流速(m/s)计算沿程阻力(Pa)
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);
}
// 根据粗糙度(mm)、流速当量直径(mm)和雷诺数计算摩擦系数, 用柯列勃洛克-怀特公式计算
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;
double dA, dB; // 系数a, b
dA = dRough / (3.7 * dCalDia);
dB = 2.51 / dRe;
double dNewX, dOldX; // 用于迭代计算的新旧数据 =1/(FricCoef)^0.5
dNewX = 5.0; // 初始值为5
double e = 1.0; // 两次迭代之差
double t = 0.0;
int nFlag = 0; // 控制最大迭代次数
while ((e > 0.0001) && (nFlag < 100))
{
dOldX = dNewX;
t = dA + dB * dOldX;
if (t < ZERO_AIR)
return 0.0; // 认为无解
dNewX = dOldX - (dOldX + 2 * log10(t)) * (t) * log(10.0) / ((t) * log(10.0) + 2 * dB);
e = fabs(dNewX - dOldX);
nFlag++;
}
if (nFlag >= 100)
return 0.0; // 认为无解
return 1 / pow(dNewX, 2);
}
// 根据管宽(mm)和管高(mm)计算流速当量直径(mm)
double TAuxTools::CalVelDia(double dWidth, double dHeight)
{
if ((dWidth < ZERO_AIR) || (dHeight < ZERO_AIR))
return 0.0;
return 2 * dWidth * dHeight / (dWidth + dHeight);
}
// 流速(m/s)、流速当量直径(mm)和黏度(m^2/s)计算雷诺数
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;
}
/*----------------------------------------------------------------------------*
* 功能描述: 用插值法从一维表格中取值
* 备 注: dAbscissa为表头;共m列数据;dX表示列值;表头升序
-----------------------------------------------------------------------------*/
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++)
{
if (dAbscissa[i] == dAbscissa[i - 1]) // 与前一个表头相等
continue;
if (dX == dAbscissa[i]) // 等于某个表头
return pTable[i];
else if (dX < dAbscissa[i]) // 小于某个表头,用查值
return (pTable[i] - pTable[i - 1])*(dX - dAbscissa[i - 1])
/ (dAbscissa[i] - dAbscissa[i - 1]) + pTable[i - 1];
}
return 0.0;
}
//////////////////////////////////////////////////////////////////////////
// 获得字体样式表
void TAuxTools::GetAllTextStyleNameArray(CStringArray& arTextStyle)
{
AcDbTextStyleTable* pTextStyleTbl = NULL;
AcDbTextStyleTableRecord* pTextStyleTblRec = NULL;
if (acdbHostApplicationServices()->workingDatabase() \
->getTextStyleTable(pTextStyleTbl, AcDb::kForRead) == Acad::eOk)
{
// 文字样式表记录
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)
{
// 获得侧方向
AcGeVector3d vtSide = vtFaceNormal;
vtSide.rotateBy(PI / 2.0, vtNormal);
vtSide.normalize();
// 添加面
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)
{
// 获得侧方向
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]));
}
// 获取面标高, 零点距到零点投影到该面的垂点的长度
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;
}
// 通过id获取文字样式名
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;
}
// 判断点pt3与pt1和pt2的位置关系。0-不共线;1--在pt1外;2--同pt1;3--在pt1和pt2之间;4--同pt2;5--在pt2外
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;
if (!vt13.isParallelTo(vt23)) // 不共线
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)
{
// 图块正方向
AcGeVector3d vtFront = vtNor.crossProduct(vtMain);
// 正方向与投影方向的角度
double dProjAng = vtFront.angleTo(vtPlaneSec, vtNor);
// 是否镜像
BOOL bMirror = (PI / 2 < dProjAng && PI * 1.5 > dProjAng);
// 旋转轴
AcGeVector3d vtAxis = vtPlaneSec.crossProduct(vtNor);
// 旋转角度
double dAngle = vtNor.angleTo(vtPlaneSec, bMirror ? -vtAxis : vtAxis);
// 矩阵
AcGeMatrix3d matNor, matHorz, matMirr;
matNor.setToRotation(dAngle, vtAxis, AcGePoint3d::kOrigin);
matHorz.setToRotation(-dProjAng, AcGeVector3d::kZAxis, AcGePoint3d::kOrigin);
matMirr.setToRotation(PI, AcGeVector3d::kXAxis, AcGePoint3d::kOrigin);
// 新图块ID
AcDbObjectId idNew = AcDbObjectId::kNull;
// 原始图块旋转之后的尺寸
AcGeScale3d scaOrg(1, 1, 1);
// 生成图块名
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;
if(pBlkTbl->has(csBlkName)) // 块存在
{
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
{
// 插入新图块
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;
// 取得图块尺寸
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);
// 设置图块插入点
//AcGePoint3d ptOrigin = Mid(ptMax, ptMin);
//ptOrigin.y = ptMin.y;
//pBlkNew->setOrigin(ptOrigin);
pBlkNew->close();
}
// 计算新图块比例
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;
// 取得新图块尺寸
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;
}
// add by dyc on 2014-01-21 解决Y型三通在比较大坐标值情况下以后后变成T型问题,求两圆交点
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);
// 直线
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)));
}
}
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;
}