最近有同事遇到了 AutoCAD 中的一种图块,不能用 explode
命令或 AutoCAD Express Tool 的 burst
命令进行分解。查看一下这种图块的属性,其图元是多重块插入(MINSERT),行、列数量均为 1,行、列间距均为 0。多重块插入(MINSERT)是不能用这两个命令分解的,如果我们找到了这个图块的块名,直接插入普通的块插入(INSERT),这个块插入就能够被分解。不过,使用这种多重块插入进行锁定防止分解的时候,操作者一般会使用匿名块(Anonymous Block),这样,这种图块就不能通过 insert
命令来插入到图形数据库中,从而能起到更好的锁定作用。这种技术其实挺无聊的,解锁的方法其实也非常简单,今天就来聊一聊这个问题。
多重插入匿名块锁定方法
我们可以使用 AutoLisp/VisualLisp 来完成这样的工作,下面列出这种方法的源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| (defun c:lock(/ blockname ss sslst) (vl-load-com) (if (setq ss (ssget)) (progn (setq blockname (rtos (getvar "CDATE") 2 8) i 0 sslst '(((0 . "ENDBLK"))) ) (repeat (sslength ss) (setq sslst (cons (entget (ssname ss i)) sslst)) (entdel (ssname ss i)) (setq i (1+ i)) ) (setq sslst (cons (list '(0 . "BLOCK") (cons 2 blockname) '(70 . 0) '(10 0.0 0.0 0.0)) sslst)) (mapcar 'entmake sslst) (entmake (list '(0 . "INSERT") (cons 2 blockname) '(100 . "AcDbEntity") '(8 . "0") '(100 . "AcDbBlockReference") (cons 10 '(0.0 0.0 0.0)) '(70 . 1) '(71 . 1) '(44 . 0.0) '(45 . 0.0) ) ) (vla-put-name (vla-item (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)) ) (vla-get-name (vlax-ename->vla-object (entlast))) ) "*U") ) (princ "\n 未选中图元!") ) (princ) )
|
代码的主体 3~40 行是对选中图元情况作出一个判断分支,未选定图元的情况不需要赘述。在选定图元的情况下,9~13 行遍历所有选中图元,获取图元的组码列表,并将其加入到 sslst
表中,并删除图元。遍历之前,sslst
中先加入了 '((0 . "ENDBLK"))
作为图块定义的结束,遍历之后,sslst
中再加入图块定义开始的组码列表,其中块名使用由当前时间转换的一个字符串。对 sslst
中的每个表进行 entmake
后,就创建了一个图块定义。16~29 行的工作是在原位以多重块插入的形式重建这些图元。30~37 行的工作是修改了刚刚插入的图块的块定义,将其改为匿名块。至此,AutoCAD 中的这部分图元就以一个匿名块的形式存在,不能够用 explode
或 burst
命令分解,也不能通过 insert
命令插入在图形数据库中。
块解锁分解方法
除了使用多重插入匿名块的方法进行锁定外,图块(BLOCK)本身也有通过块分解性特性的设定来防止分解,这里我们将这两种情况一并考虑,解锁图块并分解的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| (defun c:unlock(/ ename ellst blkobj flag) (vl-load-com) (while (not (= (cdr (assoc 0 (setq ellst (entget (setq ename (car (entsel))))))) "INSERT")) (princ "\n 选择的不是图块!") ) (setq blkobj (vla-item (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)) ) (vla-get-name (vlax-ename->vla-object ename)) ) ) (if (equal :vlax-false (vla-get-Explodable blkobj)) (progn (vla-put-Explodable blkobj :vlax-true) (setq flag T) ) ) (if (and (= (cdr (assoc 70 ellst)) 1 ) (= (cdr (assoc 71 ellst)) 1 )) (progn (entdel ename) (entmake (setq ellst (vl-remove-if '(lambda(x) (or (= (car x) -1) (= (car x) 70) (= (car x) 71) (= (car x) 44) (= (car x) 45) ) ) ellst ) ) ) (setq ename (entlast)) ) ) (vl-cmdf "explode" ename) (if flag (vla-put-Explodable blkobj :vlax-false)) (princ) )
|
解锁是对单个图块的操作,3~5 行判断选择的图元是否为图块,直至选择到图块为止;6~13 行找到该图块块定义的 Vlaobject 对象;14~19 行判断该图块定义中是否设定了不允许分解,如果是,暂时性将其定义修改为允许分解;20~41 行通过块插入(INSERT)的组码 70、71 (行列数)为 1 来判断该块是否为锁定的多重块插入(这里逻辑不是非常严谨,主要是考虑如果是普通块插入,组码 70 一般为 0,如果确实是有需要的行列形式的多重块,行列数不会同时为 1),若是,则删除块插入,同时以同名重建一个普通的块插入(匿名块也可以通过这种方式插入),并获取这个新建图块插入的图元名。完成这一系列工作后,42 行代码采用 explode
命令分解图块。43 行则对之前可能发生的图块定义中可分解性的修改进行恢复。至此,解锁过程完成,所谓“不能分解”的图块均被分解了。