【AutoLISP】字典(DICTIONARY)的结构、创建及操作
刘老帆子
编辑于 2023年05月03日 22:53
收录于文集
共7篇

在AutoLISP中,字典对象 (0 . "DICTIONARY&#​34;) 有专门命令,比通过图元上溯字典要方便。

字典相关命令有如下6个:

代码块
ts
自动换行
复制代码
(namedobjdict)
(dictrename)
(dictadd)
(dictremove)
(dictsearch)
(dictnext)
复制成功

一、(namedobjdict)及字典结构

(namedobjdict) 返回当前绘图文件的命名对象总字典实体名称<图元名>,该字典是绘图中所有非图形对象的根。可通过:

代码块
ts
自动换行
复制代码
(entget(namedobjdict))
复制成功

获得总字典的属性列表,一个默认的总字典属性列表如下所示:

代码块
ts
自动换行
复制代码
(entget(namedobjdict))

((-1 . <图元名: 1fcdca318c0>) (0 . "DICTIONARY") (330 . <图元名: 0>) (5 . "C") (100 . "AcDbDictionary") (280 . 0) (281 . 1) (3 . "ACAD_CIP_PREVIOUS_PRODUCT_INFO") (350 . <图元名: 1fcdca349e0>) (3 . "ACAD_COLOR") (350 . <图元名: 1fcdca31bb0>) (3 . "ACAD_DETAILVIEWSTYLE") (350 . <图元名: 1fcdca34a30>) (3 . "ACAD_GROUP") (350 . <图元名: 1fcdca318d0>) (3 . "ACAD_LAYOUT") (350 . <图元名: 1fcdca319a0>) (3 . "ACAD_MATERIAL") (350 . <图元名: 1fcdca31ba0>) (3 . "ACAD_MLEADERSTYLE") (350 . <图元名: 1fcdca33950>) (3 . "ACAD_MLINESTYLE") (350 . <图元名: 1fcdca31970>) (3 . "ACAD_PLOTSETTINGS") (350 . <图元名: 1fcdca31990>) (3 . "ACAD_PLOTSTYLENAME") (350 . <图元名: 1fcdca318e0>) (3 . "ACAD_SCALELIST") (350 . <图元名: 1fcdca338c0>) (3 . "ACAD_SECTIONVIEWSTYLE") (350 . <图元名: 1fcdca34a10>) (3 . "ACAD_TABLESTYLE") (350 . <图元名: 1fcdca31c60>) (3 . "ACAD_VISUALSTYLE") (350 . <图元名: 1fcdca31ef0>) (3 . "AcDbVariableDictionary") (350 . <图元名: 1fcdca31ae0>))
复制成功

一个字典的结构均与其类似。其中组码含义:

【0】对象名,对于字典为固定值"DICTIONARY&#​34;

【5】句柄handle

【100】子类名称,对于字典为固定值"AcDbDictionary&#​34;

【280】硬拥有者标志(hard-owner)。如果设置为1,则表示该字典的元素将被视为硬拥有。

【281】重复记录克隆标志(确定如何合并重复条目): 0 = 不适用 1 = 保留现有 2 = 使用克隆 3 = <xref> 00 <name> 4 = 00 <name> 5 = 解开名称混淆

【3】条目名称(每个条目一个)(可选),类似Python中字典的键名

【350】条目对象的软所有者ID/<图元名>(每个条目一个)(可选),类似Python中字典的键值。在DXF文件中该项为条目对象的<句柄>,而非<图元名>。

注:组码规范中,350的意思为3-50,即3属性的伴随属性50。

二、字典的创建-entmake方法

代码块
ts
自动换行
复制代码
(setq #listD (list '(0 . "DICTIONARY") 
                   '(100 . "AcDbDictionary")
                   '(280 . 0) ;非必要,默认为0
                   '(281 . 1) ;非必要,默认为1
             ) ;l
) ;s
(setq #enTest (entmakex #listD))
复制成功

可以创建空的字典。所创建的字典属性列表如下:

代码块
ts
自动换行
复制代码
((-1 . <图元名: 1fcdca34cb0>) (0 . "DICTIONARY") (330 . <图元名: 0>) (5 . "2BB") (100 . "AcDbDictionary") (280 . 0) (281 . 1))
复制成功

从组码330项可见,该字典的上级直接属于绘图,若想将该字典从属于某字典(如总字典),可以使用 (dictadd) 操作。

二、(dictadd) (dictremove)

任何非图形对象都可以作为条目添加进字典,字典对象也可以。

续前,将先前创建的字典作为条目加入到总字典中:

代码块
ts
自动换行
复制代码
(dictadd (namedobjdict) "TestDict1" #enTest)
复制成功

该命令的参数依次为:要加入条目的字典<图元名>;条目名<字符串>;条目值(对象)<图元名>

操作后总字典变为:

代码块
ts
自动换行
复制代码
((-1 . <图元名: 1fcdca318c0>) (0 . "DICTIONARY") (330 . <图元名: 0>) (5 . "C") (100 . "AcDbDictionary") (280 . 0) (281 . 1) (3 . "ACAD_CIP_PREVIOUS_PRODUCT_INFO") (350 . <图元名: 1fcdca349e0>) (3 . "ACAD_COLOR") (350 . <图元名: 1fcdca31bb0>) (3 . "ACAD_DETAILVIEWSTYLE") (350 . <图元名: 1fcdca34a30>) (3 . "ACAD_GROUP") (350 . <图元名: 1fcdca318d0>) (3 . "ACAD_LAYOUT") (350 . <图元名: 1fcdca319a0>) (3 . "ACAD_MATERIAL") (350 . <图元名: 1fcdca31ba0>) (3 . "ACAD_MLEADERSTYLE") (350 . <图元名: 1fcdca33950>) (3 . "ACAD_MLINESTYLE") (350 . <图元名: 1fcdca31970>) (3 . "ACAD_PLOTSETTINGS") (350 . <图元名: 1fcdca31990>) (3 . "ACAD_PLOTSTYLENAME") (350 . <图元名: 1fcdca318e0>) (3 . "ACAD_SCALELIST") (350 . <图元名: 1fcdca338c0>) (3 . "ACAD_SECTIONVIEWSTYLE") (350 . <图元名: 1fcdca34a10>) (3 . "ACAD_TABLESTYLE") (350 . <图元名: 1fcdca31c60>) (3 . "ACAD_VISUALSTYLE") (350 . <图元名: 1fcdca31ef0>) (3 . "AcDbVariableDictionary") (350 . <图元名: 1fcdca31ae0>) (3 . "TestDict1") (350 . <图元名: 1fcdca34cb0>))
复制成功

可见其中已经存在我们添加的新条目。同时#enTest的属性自动变为:

代码块
ts
自动换行
复制代码
((-1 . <图元名: 1fcdca34cb0>) (0 . "DICTIONARY") (5 . "2BB") (102 . "{ACAD_REACTORS") (330 . <图元名: 1fcdca318c0>) (102 . "}") (330 . <图元名: 1fcdca318c0>) (100 . "AcDbDictionary") (280 . 0) (281 . 1))
复制成功

可见,条目对象的属性中自动添加了反应器组码120和330,且反应器指向的图元名<图元名: 1fcdca318c0>正是总字典的图元名,从而建立了从属关系。

注:是否可以通过在entmake时手工添加反应器实现从属关系建立?例如:

代码块
ts
自动换行
复制代码
(setq #listD (list '(0 . "DICTIONARY") 
                    '(102 . "{ACAD_REACTORS") 
                    (cons 330 (namedobjdict)) 
                    '(102 . "}") 
                    (cons 330 (namedobjdict))
                   '(100 . "AcDbDictionary")
                   ;'(280 . 0)
                   ;'(281 . 1)
             ) ;l
) ;s
(setq #enTest (entmakex #listD))
(entget #enTest)
复制成功

实际上是,这样确实会创建对象时,在对象的属性中成功指定上级,但是在上级的字典中并不会自动补充该对象条目,还是需要对上级字典 (dictadd),因此是多此一举的。

从字典中删除条目的方法:

代码块
ts
自动换行
复制代码
(dictremove (namedobjdict) "TestDict1")
复制成功

其中,参数依次为:从哪个字典删除<图元名>,删除哪条<字符串>,返回值为所删除对象的<图元名>。

删除后,被删除对象的属性中同步自动删除反应器组码。

三、(dictsearch) (dictrename) (dictnext)

(dictsearch) 用于从字典<图元名>中搜索条目<字符串>,搜到后,会返回条目对象的属性列表,非常方便。

代码块
ts
自动换行
复制代码
(dictsearch (namedobjdict) "TestDict1")

((-1 . <图元名: 1fcdca34cb0>) (0 . "DICTIONARY") (5 . "2BB") (102 . "{ACAD_REACTORS") (330 . <图元名: 1fcdca318c0>) (102 . "}") (330 . <图元名: 1fcdca318c0>) (100 . "AcDbDictionary") (280 . 0) (281 . 1))
复制成功

(dictrename) 修改字典<图元名>中条目名字<字符串>至新名字<字符串>,返回值为新名字:

代码块
JavaScript
自动换行
复制代码
(dictrename (namedobjdict) "TestDict1" "TestDictNewName")

"TestDictNewName"

(dictsearch (namedobjdict) "TestDict1")

nil
复制成功

修改后,搜索旧名字返回值已经为nil,表明搜索不到了。

(dictnext)在字典<图元名>中依次搜索条目(从头开始),并返回条目对象的属性列表。

代码块
JavaScript
自动换行
复制代码
(dictnext ename [rewind])
复制成功

若[rewind]不为nil(如为T或者123),则搜索指针返回开头,从头开始:

代码块
JavaScript
自动换行
复制代码
(dictnext (namedobjdict))
((-1 . <图元名: 1fcdca349e0>) (0 . "XRECORD") (5 . "216") (102 . "{ACAD_REACTORS") (330 . <图元名: 1fcdca318c0>) (102 . "}") (330 . <图元名: 1fcdca318c0>) (100 . "AcDbXrecord") (280 . 1) (300 . "ACD") (300 . "2024") (300 . ""))
(dictnext (namedobjdict))
((-1 . <图元名: 1fcdca31bb0>) (0 . "DICTIONARY") (5 . "6B") (102 . "{ACAD_REACTORS") (330 . <图元名: 1fcdca318c0>) (102 . "}") (330 . <图元名: 1fcdca318c0>) (100 . "AcDbDictionary") (280 . 0) (281 . 1))
(dictnext (namedobjdict))
((-1 . <图元名: 1fcdca34a30>) (0 . "DICTIONARY") (5 . "21B") (102 . "{ACAD_REACTORS") (330 . <图元名: 1fcdca318c0>) (102 . "}") (330 . <图元名: 1fcdca318c0>) (100 . "AcDbDictionary") (280 . 0) (281 . 1) (3 . "Metric50") (350 . <图元名: 1fcdca34a40>))
(dictnext (namedobjdict) 0)
((-1 . <图元名: 1fcdca349e0>) (0 . "XRECORD") (5 . "216") (102 . "{ACAD_REACTORS") (330 . <图元名: 1fcdca318c0>) (102 . "}") (330 . <图元名: 1fcdca318c0>) (100 . "AcDbXrecord") (280 . 1) (300 . "ACD") (300 . "2024") (300 . ""))
复制成功


欢迎留言并发表您的见解!