3. 矿体边界悬挂节点的批量捕捉
悬挂节点的成因与批量捕捉思路
矿体边界线在数字化采集、格式转换或裁剪后,常出现端点未与任何其他线或面接触的情况,这类端点即悬挂节点(dangle node)。它会导致后续构面失败、边界不闭合、面积统计偏差。本例针对线图层中的悬挂端点,采用“识别—设容差—批量捕捉—复核统计”的闭环处理。
关键约束:捕捉容差必须小于矿体边界的最小可信间距(例如相邻勘探线间距的 1/10),否则会把本应独立的边界误吸附到一起。示例中设容差 tolerance = 2.0 m,仅对端点执行捕捉,不移动中间顶点。
识别与批量捕捉的关键实现
以下用 Python + Shapely 演示核心逻辑(示例数据为教学构造,非实测)。思路:先统计每个端点在容差范围内是否与其他线接触,判定悬挂;再对悬挂端点求最近边界线上的投影点,替换原坐标。
from shapely.geometry import LineString, Point, MultiLineString
from shapely.ops import unary_union
# 示例边界线(教学构造)
lines = [
LineString([(0,0),(0,100),(110,100)]),
LineString([(130,0),(130,90),(230,90)]),
LineString([(260,0),(260,80),(290,80)]),
]
tolerance = 2.0
def endpoints(ls):
c = list(ls.coords)
return [Point(c[0]), Point(c[-1])]
# 1) 识别悬挂端点:端点容差内无其他线接触
dangles = []
for i, ls in enumerate(lines):
for ep in endpoints(ls):
others = [l for j, l in enumerate(lines) if j != i]
if not any(ep.distance(o) <= tolerance for o in others):
dangles.append((i, ep))
print("修复前悬挂节点数:", len(dangles))
# 2) 批量捕捉:吸附到最近边界线
fixed = list(lines)
for i, ep in dangles:
others = [l for j, l in enumerate(lines) if j != i]
nearest = min(others, key=lambda o: ep.distance(o))
proj = nearest.interpolate(nearest.project(ep))
coords = list(fixed[i].coords)
if Point(coords[0]).equals(ep):
coords[0] = (proj.x, proj.y)
else:
coords[-1] = (proj.x, proj.y)
fixed[i] = LineString(coords)
# 3) 复核统计
remain = 0
for i, ls in enumerate(fixed):
for ep in endpoints(ls):
others = [l for j, l in enumerate(fixed) if j != i]
if not any(ep.distance(o) <= tolerance for o in others):
remain += 1
print("修复后悬挂节点数:", remain)
容差选择建议:先统计所有悬挂端点到最近线的距离分布,取“明显断层”处的距离作为容差上限;若容差过大导致边界被拉变形,应回退并改用“延伸至交点”而非“投影吸附”。
结果判读与验证
| 检查项 | 修复前 | 修复后 | 判定标准 |
|---|---|---|---|
| 悬挂节点数 | 3 | 0 | 应为 0 或仅剩合理孤立端点 |
| 边界线长度变化 | — | ≤ 容差 × 节点数 | 单线长度变化不超过 2.0 m |
| 构面闭合性 | 失败 | 成功 | 可生成闭合面且无悬挂 |
| 面积偏差 | — | 示例约 0.3% | 在允许误差内(示例值,需按项目定) |
验证时务必重新运行拓扑检查,确认 dangle 规则返回空集;同时对比修复前后边界线长度与构面面积,若长度变化超过容差累计值,说明捕捉点选择有误,需检查最近线判定逻辑。