871 lines
22 KiB
C++
871 lines
22 KiB
C++
#include "stdafx.h"
|
|
#include "StdArx.h"
|
|
#include "AecCoverBooleanOper.h"
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include "math.h"
|
|
#include "AecSupportFunc.h"
|
|
#include "KTCADUtilityEx.h"
|
|
#include "coretools.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[]=__FILE__;
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
#define E2TOL 1.e-1
|
|
#define E6TOL 1.e-5
|
|
#define E10TOL 1.e-10
|
|
|
|
extern Acad::ErrorStatus AddToModelSpace(AcDbEntity* pEnt,AcDbDatabase* pDb = NULL,bool bClose = true);
|
|
|
|
static void FreeBuffer(AcDbVoidPtrArray& arCurves)
|
|
{
|
|
for (int i = 0;i < arCurves.length();i++)
|
|
{
|
|
AcDbEntity* pEnt = (AcDbEntity*)arCurves.at(i);
|
|
if (pEnt != NULL)
|
|
{
|
|
DELETE_PTR(pEnt);
|
|
}
|
|
}
|
|
arCurves.setLogicalLength(0);
|
|
}
|
|
|
|
AecCoverBooleanOper::AecCoverBooleanOper()
|
|
{
|
|
}
|
|
|
|
AecCoverBooleanOper::~AecCoverBooleanOper()
|
|
{
|
|
}
|
|
|
|
static bool GreaterCoord(AecCoverBooleanOper::PTONCRITEM item1,AecCoverBooleanOper::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,Adesk::kTrue);
|
|
pCurve->getClosestPointTo(ptGe2,ptGe2,Adesk::kTrue);
|
|
|
|
AcDbArc* pArc = AcDbArc::cast(pCurve);
|
|
if (pArc != NULL)
|
|
{
|
|
AcDbCircle cir;
|
|
cir.setCenter(pArc->center());
|
|
cir.setRadius(pArc->radius());
|
|
cir.setNormal(pArc->normal());
|
|
|
|
cir.getParamAtPoint(ptGe1,dDis1);
|
|
cir.getParamAtPoint(ptGe2,dDis2);
|
|
}
|
|
else
|
|
{
|
|
pCurve->getParamAtPoint(ptGe1,dDis1);
|
|
pCurve->getParamAtPoint(ptGe2,dDis2);
|
|
}
|
|
|
|
if(dDis1 - dDis2 > E10TOL)
|
|
{
|
|
return false;//up sort
|
|
}
|
|
return true;//down sort
|
|
}
|
|
|
|
AcDbCurve* AecCoverBooleanOper::CurveElement2DbCurve(const AecEqui::AecCurveElement& el)
|
|
{
|
|
AcDbCurve* pCurve = NULL;
|
|
if (el.ptGe[1].distanceTo(el.ptGe[2]) < E2TOL)
|
|
{
|
|
pCurve = new AcDbLine(el.ptGe[0],el.ptGe[1]);
|
|
}
|
|
else
|
|
{
|
|
pCurve = AecCoverBooleanOper::FormatArc((AcGePoint3d&)el.ptGe[0],(AcGePoint3d&)el.ptGe[1],(AcGePoint3d&)el.ptGe[2]);
|
|
}
|
|
return pCurve;
|
|
}
|
|
|
|
BOOL AecCoverBooleanOper::SortPoints(AcGePoint3dArray& points,AcDbCurve * pCurve,bool bSetToCloseTo)
|
|
{
|
|
if (!pCurve) return FALSE;
|
|
AecCoverBooleanOper::PTONCRITEM ptOnCrItem;
|
|
typedef std::vector<AecCoverBooleanOper::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;
|
|
ptOnCrItem.m_ptOld = points.at(i);
|
|
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)
|
|
{
|
|
if (bSetToCloseTo)
|
|
{
|
|
ptGe = (*itHead).m_ptGeOn;
|
|
}
|
|
else
|
|
{
|
|
ptGe = (*itHead).m_ptOld;
|
|
}
|
|
points.append(ptGe);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
AcDbArc* AecCoverBooleanOper::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 AecCoverBooleanOper::BoolSubtract(AecComplexCurve& curveThisEdge,const AecComplexCurve& curveOtherEdge)
|
|
{
|
|
AecComplexCurve curveThisEdgeNew;
|
|
BOOL bSubtract = FALSE,bThisSetAt = FALSE;
|
|
AecComplexCurve compReal,compRealNew;
|
|
AecEqui::AecCurveElement elReal,elOtherSeg,elReal2;
|
|
AcDbLine lineReal,lineEdge;
|
|
AcGePoint3d ptGeT,ptSta,ptEnd,ptGeT2;
|
|
double dPara = 0.0;
|
|
AcGePoint3dArray arPoints;
|
|
AcGeVector3d vt1,vt2;
|
|
|
|
memset(&elReal2,0,sizeof(AecEqui::AecCurveElement));
|
|
|
|
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 (int 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 (int 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_PTR(pArcReal);
|
|
if (pArcEdge != NULL) DELETE_PTR(pArcEdge);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//缓存减后的实段曲线
|
|
if (compRealNew.length() > 0)
|
|
{
|
|
curveThisEdgeNew.append(compRealNew);
|
|
}
|
|
}
|
|
|
|
//被减后的所有实曲线段
|
|
curveThisEdge.setLogicalLength(0);
|
|
if (curveThisEdgeNew.length() > 0)
|
|
{
|
|
curveThisEdge.append(curveThisEdgeNew);
|
|
}
|
|
return bSubtract;
|
|
}
|
|
|
|
BOOL AecCoverBooleanOper::BoolSubtract(AecComplexCurve& curveThisEdge,const AecComplexCurveDraw& otherEdge)
|
|
{
|
|
/* a b
|
|
+-------+
|
|
A / /
|
|
______________/......./____________ B
|
|
| / 1 / 2 |
|
|
| / / |
|
|
D |___________/......./_______________+ C
|
|
/ 3 / 4
|
|
/_______/
|
|
d c
|
|
|
|
线性布尔运算 ABCD - 12,34 段算法, 同样对圆弧
|
|
otherEdage = 12,34 两段, 这两段 通过 遮挡管理类计算而得,保存在实地上.
|
|
curveThisEdge = ABCD 自身边界
|
|
*/
|
|
AecComplexCurve curveOtherEdge;
|
|
otherEdge.GetEdage(curveOtherEdge);
|
|
|
|
return AecCoverBooleanOper::BoolSubtract(curveThisEdge,curveOtherEdge);
|
|
}
|
|
|
|
BOOL AecCoverBooleanOper::HasIntersection(const AecComplexCurve& cmplThis,const AecComplexCurve& cmplOther)
|
|
{
|
|
AecComplexCurve curveThisEdge;
|
|
curveThisEdge.copyFrom(cmplThis);
|
|
|
|
AecComplexCurve curveOtherEdge;
|
|
curveOtherEdge.copyFrom(cmplOther);
|
|
|
|
BOOL bSubtracted = AecCoverBooleanOper::BoolSubtract(curveThisEdge,curveOtherEdge);
|
|
|
|
return bSubtracted;
|
|
}
|
|
|
|
BOOL AecCoverBooleanOper::BoolUnite(AecComplexCurve& curveThisEdge,const AecComplexCurve& curveOtherEdge)
|
|
{
|
|
for (int i = 0;i < curveOtherEdge.length();i++)
|
|
{
|
|
const AecEqui::AecCurveElement& elOther = curveOtherEdge.atByCstRef(i);
|
|
if (curveThisEdge.CanBoolUnite(elOther))
|
|
{
|
|
curveThisEdge.append(elOther);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
AcGePoint3d AecCoverBooleanOper::MidPoint(const AcGePoint3d& pt1,const AcGePoint3d& pt2)
|
|
{
|
|
return AcGePoint3d( (pt1.x + pt2.x) / 2.0,
|
|
(pt1.y + pt2.y) / 2.0,
|
|
(pt1.z + pt2.z) / 2.0 );
|
|
}
|
|
|
|
extern AcGePoint3d GetArcMidPoint(AcDbArc* pArc);
|
|
void AecCoverBooleanOper::TrimElement(AcDbCurve* pThis,const AcGePoint3d& pt1,const AcGePoint3d& pt2,AecComplexCurve& curveThisEdgeNew)
|
|
{
|
|
AcGePoint3d ptSta,ptEnd;
|
|
pThis->getStartPoint(ptSta);
|
|
pThis->getEndPoint(ptEnd);
|
|
|
|
AcGePoint3dArray arPts;
|
|
arPts.append(ptSta);
|
|
arPts.append(ptEnd);
|
|
arPts.append(pt1);
|
|
arPts.append(pt2);
|
|
|
|
SortPoints(arPts,pThis);
|
|
|
|
AcGePoint3d ptMOn;
|
|
AcGePoint3d ptMid = AecCoverBooleanOper::MidPoint(pt1,pt2);
|
|
pThis->getClosestPointTo(ptMid,ptMOn);
|
|
|
|
AcDbVoidPtrArray arSubCurPtrs;
|
|
pThis->getSplitCurves(arPts,arSubCurPtrs);
|
|
|
|
double dM = 0.0;
|
|
AecEqui::AecCurveElement el;
|
|
memset(&el,0,sizeof(AecEqui::AecCurveElement));
|
|
|
|
AcDbCurve* pCurve = NULL;
|
|
for (int i = 0;i < arSubCurPtrs.length();i++)
|
|
{
|
|
pCurve = (AcDbCurve*)arSubCurPtrs.at(i);
|
|
|
|
if (Acad::eOk == pCurve->getParamAtPoint(ptMOn,dM))//isOn
|
|
{
|
|
}
|
|
else
|
|
{
|
|
pCurve->getStartPoint(el.ptGe[0]);
|
|
pCurve->getEndPoint(el.ptGe[2]);
|
|
el.ptGe[1] = el.ptGe[2];
|
|
|
|
AcDbArc* pArc = AcDbArc::cast(pCurve);
|
|
if (pArc != NULL)
|
|
{
|
|
el.ptGe[1] = GetArcMidPoint(pArc);
|
|
}
|
|
curveThisEdgeNew.append(el);
|
|
}
|
|
delete pCurve;
|
|
}
|
|
}
|
|
|
|
DLLIMPEXP AcDbCurve* GetMinOffsetCurve(AcDbCurve* pPl,double dOff)
|
|
{
|
|
if (pPl != NULL)
|
|
{
|
|
double dE = 0.0,dLen = 0.0,dLen1 = 0.0,dLen2 = 0.0;
|
|
pPl->getEndParam(dE);
|
|
pPl->getDistAtParam(dE,dLen);
|
|
|
|
AcDbVoidPtrArray arCr1,arCr2;
|
|
pPl->getOffsetCurves( dOff,arCr1);
|
|
pPl->getOffsetCurves(-dOff,arCr2);
|
|
|
|
if (!arCr1.isEmpty() && !arCr2.isEmpty() )
|
|
{
|
|
AcDbCurve* pCr1 = (AcDbCurve*)arCr1.first();
|
|
AcDbCurve* pCr2 = (AcDbCurve*)arCr2.first();
|
|
|
|
pCr1->getEndParam(dE);
|
|
pCr1->getDistAtParam(dE,dLen1);
|
|
|
|
pCr2->getEndParam(dE);
|
|
pCr2->getDistAtParam(dE,dLen2);
|
|
|
|
if (dLen1 < dLen)
|
|
{
|
|
delete pCr2;
|
|
return pCr1;
|
|
}
|
|
|
|
if (dLen2 < dLen)
|
|
{
|
|
delete pCr1;
|
|
return pCr2;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
DLLIMPEXP AcDbCurve* GetMaxOffsetCurve(AcDbCurve* pPl,double dOff)
|
|
{
|
|
if (pPl != NULL)
|
|
{
|
|
double dE = 0.0,dLen = 0.0,dLen1 = 0.0,dLen2 = 0.0;
|
|
pPl->getEndParam(dE);
|
|
pPl->getDistAtParam(dE,dLen);
|
|
|
|
AcDbVoidPtrArray arCr1,arCr2;
|
|
pPl->getOffsetCurves( dOff,arCr1);
|
|
pPl->getOffsetCurves(-dOff,arCr2);
|
|
|
|
if (!arCr1.isEmpty() && !arCr2.isEmpty() )
|
|
{
|
|
AcDbCurve* pCr1 = (AcDbCurve*)arCr1.first();
|
|
AcDbCurve* pCr2 = (AcDbCurve*)arCr2.first();
|
|
|
|
pCr1->getEndParam(dE);
|
|
pCr1->getDistAtParam(dE,dLen1);
|
|
|
|
pCr2->getEndParam(dE);
|
|
pCr2->getDistAtParam(dE,dLen2);
|
|
|
|
if ( (dLen1 - dLen) < 1.e-6)
|
|
{
|
|
delete pCr1;
|
|
return pCr2;
|
|
}
|
|
|
|
if ( (dLen2 - dLen) < 1.e-6)
|
|
{
|
|
delete pCr2;
|
|
return pCr1;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//区域裁剪 curvePoly 闭合
|
|
bool AecCoverBooleanOper::PolyClip(const AecComplexCurve& curvePoly,const AecComplexCurve& curveCmpl,AecComplexCurve& crvOutSide,AecComplexCurve& crvInside)
|
|
{
|
|
bool bSuccess = false;
|
|
AcDbCurve* pCurOfPl = NULL;
|
|
AcDbVoidPtrArray arCurPtrs,arRes;
|
|
for (int i = 0;i < curvePoly.length();i++)
|
|
{
|
|
const AecEqui::AecCurveElement& elOfPl = curvePoly.atByCstRef(i);
|
|
AcDbCurve* pCurOfPl = CurveElement2DbCurve(elOfPl);
|
|
|
|
if (pCurOfPl != NULL)
|
|
arCurPtrs.append(pCurOfPl);
|
|
}
|
|
|
|
AcDbCurve* pPlCrv = KTCADUtilityEx::ConvertBoundCurve(arCurPtrs,arRes);
|
|
if (pPlCrv != NULL)
|
|
{
|
|
AcDbPolyline* pPl = AcDbPolyline::cast(pPlCrv);
|
|
if (pPl != NULL)
|
|
{
|
|
pPl->setClosed(Adesk::kTrue);
|
|
|
|
//获取offset 小一圈的pl 误差0.1
|
|
AcDbCurve* pPlMin = GetMinOffsetCurve(pPl,0.1);
|
|
AcDbCurve* pPlMax = GetMaxOffsetCurve(pPl,0.1);
|
|
|
|
if (pPlMin != NULL && pPlMax != NULL)
|
|
{
|
|
AcGePoint3d ptOn;
|
|
AcGePoint3dArray arPts;
|
|
for (int j = 0;j < curveCmpl.length();j++)
|
|
{
|
|
const AecEqui::AecCurveElement& elSeg = curveCmpl.atByCstRef(j);
|
|
AcDbCurve* pCurSeg = CurveElement2DbCurve(elSeg);
|
|
|
|
arPts.removeAll();
|
|
pCurSeg->intersectWith(pPlCrv,AcDb::kOnBothOperands,arPts);
|
|
|
|
if (arPts.isEmpty())
|
|
{
|
|
//不相交,1 inside 2 outside 3 部分重合
|
|
//先去除inside
|
|
if ( CoreTools::IsPointInPoly(elSeg.ptGe[0],*pPl) > 0 )
|
|
{
|
|
//inside
|
|
crvInside.append(elSeg);
|
|
}
|
|
else// 2,3
|
|
{
|
|
//外部,或部分重合 误差0.1
|
|
arPts.removeAll();
|
|
pCurSeg->intersectWith(pPlMax,AcDb::kOnBothOperands,arPts);
|
|
|
|
if (!arPts.isEmpty())//有重合
|
|
{
|
|
for (int n = 0;n < arPts.length();n++)
|
|
{
|
|
pPl->getClosestPointTo(arPts.at(n),ptOn);
|
|
arPts.setAt(n,ptOn);
|
|
}
|
|
|
|
//裁剪
|
|
SortPoints(arPts,pCurSeg);
|
|
|
|
arCurPtrs.removeAll();
|
|
pCurSeg->getSplitCurves(arPts,arCurPtrs);
|
|
|
|
//和内圈相交不保留
|
|
AcDbCurve* pCur = NULL;
|
|
for (int ii = 0;ii < arCurPtrs.length();ii++)
|
|
{
|
|
pCur = (AcDbCurve*)arCurPtrs.at(ii);
|
|
|
|
arPts.removeAll();
|
|
pCur->intersectWith(pPlMax,AcDb::kOnBothOperands,arPts);
|
|
|
|
if (!arPts.isEmpty())//相交,外部,保留
|
|
{
|
|
//属性相同
|
|
AecEqui::AecCurveElement el = elSeg;
|
|
if ( AecComplexCurve::MakeElement(el,pCur) )
|
|
{
|
|
crvOutSide.append(el);
|
|
}
|
|
}
|
|
else//重合段,不加入in
|
|
{
|
|
AecEqui::AecCurveElement el = elSeg;
|
|
if ( AecComplexCurve::MakeElement(el,pCur) )
|
|
{
|
|
crvInside.append(el);
|
|
}
|
|
delete pCur;
|
|
}
|
|
}
|
|
}
|
|
else //外部
|
|
{
|
|
crvOutSide.append(elSeg);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//裁剪
|
|
SortPoints(arPts,pCurSeg);
|
|
|
|
arCurPtrs.removeAll();
|
|
pCurSeg->getSplitCurves(arPts,arCurPtrs);
|
|
|
|
//和内圈相交不保留
|
|
AcDbCurve* pCur = NULL;
|
|
for (int ii = 0;ii < arCurPtrs.length();ii++)
|
|
{
|
|
pCur = (AcDbCurve*)arCurPtrs.at(ii);
|
|
|
|
arPts.removeAll();
|
|
pCur->intersectWith(pPlMin,AcDb::kOnBothOperands,arPts);
|
|
|
|
if (arPts.isEmpty())//不相交,外部,保留
|
|
{
|
|
pCur->intersectWith(pPlMax,AcDb::kOnBothOperands,arPts);
|
|
if (arPts.isEmpty())
|
|
{
|
|
//内外都无交点,说明压线重合
|
|
}
|
|
else//和外部有交点
|
|
{
|
|
//属性相同
|
|
AecEqui::AecCurveElement el = elSeg;
|
|
if ( AecComplexCurve::MakeElement(el,pCur) )
|
|
{
|
|
crvOutSide.append(el);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//内部
|
|
AecEqui::AecCurveElement el = elSeg;
|
|
if ( AecComplexCurve::MakeElement(el,pCur) )
|
|
{
|
|
crvInside.append(el);
|
|
}
|
|
delete pCur;
|
|
}
|
|
}
|
|
}
|
|
delete pCurSeg;
|
|
}
|
|
delete pPlMin;
|
|
delete pPlMax;
|
|
}
|
|
bSuccess = true;
|
|
}
|
|
delete pPlCrv;
|
|
}
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL AecCoverBooleanOper::RealInsideOther(AcDbLine& lineReal,AecEqui::AecCurveElement& 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 AecCoverBooleanOper::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;
|
|
} |