外观
坐标系
约 3195 字大约 11 分钟
2024-07-01
只要涉及到地图开发,无论如何关于坐标系的概念是逃不掉的,谁让地球它是个球呢。

地球就像个橘子 不同的坐标系就是不同的剝橘子的方法
这里就不列举国内常用的坐标系及转换方法,大家可以自行百度。
相关GIS的学习资料(含坐标系): GIS基础知识-文档、 GIS基础知识-培训视频
平台内目前支持坐标系类型可以访问 CRS类了解详情。
1. 目前常用GIS坐标系
EPSG:4326坐标系:目前最通用的标准坐标系,平时我们常说的经度纬度多少多少、从GPS 设备、智能手机中取出的数据的坐标系、国际地图提供商使用的坐标系 都是这个坐标系。WGS-84坐标系(World Geodetic System)是一种国际上采用的地心坐标系。坐标原点为地球质心,其地心空间直角坐标系的Z轴指向国际时间局(BIH)1984.0定义的协议地极(CTP)方向,X轴指向BIH1984.0的协议子午面和CTP赤道的交点,Y轴与Z轴、X轴垂直构成右手坐标系,称为1984年世界大地坐标系。这是一个国际协议地球参考系统(ITRS),是目前国际上统一采用的大地坐标系。GPS广播星历是以WGS-84坐标系为根据的。【wgs84需要保证坐标误差最小】
EPSG:3857坐标系:Web Mercator(墨卡托)投影坐标系,该坐标系是由Google 最先发明的。在投影过程中,将表示地球的参考椭球体近似的作为正球体处理(正球体半径 R = 椭球体半长轴 a)。由于墨卡托投影当纬度接近两极时,y值趋向于无穷大,那些“懒惰的工程师”为了方便,就把Y轴的取值范围也限定在X轴相同范围,搞个正方形地图,而形成了Web Mercator 投影。 目前在互联网上,大部分全国公众地图网站均采用此坐标系。【墨卡托最早用来航海,要保证方向误差最小】
EPSG:4490坐标系:2000国家大地坐标系,是我国当前最新的国家大地坐标系,英文名称为China Geodetic Coordinate System 2000,英文缩写为CGCS2000。2000国家大地坐标系是全球地心坐标系在我国的具体体现,其原点为包括海洋和大气的整个地球的质量中心。Z轴指向BIH1984.0定义的协议极地方向(BIH国际时间局),X轴指向BIH1984.0定义的零子午面与协议赤道的交点,Y轴按右手坐标系确定。
- CGCS2000 高斯平面投影坐标系(
EPSG:4491至EPSG:4554):支持CGCS2000 Gauss-Kruger Zone 和 CGCS2000 Gauss-Kruger CM 的3度带和6度带平面投影。【各种投影坐标系为了本区域的面积、长度的测量误差最小】
- CGCS2000 高斯平面投影坐标系(
上面的
EPSG:后面的数字,是WKID,由EPSG组织统一管理(这样避免重复,也具备唯一性),可以在http://epsg.io/网站进行查询了解详情。
👉 CGCS2000 与 WGS84 相差几个厘米,对于一般工程测量,可以认为二者是一致的。
👉 坐标系的更详细讲解可以参阅:GIS基础知识培训
1.1 栅格瓦片图层坐标系的设置
瓦片图层支持配置crs参数来设置坐标系的EPSG值,如crs:"EPSG:4490"
const tdtLayer = new mars3d.layer.TdtLayer({
name: "天地图注记图层",
layer: "img_z",
crs: mars3d.CRS.EPSG4326, // 标识GIS坐标系
})
map.addLayer(tdtLayer)2. 国内的偏移坐标系
通常国外使用的是WGS84的坐标系统,中国使用CGCS2000坐标系统以经纬度的形式来表示地球平面上的某一个位置,这应该是国际共识。 在我国,出于国家安全考虑,国内所有导航电子地图必须使用国家测绘局制定的加密坐标系统,即将一个真实的经纬度坐标加密成一个不正确的经纬度坐标,我们在业内将前者称之为地球坐标,后者称之为火星坐标(GCJ-02)。 当我们使用的数据和服务不同时,就产生了我们时常说的偏移和纠偏的问题。
国内偏移坐标系的分类,我们定义在 ChinaCRS类
WGS84坐标系:地球坐标系,目前国际通用的标准坐标系,通常称呼为标准无偏坐标系。
GCJ02坐标系:在我国,出于国家安全考虑,国内所有导航电子地图必须使用国家测绘局制定的加密坐标系统,即将一个真实的经纬度坐标加密成一个不正确的经纬度坐标,我们在业内将前者称之为地球坐标,后者称之为火星坐标(GCJ-02)。。
BAIDU坐标系:百度(BD09) 偏移坐标系,百度在国测局坐标基础二次加密后形成的坐标系。
2.1 栅格瓦片图层偏移坐标系的设置
瓦片图层支持配置chinaCRS参数来设置ChinaCRS,如chinaCRS:"GCJ02"
const tileLayer = new mars3d.layer.XyzLayer({
name: "电子地图",
type: "xyz",
url: "https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
subdomains: "1234",
chinaCRS: mars3d.ChinaCRS.GCJ02 // 标识国内偏移坐标系
})
map.addLayer(tileLayer)2.2 矢量数据坐标的加偏或纠偏转换
const graphicLayer = new mars3d.layer.GeoJsonLayer({
name: "纠偏后",
url: "https://data.mars3d.cn/file/geojson/areas/340303.json",
chinaCRS: mars3d.ChinaCRS.GCJ02, // 标识数据坐标,内部会纠偏
flyTo: true
})
map.addLayer(graphicLayer)- 也提供了PointTrans类 ,可以对 百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、WGS84坐标系 的坐标 进行互相转换,在加载Graphic数据前按需转换坐标。
const wgsPoint = mars3d.PointTrans.gcj2wgs([point.lng, point.lat]) // 转换为WGS84坐标
const graphic = new mars3d.graphic.BillboardEntity({
position: [wgsPoint[0], wgsPoint[1], point.alt],
style: {
image: "https://data.mars3d.cn/img/marker/lace-blue.png"
}
})
graphicLayer.addGraphic(graphic)3. 坐标系速查与选型
3.1 常用坐标系速查表
| 坐标系 | 传参写法 | 坐标形式 | 典型使用场景 |
|---|---|---|---|
| WGS84 地理坐标系 | crs: "EPSG:4326" 或 mars3d.CRS.EPSG4326 | 经纬度(度) | GPS 设备数据、GeoJSON、天地图 c 系列瓦片 |
| Web 墨卡托投影 | crs: "EPSG:3857" 或 mars3d.CRS.EPSG3857 | 平面米(Web 墨卡托) | 高德、百度、OSM 等互联网瓦片 |
| CGCS2000 地理坐标系 | crs: "EPSG:4490" 或 mars3d.CRS.EPSG4490 | 经纬度(度) | 国内天地图 2000 坐标系瓦片、政务数据 |
| CGCS2000 高斯投影(3度带/6度带) | mars3d.CRS.CGCS2000_GK_Zone_3、mars3d.CRS.CGCS2000_GK_Zone_6 | 平面米(X 北 / Y 东) | 工程测量、CAD 图纸、地方坐标系数据 |
| 平台默认(内部无偏 WGS84) | 不传(默认) | 经纬度(度) | 平台内部统一坐标,推荐业务代码使用 |
瓦片图层支持通过
crs参数(见 BaseTileLayer)指定 EPSG 值,最常用的写法是字符串形式crs: "EPSG:4490",加载方里网/大地 2000 瓦片时必须指定,否则会出现瓦片错位或空白。
3.2 选型建议
- 业务代码统一使用经纬度:平台上所有图层、矢量对象的
position都推荐使用[经度, 纬度, 高度](无偏 WGS84),只有"接入别人的瓦片/数据"时才需要声明crs与chinaCRS。 - "我得知道对方是什么坐标系":拿到一份瓦片服务或数据时,先确认它的坐标系与偏移类型,再分别配置
crs(投影/地理)与chinaCRS(国内偏移),这两个参数是正交的、可以同时设置。 - 不要手工加偏移量:偏移与纠偏请交给平台的
chinaCRS机制或 PointTrans 处理,自己加减固定值会在缩放、跨带时产生不可控误差。
4. 坐标转换
4.1 全局偏移坐标系 chinaCRS
如果整个项目使用的底图数据源是国内偏移坐标(如高德、百度),可以在创建地图时统一声明,之后的图层与矢量数据的偏移/纠偏都由平台自动处理:
const map = new mars3d.Map("mars3dContainer", {
method: {
chinaCRS: mars3d.ChinaCRS.GCJ02 // 标识地图整体使用的坐标系为国内偏移坐标系
},
scene: {
center: { lat: 31.833439, lng: 117.212587, alt: 1237, heading: 0, pitch: -60 }
}
})同时,单个图层也支持独立声明 chinaCRS,常用在"底图是偏移坐标、而某个模型是标准坐标"的混搭场景:
// 模型数据是无偏坐标,配置 chinaCRS 后内部自动加偏,与偏移底图对齐
const tiles3dLayer = new mars3d.layer.TilesetLayer({
name: "合肥国家大学科技园",
url: "https://data.mars3d.cn/3dtiles/qx-hfdxy/tileset.json",
chinaCRS: mars3d.ChinaCRS.WGS84 // 标识数据坐标,内部自动加偏
})
map.addLayer(tiles3dLayer)4.2 坐标转换 API 清单
平台坐标转换集中在 PointTrans 类中,常用的方法有:
| 方法 | 作用 | 说明 |
|---|---|---|
mars3d.PointTrans.gcj2wgs(坐标) | 国测局坐标 → WGS84 | 把高德/腾讯拾取的火星坐标转为平台使用的标准坐标 |
mars3d.PointTrans.proj4Trans(坐标, 源坐标系, 目标坐标系) | 任意投影坐标系互转 | 依赖 proj4,支持 mars3d.CRS 内的 EPSG 常量,如 4326 与 CGCS2000 高斯投影互转 |
mars3d.PointTrans.degree2dms(度值) | 十进制 → 度分秒 | 用于界面展示 |
mars3d.PointTrans.dms2degree(度, 分, 秒) | 度分秒 → 十进制 | 用于界面输入 |
mars3d.Util.formatNum(数值, 小数位) | 数值格式化 | 保留指定小数位,常用于经纬度输出 |
更多方法(如
wgs2gcj、bd2wgs、gcj2bd、bd2gcj等)见 PointTrans API 文档。
另外,坐标对象的获取与格式化的常用写法:
// 1) 从 Cesium 笛卡尔坐标得到经纬度点对象
const cartesian = event.cartesian
const point = mars3d.LngLatPoint.fromCartesian(cartesian)
point.format() // 格式化经度、纬度、高度(保留 6 位小数等)
console.log(point.lng, point.lat, point.alt)
// 2) 经纬度数组与 LngLatPoint 互转
const arr = mars3d.LngLatArray.toArray(positions) // positions → [[lng, lat, alt], ...]4.3 完整示例:坐标转换工具
下面的代码摘自平台"坐标转换"功能示例(util/pointTrans/selectPoint),演示了经纬度与度分秒、CGCS2000 高斯投影坐标之间的互相转换:
// 十进制 → 度分秒
function toDms(lng, lat) {
const jd = mars3d.PointTrans.degree2dms(lng)
const wd = mars3d.PointTrans.degree2dms(lat)
return `${jd.degree}° ${jd.minute}′ ${jd.second}″ / ${wd.degree}° ${wd.minute}′ ${wd.second}″`
}
// 度分秒 → 十进制
function dms2degree(du, fen, miao) {
return mars3d.PointTrans.dms2degree(du, fen, miao)
}
// 经纬度 → CGCS2000 高斯投影坐标(3度带 / 6度带)
function lngLatToGk(lng, lat, is6) {
const crs = is6 ? mars3d.CRS.CGCS2000_GK_Zone_6 : mars3d.CRS.CGCS2000_GK_Zone_3
const result = mars3d.PointTrans.proj4Trans([lng, lat], mars3d.CRS.EPSG4326, crs)
return { x: mars3d.Util.formatNum(result[0], 1), y: mars3d.Util.formatNum(result[1], 1) }
}
// 高斯投影坐标 → 经纬度
function gkToLngLat(x, y, is6) {
const crs = is6 ? mars3d.CRS.CGCS2000_GK_Zone_6 : mars3d.CRS.CGCS2000_GK_Zone_3
return mars3d.PointTrans.proj4Trans([x, y], crs, mars3d.CRS.EPSG4326)
}
// 地图上拾取一个点并转换
map.once(mars3d.EventType.click, (event) => {
const point = mars3d.LngLatPoint.fromCartesian(event.cartesian)
point.format()
console.log("经纬度:", point.lng, point.lat)
console.log("度分秒:", toDms(point.lng, point.lat))
console.log("高斯投影:", lngLatToGk(point.lng, point.lat, false))
})运行效果
新窗口查看
更多坐标系相关示例:
- 全局偏移坐标系配置:
map/options/chinaCRS - 瓦片图层 EPSG:4490 / EPSG:4326 / EPSG:3857:
layer-tile/crs/epsg4490
5. 坐标系常见问题
5.1 为什么底图和模型有几十米到几百米的整体偏移?
绝大多数是偏移坐标系没有声明造成的:底图(如高德、百度)是 GCJ02/BD09,而你的矢量或模型数据是 WGS84(或反过来)。解决办法就是给对应的图层加 chinaCRS(GCJ02 / BAIDU / WGS84),让平台自动加偏或纠偏,而不是去挪模型的位置。
5.2 加载天地图/地方瓦片时瓦片错位、只显示一小块或空白?
先确认服务是 EPSG:4490(天地图 c 系列)还是 EPSG:4326(天地图 w 系列),并按服务文档设置 crs;对于只覆盖某个行政区的瓦片服务(如省级服务),还需要设置 rectangle 限定范围,避免瓦片请求越界。
const layer = new mars3d.layer.XyzLayer({
name: "山东电子",
type: "xyz",
url: "http://service1.sdmap.gov.cn/...&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=你的token",
crs: "EPSG:4490", // 标识坐标系
rectangle: { xmin: 114.229839, xmax: 123.40053, ymin: 33.93893, ymax: 38.904819 }, // 限定范围
minimumLevel: 7,
maximumLevel: 18
})
map.addLayer(layer)5.3 高斯投影坐标(X/Y)顺序怎么传?
proj4Trans 的入参与返回都是 [经度, 纬度] 形式(即 X 在前、Y 在后)的数组。如果拿到的是测量坐标"横坐标 Y、纵坐标 X",转换前要先对调顺序,转换后再对调回来,避免出现"坐标跑到海里"的现象。
5.4 三维里能不能只画一个局部平面的坐标?
不能。三维球体(Cesium)内部统一使用笛卡尔空间直角坐标(Cesium.Cartesian3),任何平面坐标都必须先转换成经纬度再参与渲染。所以"平面坐标 → 经纬度 → 平台对象坐标"是必做的一步,转换过程就是上面 proj4Trans 的用法。
