我发现之前的代码中有错误,于是决定重新编写。
我以前做过类似的事情,当时有大约4500个标记,并希望选择那些距离特定位置一定距离的标记。我将那段代码进行了泛化,使其适用于任何类型的标记。
![所有标记](https://istack.dev59.com/yYLiI.webp)
![使用getSurroundingMarkers选择的标记](https://istack.dev59.com/tn1gC.webp)
我将要发布的代码包含两种方法:
selectLowDistanceMarkers
测量每个标记之间的距离,并仅选择那些与其他标记之间的距离不远的标记。由于每个标记之间的比较和之后的检查,这需要O(n+n^2)的运行时间。
getSurroundingMarkers
如果您已经知道要缩放到的位置,则此方法与上述方法相同。该方法的CPU负荷要小得多,因为它只需要对所有标记进行O(n)次运行并将它们与给定位置进行比较。
private List<Marker> selectLowDistanceMarkers(List<Marker> markers,
int maxDistanceMeters) {
List<Marker> acceptedMarkers = new ArrayList<Marker>();
if (markers == null) return acceptedMarkers;
Map<Marker, Float> longestDist = new HashMap<Marker, Float>();
for (Marker marker1 : markers) {
for (Marker marker2 : markers) {
if (!marker1.equals(marker2)) {
float distance = distBetween(marker1.getPosition(),
marker2.getPosition());
if (longestDist.containsKey(marker1)) {
if (distance > longestDist.get(marker1))
longestDist.put(marker1, distance);
} else {
longestDist.put(marker1, distance);
}
}
}
}
for (Marker marker: longestDist.keySet()) {
if (longestDist.get(marker) <= maxDistanceMeters) acceptedMarkers.add(marker);
}
return acceptedMarkers;
}
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 < getHydrantsLoadradius()) {
surroundingMarkers.add(marker);
}
}
return surroundingMarkers;
}
private float distBetween(LatLng pos1, LatLng pos2) {
return distBetween(pos1.latitude, pos1.longitude, pos2.latitude,
pos2.longitude);
}
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);
}
在使用上述任何一种过滤算法后,再次使用众所周知的LatLngBounds来确定需要缩放的程度。