在AutoCAD中使用INSERT命令插入一个块时,生成块参照实体,也叫INSERT实体,在ObjectARX中,对应类AcDbBlockReference。反正就这么一个东西,名儿还挺多,我家乡有句话叫“二嫚她婆婆俩名”,莫非这是三嫚儿?
之所以是浅说,是因为我对块的认识还处在初级阶段。我不用AutoCAD画图,自然也用不到块。前面也说过,我解析DWG的初衷就是为了读出相关图元。在达到我的目的之后,出于兴趣,有时间继续研究一下其他内容的读取。块在AutoCAD中的应用是十分广泛的,尤其是动态块的诞生,让块的地位又提升了一个台阶。有朋友私信我有没有解读动态块的内容,当时吧,对这方面的知识掌握不多,自然就 。。。。呵呵了。
块有2种,普通块和动态块。普通块,大家应该很熟悉,定义好块,插入到某个布局中,就成了块参照。对块参照能做的无非就是缩放旋转等常规操作,块内的图形是不能再被编辑的。动态块也是像普通快一样插入,缩放旋转的常规操作自然也是具备的,但是,它的超能力来自于,我们可以修改参照内的图形。
听起来,还是蛮简单的,但是,动态块的内容十分庞大。其实,动态块不应该当做图块来看,定义一个动态块,就是定义了一段程序,在程序的辅助下,我们才能实现复杂的修改。
按照Autodesk的说法,动态块是基于DAG的一套求解器。DAG就是有向无环图(Directed Acycle Graph),这个图是由node和edge构成的一个网络。node代表动作,edge是对象属性之间的依赖关系,并且edge是有方向的。具体的,咱就不多讲了,也讲不清楚,哈哈,知道有这么回事就行。
好了,现在该是去探究一下动态块的存储了。在解析DWG文件时,并没有所谓的动态块图元类型。我们知道,对象扩展字典是一个很强大的工具,二次开发者可以借助该字典对元对象实现无限扩展,动态块可以认为是Autodesk假装自己是第三方开发者对普通块进行扩展的极好示范。借助扩展字典,就无需对DWG格式做任何修改。据说动态块是2006版引入的功能,而2006版使用的DWG格式和2004是一样的。
闲话打住,探究之旅正式起航。
首先创建一个动态块BB1,由4跟直线组成,其中加入了点、线性2个参数,以及2个拉伸动作。
去除了不相关的部分,该块描述如下:
Object(BLOCK_HEADER/31)
handle: 0.1.F1
owner: 4.1.1
xdicobjhandle: 3.2.5BF
name: *U
entries:4
inserts:2
1), 3.2.5BB
2), 3.2.5BC
3), 3.2.5BD
4), 3.2.5BE
block:3.1.F2
endblk:3.1.F3
Object(BLOCK/4)
handle: 0.1.F2
owner: 4.0.F1
xdicobjhandle: 0.0.0
name: BB1
Object(LINE/13)
handle: 0.2.5BB
owner: 4.1.F1
start: 0.000000, 0.000000, 0.000000
end : 36.067069, 49.732573, 0.000000
------------
Object(LINE/13)
handle: 0.2.5BC
owner: 4.1.F1
start: 36.067069, 49.732573, 0.000000
end : 69.634529, 29.107227, 0.000000
------------
Object(LINE/13)
handle: 0.2.5BD
owner: 4.1.F1
start: 44.258738, 7.308900, 0.000000
end : 69.634529, 29.107227, 0.000000
------------
Object(LINE/13)
handle: 0.2.5BE
owner: 4.1.F1
start: 44.258738, 7.308900, 0.000000
end : 0.000000, 0.000000, 0.000000
然后,在模型空间插入此块,只调整了比例。可以看出,参照的块名是"BB1"。
这时,我们再到解析的数据里找句柄为669的块参照,看看它的数据,注意看它引用的块的句柄,正是我们刚定义的动态块BB1的句柄)
Object(INSERT/7)
handle: 0.2.669
owner: 0.0.0
xdicobjhandle: 0.0.0
entmode: 2 (MSPACE)
insert point: (989.208137, -530.611402)
block header: 5.1.F1
就是说,未对块参照执行动态调整时,它是直接引用原始的块定义的,并且没有扩展字典。
我们使用动态参数来调整一下,形状明显与上面的不同。
保存DWG,再解析一遍,查看669的数据。
Object(INSERT/7)
handle: 0.2.669
owner: 0.0.0
xdicobjhandle: 3.2.6BC
entmode: 2 (MSPACE)
insert point: (989.208137, -530.611402)
block header: 5.2.6B4
看到没,这时引用的块定义变成 6B4 了,而且有扩展字典。
我们再看看块 6B4 是咋个样子。
Object(BLOCK_HEADER/31)
handle: 0.2.6B4
owner: 4.1.1
xdicobjhandle: 3.2.6BB
name: *U
entries:4
inserts:1
1), 3.2.6B7
2), 3.2.6B8
3), 3.2.6B9
4), 3.2.6BA
block:3.2.6B5
endblk:3.2.6B6
Object(BLOCK/4)
handle: 0.2.6B5
owner: 4.0.6B4
xdicobjhandle: 0.0.0
name: *U25
Object(LINE/13)
handle: 0.2.6B7
owner: 4.0.6B4
start: 0.000000, 0.000000, 0.000000
end : 36.067069, 49.732573, 0.000000
------------
Object(LINE/13)
handle: 0.2.6B8
owner: 4.0.6B4
start: 36.067069, 49.732573, 0.000000
end : 53.107381, 39.262245, 0.000000
------------
Object(LINE/13)
handle: 0.2.6B9
owner: 4.0.6B4
start: 44.258738, -7.308900, 0.000000
end : 53.107381, 39.262245, 0.000000
------------
Object(LINE/13)
handle: 0.2.6BA
owner: 4.0.6B4
start: 44.258738, -7.308900, 0.000000
end : 0.000000, 0.000000, 0.000000
块 “*U25” 中的4条直线 6B7,6B8,6B9,6BA分别对应 块"BB1"中的 5BB,5BC,5BD和5BE,由于做了参数调整,他们的坐标值发生了变化。
这一切说明了什么呢?
当我们使用动态块时,99.99999%的概率是要对它修改的,所以:
插入动态块后,AutoCAD会复刻一份原始动态块的定义,生成一个匿名动态块,作为块参照的引用块。所有对块参照的修改,都反映在这个匿名块身上,而后,像使用普通块一样使用这个匿名块。
这样做,可以保证原始的动态块定义永远保持不变。当然,这是在你不人为修改它的定义的前提下。如果你参照它生成多个块参照对象后,再修改它的定义,AutoCAD总会询问你,是否更新这些块参照,还记得这个画面吗?
到这里,可以更新开头我对动态块的解读认知了。
解析INSERT图元,如果要生成图形,直接使用其参考的块包含的对象就可以了,不用分辨它是动态块还是普通块,动态调整的过程AutoCAD已经帮我们完成了。
起初,我还以为,生成动态块的参照,需要从参数,动作等自己去完成,那对大多数人来说都是不可能完成的任务,好在AutoCAD保存了块参照参考的匿名块的最后状态,而不是仅仅保存该状态的自定义参数值,不过想想也是,它不保存不是难为自己吗?是我想的复杂了。
没有时间去比对原始动态块和新的匿名块,他们的扩展字典的情况了,不影响大局,那是APP(这里是AutoCAD)要关心的事。
写这些,只是想作为这几天研究动态块的一个笔记。
好了,结束本篇,春节临近,祝春节快乐。