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") # 另存为
内存模型与可编辑性
DmfFile 在 load() 时把完整 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*、int、bool、str等裸类型 - 封装层:C++ 对象 ↔ numpy / Pydantic 模型转换
- 应用层:纯 Python 生态 API,禁止暴露任何
Dm*类型