经纬度坐标系转threejs空间直角坐标系

在利用threejs做一些例如城市模型等3D开发时,会发现threejs无法直接支持经纬度坐标,例如城市模型的某个建筑,它在空间直角坐标系中的位置,可以用一个x,y,z表示,但是没法和实际世界中地球坐标系的经度、纬度相关联,二者之间有一套相互映射的算法,这样当有需求需要在某个经纬度位置添加某个东西时,也可以正确的显示在三维模型中。

  1. 首先需要和建模工程师确定好他们建模的坐标0点具体是哪个位置,以及此点对应的实际世界中的经纬度坐标。且建模工程师建模一定要和真实城市街区比例一致(当然按一定比例缩小也可以)
  2. 具体实现代码
// 这个就是和建模工程师确定的建模时的0点对应的真实世界的经纬度坐标(本文经纬度为wgs84坐标系,如果是其他坐标系,需要先转换成wgs84)
const threeMapZeroCenter  =  {
  lng: 114.2858126490011,
  lat: 30.581177854141437
}

// wgs84经纬度坐标转threejs三维坐标
function wgs84ToThreePosition(lng, lat, height) {
  // 模型世界坐标0点对应的wgs84坐标
  // TODO: 需要和模型组的确定准确坐标
  const cityModelCenterPos = {
    lng: threeMapZeroCenter.lng,
    lat: threeMapZeroCenter.lat,
    height: 0,
  }

  // 找到地图的中心对应的经纬度坐标
  const center = lngLatToMercator(cityModelCenterPos)
  const mercatorMax = 20037508.3427892

  const y = height ? height : 0
  const z = (+lng / 180.0) * mercatorMax
  let x = (Math.PI / 180.0) * +lat
  const tmp = Math.PI / 4.0 + x / 2.0
  x = (mercatorMax * Math.log(Math.tan(tmp))) / Math.PI

  // 这一步是重点:墨卡托平面坐标系很大,需要结合模型调试一个合适的比例,例如下面的0.85,是结合模型上两个实际点位调试出的大概比例,通常通过0点和另外一个点确定这比例系数需要设置多少。
  return {
    x: (center.x - x) * 0.85,
    y: y - center.y,
    z: (center.z - z) * 0.85,
  }
}

// 经纬度坐标转墨卡托
function lngLatToMercator({ lng, lat, height }) {
  var y = height ? height : 0
  var z = (lng / 180.0) * 20037508.3427892
  var x = (Math.PI / 180.0) * lat
  var tmp = Math.PI / 4.0 + x / 2.0
  x = (20037508.3427892 * Math.log(Math.tan(tmp))) / Math.PI
  return { x: x, y: y, z: z }
}

你可能感兴趣的:(经纬度坐标系转threejs空间直角坐标系)