#include "StdAfx.h" #include "GiDrawutility.h" #include "EarThwormDef.h" namespace { Acad::ErrorStatus AddToModelSpace(AcDbEntity *pEnt, AcDbDatabase *pDb, bool bClose, AcDbObjectId *pId) { if (!pEnt) return Acad::eInvalidInput; if (pDb == NULL) pDb = acdbHostApplicationServices()->workingDatabase(); Acad::ErrorStatus es; AcDbBlockTable *pTbl = NULL; if (Acad::eOk == (es = pDb->getBlockTable(pTbl, AcDb::kForRead))) { AcDbBlockTableRecord *pBTR = NULL; if (Acad::eOk == (es = pTbl->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForWrite))) { es = pBTR->appendAcDbEntity(pEnt); if (es == Acad::eOk && pId) *pId = pEnt->objectId(); if (bClose) pEnt->close(); pBTR->close(); } pTbl->close(); } return es; } AcDbObjectId AddToModelSpace(AcDbEntity *pEnt, bool bClose) { if (!pEnt) return AcDbObjectId::kNull; AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase(); Acad::ErrorStatus es; AcDbObjectId id(AcDbObjectId::kNull); AcDbBlockTable *pTbl = NULL; if (Acad::eOk == (es = pDb->getBlockTable(pTbl, AcDb::kForRead))) { AcDbBlockTableRecord *pBTR = NULL; if (Acad::eOk == (es = pTbl->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForWrite))) { es = pBTR->appendAcDbEntity(id, pEnt); if (bClose) pEnt->close(); pBTR->close(); } pTbl->close(); } return id; } Acad::ErrorStatus CloneAndAddToModelSpace(const AcDbEntity *pEnt, int clr) { if (!pEnt) return Acad::eInvalidInput; AcDbEntity *p((AcDbEntity *)pEnt->clone()); p->setColorIndex(clr); return AddToModelSpace(p, NULL, true, NULL); } AcGePoint3d MidPt(AcGePoint3d ptGe1, AcGePoint3d ptGe2) { return AcGePoint3d((ptGe1.x + ptGe2.x) * 0.5 , (ptGe1.y + ptGe2.y) * .5 , (ptGe1.z + ptGe2.z) * .5); } Acad::ErrorStatus AddToModelSpace(AcDbEntity* pEnt, AcDbDatabase* pDb = NULL, bool bClose = true) { if (pDb == NULL) pDb = acdbHostApplicationServices()->workingDatabase(); Acad::ErrorStatus es; AcDbBlockTable* pTbl = NULL; if (Acad::eOk == (es = pDb->getBlockTable(pTbl, AcDb::kForRead))) { AcDbBlockTableRecord* pBTR = NULL; if (Acad::eOk == (es = pTbl->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForWrite))) { es = pBTR->appendAcDbEntity(pEnt); if (bClose) pEnt->close(); pBTR->close(); } pTbl->close(); } return es; } bool createRegion(const AcDbVoidPtrArray& curveSegments, AcDbVoidPtrArray& regions) { Acad::ErrorStatus es; if ( (es = AcDbRegion::createFromCurves(curveSegments, regions) ) != Acad::eOk) { acutPrintf(_T("\ncreateFromCurves failed:%d."),es); return false; } if (regions.isEmpty()) { acutPrintf(_T("\n result is empty.")); return false; } return true; } AcDbRegion* createRegion(AcDbEntity *pEnt) { AcDbVoidPtrArray arr, segs; arr.append(pEnt); if (!createRegion(arr, segs)) { return NULL; } return (AcDbRegion*)segs[0]; } AcDb3dPolyline* create3DPolyline(const AcGePoint3d *pBuffer, int len) { AcDb3dPolyline *p = new AcDb3dPolyline; if (!p) return NULL; for (int i = 0; i < len; ++i) { AcDb3dPolylineVertex *pV = new AcDb3dPolylineVertex(pBuffer[i]); p->appendVertex(pV); } p->makeClosed(); return p; } } // 把region变换到以 vtNormal为法向,以ptOnPlan为中心的面上,并且, 将region上的点ptOnRegion与平面中心点ptOnPlan对齐 AECDLLIMPEXP void GiDrawUtility::transfromRegion(AcDbRegion *pRegion , const AcGePoint3d &ptOnRegion , const AcGeVector3d &vtNormal , const AcGePoint3d &ptOnPlan) { AcGePlane plan; plan.set(ptOnPlan, vtNormal); AcGePoint3d pt0, pt1, pt2; plan.get(pt0, pt1, pt2); AcGeMatrix3d xform; xform.setToPlaneToWorld(plan); // 把region转到此面上 pRegion->transformBy(xform); // 把 region 上的点也转到面上 AcGePoint3d pt(ptOnRegion); pt.transformBy(xform); // 再把region在面上平移 AcGeVector3d vtm = ptOnPlan - pt; if (!vtm.isZeroLength()) { xform.setToIdentity(); xform.setToTranslation(ptOnPlan - pt); pRegion->transformBy(xform); } } AECDLLIMPEXP AcGeMatrix3d GiDrawUtility::RotateAndMove(const AcGeVector3d &vtOrig , const AcGePoint3d &ptOrig , const AcGeVector3d &vtDist , const AcGePoint3d &ptDist) { AcGeVector3d _vtOrig(vtOrig); AcGeVector3d _vtDist(vtDist); _vtOrig *= 1;// 保证长度不为0 _vtDist *= 1;// 保证长度不为0 AcGeMatrix3d mat(AcGeMatrix3d::kIdentity); //mat = _vtDist.rotateTo(_vtOrig); mat = _vtOrig.rotateTo(_vtDist); mat.setTranslation(ptDist - ptOrig); return mat; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawLoft(const AcDbRegion *pTop , const AcDbRegion *pBottom , const AcDbCurve *pLine) { AcDbRegion *_pTop = (AcDbRegion*)pTop->clone(); AcDbRegion *_pBottom = (AcDbRegion*)pBottom->clone(); AcDbCurve *_pLine(NULL); if (pLine) _pLine = (AcDbCurve *)pLine->clone(); AcArray arGuides; AcArray arSections; arSections.append(_pTop); arSections.append(_pBottom); AcDbLoftOptions op; AcDb3dSolid *pEnt = new AcDb3dSolid; if (pEnt->createLoftedSolid(arSections, arGuides, _pLine, op) != Acad::eOk) { DELETE_PTR(pEnt); DELETE_PTR(_pTop); DELETE_PTR(_pBottom); DELETE_PTR(_pLine); return NULL; } DELETE_PTR(_pTop); DELETE_PTR(_pBottom); DELETE_PTR(_pLine); return pEnt; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawLoft(const AcDbCurve *pTop , const AcDbCurve *pBottom , const AcDbCurve *pLine) { if (!pTop || !pBottom || !pLine) return NULL; AcDbCurve *_pTop = (AcDbCurve*)pTop->clone(); AcDbCurve *_pBottom = (AcDbCurve*)pBottom->clone(); AcDbCurve *_pLine = (AcDbCurve*)pLine->clone(); AcDbRegion *pRegT = createRegion(_pTop); AcDbRegion *pRegB = createRegion(_pBottom); if (!pRegT || !pRegB) return NULL; AcDbEntity *p = DrawLoft(pRegT, pRegB, pLine); DELETE_PTR(pRegT); DELETE_PTR(pRegB); DELETE_PTR(_pTop); DELETE_PTR(_pBottom); DELETE_PTR(_pLine); return p; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawRevolve(const AcDbLine& lnAxis , const AcDbRegion *pReg) { AcDbRegion *_pReg = (AcDbRegion*)pReg->clone(); AcDbRevolveOptions op; AcDb3dSolid *p = new AcDb3dSolid; if (p->createRevolvedSolid(_pReg , lnAxis.startPoint() , lnAxis.endPoint() - lnAxis.startPoint() , 2 * PI , .0 , op) != Acad::eOk) { DELETE_PTR(p); DELETE_PTR(_pReg); return NULL; } DELETE_PTR(_pReg); return p; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawRevolve(const AcDbLine& lnAxis , const AcDbCurve *pCurve) { if (!pCurve) return NULL; AcDbCurve *_pC = (AcDbCurve*)pCurve->clone(); AcDbRegion *pReg = createRegion(_pC); if (!pReg) { //DELETE_PTR(_pC); _pC->setColorIndex(1); AddToModelSpace(_pC); return NULL; } AcDbEntity *p = DrawRevolve(lnAxis, pReg); DELETE_PTR(pReg); DELETE_PTR(_pC); return p; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawRevolve(const AcDbLine& lnAxis , const AcGePoint3dArray& arSectionPtrs) { AcDb3dPolyline *pPL = create3DPolyline(arSectionPtrs.asArrayPtr() , arSectionPtrs.length()); if (!pPL) return NULL; return DrawRevolve(lnAxis, pPL); } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawCone(const AcGePoint3d &ptPos , const AcGeVector3d &vtMove , const double &Tr , const double &Br , const double &H , const double &xOffset) { AcGePoint3d ptBottom(AcGePoint3d::kOrigin); AcGePoint3d ptTop(ptBottom + xOffset * AcGeVector3d::kXAxis); ptTop.z = H; AcDbCircle cirB(ptBottom, AcGeVector3d::kZAxis, Br); AcDbCircle cirT(ptTop, AcGeVector3d::kZAxis, Tr); AcDbLine line(ptBottom, ptTop); AcDbEntity *p = DrawLoft(&cirT, &cirB, &line); if (!p) return NULL; p->transformBy(RotateAndMove(AcGeVector3d::kZAxis , ptBottom , vtMove, ptPos )); return p; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawExclude(const AcGePoint3dArray& arSectionPtrs, const AcGeVector3d &vtPath) { AcDb3dPolyline *pPL = create3DPolyline(arSectionPtrs.asArrayPtr(), arSectionPtrs.length()); if (!pPL) return NULL; return DrawExclude(pPL, vtPath); } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawMesh( const Adesk::UInt32 &rows , const Adesk::UInt32 &columns , const AcGePoint3d *pVertexList , bool bHasSeal /* = true*/) { // 去掉头尾两个无效面 int first = 1, last = rows - 1; if (!bHasSeal) { first = 0; last = rows; } // 取第一个点和最后一个点连成一条线 AcDbLine line(pVertexList[0], pVertexList[rows * columns - 1]); AcGePoint3d *pSection = new AcGePoint3d[columns]; AcArray vecPLs, vecGuides; for (int i = first; i < last; ++i) { ::memset(pSection, 0, sizeof(AcGePoint3d)*columns); ::memcpy(pSection, pVertexList + i * columns, sizeof(AcGePoint3d)*columns); AcDb3dPolyline *p3dPL = create3DPolyline(pSection, columns); vecPLs.append(p3dPL); } AcDbLoftOptions op; op.setRuled(true); op.setNormal(AcDbLoftOptions::kUseDraftAngles); AcDb3dSolid *pEnt = new AcDb3dSolid; if (pEnt->createLoftedSolid(vecPLs, vecGuides, &line, op) != Acad::eOk) { DELETE_PTR(pEnt); return NULL; } delete [] pSection; for (size_t i = 0; i < vecPLs.length(); ++i) { if (vecPLs[i]) DELETE_PTR(vecPLs[i]); } return pEnt; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawExclude(const AcDbRegion *pReg , const AcGePoint3d &ptInReg , const AcGeVector3d &vtPath) { AcDbRegion *_pReg = (AcDbRegion*)pReg->clone(); AcDbLine line; line.setStartPoint(ptInReg); line.setEndPoint(ptInReg + vtPath); AcDb3dSolid *p = new AcDb3dSolid; if (p->extrudeAlongPath(_pReg, &line) != Acad::eOk) { DELETE_PTR(p); DELETE_PTR(_pReg); return NULL; } DELETE_PTR(_pReg); return p; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawExclude(const AcDbCurve *pCurve, const AcGeVector3d &vtPath) { AcDbCurve *_pCurve = (AcDbCurve*)pCurve->clone(); AcDbRegion *pReg = createRegion(_pCurve); if (!pReg) { DELETE_PTR(_pCurve); return NULL; } AcDbExtents ext; pReg->getGeomExtents(ext); AcGePoint3d pt1(ext.maxPoint()), pt2(ext.minPoint()); AcGePoint3d ptS((pt1.x + pt2.x) * .5, (pt1.y + pt2.y) * .5, (pt1.z + pt2.z) * .5); AcDbEntity *p = DrawExclude(pReg, ptS, vtPath); DELETE_PTR(pReg); DELETE_PTR(_pCurve); return p; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawBox(const AcGePoint3d &ptPos , const AcGeVector3d &vtMove , const double &X , const double &Y , const double &Z) { AcDb3dSolid *pSolid = new AcDb3dSolid(); if (!pSolid) return NULL; if (Acad::eOk != pSolid->createBox(X, Y, Z)) return NULL; pSolid->transformBy( RotateAndMove(AcGeVector3d::kZAxis , AcGePoint3d::kOrigin , vtMove, ptPos) ); return pSolid; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawSphere(const AcGePoint3d &ptCenter , const double &dRadius) { AcDb3dSolid *pSolid = new AcDb3dSolid(); if (!pSolid) return NULL; if (Acad::eOk != pSolid->createSphere(dRadius)) return NULL; pSolid->transformBy( RotateAndMove(AcGeVector3d::kZAxis , AcGePoint3d::kOrigin , AcGeVector3d::kZAxis, ptCenter) ); return pSolid; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawPyramid(const AcGePoint3d &ptPos , const AcGeVector3d &vtMove , const double &Tx , const double &Ty , const double &Bx , const double &By , const double &H , const double &xOffset) { // 构建两个四边形region AcGePoint3d ptBottom(AcGePoint3d::kOrigin); AcGePoint3d ptTop(ptBottom + xOffset * AcGeVector3d::kXAxis); ptTop.z = H; double xt(Tx * .5), yt(Ty * .5), xb(Bx * .5), yb(By * .5); AcGePoint2d ptGeTop[4] = { AcGePoint2d(-xt, -yt) ,AcGePoint2d(-xt, yt) ,AcGePoint2d(xt, yt) ,AcGePoint2d(xt, -yt) }; AcGePoint2d ptGeBottom[4] = { AcGePoint2d(-xb, -yb) ,AcGePoint2d(-xb, yb) ,AcGePoint2d(xb, yb) ,AcGePoint2d(xb, -yb) }; AcGeMatrix3d mat; AcDbPolyline plTop; plTop.addVertexAt(0, ptGeTop[0]); plTop.addVertexAt(1, ptGeTop[1]); plTop.addVertexAt(2, ptGeTop[2]); plTop.addVertexAt(3, ptGeTop[3]); plTop.setClosed(Adesk::kTrue); mat.setToTranslation(ptTop - AcGePoint3d::kOrigin); plTop.transformBy(mat); AcDbPolyline plBottom; plBottom.addVertexAt(0, ptGeBottom[0]); plBottom.addVertexAt(1, ptGeBottom[1]); plBottom.addVertexAt(2, ptGeBottom[2]); plBottom.addVertexAt(3, ptGeBottom[3]); plBottom.setClosed(Adesk::kTrue); mat.setToTranslation(ptBottom - AcGePoint3d::kOrigin); plBottom.transformBy(mat); AcDbLine line(ptBottom, ptTop); AcDbEntity *p = DrawLoft(&plTop, &plBottom, &line); if (!p) return NULL; p->transformBy(RotateAndMove(AcGeVector3d::kZAxis , ptBottom , vtMove, ptPos)); return p; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawTydf(const AcGePoint3d &ptPos , const AcGeVector3d &vtMove , const double &Tr , const double &Bx , const double &By , const double &H , const double &xOffset , BOOL bIsTfdy) { AcGePoint3d ptBottom(AcGePoint3d::kOrigin); AcGePoint3d ptTop(ptBottom + xOffset * AcGeVector3d::kXAxis); ptTop.z = H; double xb(Bx * .5), yb(By * .5); AcGePoint2d ptGeBottom[4] = { AcGePoint2d(-xb, -yb) ,AcGePoint2d(-xb, yb) ,AcGePoint2d(xb, yb) ,AcGePoint2d(xb, -yb) }; AcGeMatrix3d mat; AcDbCircle cir(ptTop, AcGeVector3d::kZAxis, Tr); AcDbPolyline plBottom; plBottom.addVertexAt(0, ptGeBottom[0]); plBottom.addVertexAt(1, ptGeBottom[1]); plBottom.addVertexAt(2, ptGeBottom[2]); plBottom.addVertexAt(3, ptGeBottom[3]); plBottom.setClosed(Adesk::kTrue); mat.setToTranslation(ptBottom - AcGePoint3d::kOrigin); plBottom.transformBy(mat); AcDbLine line(ptBottom, ptTop); AcDbEntity *p = NULL; if (bIsTfdy) { AcGeVector3d vt(0,0,H); AcGeMatrix3d xForm1; xForm1.setToTranslation(vt); plBottom.transformBy(xForm1); ptBottom.transformBy(xForm1); xForm1.invert(); cir.transformBy(xForm1); ptTop.transformBy(xForm1); p = DrawLoft(&plBottom, &cir, &line); } else { p = DrawLoft(&cir, &plBottom, &line); } if (!p) return NULL; p->transformBy(RotateAndMove(AcGeVector3d::kZAxis , ptBottom , vtMove, ptPos)); return p; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawCylinder(const AcGePoint3d &ptFr , const AcGePoint3d &ptTo , const double &dRadius) { return DrawPipe(ptFr, ptTo, dRadius, 0.); } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawCirTorus(const AcGePoint3d &ptCenter , const AcGeVector3d &vtNormal , const double &majorRadius /* 大半径 */ , const double &minorRadius /* 小半径,大半径减小半径是管子直径 */ , const double &startAngle , const double &endAngle) { AcDbArc arc(ptCenter, vtNormal, (majorRadius + minorRadius) * .5, startAngle, endAngle); AcDbCircle cir(AcGePoint3d::kOrigin, AcGeVector3d::kZAxis, (majorRadius - minorRadius) * .5); return DrawPipe(&arc, &cir, AcGePoint3d::kOrigin); } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawRectTorus(const AcGePoint3d &ptCenter , const AcGeVector3d &vtNormal , const double &majorRadius /* 大半径 */ , const double &minorRadius /* 小半径 */ , const double &height /* 大半径减小半径是正方形的宽,这个参数是高 */ , const double &startAngle , const double &endAngle) { AcDbArc arc(ptCenter, vtNormal, (majorRadius + minorRadius) * .5, startAngle, endAngle); double dW = (majorRadius - minorRadius) * .5; double xt(dW * .5), yt(height * .5); AcGePoint2d ptGeTop[4] = { AcGePoint2d(-xt, -yt) ,AcGePoint2d(-xt, yt) ,AcGePoint2d(xt, yt) ,AcGePoint2d(xt, -yt) }; AcDbPolyline plTop; plTop.addVertexAt(0, ptGeTop[0]); plTop.addVertexAt(1, ptGeTop[1]); plTop.addVertexAt(2, ptGeTop[2]); plTop.addVertexAt(3, ptGeTop[3]); plTop.setClosed(Adesk::kTrue); return DrawPipe(&arc, &plTop, AcGePoint3d::kOrigin); } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawDish(const double &dH /*小半径*/ , const double &dD /* 大直径 */ , const AcGePoint3d &axisPnt , const AcGeVector3d &axisDir) { // 先构造一个(zox)面, 圆心为原点的1/4椭圆, 然后绕Z轴旋转 // 再转换到 axisPnt点,其中心轴(原Z轴)指向axisDir AcDbEllipse elArc(AcGePoint3d::kOrigin , -1 * AcGeVector3d::kYAxis , AcGeVector3d::kXAxis * dD * .5 , 2 * dH / dD , 0 , .5 * PI); AcDbLine line1(AcGePoint3d::kOrigin, AcGePoint3d(dD * .5, 0, 0)); AcDbLine line2(AcGePoint3d::kOrigin, AcGePoint3d(0, 0, dH)); AcDbVoidPtrArray arCurves, arRegs; arCurves.append(&line1); arCurves.append(&line2); arCurves.append(&elArc); if (AcDbRegion::createFromCurves(arCurves, arRegs) != Acad::eOk) return NULL; if (arRegs.isEmpty()) return NULL; AcDbEntity *p = DrawRevolve( AcDbLine(AcGePoint3d::kOrigin , AcGePoint3d::kOrigin + AcGeVector3d::kZAxis * 1) , (AcDbRegion*)arRegs[0]); if (!p) return NULL; AcGeMatrix3d mat = RotateAndMove(AcGeVector3d::kZAxis, AcGePoint3d::kOrigin, axisDir, axisPnt); p->transformBy(mat); AcDbEntity *pDel((AcDbEntity*)arRegs[0]); DELETE_PTR(pDel); return p; } AcDbEntity* GiDrawUtility::DrawPipe(const AcGePoint3d& ptFrom , const AcGePoint3d& ptTo , const double &dRadius , const double &dThick , const int &nSegs /*= 20*/) { AcDbCircle Cir1(AcGePoint3d::kOrigin, AcGeVector3d::kZAxis, dRadius); if (!createRegion(&Cir1)) return NULL; AcDbRegion *pBig = createRegion(&Cir1); if (!pBig) return NULL; AcDbRegion *pSml(NULL); if (!EQUAL_ZERO(dThick)) { AcDbCircle Cir2(AcGePoint3d::kOrigin, AcGeVector3d::kZAxis, dRadius - dThick); pSml = createRegion(&Cir2); if (!pSml) return NULL; } // 这里做一个布尔减 if (pBig && pSml) { if (pBig->booleanOper(AcDb::kBoolSubtract, pSml) != Acad::eOk) { acutPrintf(_T("\n DrawPipe booleanOper failed.")); DELETE_PTR(pBig); DELETE_PTR(pSml); return NULL; } } AcDbRegion *pRegion(pBig); AcDbLine path(ptTo, ptFrom); AcDbEntity *pSolid = DrawPipe(&path, pRegion, AcGePoint3d::kOrigin); DELETE_PTR(pRegion); return pSolid; } AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawPipe(const AcDbCurve* pCurve , const AcDbCurve* pPoly , const AcGePoint3d& ptCenInRgn) { if (!pPoly || !pCurve) return NULL; AcDbCurve *pClonePoly = (AcDbCurve*)pPoly->clone(); AcDbRegion *pRegion = createRegion(pClonePoly); AcDbEntity *pSolid = DrawPipe(pCurve, pRegion, ptCenInRgn); DELETE_PTR(pRegion); DELETE_PTR(pClonePoly); return pSolid; } // 分段长度大于max取max,小于max,取min static int spliteCurve(const AcDbCurve *pCurve, const double &max, const double &min, AcDbVoidPtrArray &ar) { Acad::ErrorStatus es; double dEnd = 0.0, dLen = 0.0, dSplitLen = 100000.0; es = pCurve->getEndParam(dEnd); if (es != Acad::eOk) return 0; es = pCurve->getDistAtParam(dEnd, dLen); if (es != Acad::eOk) return 0; if (dLen > max) dSplitLen = max; else dSplitLen = min; double dMax(dSplitLen), dPrec(10e-4); AcGePoint3d ptStart(AcGePoint3d::kOrigin), ptEnd(AcGePoint3d::kOrigin), pt(AcGePoint3d::kOrigin); es = pCurve->getPointAtDist(.0, ptStart); if (es != Acad::eOk) return 0; es = pCurve->getEndPoint(ptEnd); if (es != Acad::eOk) return 0; int quotient((int)(dLen / dMax)); double remainder(fmod(dLen, dMax)); if (remainder < dPrec) quotient -= 1; AcGePoint3dArray arPts; if (dLen - dMax > dPrec) { for (int i = 0; i < quotient; ++i) { if (pCurve->getPointAtDist((i + 1) * dMax, pt) != Acad::eOk) continue; arPts.append(pt); } } if (arPts.isEmpty()) return 0; es = pCurve->getSplitCurves(arPts, ar); return ar.length(); } static void deleteContainerOfArx(AcDbVoidPtrArray &ss) { while(!ss.isEmpty()) { AcDbEntity *p = (AcDbEntity *)ss.last(); ss.removeLast(); delete p; } } AcDbEntity* GiDrawUtility::DrawPipe(const AcDbCurve* pCurve , const AcDbPolyline* pPoly , const AcGePoint3d& ptCenInRgn) { return DrawPipe(pCurve, (AcDbCurve*)pPoly, ptCenInRgn); } AcDbEntity* GiDrawUtility::DrawPipe(const AcDbCurve *pCurve, double dR) { if (!pCurve) return NULL; //开始切向量,向内 AcGePoint3d ptS; AcGeVector3d vtS; pCurve->getStartPoint(ptS); if (Acad::eOk != pCurve->getFirstDeriv(ptS, vtS)) return NULL; AcDbCircle cir; cir.setNormal(vtS); cir.setCenter(ptS); cir.setRadius(dR); AcDbVoidPtrArray arCurPts, arRegs; arCurPts.append(&cir); AcDbRegion::createFromCurves(arCurPts, arRegs); if (arRegs.isEmpty()) return NULL; AcDbRegion *pReg = (AcDbRegion *)arRegs.first(); if (!pReg) return NULL; Acad::ErrorStatus es; AcDb3dSolid *pSolid = new AcDb3dSolid(); //当时闭合Polyline线时,extrudeAlongPath结果三维和CAD命令Extrude比较变小; //调整为createSweptSolid 和 CAD Extrude 命令结果一致 AcDbPolyline *pPl = AcDbPolyline::cast(pCurve); if (pPl != NULL && pPl->isClosed()) { AcDbSweepOptions sweepOp; es = pSolid->createSweptSolid((AcDbEntity *)pReg, (AcDbEntity *)pCurve, sweepOp); if (es != Acad::eOk) { acutPrintf(_T("\n拉伸错误:%d."), es); DELETE_PTR(pSolid); } } else { #ifndef ZWCAD es = pSolid->extrudeAlongPath(pReg, pCurve); DELETE_PTR(pReg); if (es != Acad::eOk) { DELETE_PTR(pSolid); // 处理 CAD 3D 实体体量不能大于 12000问题 // 拉伸 扫掠 实体,路径长不能大于 120000 ,圆,弧 除外 AcDbVoidPtrArray arCuvs; spliteCurve(pCurve, 100000., 10000., arCuvs); AcGePoint3d ptStart(AcGePoint3d::kOrigin); AcDbVoidPtrArray arSolids; for (int i = 0; i < arCuvs.length(); ++i) { AcDbCurve *p((AcDbCurve *)arCuvs[i]); if (!p) continue; AcDbEntity *pSo(DrawPipe(p, dR)); if (pSo) arSolids.append(pSo); } deleteContainerOfArx(arCuvs); if (!arSolids.isEmpty()) { pSolid = (AcDb3dSolid *)((AcDbEntity *)arSolids.first())->clone(); for (int i(1); i < arSolids.length(); ++i) es = pSolid->booleanOper(AcDb::kBoolUnite, (AcDb3dSolid *)arSolids[i]); deleteContainerOfArx(arSolids); } else acutPrintf(_T("\n拉伸错误.")); } #else AcDbSweepOptions sweepOp; es = pSolid->createSweptSolid((AcDbEntity *)pReg, (AcDbEntity *)pCurve, sweepOp); DELETE_PTR(pReg); if (es != Acad::eOk) { DELETE_PTR(pSolid); acutPrintf(_T("\n扫掠错误:%d."), es); } #endif } return pSolid; } AcDbEntity *GiDrawUtility::DrawPipe( const AcDbCurve *pCurve , const AcDbRegion *pRegion , const AcGePoint3d &ptCenInRgn) { if (!pRegion || !pCurve) return NULL; AcGePoint3d ptStart(AcGePoint3d::kOrigin); if (pCurve->getStartPoint(ptStart) != Acad::eOk) return NULL; AcGePoint3d ptEnd; if (pCurve->getEndPoint(ptEnd) != Acad::eOk) return NULL; AcGeVector3d vtNormal(AcGeVector3d::kIdentity); if (pCurve->getFirstDeriv(ptStart, vtNormal) != Acad::eOk) return NULL; AcDbRegion *pCloneRegion = (AcDbRegion*)pRegion->clone(); transfromRegion(pCloneRegion, ptCenInRgn, vtNormal, ptStart); Acad::ErrorStatus es; AcDb3dSolid *pSolid = new AcDb3dSolid(); //当时闭合Polyline线时,extrudeAlongPath结果三维和CAD命令Extrude比较变小; //调整为createSweptSolid 和 CAD Extrude 命令结果一致 AcDbPolyline* pPl = AcDbPolyline::cast(pCurve); if (pPl != NULL && pPl->isClosed() ) { AcDbSweepOptions sweepOp; es = pSolid->createSweptSolid((AcDbEntity*)pCloneRegion,(AcDbEntity*)pCurve,sweepOp); DELETE_PTR(pCloneRegion); if (es != Acad::eOk) { DELETE_PTR(pSolid); acutPrintf(_T("\n拉伸错误:%d."), es); } } else { #ifndef ZWCAD es = pSolid->extrudeAlongPath(pCloneRegion, pCurve); DELETE_PTR(pCloneRegion); if (es != Acad::eOk) { DELETE_PTR(pSolid); // 处理 CAD 3D 实体体量不能大于 12000问题 // 拉伸 扫掠 实体,路径长不能大于 120000 ,圆,弧 除外 AcDbVoidPtrArray arCuvs; spliteCurve(pCurve, 100000., 10000., arCuvs); AcGePoint3d ptStart(AcGePoint3d::kOrigin); AcDbVoidPtrArray arSolids; for (int i = 0; i < arCuvs.length(); ++i) { AcDbCurve *p((AcDbCurve *)arCuvs[i]); if (!p) continue; AcDbEntity *pSo(DrawPipe(p, pRegion, ptCenInRgn)); if (pSo) arSolids.append(pSo); } deleteContainerOfArx(arCuvs); if (!arSolids.isEmpty()) { pSolid = (AcDb3dSolid *)((AcDbEntity *)arSolids.first())->clone(); for (int i(1); i < arSolids.length(); ++i) es = pSolid->booleanOper(AcDb::kBoolUnite, (AcDb3dSolid *)arSolids[i]); deleteContainerOfArx(arSolids); } else acutPrintf(_T("\n拉伸错误.")); } #else AcDbSweepOptions sweepOp; es = pSolid->createSweptSolid((AcDbEntity *)pCloneRegion, (AcDbEntity *)pCurve, sweepOp); DELETE_PTR(pCloneRegion); if (es != Acad::eOk) { DELETE_PTR(pSolid); acutPrintf(_T("\n扫掠错误:%d."), es); } #endif } return pSolid; }