GIS 相关

GIS 相关概念介绍,包括坐标系、正射影像图等地理信息系统基础知识

简介

简单的介绍 GIS 系统中,各种坐标系的概念。

正射影像图

在局部区域(如几平方公里),地球曲率影响很小,用平面坐标近似球面坐标,可以方便测量、展示。正射影像正是利用这种局部近似,在有限范围内实现“图像即地图”。

正射影像的核心是消除畸变。普通航拍影像只是“拍照”,存在透视畸变(比如高楼倾斜)。正射影像通过数字高程模型(DEM)和摄影测量算法,逐像素校正这些畸变。结果是:每个像素都像是从正上方垂直拍摄的,并且有准确的平面坐标。

• 定义:正射影像图,orthophoto map,简称 DOM。
• 特点:
• 无畸变(像素位置和地面坐标一一对应)
• 可直接量测(可以量距离、面积等,结果和地图一致)
• 保留了影像的纹理信息(不像矢量图那样抽象)
来源 空间分辨率(像素大小) 定位精度(几何精度) 应用场景
卫星影像(商业高分) 0.3–2 m 1–5 m 区域级规划
航空摄影 10–50 cm 20–100 cm 城市级测绘
无人机航测 2–10 cm 5–20 cm 工程、矿山、大坝

精度一般要求:

  • 平面精度 ≈ 影像分辨率的 1–2 倍
  • 高程精度 ≈ 分辨率的 2–3 倍

例如:分辨率 5 cm 的无人机 DOM,平面精度可以做到 5–10 cm。

坐标系

在测绘、GNSS 定位等领域,有很多的坐标系。

对于本次项目,我们会涉及到多种坐标系:

  • 大坝坐标系:仅用于本次 GNSS 位移监测的“大坝坐标系”,原点就是本次选定的基准点(GNSS 站心);通过一次旋转把 ENU → (ΔX坝, ΔY坝, ΔZ坝) 即可使用,因此它是一种非常局部的、临时的小坐标系。→ 仅解决“本次监测位移”这一件事;
  • EPSG:4544(CGCS2000 / 3° Gauss-Krüger 120°E)是整个工程项目采用的官方投影坐标系;原点在国家规范里(120°E 与赤道交点西移 500 km);用于全坝段、全生命周期的图纸、施工、验收、档案;解决“整个大坝工程所有几何信息”的统一基准。
  • EPSG:3857,当正射影像图需切片在地图上显示的时候,需要用 EPSG:3857 这个坐标系。因为电子地图普遍都是这个坐标系。
  • 数据存储通常用 4326,显示/切片时转为 3857。
坐标系 原点 轴向 用途
ECEF 地球质心 三维直角坐标系。 X→本初子午线赤道交点,Z→北极。 卫星导航、全球定位
大地坐标系 地球表面 球面坐标系。 纬度 0°:赤道;经度 0°:格林尼治本初子午线– 高程 0 m GNSS原始数据 ,EPSG:4326 和 EPSG:4490 都属于大地坐标系
投影坐标系 地表某点 二维平面坐标系。 如 EPSG:4544,EPSG:3857
ENU 地表某点 局部站心直角坐标系。E→东,N→北,U→天顶 局部工程监测(如大坝、滑坡)
  • ECEF(Earth-Centered, Earth-Fixed)即“地心地固坐标系”,是一个 全球三维直角坐标系,随地球一起旋转,因此地面固定点的坐标不会随时间变化。任意点 P 用一组笛卡尔坐标 (X, Y, Z) 表示,单位为米。
    • 计算简单:直角坐标便于距离、矩阵运算。
    • 全球统一:卫星导航(GPS、北斗)、航天器轨道、3D Tiles、Cesium 三维地球均默认 ECEF
  • ENU (East-North-Up)坐标系是一种局部直角坐标系,需通过原点(lat₀, lon₀, h₀)(如监测点初始位置)将大地坐标转换为ENU。特点是:
    • 1、直观:东、北、天顶方向与日常地理方向一致,便于工程人员理解。
    • 2、局部精度高:在几十公里范围内,ENU坐标系可近似为平面直角坐标,忽略地球曲率误差。
    • 3、方便旋转:后续转换到大坝坐标系时,只需绕U轴旋转一个角度(γ)即可。常用于局部工程监测。

如何选择,取决于应用范围和数据提供方:

  • 国家级测绘 / 工程测量:CGCS2000(EPSG:4490 / 4544 / 4554 等投影坐标)
  • 全球数据 / 卫星影像:WGS84(EPSG:4326,或者投影成 UTM 坐标系)
  • 工程局部坐标: 方便施工/监测的小范围坐标系,一般是投影坐标经过 平移+旋转 得到。需定义坐标系的原点和方向

常用 EPSG 坐标系

  • EPSG 原指 European Petroleum Survey Group。是目前 GIS 软件中最权威的坐标系数据库
坐标系 介绍
EPSG:4326 (WGS84 经纬度坐标) 地理坐标系,和 CGCS2000 很像,只是基准不同。误差很小,普通应用中基本可以互换)。很多国际数据源都用这个。
EPSG:3857(WGS84 投影坐标系) 墨卡托(Mercator)投影,(单位米)。投影公式按球面计算,因而两极无限放大。仅用于 Web 切片地图,严禁距离、面积量算。
EPSG:4490 (CGCS2000 经纬度坐标) CGCS2000 原始定义,大地基准,单位:度(经纬度)。官方规定的大地坐标系统。注意 4490 是地理 2D 坐标(纬度、经度,单位度);高程不属于 4490 本身的定义。
EPSG:4544 (CGCS2000 投影坐标系) EPSG:4490 基础上采用 3 度带高斯-克吕格投影,中央经线 105°E。投影坐标系(Projected CRS),坐标单位是 米,常用于测绘、工程建设。

投影坐标系

“带号”可以理解为给 地球东西方向上划分的“3° 宽带子”编的号码,目的是:让 500 km 左右宽的一条窄带里,平面坐标尽量接近真实距离。每 3° 一条带子,带号对应经度区间。中国本土大约覆盖 带 24 – 45(中央经线 72°E – 135°E)。

地理坐标系的原点是 纬度 0° = 赤道, 经度 0° = 格林尼治本初子午线 ,高程 0 m = 只是椭球面的数学定义,不一定对应真实海平面或陆地表面。

每个投影坐标系(对应高斯带号),都有自己的“人工原点”——中央经线+赤道交点再西移 500 km;带号不同,原点对应的地球位置不同,但投影坐标值始终从 (500 000 m, 0 m) 起算。

中国官方规定的大地坐标系统是 CGCS2000 系列,但测绘成果报审必须给出 3°/6° 带高斯投影(按所在经度选带号),不能直接把 4490 经纬度当成果交。
不带带号的图必须用文字注明中央经线或带号,否则 10 年后资料混档,两个“485 123”无法区分是哪一带。
任何跨省、跨市、GIS 库集成场景,一律用带号版——“长坐标”是自我描述的数据,不带号就是裸数据。
经度区间 带号 中央经线 带号版 EPSG 无带号版 EPSG 备注
73.5°E–76.5°E 25 75°E 4513 4534 新疆最西端
76.5°E–79.5°E 26 78°E 4514 4535 南疆
79.5°E–82.5°E 27 81°E 4515 4536 南疆-西藏
82.5°E–85.5°E 28 84°E 4516 4537 西藏
85.5°E–88.5°E 29 87°E 4517 4538 西藏
88.5°E–91.5°E 30 90°E 4518 4539 青海
91.5°E–94.5°E 31 93°E 4519 4540 青海-西藏
94.5°E–97.5°E 32 96°E 4520 4541 青海
97.5°E–100.5°E 33 99°E 4521 4542 云南西北
100.5°E–103.5°E 34 102°E 4522 4543 云南-四川西南
103.5°E–106.5°E 35 105°E 4523 4544 川北-重庆-黔北
106.5°E–109.5°E 36 108°E 4524 4545 贵州-广西
109.5°E–112.5°E 37 111°E 4525 4546 湖南-湖北
112.5°E–115.5°E 38 114°E 4526 4547 广东-江西-河南
115.5°E–118.5°E 39 117°E 4527 4548 福建-浙江-安徽
118.5°E–121.5°E 40 120°E 4528 4549 长三角
121.5°E–124.5°E 41 123°E 4529 4550 东北东部
124.5°E–127.5°E 42 126°E 4530 4551 东北
127.5°E–130.5°E 43 129°E 4531 4552 黑龙江东
130.5°E–133.5°E 44 132°E 4532 4553 黑龙江最东
133.5°E–136.5°E 45 135°E 4533 4554 黑龙江抚远

地图如何显示

如果你的正射影像图最终要发布成 在线地图切片,通常流程就是:

  • 原始影像 → EPSG:4326/WGS-84(或 EPSG:4544 等工程坐标)
  • 用 gdalwarp 或 QGIS 一次性重投影到 EPSG:3857
  • 再用 gdal2tiles、MapProxy、GeoServer 等切成 3857 瓦片并发布

适用于电子地图显示的 EPSG:3857 就是“Web 墨卡托投影”,米为单位。成为 Web 地图事实标准(Google Maps、OpenStreetMap、Mapbox、Leaflet 等默认底图坐标系)

  • Web Mercator 把地球先当成一个 球(而不是更精确的椭球),再把球面投影到一个 圆柱面,最后展开成平面。
  • 该投影是 等角(保形) 的,(形状、方向保持不变),因此 纬线方向的尺度随纬度急剧放大(误差来自 投影公式本身)。
  • 方便在二维画布或 WebGL 里直接做平移、缩放、距离量算。计算简单,浏览器/移动端渲染效率高。对导航、定位、路径规划最直观。
  • Web Mercator 投影把地球切成 256×256 像素的正方形瓦片,层级递增,浏览器加载逻辑固定,缓存复用率高

我们拿到三个文件:tif 文件、prj文件、tfw 文件。其中 tif 文件介绍如下:

常见的 正射影像图数据格式:GeoTIFF (.tif):最常见的格式,TIFF 影像 + 内嵌空间参考信息。外加一个 .tfw / .prj 文件(如果是裸 TIFF 没内嵌坐标时)。 正射影像图(Orthophoto)的 .tif 文件是一种地理空间栅格格式(GeoTIFF)。它把 普通图像内容 和 空间定位信息 同时封装在一个文件里,因此既能像 PNG/JPG 那样看图,又能像地图那样精确量测坐标。

类别 内容 存储方式 备注
栅格图像数据 每个像素的灰度/颜色值 按行或按瓦片(Tile)存储 相当于 PNG 的“图片”
空间定位信息 仿射变换参数(6 个系数)或 RPC 系数 GeoTIFF 标签(Tag 33922、33550、34737 等) 告诉软件:像素 (i,j) ↔ 地面 (E,N) 的数学关系
坐标系/投影信息 EPSG 代码、WKT 投影字符串 GeoTIFF 标签 GeoKeyDirectory(Tag 34735) 例如 EPSG:4490、EPSG:32650

prj文件:就是对 EPSG-4544 的一段标准定义

PROJCS["CGCS2000 / 3-degree Gauss-Kruger CM 105E",GEOGCS["China Geodetic Coordinate System 2000",DATUM["China_2000",SPHEROID["CGCS2000",6378137,298.257222101,AUTHORITY["EPSG","1024"]],AUTHORITY["EPSG","1043"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4490"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",105],PARAMETER["scale_factor",1],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","4544"]]


名称 "CGCS2000 / 3-degree Gauss-Kruger CM 105E"
表示这是以 CGCS2000 大地坐标系(中国大地2000坐标系)为基础,采用 3度带高斯-克吕格投影(中央经线105°E) 的投影坐标系( 高斯-克吕格投影是一种将地球椭球面上的地理坐标(经纬度)正形投影到二维平面上的方法)。

GEOGCS[“China Geodetic Coordinate System 2000”, …]
表明其大地基准是 CGCS2000,是中国国家级大地坐标系,跟 WGS84 接近。


DATUM[“China_2000”, SPHEROID[“CGCS2000”,6378137,298.257222101]]
基准面采用椭球体参数:长半轴 = 6378137 m,扁率倒数 = 298.257222101。这是标准的 CGCS2000 椭球。


PROJECTION[“Transverse_Mercator”]
横轴墨卡托投影(高斯-克吕格就是横轴墨卡托的一个实现)。

latitude_of_origin = 0 → 投影起始纬度为赤道
central_meridian = 105 → 中央经线是东经 105°
scale_factor = 1 → 投影比例因子 1.0
false_easting = 500000 → 假东距 500km(防止出现负坐标)
false_northing = 0 → 假北距 0

UNIT[“metre”,1]
投影结果的单位是米。

AUTHORITY[“EPSG”,“4544”]
EPSG 编号 4544,对应 CGCS2000 / 3-degree Gauss-Kruger zone 35(中央经线105°E)


以上信息说明:EPSG:4544 投影坐标系的“原 点”对应 (105°E, 0°N),中央子午线与赤道的交点,X轴:中央子午线的投影。Y轴:赤道的投影。
但因为约定俗称,要有 false easting = 500,000 m,所以这个点在平面上是 (500000, 0)
在这个投影坐标系上,正射影像上每个像素的坐标确实是以 米为单位的 (E,N)。所以,如果输出的位置给了 (E、N)这样的坐标,需要转换成 EPSG:4490 才能用于地图显示。使用 gdal 工具:

# 使用 gdaltransform(把 E N 放在 stdin)
echo "605732.799 3999843.061 1623.661" | gdaltransform -s_srs EPSG:4544 -t_srs EPSG:4490
# 通常输出:<lon> <lat> <h>

总结,这段文件是:

EPSG:4544 的完整投影坐标系描述(WKT 与关键参数) EPSG:4544 的官方名称如下:

CGCS2000 / 3-degree Gauss-Kruger CM 105E , 中文习惯叫“国家 2000,三度分带,中央经线 105°E,坐标不含带号”。
投影方法:横轴墨卡托(Transverse Mercator,EPSG 代码 9807)。
核心参数:
中央经线(Longitude of natural origin):105°E
原点纬度(Latitude of natural origin):0°
比例因子(Scale factor):1.0
假东移(False easting):500 000 m
假北移(False northing):0 m
线性单位:米(EPSG:9001)

椭球体与基准
基于 China Geodetic Coordinate System 2000(EPSG:4490):
椭球:CGCS2000
长半轴 a = 6 378 137 m
扁率 1/f = 298.257 222 101

适用区域
中国陆上 103°30′E – 106°30′E 之间的狭长条带

tfw 文件: TFW 文件(通常和 .tif 配套使用,叫 World File)就是一个 栅格影像的空间参考文件。它的作用是告诉 GIS 软件:这张图像(.tif)应该放到地图上的哪个位置,缩放和旋转关系如何。

0.037220000000
0
0
-0.037220000000
602832.567790000001
4001299.158060000278

Line 1: 像素大小(X 方向,每像素宽度,单位:地图坐标单位)
Line 2: 行旋转参数(一般为 0)
Line 3: 列旋转参数(一般为 0)
Line 4: 像素大小(Y 方向,注意通常是负值,因为影像行号向下而坐标系 Y 轴向上)
Line 5: 左上角像素中心的 X 坐标
Line 6: 左上角像素中心的 Y 坐标

此内容说明:图片的像素大小是 每个像素长宽是 0.03722 米,3.7 厘米/像素。
左上角位置在 投影坐标系下的 (602832.57, 4001299.16),单位米。

高程

高程也有多种

名称 定义 基准面 与水准测量的关系 典型数值差异
椭球高(Ellipsoidal Height, h 某点沿椭球法线到参考椭球面的距离 数学椭球面(CGCS2000、WGS-84 等) 与水准测量无直接关系 在中国区域通常比正高高 30 m 左右(可正可负)
正高(Orthometric Height, H 某点沿铅垂线到大地水准面(平均海水面)的距离 大地水准面(似大地水准面) 就是日常“海拔高程”,用水准仪测得 与椭球高的关系:h = H + NN 为大地水准面差距)

在一般的土木、水利、交通等工程里,“高程”默认指的就是正高(或我国采用的正常高),也就是“海拔高”;只有在做 GNSS/GPS 测量、坐标转换或与卫星数据打交道时,才会先拿到椭球高,随后必须再换算成正高才能用于设计、施工、监测。

为什么工程图纸上不写“椭球高”

  • 设计、施工、监测都要与水准点、水位、防洪高程、结构限界等对比,而这些数据全部由水准测量给出,属于 1985 国家高程基准(正常高系统)。
  • 椭球高与正常高在我国差值可达 20–40 m,直接用会导致坝顶高程、桥墩标高、隧道埋深等统统错位。

因此,《工程测量规范》《水利水电工程测量规范》等所有行业规范均明确规定:最终成果必须归算到 1985 国家高程基准(正常高)。

如果用中国区域大地水准面模型(如 CNGG2015、CQG2000 或各省精化模型)把每个监测点的椭球高 h 改正为正高 H:
H = h − N
其中 N 为大地水准面差距,是基于电子格网文件做差值计算得到。

切片格式

最常用的三种栅格地图切片标准——TMS、WMTS、XYZ 对比:

方面 TMS (Tile Map Service) WMTS (Web Map Tile Service) XYZ (a.k.a. “Slippy Map” / “Google XYZ”)
标准组织 OSGeo(开源) OGC(开放地理空间联盟) 事实标准(Google、OSM、Mapbox 等)
协议形式 REST(纯 HTTP GET) 支持三种:KVP、SOAP、REST REST(最简 GET)
元数据接口 /tilemapresource.xml 描述层级、范围、原点、像素尺寸 标准 GetCapabilities(XML) 无官方元数据接口(靠文档或代码写死)
原点 & 轴向 左下角原点;Y 从下往上递增(0,1,2…) 左上角原点;Y 从上往下递增(0,1,2…) 与 WMTS 相同:左上角原点,Y 向下
URL 模板示例 http://host/tms/1.0.0/layer/z/x/y.png REST 形式:
…/wmts?layer=xxx&TileMatrix=z&TileRow=y&TileCol=x
https://host/{z}/{x}/{y}.png
坐标系/投影 任意,但默认 Web Mercator(EPSG:3857) 任意,通过 TileMatrixSet 显式声明 绝大多数是 Web Mercator;少量 WGS84
图块尺寸 256×256 或 512×512(XML 里声明) 256×256 常见,也可自定义 256×256 最常见
文件/图片格式 PNG、JPEG PNG、JPEG、GIF、TIFF 等 PNG、JPEG
缓存友好度 极高(静态目录即可托管) 高(支持 HTTP 缓存头) 极高(CDN 最爱)
客户端示例 Leaflet、OpenLayers、MapProxy Leaflet、OpenLayers、ArcGIS API Leaflet、Mapbox GL、Cesium、OpenLayers
易踩的坑 y 轴方向与 XYZ 相反,需要 y = (2^z - 1) - y_tms 转换 Capabilities XML 较冗长,解析略麻烦 无官方规范,不同厂商可能在原点、Z 起点上“魔改”

一句话总结

  • TMS:目录结构简单,Y 轴从下往上,适合离线包或静态服务器。
  • WMTS:OGC 标准,功能最全(多投影、多格式、GetFeatureInfo),但调用稍重。
  • XYZ:最轻量、最流行,Y 轴向下,URL 模板一目了然,几乎所有现代地图 SDK 都默认支持。

脚本工具

主要使用 gdal 工具,比较快。用 GIS 桌面工具安装麻烦,而且速度很慢。

1、查看 tif 文件信息:说明 tif 内置了空间定位信息(也就是 prj 和 tfw 的信息)

$ gdalinfo  dzh.tif

Driver: GTiff/GeoTIFF
Files: dzh.tif
Size is 86842, 67258
Coordinate System is:
PROJCRS["CGCS2000 / 3-degree Gauss-Kruger CM 105E",
    BASEGEOGCRS["China Geodetic Coordinate System 2000",
        DATUM["China 2000",
            ELLIPSOID["CGCS2000",6378137,298.257222101,
                LENGTHUNIT["metre",1]]],
        PRIMEM["Greenwich",0,
            ANGLEUNIT["degree",0.0174532925199433]],
        ID["EPSG",4490]],
    CONVERSION["Gauss-Kruger CM 105E",
        METHOD["Transverse Mercator",
            ID["EPSG",9807]],
        PARAMETER["Latitude of natural origin",0,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8801]],
        PARAMETER["Longitude of natural origin",105,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8802]],
        PARAMETER["Scale factor at natural origin",1,
            SCALEUNIT["unity",1],
            ID["EPSG",8805]],
        PARAMETER["False easting",500000,
            LENGTHUNIT["metre",1],
            ID["EPSG",8806]],
        PARAMETER["False northing",0,
            LENGTHUNIT["metre",1],
            ID["EPSG",8807]]],
    CS[Cartesian,2],
        AXIS["northing (X)",north,
            ORDER[1],
            LENGTHUNIT["metre",1]],
        AXIS["easting (Y)",east,
            ORDER[2],
            LENGTHUNIT["metre",1]],
    USAGE[
        SCOPE["Cadastre, engineering survey, topographic mapping (large scale)."],
        AREA["China - between 103°30'E and 106°30'E."],
        BBOX[22.5,103.5,42.21,106.51]],
    ID["EPSG",4544]]
Data axis to CRS axis mapping: 2,1
Origin = (602832.567790000000969,4001299.158060000278056)
Pixel Size = (0.037220000000000,-0.037220000000000)
Metadata:
  TIFFTAG_SOFTWARE=pix4dmapper
  AREA_OR_POINT=Area
Image Structure Metadata:
  COMPRESSION=LZW
  INTERLEAVE=PIXEL
  PREDICTOR=2
Corner Coordinates:
Upper Left  (  602832.568, 4001299.158) (106d 8'32.85"E, 36d 8'11.59"N)
Lower Left  (  602832.568, 3998795.815) (106d 8'31.68"E, 36d 6'50.39"N)
Upper Right (  606064.827, 4001299.158) (106d10'42.11"E, 36d 8'10.34"N)
Lower Right (  606064.827, 3998795.815) (106d10'40.89"E, 36d 6'49.13"N)
Center      (  604448.697, 4000047.487) (106d 9'36.88"E, 36d 7'30.37"N)
Band 1 Block=86842x1 Type=Byte, ColorInterp=Red
  Mask Flags: PER_DATASET ALPHA
Band 2 Block=86842x1 Type=Byte, ColorInterp=Green
  Mask Flags: PER_DATASET ALPHA
Band 3 Block=86842x1 Type=Byte, ColorInterp=Blue
  Mask Flags: PER_DATASET ALPHA
Band 4 Block=86842x1 Type=Byte, ColorInterp=Alpha

2、 重投影为 EPSG:3857

GeoTIFF 文件已经带了 坐标系 (EPSG:4544) 信息。因为要生成网页上显示的切片,需要投影为 EPSG:3857 坐标系:

gdalwarp -t_srs EPSG:3857 \
  -tr 1 1 \
  -r bilinear \
  -of GTiff \
  -co COMPRESS=DEFLATE \
  -co TILED=YES \
  -dstalpha \
  input.tif output_3857.tif

说明:

-t_srs EPSG:3857 :投影到 Web 墨卡托。
-tr 1 1 :设置输出分辨率为 1 米 × 1 米(在 EPSG:3857 的单位是米)。建议先用 gdalinfo input.tif | grep "Pixel Size" 看一下原始像元大小,再决定 -tr。
-r bilinear :双线性插值,适合连续值(影像类数据),如果是分类数据(如土地利用),建议用 -r near。
-of GTiff :输出 GeoTIFF。
-co COMPRESS=DEFLATE :压缩。
-co TILED=YES :块存储,利于快速切片。
-dstalpha :生成透明通道(让无数据区域透明)。

3、切片

gdal2tiles.py -z 0-18 -r bilinear -p mercator -a 0 \
  --processes=4 warped.tif tiles/ --tilesize=256 --tiledriver=PNG

GNSS位移量计算

有的 gnss 设备上报的数据是 大小+水平角+垂直角,需要转换成相对位移,并且还要映射到大坝坐标系。

大坝坐标系定义说明: Y轴 : 平行于坝轴线,面朝上游,右侧为正,左侧为负。 X轴 : 垂直于坝轴线,下游为正,上游为负。 Z轴 : 垂直于地面,向上为正,向下为负。

在坝轴上取两个点,计算 Y 轴与正北方的 位角 θ。可以得到一个关键信息,来定义大坝坐标系。

原理解析

根据我们的大坝坐标系定义:

• Y 轴:沿坝轴线,面向上游,右侧为正(即轴指向下游)。 • X 轴:垂直坝轴线,下游为正。 • Z 轴:向上为正。

ENU → 大坝坐标系的旋转矩阵 R 如下:

      ⎡  cosθ   sinθ   0 ⎤
R  =  ⎢ –sinθ   cosθ   0 ⎥
      ⎣   0       0    1 ⎦

计算公式:

|ΔX坝|   | cosθ   sinθ   0 |   |ΔE|
|ΔY坝| = |-sinθ   cosθ   0 | · |ΔN|
|ΔZ坝|   |  0      0     1 |   |ΔU|

即

ΔX坝 =  ΔE·cosθ + ΔN·sinθ
ΔY坝 = –ΔE·sinθ + ΔN·cosθ
ΔZ坝 =  ΔU

转换代码

计算水平方位角的 python 代码:

θ = atan2(ΔE, ΔN) (0° 指北,90° 指东,顺时针增加),θ 就是坝轴在水平面内与正北的夹角。

import math
from pyproj import Proj, Transformer

# 输入:两端点经纬度(度)
# lat1, lon1 = 36.134616757252154,106.13848686218262
# lat2, lon2 = 36.13080407775483,106.18852615356447

lat1, lon1 = 36.13822130205884,106.17324829101564
lat2, lon2 = 36.11617553449072,106.17470741271974

# 定义 CGCS2000 / 3-degree Gauss-Kruger 投影
# 这里假设中央子午线为 105E
proj = Proj(proj='tmerc', lat_0=0, lon_0=105, k=1, x_0=500000, y_0=0, ellps='GRS80')

# 经纬度转平面坐标
x1, y1 = proj(lon1, lat1)
x2, y2 = proj(lon2, lat2)

# 坝轴向量
dx = x2 - x1
dy = y2 - y1

# 计算方位角 θ(顺时针从正北算起)
theta_rad = math.atan2(dx, dy)  # 注意 dx 对应东向,dy 对应北向
theta_deg = math.degrees(theta_rad)
if theta_deg < 0:
    theta_deg += 360

print(f"坝轴方位角 θ = {theta_deg:.3f}°")%

// GNSS设备上报的数据。
/*
"data":"{
	"lat":36.123160717,
	"lon":106.17444795,
	"alt":1620.93103,
	"drft":0.0047,
	"drfH":270,
	"drfV":0,
	"mod":4,
	"pow":12.3,
	"RSSI":22,
	"clientId":"sv78dRYjrD1eICq51QcD",
	"detectedTime":"2025-08-11 13:31:32"
}
drft 是位移大小,单位是米(m),两个点之间的间距
drfH 是水平角,单位是度(°),这里假设角度是以正北为0度,顺时针方向
drfV 是垂直角,单位是度(°),正值表示向上仰角,负值表示向下

drft = 位移大小(径向距离 r)
drfH = 水平方位角(θ,北 0° 顺时针)
drfV = 垂直仰角(φ,水平 0°,上正下负)

位移量,单位米
水平角度,单位度,此角度为设备所在水平面的位移方向,正北为0度,按顺时针增大,正东为90度
垂直角度,单位度,此角度为设备所在垂直方向的位移方向,水平为0度,向下最大垂直方向-90度,向上最大垂直方向90度
*/


// 位移(大小+水平角+垂直角) 转换为 ENU 三维向量
// drft 单位 m,drfH 水平角(°,北0°顺时针),drfV 垂直角(°,正上仰角)
// (北+、东+、上+),相反是负的

// 球面位移转 ENU
func PolarToVector(drft, drfH, drfV float64) (dN, dE, dU float64) {
	// 角度转弧度
	hRad := drfH * math.Pi / 180.0
	vRad := drfV * math.Pi / 180.0

	// 分解
	hLen := drft * math.Cos(vRad) // 水平投影
	dE = hLen * math.Sin(hRad)    // 东向   	  E (East):向东(经度增大的方向)
	dN = hLen * math.Cos(hRad)    // 北向       N (North):向北(纬度增大的方向)
	dU = drft * math.Sin(vRad)    // 垂直分量    U (Up):向上(椭球面法线方向,即大地高程方向)

	// x, y z := dE,dN, dU

	return
}


// ENU 转大坝坐标系
// Y轴:沿坝轴线方向,面朝上游,右侧为正,左侧为负
// X轴:垂直于坝轴线,下游为正,上游为负
// Z轴:竖直向上

func VectorToDam(dN, dE, dU, theta float64) (dX, dY, dZ float64) {
	// θ = 坝轴线相对正北的方位角,顺时针为正
	thRad := theta * math.Pi / 180.0

	// 沿坝轴方向 → Y
	dY = dN*math.Cos(thRad) + dE*math.Sin(thRad)

	// 垂直坝轴方向 → X(下游为正)
	dX = -dN*math.Sin(thRad) + dE*math.Cos(thRad)

	// 垂直方向保持不变
	dZ = dU

	return
}
Last updated on September 11, 2025 by 北盛信息