You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OSMdroid中GeoPoint自定义海拔读取异常,动画中海拔始终为0求助

问题分析与解决方案

核心问题点

  • 动画逻辑混乱:每次执行Runnable都遍历所有geoPoints,Marker位置会被最后一个点的海拔覆盖,完全没实现“海拔先升后降”的路径逻辑。
  • 起点海拔丢失:通过proj.fromPixels(startPoint.x, startPoint.y)得到的startGeoPoint默认海拔为0,丢失了Marker初始位置的海拔信息。
  • 海拔插值逻辑缺失:没有根据动画进度t计算对应路径点的海拔,而是直接取列表中某个点的固定海拔,导致动画过程中海拔值混乱或为0。

修正步骤与代码实现

1. 准备合法路径数据

确保geoPoints按路径顺序排列,每个点通过new GeoPoint(lat, lng, alt)构造,中点海拔最高,前后节点海拔依次升降。

2. 重构动画逻辑

移除无效遍历,基于动画进度t插值计算当前位置的经纬度和海拔,实现“先升后降”的效果:

public void animateMarker(final Marker marker, final List<GeoPoint> pathPoints) {
    if (pathPoints == null || pathPoints.size() < 2) {
        return; // 至少需要起点和终点
    }

    final Handler handler = new Handler();
    final long start = SystemClock.uptimeMillis();
    final long duration = 5000;
    final LinearInterpolator interpolator = new LinearInterpolator();

    // 提取路径关键节点:起点、中点、终点
    final GeoPoint startPoint = pathPoints.get(0);
    final int midIndex = pathPoints.size() / 2;
    final GeoPoint midPoint = pathPoints.get(midIndex);
    final GeoPoint endPoint = pathPoints.get(pathPoints.size() - 1);

    handler.post(new Runnable() {
        @Override
        public void run() {
            long elapsed = SystemClock.uptimeMillis() - start;
            float t = interpolator.getInterpolation((float) elapsed / duration);
            double currentLat, currentLng, currentAlt;

            // 根据进度分两段处理海拔变化:前半段上升,后半段下降
            if (t <= 0.5f) {
                float segmentT = t * 2; // 映射到0-1区间
                currentLat = startPoint.getLatitude() + segmentT * (midPoint.getLatitude() - startPoint.getLatitude());
                currentLng = startPoint.getLongitude() + segmentT * (midPoint.getLongitude() - startPoint.getLongitude());
                currentAlt = startPoint.getAltitude() + segmentT * (midPoint.getAltitude() - startPoint.getAltitude());
            } else {
                float segmentT = (t - 0.5f) * 2; // 映射到0-1区间
                currentLat = midPoint.getLatitude() + segmentT * (endPoint.getLatitude() - midPoint.getLatitude());
                currentLng = midPoint.getLongitude() + segmentT * (endPoint.getLongitude() - midPoint.getLongitude());
                currentAlt = midPoint.getAltitude() + segmentT * (endPoint.getAltitude() - midPoint.getAltitude());
            }

            // 更新Marker位置(携带正确海拔)
            marker.setPosition(new GeoPoint(currentLat, currentLng, currentAlt));

            // 停止动画逻辑
            Button stopper = findViewById(R.id.buttonStop);
            if (stopper.isPressed()) {
                handler.removeCallbacks(this);
                GeoPoint currentPos = marker.getPosition();
                String altStr = String.valueOf(currentPos.getAltitude());
                timer.setText("Your Coordinates are : " + currentPos + " | Altitude: " + altStr);
                return;
            }

            // 继续动画循环
            if (t < 1.0) {
                handler.postDelayed(this, 15);
            }
            map.postInvalidate();
        }
    });
}

3. 关键优化说明

  • 直接使用原始GeoPoint的海拔信息,避免投影转换丢失数据。
  • 分两段插值处理,严格实现“海拔先升至中点、再下降”的需求。
  • 移除无效的列表遍历,每次仅计算当前进度对应的位置,避免重复覆盖Marker状态。
  • 停止动画时直接读取Marker当前的GeoPoint,确保获取正确的海拔值。

额外注意事项

  • 如果路径是多段连续的,可扩展逻辑:根据t计算当前处于哪一段路径,再对该段的起点和终点进行插值。
  • 调用动画时,传入完整的pathPoints列表而非单个终点,确保路径逻辑生效。

内容的提问来源于stack exchange,提问作者noro zoro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 02:01:06