在我之前的代码中发现了一个错误,并决定坐下来重写它。
我之前做过类似的事情,我有大约 4500 个标记,并想选择在特定位置一定距离内的那些。采用该代码并将其概括为与任何类型的标记一起使用。
![所有标记](https://i.stack.imgur.com/yYLiI.png)
![使用 getSurroundingMarkers 选择的标记](https://i.stack.imgur.com/tn1gC.png)
我将在下面发布的代码包含两种您可以使用的方法:
选择低距离标记
测量每个标记之间的距离,并仅选择与任何其他标记距离不远的那些。由于每个标记和之后的检查之间的比较,这需要 O(n+n^2) 运行时间。
获取周围标记
如果您已经知道要放大的位置,则此方法与上述相同。这种方法对 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) {
// in this for loop we remember the max distance for each marker
// think of a map with a flight company's routes from an airport
// these lines is drawn for each airport
// marker1 being the airport and marker2 destinations
for (Marker marker2 : markers) {
if (!marker1.equals(marker2)) {
float distance = distBetween(marker1.getPosition(),
marker2.getPosition());
if (longestDist.containsKey(marker1)) {
// possible we have a longer distance
if (distance > longestDist.get(marker1))
longestDist.put(marker1, distance);
} else {
// first distance
longestDist.put(marker1, distance);
}
}
}
}
// examine the distances collected
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);
}
/** 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);
}
同样,使用众所周知的 LatLngBounds 来确定在使用上述过滤算法之一后需要缩放多少。