本节介绍 ASCII DXF 文件的格式。只有自行编写程序处理 DXF 文件,或者使用由 AutoLISP® 和 ObjectARX® 应用程序获得的图元信息时,才需要使用本节中包含的信息。
DXF 文件本质上由代码及关联值对组成。代码(通常称为组码)表明其后的值的类型。使用这些组码和值对,可以将 DXF 文件组织到由记录组成的区域中,这些记录由组码和数据项目组成。在 DXF 文件中,每个组码和值都各占一行。
每段都以一个后跟字符串 SECTION 的组码 0 开始,其后是组码 2 和表示该段名称的字符串(例如,HEADER)。每段都由定义其元素的组码和值组成。每段都以一个后跟字符串 ENDSEC 的组码 0 结束。
从小图形中生成 DXF 文件,打印出来并在阅读本文时参考,可能会有助于用户理解本文的内容。
DXF 文件完整的结构如下:
APPID(应用程序标识表)
BLOCK_RECORD(块参照表)
DIMSTYLE(标注样式表)
LAYER(图层表)
LTYPE(线型表)
STYLE(文字样式表)
UCS(用户坐标系表)
VIEW(视图表)
VPORT(视口配置表)
如果使用 SAVE 或 SAVEAS 命令的“选择对象”选项,那么所得到的 DXF 文件的 ENTITIES 区域将只包含选择的图元。
组码和关联值定义对象或图元的特定方面。紧接着组码的一行是关联值。该值可以是字符串、整数或浮点值,例如点的 X 坐标。组中第二行后面的行(如果存在)由组定义和与组关联的数据确定。
特殊组码用作文件分隔符,例如用于表示段和表的开始和结束,以及文件本身结束的标记。
图元、对象、类、表和表条目以及文件分隔符通过 0 组码(其后是用于描述该组的名称)引入。
DXF 文件字符串的最大长度是 256 个字符。如果 AutoCAD 图形中包含的字符串超出了此数字,则在执行 SAVE、SAVEAS 和 WBLOCK 时将截断那些字符串。如果 DXF 文件包含的字符串超出了此长度,OPEN 和 INSERT 命令将失败。
SAVEAS 处理文字字符串中的 ASCII 控制字符的方法是在相应的字母前面加一个插入符号 (^)。例如,将 ASCII 控制字符 G(BEL,十进制代码 7)写为 ^G。如果文字本身包含插入符,插入符将扩展为插入符和空格 (^ )。OPEN 和 INSERT 用于执行补充转换。
应用程序可以使用 AutoLISP getvar 函数检索这些变量的值。
以下是 DXF™ 文件的 HEADER 区域的样例:
0 SECTION 2 HEADER |
HEADER 段的开始 |
9 $<变量> <组码> <值> |
为每个标题变量重复一次 |
0 ENDSEC |
HEADER 段的结束 |
以下是 DXF 文件 CLASSES 段的样例:
0 SECTION 2 CLASSES |
CLASSES 段的开始 |
0 CLASS 1 <类 dxf 记录> 2 <类名> 3 <应用程序名> 90 <标志> 280 <标志> 281 <标志> |
为每个条目重复一次 |
0 ENDSEC |
CLASSES 段的结束 |
以下是 DXF 文件 TABLES 段的样例。
0 SECTION 2 TABLES |
TABLES 段的开始 |
0 TABLE 2 <表类型> 5 <句柄> 100 AcDbSymbolTable 70 <最大条目数量> |
通用表组码;为每个条目重复一次 |
0 <表类型> 5 <句柄> 100 AcDbSymbolTableRecord . . <数据> . |
表条目数据;为每个表记录重复一次 |
0 ENDTAB |
表的结束 |
0 ENDSEC |
TABLES 段的结束 |
此 DXF 序列表示三个完整的对象:符号表和两个条目。
0 |
|
TABLE |
表示符号表条目 |
2 |
|
STYLE |
文字样式符号表条目。这是代码 0 完全定义类型这一规则的例外情况 |
5 |
|
1C |
STYLE 表句柄;与图元和其他对象的句柄相同 |
70 |
|
3 |
可跟随的 STYLE 表记录的最大数目(R13 版本之前的字段) |
1001 |
|
APP_X |
APP_X 已在符号表中放置了扩展数据 |
1040 |
|
42.0 |
只是一个浮点数 |
0 |
|
STYLE |
STYLE 符号表中第一个元素的开始 |
5 |
|
3A |
第一个条目的句柄(此处,DIMSTYLE 条目将为 105) |
2 |
|
ENTRY_1 |
第一个条目的文字名称 |
70 |
|
64 |
标准标志值 |
40 |
|
.4 |
文字高度 |
41 |
|
1.0 |
宽度比例因子 |
50 |
|
0.0 |
倾斜角度 |
71 |
|
0 |
文字生成标志 |
42 |
|
0.4 |
上次使用的高度 |
3 |
|
BUFONTS.TXT |
主要字体文件名 |
0 |
|
STYLE |
第二个条目开始。第一个条目中无扩展数据或永久反应器 |
5 |
|
C2 |
第二个条目的句柄 |
2 |
|
ENTRY_2 |
第二个条目的文字名称 |
... |
|
... |
组码 3 下的其他字段 |
3 |
|
BUFONTS.TXT |
主要字体文件名和最后一个对象类型 - 特定的组 |
102 |
|
{ACAD_REACTORS |
此条目有两个永久反应器 |
330 |
|
3C2 |
第一个反应器对象的软 ID |
330 |
|
41B |
第一个反应器对象的软 ID |
102 |
|
} |
表示反应器集的结束 |
1001 |
|
APP_1 |
此条目上附着的扩展数据 |
1070 |
|
45 |
|
1001 |
|
APP_2 |
|
1004 |
|
18A5B3EF2C199A |
|
0 |
|
UCS |
UCS 表的开始(以及上一个记录和表的结束) |
以下是 DXF 文件 BLOCKS 段的样例:
0 SECTION 2 BLOCKS |
BLOCKS 段的开始 |
0 BLOCK 5 <句柄> 100 AcDbEntity 8 <图层> 100 AcDbBlockBegin 2 <块名> 70 <标志> 10 20 30 3 <块名> 1 <外部参照路径> |
每个块条目的开始(块图元定义) |
0 <图元类型> . . <数据> . |
块中的每个图元定义有一个条目 |
0 ENDBLK 5 <句柄> 100 AcDbBlockEnd |
每个块条目的结束(endblk 图元定义) |
0 ENDSEC |
BLOCKS 段的结束 |
以下是 DXF 文件 ENTITIES 段的样例:
0 SECTION 2 ENTITIES |
ENTITIES 段的开始 |
0 <图元类型> 5 <句柄> 330 <指向所有者的指针> 100 AcDbEntity 8 <图层> 100 AcDb<类名> . . <数据> . |
每个图元定义一个条目 |
0 ENDSEC |
ENTITIES 段的结束 |
以下是 DXF 文件 OBJECTS 段的样例:
0 SECTION 2 OBJECTS |
OBJECTS 段的开始 |
0 DICTIONARY 5 <句柄> 100 AcDbDictionary |
命名对象词典(根词典对象)的开始 |
3 <词典名> 350 <子对象句柄> |
为每个条目重复一次 |
0 <对象类型> . . <数据> . |
对象数据组 |
0 ENDSEC |
OBJECTS 段的结束 |
通过 DXF 文件编写与 AutoCAD 通信的程序似乎比实际情况要难。使用 DXF 格式可以轻松地忽略不需要的信息,而只读取需要的信息。
以下是一个简单的 Visual Basic 6 程序样例,它读取 DXF 文件,并且从给定段的给定对象中提取特定代码和值。
' ReadDXF 从 DXF 文件中提取指定的代码/值对。
' 此函数需要四个字符串参数、一个有效的 DXF
' 文件名、一个 DXF 段名、该段中对象的
' 名称以及由逗号分隔的代码列表。
'
Function ReadDXF( _
ByVal dxfFile As String, ByVal strSection As String, _
ByVal strObject As String, ByVal strCodeList As String)
Dim tmpCode, lastObj As String
Open dxfFile For Input As #1
' 获取第一个代码/值对
codes = ReadCodes
' 遍历整个文件,直到“EOF”行
While codes(1) <> "EOF"
' 如果组码为“0”,并且值为“SECTION”,则
If codes(0) = "0" And codes(1) = "SECTION" Then
' 这必须是一个新的段,以便获取下一个
' 代码/值对。
codes = ReadCodes()
' 如果此段是要获取的段,则
If codes(1) = strSection Then
' 获取下一个代码/值对,并
codes = ReadCodes
' 遍历此段,直到“ENDSEC”
While codes(1) <> "ENDSEC"
' 在某段中,所有的“0”代码都表示
' 对象。如果找到了“0”代码,则存储
' 对象名称,供以后使用。
If codes(0) = "0" Then lastObj = codes(1)
' 如果此对象是用户所需的对象,
If lastObj = strObject Then
' 则在代码前后加上逗号
tmpCode = "," & codes(0) & ","
' 如果此代码位于代码列表中,
If InStr(strCodeList, tmpCode) Then
' 则附加返回值。
ReadDXF = ReadDXF & _
codes(0) & "=" & codes(1) & vbCrLf
End If
End If
' 读取其他代码/值对
codes = ReadCodes
Wend
End If
否则
codes = ReadCodes
End If
Wend
Close #1
End Function
' ReadCodes 从打开的文件中读取两行,并返回一个包含两个项目
' 的数组、一个组码及其组码值。只要一次读取 DXF 文件中的两行代码,
' 所有程序应该都能够顺利运行。但为了使代码
' 更可靠,应该添加一些进行错误检查和其他
' 检查的代码。
'
Function ReadCodes() As Variant
Dim codeStr, valStr As String
Line Input #1, codeStr
Line Input #1, codeStr
' 修剪代码中的前导空格和后续空格
ReadCodes = Array(Trim(codeStr), valStr)
End Function
与编写读取 DXF 文件的程序相比,编写创建 DXF 文件的程序更困难,因为必须保持图形的一致性,这样 AutoCAD 才能找到可接受的文件。AutoCAD 使您可以省略 DXF 文件中的很多内容,而仍然能够获得可用的图形。
以下 Visual Basic 6 子例程创建了表示多边形的 DXF 文件。
' WriteDXFPolygon 创建一个最小的 DXF 文件,其中只
' 包含 ENTITIES 段。此子例程需要五个参数:
' DXF 文件名、多边形的边数、最右侧
' 一条边(这条边为竖直方向)底部端点的 X 坐标和 Y 坐标
' 以及每条边的
' 长度。注意,因为这里只要求二维点,所以
' 不包含 Z 坐标(代码 30 和 31)。直线
' 置于“多边形”图层中。
'
Sub WriteDXFPolygon( _
dxfFile As String, iSides As Integer, _
dblX As Double, dblY As Double, dblLen As Double)
Dim i As Integer
Dim dblA1, dblA, dblPI, dblNX, dblNY As Double
Open dxfFile For Output As #1
Print #1, 0
Print #1, "SECTION"
Print #1, 2
Print #1, "ENTITIES"
dblPI = Atn(1) * 4
dblA1 = (2 * dblPI) / iSides
dblA = dblPI / 2
For i = 1 To iSides
Print #1, 0
Print #1, "LINE"
Print #1, 8
Print #1, "Polygon"
Print #1, 10
Print #1, dblX
Print #1, 20
Print #1, dblY
dblNX = dblLen * Cos(dblA) + dblX
dblNY = dblLen * Sin(dblA) + dblY
Print #1, 11
Print #1, dblNX
Print #1, 21
Print #1, dblNY
dblX = dblNX
dblY = dblNY
dblA = dblA + dblA1
Next i
Print #1, 0
Print #1, "ENDSEC"
Print #1, 0
Print #1, "EOF"
Close #1
End Sub
只要在需要数据的行上写入了格式正确的项目,DXFIN 就会接受该项目。(当然,字符串项目不应该包含前导空格,除非这些空格是字符串的一部分。)此 BASIC 程序利用了输入格式的灵活性,它生成的文件与 AutoCAD 生成的文件并不完全相同。
如果使用 DXFIN 进行加载时出现错误,AutoCAD 将通过一条信息报告该错误,指明错误的性质以及检测到错误之前在 DXF 文件中处理的最后一行数据。错误可能并不出现在这一行,尤其是当出现省略所需组这样的错误时更是如此。