564 lines
13 KiB
C++
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;
|
|
} |