明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 1966|回复: 2

ObjectArx 实现类似C# 的DrawJig,支持多实体拖动

  [复制链接]
发表于 2024-11-9 17:28:04 | 显示全部楼层 |阅读模式
首先实现接口,因为AcEdJig 仅仅支持单实体进行更新显示,如果用多实体那么就需要一个AcDbEntity 去包装,本次我们换个方式,直接在类中加入AcDbEntity接口,实现subWorldDraw显示多个图元



  1. class DrawJig : public AcDbEntity, public AcEdJig {
  2. public:
  3.         virtual DragStatus sampler() = 0;
  4.         virtual bool  update() = 0;
  5.         virtual bool subWorldDraw(AcGiWorldDraw* mode) = 0;
  6. protected:
  7.         AcDbEntity* entity() const final
  8.         {
  9.                 return (AcDbEntity*)this;
  10.         }
  11. };
复制代码
下面用一个简单的例子继承测试下

  1. class TestDrrawJig :public DrawJig {
  2. public:
  3.         TestDrrawJig() {}
  4.         bool startDrag(AcGePoint3d ptCenter);
  5.         DragStatus sampler() override;
  6.         bool update() override;
  7.         bool subWorldDraw(AcGiWorldDraw* mode)override;
  8.         AcGePoint2d Point3dTo2d(AcGePoint3d pnt);
  9.         AcDbVoidPtrArray CreateEntitys();
  10.         AcArray<AcDbEntity*> GetEntities();
  11. private:
  12.         AcGePoint3d m_centerPnt;
  13.         AcGePoint3d m_curPnt;
  14.         AcDbVoidPtrArray m_aryPtr;
  15. };

  16. inline AcEdJig::DragStatus TestDrrawJig::sampler()
  17. {
  18.         setUserInputControls((UserInputControls)(AcEdJig::kAccept3dCoordinates
  19.                 | AcEdJig::kNoNegativeResponseAccepted
  20.                 | AcEdJig::kNullResponseAccepted));
  21.         AcGePoint3d pointTemp;
  22.         DragStatus stat = acquirePoint(m_curPnt);
  23.         if (pointTemp != m_curPnt)
  24.         {
  25.                 pointTemp = m_curPnt;
  26.         }
  27.         else if (stat == AcEdJig::kNormal)
  28.         {
  29.                 return AcEdJig::kNoChange;
  30.         }
  31.         return stat;
  32. }

  33. inline bool TestDrrawJig::update()
  34. {
  35.         for (int i = 0; i < m_aryPtr.length(); i++)
  36.         {
  37.                 AcDbEntity* pEnt = (AcDbEntity*)m_aryPtr.at(i);
  38.                 delete pEnt;
  39.                 pEnt = NULL;
  40.         }
  41.         //创建新实体
  42.         m_aryPtr = CreateEntitys();

  43.         return Adesk::kTrue;
  44. }
  45. inline bool TestDrrawJig::subWorldDraw(AcGiWorldDraw* mode)
  46. {
  47.         for (int i = 0; i < m_aryPtr.length(); i++)
  48.         {
  49.                 AcDbEntity* pEnt = (AcDbEntity*)m_aryPtr[i];
  50.                 mode->geometry().draw(pEnt);
  51.         }

  52.         return Adesk::kTrue;
  53. }


  54. inline AcGePoint2d TestDrrawJig::Point3dTo2d(AcGePoint3d pnt)
  55. {
  56.         return AcGePoint2d(pnt.x, pnt.y);
  57. }

  58. inline AcDbVoidPtrArray TestDrrawJig::CreateEntitys()
  59. {
  60.         AcDbVoidPtrArray aryEnts;
  61.         //创建实体
  62.         double dist = Point3dTo2d(m_curPnt).distanceTo(Point3dTo2d(m_centerPnt));
  63.         AcGeVector2d vec = Point3dTo2d(m_curPnt) - Point3dTo2d(m_centerPnt);
  64.         AcGePoint2d pt1, pt2, pt3, pt4;
  65.         pt1 = Point3dTo2d(m_curPnt);
  66.         pt3 = pt1 - 2 * vec;
  67.         vec.rotateBy(PI * 0.5);
  68.         pt2 = Point3dTo2d(m_centerPnt) + vec;
  69.         pt4 = pt2 - 2 * vec;
  70.         AcDbPolyline* poly = new AcDbPolyline;
  71.         poly->addVertexAt(0, pt1);
  72.         poly->addVertexAt(1, pt2);
  73.         poly->addVertexAt(2, pt3);
  74.         poly->addVertexAt(3, pt4);
  75.         poly->setClosed(Adesk::kTrue);
  76.         poly->setColorIndex(1);
  77.         aryEnts.append(static_cast<void*>(poly));
  78.         AcDbCircle* circle = new AcDbCircle(m_centerPnt, AcGeVector3d::kZAxis, pt1.distanceTo(pt2) * 0.5);
  79.         circle->setColorIndex(3);
  80.         aryEnts.append(static_cast<void*>(circle));
  81.         return aryEnts;
  82. }

  83. inline AcArray<AcDbEntity*> TestDrrawJig::GetEntities()
  84. {
  85.         AcArray <AcDbEntity*> ents;
  86.         for (int i = 0; i < m_aryPtr.length(); i++) {
  87.                 ents.append((AcDbEntity*)(m_aryPtr[i]));
  88.         }
  89.         return ents;
  90. }

  91. inline bool TestDrrawJig::startDrag(AcGePoint3d ptCenter)
  92. {
  93.         m_centerPnt = ptCenter;
  94.         m_curPnt = ptCenter;
  95.         AcString prompt = _T("\n指定角点");
  96.         setDispPrompt(prompt);
  97.         AcEdJig::DragStatus stat = drag();
  98.         if (stat == AcEdJig::kNormal)
  99.         {
  100.                 return true;
  101.         }
  102.         else
  103.         {
  104.                 return false;
  105.         }
  106. }
  1. void tsJig()
  2. {
  3.         DbTrans tr;
  4.         auto btr = tr.CurrentSpace();
  5.         auto res = MapleGetPoint();
  6.         if (!res.Ok) return;
  7.         TestDrrawJig jig;
  8.         if (jig.startDrag(res.Value)) {
  9.                 auto ents = jig.GetEntities();
  10.                 tr.AddEntities(btr, ents);
  11.         }

  12. }
复制代码
这样就可以使用多实体Jig了,与C#的DrawJig 差不多
发表于 2024-12-27 22:16:42 来自手机 | 显示全部楼层
arx本来就有,类似c#不知道几个意思
回复 支持 反对

使用道具 举报

发表于 2025-5-17 18:27:52 | 显示全部楼层
本帖最后由 cable2004 于 2025-5-17 19:12 编辑

  1.   class CMoveJig : public AcEdJig {
  2.   public:
  3.     CMoveJig() : mBasePoint(), mCurrentPoint(), mOffset() {}

  4.     AcEdJig::DragStatus Start(const AcDbObjectIdArray& objIds, const AcGePoint3d& basePoint) {
  5.       mObjIds = objIds;
  6.       mBasePoint = basePoint;
  7.       mCurrentPoint = basePoint;
  8.       mOffset.set(0.0, 0.0, 0.0);
  9.       if (!PrepareDisplayEntities()) {
  10.         return kCancel;
  11.       }

  12.       setDispPrompt(_T("\n指定目标点: "));
  13.       setSpecialCursorType(AcEdJig::kCrosshair);

  14.       DragStatus stat = drag();

  15.       if (stat == kNormal) {
  16.         MoveOriginalEntities();
  17.       }

  18.       CleanupDisplayEntities();
  19.       return stat;
  20.     }

  21.   protected:
  22.     virtual DragStatus sampler() {
  23.       AcGePoint3d newPt;
  24.       DragStatus stat = acquirePoint(newPt, mBasePoint);
  25.       if (stat == kNormal && !newPt.isEqualTo(mCurrentPoint)) {
  26.         mCurrentPoint = newPt;
  27.         mOffset = mCurrentPoint - mBasePoint;
  28.         return kNormal;
  29.       }
  30.       return stat;
  31.     }

  32.     virtual Adesk::Boolean update() {
  33.       AcGeMatrix3d xform;
  34.       xform.setToTranslation(mOffset); // 创建平移矩阵
  35.       for (int i = 0; i < mDisplayEntities.length(); ++i) {
  36.         if (mDisplayEntities) {
  37.           mDisplayEntities->transformBy(xform);
  38.         }
  39.       }
  40.       acedRedraw(NULL, 1);
  41.       return Adesk::kTrue;
  42.     }

  43.     // 返回第一个实体作为主实体
  44.     virtual AcDbEntity* entity() const override {
  45.       return mDisplayEntities.isEmpty() ? NULL : mDisplayEntities[0];
  46.     }

  47.     // 添加额外方法获取所有实体
  48.     const AcArray<AcDbEntity*>& entities() const {
  49.       return mDisplayEntities;
  50.     }

  51.     virtual Adesk::Boolean worldDraw(AcGiWorldDraw* pWorldDraw) {
  52.       for (int i = 0; i < mDisplayEntities.length(); ++i) {
  53.         if (mDisplayEntities) {
  54.           mDisplayEntities->worldDraw(pWorldDraw);
  55.           if (mDisplayEntities != NULL)
  56.           {
  57.             pWorldDraw->geometry().draw(mDisplayEntities);
  58.           }
  59.         }
  60.       }
  61.       return Adesk::kTrue;
  62.     }

  63.   private:
  64.     AcDbObjectIdArray mObjIds;
  65.     AcGePoint3d mBasePoint;
  66.     AcGePoint3d mCurrentPoint;
  67.     AcGeVector3d mOffset;
  68.     AcArray<AcDbEntity*> mDisplayEntities;

  69.     bool PrepareDisplayEntities() {
  70.       for (int i = 0; i < mObjIds.length(); ++i) {
  71.         AcDbEntity* pEnt = NULL;
  72.         if (acdbOpenObject(pEnt, mObjIds, AcDb::kForRead) == Acad::eOk) {
  73.           AcDbEntity* pClone = static_cast<AcDbEntity*>(pEnt->clone());
  74.           if (pClone) {
  75.             mDisplayEntities.append(pClone);
  76.           }
  77.           pEnt->close();
  78.         }
  79.       }
  80.       return mDisplayEntities.length() > 0;
  81.     }

  82.     void CleanupDisplayEntities() {
  83.       for (int i = 0; i < mDisplayEntities.length(); ++i) {
  84.         if (mDisplayEntities) {
  85.           delete mDisplayEntities;
  86.         }
  87.       }
  88.       mDisplayEntities.removeAll();
  89.     }

  90.     void MoveOriginalEntities() {
  91.       AcGeMatrix3d xform;
  92.       xform.setToTranslation(mOffset); // 创建平移矩阵
  93.       for (int i = 0; i < mObjIds.length(); ++i) {
  94.         AcDbEntity* pEnt = NULL;
  95.         if (acdbOpenObject(pEnt, mObjIds, AcDb::kForWrite) == Acad::eOk) {
  96.           pEnt->transformBy(xform);
  97.           pEnt->close();
  98.         }
  99.       }
  100.     }


  101.      
  102.   };

  103.   // 移动选中对象命令入口函数
  104.   static void Cmd_MoveSelected() {
  105.     ads_name ss;
  106.     if (RTNORM != acedSSGet(NULL, NULL, NULL, NULL, ss)) {
  107.       acutPrintf(_T("\n未选择对象"));
  108.       return;
  109.     }

  110.     AcDbObjectIdArray objIds;
  111.     Adesk::Int32 length = 0;
  112.     acedSSLength(ss, &length);

  113.     for (long i = 0; i < length; ++i) {
  114.       ads_name ent;
  115.       acedSSName(ss, i, ent);
  116.       AcDbObjectId id;
  117.       acdbGetObjectId(id, ent);
  118.       objIds.append(id);
  119.     }
  120.     acedSSFree(ss);

  121.     ads_point pt;
  122.     if (RTNORM != acedGetPoint(NULL, _T("\n指定基点: "), pt)) {
  123.       return;
  124.     }

  125.     acdbUcs2Wcs(pt, pt, false);
  126.     AcGePoint3d basePt = asPnt3d(pt);

  127.     CMoveJig jig;
  128.     jig.Start(objIds, basePt);
  129.   }


模仿一个move移动的功能,为什么不能时时看到移动的过程,最终结果是对的。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-5-31 01:17 , Processed in 0.157793 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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