使用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)开发基础与实例教程”