爆破设计流程:布孔 → 装药 → 起爆网络 → 分析 → DMO
本文用一条端到端示例串起 lib.blasting 的全部设计步骤:从爆区多边形出发,
layout_holes 布孔 → design_charge 装药 → build_network 起爆网络 → 纯计算分析 →
resolve_schedule / build_dmo 得到与 .dmo 落盘同口径的权威起爆时间并装配 DMO 模型。
各步骤的参数/结果模型完整字段见 模块总览与数据模型; 若要用「装药结构模板」而非直算公式装药,见 装药模板套用与适配;
.dmo26 列与三个时间列的精确语义见 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}
FlyrockParams 的 W(最小抵抗线)、n(炸药作用系数)、Kf(安全系数)必填且 >0;
blast_type 决定规范下限(深孔=200m / 浅孔/二次破碎=300m);downhill=True 影响范围再 ×1.5。
六、权威起爆时间与 DMO 装配
build_network 的 delays 是纯设计递增量(不含连线燃烧)。要得到与 .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 做的事:每个设计 Hole → DmoHole(装药字段取匹配的 ChargeResult,segments
直接沿用);每条连线 → BlastLine(终点=目标孔口坐标, delay=设计延时雷管);
网络 → DmoNetwork(..., count_line_burn=雷管类型)。只要 network.edges 非空,
dmo.save() 落盘前会沿网络重算 delays(同 resolve_schedule),保证连线拓扑、
延时雷管与三个时间列一致。
.dmo26 列表头、三个时间列(起爆延时/地表起爆时间/孔内起爆时间)的完整语义与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列表。
参考链接
- 模块总览与数据模型 — 全部参数/结果模型字段、枚举、异常
- 装药模板套用与适配 — 用 explosivemodel.dmt 模板装药的另一条路径
- 全局配置库与参数来源 — 从 Dimine 全局配置读入上述参数
- DMO 炮孔数据库 —
.dmo文件类型化读写与时间列语义