#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(arr); return pNew; } AcDbPolyline* pNewCurve1 = (AcDbPolyline*)(((AcDbEntity*)ar.first())->clone()); deleteArrayVoidPtrs(ar); AcDbPolyline* pNewCurve2 = (AcDbPolyline*)(((AcDbEntity*)ar2.first())->clone()); deleteArrayVoidPtrs(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& 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 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(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(); } }