Skip to content

DMF 文件处理模块(lib.file

概述

dimine_python_sdk.lib.file 提供 DMF 文件的读取、写入和编辑功能。基于三层架构:_native(连接层)→ _adapter(封装层)→ api(应用层)。

导入方式:

from dimine_python_sdk.lib.file import DmfFile, DmfLayer, DmfEntityType, dmf_conn

核心类:DmfFile

打开文件

# 方式 1:构造时加载
dmf = DmfFile("地表.dmf")
print(dmf.info)       # 查看文件信息
print(dmf.layers)     # 获取所有图层

dmf.close()

# 方式 2:上下文管理器(推荐,自动释放)
with DmfFile("地表.dmf") as dmf:
    print(dmf.name)
    print(dmf.layer_count)
    print(dmf.layer_names)

属性

属性 类型 说明
dmf.name str 文件名(不含扩展名)
dmf.layer_count int 图层数量
dmf.layer_names List[str] 所有图层名称
dmf.layers List[DmfLayer] 所有图层(包含完整实体列表)
dmf.info dict 文件摘要(file, name, layers, total_entities, layer_names)

访问图层

支持按索引或按名称访问:

layer = dmf[0]           # 按索引
layer = dmf["地形"]       # 按名称(KeyError 如果不存在)
layer = dmf.get_layer(0)
layer = dmf.get_layer("地形")

# 检查图层是否存在
"地形" in dmf              # True/False

# 遍历所有图层
for layer in dmf:
    print(layer.name, layer.entity_count)

图层信息(DmfLayer

layer.name                       # 图层名称
layer.entity_count               # 实体数量(只读属性,与 entities 实时同步)
layer.entities                   # 实体列表:Point | Line | Shell | TextInfo
layer.id                         # 图层 ID(字符串)

# 实体类型判断
from dimine_python_sdk.models.types import Point, Line, Shell, TextInfo
for e in layer.entities:
    if isinstance(e, Point):
        print("点:", e.geometry)      # (3,) ndarray
    elif isinstance(e, Line):
        print("线:", e.geometry)      # (n,3) ndarray
    elif isinstance(e, Shell):
        print("面:", e.geometry.points, e.geometry.faces)
    elif isinstance(e, TextInfo):
        print("文本:", e.text, e.position)

保存文件

dmf.save()               # 保存到原始路径
dmf.save("output.dmf")   # 另存为

内存模型与可编辑性

DmfFileload() 时把完整 DMF 结构解析为 Python 内存模型,之后所有读取、新增图层、插入实体等操作都直接修改内存中的 DmfLayer / entities,只有在调用 save() 时才将内存模型重新序列化回 DMF 文件。

因此 DmfFile 本身就是可编辑的:

with DmfFile("input.dmf") as dmf:
    layer = dmf.add_layer("计算图层")
    layer.insert_point(np.array([1.0, 2.0, 3.0]), name="测点")
    dmf.save("output.dmf")

如需直接接触底层 C++ 对象,可使用 dimine_python_sdk.lib.file._native.create_local_database()dimine_python_sdk.lib.db.database.DmDbDatabase,但这不属于 DmfFile 的高层 API。


图层操作

添加新图层

new_layer = dmf.add_layer("新图层")
print(new_layer.name, new_layer.entity_count)  # entity_count 为只读属性

实体插入

通过 DmfFile 插入(指定图层)

import numpy as np

# 插入点(内部实现为零长度直线)
dmf.insert_point(0, np.array([1.0, 2.0, 3.0]), name="测点")

# 插入直线
dmf.insert_line(0, 
    np.array([0.0, 0.0, 0.0]), 
    np.array([10.0, 0.0, 0.0]), 
    name="线段")

# 插入多段线
dmf.insert_polyline(0,
    np.array([[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0]]),
    name="矩形")

# 插入三维面(Shell)
dmf.insert_shell(0,
    points=np.array([[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0]], dtype=np.float64),
    faces=np.array([[0, 1, 2], [0, 2, 3]], dtype=np.int32),
    name="面片")

# 插入文本
dmf.insert_text(0, np.array([5.0, 5.0, 0.0]), "标注文字", name="文本")

通过 DmfLayer 插入(图层对象直接调用)

layer = dmf["地形"]

layer.insert_point(np.array([1.0, 2.0, 3.0]), name="测点")
layer.insert_line(np.array([0, 0, 0]), np.array([10, 10, 0]), name="线段")
layer.insert_polyline(np.array([[0, 0, 0], [10, 0, 0], [10, 10, 0]]), name="多段线")
layer.insert_shell(points=..., faces=..., name="面")
layer.insert_text(np.array([0, 0, 0]), "文本", name="标注")

参数说明

方法 layer 参数 坐标参数 说明
insert_point int 或 str np.ndarray (3,) 点,内部为零长度直线
insert_line int 或 str start: (3,), end: (3,) 直线段
insert_polyline int 或 str np.ndarray (n, 3) 多段线
insert_shell int 或 str points: (n,3), faces: (m,k) 三维面片
insert_text int 或 str position: (3,), text: str 文本标注
  • layer 可以是图层索引(int)或图层名称(str
  • 所有方法均支持 name 关键字参数指定实体名称

上下文管理器

from dimine_python_sdk.lib.file import dmf_conn

with dmf_conn("地表.dmf") as dmf:
    # 使用 dmf...
    pass
# 自动 close()

异常体系

所有异常继承自 DmfError(RuntimeError)

异常类 触发场景
DmfLoadError 文件不存在或加载失败
DmfSaveError 未指定保存路径或保存失败
DmfInsertError 坐标数组维度不足 3 等插入错误
from dimine_python_sdk.lib.file._adapter import DmfError, DmfLoadError, DmfSaveError, DmfInsertError

try:
    dmf = DmfFile("不存在.dmf")
except DmfLoadError as e:
    print(f"加载失败: {e}")

实体类型枚举

from dimine_python_sdk.lib.file import DmfEntityType

# 类型码 → 类型名映射
DmfEntityType.POINT       # 0   - 点
DmfEntityType.LINE        # 1   - 直线
DmfEntityType.POLYLINE    # 2   - 多段线
DmfEntityType.SHELL       # 3   - 三维面
DmfEntityType.TEXT        # 4   - 文本
DmfEntityType.POLYGON     # 9   - 多边形
DmfEntityType.ARC         # 5   - 弧
DmfEntityType.CIRCLE      # 6   - 圆
DmfEntityType.SPLINE      # 8   - 样条曲线
DmfEntityType.ANNOTATION  # 10  - 标注
DmfEntityType.MESH        # 34  - 网格
DmfEntityType.BLOCK       # 21  - 图块

完整示例

读取并遍历 DMF 文件

from dimine_python_sdk.lib.file import DmfFile
from dimine_python_sdk.models.types import Point, Line, Shell, TextInfo

with DmfFile("剖面.dmf") as dmf:
    print(f"文件: {dmf.name}, 图层数: {dmf.layer_count}")

    for layer in dmf.layers:
        print(f"\n图层: {layer.name}, 实体数: {layer.entity_count}")
        for entity in layer.entities:
            if isinstance(entity, Point):
                print(f"  点 [{entity.feature}]: {entity.geometry}")
            elif isinstance(entity, Line):
                print(f"  线 [{entity.feature}]: {len(entity.geometry)} 个顶点")
            elif isinstance(entity, Shell):
                print(f"  面 [{entity.feature}]: {len(entity.geometry.points)} 顶点, {len(entity.geometry.faces)} 面")
            elif isinstance(entity, TextInfo):
                print(f"  文本 [{entity.feature}]: '{entity.text}' @ {entity.position}")

创建并编辑 DMF

import numpy as np
from dimine_python_sdk.lib.file import DmfFile

# 加载现有文件
with DmfFile("input.dmf") as dmf:
    # 添加新图层
    layer = dmf.add_layer("新图层")

    # 连续插入直线
    for i in range(5):
        layer.insert_line(
            np.array([float(i), 0.0, 0.0]),
            np.array([float(i), 10.0, 0.0]),
            name=f"线段-{i}",
        )

    # 保存
    dmf.save("output.dmf")

通过 DmfFile 新增(高层 API)

import numpy as np
from dimine_python_sdk.lib.file import DmfFile

# 加载现有文件,直接新增实体到指定图层
with DmfFile("input.dmf") as dmf:
    # 添加新图层
    layer = dmf.add_layer("计算图层")

    # 插入多段线
    dmf.insert_polyline("计算图层",
        points=np.array([
            [0, 0, 0], [10, 0, 0], [10, 5, 0], [5, 8, 0], [0, 5, 0]
        ]),
        name="轮廓线")

    # 保存
    dmf.save("output.dmf")

架构说明

应用层  api.py           →  DmfFile, dmf_conn (用户直接使用)
封装层  _adapter.py      →  类型转换、异常定义 (禁止 import DmPyBindInterface)
连接层  _native.py       →  唯一接触 DmPyBindInterface.pyd 的代码
  • 连接层:纯透传 C++ 调用,返回 Dm*intboolstr 等裸类型
  • 封装层:C++ 对象 ↔ numpy / Pydantic 模型转换
  • 应用层:纯 Python 生态 API,禁止暴露任何 Dm* 类型