找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 807|回复: 0

[分享] [ObjectARX]-几何类的使用

[复制链接]

已领礼包: 13个

财富等级: 恭喜发财

发表于 2019-1-18 08:00:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
打开VS2015,使用ObjectARX向导创建新工程,名为BaseGeometryClass。

(1)计算直线几何类和 圆弧几何类的交点。

注册命令InsertsetWith,实现代码:

  1. static void AAAMyGroupIntersectWith() {
  2.                 // 计算所要计算交点的几何类对象
  3.                 AcGeCircArc2d geArc(AcGePoint2d::kOrigin, 50, 0, 6);
  4.                         //AcGePoint2d::kOrigin返回一个坐标为(0,0)的点
  5.                         //圆弧的圆心为(0,0),半径为50,起始角0;终止角6

  6.                 AcGeLine2d geLine(AcGePoint2d::kOrigin, AcGePoint2d(10, 10));
  7.                         //构造一条穿过(0,0)和(10, 10)的**线
  8.                
  9.                 //计算并输出交点
  10.                 AcGePoint2d point1, point2;
  11.                 int num;
  12.                 if (geArc.intersectWith(geLine, num, point1, point2))//如果存在交点,intersectWith返回Adesk::kTrue
  13.                 {
  14.                         acutPrintf(TEXT("\n直线和圆弧有%d个交点."), num);
  15.                         if (num > 0)
  16.                         {
  17.                                 acutPrintf(TEXT("\n交点1坐标:(%.4f,%.4f)."), point1.x, point1.y);
  18.                         }
  19.                         if (num > 1)
  20.                         {
  21.                                 acutPrintf(TEXT("\n交点2坐标:(%.4f,%.4f)."), point2.x, point2.y);
  22.                         }
  23.                 }

  24.         }

效果:

  加载AutoCAD2018,执行命令IntersectWith:

[ObjectARX]-几何类的使用-1.jpg

快捷键Ctrl+F2 打开文本窗口:

直线和圆弧有2个交点.
交点1坐标:(35.3553,35.3553).
交点2坐标:(-35.3553,-35.3553).
(2)注册一个新命令LineDistance

  用于提示用户在图形窗口中选择两条直线,计算两条直线之间的最短距离,并在命令窗口中选择两条直线,计算两条直线之阿的最短距离并在命令窗口中输出:

  1. static void AAAMyGroupLineDistance() {
  2.                 // 提示用户选择所要计算距离的两条直线
  3.                 AcDbObjectIdArray lineIds;
  4.                 if (CSelectUtil::PromptSelectEnts(TEXT("\n选择两条直线:"), AcDbLine::desc(), lineIds))
  5.                 {

  6.                         if (lineIds.length() != 2)
  7.                         {
  8.                                 acutPrintf(TEXT("\n必须选择两条直线."));
  9.                                 return;
  10.                         }

  11.                         //将直线转换成对应的几何类对象
  12.                         AcGeLineSeg2d geLine1 = GetGeLineObj(lineIds[0]);
  13.                         AcGeLineSeg2d geLine2 = GetGeLineObj(lineIds[1]);

  14.                         //计算并输出两者之间的最短距离
  15.                         double distance = geLine1.distanceTo(geLine2);
  16.                         acutPrintf(TEXT("\n两条直线之间的最短距离为:%.4f."), distance);
  17.                 }
  18.         }

其中,

GetGeLineObj函数的实现:

        
  1. //根据输入的实体ID获得相同参数的AcGeLineSeg2d对象
  2.         static AcGeLineSeg2d GetGeLineObj(AcDbObjectId lineId)
  3.         {
  4.                 AcGeLineSeg2d geLine; //AcGeLineSeg2d:在二维空间中表示一个有界的线段。
  5.                 AcDbLine *pLine = NULL;
  6.                 if (acdbOpenObject(pLine, lineId, AcDb::kForRead) == Acad::eOk)
  7.                                                  //指针pLine指向打开的对象lineId
  8.                 {
  9.                         geLine.set(ToPoint2d(pLine->startPoint()),
  10.                                 ToPoint2d(pLine->endPoint()));
  11.                         pLine->close();
  12.                 }
  13.                 return geLine;
  14.         }
ToPoint2d函数的实现:

        
  1. // 二维点和三维点之间的转换
  2.         static AcGePoint2d ToPoint2d(const AcGePoint3d &point3d)
  3.         {
  4.                 return AcGePoint2d(point3d.x, point3d.y);
  5.         }
  6. PromptSelectEnts函数的实现:

  7. bool CSelectUtil::PromptSelectEnts(const TCHAR* prompt, AcRxClass* classDesc, AcDbObjectIdArray &entIds)
  8. {
  9.         std::vector<AcRxClass*> vecClassDesc;
  10.         vecClassDesc.push_back(classDesc);

  11.         return PromptSelectEnts(prompt, vecClassDesc, entIds);
  12. }

  13. bool CSelectUtil::PromptSelectEnts(const TCHAR* prompt, const std::vector<AcRxClass*> &classDescs, AcDbObjectIdArray &entIds)
  14. {
  15.         // 初始化
  16.         entIds.setLogicalLength(0);

  17.         // 提示用户选择实体
  18.         ads_name sset;
  19.         int result = 0;
  20.         acutPrintf(prompt);
  21.         result = acedSSGet(NULL, NULL, NULL, NULL, sset);

  22.         if (result != RTNORM)
  23.         {
  24.                 return false;
  25.         }

  26.         // 取得选择集的长度
  27.         long length = 0;
  28.         acedSSLength(sset, (Adesk::Int32 *)&length);

  29.         // 遍历选择集
  30.         Acad::ErrorStatus es;
  31.         AcDbEntity* pEnt = NULL;
  32.         for (long i = 0; i < length; i++)
  33.         {
  34.                 ads_name ename;
  35.                 acedSSName(sset, i, ename);

  36.                 AcDbObjectId curEntId;
  37.                 es = acdbGetObjectId(curEntId, ename);
  38.                 if (es != Acad::eOk)
  39.                 {
  40.                         continue;
  41.                 }

  42.                 // 打开实体
  43.                 es = acdbOpenObject(pEnt, curEntId, AcDb::kForRead);
  44.                 if (es != Acad::eOk)
  45.                 {
  46.                         continue;
  47.                 }

  48.                 // 判断当前实体是否是指定的实体类型
  49.                 for (int j = 0; j < (int)classDescs.size(); j++)
  50.                 {
  51.                         if (pEnt->isKindOf(classDescs[j]))
  52.                         {
  53.                                 entIds.append(pEnt->objectId());
  54.                                 break;
  55.                         }
  56.                 }

  57.                 pEnt->close();        // 关闭实体
  58.         }
  59.         acedSSFree(sset);        // 释放选择集

  60.         return (entIds.length() > 0);
  61. }
效果:

在AutoCAD2018中创建两条直线,执行命令LineDistance,得到两直线的最短距离。

[ObjectARX]-几何类的使用-2.jpg

(3)注册新命令CurveBoolean

  用于获得两条曲线相交之后形成的边界线:

命令CurveBoolean 函数的实现:

  1. //获得两条曲线相交之后形成的边界线
  2.         static void AAAMyGroupCurveBoolean() {
  3.                 //选择所要操作的两条多段线
  4.                 AcDbObjectIdArray polyIds;
  5.                 if (CSelectUtil::PromptSelectEnts(TEXT("\n选择两条多段线:"),
  6.                         AcDbPolyline::desc(), polyIds))//获得polyIds,返回bool
  7.                 {
  8.                         if (polyIds.length() != 2)
  9.                         {
  10.                                 acutPrintf(TEXT("\n必须选择两条多段线."));
  11.                                 return;
  12.                         }

  13.                         //获得两条多段线的交点
  14.                         bool bOk = false;
  15.                         AcDbPolyline *pPoly1 = NULL, *pPoly2 = NULL;
  16.                         if (acdbOpenObject(pPoly1, polyIds[0], AcDb::kForWrite) == Acad::eOk)
  17.                         {             //pPoly1指向打开的对象polyIds[0]

  18.                                 if (acdbOpenObject(pPoly2, polyIds[1], AcDb::kForWrite) ==
  19.                                         Acad::eOk)
  20.                                 {
  21.                                         AcGePoint3dArray intPoints;
  22.                                         pPoly1->intersectWith(pPoly2, AcDb::kOnBothOperands,
  23.                                                 intPoints);//pPoly2:pPoly1实体将与之相交的实体
  24.                                         //kOnBothOperands:不要扩展任何一个实体。这只会计算出两个实体
  25.                                         //的几何相交的交点
  26.                                         //intPoints:表示输出的交点

  27.                                         if (intPoints.length() >= 2)
  28.                                         {
  29.                                                 bOk = true;
  30.                                         }
  31.                                         else
  32.                                         {
  33.                                                 acutPrintf(TEXT("\n多段线之间交点少于2个,无法进行计算."));
  34.                                         }

  35.                                         //根据交点和参数值获得交点之间的曲线
  36.                                         if (bOk)
  37.                                         {
  38.                                                 GetCurveBetweenIntPoints(pPoly1, intPoints);
  39.                                                 GetCurveBetweenIntPoints(pPoly2, intPoints);

  40.                                                 pPoly2->erase(); //擦除对象
  41.                                         }
  42.                                         pPoly2->close(); //关闭对象,自从它被打开以来,对对象所做的所有更改
  43.                                                          //都被提交到数据库中

  44.                                 }

  45.                                 if (bOk)
  46.                                 {
  47.                                         pPoly1->erase();
  48.                                 }

  49.                                 pPoly1->close();
  50.                         }
  51.                 }

  52.         }

其中:

GetCurveBetweenIntPoints函数的实现:

  1. static void GetCurveBetweenIntPoints(AcDbPolyline *pPoly,
  2.                 const AcGePoint3dArray &intPoints)
  3.         {
  4.                 AcDbVoidPtrArray curves;
  5.                 pPoly->getSplitCurves(intPoints, curves);
  6.                     //在曲线上输入参数的数组intPoints
  7.                     //返回到新创建的实体的指针curves,这些实体是原始的子曲线

  8.                 for (int i = 0; i < curves.length(); i++)
  9.                 {
  10.                         AcDbCurve *pCurve = static_cast<AcDbCurve*>(curves);

  11.                         //删除首尾两条曲线,其他段的曲线添加到模型空间
  12.                         if (i == 0 || i == curves.length() - 1)
  13.                         {
  14.                                 delete pCurve;
  15.                         }
  16.                         else
  17.                         {
  18.                                 AcDbObjectId curveId = CDwgDatabaseUtil::PostToModelSpace(pCurve);
  19.                         }
  20.                 }
  21.         }

其中:

PostToModelSpace函数的声明:

        
  1. static AcDbObjectId PostToModelSpace(AcDbEntity *pEnt,
  2.                AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase());
  3. PostToModelSpace函数的实现:

  4. AcDbObjectId CDwgDatabaseUtil::PostToModelSpace(AcDbEntity *pEnt, AcDbDatabase *pDb)
  5. {
  6.         // 检查输入参数的有效性
  7.         assert(pEnt);                // 等效于assert (pEnt != NULL);

  8.                                                 // 获得当前图形数据库的块表
  9.         AcDbBlockTable *pBlkTbl = NULL;
  10.         pDb->getBlockTable(pBlkTbl, AcDb::kForRead);

  11.         // 获得模型空间对应的块表记录
  12.         AcDbBlockTableRecord *pBlkTblRcd = NULL;
  13.         pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForWrite);
  14.         pBlkTbl->close();

  15.         // 将实体添加到模型空间的块表记录
  16.         AcDbObjectId entId;
  17.         Acad::ErrorStatus es = pBlkTblRcd->appendAcDbEntity(entId, pEnt);
  18.         if (es != Acad::eOk)
  19.         {
  20.                 pBlkTblRcd->close();
  21.                 delete pEnt;        // 添加失败时,要delete
  22.                 pEnt = NULL;

  23.                 return AcDbObjectId::kNull;
  24.         }

  25.         // 关闭模型空间块表记录和实体
  26.         pBlkTblRcd->close();
  27.         pEnt->close();

  28.         return entId;
  29. }
效果:

绘制两条多段线,执行命令CurveBoolean:


[ObjectARX]-几何类的使用-3.jpg

[ObjectARX]-几何类的使用-1.jpg

项目完整代码:

   https://pan.baidu.com/s/1M5MsYoQFIvF04oCSOv68yA

参考资料:

  《AutoCAD ObjectARX(VC)开发基础与实例教程》
---------------------
作者:李燕良
来源:CSDN
原文:https://blog.csdn.net/qq_40416052/article/details/82961341
版权声明:本文为博主原创文章,转载请附上博文链接!



论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-4-24 04:16 , Processed in 0.168927 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表