Skip to content

搜索椭球体参数计算(ellipsoid)

基于最小体积包围椭球(MVEE, Khachiyan 算法)从矿体点云自动计算搜索椭球体的 形状参数(3 轴长)和方位参数(3 角度),输出可直接映射到 BlockModelDistancePowerParams

搜索椭球体参数计算模块

基于最小体积包围椭球(MVEE, Khachiyan 算法),从矿体点云计算距离幂估值 所需的搜索椭球体参数(3 轴长 + 3 角度)。

使用示例::

from dimine_python_sdk.lib.prospecting.ellipsoid import (
    compute_search_ellipsoid,
    compute_search_ellipsoid_from_dmf,
)

# 从点云直接计算
params = compute_search_ellipsoid(points)
print(params.angle_main, params.main_radius)

# 从 DMF 矿体模型计算
params = compute_search_ellipsoid_from_dmf("矿体.dmf", voxel_size=5.0)
print(params.model_dump())

# 直接映射到估值参数
eval_params = BlockModelDistancePowerParams(
    **params.to_block_model_params()
)

参考: Khachiyan, L. G. (1996). "Rounding of Polytopes in the Real Number Model of Computation". Mathematics of Operations Research.

SearchEllipsoidParams

Bases: ParamModel

搜索椭球体参数,可直接映射到 BlockModelDistancePowerParams

三个角度依次为 Z-Y-X 欧拉角序列: R = Rz(π/2 − angle_main) × Ry(angle_second) × Rx(angle_short)

其中 R 的列向量为 [PC1, PC2, PC3]。

Source code in dimine_python_sdk\lib\prospecting\ellipsoid.py
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
class SearchEllipsoidParams(ParamModel):
    """搜索椭球体参数,可直接映射到 ``BlockModelDistancePowerParams``。

    三个角度依次为 Z-Y-X 欧拉角序列:
        R = Rz(π/2 − angle_main) × Ry(angle_second) × Rx(angle_short)

    其中 R 的列向量为 [PC1, PC2, PC3]。
    """

    # ---- 形状参数 ----
    main_radius: float
    """主轴半径(m),椭球体最长半轴"""
    second_radius: float
    """次轴半径(m),椭球体中等半轴"""
    short_radius: float
    """短轴半径(m),椭球体最短半轴"""
    second_main_rate: float
    """次轴/主轴比例"""
    short_main_rate: float
    """短轴/主轴比例"""

    # ---- 方位参数(SDK 映射) ----
    angle_main: float
    """方位角(°),主轴水平投影方向,0°=正北,90°=正东"""
    angle_second: float
    """倾伏角(°),主轴与水平面夹角,正值=向下,0°=水平,90°=垂直"""
    angle_short: float
    """倾角(°),椭球体绕主轴旋转角,控制短轴(厚度方向)的侧倾"""

    # ---- 辅助信息 ----
    center: Tuple[float, float, float]
    """椭球体中心坐标 (x, y, z)"""
    pc1_direction: Tuple[float, float, float]
    """主轴方向单位向量(走向方向)"""
    pc2_direction: Tuple[float, float, float]
    """次轴方向单位向量(倾向方向)"""
    pc3_direction: Tuple[float, float, float]
    """短轴方向单位向量(厚度方向)"""

    def to_block_model_params(self) -> dict:
        """提取 ``BlockModelDistancePowerParams`` 所需的 6 个字段。

        Returns:
            dict,包含 main_radius、second_main_rate、short_main_rate、
            angle_main、angle_second、angle_short
        """
        return {
            "main_radius": self.main_radius,
            "second_main_rate": self.second_main_rate,
            "short_main_rate": self.short_main_rate,
            "angle_main": self.angle_main,
            "angle_second": self.angle_second,
            "angle_short": self.angle_short,
        }

angle_main instance-attribute

方位角(°),主轴水平投影方向,0°=正北,90°=正东

angle_second instance-attribute

倾伏角(°),主轴与水平面夹角,正值=向下,0°=水平,90°=垂直

angle_short instance-attribute

倾角(°),椭球体绕主轴旋转角,控制短轴(厚度方向)的侧倾

center instance-attribute

椭球体中心坐标 (x, y, z)

main_radius instance-attribute

主轴半径(m),椭球体最长半轴

pc1_direction instance-attribute

主轴方向单位向量(走向方向)

pc2_direction instance-attribute

次轴方向单位向量(倾向方向)

pc3_direction instance-attribute

短轴方向单位向量(厚度方向)

second_main_rate instance-attribute

次轴/主轴比例

second_radius instance-attribute

次轴半径(m),椭球体中等半轴

short_main_rate instance-attribute

短轴/主轴比例

short_radius instance-attribute

短轴半径(m),椭球体最短半轴

to_block_model_params()

提取 BlockModelDistancePowerParams 所需的 6 个字段。

Returns:

Type Description
dict

dict,包含 main_radius、second_main_rate、short_main_rate、

dict

angle_main、angle_second、angle_short

Source code in dimine_python_sdk\lib\prospecting\ellipsoid.py
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
def to_block_model_params(self) -> dict:
    """提取 ``BlockModelDistancePowerParams`` 所需的 6 个字段。

    Returns:
        dict,包含 main_radius、second_main_rate、short_main_rate、
        angle_main、angle_second、angle_short
    """
    return {
        "main_radius": self.main_radius,
        "second_main_rate": self.second_main_rate,
        "short_main_rate": self.short_main_rate,
        "angle_main": self.angle_main,
        "angle_second": self.angle_second,
        "angle_short": self.angle_short,
    }

compute_search_ellipsoid(points, voxel_size=5.0)

从点云计算搜索椭球体参数。

流程:体素降采样 → MVEE → 角度分解。

Parameters:

Name Type Description Default
points ndarray

点云坐标,shape=(N, 3),(x=东, y=北, z=高程)

required
voxel_size Optional[float]

体素降采样尺寸(米),设为 None 或 0 则跳过降采样。 推荐 5.0 m,可有效消除三角网密度不均的影响。

5.0

Returns:

Type Description
SearchEllipsoidParams

SearchEllipsoidParams,包含 6 个核心参数及辅助信息

Raises:

Type Description
ValueError

点云数量不足(< 4)

Example::

params = compute_search_ellipsoid(points, voxel_size=5.0)
# 直接用于距离幂估值
eval_params = BlockModelDistancePowerParams(
    **params.to_block_model_params(),
    sample_file="样品.dmg",
    variables="CU",
    extra_attributes="样品点数目",
)
Source code in dimine_python_sdk\lib\prospecting\ellipsoid.py
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
def compute_search_ellipsoid(
    points: np.ndarray,
    voxel_size: Optional[float] = 5.0,
) -> SearchEllipsoidParams:
    """
    从点云计算搜索椭球体参数。

    流程:体素降采样 → MVEE → 角度分解。

    Args:
        points: 点云坐标,shape=(N, 3),(x=东, y=北, z=高程)
        voxel_size: 体素降采样尺寸(米),设为 None 或 0 则跳过降采样。
                    推荐 5.0 m,可有效消除三角网密度不均的影响。

    Returns:
        SearchEllipsoidParams,包含 6 个核心参数及辅助信息

    Raises:
        ValueError: 点云数量不足(< 4)

    Example::

        params = compute_search_ellipsoid(points, voxel_size=5.0)
        # 直接用于距离幂估值
        eval_params = BlockModelDistancePowerParams(
            **params.to_block_model_params(),
            sample_file="样品.dmg",
            variables="CU",
            extra_attributes="样品点数目",
        )
    """
    if points.ndim != 2 or points.shape[1] < 3:
        raise ValueError(f"点云应为 (N, 3) 形状,当前: {points.shape}")

    if len(points) < 4:
        raise ValueError(f"点云数量不足:需要至少 4 个点,当前 {len(points)} 个")

    # 1. 体素降采样
    if voxel_size and voxel_size > 0:
        pts = _voxel_downsample(points, voxel_size)
    else:
        pts = points

    # 2. MVEE
    axes, directions, center = _compute_mvee(pts)

    # 3. 角度分解
    main_r, second_r, short_r, az, pl, dip = _decompose_angles(axes, directions)

    # 4. 比例
    second_main_rate = second_r / main_r if main_r > 0 else 0.0
    short_main_rate = short_r / main_r if main_r > 0 else 0.0

    return SearchEllipsoidParams(
        main_radius=round(main_r, 2),
        second_radius=round(second_r, 2),
        short_radius=round(short_r, 2),
        second_main_rate=round(second_main_rate, 4),
        short_main_rate=round(short_main_rate, 4),
        angle_main=round(az, 2),
        angle_second=round(pl, 2),
        angle_short=round(dip, 2),
        center=tuple(round(float(c), 2) for c in center),
        pc1_direction=tuple(round(float(v), 4) for v in directions[0]),
        pc2_direction=tuple(round(float(v), 4) for v in directions[1]),
        pc3_direction=tuple(round(float(v), 4) for v in directions[2]),
    )

compute_search_ellipsoid_from_dmf(dmf_path, voxel_size=5.0)

从 DMF 矿体模型文件直接计算搜索椭球体参数。

自动提取所有 Shell 实体的顶点,执行体素降采样与 MVEE 计算。

Parameters:

Name Type Description Default
dmf_path str

DMF 矿体模型文件路径

required
voxel_size float

体素降采样尺寸(米),推荐 5.0 m

5.0

Returns:

Type Description
SearchEllipsoidParams

SearchEllipsoidParams

Raises:

Type Description
FileNotFoundError

DMF 文件不存在

ValueError

DMF 中无 Shell 实体

Source code in dimine_python_sdk\lib\prospecting\ellipsoid.py
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
def compute_search_ellipsoid_from_dmf(
    dmf_path: str,
    voxel_size: float = 5.0,
) -> SearchEllipsoidParams:
    """
    从 DMF 矿体模型文件直接计算搜索椭球体参数。

    自动提取所有 Shell 实体的顶点,执行体素降采样与 MVEE 计算。

    Args:
        dmf_path: DMF 矿体模型文件路径
        voxel_size: 体素降采样尺寸(米),推荐 5.0 m

    Returns:
        SearchEllipsoidParams

    Raises:
        FileNotFoundError: DMF 文件不存在
        ValueError: DMF 中无 Shell 实体
    """
    from pathlib import Path

    from dimine_python_sdk.lib.io.dmf_file import DmfFile

    path = Path(dmf_path)
    if not path.exists():
        raise FileNotFoundError(f"DMF 文件不存在: {dmf_path}")

    # 提取所有 Shell 顶点
    dmf = DmfFile(str(path))
    all_vertices = []
    for layer in dmf.layers:
        for entity in layer.entities:
            if hasattr(entity, 'type') and entity.type == 'shell':
                tin = entity.geometry
                if tin is not None and hasattr(tin, 'points'):
                    pts = np.asarray(tin.points, dtype=np.float64)
                    if pts.ndim == 2 and pts.shape[1] >= 3:
                        all_vertices.append(pts[:, :3])
    dmf.close()

    if not all_vertices:
        raise ValueError(f"DMF 中未找到 Shell 实体: {dmf_path}")

    points = np.vstack(all_vertices)
    return compute_search_ellipsoid(points, voxel_size=voxel_size)