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

564 lines
13 KiB
C++

#include "stdafx.h"
#include "stdarx.h"
#include "AecDbXApronDraw.h"
#include "AecDbXApron.h"
#include "AecDbEarthWorm.h"
#include "GiDrawutility.h"
DLLIMPEXP AcDbCurve *GetMaxOffsetCurve(AcDbCurve *pPl, double dOff);
DLLIMPEXP AcDbArc *FormatArc(const AcGePoint3d &ptGe1, const AcGePoint3d &ptGe2, const AcGePoint3d &ptGe3);
DLLIMPEXP AcGePoint3d MidPoint(const AcGePoint3d &pt1, const AcGePoint3d &pt2);
ACRX_CONS_DEFINE_MEMBERS(AecDbXApronDraw, AecDbXDraw, 0);
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);
}
AecDbXApronDraw::AecDbXApronDraw(void)
{
}
AecDbXApronDraw::~AecDbXApronDraw(void)
{
}
static AcDbCurve* GetOffOutSideCurve(AcDbCurve *pIn, double dSw, AcDbCurve * pOffMax)
{
AcDbCurve * pCrvMaxoff = GetMaxOffsetCurve(pOffMax, dSw);
if (pCrvMaxoff != NULL)
{
AcDbVoidPtrArray arOff1, arOff2;
pIn->getOffsetCurves( dSw, arOff1);
pIn->getOffsetCurves(-dSw, arOff2);
if (arOff1.length() == 1 && arOff2.length() == 1)
{
AcDbCurve *pCr1 = NULL,*pCr2 = NULL;
pCr1 = (AcDbCurve *)arOff1.first();
pCr2 = (AcDbCurve *)arOff2.first();
AcDbArc *pArc1 = AcDbArc::cast(pCr1);
AcDbArc *pArc2 = AcDbArc::cast(pCr2);
AcGePoint3d pt1, pt2,pt11,pt22;
pCr1->getStartPoint(pt1);
pCr2->getStartPoint(pt2);
pCrvMaxoff->getClosestPointTo(pt1, pt11);
pCrvMaxoff->getClosestPointTo(pt2, pt22);
if (pt1.distanceTo(pt11) < 1.e-1)
{
delete pCrvMaxoff;
delete pCr2;
return pCr1;
}
if (pt2.distanceTo(pt22) < 1.e-1)
{
delete pCrvMaxoff;
delete pCr1;
return pCr2;
}
}
delete pCrvMaxoff;
FreeBuffer(arOff1);
FreeBuffer(arOff2);
}
return NULL;
}
void SetMaxLenSplit(AcDbCurve* pCrv, AcGePoint3d& ptInt)
{
AcDbLine *pLn = AcDbLine::cast(pCrv);
if (pLn != NULL)
{
if (pLn->startPoint().distanceTo(ptInt) > pLn->endPoint().distanceTo(ptInt))
{
pLn->setEndPoint(ptInt);
}
else
{
pLn->setStartPoint(ptInt);
}
return;
}
AcDbArc *pArc = AcDbArc::cast(pCrv);
if (pArc != NULL)
{
AcGePoint3d pt0, ptM;
double dL1 = 0, dS = 0,dIt = 0;
pArc->getDistAtPoint(ptInt, dL1);
double dHalf = 0.5 * (pArc->endAngle() - pArc->startAngle()) * pArc->radius();
if (dL1 > dHalf)//near end
{
pArc->getStartPoint(pt0);
pArc->getStartParam(dS);
pArc->getParamAtDist(dL1, dIt);
pArc->getPointAtParam(0.5 * (dIt + dS), ptM);
AcDbArc* pArcT = FormatArc(pt0, ptM, ptInt);
if (pArcT != NULL)
{
pArc->setStartAngle(pArcT->startAngle());
pArc->setEndAngle(pArcT->endAngle());
}
}
else//near sta
{
pArc->getEndPoint(pt0);
pArc->getEndParam(dS);
pArc->getParamAtDist(dL1, dIt);
pArc->getPointAtParam(0.5 * (dIt + dS), ptM);
AcDbArc *pArcT = FormatArc(ptInt, ptM, pt0);
if (pArcT != NULL)
{
pArc->setStartAngle(pArcT->startAngle());
pArc->setEndAngle(pArcT->endAngle());
}
}
}
}
void MakeConnect(AcDbCurve *pLast, AcDbCurve *pNext)
{
AcGePoint3dArray arPts;
pLast->intersectWith(pNext, AcDb::kExtendBoth, arPts);
int iMin = -1;
AcGePoint3d ptInt,ptTmp, pt1,pt2;
if (arPts.length() == 1)
{
iMin = 0;
}
else
{
double dL1 = 0,dMin = 1.e10;
//arPts 最多两个点
//
//取该点到线端点的距离和最小的 点
for(int i = 0;i < arPts.length();i++)
{
ptTmp = arPts.at(i);
pLast->getClosestPointTo(ptTmp, pt1, Adesk::kFalse);
pNext->getClosestPointTo(ptTmp, pt2, Adesk::kFalse);
dL1 = ptTmp.distanceTo(pt1) + ptTmp.distanceTo(pt2);
if (dL1 < dMin)
{
dMin = dL1;
iMin = i;
}
}
}
if (iMin != -1)
{
ptInt = arPts.at(iMin);
pLast->getStartPoint(pt1);
pLast->getEndPoint(pt2);
Acad::ErrorStatus es1 = Acad::eOk, es2 = Acad::eOk;
if (pt1.distanceTo(ptInt) < pt2.distanceTo(ptInt))
{
if (pt1.distanceTo(ptInt) > 1.e-2)
es1 = pLast->extend(Adesk::kTrue, ptInt);
}
else
{
if (pt2.distanceTo(ptInt) > 1.e-2)
es1 = pLast->extend(Adesk::kFalse, ptInt);
}
if (es1 == Acad::eInvalidInput)//可能落在该线上
{
//acutPrintf(_T("\nes1=%d"),es1);
double dP = 0;
es1 = pLast->getParamAtPoint(ptInt, dP);
if (es1 == Acad::eOk)
{
//acutPrintf(_T("\nes1=%d"), es1);
//取最长分割
SetMaxLenSplit(pLast, ptInt);
}
}
pNext->getStartPoint(pt1);
pNext->getEndPoint(pt2);
if (pt1.distanceTo(ptInt) < pt2.distanceTo(ptInt))
{
if (pt1.distanceTo(ptInt) > 1.e-2)
es2 = pNext->extend(Adesk::kTrue, ptInt);
}
else
{
if (pt2.distanceTo(ptInt) > 1.e-2)
es2 = pNext->extend(Adesk::kFalse, ptInt);
}
if (es2 == Acad::eInvalidInput)//可能落在该线上
{
//acutPrintf(_T("\nes1=%d"),es1);
double dP = 0;
es1 = pNext->getParamAtPoint(ptInt, dP);
if (es2 == Acad::eOk)
{
//acutPrintf(_T("\nes1=%d"), es1);
//取最长分割
SetMaxLenSplit(pNext, ptInt);
}
}
//acutPrintf(_T("\nes1 = %d es2 = %d"), es1, es2);
}
}
Acad::ErrorStatus AecDbXApronDraw::GetInAndOutSide(AcDbVoidPtrArray& arInPtrs, AcDbVoidPtrArray& arOutPtrs,bool bSetEl) const
{
/*疯狂崩溃,无法看懂代码,请老李测试修改*/
//return Acad::eOk;
AcDbEntity *pEntReal = GetAttach();
if (pEntReal == NULL)
return Acad::eOk;
AecDbXApron *pApron = AecDbXApron::cast(pEntReal);
if (pApron == NULL)
return Acad::eOk;
double dBomEl = 0.0;
pApron->GetSpecialtyData(AcDb::kForRead)->GetAt(KEY_BOMEL, dBomEl);
AcDbCurve *pBaseCrv = pApron->GetBaseCurve();
if (pBaseCrv != NULL)
{
AcDbPolyline *pPl = AcDbPolyline::cast(pBaseCrv);
if (pPl != NULL)
{
bool bIsClosed = pPl->isClosed();
AcGePoint3d ptS, ptE;
pPl->getEndPoint(ptE);
pPl->getStartPoint(ptS);
if (!bIsClosed)
{
if (ptS.distanceTo(ptE) < 1.e-3)
bIsClosed = true;
}
if (bSetEl)
pPl->setElevation(dBomEl);
double dSw = 0, dEw = 0;
pPl->getWidthsAt(0, dSw, dEw);
AcDbPolyline *pPlCln = (AcDbPolyline *)pPl->clone();
pPlCln->setConstantWidth(0.0);
AcDbCurve *pOffMax = pPlCln;
double dOffFromWall = pApron->GetOffsetFromWall();
if (dOffFromWall > 1.e-1)
{
pOffMax = GetMaxOffsetCurve(pPlCln, dOffFromWall);
// 删掉了,但没有置空
}
if (pOffMax)
pOffMax->explode(arInPtrs);
// 这里继续使用pPlCln,但又不判断是否为空,就是判断了也没有用,因为delete后,没有置空。
// 而且还有泄露
pOffMax = GetMaxOffsetCurve(pPlCln, dOffFromWall + dSw);
if (pOffMax)
pOffMax->explode(arOutPtrs);
/*AcDbCurve *pIn = NULL, *pOut = NULL, *pIO = NULL;
for (int ii = 0; ii < arInPtrs.length(); ii++)
{
pIn = (AcDbCurve *)arInPtrs.at(ii);
pPl->getWidthsAt(ii, dSw, dEw);
pOut = GetOffOutSideCurve(pIn, dSw, pOffMax);
if (pOut != NULL)
{
if (ii > 0)
{
MakeConnect((AcDbCurve *)arOutPtrs.last(), pOut);
}
if (pOut != NULL) arOutPtrs.append(pOut);
}
}
if (!arOutPtrs.isEmpty() && bIsClosed)
{
MakeConnect((AcDbCurve *)arOutPtrs.first(), (AcDbCurve *)arOutPtrs.last());
}*/
if (pOffMax)
delete pOffMax;
}
delete pBaseCrv;
}
return Acad::eOk;
}
Acad::ErrorStatus AecDbXApronDraw::Draw2d(AcGiDraw &dc) const
{
AcDbEntity *pEntReal = GetAttach();
if (pEntReal == NULL)
return Acad::eOk;
AcDbVoidPtrArray arInPtrs,arOutPtrs;
GetInAndOutSide(arInPtrs, arOutPtrs);
AcGePoint3d ptS[2], ptE[2];
AcGePoint3dArray arPtIns, arPtOuts;
AcDbCurve *pIn = NULL, *pOut = NULL, *pIO = NULL;
//绘制
int nMinSize = __min(arInPtrs.length(), arOutPtrs.length());
for (int ii = 0; ii < nMinSize; ii++)
{
pIn = (AcDbCurve *)arInPtrs.at(ii);
pOut = (AcDbCurve *)arOutPtrs.at(ii);
//里外连接线
pIn->getStartPoint(ptS[0]);
pIn->getEndPoint(ptE[0]);
if (arPtIns.find(ptS[0]) == -1)
arPtIns.append(ptS[0]);
if (arPtIns.find(ptE[0]) == -1)
arPtIns.append(ptE[0]);
pOut->getStartPoint(ptS[1]);
pOut->getEndPoint(ptE[1]);
if (arPtOuts.find(ptS[1]) == -1)
arPtOuts.append(ptS[1]);
if (arPtOuts.find(ptE[1]) == -1)
arPtOuts.append(ptE[1]);
pIn->setLayer(pEntReal->layerId());
pOut->setLayer(pEntReal->layerId());
dc.DrawEntity(pIn);
dc.DrawEntity(pOut);
dc.Add2dBuffer(pIn);
dc.Add2dBuffer(pOut);
}
if (arPtIns.length() == arPtOuts.length())
{
AcDbLine *pLn = NULL;
for (int ii = 0; ii < arPtIns.length(); ii++)
{
pLn = new AcDbLine(arPtIns.at(ii), arPtOuts.at(ii));
pLn->setLayer(pEntReal->layerId());
dc.DrawEntity(pLn);
dc.Add2dBuffer(pLn);
}
}
return Acad::eOk;
}
bool GetSamplePoints(AcDbCurve *pSubCrv, AcGePoint3d* ptGe,int nPts)
{
if (pSubCrv != NULL )
{
double dEnd = 0.0, dDis = 0.0, dSta = 0.0;
pSubCrv->getEndParam(dEnd);
pSubCrv->getStartParam(dSta);
int nSegs = nPts - 1;
double dStep = (dEnd - dSta) / nSegs;
AcGePoint3d ptTemp;
for (int i = 0; i <= nSegs; i++) // 等 分
{
pSubCrv->getPointAtParam(dSta + dStep * i, ptTemp);
ptGe[i] = ptTemp;
}
return true;
}
return false;
}
Acad::ErrorStatus AecDbXApronDraw::Draw3d(AcGiDraw &dc) const
{
AcDbEntity *pEntReal = GetAttach();
if (pEntReal == NULL)
return Acad::eOk;
AecDbXApron *pApron = AecDbXApron::cast(pEntReal);
if (pApron == NULL)
return Acad::eOk;
double dBomEl = 0.0;
pApron->GetSpecialtyData(AcDb::kForRead)->GetAt(KEY_BOMEL, dBomEl);
double dOt = pApron->GetOutSideThick();
double dIt = pApron->GetInsideThick();
AcDbVoidPtrArray arInPtrs, arOutPtrs;
GetInAndOutSide(arInPtrs, arOutPtrs,true);
AcGePoint3d ptGeB[4],ptGeT[4],ptFr[5],ptBk[5],ptTmp;
//AcGePoint3d;
AcGePoint3dArray arPtIns, arPtOuts;
AcDbCurve *pIn = NULL, *pOut = NULL, *pIO = NULL;
//绘制
int nMinSize = __min(arInPtrs.length(), arOutPtrs.length());
AcGeMatrix3d xIn, xOt;
xIn.setToTranslation(AcGeVector3d(0, 0, dIt));
xOt.setToTranslation(AcGeVector3d(0, 0, dOt));
//20 段,如果是圆弧
int nPts = 21;
int nSeg = nPts - 1;
AcGePoint3d *ptI = new AcGePoint3d[nPts];
AcGePoint3d *ptO = new AcGePoint3d[nPts];
AcDbLine ln,ln2;
for (int ii = 0; ii < nMinSize; ii++)
{
pIn = (AcDbCurve *)arInPtrs.at(ii);
pOut = (AcDbCurve *)arOutPtrs.at(ii);
//里外连接线
pIn->getStartPoint(ptGeB[0]);
pIn->getEndPoint(ptGeB[1]);
ptGeT[0] = ptGeB[0];
ptGeT[0].z += dIt;
ptGeT[1] = ptGeB[1];
ptGeT[1].z += dIt;
pOut->getEndPoint(ptGeB[2]);
pOut->getStartPoint(ptGeB[3]);
ptGeT[2] = ptGeB[2];
ptGeT[2].z += dOt;
ptGeT[3] = ptGeB[3];
ptGeT[3].z += dOt;
//创建6面体,工业建筑暂不考虑圆弧散水!
//创建loft
ptFr[0] = ptGeB[2]; ptFr[1] = ptGeB[3];
ptFr[2] = ptGeT[3]; ptFr[3] = ptGeT[2]; ptFr[4] = ptFr[0];
ptBk[0] = ptGeB[0]; ptBk[1] = ptGeB[1];
ptBk[2] = ptGeT[1]; ptBk[3] = ptGeT[0]; ptBk[4] = ptBk[0];
AcDbLine *pLnIn = AcDbLine::cast(pIn);
if (pLnIn != NULL)
{
ln2.setStartPoint(ptGeB[0]); ln2.setEndPoint(ptGeB[1]);
ln.setStartPoint(MidPoint(ptFr[0],ptFr[1]));
ln2.getClosestPointTo(MidPoint(ptFr[0], ptFr[1]), ptTmp);
ln.setEndPoint(ptTmp);
AcDbRegion *pReg1 = AecDbEarthWorm::CreateRetangeRegion(ptFr, 5);
AcDbRegion* pReg2 = AecDbEarthWorm::CreateRetangeRegion(ptBk, 5);
if (pReg1 != NULL && pReg2 != NULL)
{
AcDbEntity *pSolid = GiDrawUtility::DrawLoft(pReg1, pReg2, &ln);
if (pSolid != NULL)
{
pSolid->setLayer(pEntReal->layerId());
dc.DrawEntity(pSolid);
dc.Add3dBuffer(pSolid);
}
delete pReg1; delete pReg2;
}
}
AcDbArc *pArcIn = AcDbArc::cast(pIn);
if (pArcIn != NULL)
{
GetSamplePoints(pIn, ptI, nPts);
GetSamplePoints(pOut, ptO, nPts);
for (int j = 0;j < nSeg;j++)
{
ptGeB[0] = ptI[j];
ptGeB[1] = ptI[j + 1];
ptGeT[0] = ptGeB[0];
ptGeT[0].z += dIt;
ptGeT[1] = ptGeB[1];
ptGeT[1].z += dIt;
ptGeB[2] = ptO[j];
ptGeB[3] = ptO[j + 1];
ptGeT[2] = ptGeB[2];
ptGeT[2].z += dOt;
ptGeT[3] = ptGeB[3];
ptGeT[3].z += dOt;
//创建6面体,工业建筑暂不考虑圆弧散水!
//创建loft
ptFr[0] = ptGeB[2]; ptFr[1] = ptGeB[3];
ptFr[2] = ptGeT[3]; ptFr[3] = ptGeT[2]; ptFr[4] = ptFr[0];
ptBk[0] = ptGeB[0]; ptBk[1] = ptGeB[1];
ptBk[2] = ptGeT[1]; ptBk[3] = ptGeT[0]; ptBk[4] = ptBk[0];
ln2.setStartPoint(ptGeB[0]); ln2.setEndPoint(ptGeB[1]);
ln.setStartPoint(MidPoint(ptFr[0], ptFr[1]));
ln2.getClosestPointTo(MidPoint(ptFr[0], ptFr[1]), ptTmp);
ln.setEndPoint(ptTmp);
AcDbRegion *pReg1 = AecDbEarthWorm::CreateRetangeRegion(ptFr, 5);
AcDbRegion *pReg2 = AecDbEarthWorm::CreateRetangeRegion(ptBk, 5);
if (pReg1 != NULL && pReg2 != NULL)
{
AcDbEntity *pSolid = GiDrawUtility::DrawLoft(pReg1, pReg2, &ln);
if (pSolid != NULL)
{
pSolid->setLayer(pEntReal->layerId());
dc.DrawEntity(pSolid);
dc.Add3dBuffer(pSolid);
}
delete pReg1; delete pReg2;
}
}
}
}
delete[] ptI;
delete[] ptO;
return Acad::eOk;
}