假设我每20分钟收集一次用户位置数据。在一天结束时,我有ArrayList
个包含lat
和long
字段及其他数据的对象。
我遇到两个问题并试图找出问题:
部分地点是从建筑物内部拍摄的,所以它们不是很准确,可能会散布在当时用户所在的实际位置。
有些位置是在不同时间拍摄的,但是来自同一位置,因为用户没有移动。
我想要达到的目的是找到彼此靠近的所有位置:比如说70米,找到所有这些位置的平均位置,只用这个平均位置替换它们。
所以我要回答两个重要的问题:
找到所有近处位置的最佳方法是什么? 70米距离(请记住,阵列包含有效的位置变化。所以我必须找到附近的组并保持其他组完好无损。)
是否有方法或方法可以找到许多近处的平均位置?
答案 0 :(得分:2)
关于近位置,我之前在这里回答了类似的问题: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)
答案 1 :(得分:1)
我不确定您是如何获取用户的位置的 - 无论您使用传统的LocationManager
还是播放服务。我总是模仿我在Android开发人员博客上记录this approach的位置。如果您可以灵活地在位置收集方法之间切换,那么这个人是在内部还是外部都不应该那么重要。您应该在任何给定时间获得最佳位置。
假设您在足够的时间表上获得位置(我不知道您何时检查更新,但由于您希望所有内容都在半径70米范围内,我假设其按时间表而不是距离更改)找到平均点的基本方法是:
(1)将每个纬度/长度对转换为单位长度的3D矢量。 (2)对每个向量求和 (3)归一化得到的矢量 (4)转换回球坐标
这种方法documented here以及earlier SO post计算一组角度的平均值
示例代码非常容易理解 - 只需插入从您的位置获取的lat long值,您就可以了。
答案 2 :(得分: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;
}