Skip to content

爆破设计流程:布孔 → 装药 → 起爆网络 → 分析 → DMO

本文用一条端到端示例串起 lib.blasting 的全部设计步骤:从爆区多边形出发, layout_holes 布孔 → design_charge 装药 → build_network 起爆网络 → 纯计算分析 → resolve_schedule / build_dmo 得到与 .dmo 落盘同口径的权威起爆时间并装配 DMO 模型。

各步骤的参数/结果模型完整字段见 模块总览与数据模型; 若要用「装药结构模板」而非直算公式装药,见 装药模板套用与适配.dmo 26 列与三个时间列的精确语义见 DMO 炮孔数据库

示例前提:纯 Python,无需 DIMINE_HOME、无需 Dimine GUI。全文代码可直接运行 (最后一步 .dmo 落盘除外——写盘走 Dimine 原生数据表,见步骤 6)。

from dimine_python_sdk.lib.blasting import (
    BlastRegion, HoleLayoutParams, ChargeParams, Explosive, NetworkParams,
    DetonatorType, layout_holes, design_charge, build_network,
    flyrock_range, throw_direction, blast_bounds, resolve_schedule, build_dmo,
    FlyrockParams,
)

一、定义爆破区域 BlastRegion

爆破区域 = 爆区多边形 + 前排方向(自由面朝向) + 孔口/孔底标高策略

region = BlastRegion(
    name="M01",                                  # 爆区名称 / 编号
    polygon=[(0, 0), (30, 0), (30, 25), (0, 25)],  # 顶点 (X, Y);可传 np.ndarray
    front_azimuth=90.0,                          # 前排方向角 °:0=正北(+Y)、90=正东(+X)
    mouth={"mode": "z", "value": 765.0},          # 孔口标高 = 765 m
    bottom={"mode": "depth", "value": 15.0},      # 孔底 = 孔口标高 − 15 m(即台阶 15 m)
)

标高策略 ElevationSpec.mode 决定每个炮孔的口/底 Z 怎么来:

mode 孔口 孔底 必填
"z" value(标高 m)
"depth" value(孔深 m,孔底=孔口−value)
"surface_file" interp_fn(x, y) -> z
"bottom_file" interp_fn(x, y) -> z
"slope" value(坡度角 °,从自由面向爆区内下倾)

孔口标高只支持 "z" / "surface_file";孔底支持全部五种。文件模式需要传入 (x, y) -> z 的插值函数(如用 lib.io.dmf_file.DmfFile 读出的地表三角网做插值)。


二、布孔 layout_holes

按孔网参数在多边形内排布炮孔网格,并逐孔解算坐标 / 孔深 / 超深:

layout = HoleLayoutParams(
    hole_spacing=5.0,        # 孔间距 m
    row_spacing=4.0,         # 排间距 m
    pattern="方形",           # 方形 / 梅花形 / 三角形 / 自定义(或 LayoutPattern 枚举)
    front_distance=2.0,      # 前排安全距离(第一排孔距自由面)m
    back_distance=2.0,       # 后冲距离 m
    left_distance=2.0,       # 左侧冲距离 m
    right_distance=2.0,      # 右侧冲距离 m
    diameter=220.0,          # 孔径 mm
    inclination=-90.0,       # 倾角 °(负=向下,垂直=-90)
    front_overdrill=2.0,     # 前排超深 m
    back_overdrill=1.0,      # 后排超深 m
    detonator=DetonatorType.NONEL,   # 雷管类型(影响后续起爆时间口径)
)
holes = layout_holes(region, layout)   # -> list[Hole]
print(holes[0].number)       # "B-02":排号 A、B、…,孔号 A-01、B-01、…
print(holes[0].row, holes[0].col)      # 排号(0=前排)/ 排内序号
print(holes[0].depth, holes[0].overdrill, holes[0].bench_height)
# 孔深 m / 超深 m / 台阶高度 = 孔深−超深

布孔行为要点:

  • 多边形先按 front_azimuth + rotation_angle 旋转到「前排朝 +Y、排方向沿 X」的局部系, 用 前排/后冲/左侧/右侧冲距离 收缩包围盒得到布孔范围,再铺网格;梅花形/三角形 相邻排错开半孔距
  • 网格先按「点在多边形内」粗筛,再按每条边要求的垂直安全距离精筛——任意孔口到爆区边界的 垂直距离都不小于对应(前/后/左/右)安全距离。
  • 超深:第 0 排(前排)用 front_overdrill,其余用 back_overdrill;孔底标高先按 策略算「设计孔底」,再下移超深得到实际孔底,孔深 = 孔口 − 实际孔底。
  • 坐标解算:默认垂直孔(倾角 −90)孔底与孔口同 XY;非垂直时孔底沿方位/倾角方向偏移。
  • 合法输入下不抛异常;多边形顶点数不合法、或安全距离把布孔范围收缩成空、或标高策略缺 value/interp_fn 时抛 ValueError

Hole.bench_height(= 孔深 − 超深,>=0)是后续装药负担体积所取的高度, Hole.row == 0 表示前排孔。完整字段见 overview 数据模型


三、装药(直算口径)design_charge

单耗最小填塞直算每孔药量 / 装药结构。主炸药取 explosives[0](列表可为空, 此时抛 ValueError)。

explosives = [Explosive(name="乳化炸药", line_density=6.0, unit_price=8.0)]

charges = design_charge(
    holes,
    ChargeParams(
        template="连续装药",        # 连续装药 / 间隔装药(内置模板)
        in_hole_delay=350.0,        # 孔内雷管延时基值 ms(最靠孔口的炸药段)
        # specific_charge=0.4,      # 单耗 q kg/m³(默认 0.4)
        # charge_mode=ChargeMode.BY_SPECIFIC_CHARGE,
        # adjust_rule=AdjustRule.PROPORTIONAL,
    ),
    explosives,
    burden=4.0,                     # 最小抵抗线 W (m)
)  # -> list[ChargeResult](每孔一个,顺序与 holes 一致)

c = charges[0]
print(c.hole_number, round(c.charge_weight, 2), round(c.charge_length, 2))
print([(s.fill_type, round(s.length, 2), s.weight, s.delay) for s in c.segments])

药量公式

负担面积 装药量 备注
前排(row == 0 a·W q · a · W · H a=孔距、W=最小抵抗线
后排 a·b k · q · a · b · H b=排距、k=后排增大系数(默认 1.15)

其中 H = hole.bench_height(台阶高度),q = params.specific_charge

最小填塞底线

直算与模板适配两条装药路径共用同一权威口径:

min_stemming_length(params, burden, diameter_m)
    = max(params.min_stemming, 0.7·W, 20·diameter(m), 4.5m)

ChargeMode.STEMMING_SPACER(优先填塞和间隔器)还会在此基础上再要求 max(min_stem, min_stemming + spacer_length)

装药结构

  • 结构自孔口 → 孔底有序;segments[0] 恒为孔口填塞段
  • 连续装药:填塞 + 一整段炸药;间隔装药:填塞 + 多段炸药(相邻段间插入 间隔器)。
  • 段数:segments 显式指定优先;否则连续=1 段、间隔装药按孔深自动(>15m 分 3 段、

    8m 分 2 段、否则 1 段)。

  • 炸药段孔内雷管延时自孔口向下逐段递增in_hole_delay + 段号×deck_delay_step (默认 350 → 380 → 410 ms);惰性段(填塞物 / 间隔器)delay = -1,不参与起爆。
  • MOUTH_FIRST(优先孔口装药 / 正向起爆):炸药靠孔口、填塞靠孔底;其余(PROPORTIONAL 默认 / BOTTOM_FIRST)均为孔口填塞在上、炸药在下。
  • 填塞长度 = 孔深 − 装药长度 − 间隔总长(填满炮孔)。当单耗所需装药长度超过 「孔深 − 最小填塞 − 间隔」时会截断,并把原因写入该孔 ChargeResult.warnings (例如孔太浅容纳不下)。返回的 charge_length / charge_weight / stemming_length / spacer_length 按分段实际求和。

工程提示:装药被截断并告警通常是「单耗算出的药量装不进这个孔」——实际应调大孔径/ 孔网或换更高线密度的炸药。校验惯例:Σ segment.length == 孔深stemming_length >= min_stemming_length(...)、惰性段 delay == -1


四、起爆网络 build_network

按连线类型生成以起爆孔为根的树(每孔恰好一个父孔),赋「设计地表起爆时间」初值并统计单段药量:

net = build_network(
    holes,
    NetworkParams(
        connection_type="V型",     # V型 / 斜线型
        hole_delay=25.0,           # 孔间延时 ms
        row_delay_min=42.0,        # 排间延时 ms(V型累进基准)
    ),
    init_delay=100.0,              # 起爆孔地表起爆时间锚点 ms
    charge_results=charges,        # 用于单段最大药量统计(可省略)
)  # -> NetworkResult
  • V 型:起爆孔自动取第一排中部;中心列自上而下作脊线,每排自脊点向左右各拉一臂 传爆。地表起爆时间 = 起爆孔延时 + 排号×排间延时 + |列偏移|×孔间延时。
  • 斜线型:起爆孔自动取第一排侧翼(col 最小者);全网络为单条单调链逐孔传爆。
  • initiating_hole 可显式指定起爆孔(如 "A-02"),连线树会重根到该孔;编号不在孔 列表内抛 ValueError
  • 返回字段:
  • delays:孔号 → 地表起爆时间 ms(纯设计递增量,不含导爆管连线燃烧时长);
  • relays[(a, b)]:每条连线的设计延时雷管 ms(孔间=孔间延时、排间=排间延时), 不是两孔时间差——写入 .dmo 连线信息时以此为延时雷管;
  • segment_charges:地表起爆时刻 → 该时刻各孔药量之和(单段最大药量参考);
  • edges / nodes / initiating_hole
  • 网络内建校验(违反抛 ValueError):恰一个根孔且为起爆孔、其余每孔入度恰 1、无自环 无重复边、连线数 = 孔数 − 1(连通无环)、沿连线父孔时刻早于子孔。

五、纯计算分析

等时线/柱状图/动画等 matplotlib 出图在 skill,本包只提供三项纯数值

# 飞石安全距离(GB 6722-2014):R = Kf·n·W;深孔 ≥200m / 浅孔≥300m,下坡 ×1.5
flyrock_range(FlyrockParams(W=4.0, n=1.0, Kf=1.0))
# -> {"影响范围": 200.0, "理论值": 4.0, "规范下限值": 200.0, "爆破类型": "深孔", "下坡方向": False}

# 抛掷方向 = 前排方向(自由面朝向)
throw_direction(region)
# -> {"azimuth": 90.0, "vector": [1.0, ...], "note": "岩石抛掷方向 = 前排方向(自由面朝向)"}

# 爆破范围 = 全部孔口/孔底最小外接盒
blast_bounds(holes)
# -> {"X最小": ..., "Y最小": ..., "Z最小": ..., "X最大": ..., "Y最大": ..., "Z最大": ..., "炮孔数": 24}

FlyrockParamsW(最小抵抗线)、n(炸药作用系数)、Kf(安全系数)必填且 >0; blast_type 决定规范下限(深孔=200m / 浅孔/二次破碎=300m);downhill=True 影响范围再 ×1.5。


六、权威起爆时间与 DMO 装配

build_networkdelays纯设计递增量(不含连线燃烧)。要得到与 .dmo 落盘 完全一致的「地表起爆时间」,用 resolve_schedule —— 它沿连线网络按 「根锚 + Σ(延时雷管 + 连线燃烧时长)」重算,与 DmoFile.save 写盘推导同源

# 权威地表起爆时间 {孔号: ms}
surface = resolve_schedule(
    holes, charges, net, region,
    burn_velocity=2000.0,                     # 导爆管燃速 m/s
    detonator=DetonatorType.NONEL,            # 默认导爆管:计入连线燃烧时长
)
net.delays = surface                          # 回写,供 Excel/分析/落盘统一消费

导爆管 vs 数码电子(两种雷管的权威时间口径不同,务必显式一致传入):

雷管 地表起爆时间 锚点
NONEL 导爆管 父孔 + 孔间延时雷管 + 连线燃烧时长(孔口距离 ÷ 燃速) 起爆孔锚定「起爆延时」
DIGITAL 数码电子 父孔 + 孔间延时雷管(逐孔独立编程、无导爆管传爆,不计连线燃烧 首爆点锚 0

燃烧时长取决于孔口间距与燃速,故设计初值与权威值会差若干 ms;只有起爆孔本身一致。

把完整设计结果装配为 .dmo 模型(内存,不落盘):

dmo = build_dmo(
    holes, charges, net, region,
    burn_velocity=2000.0, detonator=DetonatorType.NONEL,
)  # -> lib.io.dmo_file.DmoFile

dmo.save("爆破设计结果.dmo", burn_velocity=2000.0)   # 落盘(需 Dimine 原生运行环境)

build_dmo 做的事:每个设计 HoleDmoHole(装药字段取匹配的 ChargeResultsegments 直接沿用);每条连线 → BlastLine(终点=目标孔口坐标, delay=设计延时雷管); 网络 → DmoNetwork(..., count_line_burn=雷管类型)。只要 network.edges 非空, dmo.save() 落盘前会沿网络重算 delays(同 resolve_schedule),保证连线拓扑、 延时雷管与三个时间列一致。

.dmo 26 列表头、三个时间列(起爆延时/地表起爆时间/孔内起爆时间)的完整语义与 DmoFile.holes / .network 类型化模型见 DMO 炮孔数据库


校验检查点

每次设计完成后建议核对(skill 同款校验清单):

  • [ ] len(charges) == len(holes),且每孔 Σ segment.length == 孔深(±0.2m)
  • [ ] 填塞 stemming_length >= min_stemming_length(params, W, 直径_m),不足则该孔 warnings
  • [ ] len(net.edges) == len(holes) - 1,无孤立孔;沿每条边父孔时刻 < 子孔时刻
  • [ ] resolve_schedule(...) 回写 net.delays 后再算单段最大药量 / 出报告
  • [ ] 飞石影响范围 ≥ GB6722 规范下限;起爆点孔均已点亮(锚定延时)

继续处理一个已有的 .dmo

若要读取某个 .dmo(炮孔 + 装药 + 连线已定)继续修改或分析,用类型化 DmoFile

from dimine_python_sdk.lib.io.dmo_file import DmoFile

dmo = DmoFile("已设计.dmo")            # 加载即建 holes / network 模型
dmo.network.line_of("A-01", "A-02").delay = 42.0   # 改某条连线的延时雷管
dmo.holes[0].diameter = 250.0          # 就地改孔参数
dmo.save("已设计_改.dmo", burn_velocity=2000.0)     # 下游地表起爆时间自动沿网络重算

注意:DmoFile.holes 的元素是 DmoHole(模型字段见 dmo_file.md),不含设计布孔 所需的 row / col 等字段。若要把它当作设计 Hole 重新走 build_network(依赖 row/col 分组)等算法,需自行由孔口坐标 / 相对前排的位置重建 Hole 列表。


参考链接