マップ上のマーカーをクラスタリングするためのアルゴリズムを開発しようとしています。表示されるマーカーの量は、現在のズーム レベルによって異なります。10 個のグループから 1 つのマーカーを表示する場合、そのタイトルを「10」に設定します。問題は、目に見えるマーカーにタイトルがまったくない場合があることです。それがどのように可能かわかりません。これが私のコードです:
public class MainActivity extends FragmentActivity {
private ArrayList<Marker> markers = new ArrayList<Marker>();
private Bitmap markerImage;
private float oldZoom = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
markerImage = BitmapFactory.decodeResource(this.getResources(), R.drawable.ic_launcher);
setContentView(R.layout.activity_main);
final GoogleMap map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
map.getUiSettings().setMyLocationButtonEnabled(true);
map.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition cameraPosition) {
if (cameraPosition.zoom != oldZoom) {
checkMarkers(map);
}
oldZoom = cameraPosition.zoom;
}
});
createMarkers(map);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
private void createMarkers(GoogleMap map) {
double initLat = 48.462740;
double initLng = 35.039572;
for (float i = 0; i < 2; i += 0.2) {
LatLng pos = new LatLng(initLat + i, initLng);
Marker marker = map.addMarker(new MarkerOptions()
.position(pos)
.icon(BitmapDescriptorFactory.fromBitmap(markerImage)));
markers.add(marker);
}
for (float i = 0; i < 2; i += 0.2) {
LatLng pos = new LatLng(initLat, initLng + i);
Marker marker = map.addMarker(new MarkerOptions()
.position(pos)
.icon(BitmapDescriptorFactory.fromBitmap(markerImage)));
markers.add(marker);
}
initLat = 40.462740;
initLng = 30.039572;
for (float i = 0; i < 2; i += 0.2) {
LatLng pos = new LatLng(initLat + i, initLng + i);
Marker marker = map.addMarker(new MarkerOptions()
.position(pos)
.icon(BitmapDescriptorFactory.fromBitmap(markerImage)));
markers.add(marker);
}
}
private void checkMarkers(GoogleMap map) {
Projection projection = map.getProjection();
LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;
HashMap<Marker, Point> points = new HashMap<Marker, Point>();
for (Marker marker : markers) {
if (bounds.contains(marker.getPosition())) {
points.put(marker, projection.toScreenLocation(marker.getPosition()));
marker.setVisible(false);
}
}
CheckMarkersTask checkMarkersTask = new CheckMarkersTask();
checkMarkersTask.execute(points);
}
private class CheckMarkersTask extends AsyncTask<HashMap<Marker, Point>, Void, HashMap<Point, ArrayList<Marker>>> {
private double findDistance(float x1, float y1, float x2, float y2) {
return Math.sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
}
@Override
protected HashMap<Point, ArrayList<Marker>> doInBackground(HashMap<Marker, Point>... params) {
HashMap<Point, ArrayList<Marker>> clusters = new HashMap<Point, ArrayList<Marker>>();
HashMap<Marker, Point> points = params[0];
boolean wasClustered;
for (Marker marker : points.keySet()) {
Point point = points.get(marker);
wasClustered = false;
for (Point existingPoint : clusters.keySet()) {
if (findDistance(point.x, point.y, existingPoint.x, existingPoint.y) < 25) {
wasClustered = true;
clusters.get(existingPoint).add(marker);
break;
}
}
if (!wasClustered) {
ArrayList<Marker> markersForPoint = new ArrayList<Marker>();
markersForPoint.add(marker);
clusters.put(point, markersForPoint);
}
}
return clusters;
}
@Override
protected void onPostExecute(HashMap<Point, ArrayList<Marker>> clusters) {
for (Point point : clusters.keySet()) {
ArrayList<Marker> markersForPoint = clusters.get(point);
Marker mainMarker = markersForPoint.get(0);
mainMarker.setTitle(Integer.toString(markersForPoint.size()));
mainMarker.setVisible(true);
}
}
}
}
ご覧のとおり、すべての可視マーカーにはタイトルが必要ですが、実際にはそうでないことがよくあります。何が間違っているのですか?
UPD:各 CameraChange で map.clear() と readd マーカーを呼び出すと (タイトルと可視性を置き換えるのではなく)、すべて正常に動作することがわかりました。私には奇妙に見えます