1、,第9章 访问和修改图形数据库,9.1 获取图元的名字AutoCAD的图形是由多个图形对象组成的,最基本的图形对象称作图元。图元之间是以链表的形式存储的。每个图元都有一个用16进制表示的唯一的名字。entnext函数可以获取图形库第一个图元的名字或指定图元的下一个图元的名字。entlast函数可以获取图形库最后一个,即最新生成的图元的名字。通过entnext函数,可以访问到图形库的每一个图元。,假定本作业依次绘制了一条直线、一个圆和一个圆弧。 (setq e1(entnext);返回图形库第一个图元即这条直线的图元名,并将其赋给了变量e1。 (setq e2(entnext e1);返回图形库
2、e1的下一个图元即这个圆的图元名,并将其赋给了变量e2。 (setq e3(entnext e2);返回图形库e2的下一个图元即即这个图弧的图元名,并将其赋给了变量e3。 (setq e4(entlast);返回图形库最后一个图元即这个图弧的图元名,并将其赋给了变量e1。因为圆弧既是第3个图元,也是最后一个图元,所以e3和e4记录的是同一图元的名字。,【例9-1】绘制下图所示的4个带有中心线的螺纹孔。要求首先获取中心线的螺纹孔的图元名,然后复制这些指定名字的图元。以下表达式首先生成了两条中心线和1个螺纹孔。在生成这些图元的同时获取并保存了这些图元的名字为e1、e2、e3和e4。,(comman
3、d “layer“ “m“ “zhongxin“ “l“ “center“ “ “) (command “line“ “-5,0“ “5,0“ “) (setq e1(entlast) (command “line“ “0,-5“ “0,5“ “) (setq e2(entlast) (command “layer“ “m“ “cuxian“ “lw“ 0.3 “ “) (command “circle“ “0,0“ 3) (setq e3(entlast),(command “layer“ “m“ “xixian“ “) (command “arc“ “-3.5,0“ “0,3.5“ “0,
4、-3.5“) (setq e4(entlast)以下表达式调用AutoCAD的copy命令,复制3个带有中心线的螺纹孔。 (command “copy“ e1 e2 e3 e4 “ “m“ “0,0“ “12,0“ “24,0“ “36,0“ “),例9-2 定义绘制图b所示图形的命令。插入点p0、直径d、宽度b和h作为绘制该图形时交互输入的参数。该例的主要目的是示范如何利用图元名实现AutoCAD的图形编辑和填充剖面线。,a b (defun c:keyway() (setq pc (getpoint “输入定位点: “) (setq d (getdist pc “输入轴的直径:“) (se
5、tq b (getdist pc “输入键槽的宽度:“),(setq w (getdist pc “输入键槽的深度:“) (setq r (* 0.5 d) (command “circle“ pc r) ;绘制圆 (setq e1 (entlast) ;将entlast返回的该圆的图元名赋给e1 (setq p0(polar pc 0 r) ;p0是圆上一点,将用于修剪该圆 (setq p1(list (car pc) (+ (cadr pc) (* 0.5 b) (setq p2(list (+ (car pc) (* 1.2 r) (cadr p1) (command “line“ p1
6、 p2 “) (setq e2 (entlast) ;将entlast返回的该直线的图元名赋给e2 (setq p3(list (car pc) (- (cadr pc) (* 0.5 b) (setq p4(list (car p2) (cadr p3) (command “line“ p3 p4 “),(setq e3 (entlast) ;将entlast返回的该直线的图元名赋给e3 (setq p5(list (+ (car pc) (- r w) (+ (cadr pc) (* 0.5 b) (setq p6(list (+ (car pc) (- r w) (- (cadr pc)
7、 (* 0.5 b) (command “line“ p5 p6 “) (setq e4 (entlast) ;将entlast返回的该直线的图元名赋给e4 ;e1、e2等作为剪切边,p0、p1等点确定被剪边和剪去哪一段 (command “trim“ e1 e2 e3 e4 “ p0 p1 p2 p3 p4 “) ;e1、e2等作为剖面域的边界绘制剖面线 (command “hatch“ “ansi31“ “2“ “0“ e1 e2 e3 e4 “) ; ),9.2 图元表图元表记录着图元的名字、类型、几何数据、图层、颜色等信息。通过修改或创建图元表,可以实现编辑或生成图元。 9.2.1 获
8、取图元表例如输入下面3个表达式: (command “text“ “10,20“ 5 0 “ABCDE“);书写文本 (setq e(entlast);获取文本的图元名,将图元的名字赋给变量e。 (setq elist(entget e) ;获取图元名字为e的图元表。在“Command:“提示下键入!elist或在控制台“_$“提示下键入elist,即可得到以下该图元的图元表。,(-1 . );图元名(0 . “TEXT“);图元种类(330 . );软指针句柄(5 . “19F“);图元描述字(100 . “AcDbEntity“);AutoCAD图元(67 . 0);模型空间(410 .
9、“Model“);模型空间标识(8 . “0“) ;所在图层名(100 . “AcDbText“) ;AutoCAD文本(10 10.0 20.0 0.0) ;定位点坐标(40 . 5.0);文本字高(1 . “ABCDE“);文本内容,(50 . 0.0);文本的旋转角度(41 . 1.0);文字的宽度因子(51 . 0.0);文字的倾斜角度(7 . “STANDARD“);字样的名字(71 . 0);正常文本(非左右或上下镜像的文本)(72 . 0);左下角点对齐方式(11 0.0 0.0 0.0);辅助的定位点坐标(210 0.0 0.0 1.0);厚度方向(100 . “AcDbTex
10、t“) ;AutoCAD文本(73 . 0);不垂直书写),对图元表的补充说明: (1)图元表的每个元素还是表,子表的第一个元素是具有一定含义的整数,其含义与图元在DXF(图形交换文件)中实体代码的含义相同(详见AutoCAD有关DXF文件的介绍)。 (2)多数的子表采用了点对结构,这样既节省存储空间,也可以简化运算,详见第2.4节数据的存储结构。 (3)其他种类图元的图元表的非几何信息部份基本相同,几何信息部份有些差异。 9.2.2 对图元表的操作假定elist是某图元的图元表。利用AutoLISP有关表处理的函数可以修改图元表。 (1)了解图元的种类 (cdr (assoc 0 elist
11、),该表达式的内层表达式中,用0作为关键字,在elist表中寻找相关的子表,返回有关图元种类的子表(0 . “图元种类“),由于此表为点对,所以cdr函数返回它的第2个元素“图元种类“。若此图元为直线,则返回“LINE“,若此图元为单行文本,则返回“TEXT“。 (2)了解图元所在图层的名字 (cdr (assoc 8 elist)该表达式的内层表达式中,用8作为关键字,返回elist表中有关图层名字的子表(8 . “图层名“),由于此表为点对,所以cdr函数返回它的第2个元素“图层名“。 (3)了解圆、圆弧的半径或单行文本的字高 (cdr (assoc 40 elist)该表达式的内层表达式
12、中,用40作为关键字,返回elist表中有关圆、圆弧的半径或单行文本的字高的子表(40 . 数值),由于此表为点对,所以cdr函数返回它的第2个元素具体的数值。,(4)了解直线的起点、圆、圆弧的中心或单行文本的定位点 (cdr (assoc 10 elist)该表达式的内层表达式中,用10作为关键字,返回elist表中有关直线的起点、圆、圆弧的中心或单行文本的定位点的子表(10 数值 数值 数值),注意此表不再是点对,所以cdr函数返回去掉它的第1个元素之后的子表,即点的XYZ坐标。 (5)用圆、圆弧的半径或单行文本的新值取代其老值 (setq elist (subst (cons 40 h)
13、(assoc 40 elist)elist) (cons 40 h)构造一个新的点对子表,例如(40 . 3.5)。(assoc 40 elist)返回elist表内的点对子表,例如(40 . 5.0)。subst函数用新子表,例如(40 . 3.5),替换elist表内的老子表(40 . 5.0)。最外层的setq函数将替换后的赋给了变量elist。 (6)更新图形库的图元表 (entmod elist) entmod函数的功能是更新图形库的指定图元表的图元,即更新了实际图形对象。例如单行文本的字高由5.0改变为3.5。,9.2.3 举例 【例9-3】定义将本作业所有的单行文本改变为指定高度
14、的命令。,右图所示为修改图形数据库内单行文本字高的程序流程图,其中e1是用于存放图元名的变量。单行文本的图元种类是TEXT,用MTEXT书写的是段落文本,它的图元种类是MTEXT。因此本程序不能修改用MTEXT书写的文本。,否,否,是,是,以下是定义改变本作业所有单行文本为指定的高度命令的程序代码: (defun c:cth( / h e el) (setq h(getdist “n输入文本新的字高: “) (setq e(entnext);得到第一个图元的名字 (while e ;当e有定义时做以下运算 (setq el(entget e);得到第一个图元的图元表 (if (= “TEXT“
15、 (cdr (assoc 0 el) (progn ;如果图元的类型为“TEXT“时做以下运算 (setq el(subst (cons 40 h)(assoc 40 el)el);新字高替换图元表的原字高 (if (= 3 (cdr (assoc 72 el);如果文本为Align方式对齐,(setq el(subst (cons 72 0) (assoc 72 el) el);忽略第二个定位点 ) (entmod el);更新图形数据库的el图元表 ) ) (setq e(entnext e);令e等于e的下一个图元名 ) (princ);静默退出 ),9.3 选择集选择集是有名字的一些图
16、元名的集合,常用于编辑或修改图形对象的命令。 9.3.1 常用的有关选择集的函数 (1)(ssget 选择方法 点1 点2 点表 过滤表) 创建一个选择集。有以下一些选择方法。 C(Crossing):与点1、点2所确定的窗口相交的那些对象被选中。 CP(Cpolygon):与点表所确定的多边形相交的那些对象被选中。 F(Fence):与点表所确定的折线相交的那些对象被选中。,I(Implied):处于夹取(Grips)状态的那些对象被选中 L(Last):最新的、最后绘制的那个图元被选中。由于在多文档环境下最后绘制的对象并不一定是可见的,例如,这个绘图窗口被最小化或未放置在顶层,这时使用该选
17、项将返回nil。 P(Previous):上一次创建的选择集。 W(Window):整体在点1、点2所确定的窗口之内的那些对象被选中。 WP(Wpolygon):整体在点表所确定的多边形之内的那些对象被选中。 X:整个数据库,包括被关闭、被冻结图层上的对象和屏幕之外的那些对象被选中。,:E:通过光标拾取框的那些对象被选中。 :N:在该函数的执行过程中,为选定对象调用ssnamex函数获得容器块和转换矩阵的附加信息。只有通过“W“、“C“和点拾取选择方法时,才可以使用这一附加信息。 :S:只允许单一选择集。 点1、点2、点表和过滤表是与选择方法配合使用的。 过滤表的功能是根据过滤表描述的条件对所
18、选的对象进行筛选,只保留满足过滤条件的对象。过滤表是entget函数返回的图元表中的点对,例如(0 . “LINE“)、(8 . “LAYER1“)、(6 . “center“)、(62 . 1),点对的第1个元素是图形交换文件中的组码,详见AutoCAD有关DXF文件的介绍。,如果仅提供了一个点,该函数认为用户通过这个点来选择单个的对象。如果省略所有的参数,在调用该函数时将出现“Select objects:“提示,这用户以交互方式选择对象。在这种情况下,亮显被选取的对象。该函数忽略当前设置的对象捕捉模式。由于选择集会占用临时文件存储区,所以AutoLISP不允许同时打开128以上的个选择集
19、。如果成功该函数返回创建选择集的名称,例如,否则返回nil。以下是调用该函数的一些表达式。(setq s1 (ssget (2 2);创建一个选择集,如果存在一个通过点(2,2)的图元,它将被选中并将返回的选择集的名字赋给变量s1,(setq s2 (ssget “w“ (0 0) (10 10);创建一个选择集,它的成员是所有整体在对角点(0,0)和(10,10)窗口内的图元,如果成功则将选择集的名字赋给变量s2(setq s3 (ssget “X“ (0 . “LINE“) (62 . 5) ;(0 . “LINE“) (62 . 5)是过滤表,该选择集的成员是当前作业中所有蓝色的直线,如
20、果成功将选择集的名字赋给变量s3(setq s4 (ssget);以交互方式创建一个选择集。执行到该表达式时,自动切换到图形窗口,出现“Select objects:“提示,等待用户操作。用户此时可用各种选择方法多次选择,直至用空回车响应“Select objects:“提示。选择集由交互选择的这些图元组成,将选择集的名字赋给变量s4,(2)(entsel 提示信息)提示用户以单点方式选择单个对象。若省略提示信息,则提示信息为“Select object:“。返回值为两个元素组成的表,第一个元素是所选的图元名,第二个元素是用户选择对象时拾取点在当前UCS下的坐标。 (3)(ssadd 图元名
21、选择集)将指定的图元加入到选择集。如果调用该函数时无参数,将创建一个空选择集;如果只提供图元名,将创建一个仅含该图元的选择集。,(4)(ssdel图元名 选择集)从选择集内移去指定的图元。 (5)(sslength ss)返回选择集的长度,即选择集内图元的数量。 (6)(ssname 选择集 序号)返回选择集中由序号指定的那个图元名。选择集内第一个元素的序号为零。,9.3.2 举例 【例9-4】 定义将选到的单行文本改变为指定高度的命令。 (defun c:csth( / h s1 n e el) (setq h(getdist “n输入文本的高度:“) (setq s1(ssget);以交互
22、方式得到一个选择集 (setq n 0) ;序号的初值为0 (repeat (sslength s1);重复执行,执行的次数等于所选对象的个数 (setq e(ssname s1 n);得到选择集内第n个对象的图元名 (setq el(entget e);得到这个对象的图元表 (if (= “TEXT“ (cdr (assoc 0 el);判断这个对象是否为TEXT(progn ;是TEXT,(setq el(subst (cons 40 h) (assoc 40 el) el);用新字高替换图元表的原字高点表 (if (= 3 (cdr (assoc 72 el) ;如果文本为Align方式
23、对齐 (setq el(subst (cons 72 0)(assoc 72 el) el);忽略第二个定位点 )(entmod el) ;更新图形数据库的el图元表 ) ) (setq n(1+ n) ;序号n的数量加1 ) ),9.4 符号表AutoCAD的符号表是指视窗表、线型表、图层表、字样表、视图表、用户坐标系表、用户应用程序标识表、尺寸式样表和块记录表。在某些情况下,仅从图元表不能了解图元的全部特性,例如当图元的颜色、线型与所在图层一致时,图元表中没有记录颜色、线型的子表,因此,了解这样图元的颜色,就需要访问图层表。 9.4.1 符号表操作函数 (1)(tblnext 表的种类 回
24、绕)表的种类可以是“LAYER“、“LTYPE“、“VIEW“、“STYLE“、“BLOCK“、“UCS“、“APPID“、“DIMSTYLE“和“VPORT“。若回绕项为T,则返回指定种类的第一个符号表,若该项为nil或缺省,则返回指定种类的当前表符号的下一个符号表。,例如返回图层表,若当前作业的图层名依次是“0“、“layer1“、 “layer2“和“layer3“。随时输入表达式(tblnext “layer“ T)都返回(0 . “LAYER“) (2 . “0“) (70 . 0) (62 . 7) (6 . “CONTINUOUS“)。因为回绕项为T,所以返回当前作业的第一个图层
25、表。接着输入表达式(tblnext “layer“ nil)或(tblnext “layer“)返回(0 . “LAYER“) (2 . “ layer1“) (70 . 0) (62 . 7) (6 . “CONTINUOUS“)。因为回绕项为nil或缺省,所以返回当前图层表的下一个图层表。同样的操作依次返回layer2、layer3的图层表。再输入这个表达式,将返回nil,因为layer3是最后的图层。,例如返回块定义表,若当前作业已定义了名字为“BOX“的图块,输入表达式(tblnext “block“) 返回(0 . “BLOCK“) (2 . “BOX“) (70 . 0) (10
26、9.0 2.0 0.0) (-2 . ) (2)(tblobjname 表的种类 表名) 返回指定种类表的图元名。如果找到,返回符号表的图元名。返回的图元名可以用于entget和entmod 操作。例如(tblobjname “layer“ “0“),返回名字为0的图层表的图元名。,(3)(tblsearch 表的种类 表名 设置下一个)返回指定种类和名字的符号表。如果“设置下一个“为T,该表将作为定位点,随后调用tblnext函数在不回绕的设置下,就会返回该表的下一个表。例如(tblsearch “layer“ “ t) 返回(0 . “LAYER“) (2 . “layer1“) (70
27、. 0) (62 . 7) (6 . “CONTINUOUS“)图层表,且layer1为定位点,接着输入表达式(tblnext “layer“ )返回(0 . “LAYER“) (2 . “layer2“) (70 . 0) (62 . 7) (6 . “CONTINUOUS“)图层表。,(defun c:ccolor (/ oldcolor newcolor new_cl e el old_cl layname laytab laycolor)(setq oldcolor (getint “n输入待改变的颜色号: “)(setq newcolor (getint “n输入新的颜色号: “)(
28、setq new_cl (cons 62 newcolor) ;构造新颜色子表(setq e (entnext) ;得到第一个图元名(while e ;当图元的名字有定义时(setq el (entget e) ;得到一个图元表(if(= “LINE“ (cdr (assoc 0 el);判断该图元是否是直线(progn ;是直线(setq old_cl (assoc 62 el) ;得到老颜色子表(点对)(if (null old_cl);判断颜色子表是否为空,(progn ;没有颜色子表,即颜色随层 (setq layname (cdr (assoc 8 el) ;得到图层名 (setq
29、laytab (tblsearch “LAYER“ layname) ;得到指定图层名的图层表 (setq laycolor (cdr (assoc 62 laytab) ;得到图层的颜色号 (if(= oldcolor laycolor);判断图层的颜色是否与待改的颜色相同 (progn ;相同,该层颜色为被改色 (setq el (cons new_cl el) ;插入颜色子表 (entmod el);更新图形数据库的el图元表 ),(progn ;有颜色子表,即颜色独立于图层 (if(= oldcolor (cdr old_cl);判断图元的颜色是否与待改的颜色相同 (progn ;相同,该层颜色为被改色 (setq el (subst new_cl old_cl el) ;颜色替换 (entmod el) ; 更新图形数据库的el图元表 )(setq e (entnext e);令e等于e的下一个图元的名字 ),