admin 发表于 2024-2-23 22:50:43

[每日一码] AcBr 类开发代码

//
// ObjectARX defined commands
#include "StdAfx.h"
#include "StdArx.h"
#include "brbrep.h"      // AcBrBrep
#include "dbents.h"
#include "dbregion.h"      // AcDbRegion
#include "dbpl.h"      // AcDbPolyline
#include "gecomp3d.h"      // AcGeCompositeCurve2d
// 根据轻量多段线创建对应的AcGeCurve2d对象
BOOL PolylineToGeCurve(const AcDbPolyline *&pPline,
                                           AcGeCurve3d *&pGeCurve)
{
      int nSegs;      // 多段线的段数
      AcGeLineSeg3d line, *pLine;      // 几何曲线的直线段部分
      AcGeCircArc3d arc, *pArc;      // 几何曲线的圆弧部分
      AcGeVoidPointerArray geCurves;      // 指向组成几何曲线的分段曲线的指针数组
      nSegs = pPline->numVerts() - 1;
      // 根据多段线创建对应的分段几何曲线
      for (int i = 0; i < nSegs; i++)
      {
                if (pPline->segType(i) == AcDbPolyline::kLine)
                {
                        pPline->getLineSegAt(i, line);
                        pLine = new AcGeLineSeg3d(line);
                        geCurves.append(pLine);
                }
                else if (pPline->segType(i) == AcDbPolyline::kArc)
                {
                        pPline->getArcSegAt(i, arc);
                        pArc = new AcGeCircArc3d(arc);
                        geCurves.append(pArc);
                }
      }
      // 处理闭合多段线最后一段是圆弧的情况
      if (pPline->isClosed() && pPline->segType(nSegs) == AcDbPolyline::kArc)
      {
                pPline->getArcSegAt(nSegs, arc);
                pArc = new AcGeCircArc3d(arc);
                pArc->setAngles(arc.startAng(), arc.endAng() -
                        (arc.endAng() - arc.startAng()) / 100);
                geCurves.append(pArc);
      }
      // 根据分段的几何曲线创建对应的复合曲线
      if (geCurves.length() == 1)
      {
                pGeCurve = (AcGeCurve3d *)geCurves;
      }
      else
      {
                pGeCurve = new AcGeCompositeCurve3d(geCurves);
      }
      // 释放动态分配的内存
      for (i = 0; i < geCurves.length(); i++)
      {
                delete geCurves<i>;
      }
      return TRUE;
}
// 将实体添加到图形数据库的模型空间
AcDbObjectId PostToModelSpace(AcDbEntity* pEnt)
{
      AcDbBlockTable *pBlockTable;
      acdbHostApplicationServices()->workingDatabase()
                ->getBlockTable(pBlockTable, AcDb::kForRead);
      AcDbBlockTableRecord *pBlockTableRecord;
      pBlockTable->getAt(ACDB采用MODEL采用SPACE, pBlockTableRecord,
                AcDb::kForWrite);   
      AcDbObjectId entId;
      pBlockTableRecord->appendAcDbEntity(entId, pEnt);
      pBlockTable->close();
      pBlockTableRecord->close();
      pEnt->close();
      return entId;
}
// 根据给定的边界对象创建面域
AcDbObjectIdArray CreateRegion(const AcDbObjectIdArray& curveIds)
{
      AcDbObjectIdArray regionIds;      // 生成的面域的ID数组
      AcDbVoidPtrArray curves;      // 指向作为面域边界的曲线的指针的数组
      AcDbVoidPtrArray regions;      // 指向创建的面域对象的指针的数组
      AcDbEntity *pEnt;      // 临时指针,用来关闭边界曲线
      AcDbRegion *pRegion;      // 临时对象,用来将面域添加到模型空间
      // 用curveIds初始化curves
      for (int i = 0; i < curveIds.length(); i++)
      {
                acdbOpenAcDbEntity(pEnt, curveIds.at(i), AcDb::kForRead);
                if (pEnt->isKindOf(AcDbCurve::desc()))
                {
                        curves.append(static采用cast<void*>(pEnt));
                }
      }
      Acad::ErrorStatus es = AcDbRegion::createFromCurves(curves, regions);
      if (es == Acad::eOk)
      {
                // 将生成的面域添加到模型空间
                for (i = 0; i < regions.length(); i++)
                {
                        // 将空指针(可指向任何类型)转化为指向面域的指针
                        pRegion = static采用cast<AcDbRegion*>(regions<i>);
                        pRegion->setDatabaseDefaults();
                        AcDbObjectId regionId;
                        regionId = PostToModelSpace(pRegion);
                        regionIds.append(regionId);
                }
      }
      else      // 如果创建不成功,也要删除已经生成的面域
      {
                for (i = 0; i < regions.length(); i++)
                {
                        delete (AcRxObject*)regions<i>;
                }
      }
      // 关闭作为边界的对象
      for (i = 0; i < curves.length(); i++)
      {
                pEnt = static采用cast<AcDbEntity*>(curves<i>);
                pEnt->close();
      }
      return regionIds;
}
// 判断点是否在指定的面域内部
bool PtInRegion(AcGePoint3d &pt, AcDbRegion *pRegion)
{
      if (pRegion == NULL)
                return false;
      AcBrBrep brep;
      if (brep.set(*pRegion) != AcBr::eOk)
                return false;
      AcBr::Relation relation;
      AcBr::ErrorStatus es = brep.getPointRelationToBrep(pt, relation);
      if (es != AcBr::eOk)
                return false;
      switch (relation)
      {
      case AcBr::kBoundary:
      case AcBr::kInside:
                return true;
      default:
                return false;
      }
}
// 判断一条多段线是否在另一条多段线内部
bool PolyInRegion(AcDbPolyline *pPoly, AcDbRegion *pRegion)
{
      if ((pPoly == NULL) || (pRegion == NULL))
                return false;
      // 创建Brep实体
      AcBrBrep brep;
      if (brep.set(*pRegion) != AcBr::eOk)
                return false;
      // 根据多段线创建对应的几何类
      //AcGeCurve3d *pGeCurve = NULL;
      AcGeLineSeg3d *pGeCurve = new AcGeLineSeg3d(AcGePoint3d(50, 50, 0),
                AcGePoint3d(60, 60, 0));
      //PolylineToGeCurve(pPoly, pGeCurve);
      AcBr::Relation relation;
      AcBr::ErrorStatus es = brep.getCurveRelationToBrep(*pGeCurve, relation);
      delete pGeCurve;      // 在函数PolylineToGeCurve中分配了内存
      if (es != AcBr::eOk)
                return false;
      switch (relation)
      {
      case AcBr::kBoundary:
      case AcBr::kInside:
                return true;
      default:
                return false;
      }
}
// This is command 'PTINREGION'
void ZffCHAP2PtInRegion()
{
      // 创建一个圆作为拉伸的截面
      AcGeVector3d vec(0, 0, 1);      // 圆所在平面的法矢量
      AcGePoint3d ptCenter(30, 0, 0);      // 圆心位置与半径的大小有关
      AcDbCircle *pCircle = new AcDbCircle(ptCenter, vec, 30);
      AcDbObjectId circleId = PostToModelSpace(pCircle);
      // 根据圆创建一个面域
      AcDbObjectIdArray boundaryIds, regionIds;
      boundaryIds.append(circleId);
      regionIds = CreateRegion(boundaryIds);
      // 打开面域
      AcDbRegion *pRegion;
      acdbOpenObject(pRegion, regionIds, AcDb::kForRead);
      AcGePoint3d pt(1, 0, 0);
      if (PtInRegion(pt, pRegion) == true)
      {
                acedAlert("True");
      }
      pRegion->close();
}
// This is command 'POLYCONTAIN'
void ZffCHAP2PolyContain()
{
      // 提示用户选择对象
      ads采用name en1, en2;
      ads采用point pt;
      if (acedEntSel("n选择第一条多段线:", en1, pt) != RTNORM)
                return;
      if (acedEntSel("n选择第二条多段线:", en2, pt) != RTNORM)
                return;
      // 获得选择对象的指针
      AcDbObjectId polyId1, polyId2;
      Acad::ErrorStatus es = acdbGetObjectId(polyId1, en1);
      es = acdbGetObjectId(polyId2, en2);
      AcDbPolyline *pPoly;
      es = acdbOpenObject(pPoly, polyId1, AcDb::kForRead);
      // 根据第二条多段线创建一个面域
      AcDbObjectIdArray boundaryIds, regionIds;
      boundaryIds.append(polyId2);
      regionIds = CreateRegion(boundaryIds);
      // 打开面域
      AcDbRegion *pRegion;
      acdbOpenObject(pRegion, regionIds, AcDb::kForWrite);
      if (PolyInRegion(pPoly, pRegion) == true)
      {
                acedAlert("第一条多段线在第二条多段线内部!");
      }
      pPoly->close();
      pRegion->erase();
      pRegion->close();
}

admin 发表于 2024-2-23 22:51:32

我在CAD2008使用过程中发现BOOL PolylineToGeCurve(const AcDbPolyline *&pPline,
                                           AcGeCurve3d *&pGeCurve)函数生成的AcGeCurve3d* 并没有被释放,导致CAD的占用内存越用越大,不知道是怎么回事。
// 释放动态分配的内存
      for (i = 0; i < geCurves.length(); i++)
      {
                delete geCurves;
      }
这一段语句实际上是不能运行的:
错误      4      error C2440: 'delete' : cannot convert from 'AcGeVoidPointerArray' to 'void *'      d:\backup\documents\ymf\软件开发\nbtsurvey开发版\vc\nbtsurvey\nbtsurvey\cconversion.cpp      290
页: [1]
查看完整版本: [每日一码] AcBr 类开发代码