3.10.2 选择集的关系过滤
在选择集中可以使用关系运算符。例如:我们要选取“parts”图层上半径大于等于2.0的所有圆。在缺省情况下,acedSSGet()函数选取满足过滤表中所有条件的实体。过滤时每两个项之间的隐含关系是“相等(equals)”。对于数值型组码(整数、实数、点和向量),借助在结果缓冲
区中包
含一个说明关系运算符的特殊组码“-4”可以指定其他的关系运算。该运算符应用于紧跟其后的结果缓冲区项。关系运算符由字符串指定。表3-8列出了所有的关系运算符。
关系运算符可以用实例来很好地说明,继续我们所举的例子:选取“parts”图层上半径大于等于2.0的所有圆。其程序代码如下: 表3-8 选择集过滤表的关系运算符
关系运算符说 明 “*” 任意(始终为真) “=” 等于
“!=” 不等于(C/C++) “/=” 不等于(AutoLISP) “<>” 不等于 “<” 小于 “<=” 小于或等于 “>” 大于 “>=” 大于或等于
“&” 按位“与”(只用于整数组码) “&=” 按位等于(只用于整数组码)
3.10.3 选择集的条件过滤
除关系测试外,我们还可以使用条件运算符。表3-9列出了所有的选择集条件运算符。 表3-9 选择集过滤表的条件运算符 起始运算符 中间内容 终止运算符 “
选择集的条件运算符允许我们执行像选择图形中半径为1.0的所有圆和“parts”图层上的所有直线这一类的选择集操作。编程后代码如下: 本例有助于掌握选择集的关系过滤和条件过滤。
3.10.4 选择集的扩展实体数据过滤
从R11版本起,AutoCAD就有了一个为实体添加数据的机制,称为扩展实体数据(xdata)。我不准备深入讨论扩展实体数据,因为从AutoCAD R13 c4a起,在AutoCAD R14和以后的版本中引入了一种新的机制称为XRecords,这在后面的章节中将会加以讨论。扩展实体数据通常是由外部应用程序附加到一个对象上的文本串、数值、3D点、距离、层名或其他数据。扩展数据的大小是每个实体16KB。注意XRecords是不附加于任何实体的,因此XRecords的存在并不需要实体的存在。借助在过滤表中使用-3组码标记指定应用程序名,就可以检索扩展数据。acedSSGet()函数返回登记有特定名称的扩展数据的实体集合,acedSSGet()函数并不检索单个扩展数据项(组码范围为1000~2000)。 下面为选择所有实体的代码段,所有实体均有以其应用程序ID号为“APPNAME”注册的扩展数据:在ADSRX文档中,有关扩展实体数据的信息还有很多,但由于AutoCAD R14和以后的版本使用XRecords,因此,在后面的章节中我们将详细讨论XRecords。
3.10.5 转换矩阵和选择集 acedXformSS()[ads_xformss()]
借助acedXformSS()函数,选择集可以使用转换矩阵。利用转换矩阵,可以变比、移动、旋转或镜像选择集中的实体。这可以用适当的矩
阵元素设置调用acedXformSS()函数来实现,而不是循环整个选择集并执行acedCommand()/acedCmd()函数来变比、移动、旋转或镜像每一个实体。在这里我不想完整地讨论矩阵代数学。ObjectARX已经定义了处理矩阵代数的数值函数(见AcGeMatrix2d和AcGeMatrix3d矩阵操作类)。前面讲过转换矩阵是一个具有ads_real数据类型的4×4阶数组。矩阵的前三列确定比例和旋转,第四列是一个平移向量。矩阵的最后一行其值规定为[0 0 0 1],传递ads_matrix型参数的函数忽略了此值。ADSRX为平移操作定义符号T,如下所示:
acedXformSS()函数的定义如下:acedXformSS()函数将一个转换矩阵genmat应用于由ssname指定的选择集。参数genmat是一个4×4阶矩阵。如果genmat没有均匀变比,acedXformSS()函数返回RTERROR。把转换矩阵应用于选择集是不使用acedCommand()、acedCmd()或acdbEntMod()函数即在选择集中变比、旋转或移动实体的一种方法。如果acedXformSS()函数调用成功返回RTNORM,否则返回
RTERROR。
下面是一段初始化矩阵的程序代码:
在上面的函数中,我们使用嵌套的for循环初始化了ads_matrix类型的参数id(各元素的值为0),然后再用一个for循环初始化了元素0,0 1,1 2,2和3,3使其值为1。现在矩阵被初始化为恒等矩阵。观察如下由Tx、Ty和Tz决定的平移矩阵:
改变第四列中的前三个元素的值并应用acedXformSS()函数,选择集中的所有实体将沿X、Y和Z方向移动适当的距离。注意,如果只需
要在X方向移动,那么只需改变矩阵中的Tx值。
当处理选择集和acedXformSS()函数时,所有的比例系数必须相等,即Sx=Sy=Sz。还有像旋转矩阵之类的其他2D和3D操作(参阅ADSRX和ObjectARX文档)。现在让我们来看一个用于选择集操作的转换矩阵实例。
这是要对选择集实施变换的矩阵,X、Y和Z方向的缩放系数是0.5,选择集的移动距离是(20.0,5.0)。
下面是程序代码:
3.10.6 选择集的操作
既然我们已经看到有各种方法创建选择集,现在就让我们来看看操作这些选择集的函数。也许我们要知道的第一件事是有多少实体组成了该选择集。
1. acedSSLength()[ads_sslength()]
acedSSLength()函数返回组成选择集的实体个数。
其定义如下:acedSSLength()函数返回一个长整数len,表示选择集sname中含有的实体个数。结果是特定实体的个数,不管选择集是怎样选取的,选择集不包含重复的实体。如果acedSSLength()函数调用成功,返回RTNORM,否则返回一个错误码。acedSSLength()函数通常和for循环连用,如下例程序代 码所示:
2. acedSSName()[ads_ssname()]
在上述代码中,如果acedSSLength()函数返回的变量len的值大于0,那么我们就能够得到一个由长整型变量i表示在选择集中位置的特定实体。为得到在选择集特定位置上的实体,可以使用acedSSName()函数。表示实体在选择集中位置的序号从0开始,第一个实体的序
号是0。
下面是acedSSName()函数的定义:acedSSName()函数选取选择集ss中位置序号为i的实体,并在entres中返回实体名。实体从0开始编号,所以i必须是非负的且不大于选择集中最后一个实体的序号(acedSSLength(ss)-1)。在用acedSSGet()函数获得的选择集中的实体名总是
主实体名。acedSSName()函数不能获得子实体名(例如块的属性和多段线的顶点)。如果acedSSName()函数调用成功,返回RTNORM,否则返回一个错误码。
在过去,就ADS和选择集而言,函数acedSSLength()返回选择集的长度。一旦有了选择集的长度,就能够使用for循环通过选择集,并使用acedSSName()函数获得实体名。一旦有了实体名,就能使用acdbEntGet()函数获得实体数据,该函数返回结果缓冲区链表形式的实体数据。然后可以修改结果缓冲区表,调用acdbEntMod()函数改变实体数据库,如有必要可以调用acdbEntUpd()函数更新实体的表达。
正如前文所述,ObjectARX处理实体数据库有更好的机制,其中一些在上面的代码段中已有暗示。现在趋向于不再使用acdbEntGet()、acdbEntMod()和acdbEntUpd()函数。然而,我们仍然使用选择集。
3. acedSSFree()[ads_ssfree()]
在上述代码段的最后一行,调用了acedSSFree()函数。当处理选择集时,在操作完成后释放选择集是很重要的,因为AutoCAD只能同时
打开有限的选择集个数(最大为128)。
下面是acedSSFree()函数的定义:acedSSFree()函数释放由sname指定的选择集。该选择集必须预先通过调用acedSSGet()或acedSSAdd()函数获得。稍后我们将讨论acedSSAdd()和acedSSDel()函数。
ADSRX应用程序不能同时打开多于128个的选择集。如果达到了此极限,AutoCAD拒绝创建更多的选择集。同时,我们不推荐使用大量的选择集。而应该保持一个合理的选择集数目,并尽可能调用acedSSFree()函数释放无用的选择集。如果acedSSFree()函数调用成功,返回RTNORM,否则返回一个错误码。
4. acedSSAdd()[ads_ssadd()]
acedSSAdd()函数创建一个新的选择集或把一个实体添加到一个已存在的选择集中。
acedSSAdd()函数的定义如下:参数ename指定一个实体,sname指定一个选择集。如果ename和sname均为空指针(NULL),acedSSAdd()函数创建一个没有实体的新选择集(以后可以添加实体的空选择集),其名由result设置。如果ename为一有效实体,但sname是NULL,则acedSSAdd()函数创建一个新的选择集,其中包含一个实体ename,选择集名为result。如果ename指定了一有效实体,sname指定了一已有的选择集,acedSSAdd()函数把实体ename添加到由sname指定了的选择集中。在所有情形下,acedSSAdd()函数把result设置为新建的或更新的选择集名。如果由ename指定的实体已经在sname指定的选择集中,acedSSAdd()函数就不考虑这种请求,也不报告错误。参数sname和result可以指定同一个选择集。这是添加实体ename到一个已有的选择集中去的最直观的方法。调用acedSSAdd()函数且sname
参数为NULL创建的每一个选择集,以后必须调用acedSSFree()函数来释放。这一点也适用于空选择集(当ename也是NULL时)。如果acedSSAdd()函数返回一错误码,就不创建新的选择集。如果acedSSAdd()函数调用成功,返回RTNORM,否则返回一个错误码。
5. acedSSDel()[ads_ssdel()]
用acedSSDel()函数从一个已有的选择集中删除实体。acedSSDel()函数的定义如下:
acedSSDel()函数从选择集ss中删除由ename指定的实体。实体名和选择集名必须对当前图形有效。 6. acedSSMemb()[ads_ssmemb()]
最后,使用acedSSMemb()函数可以检验一个实体是否在一个已有的选择集中。acedSSMemb()函数的定义如下:
acedSSMemb()函数测试实体ename是否是选择集ss的一员。实体名和选择集名必须对当前图形有效。如果acedSSMemb()函数找到ename,返回RTNORM,如果没有找到,则返回RTERROR。