【问题标题】:How to rotate map view smoothly with bearing in android如何在android中使用方位平滑旋转地图视图
【发布时间】:2012-09-12 07:11:48
【问题描述】:

当用户改变他的方向时,我正在尝试旋转地图视图,即如果用户左转和右转,它应该相应地旋转。我正在根据当前位置旋转地图视图,它正在正确旋转但它在抖动。这里是我用于旋转的代码

   public void onGPSUpdate(Location location) 
{
     boolean check=isBetterLocation(location, tempLoc);
    tempLoc=location;

     if(check){
        showLocation(location);

     }

}
isBetterLocation method is copied from google docs for better location.

private void showLocation(Location loc){
   mRotateView.rotate(-loc.getBearing());             
   }

我注册了一个位置更新,时间间隔为 0,最小距离为 10 以进行频繁更新。这里我的问题是地图视图总是抖动,谁能告诉我如何像 waze 地图等其他应用程序一样平滑地旋转地图视图.谢谢...

【问题讨论】:

  • 您需要澄清问题是否出在您从 gps 跳来跳去的方位上。或者实际旋转到新轴承,这就是 Konrad 所说的。
  • @lfor 是的,你纠正了我得到的轴承正在跳来跳去。你对此有什么想法吗?
  • 我知道你走得越快就会越好。您需要对获得的值进行某种过滤。
  • @lfor 是的,你知道我们应该在这里使用哪个过滤器吗?
  • 嗯,我不会在我的应用程序中做任何过滤做同样的事情。过滤只会让它在开始移动时更慢地获得一个好的方向。如果我要过滤,我会做一个简单的 new_heading = (old_heading * (1-filter)) + (gps_heading * filter) 样式,然后尝试从 0.25 开始的过滤器值。这将需要一些调整以应对 359-0 不连续性,但如果差异 > 180 度,一些简单的加法或减法 360 应该对其进行排序。

标签: android google-maps geolocation


【解决方案1】:

您是在尝试以平滑的方式旋转地图,例如一次旋转一个度数,还是在位置更新时让它从 A 度旋转到 B 度?

有点像

while (oldAngle != newAngle)
{
mapView.rotate(newAngle);
// this is where you would decied to add or subtract; 
newAngle ++ or -- ; 
}

不确定这是否会完全像循环运行得很快那样工作,所以可以将其作为 asynctask 执行,并在其中添加暂停以模拟平滑旋转。

Double angle = Math.atan2((userstartPoint.getX() - userendPoint.getX()), userstartPoint.getY() - userendPoint.getY());
            angle = Math.toDegrees(angle);
            map.setRotationAngle(angle);

所以基本上我得到起点(新位置),然后是终点(旧位置),并在其上执行 Math.atan2,如您所见。然后将其转换为度数并将其设置为我的地图旋转。 现在它不会进行平滑旋转,但我不需要。在这里您可以设置自己的步进器以实现平滑旋转。除非谷歌地图已经有一个。

【讨论】:

  • 如果用户改变他的行进方向,我必须旋转它,例如,如果他左转,它应该向左旋转。
  • 您可以尝试做的是获取旧的 map.angle,然后获取新的航向并通过一个循环运行它,该循环一次减去或增加新航向 1 度,然后设置每次到map.rotation。
  • @Konard 谢谢你的想法,我试过了,但它不能正常工作,因为如果我们试图基于标题旋转,如果用户设备指向不同的标题,那么它不会准确旋转。
  • 这是我在我的应用程序中使用的地图角度旋转,现在这有点不同,因为我使用的是 Esri API 而不是谷歌,但我相信你可以实现这个。 !!!将代码添加到我的原始帖子中!!!
  • @Konard 我不明白你的代码中的 userStart x 和 y 是什么。
【解决方案2】:

由于位置的方位值不是很精确,而且往往会稍微跳跃,因此您应该对方位使用过滤器。例如,将最后 5 个方位值保留在一个数组中,并使用这些值的平均值作为将地图旋转到的方位。或者使用SensorEvent docs 中解释的过滤器 - 它更容易使用并且可以更好地调整。

这将平滑地图的旋转。保持稳定。

编辑:

低通滤波器的一个版本:

public static float exponentialSmoothing(float input, float output, float alpha) {
    output = output + alpha * (input - output);
    return output;
}

像这样使用它:

final static float ALPHA = 0.33; // values between 0 and 1
float bearing;

// on location/bearing changed:

bearing = exponentialSmoothing(bearing, newBearing, ALPHA);

bearing 将是用于实际旋转地图的值,newBearing 将是您从每个事件中获得的方位,使用 ALPHA 您可以控制旋转对新方向的速度或速度通过加权计算结果中考虑了多少旧轴承和新轴承。较小的值对旧值的权重较高,较高的值对新值的权重较高。

我希望效果更好。

【讨论】:

  • 谢谢你的想法,我试过平均轴承但旋转不正确,我还检查了平均值是否大于或等于360,我做到了360。
  • 是的,这里有一些微妙之处,因为方位分别在北方跳跃。 0/360 度——尝试实现我添加到答案中的低通滤波器。
【解决方案3】:

要更改地图的方位,请使用Camera 类。您可以使用新的方位定义一个新的CameraPosition,并告诉相机使用GoogleMap.moveCamera 或GoogleMap.animateCamera 移动,如果您想要平滑移动。

【讨论】:

    【解决方案4】:

    我已经在我的应用程序中实现了这一点。我基本上所做的是我采用路径的最后一个和倒数第二个 LatLng 并使用计算方位

    public static float getRotationAngle(LatLng secondLastLatLng, LatLng lastLatLng)
    {
        double x1 = secondLastLatLng.latitude;
        double y1 = secondLastLatLng.longitude;
        double x2 = lastLatLng.latitude;
        double y2 = lastLatLng.longitude;
    
        float xDiff = (float) (x2 - x1);
        float yDiff = (float) (y2 - y1);
    
        return (float) (Math.atan2(yDiff, xDiff) * 180.0 / Math.PI);
    
    }
    

    将此角度设置为相机位置的方位角。

    注意:有时(很少)它会将地图旋转到相反的方向。我正在寻找它,但如果有人有理由请回复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-10
      • 2011-05-19
      • 1970-01-01
      • 1970-01-01
      • 2015-07-11
      • 2012-11-04
      相关资源
      最近更新 更多