2

假设我每 20 分钟收集一次用户位置数据。归根结底,我有一个ArrayList包含字段和其他数据lat的对象。long

我有两个问题,我面临并试图弄清楚:

  1. 一些位置是从建筑物内部获取的,因此它们不是很准确,并且可能分布在用户当时所在的实际位置周围。

  2. 由于用户没有移动,一些位置是在不同时间但从同一位置拍摄的。

我想要实现的是找到彼此靠近的所有位置:假设 70 米,找到所有这些位置的平均位置,然后只用这个平均位置替换它们。

所以我要回答两个重要的问题:

  1. 找到所有距离 < 70 米的附近位置的最佳方法是什么(请记住,数组包含位置的有效变化。所以我必须找到附近的组并保持其他组完好无损)。

  2. 有没有办法找到许多附近人的平均位置?

4

3 回答 3

4

关于附近的位置,我之前在这里回答了一个类似的问题:Android Maps v2 - animate camera to include most markers

具体来说,我认为您将能够使用这段代码:

private List<Marker> getSurroundingMarkers(List<Marker> markers,
        LatLng origin, int maxDistanceMeters) {
    List<Marker> surroundingMarkers = surroundingMarkers = new ArrayList<Marker>();
    if (markers == null) return surroundingMarkers ;


        for (Marker marker : markers) {

            double dist = distBetween(origin, marker.getPosition());

            if (dist < maxDistanceMeters) {
                surroundingMarkers.add(marker);
            }
        }


    return surroundingMarkers;
}

private float distBetween(LatLng pos1, LatLng pos2) {
    return distBetween(pos1.latitude, pos1.longitude, pos2.latitude,
            pos2.longitude);
}

/** distance in meters **/
private float distBetween(double lat1, double lng1, double lat2, double lng2) {
    double earthRadius = 3958.75;
    double dLat = Math.toRadians(lat2 - lat1);
    double dLng = Math.toRadians(lng2 - lng1);
    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
            + Math.cos(Math.toRadians(lat1))
            * Math.cos(Math.toRadians(lat2)) * Math.sin(dLng / 2)
            * Math.sin(dLng / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double dist = earthRadius * c;

    int meterConversion = 1609;

    return (float) (dist * meterConversion);
}

可能重写标记部分以使用 LatLng 代替。

关于平均,这应该是一个简单的问题(假设你有 n 个 LatLng):

lat_avg = (lat1+lat2+...+latn)/n 
lng_avg = (lng1+lng2+...+lngn)/n 

latlng_avg = new LatLng(lat_avg, lat_lng)
于 2013-10-29T19:29:20.327 回答
1

我不确定您如何获取用户的位置 - 无论您使用的是传统LocationManager服务还是游戏服务。我一直使用 android 开发人员博客上记录的这种方法来模拟我的位置。如果您可以灵活地在位置收集方法之间切换,那么此人是在内部还是在外部都无关紧要。您应该在任何给定时间获得最佳位置。

假设您在足够的时间表上获得位置(我不知道您何时检查更新,但由于您希望所有内容都在 70m 半径范围内,我假设它在时间表上而不是距离变化)基本方式找到平均点是:

(1) 将每个纬度/经度对转换为单位长度的 3D 向量。(2) 对每个向量求和 (3) 归一化结果向量 (4) 转换回球坐标

这种方法在此处以及更早的关于计算一组角度的平均值的SO 帖子中都有记录

示例代码很容易理解 - 只需插入从位置抓取中获得的 lat long 值,就可以了。

于 2013-10-29T19:46:51.460 回答
0

对于来自同一位置的标记,我创建了以下方法:

public ArrayList<MyLocation> removeSameLocationMarkers(List<ParseObject> objects, int maxDistanceMeters) 
{
    boolean isLocationExist;
    ArrayList<MyLocation> acceptedLocations = new ArrayList<MyLocation>();

    if (objects == null) return acceptedLocations;

    for (ParseObject location1 : objects) 
    {
        isLocationExist = false;
        for (MyLocation location2 : acceptedLocations) 
        {
            if (!location1.equals(location2)) 
            {
                float distance = distBetween(location1.getDouble("latitude"), location1.getDouble("longitude"), location2.getLatitude(), location2.getLongitude());
                if (distance < maxDistanceMeters) 
                {
                    location2.addTimeToLocation(location1.getString("time"));
                    isLocationExist = true;
                }
            }
        }
        if (!isLocationExist)
        {
            Location newLocation = new Location("");
            newLocation.setLatitude(location1.getDouble("latitude"));
            newLocation.setLongitude(location1.getDouble("longitude"));
            String provider = location1.getString("provider");
            if (provider != null)
            {
                newLocation.setProvider(provider);
            }
            MyLocation newMyLocation = new MyLocation(newLocation);
            newMyLocation.addTimeToLocation(location1.getString("time"));
            acceptedLocations.add(newMyLocation);
        }
    }

    return acceptedLocations;
}
于 2013-10-30T02:46:02.130 回答