高级 DXF 主题

本章介绍 DXF 二次开发中涉及的进阶主题,包括句柄参照、扩展数据、子类标记、对象坐标系和任意轴算法等。

句柄(组码 5)是 DXF 文件中每个对象/图元的唯一标识符,格式为最多 16 个十六进制数字的字符串。句柄在整个 DXF 文件中唯一,由 AutoCAD 自动分配。

句柄的关键特性:

  • 每次新建文件或保存文件时重新生成
  • 在 INSERT 和 XREF 操作期间进行转换
  • 用于建立对象之间的引用关系

DXF 使用不同的组码范围来表示不同类型的句柄参照:

组码范围 参照类型 说明
320-329 任意句柄 “按原样”获取,在 INSERT/XREF 操作期间不进行转换
330-339 软指针 指向其他对象,不表示所有权关系
340-349 硬指针 指向其他对象的强引用
350-359 软所有者 所有者可以删除被所有者,但不强制执行
360-369 硬所有者 所有者可以删除被所有者,强制执行
390-399 PlotStyle 句柄 用于打印样式对象
  • 指针参照(Pointer):对象 A 引用对象 B,但 A 并不拥有 B。例如,图元引用一个 LAYER,但图元不拥有该图层。
  • 所有者参照(Owner):对象 A 拥有对象 B,当 A 被删除时,B 也会被删除。例如,LAYOUT 词典拥有多个 LAYOUT 对象。

组码 1005 在扩展数据中用于存储句柄值,其特殊之处在于不进行 INSERT/XREF 转换。在扩展数据中使用句柄时,需使用 1005 组码而非 330-369 组码。

组码 100 用于存储子类数据标记(Subclass Marker),该标记指示从哪个 ObjectARX 派生类定义了后续的数据。子类标记是理解 DXF 对象继承关系的关键。

子类标记示例:

  • AcDbEntity — 所有图元的基本类
  • AcDbCircle — 圆的具体类
  • AcDbLine — 直线的具体类
  • AcDbPolyline — 多段线的具体类
  • AcDbBlockReference — 块参照

一个对象的完整继承链通过多个子类标记体现。以直线为例:

0           ; 图元开始
LINE
5
42
100
AcDbEntity  ; 通用图元数据(图层、颜色、线型等)
100
AcDbLine    ; 直线特定数据(起点、终点坐标)
10
0.0
20
0.0
11
100.0
21
100.0

从 ObjectARX 派生的每个具体类必须拥有子类标记。

扩展数据(Extended Data,简称 XDATA)允许应用程序在 DXF 对象或图元中存储自定义数据。所有扩展数据都以组码 -3 为标记。

-3           ; 扩展数据开始标记(固定)
1001
APP_NAME     ; 注册的应用程序名
1000
...          ; 扩展数据内容
组码 说明
1000 ASCII 字符串(最多 255 字节)
1001 注册的应用程序名(最多 31 字节)
1002 控制字符串(“{” 开始, “}” 结束)
1003 图层名
1004 二进制数据块(最多 127 字节)
1005 图元句柄
1010 三维点
1011 三维世界空间位置
1012 三维世界空间位移
1013 三维空间方向
1040 双精度浮点值
1041 距离值
1042 缩放比例
1070 16 位有符号整数
1071 32 位有符号长整数

XDATA 使用 1002 组码来组织数据层次:

-3
1001
MY_APP         ; 应用程序名
1002
{              ; 开始一个列表
1000
Item 1
1000
Item 2
1002
{              ; 嵌套列表
1040
1.5
1040
2.5
1002
}              ; 结束嵌套
1002
}              ; 结束列表

使用自定义 XDATA 前,应用程序名必须在 APPID 符号表中注册。例如:

 0
 APPID
 2
 MY_APP
 70
 0

对象坐标系(Object Coordinate System,OCS)是通过拉伸方向(组码 210/220/230)和任意轴算法建立的坐标系。在 OCS 中定义点的图元,其点坐标使用该图元特有的坐标系。

使用 OCS 的图元类型:LINE、CIRCLE、ARC、TEXT 等。

不使用 OCS 的图元类型:LWPOLYLINE(使用标高+OCS)、3DFACE(使用世界坐标系)、POLYLINE(使用世界坐标系)。

拉伸方向(组码 210/220/230)默认为 (0, 0, 1),表示图元位于世界坐标系的 XY 平面。当拉伸方向为单位矢量 (0, 0, 1) 时,OCS 与 WCS 一致。

如果拉伸方向不是 (0, 0, 1),则需要使用任意轴算法将 OCS 坐标转换为 WCS 坐标。

任意轴算法(Arbitrary Axis Algorithm,AAA)用于计算 OCS 的 X 轴和 Y 轴方向。该算法是处理非平面图元的关键。

假设拉伸方向为 N(单位矢量):

1. 如果 |N| 非常接近 (0, 0, 1)(容差 1/64):
   X_axis = (1, 0, 0)
   Y_axis = (0, 1, 0)
   结束

2. 如果 |N| 非常接近 (0, 0, -1)(容差 1/64):
   X_axis = (-1, 0, 0)
   Y_axis = (0, 1, 0)
   结束

3. 否则:
   W = (0, 0, 1)  (世界坐标 Z 轴)
   X_axis = W × N   (叉积,归一化)
   Y_axis = N × X_axis  (叉积,归一化)
import math
 
def arbitrary_axis_algorithm(normal):
    """计算任意轴算法,返回 OCS 的 X 轴和 Y 轴方向"""
    x, y, z = normal
 
    # 检查是否接近 (0,0,1) 或 (0,0,-1)
    if abs(x) < 1/64 and abs(y) < 1/64 and abs(z) > 0:
        if z > 0:
            return (1, 0, 0), (0, 1, 0)
        else:
            return (-1, 0, 0), (0, 1, 0)
 
    # 计算 X 轴 = W × N
    wx, wy, wz = 0, 0, 1
    x_axis = (
        wy * z - wz * y,   # Y*Z - Z*Y
        wz * x - wx * z,   # Z*X - X*Z
        wx * y - wy * x    # X*Y - Y*X
    )
 
    # 归一化 X 轴
    length = math.sqrt(x_axis[0]**2 + x_axis[1]**2 + x_axis[2]**2)
    if length > 0:
        x_axis = (x_axis[0]/length, x_axis[1]/length, x_axis[2]/length)
 
    # 计算 Y 轴 = N × X_axis
    y_axis = (
        y * x_axis[2] - z * x_axis[1],
        z * x_axis[0] - x * x_axis[2],
        x * x_axis[1] - y * x_axis[0]
    )
 
    # 归一化 Y 轴
    length = math.sqrt(y_axis[0]**2 + y_axis[1]**2 + y_axis[2]**2)
    if length > 0:
        y_axis = (y_axis[0]/length, y_axis[1]/length, y_axis[2]/length)
 
    return x_axis, y_axis
 
 
def ocs_to_wcs(point_ocs, normal):
    """将 OCS 坐标转换为 WCS 坐标"""
    x_axis, y_axis = arbitrary_axis_algorithm(normal)
 
    # OCS point = (u, v, w)
    # WCS point = origin + u*X_axis + v*Y_axis + w*normal
    u, v, w = point_ocs
    wx = u * x_axis[0] + v * y_axis[0] + w * normal[0]
    wy = u * x_axis[1] + v * y_axis[1] + w * normal[1]
    wz = u * x_axis[2] + v * y_axis[2] + w * normal[2]
 
    return (wx, wy, wz)

扩展词典(Extension Dictionary)允许在对象上附加自定义词典。使用组码 102 后跟 {ACAD_REACTORS{ACAD_XDICTIONARY 来标识。

102
{ACAD_XDICTIONARY    ; 扩展词典开始
360
FD                  ; 硬所有者句柄(指向词典对象)
102
}                    ; 扩展词典结束

永久反应器(Persistent Reactor)使得对象之间可以建立事件响应关系。当被监控的对象发生变化时,反应器对象会自动收到通知。

102
{ACAD_REACTORS      ; 反应器链开始
330
F0                  ; 软指针句柄(指向所有者)
102
}                    ; 反应器链结束

本章介绍了 DXF 开发中的高级话题。句柄管理确保了对象间的正确引用关系;子类标记使得 DXF 能够表示复杂的类继承结构;扩展数据为应用程序提供了自定义存储能力;对象坐标系和任意轴算法则是处理三维空间中非平面图元的基础。掌握这些高级概念是开发专业 DXF 应用程序的必要条件。

该主题尚不存在

您访问的页面并不存在。如果允许,您可以使用创建该页面按钮来创建它。

  • dxf格式/09_dxf_advanced.txt
  • 最后更改: 2026/06/17 09:45
  • 张叶安