经纬志
首页 / 实战手册 / 坐标与投影

UTM 带号差 1,西安的点位横向偏了 551 公里

先看结论

数据按 49 带投影,地图却声明成 50 带,点位整体东移半个省。

最后验证 2026-11-03 · 多技术栈 · 更新 2026-10-29 · 引用本文

现象

西安钟楼 108.940174, 34.341568。正确带号是 49(EPSG:32649,中央经线 111°E), 投影结果约为 x = 308600, y = 3804900。 实际数据被错误地按 50 带(EPSG:32650,中央经线 117°E)投影, 得到 x = -241300, y = 3804900,负值被写入数据库时还常常被截断成 0。

如果把 49 带的 x = 308600 拿到声明为 32650 的地图上渲染, 按 50 带的定义,这个 x 表示中央经线以西 191.4 公里(117°E - 1.9° ≈ 115.1°E), 点位落到山西吕梁一带,横向偏差 551 公里,纵向几乎不变。

原因

UTM 按 6 度分带,带号 n = floor(lon / 6) + 31(东经为正)。 每差一个带号,中央经线差 6 度。北纬 34° 处 1 度经差约 91.9 公里, 6 度就是 551 公里,正好等于观测到的偏移量。

常见的错法有两种:一是把带号按 floor(lon/6) 计算,少加了 31; 二是数据在 49 带、服务配置成 50 带,两边各写对了一半,合起来就错。

// 带号计算:西安经度 108.940174
Math.floor(108.940174 / 6) + 31;   // 49  <- 正确
Math.floor(108.940174 / 6);        // 18  <- 少了 +31,EPSG:32618 是大西洋

// 中央经线
const zone = 49;
const cm = zone * 6 - 183;         // 111  (度)

排查过程

  1. 看 x 值。UTM 的假东是 500000,正常数据 x 在 160000~840000,超出这个范围就会跨带。
  2. 用 y 值反推纬度,确认纵向没问题,说明只是带号错而不是整体错。
  3. 用经度算一次带号,与图层声明的 EPSG 码比对。
  4. 把同一个点用相邻带的 EPSG 码投影两次,看哪一次的 x 更接近 500000,那一带才是正确的。
// proj4js 逐带试算,找 x 最接近 500000 的带
for (let z = 47; z <= 51; z++) {
  const epsg = 'EPSG:326' + z;
  const [x, y] = proj4('EPSG:4326', epsg, [108.940174, 34.341568]);
  console.log(z, x.toFixed(0), y.toFixed(0));
}
// 48:  -360400  3805200
// 49:   308600  3804900   <- 距 500000 最近
// 50:  -241300  3804900

解决方案

按数据实际所在的带号声明坐标系,不要按「省」或「项目名」去套。 一批数据跨越两个带时,应按带分文件存储,或在入库前统一转成经纬度。

// GeoServer 图层声明(正确的写法)
<nativeCRS>EPSG:32649</nativeCRS>
<srs>EPSG:32649</srs>

// proj4js 显式定义,避免只写 32649 时依赖内置表
proj4.defs('EPSG:32649',
  '+proj=utm +zone=49 +datum=WGS84 +units=m +no_defs');

proj4('EPSG:4326', 'EPSG:32649', [108.940174, 34.341568]);
// => [308600, 3804900]

验证

投影后 x 应落在 160000~840000,该点的 x=308600、y=3804900。 再反向投影回 4326,应回到 108.9402, 34.3416,往返误差小于 1e-6 度。

const back = proj4('EPSG:32649', 'EPSG:4326', [308600, 3804900]);
console.assert(Math.abs(back[0] - 108.940174) < 1e-4, '带号仍不对');
console.assert(back[1] > 34 && back[1] < 35, '纬度不在陕西');

适用版本

工具版本说明
proj4js2.9 及以上EPSG:326xx(北半球)/ 327xx(南半球)内置
GeoServer2.20 及以上nativeCRS 与实际投影必须一致
QGIS3.28 及以上可用「重投影图层」把 x 负值暴露出来
引用本文

经纬志(2026)。《UTM 带号差 1,西安的点位横向偏了 551 公里》。https://www.jingweizhi.com/cookbook/utm-zone-off-by-one.html(访问日期 2026-11-03)。