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
相关产品推荐
相关产品推荐

