如何计算关于墨卡托投影的绕地球轨道?

时间:2018-07-05 15:14:19

标签: three.js mercator

我正在尝试在three.js中创建一个小的交互式UFO绕地球飞行场景。

我认为最好在地图的2D投影上控制UFO(如小地图),将像素坐标转换为lat / lng坐标,最后将lat / lng转换为我可以用于我的Vector 3D场景。

事实证明并非如此。

如果UFO在赤道上飞行(+/-度),效果很好,但可以肯定的是,我忘记将投影应用于2D控件:

enter image description here

现在我有点迷路了。我的控件(WASD键)基本上可以在小地图上设置UFO的速度和旋转,但是我必须向播放器添加某种“校正”。这就是当前设置值的方式:

let left = parseFloat(this.minimapPlayer.style.left) + this.speed * Math.cos(Math.PI / 180 * this.rotation)
let top = parseFloat(this.minimapPlayer.style.top) + this.speed * Math.sin(Math.PI / 180 * this.rotation)

是否有一种方法可以创建“真实”轨道,以使我的UFO不会总是飞越两极?还是有更好的方法来处理UFO的轨道(也许没有小地图)?

这是到目前为止的完整动画代码:

animatePlane(firstRender) {
  requestAnimationFrame(this.animatePlane)

  // set next position
  let left = parseFloat(this.minimapPlayer.style.left) + this.speed * Math.cos(Math.PI / 180 * this.rotation)
  let top = parseFloat(this.minimapPlayer.style.top) + this.speed * Math.sin(Math.PI / 180 * this.rotation)

  // handle border collisions
  if (left < 0) {
    left = this.minimapBounds.width
  }

  if (left > this.minimapBounds.width) {
    left = 0
  }

  if (top < 0 || top > this.minimapBounds.height) {
    this.rotation = this.rotation * -1

    if (this.rotation > 0) {
      this.plane.up.set(0, 1, 0)
    } else {
      this.plane.up.set(0, -1, 0)
    }

    top = top + this.speed * Math.sin(Math.PI / 180 * this.rotation)

    if (left < this.minimapBounds.width / 2) {
      left = left + this.speed * Math.cos(Math.PI / 180 * this.rotation) + this.minimapBounds.width / 2
    } else {
      left = left + this.speed * Math.cos(Math.PI / 180 * this.rotation) - this.minimapBounds.width / 2
    }
  }

  this.minimapPlayer.style.left = `${left}px`
  this.minimapPlayer.style.top = `${top}px`

  // convert to lat/lng
  const lat = (180 / this.minimapBounds.height) * (top - this.minimapBounds.height / 2) * -1
  const lng = (360 / this.minimapBounds.width) * (left - this.minimapBounds.width / 2)

  // convert to vector
  const p = this.latLongToVector3(lat, lng, this.radius, 200)
  this.plane.position.set(p.x, p.y, p.z)

  // bottom of the plane should always look the the middle of the earth
  this.plane.lookAt(new THREE.Vector3(0,0,0))
}

0 个答案:

没有答案