简介
最简单的测绘基础知识介绍。
正射影像图
• 定义:正射影像图,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 定位等领域,有很多的坐标系。
坐标系 | 原点 | 轴向 | 用途 |
---|---|---|---|
ECEF | 地球质心 | X→本初子午线赤道交点,Z→北极 | 卫星导航、全球定位 |
大地坐标系 | 地球表面 | 纬度、经度、高程 | GNSS原始数据 |
ENU | 地表某点 | E→东,N→北,U→天顶 | 局部工程监测(如大坝、滑坡) |
- EPSG 原指 European Petroleum Survey Group。是目前 GIS 软件中最权威的坐标系数据库
- ENU (East-North-Up)坐标系是一种局部直角坐标系,需通过原点(lat₀, lon₀, h₀)(如监测点初始位置)将大地坐标转换为ENU。特点是:1、直观:东、北、天顶方向与日常地理方向一致,便于工程人员理解。2、局部精度高:在几十公里范围内,ENU坐标系可近似为平面直角坐标,忽略地球曲率误差。3、方便旋转:后续转换到大坝坐标系时,只需绕U轴旋转一个角度(γ)即可。常用于局部工程监测。
取决于应用范围和数据提供方:
- 国家级测绘 / 工程测量:CGCS2000(EPSG:4490 / 4544 / 4554 等投影坐标)
- 全球数据 / 卫星影像:WGS84(EPSG:4326,或者投影成 UTM 坐标系)
- 工程局部坐标: 方便施工/监测的小范围坐标系,一般是投影坐标经过 平移+旋转 得到。需定义坐标系的原点和方向
坐标系 | 介绍 |
---|---|
EPSG:4326 (WGS84 经纬度坐标) | 地理坐标系,和 CGCS2000 很像,只是基准不同(误差小于 1m,普通应用中基本可以互换)。很多国际数据源都用这个。 |
EPSG:4490 (CGCS2000 经纬度坐标) | CGCS2000 原始定义,大地基准,单位:度(经纬度)。中国官方规定的大地坐标系统。和 WGS84 椭球误差极小。注意 4490 是地理 2D 坐标(纬度、经度,单位度);高程不属于 4490 本身的定义。 |
EPSG:4544 (CGCS2000 的投影坐标系) | 基础上采用 3 度带高斯-克吕格投影,中央经线 105°E。投影坐标系(Projected CRS),坐标单位是 米,常用于测绘、工程建设。 |
EPSG:3857(WGS84 投影坐标系 | 采用 圆柱等角(正形)投影,(单位米)。把地球近似为 正球体,而非 WGS84 的椭球体。一般用于电子地图。 |
注意:
- 地理坐标系的原点是 纬度 0° = 赤道, 经度 0° = 格林尼治本初子午线 ,高程 0 m = 只是椭球面的数学定义,不一定对应真实海平面或陆地表面。
- 投影坐标系一般是 2D(X、Y) + 高程。原点一般是自己人为定义的(毕竟球面只能在小范围内视为平面).投影平面 0 点的定义(East=0, North=0)。每个投影都有自己的“平面原点”,与真实经纬度或空间直角原点毫无关系。
常见几种投影坐标系的原点定义:
1、高斯-克吕格 / Gauss-Krüger
• 原点取中央经线 L₀ 与 赤道 的交点;
• 为防负坐标,通常把 X 轴西移 500 000 m(中国统一加 500 km,称“东伪偏移”)。
因此中国国内坐标:(X, Y) = (0, 0) 实际在赤道、中央经线以西 500 km 处。
2、UTM
• 原点也是中央经线 L₀ 与赤道交点;
• 规定东伪偏移 500 000 m,北半球北伪偏移 0 m,南半球北伪偏移 10 000 000 m。
所以 UTM Zone 50N 的 (0, 0) 在赤道、117°E 以西 500 km。
3、任意工程独立坐标系
• 设计单位可自定义原点:常选坝轴线左端点、或城市中心某点;
• 通过平移参数 East₀, North₀ 直接给出“该点对应 (0,0)”。
适用于电子地图显示的 EPSG:3857 就是“Web 墨卡托投影”,米为单位。成为 Web 地图事实标准(Google Maps、OpenStreetMap、Mapbox、Leaflet 等默认底图坐标系)
- Web Mercator 把地球先当成一个 球(而不是更精确的椭球),再把球面投影到一个 圆柱面,最后展开成平面。
- 该投影是 等角(保形) 的,(形状、方向保持不变),因此 纬线方向的尺度随纬度急剧放大(误差来自 投影公式本身)。
- 方便在二维画布或 WebGL 里直接做平移、缩放、距离量算。计算简单,浏览器/移动端渲染效率高。对导航、定位、路径规划最直观。
- Web Mercator 投影把地球切成 256×256 像素的正方形瓦片,层级递增,浏览器加载逻辑固定,缓存复用率高
数据存储通常用 4326,显示/切片时转为 3857。
对于单次项目,我们会涉及到多种坐标系:
- 大坝坐标系:仅用于本次 GNSS 位移监测的“大坝坐标系”,原点就是本次选定的基准点(GNSS 站心);通过一次旋转把 ENU → (ΔX坝, ΔY坝, ΔZ坝) 即可使用,因此它是一种非常局部的、临时的小坐标系。→ 仅解决“本次监测位移”这一件事;
- EPSG:4544(CGCS2000 / 3° Gauss-Krüger 120°E)是整个工程项目采用的官方投影坐标系;原点在国家规范里(120°E 与赤道交点西移 500 km);用于全坝段、全生命周期的图纸、施工、验收、档案;解决“整个大坝工程所有几何信息”的统一基准。
- EPSG:3857,当正射影像图需切片在地图上显示的时候,需要用 EPSG:3857 这个坐标系。因为电子地图普遍都是这个坐标系。
地图如何显示
如果你的正射影像图最终要发布成 在线地图切片,通常流程就是:
- 原始影像 → EPSG:4326/WGS-84(或 EPSG:4544 等工程坐标)
- 用 gdalwarp 或 QGIS 一次性重投影到 EPSG:3857
- 再用 gdal2tiles、MapProxy、GeoServer 等切成 3857 瓦片并发布
我们拿到三个文件: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 + N(N 为大地水准面差距) |
在一般的土木、水利、交通等工程里,“高程”默认指的就是正高(或我国采用的正常高),也就是“海拔高”;只有在做 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设备上报的数据。
// DzhGnssRealtimeData 保存dzhGnss设备的最新实时值
type DzhGnssRealtimeData struct {
Lat float64 `json:"lat"` // 纬度
Lon float64 `json:"lon"` // 经度
Alt float64 `json:"alt"` // 海拔高度,单位 m
X float64 `json:"x"` // X方向位移,单位 mm
Y float64 `json:"y"` // Y方向位移,单位 mm
Z float64 `json:"z"` // Z方向位移,单位 mm
Power float64 `json:"power"` // 电压
RSSI int `json:"rssi"` // 信号强度
Timestamp int64 `json:"timestamp"` // Unix时间戳
}
/*
"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
}