AutoCAD二次开发-ObjectARX(C++)-符号表之UCS

  使用ObjectARX中创建一个新的项目,命名为OperateUCS。

  一,注册一个命令NewUcs,创建一个新的UCS

(1)获得当前图形的UCS表

	AcDbUCSTable *pUcsTbl = NULL;
	acdbHostApplicationServices()->workingDatabase()
		->getUCSTable(pUcsTbl, AcDb::kForWrite);

    getUCSTable函数:在模式指定的模式AcDb :: kForWrite下打开数据库的UCS表
                                  pUcsTbl.pUcsTbl指针由UCS表pUcsTbl的地址填充

(2)定义UCS参数

		AcGePoint3d ptOrigin(0, 0, 0);
		AcGeVector3d vecXAxis(1, 1, 0);
		AcGeVector3d vecYAxis(-1, 1, 0);

(3)创建新的UCS表的参数 ''

AcDbUCSTableRecord *pUcsTblRcd = new AcDbUCSTableRecord();

(4)设置UCS的参数

		Acad::ErrorStatus es = pUcsTblRcd->setName(TEXT("NewUcs"));//为UCS命名
		if (es != Acad::eOk)//如果命名失败
		{
			delete pUcsTblRcd;
			pUcsTbl->close();
			return;
		}
		pUcsTblRcd->setOrigin(ptOrigin);//设置轴
		pUcsTblRcd->setXAxis(vecXAxis);
		pUcsTblRcd->setYAxis(vecYAxis);

setXAxis函数:设置AcDbUCSTableRecord以vecXAxis作为它所代表的UCS的新X轴.vecXAxis必须在WCS的坐标中,并且必须具有非零的长度。

(5)将新建的UCS表记录添加到UCS表中

		es = pUcsTbl->add(pUcsTblRcd);
		if (es != Acad::eOk)
		{
			delete pUcsTblRcd;
			pUcsTbl->close();
			return;
		}
		

(6)关闭对象

		pUcsTblRcd->close();
		pUcsTbl->close();

二,注册一个命令SetCurUcs,将UCS表中已经存在的一个UCS设置为当前UCS

(1)提示用户输入UCS的名称

		TCHAR ucsName[40];
		if (acedGetString(NULL, TEXT("\\n输入用户坐标系的名称:"), ucsName) != RTNORM)
			return;

acedGetString函数:指向缓冲区大小字符的预先分配的字符串缓冲区,其中包含字符串BUFSIZE:结果缓冲区的大小,字符

int acedGetString(
    int cronly, 
    const ACHAR * prompt, 
    ACHAR * result, 
    size_t bufsize
);

int cronly:如果非零,字符串可以包含空格,用户必须通过输入返回来终止它;如果0,输入空白或返回终止字符串

(2)获得指定的UCS表的记录

		AcDbUCSTable *pUcsTbl = NULL;
		acdbHostApplicationServices()->workingDatabase()
			->getUCSTable(pUcsTbl, AcDb::kForRead);
		if (!pUcsTbl->has(ucsName))
		{
			pUcsTbl->close();
			return;
		}
		AcDbUCSTableRecord *pUcsTblRcd;
		pUcsTbl->getAt(ucsName, pUcsTblRcd, AcDb::kForRead);

getAt函数:这个函数在UCSTable中搜索带有名称入口名UCSNAME的记录,如果找到,则在的openMode指定的模式kForRead下打开记录如果打开操作成功,pRecord返回指向打开的记录pUcsTblRcd。

Acad::ErrorStatus getAt(
    const ACHAR* entryName, 
    AcDbUCSTableRecord*& pRec, 
    AcDb::OpenMode openMode = AcDb::kForRead, 
    bool openErasedRec = false
) const;

(3)获得UCS的变换矩阵

		AcGeMatrix3d mat;
		AcGeVector3d vecXAxis, vecYAxis, vecZAxis;
		vecXAxis = pUcsTblRcd->xAxis();;
		vecYAxis = pUcsTblRcd->yAxis();
		vecZAxis = vecXAxis.crossProduct(vecYAxis);
		mat.setCoordSystem(pUcsTblRcd->origin(), vecXAxis,
			vecYAxis, vecZAxis);

xAxis()函数:返回AcDbUCSTableRecord代表的UCS的X轴矢量(在WCS坐标中)。

vecXAxis.crossProduct(vecYAxis)函数:返回向量vecXAxis和向量vecYAxis的叉乘。

setCoordSystem函数:将这个矩阵设置为矩阵,它将标准坐标系统与原点(0,0,0)和轴(1,0,0),(0,1,0)和(0,0,1)映射到坐标系统,它的原点和轴是X轴,Y轴,Z轴和。

(4)关闭UCS表和UCS表记录

		pUcsTblRcd->close();
		pUcsTbl->close();

(5)设置当前的UCS

acedSetCurrentUCS(mat);

acedSetCurrentUCS函数:这个函数从3D矩阵垫上设置当前的UCS,矩阵的第一行是UCS x轴(在WCS坐标中),第二行是UCS y轴,第三行是UCS z轴。

三,注册一个命令MoveUcsOrigin,用于移动当前UCS的原点

(1)获得当前UCS的变换矩阵

		AcGeMatrix3d mat;
		Acad::ErrorStatus es = acedGetCurrentUCS(mat);

(2)根据变换矩阵获得UCS的参数

		AcGePoint3d ptOrigin;
		AcGeVector3d vecXAxis, vecYAxis, vecZAxis;
		mat.getCoordSystem(ptOrigin, vecXAxis, vecYAxis, vecZAxis);

(3)移动UCS的原点

		AcGeVector3d vec(100, 100, 0);
		ptOrigin += vec;

(4)更新变换矩阵

mat.setCoordSystem(ptOrigin, vecXAxis, vecYAxis, vecZAxis);

(5)应用新的UCS

acedSetCurrentUCS(mat);

四,注册一个命令RotateUcs,用于将当前UCS绕Ž轴旋转60°

(1)获得当前UCS的变换矩阵

		AcGeMatrix3d mat;
		Acad::ErrorStatus es = acedGetCurrentUCS(mat);

(2)根据变换矩阵获得UCS的参数

		AcGePoint3d ptOrigin;
		AcGeVector3d vecXAxis, vecYAxis, vecZAxis;
		mat.getCoordSystem(ptOrigin, vecXAxis, vecYAxis, vecZAxis);

(3)绕Ž轴旋转60°

		vecXAxis.rotateBy(60 * atan(1) * 4 / 180, vecZAxis);
		vecYAxis.rotateBy(60 * atan(1) * 4 / 180, vecYAxis);

atan(1)* 4:atan()是反正切函数,正切函数tan(1)=π/ 4,所以pi = 4.0 * atan(1.0)= 3.14159 ……;这个式子的意思是PI等于4乘以1.0的正切值。

60 * atan(1)* 4/180即60 * pi / 180 = pi / 3 = 60。

(4)更新变换矩阵

mat.setCoordSystem(ptOrigin, vecXAxis, vecYAxis, vecZAxis);

(5)应用新的UCS

acedSetCurrentUCS(mat);

五,注册一个命令AddEntInUcs,用于根据UCS中的坐标创建实体

(1)

		ads_point pt1, pt2;
		if (acedGetPoint(NULL, TEXT("\\n拾取直线的起点:"), pt1) != RTNORM)
			return;
		if (acedGetPoint(pt1, TEXT("拾取直线的终点:"), pt2) != RTNORM)
			return;

(2)按照UCS坐标创建实体

AcDbLine *pLine = new AcDbLine(asPnt3d(pt1), asPnt3d(pt2));

asPnt3d函数:这个内联函数返回3个双的PNT数组作为AcGePoint3d对象

(3)对实体进行几何变换

		AcGeMatrix3d mat;
		Acad::ErrorStatus es = acedGetCurrentUCS(mat);
		pLine->transformBy(mat);

(4)加入到模型空间

CDwgDatabaseUtil::PostToModelSpace(pLine);

其中,CDwgDatabaseUtil :: PostToModelSpace(PLINE)的实现:

AcDbObjectId CDwgDatabaseUtil::PostToModelSpace( AcDbEntity *pEnt, AcDbDatabase *pDb )
{
	// 检查输入参数的有效性
	assert (pEnt);		// 等效于assert (pEnt != NULL);
	
	// 获得当前图形数据库的块表
	AcDbBlockTable *pBlkTbl = NULL;
	pDb->getBlockTable(pBlkTbl, AcDb::kForRead);
	
	// 获得模型空间对应的块表记录
	AcDbBlockTableRecord *pBlkTblRcd = NULL;
	pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForWrite);
	pBlkTbl->close();
	
	// 将实体添加到模型空间的块表记录
	AcDbObjectId entId;
	Acad::ErrorStatus es = pBlkTblRcd->appendAcDbEntity(entId, pEnt);
	if (es != Acad::eOk)
	{
		pBlkTblRcd->close();
		delete pEnt;	// 添加失败时,要delete
		pEnt = NULL;
		
		return AcDbObjectId::kNull;
	}
	
	// 关闭模型空间块表记录和实体
	pBlkTblRcd->close();
	pEnt->close();
	
	return entId;
}

六,效果

(1)编译程序,在CAD中加载应用程序

(2)执行NewUcs命令,在图形中创建一个新的UCS

(3)执行UCS命令

(4)输入:?

(5)直接按回车键

 (6)按ESC键

(7)执行SetCurUcs命令,输入NewUcs做为UCS名称

(8)执行UCS 

(9)执行MoveUcsOrigin命令

(10)执行RotateUcs命令

 点击确定后:

(11)执行AddEntInUcs命令

 七,项目的完整代码

static void AAAMyGroupNewUcs() {
		// Put your command code here

		//获得当前图形的UCS表
		AcDbUCSTable *pUcsTbl = NULL;
		acdbHostApplicationServices()->workingDatabase()
			->getUCSTable(pUcsTbl, AcDb::kForWrite);
		//getUCSTable函数:在模式指定的模式AcDb::kForWrite下打开数据库的UCS表pUcsTbl。
		//pUcsTbl指针由UCS表pUcsTbl的地址填充

		//定义UCS参数
		AcGePoint3d ptOrigin(0, 0, 0);
		AcGeVector3d vecXAxis(1, 1, 0);
		AcGeVector3d vecYAxis(-1, 1, 0);

		//创建新的UCS表的参数
		AcDbUCSTableRecord *pUcsTblRcd = new AcDbUCSTableRecord();

		//设置UCS的参数
		Acad::ErrorStatus es = pUcsTblRcd->setName(TEXT("NewUcs"));//为UCS命名
		if (es != Acad::eOk)//如果命名失败
		{
			delete pUcsTblRcd;
			pUcsTbl->close();
			return;
		}
		pUcsTblRcd->setOrigin(ptOrigin);//设置轴的原点
		pUcsTblRcd->setXAxis(vecXAxis);
		pUcsTblRcd->setYAxis(vecYAxis);
		//setXAxis函数:设置AcDbUCSTableRecord以vecXAxis作为它所代表的UCS的新X轴。vecXAxis必须在WCS的坐标中,并且必须具有非零的长度。
		
		//将新建的UCS表记录添加到UCS表中
		es = pUcsTbl->add(pUcsTblRcd);
		if (es != Acad::eOk)
		{
			delete pUcsTblRcd;
			pUcsTbl->close();
			return;
		}
		

		//关闭对象
		pUcsTblRcd->close();
		pUcsTbl->close();
	}

	static void AAAMyGroupSetCurUcs() {
		// Put your command code here

		//提示用户输入UCS的名称
		TCHAR ucsName[40];
		if (acedGetString(NULL, TEXT("\\n输入用户坐标系的名称:"), ucsName) != RTNORM)
			return;

		//获得指定的UCS表的记录
		AcDbUCSTable *pUcsTbl = NULL;
		acdbHostApplicationServices()->workingDatabase()
			->getUCSTable(pUcsTbl, AcDb::kForRead);
		if (!pUcsTbl->has(ucsName))
		{
			pUcsTbl->close();
			return;
		}
		AcDbUCSTableRecord *pUcsTblRcd;
		pUcsTbl->getAt(ucsName, pUcsTblRcd, AcDb::kForRead);

		//获得UCS的变换矩阵
		AcGeMatrix3d mat;
		AcGeVector3d vecXAxis, vecYAxis, vecZAxis;
		vecXAxis = pUcsTblRcd->xAxis();;
		vecYAxis = pUcsTblRcd->yAxis();
		vecZAxis = vecXAxis.crossProduct(vecYAxis);
		mat.setCoordSystem(pUcsTblRcd->origin(), vecXAxis,
			vecYAxis, vecZAxis);


		//关闭UCS表和UCS表记录
		pUcsTblRcd->close();
		pUcsTbl->close();

		//设置当前的UCS
		acedSetCurrentUCS(mat);

	}

	//(3)注册一个命令MoveUcsOrigin,用于移动当前UCS的 原点
	static void AAAMyGroupMoveUcsOrigin() {
		// Put your command code here
		//获得当前UCS的变换矩阵
		AcGeMatrix3d mat;
		Acad::ErrorStatus es = acedGetCurrentUCS(mat);

		//根据变换矩阵获得UCS的参数
		AcGePoint3d ptOrigin;
		AcGeVector3d vecXAxis, vecYAxis, vecZAxis;
		mat.getCoordSystem(ptOrigin, vecXAxis, vecYAxis, vecZAxis);

		//移动UCS的原点
		AcGeVector3d vec(100, 100, 0);
		ptOrigin += vec;

		//更新变换矩阵
		mat.setCoordSystem(ptOrigin, vecXAxis, vecYAxis, vecZAxis);

		//应用新的UCS
		acedSetCurrentUCS(mat);
	}

	//(4)注册一个命令RotateUcs,用于将当前UCS绕Z轴旋转60°
	static void AAAMyGroupRotateUcs() {
		// Put your command code here
		//获得当前UCS的变换矩阵
		AcGeMatrix3d mat;
		Acad::ErrorStatus es = acedGetCurrentUCS(mat);

		//根据变换矩阵获得UCS的参数
		AcGePoint3d ptOrigin;
		AcGeVector3d vecXAxis, vecYAxis, vecZAxis;
		mat.getCoordSystem(ptOrigin, vecXAxis, vecYAxis, vecZAxis);

		//绕Z轴旋转60°
		vecXAxis.rotateBy(60 * atan(1) * 4 / 180, vecZAxis);
		vecYAxis.rotateBy(60 * atan(1) * 4 / 180, vecYAxis);

		//更新变换矩阵
		mat.setCoordSystem(ptOrigin, vecXAxis, vecYAxis, vecZAxis);

		//应用新的UCS
		acedSetCurrentUCS(mat);
	}

	//(5)注册一个命令AddEntInUcs,用于根据UCS中的坐标创建实体
	static void AAAMyGroupAddEntInUcs() {
		// Put your command code here
		ads_point pt1, pt2;
		if (acedGetPoint(NULL, TEXT("\\n拾取直线的起点:"), pt1) != RTNORM)
			return;
		if (acedGetPoint(pt1, TEXT("拾取直线的终点:"), pt2) != RTNORM)
			return;
		//按照UCS坐标创建实体
		AcDbLine *pLine = new AcDbLine(asPnt3d(pt1), asPnt3d(pt2));

		//对实体进行几何变换
		AcGeMatrix3d mat;
		Acad::ErrorStatus es = acedGetCurrentUCS(mat);
		pLine->transformBy(mat);

		//加入到模型空间
		CDwgDatabaseUtil::PostToModelSpace(pLine);
	}

参考资料:

“AutoCAD ObjectARX(VC)开发基础与实例教程”

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片