设为首页收藏本站

中国膜结构网

 找回密码
 立即注册
膜结构车棚
膜结构车棚膜结构资质国产膜材 膜结构网中国膜结构协会
查看: 96|回复: 3

ObjectARX自定义实体

[复制链接]
  • TA的每日心情
    开心
    2021-3-9 08:49
  • 签到天数: 1442 天

    连续签到: 21 天

    [LV.10]以坛为家III

    发表于 2021-1-19 14:36 | 显示全部楼层 |阅读模式
    http://www.mjgw.org/ 专业从事膜结构设计、制作加工、施工安装的膜结构咨询服务,能够为客户提供专业的膜结构整体解决方案。做中国最好的膜结构综合服务平台。欢迎大家联系QQ:463017170.
    https://blog.csdn.net/phd17621680432/article/details/89181257?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522161103786216780299088680%252522%25252C%252522scm%252522%25253A%25252220140713.130102334..%252522%25257D&request_id=161103786216780299088680&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-89181257.first_rank_v2_pc_rank_v29&utm_term=%20arx%20%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AE%9E%E4%BD%93
    说明: 此次绘制的CAD自定义实体是一个矩形,具有拉伸功能。因为初次接触自定义实体,在一次次制作的过程中遇到了很多困难,幸好有老大和同事的帮助,当然还有广大网友们的文章协助,才完成了这个自定义实体的绘制。我不敢说到目前还会有什么问题,但希望能帮助到别人。

    一、需要重载的函数
        //绘制夹点
        virtual Acad::ErrorStatus getGripPoints(AcDbGripDataPtrArray& grips, const double curViewUnitSize, const int gripSize, const AcGeVector3d& curViewDir, const int bitflags) const;
            //移动夹点
            virtual Acad::ErrorStatus moveGripPointsAt(const AcDbVoidPtrArray& gripAppData,const AcGeVector3d& offset,const int bitflags);
            //加载数据
            virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* pFiler);
            //保存数据
            virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* pFiler) const;
            //矩阵转换
            virtual Acad::ErrorStatus transformBy(const AcGeMatrix3d& xform);
            //分解(炸开)
            virtual Acad::ErrorStatus explode(ZcDbVoidPtrArray& entitySet) const;
            //夹点状态
            virtual void gripStatus(const AcDb::GripStat status);
            //实体绘制
            virtual Adesk::Boolean worldDraw(AcGiWorldDraw* pWd);
            //捕捉点
            virtual Acad::ErrorStatus getOsnapPoints(AcDb::OsnapMode osnapMode, Adesk::GsMarker gsSelectionMark, const AcGePoint3d& pickPoint, const AcGePoint3d& lastPoint,
                    const AcGeMatrix3d& viewXform, AcGePoint3dArray& snapPoints, AcDbIntArray & geomIds) const;
            //外包矩形
            virtual Acad::ErrorStatus getGeomExtents(AcDbExtents& extents) const;
            //删除
            virtual        Acad::ErrorStatus erase(Adesk::Boolean erasing = true);

    二、成员变量
    因为这个自定义实体是矩形,所以是由四个直线组成,且由三个夹点。

            AcDbLine m_lineHori1;
            AcDbLine m_lineHori2;
            AcDbLine m_lineVert1;
            AcDbLine m_lineVert2;

            AcGePoint3d m_ptBase;               
            AcGePoint3d m_ptRight;       
            AcGePoint3d m_ptTop;

    所以在写重载函数时,每个直线实体都要写一下。例如在worldDraw函数:

    Adesk::Boolean CDiBanCsm::worldDraw(AcGiWorldDraw* pWd)
    {
            assertReadEnabled();
            m_lineHori1.worldDraw(pWd);
            m_lineHori2.worldDraw(pWd);
            m_lineVert1.worldDraw(pWd);
            m_lineVert2.worldDraw(pWd);
            return Adesk::kTrue;
    }

    因为有夹点这个成员变量,所以,在dwgInFields函数、dwgOutFields函数、transformBy函数中也要将夹点添加进去:

    Acad::ErrorStatus CDiBanCsm::dwgInFields(AcDbDwgFiler* pFiler)
    {
            assertWriteEnabled();
            AcDbEntity::dwgInFields(pFiler);

            m_lineHori1.dwgInFields(pFiler);
            m_lineHori2.dwgInFields(pFiler);
            m_lineVert1.dwgInFields(pFiler);
            m_lineVert2.dwgInFields(pFiler);
           
            pFiler->readPoint3d(&m_ptBase);
            pFiler->readPoint3d(&m_ptRight);
            pFiler->readPoint3d(&m_ptTop);

            return pFiler->filerStatus();
    }

    三、夹点绘制
    绘制夹点比较麻烦,如果你不是要绘制夹点的形状,可以重载

    Acad::ErrorStatus getGripPoints(
        AcGePoint3dArray& gripPoints,
        AcDbIntArray & osnapModes,
        AcDbIntArray & geomIds
    ) const;

    只需要在gripPoints参数中添加夹点坐标就可以,夹点为默认夹点。
    这里,我们需要改变夹点的形状,所以这里我们需要绘制夹点。夹点用AcDbGripData类绘制,它是new出来的,所以我们需要将它delete。
    我们需要重载gripStatus函数,在AcDb::kGripsDone状态下,将new的AcDbGripData指针delte。
    我们要声明一个全局的map变量来存放AcDbGripData指针:

    //键:自定义实体指针                值:AcDbGripData指针数组
    static std::map<const AcDbEntity*, AcDbGripDataPtrArray> s_mapGripPtr;

    直接上代码了:

    Acad::ErrorStatus CDiBanCsm::getGripPoints(AcDbGripDataPtrArray& grips, const double curViewUnitSize,
            const int gripSize, const AcGeVector3d& curViewDir, const int bitflags) const
    {
            assertReadEnabled();
            std::vector<CString>::const_iterator appIter = GetGripName();//这里appIter是一个字符串容器,存放的是夹点名称
            AcDbGripDataPtrArray tempGripArr;

            //BasePt
            AcDbGripData* pGripBase = new AcDbGripData();
            pGripBase->setAppData((void*)&(*appIter));//将夹点名称设置到数据中
            pGripBase->setGripPoint(m_ptBase);//设置夹点坐标
            grips.append(pGripBase);
            tempGripArr.append(pGripBase);
            appIter++;

            //RightPt
            AcDbGripData* pGripRight = new AcDbGripData();
            pGripRight->setAppData((void*)&(*appIter));
            pGripRight->setGripPoint(m_ptRight);
            pGripRight->setWorldDraw(DrawStretchGrip);
            grips.append(pGripRight);
            tempGripArr.append(pGripRight);
            appIter++;

            //TopPt
            AcDbGripData* pGripTop = new AcDbGripData();
            pGripTop->setAppData((void*)&(*appIter));
            pGripTop->setGripPoint(m_ptTop);
            pGripTop->setWorldDraw(DrawStretchGrip);
            grips.append(pGripTop);
            tempGripArr.append(pGripTop);
            appIter++;

            auto a = this;
            CCustomBase::s_mapGripPtr[this] = tempGripArr;//将new出来的AcDbGripData指针添加到s_mapGripPtr变量中
            return Acad::eOk;
    }

    bool CDiBanCsm:rawStretchGrip(AcDbGripData *pThis, AcGiWorldDraw *pWd, const AcDbObjectId& entId, AcDbGripOperations:rawType type, AcGePoint3d *cursor, double dGripSize)
    {
            dGripSize *= CCustomBase::s_gripSize / 2;//夹点的大小 CCustomBase::s_gripSize == 2.8
            AcGePoint3d        pt = pThis->gripPoint();
            CString* pStr = (CString*)(pThis->appData());
            AcGeVector3d vec = AcGeVector3d::kXAxis;
            AcDbObjectPointer<CDiBanCsm> m_pDiBan(entId, AcDb::kForRead);
            if (m_pDiBan.openStatus() != Acad::eOk)
                    return false;

            if (*pStr == _T("RightPt"))
                    vec = m_pDiBan->GetHoriDirection().normal();//得到实体的水平向量,这个接口自己写,通过直线的两点坐标
            else if (*pStr == _T("TopPt"))
                    vec = m_pDiBan->GetVertDirection().normal();//得到实体的垂直向量

            auto vecUp = AcGeVector3d::kZAxis.crossProduct(vec).normal();
            AcGePoint3d pts[3];
            pts[0] = pt + vec * dGripSize;
            pts[1] = pt - vec * dGripSize / 2 + vecUp * dGripSize * .7;
            pts[2] = pt - vec * dGripSize / 2 - vecUp * dGripSize * .7;

            pWd->subEntityTraits().setFillType(kAcGiFillAlways);
            pWd->geometry().polygon(3, pts);

            return true;
    }

    在重载的gripStatus函数中delete夹点指针

    void CDiBanCsm::gripStatus(const AcDb::GripStat status)
    {
            AcDbEntity::gripStatus(status);

            switch (status)
            {
            case AcDb::kGripsDone:
                    CCustomBase:eleteGrip(this);
                    break;
            case AcDb::kGripsToBeDeleted:
                   
                    break;
            case AcDb::kDimDataToBeDeleted:

                    break;
            }
    }

    bool CCustomBase:eleteGrip(const AcDbEntity* pEnt)
    {
            std::map<const AcDbEntity*, AcDbGripDataPtrArray>::iterator iter;
            for (iter = s_mapGripPtr.begin(); iter != s_mapGripPtr.end(); iter++)
            {
                    if (pEnt == iter->first)
                    {
                            AcDbGripDataPtrArray tempGripArr = iter->second;
                            for (int i = 0; i < tempGripArr.length(); ++i)
                            {
                                    DEL(tempGripArr);//这里delete 指针
                                    tempGripArr = NULL;
                            }
                    }
            }
            int n = CCustomBase::s_mapGripPtr.erase(pEnt);//如果删除了会返回1,否则返回0  
            return n;
    }

    移动夹点就比较简单了,重写moveGripPointsAt函数就可以了

    Acad::ErrorStatus CDiBanCsm::moveGripPointsAt(const AcDbVoidPtrArray& gripAppData,const AcGeVector3d& offset,
    const int bitflags)
    {
            assertWriteEnabled();
            CString* pStrTemp = NULL;
            for (int i = 0; i < gripAppData.length(); i++)
            {
                    pStrTemp = static_cast<CString*>(gripAppData);
                    if (*pStrTemp == _T("BasePt"))//通过点的名称,判断移动的是哪个夹点
                    {
                            //这里我是通过偏移向量,来移动直线的两点位置
                            SetLinePoint(m_lineHori1, 3, offset);
                            SetLinePoint(m_lineHori2, 3, offset);
                            SetLinePoint(m_lineVert1, 3, offset);
                            SetLinePoint(m_lineVert2, 3, offset);
                            m_ptBase = GetBaseGripPt();//重新定义夹点的位置
                            m_ptRight = GetRightGripPt();
                            m_ptTop = GetTopGripPt();
                    }
                    else if (*pStrTemp == _T("RightPt"))
                    {
                            AcGePoint3d ptStart = m_lineHori2.startPoint();
                            AcGePoint3d ptEnd = m_lineHori2.endPoint();
                            AcGeVector3d vctHori = ptEnd - ptStart;
                            AcGeVector3d vctOffset = GetProjectVector(m_ptBase, offset, vctHori);
                            SetLinePoint(m_lineHori1,2,vctOffset);
                            SetLinePoint(m_lineHori2, 2, vctOffset);
                            SetLinePoint(m_lineVert2, 3, vctOffset);
                            m_ptBase = GetBaseGripPt();
                            m_ptRight = GetRightGripPt();
                            m_ptTop = GetTopGripPt();
                    }
                    else if (*pStrTemp == _T("TopPt"))
                    {
                            AcGePoint3d ptStart = m_lineVert1.startPoint();
                            AcGePoint3d ptEnd = m_lineVert1.endPoint();
                            AcGeVector3d vctHori = ptEnd - ptStart;
                            AcGeVector3d vctOffset = GetProjectVector(m_ptBase, offset, vctHori);
                            SetLinePoint(m_lineVert1, 2, vctOffset);
                            SetLinePoint(m_lineVert2, 2, vctOffset);
                            SetLinePoint(m_lineHori1, 3, vctOffset);
                            m_ptBase = GetBaseGripPt();
                            m_ptRight = GetRightGripPt();
                            m_ptTop = GetTopGripPt();
                    }
            }
            return Acad::eOk;
    }

    AcGeVector3d CCustomBase::GetProjectVector(const AcGePoint3d& ptBase, const AcGeVector3d& vctOffset, const AcGeVector3d& vctDirection)
    {//得到某一向量在指定向量上的投影向量
            AcGePoint3d ptOffset = ptBase + vctOffset;
            AcGeLine3d geLine(ptBase, vctDirection);
            AcGePoint3d ptTarget = geLine.closestPointTo(ptOffset);
            return ptTarget - ptBase;
    }

    四、实体分解
    需要重写explode函数,这里有两个知识要说,一个是如果自定义实体可以分解,需要添加克隆的直线指针

    Acad::ErrorStatus CDiBanCsm::explode(ZcDbVoidPtrArray& entitySet) const
    {
            assertReadEnabled();
            entitySet.append(m_lineHori1.clone());
            entitySet.append(m_lineHori2.clone());
            entitySet.append(m_lineVert1.clone());
            entitySet.append(m_lineVert2.clone());
            return Acad::eOk;
    }

    如果你想让自定义实体不能分解,返回值返回:Acad::eCannotExplodeEntity即可。

    五、总结
    其实原本的代码比这个多很多,这里我只是截取了重要部分展示。这是目前绘制的自定义实体,某些地方还需要改进。
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2021-3-9 08:49
  • 签到天数: 1442 天

    连续签到: 21 天

    [LV.10]以坛为家III

     楼主| 发表于 2021-1-19 14:39 | 显示全部楼层
    1. 本文介绍了构造自定义实体的步骤、必须继承的函数和必须注意的事项
    2. 1.新建一个从AcDbEntity继承的类,如EntTest,必须添加的头文件: "stdarx.h","acadstrc.h", "geassign.h"。
    3. 2.在该类头文件的类声明中添加宏:ACRX_DECLARE_MEMBERS(EntTest);
    4. 3.在该类的cpp文件中,类的前面添加宏:
    5. ACRX_DXF_DEFINE_MEMBERS(EntTest, AcDbEntity,AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent,0,平面实体,"autoCAD");//第5个参数为在CAD中该实体类的名称,
    6. MAKE_ACDBOPENOBJECT_FUNCTION(EntTest);
    7. 4.从AcDbEntity类中重载几个必须的虚函数:
    8.       virtual Adesk::Boolean worldDraw(AcGiWorldDraw* mode);
    9.      virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler*);
    10.     virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler*) const;
    11. virtual Acad::ErrorStatus getGripPoints(AcGePoint3dArray& gripPoints,AcDbIntArray&osnapModes,AcDbIntArray& geomIds) const;
    12.     virtual Acad::ErrorStatus moveGripPointsAt(const AcDbIntArray& indices,const AcGeVector3d& offset);
    13. 5.实现第4步中几个虚函数必须注意:
    14.   在dwgInFields函数的开始处必须有:
    15.    assertWriteEnabled();
    16. AcDbObject::dwgInFields(pFiler);
    17. if(pFiler->filerType()==AcDb::kWblockCloneFiler)
    18. {
    19.   AcDbHardPointerId Id;
    20.   pFiler->readItem(&Id);
    21. }
    22. 在dwgOutFields函数的开始处必须有:
    23.      assertReadEnabled();
    24.   AcDbObject::dwgOutFields(pFiler);
    25.   if (pFiler->filerType()==AcDb::kWblockCloneFiler)
    26.    pFiler->writeHardPointerId((AcDbHardPointerId)ownerId());
    27. 上叙两个函数是用来写入写出自定义实体的成员变量的,以保证在拖动夹点的过程中这些变量是实时变化的(可以在worldDraw或moveGripPointsAt中改变这些值)。成员变量不能为指针,在要用数组指针的场合可用Carray数组来实现。
    28. 6.这一步很重要,少了它就不是自定义实体了,呵呵。
    29. 在InitApplication()函数中添加:
    30.   EntTest::rxInit();
    31.   acrxBuildClassHierarchy();
    32. 下面是一个最简单的自定义实体的例子,一根线段,变量成员只有StartPoint,EndPoint,最重要的那几个重载的虚函数的作用和运行顺序得靠自己去慢慢摸索了。我想这个例子刚入门的你还是有点帮助的,注意:AddEntityToDbs()函数也比不可少
    33. 头文件:
    34. #if !defined(AFX_ACDBENTITYTEST_H__E622CCB1_4E1D_4985_8813_0CEE3BF4ED20__INCLUDED_)
    35. #define AFX_ACDBENTITYTEST_H__E622CCB1_4E1D_4985_8813_0CEE3BF4ED20__INCLUDED_
    36. #if _MSC_VER > 1000
    37. #pragma once
    38. #endif // _MSC_VER > 1000
    39. #include "stdafx.h"
    40. #include "stdarx.h"
    41. #include "acadstrc.h"
    42. #include "geassign.h"
    43. #include "acedads.h"
    44. #include "math.h"
    45. #include <fstream.h>

    46. class AcdbEntityTest:public AcDbEntity
    47. {
    48. public:
    49. ACRX_DECLARE_MEMBERS(AcdbEntityTest);
    50. AcdbEntityTest();
    51. virtual ~AcdbEntityTest();
    52. virtual void Initialize();


    53. //自定义实体必须重载的函数----------------------------------------------------
    54.     virtual Adesk::Boolean worldDraw(AcGiWorldDraw* mode);
    55. virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler*);
    56.     virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler*) const;
    57. virtual Acad::ErrorStatus getGripPoints(AcGePoint3dArray& gripPoints,
    58.   AcDbIntArray& osnapModes,
    59.   AcDbIntArray& geomIds) const;

    60.     virtual Acad::ErrorStatus moveGripPointsAt(const AcDbIntArray& indices,
    61.   const AcGeVector3d& offset);

    62. virtual Acad::ErrorStatus getOsnapPoints(
    63.   AcDb::OsnapMode   osnapMode,
    64.   int               gsSelectionMark,
    65.   const AcGePoint3d&    pickPoint,
    66.   const AcGePoint3d&    lastPoint,
    67.   const AcGeMatrix3d&   viewXform,
    68.   AcGePoint3dArray& snapPoints,
    69.   AcDbIntArray&     geomIds) const ;

    70. private:
    71. AcGePoint3d StartPoint;
    72. AcGePoint3d EndPoint;
    73. };
    74. #endif // !defined(AFX_ACDBENTITYTEST_H__E622CCB1_4E1D_4985_8813_0CEE3BF4ED20__INCLUDED_)
    75. cpp:
    76. #include "stdafx.h"
    77. #include "stdarx.h"
    78. #include "Resource.h"
    79. #include "acadstrc.h"
    80. #include "geassign.h"
    81. #include "acedads.h"
    82. #include "math.h"
    83. #include <fstream.h>
    84. #include "AcdbEntityTest.h"
    85. #include "global.h"
    86. ACRX_DXF_DEFINE_MEMBERS(AcdbEntityTest, AcDbEntity,AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent,0,EntityDIM,"autoCAD");
    87. MAKE_ACDBOPENOBJECT_FUNCTION(AcdbEntityTest);
    88. #ifdef _DEBUG
    89. #undef THIS_FILE
    90. static char THIS_FILE[]=__FILE__;
    91. #define new DEBUG_NEW
    92. #endif
    93. //
    94. // Construction/Destruction
    95. //
    96. AcdbEntityTest::AcdbEntityTest()
    97. {
    98. abarx=new AboutArx();
    99. }
    100. AcdbEntityTest::~AcdbEntityTest()
    101. {

    102. }
    103. Acad::ErrorStatus AcdbEntityTest::dwgInFields(AcDbDwgFiler* pFiler)
    104. {
    105. assertWriteEnabled();
    106. AcDbObject::dwgInFields(pFiler);
    107. if(pFiler->filerType()==AcDb::kWblockCloneFiler)
    108. {
    109.   AcDbHardPointerId Id;
    110.   pFiler->readItem(&Id);
    111. }
    112. pFiler->readItem(&StartPoint);
    113. pFiler->readItem(&EndPoint);
    114. return pFiler->filerStatus();
    115. }
    116. Acad::ErrorStatus AcdbEntityTest::dwgOutFields(AcDbDwgFiler* pFiler) const
    117. {
    118.      assertReadEnabled();
    119.   AcDbObject::dwgOutFields(pFiler);
    120.   if (pFiler->filerType()==AcDb::kWblockCloneFiler)
    121.   {
    122.    pFiler->writeHardPointerId((AcDbHardPointerId)ownerId());
    123.   }
    124.   pFiler->writeItem(StartPoint);
    125.   pFiler->writeItem(EndPoint);
    126. return pFiler->filerStatus();
    127. }
    128. Adesk::Boolean  AcdbEntityTest::worldDraw(AcGiWorldDraw* pWd)
    129. {
    130. AcDbObjectId originalLineTypeID;
    131. originalLineTypeID=pWd->subEntityTraits().lineTypeId();
    132. Adesk::UInt16 originalColor;
    133. originalColor=pWd->subEntityTraits().color();

    134. //获取虚线线型ID

    135. Acad::ErrorStatus err;
    136. AcDbObjectId dashId;
    137. AcDbLinetypeTable*pLinetypeTable;

    138. acdbHostApplicationServices()->workingDatabase()->loadLineTypeFile("ACAD_ISO02W100","acadiso.lin");
    139. acdbHostApplicationServices()->workingDatabase()->getLinetypeTable(pLinetypeTable,AcDb::kForRead);
    140. err=pLinetypeTable->getAt("ACAD_ISO02W100",dashId,Adesk::kTrue);
    141. pLinetypeTable->close();
    142. pWd->subEntityTraits().setLineType(originalLineTypeID);
    143. pWd->subEntityTraits().setColor(1);
    144. AcGePoint3d Verts[2];
    145. Verts[0]=StartPoint;
    146. Verts[1]=EndPoint;
    147. pWd->geometry().polyline(2,Verts);
    148. return AcDbEntity::worldDraw(pWd);
    149. }
    150. Acad::ErrorStatus AcdbEntityTest::getGripPoints(AcGePoint3dArray& gripPoints,
    151.            AcDbIntArray& osnapModes,
    152.            AcDbIntArray& geomIds)const
    153. {
    154. assertReadEnabled();
    155. gripPoints.append(StartPoint);
    156. gripPoints.append(EndPoint);
    157. return Acad::eOk;
    158. }
    159. Acad::ErrorStatus AcdbEntityTest::moveGripPointsAt(const AcDbIntArray& indices,const AcGeVector3d& offset)
    160. {
    161. assertReadEnabled();
    162. Acad::ErrorStatus es=Acad::eOk;
    163. if(indices.length()==0)
    164. {
    165.   return Acad::eOk;
    166. }
    167. int num=indices.length();
    168. for(int i=0;i<num;i++)
    169. {
    170.   int k=indices[i];
    171.   if (k==0)
    172.   {
    173.    StartPoint.x+=offset.x;
    174.    StartPoint.y+=offset.y;
    175.   }
    176.   else
    177.   {
    178.    EndPoint.x+=offset.x;
    179.    EndPoint.y+=offset.y;
    180.   }


    181. }

    182. return Acad::eOk;
    183. }
    184. Acad::ErrorStatus AcdbEntityTest::getOsnapPoints(
    185.              AcDb::OsnapMode   osnapMode,
    186.              int   gsSelectionMark,
    187.              const AcGePoint3d&    pickPoint,
    188.              const AcGePoint3d&    lastPoint,
    189.              const AcGeMatrix3d&   viewXform,
    190.              AcGePoint3dArray& snapPoints,
    191.              AcDbIntArray&     geomIds) const
    192. {   //设置捕捉点
    193. assertReadEnabled();
    194. Acad::ErrorStatus es=Acad::eOk;
    195. if(osnapMode!=AcDb::kOsModeEnd)
    196. {
    197.   return Acad::eOk;
    198. }
    199. return Acad::eOk;
    200. }

    201. void AcdbEntityTest::Initialize()
    202. {
    203. AcGePoint3d inputPt;
    204. if(ads_getpoint(NULL,"\n ==NOTE== 请输入起点: ",asDblArray(inputPt))!=RTNORM)
    205. {
    206.   ads_printf("\n ==NOTE== 错误");
    207. }
    208.   StartPoint=inputPt;
    209. AcDbObjectId entityID=AddEntityToDbs(this);
    210. int track,type;
    211. track=1;
    212. struct resbuf entdata;
    213. while (track>0)
    214. {
    215.   if(ads_grread (track, &type, &entdata)!=RTNORM)
    216.   {
    217.    ads_printf("\n !=RTNORM");
    218.    break;
    219.   }
    220.   AcdbEntityTest * pmyEntity=this;
    221.   acdbOpenObject(pmyEntity,entityID, AcDb::kForWrite);
    222.   this->assertWriteEnabled();
    223.   if(type==5)
    224.   {
    225.    AcGePoint3d movePt;    //鼠标当前位置
    226.    movePt[X]=entdata.resval.rpoint[X];
    227.    movePt[Y]=entdata.resval.rpoint[Y];
    228.    EndPoint=movePt;
    229.    this->close();
    230.   }

    231.   if(type==3)
    232.   {
    233.    track=1;
    234.    AcGePoint3d movePt;    //鼠标当前位置
    235.    movePt[X]=entdata.resval.rpoint[X];
    236.    movePt[Y]=entdata.resval.rpoint[Y];
    237.    EndPoint=movePt;
    238.    this->close();
    239.    break;
    240.   }
    241.   if(type==13)
    242.   {
    243.    //鼠标右键退出
    244.    track=1;
    245.    AcGePoint3d movePt;  //鼠标当前位置
    246.    movePt[X]=entdata.resval.rpoint[X];
    247.    movePt[Y]=entdata.resval.rpoint[Y];
    248.    EndPoint=movePt;
    249.    this->close();
    250.    break;
    251.   }
    252. }
    253. }
    254. AcDbObjectId AboutArx::AddEntityToDbs(AcDbEntity*pEnt)//将生成的自定义实体对象加入CAD数据库
    255. {
    256. AcDbBlockTable *bt;
    257. acDocManager->lockDocument(acDocManager->curDocument(),AcAp::kWrite);
    258. AcDbObjectId entityId;
    259. acdbCurDwg()->getBlockTable(bt,AcDb::kForRead);
    260. AcDbBlo
    复制代码
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-3-9 08:49
  • 签到天数: 1442 天

    连续签到: 21 天

    [LV.10]以坛为家III

     楼主| 发表于 2021-1-19 14:40 | 显示全部楼层
    1. 源地址:https://blog.csdn.net/u012158162/article/details/67644392

    2. 一。目的
    3. 在ObjectArx中已经有了许多实体,如AcDbLine,AcDbCircle,AcDbArc等,
    4. 但在用户使用Cad时,会有一些对他们来讲常用的“实体“,如一扇门,如
    5. 果我们能提供一个“门实体“,让用户能向添加直线一样方便,相信用户是
    6. 很乐意接受由此功能的软件!这是,我们为这个“门“就相当于一个自定
    7. 义实体”!(PS:希望没理解错)!
    8. 本文将介绍创建一个长方体的自定义实体,支持简单的编辑以及二维,三维
    9. 显示!

    10. 二。相关知识储备
    11. 1)既然是自定义实体,那你就必须将其显示出来,来告诉用户你的
    12. 自定义实体“长”什么样子,如下函数:(与MFC中的OnPaint()有点相似)
    13. virtual Adesk::Boolean subWorldDraw (AcGiWorldDraw *mode) ;扩
    14. 可以看出这是一个虚函数,由父类AcDbEntity继承而来,并且绝对需要你
    15. 重写的函数,与之类似的还有其他几个从父类继承而来的虚函数,理论上都
    16. 需要重写!

    17. 2)由于这里需要绘制长方体,就涉及到面的绘制,可以用到以下二个函数
    18. (二者择其一即可完成面的绘制)
    19.     virtual Adesk::Boolean  mesh(const Adesk::UInt32 rows,
    20.                                  const Adesk::UInt32 columns,
    21.                                  const AcGePoint3d* pVertexList,
    22.                                  const AcGiEdgeData* pEdgeData = NULL,
    23.                                  const AcGiFaceData* pFaceData = NULL,
    24.                                  const AcGiVertexData* pVertexData = NULL,
    25.                                  const bool bAutoGenerateNormals = true
    26.                                  ) const = 0;


    27.     virtual Adesk::Boolean  shell(const Adesk::UInt32 nbVertex,
    28.                                  const AcGePoint3d* pVertexList,
    29.                                  const Adesk::UInt32 faceListSize,
    30.                                  const Adesk::Int32* pFaceList,
    31.                                  const AcGiEdgeData* pEdgeData = NULL,
    32.                                  const AcGiFaceData* pFaceData = NULL,
    33.                                  const AcGiVertexData* pVertexData = NULL,
    34.                                  const struct resbuf* pResBuf = NULL,
    35.                                  const bool bAutoGenerateNormals = true
    36.                                  ) const = 0;
    37. 3 )需要获取当前用户采取什么模式预览:
    38.     virtual AcGiRegenType           regenType() const = 0;
    39. 还回值为枚举型

    40. 三。实现流程
    41. 1)首先创建一个继承自AcDbEntity的自定义实体类,将几个必须由自定义
    42. 实体 类 实现的虚函数声明!
    43. 2)绘制你的自定义实体:
    44. [cpp]  view plain  copy
    45. void AcDbMyEntity::MyEntityShell(AcGiWorldDraw *mode, const AcGePoint3d &ptBase, INT32 xLen, INT32 yLen, INT32 zLen)  
    46. {  
    47.     const INT32 POINT_COUNT = 8;  
    48.     AcGePoint3d ptList[POINT_COUNT] = {};  
    49.   
    50.     INT32 index = 0;  
    51.     ptList[index++].set(ptBase[X],          ptBase[Y],          ptBase[Z]);  
    52.     ptList[index++].set(ptBase[X] + xLen,   ptBase[Y],          ptBase[Z]);  
    53.     ptList[index++].set(ptBase[X] + xLen,   ptBase[Y] + yLen,   ptBase[Z]);  
    54.     ptList[index++].set(ptBase[X],          ptBase[Y] + yLen,   ptBase[Z]);  
    55.   
    56.     ptList[index++].set(ptBase[X],          ptBase[Y],          ptBase[Z] + zLen);  
    57.     ptList[index++].set(ptBase[X] + xLen,   ptBase[Y],          ptBase[Z] + zLen);  
    58.     ptList[index++].set(ptBase[X] + xLen,   ptBase[Y] + yLen,   ptBase[Z] + zLen);  
    59.     ptList[index++].set(ptBase[X],          ptBase[Y] + yLen,   ptBase[Z] + zLen);  
    60.   
    61.   
    62.     Adesk::Int32 faceList[] = {4, 0, 1, 2, 3,  
    63.                                 4, 4, 5, 6, 7,  
    64.                                 4, 0, 1, 5, 4,  
    65.                                 4, 1, 2, 6, 5,  
    66.                                 4, 2, 3, 7, 6,  
    67.                                 4, 3, 0, 4, 7,  
    68.                                 };  
    69.   
    70.     INT32 faceLen = sizeof(faceList) / sizeof(faceList[0]);  
    71.   
    72.     AcGiFaceData faceData;  
    73.     INT32 baseColor = 10;  
    74.     INT32 incColor = 30;  
    75.     short colors[] = {(baseColor += incColor),  
    76.                         (baseColor += incColor),  
    77.                         (baseColor += incColor),  
    78.                         (baseColor += incColor),  
    79.                         (baseColor += incColor),  
    80.                         (baseColor += incColor)};  
    81.     faceData.setColors(colors);  
    82.   
    83.     mode->geometry().shell(POINT_COUNT, ptList, faceLen, faceList, NULL, &faceData);  
    84. }  

    85. 这里我采用的是shell(),当然mesh()也是可以的,简单说一下这个函数,
    86. 如facelist 第一组属性,{4,0,1,2,3,****}
    87. 第一个数字4表明此面是由4个点组成,后面0,1,2,3是ptList中点的索引,由
    88. 此4点组 成一个面,后面几组数值以此类推!
    89. 3)支持二维三维显示:
    90. [cpp]  view plain  copy
    91. Adesk::Boolean AcDbMyEntity::subWorldDraw (AcGiWorldDraw *mode) {  
    92.     assertReadEnabled () ;  
    93.   
    94.     INT32 xBase = m_ptBase[X];  
    95.     INT32 yBase = m_ptBase[Y];  
    96.     INT32 zBase = m_ptBase[Z];  
    97.     INT32 xLen = m_len3D[X];  
    98.     INT32 yLen = m_len3D[Y];  
    99.     INT32 zLen = m_len3D[Z];  
    100.   
    101.     switch (mode->regenType())  
    102.     {  
    103.   
    104.     case kAcGiStandardDisplay:  
    105.         {  
    106.             const INT32 POINT_COUNT = 5;  
    107.             AcGePoint3d ptList[POINT_COUNT] = {};  
    108.               
    109.             INT32 index = 0;  
    110.             ptList[index++].set(xBase,          yBase,          zBase);  
    111.             ptList[index++].set(xBase + xLen,   yBase,          zBase);  
    112.             ptList[index++].set(xBase + xLen,   yBase + yLen,   zBase);  
    113.             ptList[index++].set(xBase,          yBase + yLen,   zBase);  
    114.             ptList[index].set(xBase,            yBase,          zBase);  
    115.   
    116.             mode->geometry().polyline(POINT_COUNT, ptList);  
    117.   
    118.             m_enShowMode = en2D;  
    119.         }  
    120.         break;;  
    121.     case eAcGiRegenTypeInvalid:  
    122.     case kAcGiHideOrShadeCommand:  
    123.     case kAcGiRenderCommand:  
    124.     case kAcGiForExplode:  
    125.     case kAcGiSaveWorldDrawForProxy:  
    126.         {  
    127.             MyEntityShell(mode, m_ptBase, xLen, yLen, zLen);  
    128.         }  
    129.     default:  
    130.         break;;      
    131.     }  
    132.       
    133.     return (AcDbEntity::subWorldDraw (mode)) ;  
    134. }  

    135. 四。效果截图:
    136. 1)三维实体,每一面都有特定颜色,可以简单的加宽
    复制代码
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-3-9 08:49
  • 签到天数: 1442 天

    连续签到: 21 天

    [LV.10]以坛为家III

     楼主| 发表于 2021-1-25 17:26 | 显示全部楼层
    1. 1.arx文档中规定的必须重写的几个函数

    2. //AcDbObject:
    3. virtual Acad::ErrorStatus
    4. dwgInFields(AcDbDwgFiler* filer);

    5. virtual Acad::ErrorStatus
    6. dwgOutFields(AcDbDwgFiler* filer) const;

    7. virtual Acad::ErrorStatus
    8. dxfInFields(AcDbDxfFiler* filer);

    9. virtual Acad::ErrorStatus
    10. dxfOutFields(AcDbDxfFiler* filer) const;
    11. //AcDbEntity
    12. virtual Adesk::Boolean      
    13. subWorldDraw(
    14.     AcGiWorldDraw* mode);

    15. virtual Acad::ErrorStatus   
    16. subGetGeomExtents(
    17.     AcDbExtents& extents) const;

    18. virtual Acad::ErrorStatus   
    19. subTransformBy(
    20.     const AcGeMatrix3d& xform);

    21. virtual Acad::ErrorStatus   
    22. subGetTransformedCopy(
    23.     const AcGeMatrix3d& xform,
    24.     AcDbEntity*& ent) const;

    25. virtual Acad::ErrorStatus   
    26. subGetGripPoints(
    27.     AcGePoint3dArray& gripPoints,
    28.     AcDbIntArray&  osnapModes,
    29.     AcDbIntArray&  geomIds) const;

    30. virtual Acad::ErrorStatus
    31. subMoveGripPointsAt(
    32.     const AcDbIntArray& indices,
    33.     const AcGeVector3d& offset);
    34. 以上函数是文档中规定的必须重写的函数
    35. 2.实际工作中要求的必须重载
    36. 1)实际工作中必须重载的函数
    37. virtual Adesk::Boolean      
    38. subWorldDraw(
    39.     AcGiWorldDraw* mode);
    40. 分析:从函数的名称我们就可以判断出,这个是自定义实体的外观,相信如果外观都不需要的情况在实际工作中应该是很少出现的
    41. 应用情形:
    42. 最典型的当属于Jig,只是为了实现动态效果的实体,并不需要自定义实体存档,说白了就是只起到一个临时实体的作用(为什么称作临时实体,只在Jig运行期间出现,Jig完成之后立即释放),在这种情形下,其余文档中要求的重载都可不必实现
    43. 3.实例讲解
    44. 我们只写一个最简单的实例,来讲解一下自定义实体每一个被重写的函数的意义
    45. 自定义实体要实现的效果:
    46. 绘制一个圆,并且能够设置颜色
    47. 1).h
    48. class CCustomColorCircle:public AcDbEntity
    49. {
    50. public:
    51.    ACRX_DECLARE_MEMBERS(CCustomColorCircle);
    52.    CCustomColorCircle(AcGePoint3d centerPt);
    53.    ~CCustomColorCircle() ;
    54. proctected:
    55.   virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer);
    56. virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const;
    57.   virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler* filer);

    58.   virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* filer) const;
    59.   virtual Adesk::Boolean      subWorldDraw(AcGiWorldDraw* mode);

    60.   virtual Acad::ErrorStatus   subGetGeomExtents(AcDbExtents& extents) const;

    61.   virtual Acad::ErrorStatus   subTransformBy(const AcGeMatrix3d& xform);

    62.   virtual Acad::ErrorStatus   subGetTransformedCopy(const AcGeMatrix3d& xform,AcDbEntity*& ent) const;

    63.   virtual Acad::ErrorStatus   subGetGripPoints(AcGePoint3dArray& gripPoints,AcDbIntArray&  osnapModes,AcDbIntArray&  geomIds) const;

    64.   virtual Acad::ErrorStatus   subMoveGripPointsAt( const AcDbIntArray& indices,const AcGeVector3d& offset);
    65. public:
    66.   virtual Acad::ErrorStatus   setColorIndex(Adesk::UInt16 color, Adesk::Boolean doSubents=true);
    67. private:
    68.   //圆心
    69.   AcGePoint3d m_CenterPoint ;
    70. };
    71. 2)cpp
    72. //首先是要加入的动态识别一些函数的实现
    73. ACRX_DXF_DEFINE_MEMBERS(CCustomColorCircle, AcDbEntity, AcDb::kDHL_CURRENT,
    74.     AcDb::kMReleaseCurrent, 0, CUSTOMCIRCLE, /*MSG0*/"TSZ");
    75. MAKE_ACDBOPENOBJECT_FUNCTION(CCustomColorCircle) ;
    76. /*
    77. 在源文件中我们来分析每个函数的实现,以及它们在什么情况下被调用
    78. */
    79. /*
    80. 这里定义一个版本号,随着版本的提升,数据也可能发生变化,有可能增加,有可能减少,所以针对不同的版本
    81. 必须用不同的方式进行处理(序列化与反序列化也是必须的)
    82. */
    83. #define VERSION 1
    84. //我们知道针对非自定义实体,不是每一种类型的实体,对其设置setColorIndex都能起作用,同理如果你想让你的自定义实体能够通过setColorIndex设置颜色,必须重写这个函数
    85. virtual Acad::ErrorStatus   CCustomColorCircle::setColorIndex(Adesk::UInt16 color, Adesk::Boolean doSubents=true)
    86. {
    87.      return AcDbEntity::setColorIndex( color , doSubents ) ;
    88. }
    89. /*
    90. 用途:这个函数就是你自定义实体的几何表现,说白了你要让你自定义的实体以何种面目示人
    91. 当调用如下函数时会被调用:所有调用更新绘制的时候
    92. 不实现会发生什么:(不实现无任何意义)
    93. */
    94. virtual Adesk::Boolean      CCustomColorCircle::subWorldDraw(AcGiWorldDraw* mode)
    95. {
    96.      //因为能够通过setColorIndex设置颜色,在这里设置一下
    97.      int colorIndex = this->colorIndex ;
    98.      mode->subEntityTraits().setColor( colorIndex ) ;
    99.      //接下来绘制圆,这里为了简单(偷懒)我们对圆的半径设置一个固定的值
    100.      double dCircleRadius = 200.0 ;
    101.      mode->geometry().circle( m_CenterPoint , dCircleRadius , AcGeVector3d::kZAxis ) ;
    102.      return Adesk::kTrue ;
    103. }
    104. /*
    105. 用途:获得一个实体的范围(一个极大点  一个极小点)
    106. 当调用如下函数时会被调用:CCustomColorCircle.getGeomExtents
    107. 不实现会发生什么:得到的范围无意义(得到的极大点 和极小点的坐标都是没有意义的浮点数)
    108. */
    109. virtual Acad::ErrorStatus   CCustomColorCircle::subGetGeomExtents(AcDbExtents& extents) const
    110. {
    111.      extents.addPoint( m_CenterPoint + sqrt(2)*200.0*AcGeVector3d(1,1,0) ) ;
    112.      extents.addPoint( m_CenterPoint - sqrt(2)*200.0*AcGeVector3d(1,1,0) ) ;
    113.      return Acad::eOk ;
    114. }
    115. /*
    116. 用途:dwgIn:利用图纸初始化数据成员(反序列化)  dwgOut:将当前数据成员写入图纸(序列化)
    117. 深入分析:想象一种情况,你建立了一个自定义实体添加到模型空间中,然后保存图纸->关闭图纸,然后再次打开图纸,这时你利用ID打开自定义实体,这时数据成员应该如何初始化?
    118. 如果你想通了,就能够明白为什么要这么做,其实就是序列化与反序列化,因为dwg是一个存储在硬盘上的文件
    119. 这也就意味着,每一个数据成员都需要需要序列化与反序列化(这是保证你的自定义实体能够使用的基本条件)
    120. 在什么时候被调用(不一定每一次都发生):dwgin:save  saveas  wblock insert copy purge
    121.                                  dwgOut:wblock save saveas acdbEntGet
    122. */
    123. virtual Acad::ErrorStatus CCustomColorCircle::dwgInFields(AcDbDwgFiler* filer)
    124. {
    125. assertWriteEnabled() ;
    126. if ( AcDbEntity::dwgInFields ( filer ) != Acad::eOk )
    127. {
    128. return filer->filerStatus() ;
    129. }
    130. int version ;
    131. filer->readItem(&version);
    132. filer->readItem( &m_CenterPoint ) ;
    133. return filer->filerStatus() ;
    134. }
    135. virtual Acad::ErrorStatus CCustomColorCircle::dwgOutFields(AcDbDwgFiler* filer) const
    136. {
    137. assertReadEnabled() ;
    138. if ( AcDbEntity::dwgOutFields ( filer ) != Acad::eOk )
    139. {
    140. return filer->filerStatus() ;
    141. }
    142. filer->writeItem( VERSION ) ;
    143. filer->writeItem( m_CenterPoint ) ;
    144. return filer->filerStatus() ;
    145. }
    146. /*
    147. dxfin 和dxfOut的意义按着我的理解是为了和dwg保持一致
    148. 并且dxf格式也是dwg自始至终都存的东西,并且在构建选择集的时候也很有用
    149. */
    150. virtual Acad::ErrorStatus CCustomColorCircle::dxfInFields(AcDbDxfFiler* filer)
    151. {
    152. assertWriteEnabled();
    153. if( AcDbEntity::dxfInFields(filer) != Acad::eOk ||
    154. filer->atSubclassData( _T("CCustomColorCircle") ) )
    155. {
    156. return filer->filerStatus() ;
    157. }
    158. //读取版本
    159.      resbuf rb ;
    160.      filer->readItem( &rb ) ;
    161.      int iVersion = rb.resval.rint ;
    162.      //读取圆心
    163.   filer->readItem(&rb) ;
    164.   m_CenterPoint = AcGePoint3d( rb.resval.rpoint[0] , rb.resval.rpoint[1] ,
    165. rb.resval.rpoint[2] ) ;

    166. }
    167. virtual Acad::ErrorStatus CCustomColorCircle::dxfOutFields(AcDbDxfFiler* filer) const
    168. {
    169.      assertReadEnabled();
    170.      Acad::ErrorStatus es ;
    171.      if ( ( es = AcDbEntity::dxfOutFields(filer))
    172.           != Acad::eOk )
    173.      {
    174.           return es ;
    175.      }
    176.     filer->wirteItem( AcDb::kDxfSubClass , _T("CCustomColorCircle") ) ;
    177.     filer->writeInt16( AcDb::kDxfInt16 , VERSION ) ;
    178.     filer->writePoint3d( AcDb::kDxfXCoord , m_CenterPoint ) ;
    179.     return filer->filerStatus() ;
    180. }
    181. /*
    182. 用途:选中一下cad提供的实体,例如直线,你会看到三个点(起点 中点  和 终点),选中一个圆,你会看到一个圆心,选择圆弧,会看到三个点(圆弧起点 圆弧中点  圆弧圆心),并且通过拖动这些点能够实现简单的
    183. 编辑功能
    184. 不实现会发生什么:你选中你添加到空间中的实体,你会发现不会有特征点显示出来,也就无法通过用户交互的方式编辑这个实体(当然可以通过程序实现)
    185. 注意:在这里我们多添加几个点到gripPoints中(这个有助于我们分析subMoveGripPointsAt函数)
    186. */
    187. virtual Acad::ErrorStatus   CCustomColorCircle::subGetGripPoints(AcGePoint3dArray& gripPoints,AcDbIntArray&  osnapModes,AcDbIntArray&  geomIds) const
    188. {
    189.      /*这里添加三个点 添加三个点的顺序很重要
    190.      向gripPoints中填充点,这些点在实体被选中后,会显示出来
    191.      */
    192.      gripPoints.append( m_CenterPoint ) ;
    193.      gripPoints.append( m_CenterPoint + 20 * AcGeVector3d::kXAxis ) ;
    194.      gripPoints.append( m_CenterPoint - 20 * AcGeVector3d::kXAxis ) ;
    195. }
    196. /*
    197. 用途:subGetGripPoints只让可以被编辑的点被显示出来,但是真正发挥作用的却是subMoveGripPointsAt
    198. 这个函数决定了 当用户拖拽特征点的时候,实体应该如何变化
    199. 如果不实现会怎么样:不实现,你就只能看看,无法实现任意的编译功能
    200. */
    201. virtual Acad::ErrorStatus   CCustomColorCircle::subMoveGripPointsAt( const AcDbIntArray& indices,const AcGeVector3d& offset)
    202. {
    203.      /*
    204.      indices:用户选择的特征点的索引(和你在subGetGripPoints的填充顺序是一致的,从0开始)
    205.      offset(拖拽产生的向量)
    206.      */
    207.      //在这里我们这其实只是一个圆,所以简单调用矩阵变换函数
    208.      if ( indices.length() == 0 || offset.length() == 0 )
    209.           return Acad::eOk ;
    210. #ifdef _DEBUG
    211.      //输出当前用户拖拽点的索引
    212.      acutPrintf( _T("\n%d") , inDices)
    213. #endif
    214.      return transformBy( AcGeMatrix3d::translation(offset) ) ;//这个函数又会调用subTransformby
    215. }
    216. 在dll的入口加入如下两行代码:
    217.      CCustomColorCircle::rxInit() ;
    218. acrxBuildClassHierarchy() ;
    219. 总结:
    220. 1)适用情况:
    221.      通常情况下,并不建议使用自定义实体,但是有一种情况除外,作为jig的entity实体使用时,这时适用自定义实体再合适不过,而且只需
    222. 实现一个函数subWorldDraw(),其余情况(说白了就是实体需要存在dwg文档中时),这里的原则是能不用就不用
    223. 2)如何学习:
    224.      我这里也只做了一个基本的介绍,还有很多可以重写的函数,并且能够实现非常强大的功能,那么我们如和才能找到我们需要实现哪一个函数,
    225. 这里也有一个技巧,我们发现重载的基本上都会加上一个sub,比如我们对于cad已经提供的实体调用trans,那么在自定义实体中重载的就是sub,
    226. 当然这只符合一些编辑功能的重写,其余的要做到两点,最好将你想实现的效果,在cad提供的实体中通过,然后通过编程实现效果
    227. 3)给出代码的问题:
    228.      我这是在外网机器上一行一行敲的,难免出现问题
    229. 4)进阶:
    230.      在ObjectArx中提供了一个例子 samples/entity/polysamp,这个例子非常好
    231. 5)千万不要忘了
    232. CCustomColorCircle::rxInit() ;
    233. acrxBuildClassHierarchy() ;
    复制代码
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

    推荐膜材品牌上一条 /5 下一条

    进口膜材 国产膜材 pvdf膜材ptfe膜材ETFE膜材
    最好的膜结构公司 一级膜结构资质 膜结构一级资质
    膜结构设计-膜结构十大品牌-etfe设计-充气膜结构
    诺科膜结构
    遨都膜结构设计
    中国膜结构网
    中国空间膜结构协会

    QQ|申请友链|Archiver|手机版|中国膜结构论坛

    GMT+8, 2021-3-9 12:44 , Processed in 0.216522 second(s), 24 queries .

    Powered by 中国膜结构网->膜材采购->膜结构设计->膜结构安装->膜结构维修

    © 2014-2020 膜结构协会->进口膜材->国产膜材->PVDF膜材->PTFE膜材->ETFE膜材.

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