带有地形层的MapLibre GL JS:如何将水平面固定到特定高度?

问题描述 投票:0回答:1

我基于“添加 3D 模型”示例编写了一些代码,以便在地图上仅绘制水平面,并使用

setTerrain
添加地形图层。我的目的是在海拔高度绘制半透明图层,并让它们与山脉相交,有点类似于等高线。

我在海拔 0 处创建了一个 1 公里宽的正方形。海拔 0 是可见地图区域中心地形的高度。当我拖动地图并释放鼠标时,高度 0 会重置为中心地形的新高度 0,从而使飞机改变其相对高度:

为了更好地说明问题,夸大了海拔。

如何指定飞机的高度(以米为单位)并在拖动地图时将其固定在该高度?我想我需要获取中心地形的高度,然后从平面的 z 位置添加/减去它,但是如何在自定义图层的渲染函数中执行此操作?

three.js mapbox-gl-js terrain maplibre-gl
1个回答
0
投票

就像你说的,一个简单的解决方案是获取屏幕中心地形的高度和模型的高度,然后减去它们。这可以像这样实现:

  render(gl, matrix) {
    
    const modelOrigin = new LngLat(11.53, 47.67);  // just an example
    const modelElevation = map.terrain ? map.terrain.getElevationForLngLatZoom(modelOrigin, map.getZoom()) : 0;
    const modelOriginMercator = mlg.MercatorCoordinate.fromLngLat(modelOrigin, 0);
  
    // calculating the difference between center-elevation and model-elevation
    const terrainCenterElevation = map.transform.elevation;
    const deltaMetersZ = modelElevation - terrainCenterElevation;
    const mercatorPerMeter = modelOriginMercator.meterInMercatorCoordinateUnits();
    const deltaMercatorZ = deltaMetersZ * mercatorPerMeter;

    const modelTransform = {
      translateX: modelOriginMercator.x,
      translateY: modelOriginMercator.y,
      translateZ: modelOriginMercator.z + deltaMercatorZ,
      rotateX: Math.PI / 2,
      rotateY: 0,
      rotateZ: 0,
      scale: modelOriginMercator.meterInMercatorCoordinateUnits()
    };

    const rotationX = new Matrix4().makeRotationAxis(new Vector3(1, 0, 0), modelTransform.rotateX);
    const rotationY = new Matrix4().makeRotationAxis(new Vector3(1, 0, 0), modelTransform.rotateY);
    const rotationZ = new Matrix4().makeRotationAxis(new Vector3(0, 0, 1), modelTransform.rotateZ);

    const m = new Matrix4().fromArray(matrix);
    const l = new Matrix4()
      .makeTranslation(modelTransform.translateX, modelTransform.translateY, modelTransform.translateZ)
      .scale(new Vector3(modelTransform.scale, modelTransform.scale, modelTransform.scale))
      .multiply(rotationX).multiply(rotationY).multiply(rotationZ);
    const cameraProjectionMatrix = m.multiply(l);

    // @ts-ignore
    this.camera.projectionMatrix = cameraProjectionMatrix;
    // @ts-ignore
    this.renderer.resetState();
    // @ts-ignore
    this.renderer.render(this.scene, this.camera);
    map.triggerRepaint();


}
  • maplibre 似乎总是将 Threejs 场景精确定位在屏幕中心的高度...因此,当使用
    mlg.MercatorCoordinate.fromLngLat(modelOrigin, 0)
    获取模型高度时,我们不需要提供实际的模型高度,只需传递
    0
  • deltaMercatorZ
    正在添加到模型的 z 轴翻译中

关于 transform.ts 中的 maplibre 命名法的一些注释

  • elevation
    [米]:
    center
  • 下地形的高度
  • center
    [lng, lat]:屏幕中心在世界中的位置
  • centerPoint
    [像素]:屏幕中心在屏幕上的位置
  • altitude
    [m]:相机相对于海平面的高度

我认为可能有一个更优雅的解决方案,但这可能暂时可以完成工作!

© www.soinside.com 2019 - 2024. All rights reserved.