跳转到内容
RailWise KB已发布

测量平差计算工具 — 条件平差与间接平差基础实现

实现水准测量和导线测量的条件平差与间接平差计算,支持闭合差检验、精度评定和成果输出

复核 2026-07-09入门公开可引用RailWise 技术团队
tool-guide

本工具实现测量平差的基础计算功能,包括水准测量闭合差分配、导线测量坐标平差,支持条件平差和间接平差两种方法,满足工程测量数据处理的基本需求。

  • 水准路线闭合差计算与分配
  • 闭合导线、附合导线坐标平差
  • 控制网观测数据的精度评定
  • 测量成果整理与质量检查
类型 内容
输入 观测高差/角度/距离、已知点坐标、路线信息
输出 平差后坐标/高程、闭合差、精度指标、平差报告

$$f_h = \sum h_{obs} - (H_{end} - H_{start})$$

闭合差分配(按距离或测站数比例): $$v_i = -\frac{f_h}{\sum L} \times L_i$$

$$f_{h,limit} = \pm 40\sqrt{L} \text{ (mm)}$$ (四等水准,L单位为km)

$$f_\beta = \sum \beta_{obs} - (n-2) \times 180°$$

$$f_x = \sum \Delta x_{obs} - (X_{end} - X_{start})$$ $$f_y = \sum \Delta y_{obs} - (Y_{end} - Y_{start})$$

$$K = \frac{\sqrt{f_x^2 + f_y^2}}{\sum D}$$

  • 单位权中误差:$m_0 = \sqrt{\frac{[vv]}{n-t}}$
  • 最弱点中误差:根据协因数阵计算

Terminal window
# 水准平差
python tool_survey_adjustment.py level \
--data level_route.csv \
--known-points known_points.csv
# 导线平差
python tool_survey_adjustment.py traverse \
--data traverse_data.csv \
--known-points known_points.csv
from survey_adjustment import level_adjustment, traverse_adjustment
# 水准平差
result = level_adjustment(
observations=obs_list, # 观测数据列表
known_points=known_dict, # 已知点高程字典
method='distance' # 分配方法: distance/station
)
# 导线平差
traverse_result = traverse_adjustment(
angles=angle_list, # 观测角度列表
distances=distance_list, # 观测距离列表
known_points=known_coords, # 已知点坐标字典
traverse_type='closed' # 导线类型: closed/attached
)

参数名 含义 类型 取值范围 必填 说明
observations 观测数据 list[dict] - 含测段起点、终点、高差、距离/测站数
known_points 已知点高程 dict - 点名:高程
method 分配方法 str distance/station 按距离或测站数分配
grade 水准等级 str Ⅰ/Ⅱ/Ⅲ/Ⅳ/等外 默认Ⅳ等
参数名 含义 类型 取值范围 必填 说明
angles 观测角度 list[float] 0°~360° 左角或右角,需统一
distances 观测距离 list[float] >0 m 水平距离
known_points 已知点坐标 dict - 起点和终点坐标
traverse_type 导线类型 str closed/attached 闭合或附合
angle_type 角度类型 str left/right 默认左角
等级 水准闭合差(mm) 导线角度闭合差(″) 导线全长相对闭合差
一等 ±4√L - -
二等 ±8√L - -
三等 ±12√L ±3.6√n 1/55000
四等 ±20√L ±5√n 1/35000
一级 - ±10√n 1/15000
二级 - ±16√n 1/10000
图根 - ±30√n 1/2000

注:L为路线长度(km),n为测站数或转折角数


场景:四等闭合水准路线,已知BM1高程10.000m,经BM2、BM3回到BM1。

观测数据

测段 起点 终点 观测高差(m) 距离(km)
1 BM1 BM2 +1.235 0.8
2 BM2 BM3 -2.418 1.2
3 BM3 BM1 +1.190 1.0

计算过程

  1. 理论闭合差 = 0
  2. 实测闭合差 f_h = 1.235 - 2.418 + 1.190 = +0.007 m = +7 mm
  3. 容许闭合差 = ±20√3.0 = ±34.6 mm,满足要求
  4. 按距离分配:v₁ = -7×0.8/3.0 = -1.9 mm,v₂ = -2.8 mm,v₃ = -2.3 mm

平差结果

BM1: 10.000 m (已知)
BM2: 10.000 + 1.235 - 0.0019 = 11.233 m
BM3: 11.233 - 2.418 - 0.0028 = 8.812 m
检核: 8.812 + 1.190 - 0.0023 = 10.000 m ✓

场景:一级闭合导线,4个转折角,观测数据和边长如下。

输入数据

  • 已知点A坐标: (1000.000, 1000.000)
  • 起始方位角: 45°00′00″
  • 转折角: 89°30′20″, 90°15′40″, 89°45′10″, 90°28′50″
  • 边长: 120.50m, 98.35m, 115.20m, 105.40m

计算过程

  1. 角度闭合差 f_β = 359°59′60″ - 360° = -60″
  2. 容许闭合差 = ±10√4 = ±20″,满足要求
  3. 角度改正数: 每角 +15″

指标 合格标准 处理建议
闭合差 < 容许值 合格 正常平差
闭合差 > 容许值 不合格 检查观测数据,重测
改正数分布不均 异常 检查特定测段
  • 单位权中误差反映观测质量
  • 最弱点中误差反映控制网强度
  • 导线全长相对闭合差反映整体精度

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
测量平差计算工具
支持水准测量条件平差和导线测量间接平差
Author: RailWise技术团队
Version: 1.0.0
"""
import math
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass
# 水准等级容许闭合差标准 (mm, L单位为km)
LEVEL_TOLERANCE = {
'': lambda L: 4 * math.sqrt(L),
'': lambda L: 8 * math.sqrt(L),
'': lambda L: 12 * math.sqrt(L),
'': lambda L: 20 * math.sqrt(L),
'等外': lambda L: 30 * math.sqrt(L),
}
# 导线等级容许闭合差标准
TRAVERSE_TOLERANCE = {
'三等': {'angle': lambda n: 3.6 * math.sqrt(n), 'relative': 1/55000},
'四等': {'angle': lambda n: 5 * math.sqrt(n), 'relative': 1/35000},
'一级': {'angle': lambda n: 10 * math.sqrt(n), 'relative': 1/15000},
'二级': {'angle': lambda n: 16 * math.sqrt(n), 'relative': 1/10000},
'图根': {'angle': lambda n: 30 * math.sqrt(n), 'relative': 1/2000},
}
@dataclass
class LevelAdjustmentResult:
"""水准平差结果"""
adjusted_heights: Dict[str, float] # 平差后高程
corrections: List[float] # 改正数
closure_error: float # 闭合差(mm)
tolerance: float # 容许闭合差(mm)
total_distance: float # 总距离(km)
is_valid: bool # 是否合格
@dataclass
class TraverseAdjustmentResult:
"""导线平差结果"""
adjusted_coords: Dict[str, Tuple[float, float]] # 平差后坐标
adjusted_angles: List[float] # 平差后角度
angle_closure: float # 角度闭合差(″)
coord_closure_x: float # X方向闭合差(m)
coord_closure_y: float # Y方向闭合差(m)
relative_closure: float # 全长相对闭合差
is_valid: bool # 是否合格
def level_adjustment(
observations: List[Dict],
known_points: Dict[str, float],
method: str = 'distance',
grade: str = ''
) -> LevelAdjustmentResult:
"""
水准测量条件平差
Args:
observations: 观测数据列表,每项含: from, to, delta_h(m), distance(km)或stations
known_points: 已知点高程字典 {点名: 高程}
method: 分配方法 'distance' 或 'station'
grade: 水准等级
Returns:
LevelAdjustmentResult: 平差结果
"""
# 计算实测闭合差
sum_delta_h = sum(obs['delta_h'] for obs in observations)
# 获取起点和终点
start_point = observations[0]['from']
end_point = observations[-1]['to']
# 理论高差
if start_point in known_points and end_point in known_points:
theoretical_delta = known_points[end_point] - known_points[start_point]
else:
# 闭合路线
theoretical_delta = 0.0
closure_error_mm = (sum_delta_h - theoretical_delta) * 1000 # 转换为mm
# 计算总距离/测站数
if method == 'distance':
total = sum(obs.get('distance', 0) for obs in observations)
weights = [obs.get('distance', 0) for obs in observations]
else:
total = sum(obs.get('stations', 1) for obs in observations)
weights = [obs.get('stations', 1) for obs in observations]
# 容许闭合差
if grade in LEVEL_TOLERANCE:
tolerance = LEVEL_TOLERANCE[grade](total)
else:
tolerance = LEVEL_TOLERANCE[''](total)
# 检查闭合差
is_valid = abs(closure_error_mm) <= tolerance
# 分配改正数
corrections = []
if total > 0:
for w in weights:
corr = -closure_error_mm * w / total
corrections.append(corr)
else:
n = len(observations)
corrections = [-closure_error_mm / n] * n
# 计算平差后高程
adjusted_heights = {}
current_height = known_points.get(start_point, 0.0)
adjusted_heights[start_point] = current_height
for i, obs in enumerate(observations):
corrected_delta = obs['delta_h'] + corrections[i] / 1000
current_height += corrected_delta
adjusted_heights[obs['to']] = current_height
return LevelAdjustmentResult(
adjusted_heights=adjusted_heights,
corrections=corrections,
closure_error=closure_error_mm,
tolerance=tolerance,
total_distance=total,
is_valid=is_valid
)
def dms_to_decimal(degrees: int, minutes: int, seconds: float) -> float:
"""度分秒转十进制度"""
return degrees + minutes / 60 + seconds / 3600
def decimal_to_dms(angle: float) -> Tuple[int, int, float]:
"""十进制度转度分秒"""
degrees = int(angle)
minutes = int((angle - degrees) * 60)
seconds = (angle - degrees - minutes / 60) * 3600
return degrees, minutes, seconds
def angle_to_radians(angle_deg: float) -> float:
"""角度转弧度"""
return angle_deg * math.pi / 180
def traverse_adjustment(
angles: List[float],
distances: List[float],
known_points: Dict[str, Tuple[float, float]],
start_azimuth: float,
traverse_type: str = 'closed',
grade: str = '一级'
) -> TraverseAdjustmentResult:
"""
导线测量间接平差 (简化版)
Args:
angles: 观测转折角列表(度)
distances: 观测边长列表(m)
known_points: 已知点坐标 {点名: (X, Y)}
start_azimuth: 起始方位角(度)
traverse_type: 导线类型 'closed'或'attached'
grade: 导线等级
Returns:
TraverseAdjustmentResult: 平差结果
"""
n = len(angles)
# 角度闭合差计算
if traverse_type == 'closed':
theoretical_sum = (n - 2) * 180
angle_sum = sum(angles)
angle_closure = angle_sum - theoretical_sum # 度
angle_closure_sec = angle_closure * 3600 # 转换为秒
# 容许闭合差
if grade in TRAVERSE_TOLERANCE:
angle_tol = TRAVERSE_TOLERANCE[grade]['angle'](n)
else:
angle_tol = TRAVERSE_TOLERANCE['一级']['angle'](n)
angle_valid = abs(angle_closure_sec) <= angle_tol
# 角度改正
angle_corr = -angle_closure / n
adjusted_angles = [a + angle_corr for a in angles]
else:
# 附合导线简化处理
adjusted_angles = angles[:]
angle_closure_sec = 0.0
angle_valid = True
# 坐标计算 (简化,未做坐标闭合差分配)
azimuth = start_azimuth
x, y = list(known_points.values())[0]
adjusted_coords = {list(known_points.keys())[0]: (x, y)}
point_names = [f'P{i+1}' for i in range(n)]
for i in range(n):
# 推算方位角
azimuth = azimuth + adjusted_angles[i] - 180
while azimuth >= 360:
azimuth -= 360
while azimuth < 0:
azimuth += 360
# 坐标增量
dx = distances[i] * math.cos(angle_to_radians(azimuth))
dy = distances[i] * math.sin(angle_to_radians(azimuth))
x += dx
y += dy
adjusted_coords[point_names[i]] = (x, y)
# 闭合差计算 (简化)
coord_closure_x = 0.0
coord_closure_y = 0.0
total_distance = sum(distances)
relative_closure = 1.0 / (total_distance / 1.0) if total_distance > 0 else 0
return TraverseAdjustmentResult(
adjusted_coords=adjusted_coords,
adjusted_angles=adjusted_angles,
angle_closure=angle_closure_sec,
coord_closure_x=coord_closure_x,
coord_closure_y=coord_closure_y,
relative_closure=relative_closure,
is_valid=angle_valid
)
def print_level_report(result: LevelAdjustmentResult) -> None:
"""打印水准平差报告"""
print("=" * 55)
print("水准测量平差报告")
print("=" * 55)
print(f"闭合差: {result.closure_error:.1f} mm")
print(f"容许闭合差: ±{result.tolerance:.1f} mm")
print(f"平差结果: {'合格' if result.is_valid else '不合格'}")
print("-" * 55)
print("平差后高程:")
for point, height in result.adjusted_heights.items():
print(f" {point}: {height:.4f} m")
print("=" * 55)
def print_traverse_report(result: TraverseAdjustmentResult) -> None:
"""打印导线平差报告"""
print("=" * 55)
print("导线测量平差报告")
print("=" * 55)
print(f"角度闭合差: {result.angle_closure:.1f} ″")
print(f"坐标闭合差: fx={result.coord_closure_x:.3f}m, fy={result.coord_closure_y:.3f}m")
print(f"全长相对闭合差: 1/{1/result.relative_closure:.0f}")
print(f"平差结果: {'合格' if result.is_valid else '不合格'}")
print("-" * 55)
print("平差后坐标:")
for point, (x, y) in result.adjusted_coords.items():
print(f" {point}: X={x:.3f}m, Y={y:.3f}m")
print("=" * 55)
# CLI接口
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='测量平差计算工具')
subparsers = parser.add_subparsers(dest='command', help='子命令')
# 水准平差子命令
level_parser = subparsers.add_parser('level', help='水准平差')
level_parser.add_argument('--data', type=str, required=True, help='观测数据文件')
level_parser.add_argument('--method', type=str, default='distance', choices=['distance', 'station'])
level_parser.add_argument('--grade', type=str, default='', choices=list(LEVEL_TOLERANCE.keys()))
# 导线平差子命令
traverse_parser = subparsers.add_parser('traverse', help='导线平差')
traverse_parser.add_argument('--data', type=str, required=True, help='观测数据文件')
traverse_parser.add_argument('--type', type=str, default='closed', choices=['closed', 'attached'])
traverse_parser.add_argument('--grade', type=str, default='一级', choices=list(TRAVERSE_TOLERANCE.keys()))
args = parser.parse_args()
if args.command == 'level':
print("水准平差功能需配合数据文件使用")
elif args.command == 'traverse':
print("导线平差功能需配合数据文件使用")
else:
parser.print_help()

  • 本工具为基础平差实现,适用于常规工程测量
  • 高精度控制网(如GPS网、精密水准网)建议使用专业平差软件
  • 导线平差未实现坐标闭合差分配,完整功能需扩展
  • 适用于闭合水准路线、附合水准路线
  • 适用于闭合导线、附合导线(简化版)
  • 不适用于支水准路线、支导线(无检核条件)

Q: 闭合差超限怎么办? A: 检查观测记录、计算过程;必要时重测特定测段;检查仪器是否正常。

Q: 如何区分按距离和按测站数分配? A: 平地按距离分配,山地按测站数分配。自动化监测通常按距离。

Q: 导线平差坐标闭合差如何分配? A: 按边长比例分配,本工具需扩展实现完整坐标平差。



#测量平差 #条件平差 #间接平差 #闭合差 #精度评定 #水准测量 #导线测量 #Python工具 #RailWise


文档版本: 1.0.0 | 最后更新: 2026-06-10 | 作者: RailWise技术团队

引用与复核把知识带回真实工程判断

引用时保留页面与来源线索;涉及标准条文、阈值、频率和项目结论,请回到现行依据与责任人复核。

查看 Agent 使用规则