APP下载

AutoCAD DXF文件格式与二次开发

2017-05-26刘胜华徐卫兵

科技资讯 2017年10期

刘胜华++徐卫兵

摘 要:DXF格式文件是传统图形开发中最常用的绘图交换文件,具有开放的数据结构。针对内业数据处理中常遇到的从图上快速提取点、线坐标、高程等属性数据的问题,通过DXF格式文件的编程操作,是高效解决问题的一种方法。文章简要介绍了DXF格式交换文件的结构,详细分析了实体段(ENTITIES)组码与组值的含义,用VB6.0给出了一个通用的DXF文件读写的编程方案。

关键词:AutoCAD DXF格式 组码 组值 DXF文件读写

中图分类号:TP31 文献标识码:A 文章编号:1672-3791(2017)04(a)-0015-03

DXF(Drawing Exchange Format绘图交换文件)是Autodesk公司开发的用于AutoCAD与其它软件之间进行CAD数据交换的文件格式,是AutoCAD图形文件中所包含的全部信息的标记数据的一种表示方法。DXF是一种开放的矢量数据格式,可以分为两类:ASCII格式和二进制格式;ASCII具有可读性好,但占有空间较大;二进制格式占有空间小、读取速度快。由于Autocad现在是最流行的cad系统,DXF也被广泛使用,成为事实上的标准。绝大多数CAD系统都能读入或输出DXF文件。

1 DXF文件结构

通过DxfOut命令输出DXF文件时,使用“DXF选项”可控制DXF文件的格式是ASCII格式还是BINARY格式,ASCII格式DXF文件是最常用的,具有可读性好,易于编程开发的特点,文中“DXF文件”表示ASCII DXF文件。

DXF文件的结构虽看来繁杂,本质上是有配对的组码(group code)和组值(group vaule)依次排列组织成段。在DXF文件中,每个组码和值都各占一行。

完整的DXF文件由七个段(SECTION)组成。每个段由一行组码0及一行字符串SECTION开始,紧接着是组码2及一行表示段名称的字符串(例如HADER)。段的结束由一行组码0及一行表示该段结束的字符串ENDSEC。这些段中的内容由对象或图元组成,而这些对象或图元由标志它们属性的组码和组值组成。整个文件以一行组码0及一行EOF结束。DXF文件完整的结构如下:

(1)标题段(HEADER):记录AutoCAD系统的所有标题变量的当前值或当前状态。每个参数都包含一个变量名称及其关联的值。

(2)类段(CLASSES):包括应用程序定义的类的信息,这些实例将显示在BLOCKS、ENTITIES以及OBJECTS段的数据中,类定义在类的层次结构中是固定不变的。

(3)表段(TABLES):包含以下符号表的定义,每个表又包含可变数目的表项。

APPID(应用程序标识表)

BLOCK_RECORD(块参照表)

DIMSTYLE(标注样式表)

LAYER(图层表)

LTYPE(线型表)

STYLE(文字样式表)

UCS(用户坐标系表)

VIEW(视图表)

VPORT(视口配置表)

(4)块段(BLOCK):记录了所用块的块名,当前图层层名、块的种类、塊的插入基点及组成该块的所有成员。块的种类分为图形块、带有属性的块和无名块3种。

(5)实体段(ENTITIES):记录了每个实体的名称、坐标、所在图层及其名字、线型、颜色等。

(6)物体段(OBJECTS):记录非图形对象的数据,供 AutoLISP 以及ObjectARX应用程序所使用。

(7)文件结束段(EOF of FILE)DXF文件的结束标志。

2 DXF文件组码与组值

一个DXF文件由若干个组构成,每个组占两行:第一行为组的代码;第二行为组值。组代码相当于数据类型的代码,它由CAD图形系统所规定,而组值为具体的数值,二者结合起来表示一个数据的含义和值。例如:代码10代表一个点的X坐标,占一行;而紧随的第二行3456234.23则表示该点X坐标的具体数值。

(1)组代码和组值的类型组代码为一个非负的不超过三位的整数,而组值由组代码的类型决定。例如:

代码0~9组值类型为字符型。

代码10~59组值类型为实型。

代码60~79组值类型为整型。

(2)组代码的含义每个组代码均有规定的含义,有些代码含义是固定的,而有些组代码则因应用场合不同而有多个含义,应具体分析。现将他们的含义举例介绍如下。

0:表示一个事物的开始,如一个块、表、图层、实体等。

1:字符型数据的值,如TEXT的字符串、文件名、属性值等。

2:一个事物的名字,如段、表、块、线型、视图等的名字。

3~5:字符型数据的值,如文件名、线型说明等。

6:线型名(固定类型)。

8:图层名(固定类型)。

实体的坐标与相应的组代码10~18、20~28、30~38的用法应根据实体所用到点的数量,按组代码个位的0、1、2、……的顺序使用。例如:LINE的起点组代码为10、20、30,而11、21、31为其终点。其他类似。

3 用VB6.0读写DXF

DXF文件的结构相当复杂,完整读取DXF文件也是一项异常繁琐的工程。在实际应用中,为了提取图形的实体信息(如点的坐标、高程),可以省略DXF文件中的许多段,只要获取ENTITIES段中对应的图元信息,进行点、线、文字等实体坐标的提取。

4 DXF TO DAT程序实例

下面是以VB6.0为开发平台,编写的读DXF文件输出DAT文件的程序实例。

Dim A As String, B As String, i As Double, kff As Boolean '定义变量

DatName = Text2 'DAT文件

DxfName = Text1 'DXF文件

Szfw = Val(Text4.Text) '取值范围

If Val(Text5.Text) = 0 Then

Xsw = "0"

Else

For J = 1 To Val(Text5.Text)

Xsw = Xsw & "0"

Next J

End If '小数位

If InStr(Text3.Text, "默认") Then LLay = "" Else LLay = UCase(Trim(Text3.Text))

'图层控制

If DatName = "" Or DxfName = "" Then

MsgBox "对不起,你必须要先选择文件后才能运行" & Chr(13) & Chr(10) & "请重新选择文件"

Else

On Error Resume Next

Open Text1.Text For Input As #1

Open Text2.Text For Output As #2

If Err.Number = 53 Then GoTo R053

If Err.Number = 76 Then GoTo R076

FLG1 = 0: FLG2 = 0: FLG3 = 0

Do While Not (EOF(1))

If FLG1 = 0 And FLG2 = 0 And FLG3 = 0 Then

Line Input #1, A

Line Input #1, B

If Val(A) = 2 And UCase(B) = LBolck Then

FLG1 = 1: FLG2 = 0: FLG3 = 0

Else

FLG1 = 0: FLG2 = 0: FLG3 = 0

End If

End If

'-----------------------------------BLOCK

If FLG1 = 1 And FLG2 = 1 And FLG3 = 0 Then

Line Input #1, A

Line Input #1, B

If LLay = "" Then KKM = InStr(UCase(B), LLay) Else KKM = (UCase(B) = LLay)

If Val(A) = 8 And KKM And InStr(UCase(B), "ENDSEC") = 0 Then

FF = FF + 1: LA(FF) = B: FLG1 = 1: FLG2 = 1: FLG3 = 1

ElseIf Val(A) = 8 And KKM = 0 And InStr(UCase(B), "ENDSEC") = 0 Then

FLG1 = 1: FLG2 = 0: FLG3 = 0

Else

FLG1 = 1: FLG2 = 1: FLG3 = 0

End If

End If

'------------------------------------Layer

If FLG1 = 1 And FLG2 = 1 And FLG3 = 1 Then

Line Input #1, A

Line Input #1, B

If Val(A) = 10 And Val(B) > Szfw Or Val(A) = 11 And Val(B) > Szfw Or Val(A) = 12 And Val(B) > Szfw Or Val(A) = 13 And Val(B) > Szfw Then

i = i + 1: Y(i) = Val(B): PPK(i) = PD(LIN) & LIN & "."

ElseIf Val(A) = 20 And Val(B) > Szfw Or Val(A) = 21 And Val(B) > Szfw Or Val(A) = 22 And Val(B) > Szfw Or Val(A) = 23 And Val(B) > Szfw Then

X(i) = Val(B)

ElseIf A = GcDm Or Val(A) = 30 Or Val(A) = 31 Or Val(A) = 32 Or Val(A) = 33 Then

HH(i) = Val(B)

ElseIf Val(A) = 0 And InStr(UCase(B), LFlg) And InStr(UCase(B), "ENDSEC") = 0 Then

LIN = LIN + 1: PD(LIN) = B: FLG1 = 1: FLG2 = 1: FLG3 = 0

ElseIf Val(A) = 0 And InStr(UCase(B), LFlg) = 0 And InStr(UCase(B), "ENDSEC") = 0 Then

FLG1 = 1: FLG2 = 0: FLG3 = 0

ElseIf Val(A) = 0 And InStr(UCase(B), "ENDSEC") Then

Exit Do

Else

FLG1 = 1: FLG2 = 1: FLG3 = 1

End If

End If

Loop

Close #1

'------------------------------------讀XYH

5 运行

输出dxf文件后,运行程序界面如下:

输入图层名称:控制是读出单一图层(如HI)的实体对象还是全部图层的实体对象(默认值ALL)。

读取实体类型:控制是读出单一的点(POINT)对象、线(LINE)对象……还是全部(ALL)对象的坐标。

6 结语

在现实测量中,从图上取点、线的坐标是内业成图中经常遇到的事情。目前的成图软件大多是基于AutoCAD为平台开发的,而AutoDXF文件作为通用的数据交换格式,编程可以大大提高数据转换的效率,希望该例对工作中遇到的类似事情有所借鉴作用。

参考文献

[1] 罗卓书.AutoCAD2000中文版基础培训教程[M].北京:电子工业出版社,2000.

[2] 唐学忠.Visual Basic程序设计教程[M].中国电力出版社,2002.

[3] 王玉琨.CAD二次开发技术及其工程应用[M].清华大学出版社,2008.