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

513 lines
14 KiB
C++

#include "stdafx.h"
#include "TCoverBooleanOper.h"
#include <vector>
#include <algorithm>
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define E2TOL 1.e-2
#define E6TOL 1.e-6
#define E10TOL 1.e-10
static void FreeBuffer(AcDbVoidPtrArray& arCurves)
{
for (int i = 0;i < arCurves.length();i++)
{
AcDbEntity* pEnt = (AcDbEntity*)arCurves.at(i);
if (pEnt != NULL)
{
delete pEnt;
}
}
arCurves.setLogicalLength(0);
}
TCoverBooleanOper::TCoverBooleanOper()
{
}
TCoverBooleanOper::~TCoverBooleanOper()
{
}
static bool GreaterCoord(TCoverBooleanOper::PTONCRITEM item1,TCoverBooleanOper::PTONCRITEM item2)
{
AcDbCurve * pCurve = item1.m_pCurve;
AcGePoint3d ptGe1 = item1.m_ptGeOn;
AcGePoint3d ptGe2 = item2.m_ptGeOn;
double dDis1 = 0.0,dDis2 = 0.0;
pCurve->getClosestPointTo(ptGe1,ptGe1);
pCurve->getClosestPointTo(ptGe2,ptGe2);
pCurve->getParamAtPoint(ptGe1,dDis1);
pCurve->getParamAtPoint(ptGe2,dDis2);
if(dDis1 - dDis2 > E10TOL)
{
return false;//up sort
}
return true;//down sort
}
AcDbCurve* TCoverBooleanOper::CurveElement2DbCurve(TDb::TCurveElement el)
{
AcDbCurve* pCurve = NULL;
if (el.ptGe[1].distanceTo(el.ptGe[2]) < E2TOL)
{
pCurve = new AcDbLine(el.ptGe[0],el.ptGe[1]);
}
else
{
pCurve = FormatArc(el.ptGe[0],el.ptGe[1],el.ptGe[2]);
}
return pCurve;
}
BOOL TCoverBooleanOper::SortPoints(AcGePoint3dArray& points,AcDbCurve * pCurve)
{
TCoverBooleanOper::PTONCRITEM ptOnCrItem;
typedef std::vector<TCoverBooleanOper::PTONCRITEM> PtOnCrItemVector;
//排序
AcGePoint3d ptGeSta,ptGeEnd;
pCurve->getStartPoint(ptGeSta);
pCurve->getEndPoint(ptGeEnd);
PtOnCrItemVector vectorItems;
ptOnCrItem.m_pCurve = pCurve;
AcGePoint3d ptGeT;
int nLength = points.length();
for(int i = 0;i < nLength;i++)
{
ptGeT = points.at(i);
pCurve->getClosestPointTo(ptGeT,ptGeT,Adesk::kTrue);
ptOnCrItem.m_ptGeOn = ptGeT;
vectorItems.push_back(ptOnCrItem);
}
PtOnCrItemVector::iterator itHead = vectorItems.begin();
PtOnCrItemVector::iterator itTail = vectorItems.end();
std::sort(itHead,itTail,GreaterCoord);
itHead = vectorItems.begin();
itTail = vectorItems.end();
points.removeSubArray(0,nLength - 1);
AcGePoint3d ptGe;
for(;itHead != itTail;++itHead)
{
ptGe = (*itHead).m_ptGeOn;
points.append(ptGe);
}
return TRUE;
}
AcDbArc* TCoverBooleanOper::FormatArc(AcGePoint3d& ptGe1,AcGePoint3d& ptGe2,AcGePoint3d& ptGe3)
{
//三点确认投影到 XY 面上
ptGe1.z = ptGe2.z = ptGe3.z = 0.0;
AcDbArc* pArcThis = NULL;
AcGeCircArc3d cirArc3d;
cirArc3d.set(ptGe1,ptGe2,ptGe3);
AcGeVector3d vtNorm = cirArc3d.normal();
AcDbCircle cir;
cir.setCenter(cirArc3d.center());
cir.setRadius(cirArc3d.radius());
cir.setNormal(vtNorm);
AcGePoint3dArray arPts;
arPts.append(ptGe1);
arPts.append(ptGe3);
AcDbVoidPtrArray arCurPtrs;
cir.getSplitCurves(arPts,arCurPtrs);
double dPara = 0.0;
AcDbCurve* pCurve = NULL;
for (int j = 0;j < arCurPtrs.length();j++)
{
pCurve = (AcDbCurve*)arCurPtrs.at(j);
if (pCurve != NULL)
{
if (Acad::eOk == pCurve->getParamAtPoint(ptGe2,dPara))
{
AcDbArc* pArc = AcDbArc::cast(pCurve);
if (pArc != NULL)
{
pArcThis = pArc;
arCurPtrs.removeAt(j);
}
break;
}
}
}
FreeBuffer(arCurPtrs);
return pArcThis;
}
BOOL TCoverBooleanOper::BoolSubtract(TComplexCurve& curveThisEdge,const TDbExtentsEdge& otherEdge)
{
/* a b
+-------+
A / /
______________/_______/____________ B
| / 1 / 2 |
| / / |
D |___________/_______/_______________+ C
/ 3 / 4
/_______/
d c
线性布尔运算 ABCD - 12,34 段算法, 同样对圆弧
otherEdage = 12,34 两段, 这两段 通过 TCoverReleationManager 遮挡管理类计算而得,保存在实地上.
curveThisEdge = ABCD 自身边界
*/
TComplexCurve curveOtherEdge,curveThisEdgeNew;
otherEdge.GetEdage(curveOtherEdge);
BOOL bSubtract = FALSE,bThisSetAt = FALSE;
TComplexCurve compReal,compRealNew;
TDb::TCurveElement elReal,elOtherSeg,elReal2;
AcDbLine lineReal,lineEdge;
AcGePoint3d ptGeT,ptSta,ptEnd,ptGeT2;
double dPara = 0.0;
AcGePoint3dArray arPoints;
AcGeVector3d vt1,vt2;
memset(&elReal2,0,sizeof(TDb::TCurveElement));
for (int i = 0;i < curveThisEdge.length();i++)
{
elReal = curveThisEdge.at(i);
if (elReal.ptGe[0].distanceTo(elReal.ptGe[1]) < E2TOL)
continue;
compRealNew.setLogicalLength(0);
compRealNew.append(elReal);
for (int n = 0;n < compRealNew.length();n++)
{
elReal = compRealNew.at(n);
for (int j = 0;j < curveOtherEdge.length();j++)
{
//判断有部分重合的图元段
elOtherSeg = curveOtherEdge.at(j);
//确保遮挡线和原线在同一标高;[正常运算是在同一标高]
elOtherSeg.ptGe[0].z = elReal.ptGe[0].z;
elOtherSeg.ptGe[1].z = elReal.ptGe[1].z;
elOtherSeg.ptGe[2].z = elReal.ptGe[2].z;
if (elReal.ptGe[1].distanceTo(elReal.ptGe[2]) < E2TOL) //实段直线
{
if (elOtherSeg.ptGe[1].distanceTo(elOtherSeg.ptGe[2]) < E2TOL)//虚段直线
{
vt1 = elOtherSeg.ptGe[1] - elOtherSeg.ptGe[0];
vt2 = elReal.ptGe[1] - elReal.ptGe[0];
if (vt1.isParallelTo(vt2)) //两直线平行
{
lineReal.setStartPoint(elReal.ptGe[0]);
lineReal.setEndPoint(elReal.ptGe[1]);
lineReal.getClosestPointTo(elOtherSeg.ptGe[0],ptGeT,Adesk::kTrue);
if (ptGeT.distanceTo(elOtherSeg.ptGe[0]) < E2TOL)//共线
{
//判断 lineReal 整体在 lineOther 上
if (RealInsideOther(lineReal,elOtherSeg))
{
compRealNew.removeAt(n);
n -= 1;
bSubtract = TRUE;
break;
continue;
}
arPoints.setLogicalLength(0);
if (Acad::eOk == lineReal.getParamAtPoint(ptGeT,dPara)) //在实线上
{
if ( ptGeT.distanceTo(elReal.ptGe[0]) < E2TOL ||
ptGeT.distanceTo(elReal.ptGe[1]) < E2TOL ) //有一端点重合
{
//判断是否整体和 real 重合
lineReal.getClosestPointTo(elOtherSeg.ptGe[1],ptGeT2,Adesk::kTrue);
if ( ptGeT2.distanceTo(elReal.ptGe[0]) < E2TOL ||
ptGeT2.distanceTo(elReal.ptGe[1]) < E2TOL ) //另外端点重合
{
compRealNew.removeAt(n);
n -= 1;
bSubtract = TRUE;
break;
}
}
else
{
arPoints.append(ptGeT);
}
}
lineReal.getClosestPointTo(elOtherSeg.ptGe[1],ptGeT,Adesk::kTrue);
if (Acad::eOk == lineReal.getParamAtPoint(ptGeT,dPara)) //在实线上
{
if ( ptGeT.distanceTo(elReal.ptGe[0]) < E2TOL ||
ptGeT.distanceTo(elReal.ptGe[1]) < E2TOL ) //排出端点
{
// 不用处理重合的情况, 上面也经作了判断处理
}
else
{
arPoints.append(ptGeT);
}
}
// 根据虚线图元在另实线上的实际落点,分割实线,减去虚的部分
if (arPoints.length() > 0)
{
AcDbVoidPtrArray arCurves;
SortPoints(arPoints,&lineReal);
lineReal.getSplitCurves(arPoints,arCurves);
lineEdge.setStartPoint(elOtherSeg.ptGe[0]);
lineEdge.setEndPoint(elOtherSeg.ptGe[1]);
compReal.setLogicalLength(0);
AcDbCurve* pCurve = NULL;
for (int k = 0;k < arCurves.length();k++)
{
pCurve = (AcDbCurve*)arCurves.at(k);
//判断 pcurve的中点是否在 other 上
pCurve->getStartPoint(ptSta);
pCurve->getEndPoint(ptEnd);
ptGeT = TSupportFunc::Mid(ptSta,ptEnd);
if (Acad::eOk == lineEdge.getParamAtPoint(ptGeT,dPara)) //该部分落在虚的图元上,不保留
{
}
else //该部分不落在虚的图元上,保留;
{
if (ptSta.distanceTo(ptEnd) > E2TOL)//不是点
{
elReal2 = elReal; //继承属性
elReal2.ptGe[0] = ptSta;
elReal2.ptGe[1] = ptEnd;
elReal2.ptGe[2] = ptEnd;
elReal2.bHided = 0;
compReal.append(elReal2);
bSubtract = TRUE;
}
}
}
// 获取割减后的实线
for (k = 0;k < compReal.length();k++)
{
elReal2 = compReal.at(k);
if (k == 0)
{
//替换本身
compRealNew.setAt(n,elReal2);
elReal = elReal2;
bSubtract = TRUE;
}
else
{
//继续追加
compRealNew.append(elReal2);
bSubtract = TRUE;
}
}
FreeBuffer(arCurves);
}
}
}
}
}
else // elReal 是圆弧 ,圆弧的减运算
{
if (elOtherSeg.ptGe[1].distanceTo(elOtherSeg.ptGe[2]) > E2TOL ) //圆弧
{
//前提条件 : 首先同心,同半径
AcDbArc* pArcReal = FormatArc(elReal.ptGe[0],elReal.ptGe[1],elReal.ptGe[2]);
AcDbArc* pArcEdge = FormatArc(elOtherSeg.ptGe[0],elOtherSeg.ptGe[1],elOtherSeg.ptGe[2]);
if (pArcReal != NULL && pArcEdge != NULL)
{
double dDist1 = pArcReal->center().distanceTo(pArcEdge->center());
double dDist2 = pArcReal->radius() - pArcEdge->radius();
if (pArcReal->center().distanceTo(pArcEdge->center()) < E2TOL &&
fabs(pArcReal->radius() - pArcEdge->radius()) < E2TOL) //共圆
{
//判断 lineReal 整体在 lineOther 上
if (RealInsideOther(pArcReal,pArcEdge))
{
compRealNew.removeAt(n);
n -= 1;
bSubtract = TRUE;
break;
continue;
}
// 判断是否重合
pArcReal->getClosestPointTo(elOtherSeg.ptGe[0],ptGeT,Adesk::kTrue);
arPoints.setLogicalLength(0);
if ( ptGeT.distanceTo(elReal.ptGe[0]) < E2TOL ||
ptGeT.distanceTo(elReal.ptGe[2]) < E2TOL ) //有一端点重合
{
//判断是否整体和 real 重合
pArcReal->getClosestPointTo(elOtherSeg.ptGe[2],ptGeT2,Adesk::kTrue);
if ( ptGeT2.distanceTo(elReal.ptGe[0]) < E2TOL ||
ptGeT2.distanceTo(elReal.ptGe[2]) < E2TOL ) //另外端点重合
{
compRealNew.removeAt(n);
n -= 1;
bSubtract = TRUE;
break;
}
}
else
{
arPoints.append(ptGeT);
}
pArcReal->getClosestPointTo(elOtherSeg.ptGe[2],ptGeT,Adesk::kTrue);
if (Acad::eOk == pArcReal->getParamAtPoint(ptGeT,dPara)) //在实线上
{
if ( ptGeT.distanceTo(elReal.ptGe[0]) < E2TOL ||
ptGeT.distanceTo(elReal.ptGe[2]) < E2TOL ) //排出端点
{
// 不用处理重合的情况, 上面也经作了判断处理
}
else
{
arPoints.append(ptGeT);
}
}
// 根据虚线图元在另实线上的实际落点,分割实线,减去虚的部分
if (arPoints.length() > 0)
{
AcDbVoidPtrArray arCurves;
SortPoints(arPoints,pArcReal);
pArcReal->getSplitCurves(arPoints,arCurves);
compReal.setLogicalLength(0);
AcDbCurve* pCurve = NULL;
double dSta = 0.0,dEnd = 0.0;
for (int k = 0;k < arCurves.length();k++)
{
pCurve = (AcDbCurve*)arCurves.at(k);
//判断 pcurve的中点是否在 other 上
pCurve->getStartParam(dSta);
pCurve->getEndParam(dEnd);
pCurve->getStartPoint(ptSta);
pCurve->getEndPoint(ptEnd);
ptGeT = TSupportFunc::Mid(pCurve);
if (Acad::eOk == pArcEdge->getParamAtPoint(ptGeT,dPara)) //该部分落在虚的图元上,不保留
{
}
else //该部分不落在虚的图元上,保留;
{
elReal2 = elReal; //继承属性
elReal2.ptGe[0] = ptSta;
elReal2.ptGe[1] = ptGeT;
elReal2.ptGe[2] = ptEnd;
elReal2.bHided = 0;
compReal.append(elReal2);
bSubtract = TRUE;
}
}
// 获取割减后的实线
for (k = 0;k < compReal.length();k++)
{
elReal2 = compReal.at(k);
if (k == 0)
{
compRealNew.setAt(n,elReal2);
elReal = elReal2;
bSubtract = TRUE;
}
else
{
compRealNew.append(elReal2);
bSubtract = TRUE;
}
}
FreeBuffer(arCurves);
}
}
}
//释放 临时圆弧对象
if (pArcReal != NULL) delete pArcReal;
if (pArcEdge != NULL) delete pArcEdge;
}
}
}
}
//缓存减后的实段曲线
if (compRealNew.length() > 0)
{
curveThisEdgeNew.append(compRealNew);
}
}
//被减后的所有实曲线段
curveThisEdge.setLogicalLength(0);
if (curveThisEdgeNew.length() > 0)
{
curveThisEdge.append(curveThisEdgeNew);
}
return bSubtract;
}
BOOL TCoverBooleanOper::RealInsideOther(AcDbLine& lineReal,TDb::TCurveElement& elOtherSeg)
{
//已经判断共线了
AcDbLine lineEdage(elOtherSeg.ptGe[0],elOtherSeg.ptGe[1]);
double dPara = 0.0;
if (Acad::eOk == lineEdage.getParamAtPoint(lineReal.startPoint(),dPara) &&
Acad::eOk == lineEdage.getParamAtPoint(lineReal.endPoint(),dPara))
{
return TRUE;
}
return FALSE;
}
BOOL TCoverBooleanOper::RealInsideOther(AcDbArc* pArcReal,AcDbArc* pArcEdge)
{
ASSERT(pArcEdge != NULL);
ASSERT(pArcReal != NULL);
AcGePoint3d ptSta,ptEnd;
pArcReal->getStartPoint(ptSta);
pArcReal->getEndPoint(ptEnd);
double dPara = 0.0;
if (Acad::eOk == pArcEdge->getParamAtPoint(ptSta,dPara) &&
Acad::eOk == pArcEdge->getParamAtPoint(ptEnd,dPara))
{
return TRUE;
}
return FALSE;
}