专题---自定义实体类

一、概述

  • 意义:在ObjectArx中如AcDbLine,AcDbCircle,AcDbArc等均为实体类,用户可以根据需要,自定义实体类“,如一扇门等,效果如下图
    在这里插入图片描述

二、项目初始化

  • 目的:初始化项目,创建一个ChDbLine自定义实体类,跟AcDbLine一样

2.1 创建空解决方案

  • 菜单-》文件-》新建-》项目…
    在这里插入图片描述

2.2 DBX操作

2.2.1 创建DBX

  • 在空解决方案中添加
    在这里插入图片描述
  • 向导设置
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

注意:未写可不修改,第一个选项前缀自己决定

2.2.2 调试DBX

  • 选择Release/x64,按调试(F5)
    • 错误1:无法打开包括文件: “corecrt.h”: No such file or directory
      解决1:将C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt路径加入包含路径(注意数字不一定相同)
    • 错误2:无法打开文件“ucrt.lib”
      解决2:将C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64路径加入库路径(注意数字不一定相同)
    • 错误3:调用aced类。。。不可调用数据库类
  • 图示
    在这里插入图片描述

    注:将属性页中,调试-》命令一栏清空,否则调试后,会自动启动CAD

2.2.3 创建实体类

  • 在DBX项目内添加自定义实体类
    在这里插入图片描述
    在这里插入图片描述
  • 自定义线类(继承自曲线类)
    在这里插入图片描述
    在这里插入图片描述

2.2.4 调试实体类

  • ChDbLine.cpp
    ...
    //----- AcDbEntity protocols
    Adesk::Boolean ChDbLine::subWorldDraw (AcGiWorldDraw *mode) {
    	assertReadEnabled () ;
    
    	// 设置图形颜色
    	mode->subEntityTraits().setColor(1);
    	// 点数组
    	AcGePoint3d pts[2];
    	pts[0] = AcGePoint3d(0, 0, 0);
    	pts[1] = AcGePoint3d(100, 100, 0);
    	// geometry函数:返回AcGiGeometry对象,其类方法worldLine 在世界坐标系中画直线
    	mode->geometry().worldLine(pts);
    
    	return (AcDbCurve::subWorldDraw (mode)) ;
    }
    ...
    
  • 调试
    遇到问题:switch 语句包含“default”但是未包含“case”标签,警告被视为错误,解决方法如下
    在这里插入图片描述

2.3 ARX操作

2.3.1 创建arx项

  • ARX创建
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    向导只修改此默认项即可

  • 添加依赖(arx是依赖于DBX的)
    在这里插入图片描述
    在这里插入图片描述

    两文件职责:DBX负责创建自定义类,依赖于DBX的arx负责调用自定义类

2.3.2 调试ARX

  • 方法:在解决方案中my_app上单击右键-》生成

  • 遇到问题
    • 错误1:无法打开包括文件: “ctype.h”
      解答1:将C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt路径加入包含路径(注意数字不一定相同)
    • 错误2:无法打开文件“ucrt.lib”
      解决2:将C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64路径加入库路径(注意数字不一定相同)

  • 修改对话框:参考2.2.2

2.3.3 调用代码

  • acrxEntryPoint.cpp文件(my_app项目)
    ...
    #include "ChDbLine.h"
    ...
    class Cmy_appApp : public AcRxArxApp {
    	...
    	static void MyGroupMyCommand () {
    		// 获取块表记录
    		AcDbBlockTable* pBlkTbl = NULL;
    		acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl);
    		AcDbBlockTableRecord* pBlkTblRcd = NULL;
    		pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForWrite);
    		pBlkTbl->close();
    		// 创建 自定义实体类 对象,并添加进块表记录中
    		ChDbLine* pLine = new ChDbLine();
    		pBlkTblRcd->appendAcDbEntity(pLine);
    		// 关闭自定义实体类、块表记录
    		pLine->close();
    		pBlkTblRcd->close();
    	}
    	...
    }
    ...
    

  • 调试:在解决方案中my_app上单击右键-》生成
    • 遇到问题:无法打开包括文件: “ChDbLine.h”
      解答:添加头文件D:\CPP\CustomerTest\my_entity,修改对话框参考2.2.2,即包含ChDbLine.h文件的文件夹
    • 遇到问题:无法解析的外部符号 "public: __cdecl ChDbLine::ChDbLine(void)"
      解答:添加库文件(理论上在对话框参考2.2.2添加库文件夹也行,这里有点小问题)
      在这里插入图片描述
      在这里插入图片描述

2.4 CAD测试

  • 加载:文件位置D:\CPP\CustomerTest\x64\Release

    注意:

    • 隶属关系:DBX和依赖与它的arx两个文件,是一个解决方案内的项目,生成的目标文件属于CustomerTest解决方案
    • 加载顺序:先加载DBX,后加载arx
  • 加载后运行:MYCOMMANDLOCAL命令
  • 效果
    在这里插入图片描述

三、DBX项目深化

  • 目的:深化ChDbLine类,添加功能如:显示夹点、移动、拉伸、捕捉等

3.1 依赖文件修改

  • acrxEntryPoint.cpp文件(my_app项目)
    ...
    #include "ChDbLine.h"
    ...
    static void MyGroupMyCommand () {
    	// 交互式 图中画自定义实体类
    	AcGePoint3d ptStart, ptEnd;
    	// asDblArray函数可以实现AcGePoint3d 与 ads_real类型间转换
    	if (acedGetPoint(NULL, L"\n请输入起点:", asDblArray(ptStart)) != RTNORM) return;
    	if (acedGetPoint(NULL, L"\n请输入终点:", asDblArray(ptEnd)) != RTNORM) return;
    
    	AcDbBlockTable* pBlkTbl = NULL;
    	acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl);
    	AcDbBlockTableRecord* pBlkTblRcd = NULL;
    	pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForWrite);
    	pBlkTbl->close();
    	
    	// 主要修改了以下这句:重载了构造函数
    	ChDbLine* pLine = new ChDbLine(ptStart, ptEnd);
    	
    	pBlkTblRcd->appendAcDbEntity(pLine);
    	pLine->close();
    	pBlkTblRcd->close();
    }
    	...
    }
    ...
    

3.2 被依赖文件修改

  • ChDbLine.h
    ...
    class DLLIMPEXP ChDbLine : public AcDbCurve {
    
    public:
    	ACRX_DECLARE_MEMBERS(ChDbLine) ;
    
    protected:
    	static Adesk::UInt32 kCurrentVersionNumber ;
    
    public:
    	ChDbLine();
    	// 增加构造函数
    	ChDbLine(const AcGePoint3d &ptstart, const AcGePoint3d &ptend);
    	virtual ~ChDbLine () ;
    
    	//----- AcDbObject protocols
    	//- Dwg Filing protocol
    	// 存入DWG数据库参数:此处为起、终点
    	virtual Acad::ErrorStatus dwgOutFields (AcDbDwgFiler *pFiler) const ;
    	// 读取DWG数据库参数:参数会提取出给subWorldDraw做渲染
    	virtual Acad::ErrorStatus dwgInFields (AcDbDwgFiler *pFiler) ;
    
    	//- Dxf Filing protocol
    	// 存入、读取DXF数据库参数
    	virtual Acad::ErrorStatus dxfOutFields (AcDbDxfFiler *pFiler) const ;
    	virtual Acad::ErrorStatus dxfInFields (AcDbDxfFiler *pFiler) ;
    
    	// 获取起、终点
    	virtual AcGePoint3d getStartPoint() const;
    	virtual AcGePoint3d getEndPoint() const;
    
    	// 写入起、终点
    	virtual Acad::ErrorStatus setStartPoint(AcGePoint3d newVal);
    	virtual Acad::ErrorStatus setEndPoint(AcGePoint3d newVal);
    
    	//----- AcDbEntity protocols
    	//- Graphics protocol
    protected:
    	// 绘制实体的图形显示:此处定义了自定义实体的样子
    	virtual Adesk::Boolean subWorldDraw (AcGiWorldDraw *mode) ;
    	// 定义自定义实体属性:如果有特殊定义的话
    	virtual Adesk::UInt32 subSetAttributes (AcGiDrawableTraits *traits) ;
    	// 重写夹点显示函数:开启显示夹点,只要添加进gripPoints点列表中即可
    	virtual Acad::ErrorStatus subGetGripPoints(AcGePoint3dArray& gripPoints,
    											   AcDbIntArray& osnapModes,
    											   AcDbIntArray &geomIds) const;
    	// 重写几何变换函数:响应move命令,否则不可移动
    	virtual Acad::ErrorStatus subTransformBy(const AcGeMatrix3d& xform);
    	// 重写移动夹点变换函数:否则点选起终点的夹点也是平移效果
    	virtual Acad::ErrorStatus subMoveGripPointsAt(const AcDbIntArray & indices,
    												  const AcGeVector3d& offset);
    	// 重写捕捉点:捕捉点类型osnapMode、捕捉点列表snapPoints
    	virtual Acad::ErrorStatus subGetOsnapPoints(AcDb::OsnapMode osnapMode,
    												Adesk::GsMarker gsSelectionMark,
    												const AcGePoint3d& pickPoint,
    												const AcGePoint3d& lastPoint,
    												const AcGeMatrix3d& viewXform,
    												AcGePoint3dArray& snapPoints,
    												AcDbIntArray& geomIds) const;
    	// 类成员变量:起点、终点
    	AcGePoint3d ptStart;
    	AcGePoint3d ptEnd;
    
    } ;
    
    #ifdef MY_ENTITY_MODULE
    ACDB_REGISTER_OBJECT_ENTRY_AUTO(ChDbLine)
    #endif	
    
  • ChDbLine.cpp

    读前注意:

    1. 中文注释为新增加的,其他未注释的为向导自动生成的
    2. 重写函数首句必须为assertReadEnabled () ;assertWriteEnabled () ;CAD会在程序执行前测试实体是否满足函数读写的前置需求
    ...
    // 默认构造函数
    ChDbLine::ChDbLine () : AcDbCurve () {}
    // 重载构造函数
    ChDbLine::ChDbLine(const AcGePoint3d &ptstart, const AcGePoint3d &ptend)
    {
    	ptStart = ptstart;
    	ptEnd = ptend;
    }
    // 析构函数
    ChDbLine::~ChDbLine () {}
    
    //-----------------------------------------------------------------------------
    //----- AcDbObject protocols
    //- Dwg Filing protocol
    Acad::ErrorStatus ChDbLine::dwgOutFields (AcDbDwgFiler *pFiler) const {
    	assertReadEnabled () ;
    	//----- Save parent class information first.
    	Acad::ErrorStatus es =AcDbCurve::dwgOutFields (pFiler) ;
    	if ( es != Acad::eOk )
    		return (es) ;
    	//----- Object version number needs to be saved first
    	if ( (es =pFiler->writeUInt32 (ChDbLine::kCurrentVersionNumber)) != Acad::eOk )
    		return (es) ;
    
    	//----- Output params
    	// 将数据写入数据库
    	pFiler->writeItem(ptStart);
    	pFiler->writeItem(ptEnd);
    
    	return (pFiler->filerStatus ()) ;
    }
    
    Acad::ErrorStatus ChDbLine::dwgInFields (AcDbDwgFiler *pFiler) {
    	assertWriteEnabled () ;
    	//----- Read parent class information first.
    	Acad::ErrorStatus es =AcDbCurve::dwgInFields (pFiler) ;
    	if ( es != Acad::eOk )
    		return (es) ;
    	//----- Object version number needs to be read first
    	Adesk::UInt32 version =0 ;
    	if ( (es =pFiler->readUInt32 (&version)) != Acad::eOk )
    		return (es) ;
    	if ( version > ChDbLine::kCurrentVersionNumber )
    		return (Acad::eMakeMeProxy) ;
    
    	//----- Read params
    	// 将数据读出数据库
    	pFiler->readItem(&ptStart);
    	pFiler->readItem(&ptEnd);
    
    	return (pFiler->filerStatus ()) ;
    }
    
    //- Dxf Filing protocol
    Acad::ErrorStatus ChDbLine::dxfOutFields (AcDbDxfFiler *pFiler) const {
    	assertReadEnabled () ;
    	//----- Save parent class information first.
    	Acad::ErrorStatus es =AcDbCurve::dxfOutFields (pFiler) ;
    	if ( es != Acad::eOk )
    		return (es) ;
    	es =pFiler->writeItem (AcDb::kDxfSubclass, _RXST("ChDbLine")) ;
    	if ( es != Acad::eOk )
    		return (es) ;
    	//----- Object version number needs to be saved first
    	if ( (es =pFiler->writeUInt32 (kDxfInt32, ChDbLine::kCurrentVersionNumber)) != Acad::eOk )
    		return (es) ;
    	//----- Output params
    	//.....
    
    	return (pFiler->filerStatus ()) ;
    }
    
    Acad::ErrorStatus ChDbLine::dxfInFields (AcDbDxfFiler *pFiler) {
    	assertWriteEnabled () ;
    	//----- Read parent class information first.
    	Acad::ErrorStatus es =AcDbCurve::dxfInFields (pFiler) ;
    	if ( es != Acad::eOk || !pFiler->atSubclassData (_RXST("ChDbLine")) )
    		return (pFiler->filerStatus ()) ;
    	//----- Object version number needs to be read first
    	struct resbuf rb ;
    	pFiler->readItem (&rb) ;
    	if ( rb.restype != AcDb::kDxfInt32 ) {
    		pFiler->pushBackItem () ;
    		pFiler->setError (Acad::eInvalidDxfCode, 
    					      _RXST("\nError: expected group code %d (version #)"), 
    						  AcDb::kDxfInt32) ;
    		return (pFiler->filerStatus ()) ;
    	}
    	Adesk::UInt32 version =(Adesk::UInt32)rb.resval.rlong ;
    	if ( version > ChDbLine::kCurrentVersionNumber )
    		return (Acad::eMakeMeProxy) ;
    
    	while ( es == Acad::eOk && (es =pFiler->readResBuf (&rb)) == Acad::eOk ) {
    		switch ( rb.restype ) {
    
    			default:
    				pFiler->pushBackItem () ;
    				es =Acad::eEndOfFile ;
    				break ;
    		}
    	}
    
    	if ( es != Acad::eEndOfFile )
    		return (Acad::eInvalidResBuf) ;
    
    	return (pFiler->filerStatus ()) ;
    }
    
    //-----------------------------------------------------------------------------
    //----- AcDbEntity protocols
    Adesk::Boolean ChDbLine::subWorldDraw (AcGiWorldDraw *mode) {
    	assertReadEnabled () ;
    
    	// 点数组:设置起始点
    	AcGePoint3d pts[2];
    	pts[0] = ptStart;
    	pts[1] = ptEnd;
    	// geometry函数:返回AcGiGeometry对象,其类方法worldLine 在世界坐标系中画直线
    	// 传入的是点数组指针
    	mode->geometry().worldLine(pts);
    
    	return (AcDbCurve::subWorldDraw (mode)) ;
    }
    
    
    Adesk::UInt32 ChDbLine::subSetAttributes (AcGiDrawableTraits *traits) {
    	assertReadEnabled () ;
    	return (AcDbCurve::subSetAttributes (traits)) ;
    }
    
    // 重写夹点显示函数
    Acad::ErrorStatus ChDbLine::subGetGripPoints(AcGePoint3dArray& gripPoints, 
    											 AcDbIntArray& osnapModes, 
    											 AcDbIntArray & geomIds) const
    {
    	assertReadEnabled();
    	// 注意此处添加顺序直接影响夹点顺序,影响后续几何变换换
    	gripPoints.append(ptStart);
    	gripPoints.append(AcGePoint3d((ptStart.x + ptEnd.x) / 2, (ptStart.y + ptEnd.y) / 2, 0));
    	gripPoints.append(ptEnd);
    	return Acad::eOk;
    }
    
    // 重写几何变换函数
    Acad::ErrorStatus ChDbLine::subTransformBy(const AcGeMatrix3d& xform)
    {
    	assertWriteEnabled();
    	ptStart.transformBy(xform);
    	ptEnd.transformBy(xform);
    	return Acad::eOk;
    }
    
    // 重写移动夹点变换函数
    Acad::ErrorStatus ChDbLine::subMoveGripPointsAt(const AcDbIntArray & indices, 
    											    const AcGeVector3d& offset)
    {
    	assertWriteEnabled();	
    	// 获取鼠标点击的夹点序号:与夹点添加顺序有关
    	int p = indices.at(0);
    	// 起点:起点变换
    	if (p == 0) {
    		ptStart += offset;
    	}
    	// 中点:起、终点均变换
    	if (p == 1)
    	{	
    		ptStart += offset;
    		ptEnd += offset;
    	}
    	// 终点:终点变换
    	if (p == 2)
    	{
    		ptEnd += offset;
    	}
    
    	return Acad::eOk;
    }
    
    // 重写捕捉点:osnapMode捕捉点类型、snapPoints捕捉点点列表
    Acad::ErrorStatus ChDbLine::subGetOsnapPoints(AcDb::OsnapMode osnapMode,
    											  Adesk::GsMarker gsSelectionMark,
    											  const AcGePoint3d& pickPoint,
    											  const AcGePoint3d& lastPoint,
    											  const AcGeMatrix3d& viewXform,
    											  AcGePoint3dArray& snapPoints,
    											  AcDbIntArray& geomIds) const
    {
    	assertReadEnabled();
    
    	switch (osnapMode)
    	{
    	// 端点:其他点类型点进AcDb结构体中看
    	case AcDb::kOsModeEnd:
    		{
    			snapPoints.append(ptStart);
    			snapPoints.append(ptEnd);
    		}
    		break;
    
    	// 中点
    	case AcDb::kOsModeMid:
    		{
    			snapPoints.append(AcGePoint3d((ptStart.x + ptEnd.x) / 2, 
    										  (ptStart.y + ptEnd.y) / 2, 
    										  0));
    		}
    		break;
    
    	default:
    		break;
    	}	   	  
    	return Acad::eOk;
    }
    
    // 获取起点
    AcGePoint3d ChDbLine::getStartPoint() const
    {
    	assertReadEnabled();
    	return ptStart;
    }
    
    // 获取终点
    AcGePoint3d ChDbLine::getEndPoint() const
    {
    	assertReadEnabled();
    	return ptEnd;
    }
    
    // 设置起点
    Acad::ErrorStatus ChDbLine::setStartPoint(AcGePoint3d newVal)
    {
    	assertWriteEnabled();
    	ptStart = newVal;
    	return Acad::eOk;
    }
    
    // 设置终点
    Acad::ErrorStatus ChDbLine::setEndPoint(AcGePoint3d newVal)
    {
    	assertWriteEnabled();
    	ptEnd = newVal;
    	return Acad::eOk;
    }	
    

3.3 效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、COM创建OPM

  • COM:即组件对象模型,是Component Object Model取前三个字母的缩写
  • OPM:即对象属性管理器,是Object Property Management前三个字母缩写
    后续补充,非自定义实体类的必要组件

传送门 返回 列表

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值