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

599 lines
14 KiB
C++

#include "stdafx.h"
#include "AecDbBalconyDraw.h"
#include "AecDbBalcony.h"
#include "AecDbEarthWorm.h"
#include "AcDbX3dSolid.h"
#include "CoreTools.h"
DLLIMPEXP AcDbPolyline* FormatPolyline(AcGePoint3d* ppPts,int nCount);
DLLIMPEXP AcDbCurve* GetMinOffsetCurve(AcDbCurve* pPl,double dOff);
DLLIMPEXP AcDbCurve* GetMaxOffsetCurve(AcDbCurve* pPl,double dOff);
DLLIMPEXP AcGePoint3d MidPoint(AcGePoint3d& pt1,AcGePoint3d& pt2);
ACRX_CONS_DEFINE_MEMBERS(AecDbBalconyDraw,AecDbXDraw,0);
namespace
{
AcDbCurve* makeOffsetCurveByDir(AcDbPolyline* pCurve
, const double& dOffset
, const AcGeVector3d& vtDir)
{
if (!pCurve) return NULL;
int len(pCurve->numVerts());
if (len < 2) return NULL;
AcGeVector3d vt(vtDir);
vt.normalize();
AcDbVoidPtrArray ar, ar2;
pCurve->getOffsetCurves(dOffset, ar);
pCurve->getOffsetCurves(-dOffset, ar2);
// 没有都成功,那么,哪个成功用哪个。
if (!(!ar2.isEmpty() && !ar.isEmpty()))
{
AcDbVoidPtrArray &arr(ar.isEmpty() ? ar2 : ar);
if (arr.isEmpty()) return NULL;
AcDbCurve *pNew((AcDbCurve *)((AcDbCurve *)arr.first())->clone());
deleteArrayVoidPtrs<AcDbEntity>(arr);
return pNew;
}
AcDbPolyline* pNewCurve1 = (AcDbPolyline*)(((AcDbEntity*)ar.first())->clone());
deleteArrayVoidPtrs<AcDbEntity>(ar);
AcDbPolyline* pNewCurve2 = (AcDbPolyline*)(((AcDbEntity*)ar2.first())->clone());
deleteArrayVoidPtrs<AcDbEntity>(ar2);
AcDbCurve* pSelect(NULL);
double d1, d2;
AcDbLine line1, line2;
AcGePoint3d pt, pt1, pt2;
AcGeLineSeg3d seg, seg1, seg2;
for (int i(0); i < len - 1; ++i)
{
pCurve->getLineSegAt(i, seg);
pt = seg.startPoint();
pt += vt * 1;
pNewCurve1->getLineSegAt(i, seg1);
pNewCurve2->getLineSegAt(i, seg2);
line1.setStartPoint(seg1.startPoint());
line1.setEndPoint(seg1.endPoint());
line2.setStartPoint(seg2.startPoint());
line2.setEndPoint(seg2.endPoint());
line1.getClosestPointTo(pt, pt1, Adesk::kTrue);
line2.getClosestPointTo(pt, pt2, Adesk::kTrue);
d1 = pt.distanceTo(pt1);
d2 = pt.distanceTo(pt2);
if (EQUAL(d1, d2))
continue;
if (d1 > d2)
pSelect = (AcDbCurve*)pNewCurve2->clone();
else
pSelect = (AcDbCurve*)pNewCurve1->clone();
break;
}
if (!pSelect)
pSelect = (AcDbCurve*)pNewCurve1->clone();
DELETE_PTR(pNewCurve1);
DELETE_PTR(pNewCurve2);
return pSelect;
}
AcDbCurve* makeCurve(AcDbPolyline* pPline, const std::vector<double>& arOffset, const AcGeVector3d& vtDir)
{
if (!pPline) return NULL;
if (!pPline->isOnlyLines()) return NULL;
int nSeg(pPline->numVerts() - 1);
if (nSeg > arOffset.size()) return NULL;
AcDbVoidPtrArray arCurves;
std::vector<AcGeLineSeg3d> segs;
AcGeLineSeg3d seg;
for (int i(0); i < nSeg; ++i)
{
AcDbPolyline* pCurve = (AcDbPolyline*)makeOffsetCurveByDir(pPline, arOffset[i], vtDir);
// 是第几个 polyline 就把自己的第几段seg取出来
if (pCurve)
{
pCurve->getLineSegAt(i, seg);
segs.push_back(seg);
DELETE_PTR(pCurve);
}
}
if (segs.empty()) return NULL;
AcGePoint3dArray arpts, ar;
AcGeLineSeg3d seg1, seg2;
AcDbLine line1, line2;
for (int i(0); i < segs.size() - 1; ++i)
{
ar.removeAll();
line1.setStartPoint(segs[i].startPoint());
line1.setEndPoint(segs[i].endPoint());
line2.setStartPoint(segs[i + 1].startPoint());
line2.setEndPoint(segs[i + 1].endPoint());
if (line1.intersectWith(&line2, AcDb::kExtendBoth, ar) == Acad::eOk && !ar.isEmpty())
arpts.append(ar.first());
}
arpts.insertAt(0, segs[0].startPoint());
arpts.append(segs.rbegin()->endPoint());
return FormatPolyline(arpts.asArrayPtr(), arpts.length());
}
void extendCurve(AcDbPolyline* pPline, const double& dExt1, const double& dExt2)
{
if (!pPline) return;
int len(pPline->numVerts());
if (len < 2) return;
AcDb::Planarity epl;
AcGePlane pln;
pPline->getPlane(pln, epl);
pln.set(AcGePoint3d::kOrigin, pPline->normal());
AcGePoint3d ptFirst, ptSecond, ptLast, ptSecLast;
pPline->getPointAt(0, ptFirst);
pPline->getPointAt(1, ptSecond);
pPline->getPointAt(len - 1, ptLast);
pPline->getPointAt(len - 2, ptSecLast);
AcGeVector3d vt1(ptFirst - ptSecond), vt2(ptLast - ptSecLast);
vt1.normalize();
vt2.normalize();
ptFirst += vt1 * dExt1;
ptLast += vt2 * dExt2;
AcGePoint2d pt1(ptFirst.convert2d(pln));
AcGePoint2d pt2(ptLast.convert2d(pln));
pPline->setPointAt(0, ptFirst.convert2d(pln));
pPline->setPointAt(len - 1, ptLast.convert2d(pln));
}
AcDbRegion* makeRegion(const int count, va_list ap)
{
AcDbVoidPtrArray ar;
AcGePoint3dArray pts;
for (int i = 0; i < count; ++i)
{
pts.append(va_arg(ap, AcGePoint3d));
}
if (pts.length() < 3) return NULL;
pts.append(pts[0]);
for (int i = 0; i < pts.length() - 1; ++i)
ar.append(new AcDbLine(pts[i], pts[i + 1]));
AcDbRegion* pReg = CoreTools::createRegion(ar);
deleteArrayVoidPtrs<AcDbEntity>(ar);
return pReg;
}
AcDbRegion* makeRegion2(const int count, ...)
{
va_list vlist;
va_start(vlist, count);
AcDbRegion* pReg = makeRegion(count, vlist);
va_end(vlist);
return pReg;
}
void drawSolid(AcGiDraw& dc, AcDbRegion* pReg, const AcGeVector3d& vt)
{
if (!pReg) return;
AcDbExtents ext;
pReg->getGeomExtents(ext);
AcGePoint3d ptCen(CoreTools::MidPt(ext.maxPoint(), ext.minPoint()));
AecDbEwPipeBase base;
base.setLayer(dc.GetLayerId());
base.SetSection(pReg, ptCen);
base.SetBaseCurve(ptCen, ptCen + vt);
base.Draw3d(dc);
dc.Add3dBuffer(base.Get3DBuffer());
base.Clean3DBufferNoDel();
}
}
AecDbBalconyDraw::AecDbBalconyDraw(void)
{
}
AecDbBalconyDraw::~AecDbBalconyDraw(void)
{
}
Acad::ErrorStatus AecDbBalconyDraw::Draw2d(AcGiDraw &dc) const
{
AcDbEntity* pEntReal = GetAttach();
if (pEntReal == NULL)
return Acad::eOk;
AecDbBalcony* pDblcony = AecDbBalcony::cast(pEntReal);
if (pDblcony == NULL)
return Acad::eOk;
BalconyData data;
memset(&data,0,sizeof(BalconyData));
pDblcony->GetBalconyData(data);
AcGeVector3d vtDir(0,0,0);
GetSpecialtyData()->GetAt(KEY_StartDir,vtDir);
AcDbCurve *pBaseCrv = pDblcony->GetBaseCurve();
AcDbPolyline *pPl = AcDbPolyline::cast(pBaseCrv);
if (!pPl)
{
DELETE_PTR(pBaseCrv);
return Acad::eOk;
}
AcDbPolyline *pOuter = (AcDbPolyline*)makeOffsetCurveByDir(pPl, data.dRailWidth, vtDir);
if (pOuter)
{
dc.DrawEntity(pOuter);
dc.Add2dBuffer(pOuter);
}
AcDbPolyline* pInner = (AcDbPolyline*)makeOffsetCurveByDir(pOuter, data.dSlabThick, -vtDir);
if (pInner)
{
extendCurve(pInner, -data.dSlabThick, -data.dSlabThick);
dc.DrawEntity(pInner);
dc.Add2dBuffer(pInner);
}
DELETE_PTR(pBaseCrv);
AcDbPolyline* pWall = (AcDbPolyline*)makeOffsetCurveByDir(pOuter, data.dRailWidth - data.dSlabThick * 2, -vtDir);
if (pWall)
{
AcGePoint3d ptOuterS, ptInnerS, ptOuterE, ptInnerE;
AcGePoint3d ptOuterS1, ptInnerS1, ptOuterE1, ptInnerE1;
pOuter->getStartPoint(ptOuterS);
pInner->getStartPoint(ptInnerS);
pOuter->getEndPoint(ptOuterE);
pInner->getEndPoint(ptInnerE);
pWall->getClosestPointTo(ptOuterS, ptOuterS1);
pWall->getClosestPointTo(ptInnerS, ptInnerS1);
pWall->getClosestPointTo(ptOuterE, ptOuterE1);
pWall->getClosestPointTo(ptInnerE, ptInnerE1);
AcDbLine *pL(new AcDbLine(ptOuterS, ptOuterS1));
dc.DrawEntity(pL);
dc.Add2dBuffer(pL);
pL = new AcDbLine(ptInnerS, ptInnerS1);
dc.DrawEntity(pL);
dc.Add2dBuffer(pL);
pL = new AcDbLine(ptOuterE, ptOuterE1);
dc.DrawEntity(pL);
dc.Add2dBuffer(pL);
pL = new AcDbLine(ptInnerE, ptInnerE1);
dc.DrawEntity(pL);
dc.Add2dBuffer(pL);
DELETE_PTR(pWall);
}
return Acad::eOk;
}
Acad::ErrorStatus AecDbBalconyDraw::Draw3d(AcGiDraw &dc) const
{
AcDbEntity* pEntReal = GetAttach();
if (pEntReal == NULL)
return Acad::eOk;
AecDbBalcony* pDblcony = AecDbBalcony::cast(pEntReal);
if (pDblcony == NULL)
return Acad::eOk;
BalconyData data;
memset(&data, 0, sizeof(BalconyData));
pDblcony->GetBalconyData(data);
AcGeVector3d vtDir(0, 0, 0);
GetSpecialtyData()->GetAt(KEY_StartDir, vtDir);
AcDbCurve* pBaseCrv = pDblcony->GetBaseCurve();
if (!pBaseCrv) return Acad::eOk;
AcDbPolyline *pPl = AcDbPolyline::cast(pBaseCrv);
if (!pPl)
{
DELETE_PTR(pBaseCrv);
return Acad::eOk;
}
pPl->setElevation(data.dBomEl);
//绘制底板
AcDbPolyline *pCurve = (AcDbPolyline*)makeOffsetCurveByDir(pPl, data.dRailWidth, vtDir);
if (!pCurve)
{
DELETE_PTR(pBaseCrv);
return Acad::eOk;
}
AcGePoint3d ptS, ptE;
pCurve->getPointAt(0, ptS);
pPl->getPointAt(0, ptE);
AcDbLine line1(ptS, ptE);
pCurve->getPointAt(pCurve->numVerts() - 1, ptS);
pPl->getPointAt(pPl->numVerts() - 1, ptE);
AcDbLine line2(ptS, ptE);
AcDbVoidPtrArray ptrs;
ptrs.append(&line1);
ptrs.append(&line2);
ptrs.append(pCurve);
ptrs.append(pPl);
AcDbRegion *pReg = CoreTools::createRegion(ptrs);
if (!pReg)
{
DELETE_PTR(pCurve);
DELETE_PTR(pBaseCrv);
return Acad::eOk;
}
drawSolid(dc, pReg, AcGeVector3d::kZAxis * data.dSlabThick);
AcDbRegion *pRegTop = (AcDbRegion *)pReg->clone();
DELETE_PTR(pReg);
AcGePoint3dArray ar;
AcGePoint3d pt;
for (int i = 0; i < pCurve->numVerts(); ++i)
{
pCurve->getPointAt(i, pt);
ar.append(pt);
}
DELETE_PTR(pCurve);
pPl->getStartPoint(ptS);
pPl->getEndPoint(ptE);
DELETE_PTR(pPl);
switch (data.nRailEdge)
{
case 0://全封闭
{
ar.insertAt(0, ptS);
ar.append(ptE);
break;
}
case 1://起点开
{
ar.append(ptE);
break;
}
case 2://终点开
{
ar.insertAt(0, ptS);
break;
}
case 3://全开
{
break;
}
default:
break;
}
AcDbPolyline *pPlRail = FormatPolyline(ar.asArrayPtr(), ar.length());
if (!pPlRail) return Acad::eOk;
AcDbPolyline *pPlRailOffset = (AcDbPolyline*)makeOffsetCurveByDir(pPlRail, data.dSlabThick, vtDir);
if (!pPlRailOffset)
{
DELETE_PTR(pPlRail);
return Acad::eOk;
}
pPlRail->getStartPoint(ptS);
pPlRailOffset->getStartPoint(ptE);
line1.setStartPoint(ptS);
line1.setEndPoint(ptE);
pPlRail->getEndPoint(ptS);
pPlRailOffset->getEndPoint(ptE);
line2.setStartPoint(ptS);
line2.setEndPoint(ptE);
ptrs.removeAll();
ptrs.append(&line1);
ptrs.append(&line2);
ptrs.append(pPlRail);
ptrs.append(pPlRailOffset);
pReg = CoreTools::createRegion(ptrs);
DELETE_PTR(pPlRailOffset);
DELETE_PTR(pPlRail);
if (!pReg)
return Acad::eOk;
drawSolid(dc, pReg, AcGeVector3d::kZAxis * data.dRailHeight);
DELETE_PTR(pReg);
//绘制玻璃窗户
if (data.bAddOpening)
{
//...
OpeningData opdata;
memset(&opdata, 0, sizeof(OpeningData));
opdata.ptPos.z = data.dBomEl + data.dRailHeight;
//默认数值
opdata.nType = 2;
opdata.nFlag = 0;//带型窗户
opdata.dWidth = 99999;//实际取路径
opdata.dBomEl = 0;
opdata.dHeight = data.duFrame;
opdata.dThick = data.dvFrame;
//data.dBomEl = m_dBomEl;
memset(opdata.dXData, 0, sizeof(double) * 16);
opdata.dXData[0] = 1000;
opdata.dXData[1] = 800;
opdata.dXData[2] = 65;
opdata.dXData[3] = 135;
opdata.dXData[4] = 30;
opdata.dXData[5] = data.dBomEl + data.dRailHeight;
_tcscpy(opdata.szBlockName2d, _T("*"));
_tcscpy(opdata.szBlockName3d, _T("*"));
_tcscpy(opdata.szName, _T("带型窗户"));
_tcscpy(opdata.szSpec, _T("断桥铝合金"));
_tcscpy(opdata.szFactory, _T("定做"));
_tcscpy(opdata.szNo, _T("AAA-00"));
AcGePoint3dArray arZLines;
arZLines.append(ar);
AcDbObjectId idLayer = KTSetting::InitLayer(_T("LAY_WIN"));
AcDbPolyline *pPlPath = FormatPolyline((AcGePoint3d *)arZLines.asArrayPtr(), arZLines.length());
dc.SetLayer(idLayer);
dc.SetColor(4);
DrawGlass(dc, pPlPath, opdata, idLayer);
}
//绘制顶板
if (data.nRailEdge == 0 && pRegTop != NULL)//全封闭
{
//...
AcGeVector3d vtZMov(0,0,0);
vtZMov.z = data.dRailHeight + data.duFrame;
AcGeMatrix3d xMove;
xMove.setToTranslation(vtZMov);
pRegTop->transformBy(xMove);
dc.SetLayer(pEntReal->layerId());
dc.SetColor(pEntReal->colorIndex());
drawSolid(dc, pRegTop, AcGeVector3d::kZAxis *data.dSlabThick);
}
return Acad::eOk;
}
void AecDbBalconyDraw::DrawGlass(AcGiDraw &dc, AcDbPolyline *pPl, const OpeningData &data, const AcDbObjectId &layerId) const
{
if (!pPl) return;
AecDbEwPipeBase wall;
double dBomEl = data.ptPos.z + data.dBomEl;
pPl->setElevation(dBomEl);
wall.setLayer(layerId);
wall.SetBaseCurve(pPl);
wall.SetSection(data.dXData[4], data.dHeight, 0.0, kMid);
wall.Draw3d(dc);
dc.Add3dBuffer(wall.Get3DBuffer());
wall.Clean3DBufferNoDel();
//下框架
wall.SetSection(data.dXData[2], data.dXData[2], 0.0, kMid);
wall.GetSpecialtyData()->SetAt(_T("COLOR"), 8);
wall.Draw3d(dc);
dc.Add3dBuffer(wall.Get3DBuffer());
wall.Clean3DBufferNoDel();
//第一格
double dEl1 = dBomEl + data.dXData[1];
pPl->setElevation(dEl1);
wall.SetSection(data.dXData[3], data.dXData[2], 0.0, kMid);
wall.SetSection(data.dXData[3], data.dXData[2], 0.0);
wall.SetBaseCurve(pPl);
wall.Draw3d(dc);
dc.Add3dBuffer(wall.Get3DBuffer());
wall.Clean3DBufferNoDel();
//顶框架
double dTopBom = dBomEl + data.dHeight - data.dXData[2];
pPl->setElevation(dTopBom);
wall.SetBaseCurve(pPl);
wall.Draw3d(dc);
dc.Add3dBuffer(wall.Get3DBuffer());
wall.Clean3DBufferNoDel();
//列框
double dSta = 0, dEnd = 0, dLen = 0;
pPl->getStartParam(dSta);
pPl->getEndParam(dEnd);
pPl->getDistAtParam(dEnd, dLen);
int nCols = (int)(dLen / data.dXData[0]);
double dStep = (dEnd - dSta) / nCols;
//恢复到底标高
pPl->setElevation(dBomEl);
AcDbLine ln;
AcGePoint3d ptSta, ptEnd;
wall.SetSection(data.dXData[2], data.dXData[2], 0.0);
wall.GetSpecialtyData()->SetAt(_T("COLOR"), 8);
//框架
AcGePoint3d ptOn;
for (int i = 0; i < nCols; i++)
{
pPl->getPointAtParam(dSta, ptSta);
ptSta.z = dBomEl;
ptEnd = ptSta;
ptEnd.z = ptSta.z + data.dHeight;
ln.setStartPoint(ptSta);
ln.setEndPoint(ptEnd);
wall.SetBaseCurve(&ln);
wall.Draw3d(dc);
dc.Add3dBuffer(wall.Get3DBuffer());
wall.Clean3DBufferNoDel();
dSta += dStep;
}
//拐点
for (int i = 1; i < pPl->numVerts() - 1; i++)
{
pPl->getPointAt(i, ptSta);
ptSta.z = dBomEl;
ptEnd = ptSta;
ptEnd.z = ptSta.z + data.dHeight;
ln.setStartPoint(ptSta);
ln.setEndPoint(ptEnd);
wall.SetBaseCurve(&ln);
wall.Draw3d(dc);
dc.Add3dBuffer(wall.Get3DBuffer());
wall.Clean3DBufferNoDel();
}
}