Skip to content

轮廓线建模

轮廓线建模模块提供基于轮廓线的三维表面重建功能,支持两轮廓线生成三角网和单轮廓线封闭为面两种模式。基于本地 C++ 扩展 DmPyBindInterface 实现高性能计算,无需连接数采软件即可使用。

1. 两轮廓线建模

根据两条轮廓线(上下对应的点集)生成三角网模型,返回 List[TINGeometry]。每个 TINGeometry 包含 points(顶点坐标,shape=(N,3))和 faces(三角面片索引,shape=(M,3))。

基础用法

import numpy as np
from dimine_python_sdk.lib.exploitation import ContourModeling, ContourAlgorithm
from dimine_python_sdk.models import TINGeometry

# 两条轮廓线点集
contour1 = [[-52.28, 13.95, 0], [-52.28, -25.46, 0], [2.37, -25.46, 0],
            [2.37, 13.95, 0], [-52.28, 13.95, 0]]
contour2 = [[-52.28, 13.95, 50], [-52.28, -25.46, 50], [2.37, -25.46, 50],
            [2.37, 13.95, 50], [-52.28, 13.95, 50]]

# 两轮廓线建模
models = ContourModeling.two_contour_modeling(
    ContourAlgorithm.MIN_PERIMETER, contour1, contour2
)

print(f"生成模型数量: {len(models)}")
for i, tin in enumerate(models):
    print(f"  模型[{i}] 顶点数: {tin.points.shape[0]}, 三角面片数: {tin.faces.shape[0]}")

支持的输入格式

two_contour_modeling(method, line1, line2)line1line2 支持三种输入格式:

import numpy as np
from dimine_python_sdk.models.types import Line
from dimine_python_sdk.lib.exploitation import ContourModeling, ContourAlgorithm

# 方式一:List[List[float]] 纯列表
result = ContourModeling.two_contour_modeling(
    ContourAlgorithm.MIN_PERIMETER,
    [[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0]],
    [[0, 0, 20], [10, 0, 20], [10, 10, 20], [0, 10, 20]],
)

# 方式二:np.ndarray
arr1 = np.array([[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0]])
arr2 = np.array([[0, 0, 20], [10, 0, 20], [10, 10, 20], [0, 10, 20]])
result = ContourModeling.two_contour_modeling(
    ContourAlgorithm.MIN_PERIMETER, arr1, arr2
)

# 方式三:Line Pydantic 模型
line1 = Line(geometry=[[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0]])
line2 = Line(geometry=[[0, 0, 20], [10, 0, 20], [10, 10, 20], [0, 10, 20]])
result = ContourModeling.two_contour_modeling(
    ContourAlgorithm.MIN_PERIMETER, line1, line2
)

2. 单轮廓线封闭为面

将一条封闭的轮廓线封闭为三角网平面。

from dimine_python_sdk.lib.exploitation import ContourModeling, ContourAlgorithm

# 封闭轮廓线
contour = [[-52.28, 13.95, 0], [-52.28, -25.46, 0], [2.37, -25.46, 0],
           [2.37, 13.95, 0], [-52.28, 13.95, 0]]

# 单轮廓线封闭为面
models = ContourModeling.single_contour_modeling(
    ContourAlgorithm.MIN_PERIMETER, contour
)

tin = models[0]
print(f"顶点数: {tin.points.shape[0]}")
print(f"三角面片数: {tin.faces.shape[0]}")

同样支持三种输入格式(List[List[float]]np.ndarrayLine)。

3. 轮廓线外推建模

将一条轮廓线沿指定方向按外推模式生成三角网模型,用于矿体尖推/楔推/平推等场景。

基础用法

from dimine_python_sdk.lib.exploitation import (
    ContourModeling,
    ContourAlgorithm,
    ExtrapolateMode,
    ExtrapolateDirection,
)

# 轮廓线点集
contour = [[-52.28, 13.95, 0], [-52.28, -25.46, 0], [2.37, -25.46, 0],
           [2.37, 13.95, 0], [-52.28, 13.95, 0]]

# 尖推(TIP)方式外推
models = ContourModeling.contour_extrapolate_modeling(
    model=ExtrapolateMode.TIP,
    point_set=contour,
    extra_dir=ExtrapolateDirection.BOTH,
    forward_distance=25.0,
    backward_distance=25.0,
)

print(f"外推生成模型数量: {len(models)}")
for i, tin in enumerate(models):
    print(f"  模型[{i}] 顶点数: {tin.points.shape[0]}, 三角面片数: {tin.faces.shape[0]}")

外推模式

通过 ExtrapolateMode 枚举指定外推方式:

枚举值 数值 说明
ExtrapolateMode.TIP 0 尖推 — 外推端尖灭为一条线
ExtrapolateMode.WEDGE 1 楔推 — 外推端形成楔形过渡
ExtrapolateMode.FLAT 2 平推 — 外推端平直封闭

外推方向

通过 ExtrapolateDirection 枚举指定外推方向:

枚举值 数值 说明
ExtrapolateDirection.BOTH 0 两端外推
ExtrapolateDirection.FRONT 1 正侧(前向)外推
ExtrapolateDirection.BACK 2 反侧(后向)外推

完整参数说明

models = ContourModeling.contour_extrapolate_modeling(
    model=ExtrapolateMode.WEDGE,    # 外推模式:TIP / WEDGE / FLAT
    point_set=contour,               # 轮廓线点集
    extra_dir=ExtrapolateDirection.BOTH,  # 外推方向
    forward_distance=25.0,           # 正侧外推距离
    backward_distance=25.0,          # 反侧外推距离
    auto_calc=True,                  # 自动计算外推法向量
    normal=None,                     # 手动指定法向量(auto_calc=False 时需提供)
    zoom=70.0,                       # 缩放比例,楔推和平推时使用,范围 (0, 100]
    pinchout_point_count=2,          # 楔推尖灭点数
    close=True,                      # 平推时是否封闭外推端
    taper_line_verical=False,        # 楔推时是否按短轴尖灭
)

三种外推模式效果对比

from dimine_python_sdk.lib.exploitation import (
    ContourModeling, ExtrapolateMode, ExtrapolateDirection,
)

contour = [[0, 0, 0], [10, 0, 0], [10, 5, 0], [0, 5, 0], [0, 0, 0]]

# 尖推 — 外推端收缩为一条线
tip_result = ContourModeling.contour_extrapolate_modeling(
    ExtrapolateMode.TIP, contour, forward_distance=15.0,
)

# 楔推 — 外推端楔形过渡
wedge_result = ContourModeling.contour_extrapolate_modeling(
    ExtrapolateMode.WEDGE, contour, forward_distance=15.0,
)

# 平推 — 外推端平直封闭
flat_result = ContourModeling.contour_extrapolate_modeling(
    ExtrapolateMode.FLAT, contour, forward_distance=15.0,
)

print(f"尖推: {len(tip_result)} 模型, 楔推: {len(wedge_result)} 模型, 平推: {len(flat_result)} 模型")

4. 多平行轮廓线建模

将多条平行的轮廓线(如多层水平断面)生成三角网模型。适用于多层矿体或地层的分层建模场景。

基础用法

from dimine_python_sdk.lib.exploitation import ContourModeling

# 三条平行轮廓线(例如三个不同高程的断面)
contour1 = [[-52.28, 13.95, 0], [-52.28, -25.46, 0], [2.37, -25.46, 0],
            [2.37, 13.95, 0], [-52.28, 13.95, 0]]
contour2 = [[-52.28, 13.95, 50], [-52.28, -25.46, 50], [2.37, -25.46, 50],
            [2.37, 13.95, 50], [-52.28, 13.95, 50]]
contour3 = [[-52.28, 13.95, 100], [-52.28, -25.46, 100], [2.37, -25.46, 100],
            [2.37, 13.95, 100], [-52.28, 13.95, 100]]

# 多平行轮廓线建模
models = ContourModeling.multi_parallel_contour_modeling(
    polylines_set=[contour1, contour2, contour3],
    space_x=1.0,
    space_y=1.0,
    vertical_tol=0.5,
    close_end=True,
)

print(f"生成模型数量: {len(models)}")
for i, tin in enumerate(models):
    print(f"  模型[{i}] 顶点数: {tin.points.shape[0]}, 三角面片数: {tin.faces.shape[0]}")

参数说明

参数 类型 默认值 说明
polylines_set List[Line] / List[np.ndarray] / List[List[List[float]]] 多条轮廓线数据集。每个元素为一条轮廓线,支持三种输入格式
space_x float 1.0 X 方向网格大小
space_y float 1.0 Y 方向网格大小
vertical_tol float 0.5 垂直方向间隔容差
close_end bool True 是否封闭端部

支持的输入格式

polylines_set 的每个元素支持三种格式,与两轮廓线建模一致:

import numpy as np
from dimine_python_sdk.models.types import Line
from dimine_python_sdk.lib.exploitation import ContourModeling

# 方式一:List[List[List[float]]]
set1 = [
    [[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0], [0, 0, 0]],
    [[0, 0, 20], [10, 0, 20], [10, 10, 20], [0, 10, 20], [0, 0, 20]],
    [[0, 0, 40], [10, 0, 40], [10, 10, 40], [0, 10, 40], [0, 0, 40]],
]
models = ContourModeling.multi_parallel_contour_modeling(set1)

# 方式二:List[np.ndarray]
set2 = [
    np.array([[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0], [0, 0, 0]]),
    np.array([[0, 0, 20], [10, 0, 20], [10, 10, 20], [0, 10, 20], [0, 0, 20]]),
    np.array([[0, 0, 40], [10, 0, 40], [10, 10, 40], [0, 10, 40], [0, 0, 40]]),
]
models = ContourModeling.multi_parallel_contour_modeling(set2)

# 方式三:List[Line Pydantic 模型]
set3 = [
    Line(geometry=[[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0], [0, 0, 0]]),
    Line(geometry=[[0, 0, 20], [10, 0, 20], [10, 10, 20], [0, 10, 20], [0, 0, 20]]),
    Line(geometry=[[0, 0, 40], [10, 0, 40], [10, 10, 40], [0, 10, 40], [0, 0, 40]]),
]
models = ContourModeling.multi_parallel_contour_modeling(set3)

5. 实体合并

将多个 DmPolyData 多边形/三角网数据合并为一个实体。可用于将分段建模的结果合并为完整实体。

基础用法

from dimine_python_sdk.lib.types.entity import DmPolyData
from dimine_python_sdk.lib.types.point import DmDPoint
from dimine_python_sdk.lib.exploitation import ContourModeling

# 构建第一个四面体
poly1 = DmPolyData()
p1 = poly1.insert_unique_point(DmDPoint(0, 0, 0))
p2 = poly1.insert_unique_point(DmDPoint(10, 0, 0))
p3 = poly1.insert_unique_point(DmDPoint(5, 10, 0))
p4 = poly1.insert_unique_point(DmDPoint(5, 5, 10))

poly1.insert_next_poly_cell([p1, p2, p3])  # 底面
poly1.insert_next_poly_cell([p1, p2, p4])  # 侧面1
poly1.insert_next_poly_cell([p2, p3, p4])  # 侧面2
poly1.insert_next_poly_cell([p3, p1, p4])  # 侧面3

# 构建第二个四面体(与第一个相邻)
poly2 = DmPolyData()
p5 = poly2.insert_unique_point(DmDPoint(10, 0, 0))
p6 = poly2.insert_unique_point(DmDPoint(20, 0, 0))
p7 = poly2.insert_unique_point(DmDPoint(15, 10, 0))
p8 = poly2.insert_unique_point(DmDPoint(15, 5, 10))

poly2.insert_next_poly_cell([p5, p6, p7])  # 底面
poly2.insert_next_poly_cell([p5, p6, p8])  # 侧面1
poly2.insert_next_poly_cell([p6, p7, p8])  # 侧面2
poly2.insert_next_poly_cell([p7, p5, p8])  # 侧面3

# 合并两个实体,返回 List[TINGeometry]
results = ContourModeling.unite_polydata([poly1, poly2])

for i, merged in enumerate(results):
    print(f"合并结果[{i}]: 顶点数={merged.points.shape[0]}, 面片数={merged.faces.shape[0]}")

配合轮廓线建模使用

from dimine_python_sdk.lib.exploitation import ContourModeling, ContourAlgorithm
from dimine_python_sdk.lib.types.entity import DmPolyData
from dimine_python_sdk.lib.types.point import DmDPoint

# 1. 对相邻轮廓线分别建模
contour1 = [[0, 0, 0], [10, 0, 0], [10, 8, 0], [0, 8, 0], [0, 0, 0]]
contour2 = [[0, 0, 15], [10, 0, 15], [10, 8, 15], [0, 8, 15], [0, 0, 15]]
contour3 = [[0, 0, 30], [10, 0, 30], [10, 8, 30], [0, 8, 30], [0, 0, 30]]

# 两段分别建模
models_1 = ContourModeling.two_contour_modeling(
    ContourAlgorithm.MIN_PERIMETER, contour1, contour2
)
models_2 = ContourModeling.two_contour_modeling(
    ContourAlgorithm.MIN_PERIMETER, contour2, contour3
)

# 2. 将 TINGeometry 直接传给 unite_polydata
merged_results = ContourModeling.unite_polydata(models_1 + models_2)
print(f"合并后共 {len(merged_results)} 个实体")
for i, merged in enumerate(merged_results):
    print(f"  实体[{i}]: 顶点={merged.points.shape[0]}, 面片={merged.faces.shape[0]}")

6. 算法类型

通过 ContourAlgorithm 枚举指定两轮廓线之间的连接算法:

枚举值 数值 说明
ContourAlgorithm.MIN_PERIMETER 0 最小周长法 — 选择使三角网总周长最小的连接方式
ContourAlgorithm.MIN_SURFACE_AREA 1 最小表面积法 — 选择使三角网总表面积最小的连接方式
ContourAlgorithm.SYNC_ADVANCE 2 同步前进法 — 两条轮廓线同步推进连接
ContourAlgorithm.MIN_DISTANCE 3 最小距离法 — 选择距离最小的对应点连接
from dimine_python_sdk.lib.exploitation import ContourModeling, ContourAlgorithm

contour1 = [[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0]]
contour2 = [[0, 0, 20], [10, 0, 20], [10, 10, 20], [0, 10, 20]]

# 尝试不同算法对比效果
models = ContourModeling.two_contour_modeling(
    ContourAlgorithm.MIN_SURFACE_AREA, contour1, contour2
)

7. 异常处理

轮廓线建模定义了层次化异常,建议调用时捕获具体异常:

from dimine_python_sdk.lib.exploitation import (
    ContourModeling,
    ContourAlgorithm,
    ModelingError,
    TwoContourModelingError,
    SingleContourModelingError,
    ContourExtrapolateModelingError,
    ParallelContourModelingError,
)

try:
    models = ContourModeling.two_contour_modeling(
        ContourAlgorithm.MIN_PERIMETER, contour1, contour2
    )
except TwoContourModelingError as e:
    print(f"两轮廓线建模失败: {e}")
except ModelingError as e:
    print(f"轮廓线建模错误: {e}")

异常继承关系:

RuntimeError
 └── ModelingError
      ├── TwoContourModelingError         (两轮廓线建模失败)
      ├── SingleContourModelingError      (单轮廓线封闭为面失败)
      ├── ContourExtrapolateModelingError (轮廓线外推建模失败)
      └── ParallelContourModelingError    (多平行轮廓线建模失败)

8. 提交到 Dimine 场景

生成的三角网模型可以通过 conn 模块提交到 Dimine 场景中显示:

import asyncio
import numpy as np
from dimine_python_sdk.conn import open_client
from dimine_python_sdk.lib.exploitation import ContourModeling, ContourAlgorithm
from dimine_python_sdk.models.types import Shell

async def main():
    # 轮廓线点集
    contour1 = [[-52.28, 13.95, 0], [-52.28, -25.46, 0], [2.37, -25.46, 0],
                [2.37, 13.95, 0], [-52.28, 13.95, 0]]
    contour2 = [[-52.28, 13.95, 50], [-52.28, -25.46, 50], [2.37, -25.46, 50],
                [2.37, 13.95, 50], [-52.28, 13.95, 50]]

    # 两轮廓线建模
    models = ContourModeling.two_contour_modeling(
        ContourAlgorithm.MIN_PERIMETER, contour1, contour2
    )

    # 提交到场景
    async with open_client() as client:
        files = await client.get_files()
        layers = await client.get_layers(file_id=files[0].id)

        shells = [
            Shell(
                file=files[0].id,
                layer=layers[0].id,
                feature="0",
                geometry=tin,
                color=[139, 90, 43],
            )
            for tin in models
        ]
        await client.create_geometry(shells)
        print(f"已提交 {len(shells)} 个模型到场景")

if __name__ == "__main__":
    asyncio.run(main())

9. 完整示例

import numpy as np
from dimine_python_sdk.lib.exploitation import (
    ContourModeling,
    ContourAlgorithm,
    ModelingError,
)
from dimine_python_sdk.models.types import Line


def main():
    # 示例一:两轮廓线建模(list 输入,最小距离法)
    contour1 = [
        [0.0, 0.0, 0.0],
        [10.0, 0.0, 0.0],
        [10.0, 8.0, 0.0],
        [0.0, 8.0, 0.0],
        [0.0, 0.0, 0.0],
    ]
    contour2 = [
        [0.0, 0.0, 15.0],
        [10.0, 0.0, 15.0],
        [10.0, 8.0, 15.0],
        [0.0, 8.0, 15.0],
        [0.0, 0.0, 15.0],
    ]

    try:
        models = ContourModeling.two_contour_modeling(
            ContourAlgorithm.MIN_DISTANCE, contour1, contour2
        )
        print(f"两轮廓线建模: {len(models)} 个模型")
        for i, tin in enumerate(models):
            print(f"  模型[{i}] 顶点: {tin.points.shape[0]}, 面片: {tin.faces.shape[0]}")
    except ModelingError as e:
        print(f"建模失败: {e}")

    # 示例二:单轮廓线封闭为面(ndarray 输入)
    points = np.array([
        [0.0, 0.0, 0.0],
        [5.0, 0.0, 0.0],
        [5.0, 5.0, 0.0],
        [0.0, 5.0, 0.0],
        [0.0, 0.0, 0.0],
    ])

    try:
        models = ContourModeling.single_contour_modeling(
            ContourAlgorithm.MIN_PERIMETER, points
        )
        print(f"\n单轮廓线封闭: {len(models)} 个模型")
        tin = models[0]
        print(f"  顶点: {tin.points.shape[0]}, 面片: {tin.faces.shape[0]}")
    except ModelingError as e:
        print(f"封闭失败: {e}")

    # 示例三:Line 模型输入
    line1 = Line(geometry=[
        [0.0, 0.0, 0.0], [3.0, 0.0, 0.0], [3.0, 3.0, 0.0], [0.0, 3.0, 0.0]
    ])
    line2 = Line(geometry=[
        [0.0, 0.0, 10.0], [3.0, 0.0, 10.0], [3.0, 3.0, 10.0], [0.0, 3.0, 10.0]
    ])

    try:
        models = ContourModeling.two_contour_modeling(
            ContourAlgorithm.MIN_SURFACE_AREA, line1, line2
        )
        print(f"\nLine 输入两轮廓线建模: {len(models)} 个模型")
    except ModelingError as e:
        print(f"建模失败: {e}")


if __name__ == "__main__":
    main()