#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; }