The logic behind map clustering is relatively simple. Something like the following pseudo code would do:
Code:
Create cluster list.
//For each marker within the current viewport ....
for (int i= 0; index < markers.Count; i++)
{
if (cluster nearby?){
add marker to nearest cluster.
} else {
create new cluster
add marker to cluster
add cluster to cluster list
}
}
return cluster list;
As well as holding an array of associated markers, any cluster needs two further properties - a center point and a radius.
The simplest way to set a centre point would be to use the location of the first marker in the cluster.
The distances should really be related to the viewport size i.e the distance between the
The "nearby" bit can be done using the Haversine formula ie. Geocordinate.distanceTo()
The reason there is no MapComponent providing clustering on the device is due to the limits of the Java ME environment. It doesn't make sense to hold the information about 10,000 markers on a device and it is very likely to run out of memory.
Your best bet would be to look at server side clustering. You could create a MapComponent that overrides mapUpdated so that when the viewport changes it makes a request to a server passing back the coordinates of the viewport. The server would then return the details of the markers within the viewport using clustering as necessary in the form of an XML or JSON file. As a refinement I'd suggest loading a slighltly larger area than the viewport so you only need to make another server request if the user has panned out of area (or altered the zoom.)
If you can move the computations server side, the Maps API is reduced to being a presentation layer, which is the job it does best.
Code:
public abstract class ClusterComponent implements MapComponent {
...
protected MapDisplay map;
private double thresholdDistance;
public void attach(MapDisplay map) {
this.map = map;
radius= map.getCenter().distanceTo(
map.pixelToGeo(
new Point(map.getWidth(), map.getHeight())));
}
// from MapComponent
public void mapUpdated(boolean zoomChanged) {
mapUrl = getMapURL(map);
if (zoomChanged || map.getCenter().distanceTo(coord) > radius/2) {
//map.getCenter();
// radius= map.getCenter().distanceTo(
// map.pixelToGeo(
// new Point(map.getWidth(), map.getHeight())));
// 1) Create new thread....
// 2) Make Server request passing in centerpoint and radius...
// 3) When received clear all points and re-add markers.
// etc.
}
}