3.11 数据类型转换函数
有时会要求转换数据类型,特别是当使用acutPrintf()函数在命令行提示用户时。表3-10列出了ADS转换函数。 表3-10 常用的ADS转换函数
函 数说 明
acdbRToS() 转换ads_real类型的数值为字符串 acdbAngToS() 按格式转换角度为字符串 acutToUpper() 把字符转换为大写 acutToLower() 把字符转换为小写
acedTrans() 把点或位移从一个坐标系转换到另一个坐标系 1. acdbRToS()[ads_rtos()] acdbRToS()函数的定义如下:
acdbRToS()函数按照unit和prec(精度)设置的格式把val转换为字符串,结果放入str,str必须指向足以容纳格式化字符串的一块缓冲区。参数unit选取转换后字符串的单位制,其值应符合AutoCAD系统变量LUNITS允许的取值范围(1~5,参阅AutoCAD在线帮助中的“系统
变量”)。如果unit
的值为-1,acdbRToS()函数使用LUNITS的当前值。参数prec选取字符串中包含的小数位数。如果prec的值为-1,acdbRToS()函数使用AutoCAD系统变量LUPREC的当前值。AutoCAD尺寸标注变量DIMZIN的当前值控制acdbRToS()函数是否把前导零和结尾零写入str。如果acdbRToS()函数调用成功
,返回RTNORM,否则返回一个错误码。
2. acdbAngToS()[ads_angtos()] acdbAngToS()函数的定义如下:
acdbAngToS()函数按照unit和prec(精度)设置的格式把v转换为字符串,参数v以弧度为单位,结果放入str,str必须指向足以容纳格式化字符串的一块缓冲区。字符串的大小取决于请求模式和精度,通常15字节就足够了。参数unit选取角度转换后的单位制,其值应符合AutoCAD系统变量AU
NITS允许的取值范围。此外,如果设置unit的值为-1,acdbAngToS()函数使用AUNITS的当前值。参数prec选取字符串中包含的小数位数。如果prec的值设置为-1,acdbAngToS()函数使用AutoCAD系统变量AUPREC的当前值。AutoCAD尺寸标注变量DIMZIN的当前值控制acdbAngToS()函数是否把
前导零和结尾零写入str。AutoCAD用户指南说明了DIMZIN如何取值。如果acdbAngToS()函数调用成功,返回RTNORM,否则返回一个错误码。
3. acutToUpper()[ads_toupper()]和acutToLower()[ads_tolower()] acutToUpper()和acutToLower()函数的定义如下:
这两个函数分别把字符参数(ASCII码整数值)转换为大写或小写字符。
4. acedTrans()[ads_trans()] acedTrans()函数的定义如下:
acedTrans()函数把坐标点或位移量从一个坐标系统转换到另一个坐标系统。参数pt既可解释为一个三维点,也可解释为一个三维位移矢量。参数from指定pt所在的坐标系统,参数to指定转换后的坐标系统。如果参数disp不等于0,则pt被看作是一个位移矢量,否则pt是一个点。说明acedT
rans()函数最好的方法是通过例子。AutoCAD使用的坐标系统代码为:1表示WCS(世界坐标系统),2表示当前的UCS(用户坐标系统)。AutoCAD还定义了2和3,这些值我很少使用,你可以查阅有关文档。 下面是一段从UCS转换到WCS的程序代码:
这是第一段没有使用结果缓冲区指针的程序代码。在函数中声明结果缓冲区类型的变量为局部变量,在函数退出时会自动清除,无需调用acutRelRb()函数。然而,请注意必须在resbuf 变量的前面放上&运算符,因为acedTrans()函数需要一个指向 resbuf 结构的指针(或地址)。
3.12 应用程序实例CH3_2
在本应用程序中,我们再次示范了acedGetXXX()类函数的使用,还示范了选择集函数的使用。当循环通过选择集时,还示范了怎样利用结果缓冲区链表改变选择集中实体的特性。在一个纯粹的ObjectARX应用程序中,改变实体的特性是由相应实体类中的get和set函数完成的。我们先来观察
应用程序实例CH3_2的程序代码,然后讨论其要点。CH3_2.CPP文件内容如下: 用户定义命令CEL的CH3_2Commands.cpp文件内容如下:
3.13 应用程序实例CH3_2要点分析
本应用程序能选取一组实体,并把这些实体的图层改为选中的目标实体所在的图层。虽然在AutoCAD R14/2000中已经存在类似的命令,但我要说明的只是选择集的使用。在该应用程序中,要求用户选取组成选择集srcSS的实体,如下所示: 然后,接着调用acedEntSel()函数选取目标实体,如下所示:
如果一切正常,最后将调用用户定义的chgEntsLyr()函数,实现程序的全部动作。该函数要求有两个参数:一个为实体,另一个为选择集。
注意它们都是ads_name类型的数据。我们必须提取目标实体的数据,这可以调用acdbEntGet()函数来实现,该函数返回指针rbTargEnt指向的结果缓冲
区链表。我们使用结果缓冲区指针rbTrav遍历该链表,在此提取层名并拷贝到lyrName。不要使用结果缓冲区指针rbTargEnt来遍历该链表,因为在完成该操作后,无法释放由acdbEntGet()函数分配的内存—一个典型的内存泄漏错误,极其平常。下一步是使用acedSSLength()函数得到选择
集的长度,之后就进入了for循环。在for循环中,使用acedSSName()函数得到实体名,并在ssEntName中返回。我们再一次使用结果缓冲区指针rbTrav遍历该链表,当到达图层结果缓冲区时,把rbTrav->resval.rstring的值改为lyrName。注意我们为何使用acdbEntMod(rbSSEnt)
函数更新实
体。使用结果缓冲区rbSSEnt更新实体是因为rbSSEnt是结果缓冲区链表,而rbTrav只是用来遍历该链表的结果缓冲区指针。在for循环开始下一轮循环之前,释放rbSSEnt缓冲区。一旦从函数调用返回,在退出应用程序之前,调用acedSSFree()函数。可别忘了释放选择集。
3.14 应用程序实例CH3_3
本应用程序示范了怎样对选择集使用ads_matrix数据类型的矩阵和怎样使用对ads_matrix数据类型进行操作的选择集函数acedXformSS()。利用矩阵,可以比例变换、旋转、镜像、平移,可以绕X、Y或Z轴旋转。在该应用程序中,我们仅示例了比例变换。CH3_3.CPP文件内容如下:
用户定义命令TSS的CH3_3Commands.cpp文件内容如下:
3.15 应用程序实例CH3_3要点分析
在tss()(转换选择集)函数中,有一个ads_matrix数据类型的变量xform和一个选择集ssGrp。使用acedSSGet()函数请求用户选择一组实体。如果选择成功,将把实体放在选择集ssGrp中。然后,使用acedGetReal()函数请求用户输入一比例系数,注意我们是怎样初始化acedInitGet()函数的
。既然我们有了一个有效的选择集和一个比例系数,我们就可以调用用户定义的ident_init()函数初始化矩阵,这是一个嵌套的for循环,
把所有的矩阵元素初始化为0.0。然后再用一个for循环,把前三列对角线上的元素初始化为1.0。被初始化为1.0的元素是id[0][0]、id[1][1]和id[2][
2]。在矩阵完成初始化以后,我们用sf中的比例系数来替代这三个元素的值。我们无须使用for循环遍历选择集,只需简单地调用acedXformSS(ssGrp,xform)函数,这将一次改变选择集中所有实体的比例系数。在ObjectARX的几何类AcGe-中有许多矩阵转换操作函数。 有许多ADS函数我未涉及(或未详细讨论),主要是因为这些函数针对ADS/C形式的编程,ObjectARX有它自己的定义,其编程形式完善
得多(并非我有偏见)。我未涉及到的ADS函数有:acedDefun()、acedGetFunCode()、acedRegFund()、acedInvoke()、acedGetArgs()、acdbEntDel()、
acdbEn
tMod()、acdbEntNext()、acdbEntGet()、acdbEntUpd()和acdbHandEnt(),等等。我所讨论的ADSRX函数是在ObjectARX中使用可能性最大的函数。
//////////////////////////////////////////////////////////////////////////////////////////////////////