TIN 三角网 3D 可视化
dimine_python_sdk.lib.visualization 提供基于 PyVista 的 TIN 三角网 3D 渲染功能,支持多角度视图和灵活的图片输出。
注意:此模块为纯 Python 实现,不依赖
DmPyBindInterface.pyd,无需运行 Dimine 桌面客户端即可使用。
安装
PyVista 为可选依赖,需手动安装:
# pip
pip install dimine-python-sdk[vis]
# uv
uv add dimine-python-sdk --extra vis
# 或直接安装 pyvista
pip install pyvista
快速开始
基础渲染
import numpy as np
from dimine_python_sdk.models.types import TINGeometry
from dimine_python_sdk.lib.visualization import render_tin, CameraAngle, TinRenderConfig
# 创建一个简单的 TIN 网格
tin = TINGeometry(
faces=np.array([[0, 1, 2], [0, 2, 3]], dtype=np.int32),
points=np.array(
[[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [0.0, 1.0, 0.5]],
dtype=np.float32,
),
)
# 配置渲染参数
config = TinRenderConfig(
angles=[
CameraAngle(name="top", preset="top"),
CameraAngle(name="isometric", preset="isometric"),
],
mode="combined",
)
# 输出到文件
result = render_tin(tin, config, output_path="tin_output.png")
print(result["output_files"])
# ['tin_output.png']
交互式显示
不指定 output_path 时,返回 Plotter 对象用于交互浏览:
result = render_tin(tin, config)
for plotter in result["plotters"]:
plotter.show()
核心 API
render_tin()
def render_tin(
geometries: Union[TINGeometry, List[TINGeometry]],
config: TinRenderConfig,
output_path: Optional[str] = None,
output_prefix: str = "tin_render",
image_format: str = "png",
) -> Dict[str, Any]:
参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
geometries |
TINGeometry \| List[TINGeometry] |
— | 待渲染的三角网几何体 |
config |
TinRenderConfig |
— | 渲染配置(角度、模式、样式等) |
output_path |
str \| None |
None |
输出路径。separate 模式为目录,combined 模式为文件。None 时返回 Plotter 对象 |
output_prefix |
str |
"tin_render" |
输出文件前缀(仅 separate 模式) |
image_format |
str |
"png" |
图像格式(png、jpg、svg 等) |
返回值 Dict[str, Any]:
| 键 | 类型 | 说明 |
|---|---|---|
mode |
str |
渲染模式 "separate" 或 "combined" |
angles |
List[str] |
使用的角度名称列表 |
output_files |
List[str] \| None |
输出文件路径列表(output_path 为 None 时为 None) |
plotters |
List[Plotter] \| None |
Plotter 对象列表(仅 output_path=None 时非空) |
config |
TinRenderConfig |
本次使用的配置对象 |
配置模型
CameraAngle — 相机角度
每个角度通过预设名称或自定义坐标定义(二者择一):
from dimine_python_sdk.lib.visualization import CameraAngle
# 预设模式
CameraAngle(name="top", preset="top")
# 自定义模式: (camera_position, focal_point, view_up)
CameraAngle(
name="custom_view",
custom=((100.0, 50.0, 80.0), (0.0, 0.0, 0.0), (0.0, 0.0, 1.0)),
)
预设角度(采矿行业惯例,Z 轴朝上):
| 预设值 | 方向 | 用途 |
|---|---|---|
top |
从 +Z 向下看 | 俯视图 / 平面图 |
bottom |
从 -Z 向上看 | 仰视图 |
north |
从 +Y 向 -Y 看 | 北视图 |
south |
从 -Y 向 +Y 看 | 南视图 |
east |
从 +X 向 -X 看 | 东视图 |
west |
从 -X 向 +X 看 | 西视图 |
isometric |
45° 3D 等轴测 | 等轴测视图 |
RenderOptions — 渲染选项
from dimine_python_sdk.lib.visualization import RenderOptions
RenderOptions(
width=1024, # 图像宽度(像素)
height=768, # 图像高度(像素)
dpi=96, # 分辨率
background_color="white", # 背景颜色
show_edges=True, # 显示网格边线
edge_color="black", # 边线颜色
edge_width=1.0, # 边线宽度
mesh_opacity=1.0, # 网格透明度 (0.0~1.0)
show_axes=False, # 显示坐标轴
show_grid=False, # 显示网格平面
lighting=True, # 启用光照
smooth_shading=True, # 启用平滑着色
)
TinSubplotLayout — 子图布局
用于 combined 模式下的子图排列:
from dimine_python_sdk.lib.visualization import TinSubplotLayout
TinSubplotLayout(
rows=1, # 子图行数
cols=4, # 子图列数
title="多角度对比", # 组合视图总标题
spacing=0.1, # 子图间距比例
border=False, # 是否显示子图边框
)
TinRenderConfig — 总配置
from dimine_python_sdk.lib.visualization import TinRenderConfig, CameraAngle
config = TinRenderConfig(
angles=[
CameraAngle(name="俯视图", preset="top"),
CameraAngle(name="北视图", preset="north"),
CameraAngle(name="东视图", preset="east"),
CameraAngle(name="等轴测", preset="isometric"),
],
mode="combined", # "separate" | "combined"
render_options=RenderOptions(width=1920, height=1080),
layout=TinSubplotLayout(rows=1, cols=4, title="TIN 多角度视图"),
colors=["#4C72B0"], # 网格颜色(与 geometries 一一对应)
labels=["地形曲面"], # 图例标签
show_legend=True, # 显示图例
)
两种渲染模式
Separate 模式(mode="separate")
每个角度独立渲染为一个 Plotter 或图片文件:
config = TinRenderConfig(
angles=[
CameraAngle(name="top", preset="top"),
CameraAngle(name="north", preset="north"),
CameraAngle(name="east", preset="east"),
],
mode="separate",
)
# 保存到目录,每个角度一个文件
result = render_tin(
tin, config,
output_path="./renders/",
output_prefix="terrain",
)
# 生成: ./renders/terrain_top.png
# ./renders/terrain_north.png
# ./renders/terrain_east.png
Combined 模式(mode="combined")
所有角度合成在一张图中:
config = TinRenderConfig(
angles=[
CameraAngle(name="top", preset="top"),
CameraAngle(name="north", preset="north"),
CameraAngle(name="east", preset="east"),
CameraAngle(name="isometric", preset="isometric"),
],
mode="combined",
layout=TinSubplotLayout(rows=2, cols=2, title="四视图对比"),
)
result = render_tin(tin, config, output_path="four_views.png")
不指定 layout 时,自动生成 1 行 N 列布局。
多几何体叠加
传入多个 TINGeometry,它们会叠加渲染在同一视图中:
tin1 = TINGeometry(faces=faces1, points=points1) # 地形
tin2 = TINGeometry(faces=faces2, points=points2) # 矿体
config = TinRenderConfig(
angles=[CameraAngle(name="iso", preset="isometric")],
mode="separate",
colors=["#4C72B0", "#DD8452"], # 地形蓝色,矿体橙色
labels=["地形", "矿体"],
show_legend=True,
)
result = render_tin([tin1, tin2], config, output_path="combined.png")
异常处理
from dimine_python_sdk.lib.visualization import (
VisualizationError,
MissingPyVistaError,
TINRenderError,
InvalidTINDataError,
LayoutError,
)
try:
result = render_tin(tin, config, output_path="output.png")
except MissingPyVistaError:
print("请先安装 PyVista: pip install pyvista")
except InvalidTINDataError as e:
print(f"TIN 数据无效: {e}")
except LayoutError as e:
print(f"子图布局错误: {e}")
except TINRenderError as e:
print(f"渲染失败: {e}")
异常层次:
VisualizationError(RuntimeError)
├── MissingPyVistaError # PyVista 未安装
├── TINRenderError # 渲染过程中出错
│ └── InvalidTINDataError # 输入数据无效(空数据、形状错误、索引越界)
└── LayoutError # 子图布局配置错误
完整示例
import numpy as np
from dimine_python_sdk.models.types import TINGeometry
from dimine_python_sdk.lib.visualization import (
render_tin,
CameraAngle,
TinRenderConfig,
RenderOptions,
TinSubplotLayout,
)
# 构建一个丘陵地形 TIN
np.random.seed(42)
n = 50
x = np.random.uniform(0, 100, n)
y = np.random.uniform(0, 100, n)
z = 10 * np.sin(x / 10) * np.cos(y / 10) + np.random.normal(0, 1, n)
points = np.column_stack([x, y, z]).astype(np.float32)
# 使用 Delaunay 三角剖分生成面
from scipy.spatial import Delaunay
tri = Delaunay(points[:, :2])
faces = tri.simplices.astype(np.int32)
tin = TINGeometry(faces=faces, points=points)
# 配置四视图
config = TinRenderConfig(
angles=[
CameraAngle(name="俯视图", preset="top"),
CameraAngle(name="北视图", preset="north"),
CameraAngle(name="东视图", preset="east"),
CameraAngle(name="等轴测", preset="isometric"),
],
mode="combined",
render_options=RenderOptions(
width=1920,
height=1080,
background_color="#F5F5F5",
show_edges=True,
edge_width=0.5,
mesh_opacity=0.9,
smooth_shading=True,
),
layout=TinSubplotLayout(rows=2, cols=2, title="地形 TIN 四视图"),
colors=["#6BAED6"],
labels=["地形曲面"],
show_legend=False,
)
result = render_tin(tin, config, output_path="terrain_views.png")
print(f"输出文件: {result['output_files']}")