如何根据osmdroid中的标记数量设置簇的图标?
How to set the icon of cluster based on number of markers in osmdroid?
我在 osmdroid 中使用集群。最初有一个大集群。在缩放集群时,集群会分成两个单独的集群。然后在进一步缩放时,这些集群会分解为标记数量较少的较小集群。
我想要的是根据集群拥有的标记数量为集群设置不同的图标。
radiusMarkerClusterer.setRadius(40);
radiusMarkerClusterer.setMaxClusteringZoomLevel(17);
radiusMarkerClusterer.reversedClusters();
for (int i = 0; i < alert.size(); i++) {
position = new GeoPoint(Double.parseDouble(alert.get(i).getLatitude()), Double.parseDouble(alert.get(i).getLongitude()));
marker = new Marker(map);
marker.setPosition(position);
mapController.animateTo(position);
Log.i(TAG, "MArker added to cluster ");
radiusMarkerClusterer.add(marker);
}
map.getOverlays().add(radiusMarkerClusterer);
这就是我现在实现集群的方式。有办法吗?
RadiusMarkerClusterer 不支持不同缩放比例的不同绘图。您需要创建自定义 MarkerClusterer 子类。
查看 RadiusMarkerClusterer 的来源以获取指导和灵感。标记的可绘制对象是在方法 buildClusterMarker
中创建的
@Override public Marker buildClusterMarker(StaticCluster cluster, MapView mapView)
如您所见,可以访问 MapView,因此您可以获得当前缩放级别并决定应使用哪个图标。
创建自定义 class RadiusMarkerClusterer。
import android.content.Context;
import android.graphics.*;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v4.content.res.ResourcesCompat;
import android.util.Log;
import android.view.MotionEvent;
import com.kintanpatel.mygmail.R;
import org.osmdroid.bonuspack.clustering.MarkerClusterer;
import org.osmdroid.bonuspack.clustering.StaticCluster;
import org.osmdroid.util.BoundingBox;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.Marker;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Objects;
/**
* Radius-based Clustering algorithm:
* create a cluster using the first point from the cloned list.
* All points that are found within the neighborhood are added to this cluster.
* Then all the neighbors and the main point are removed from the list of points.
* It continues until the list is empty.
* <p>
* Largely inspired from GridMarkerClusterer by M.Kergall
*
* @author sidorovroman92@gmail.com
*/
public class RadiusMarkerClusterer extends MarkerClusterer {
/**
* cluster icon anchor
*/
public float mAnchorU = Marker.ANCHOR_CENTER, mAnchorV = Marker.ANCHOR_CENTER;
/**
* anchor point to draw the number of markers inside the cluster icon
*/
public float mTextAnchorU = Marker.ANCHOR_CENTER, mTextAnchorV = Marker.ANCHOR_CENTER;
protected int mMaxClusteringZoomLevel = 17;
protected int mRadiusInPixels = 100;
protected double mRadiusInMeters;
protected Paint mTextPaint;
private ArrayList<Marker> mClonedMarkers;
private Context mContext;
public RadiusMarkerClusterer(Context ctx) {
super();
mTextPaint = new Paint();
mTextPaint.setColor(Color.WHITE);
mTextPaint.setTextSize(15 * ctx.getResources().getDisplayMetrics().density);
mTextPaint.setFakeBoldText(true);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setAntiAlias(true);
Drawable clusterIconD = ctx.getResources().getDrawable(org.osmdroid.bonuspack.R.drawable.marker_cluster);
Bitmap clusterIcon = ((BitmapDrawable) clusterIconD).getBitmap();
setIcon(clusterIcon);
mContext = ctx;
}
/**
* If you want to change the default text paint (color, size, font)
*/
public Paint getTextPaint() {
return mTextPaint;
}
/**
* Set the radius of clustering in pixels. Default is 100px.
*/
public void setRadius(int radius) {
mRadiusInPixels = radius;
}
/**
* Set max zoom level with clustering. When zoom is higher or equal to this level, clustering is disabled.
* You can put a high value to disable this feature.
*/
public void setMaxClusteringZoomLevel(int zoom) {
mMaxClusteringZoomLevel = zoom;
}
/**
* Radius-Based clustering algorithm
*/
@Override
public ArrayList<org.osmdroid.bonuspack.clustering.StaticCluster> clusterer(MapView mapView) {
ArrayList<org.osmdroid.bonuspack.clustering.StaticCluster> clusters = new ArrayList<org.osmdroid.bonuspack.clustering.StaticCluster>();
convertRadiusToMeters(mapView);
mClonedMarkers = new ArrayList<Marker>(mItems); //shallow copy
while (!mClonedMarkers.isEmpty()) {
Marker m = mClonedMarkers.get(0);
org.osmdroid.bonuspack.clustering.StaticCluster cluster = createCluster(m, mapView);
clusters.add(cluster);
}
return clusters;
}
private org.osmdroid.bonuspack.clustering.StaticCluster createCluster(Marker m, MapView mapView) {
GeoPoint clusterPosition = m.getPosition();
org.osmdroid.bonuspack.clustering.StaticCluster cluster = new org.osmdroid.bonuspack.clustering.StaticCluster(clusterPosition);
cluster.add(m);
mClonedMarkers.remove(m);
if (mapView.getZoomLevel() > mMaxClusteringZoomLevel) {
//above max level => block clustering:
return cluster;
}
Iterator<Marker> it = mClonedMarkers.iterator();
while (it.hasNext()) {
Marker neighbour = it.next();
double distance = clusterPosition.distanceToAsDouble(neighbour.getPosition());
if (distance <= mRadiusInMeters) {
cluster.add(neighbour);
it.remove();
}
}
return cluster;
}
@Override
public Marker buildClusterMarker(org.osmdroid.bonuspack.clustering.StaticCluster cluster, MapView mapView) {
Marker m = new Marker(mapView);
m.setPosition(cluster.getPosition());
m.setInfoWindow(null);
m.setAnchor(mAnchorU, mAnchorV);
Log.e("cluster size", cluster.getSize() + "");
int clusterSize = cluster.getSize();
if (clusterSize < 1000 && clusterSize > 500) {
Drawable clusterIconD = ResourcesCompat.getDrawable(mContext.getResources(), R.drawable.red_cluster, null);
mClusterIcon = ((BitmapDrawable) Objects.requireNonNull(clusterIconD)).getBitmap();
} else if (clusterSize > 50) {
Drawable clusterIconD = ResourcesCompat.getDrawable(mContext.getResources(), R.drawable.red_cluster, null);
mClusterIcon = ((BitmapDrawable) Objects.requireNonNull(clusterIconD)).getBitmap();
} else {
Drawable clusterIconD = ResourcesCompat.getDrawable(mContext.getResources(), R.drawable.cluster, null);
mClusterIcon = ((BitmapDrawable) Objects.requireNonNull(clusterIconD)).getBitmap();
}
Bitmap finalIcon = Bitmap.createBitmap(mClusterIcon.getWidth(), mClusterIcon.getHeight(), mClusterIcon.getConfig());
Canvas iconCanvas = new Canvas(finalIcon);
iconCanvas.drawBitmap(mClusterIcon, 0, 0, null);
String text = "" + cluster.getSize();
int textHeight = (int) (mTextPaint.descent() + mTextPaint.ascent());
iconCanvas.drawText(text,
mTextAnchorU * finalIcon.getWidth(),
mTextAnchorV * finalIcon.getHeight() - textHeight / 2,
mTextPaint);
m.setIcon(new BitmapDrawable(mapView.getContext().getResources(), finalIcon));
// swapFunction(cluster.getSize());
return m;
}
@Override
public void renderer(ArrayList<org.osmdroid.bonuspack.clustering.StaticCluster> clusters, Canvas canvas, MapView mapView) {
for (StaticCluster cluster : clusters) {
if (cluster.getSize() == 1) {
//cluster has only 1 marker => use it as it is:
cluster.setMarker(cluster.getItem(0));
} else {
//only draw 1 Marker at Cluster center, displaying number of Markers contained
Marker m = buildClusterMarker(cluster, mapView);
cluster.setMarker(m);
}
Log.e("cluster size", cluster.getSize() + "");
}
//swapFunction(clusters, mapView);
}
private void convertRadiusToMeters(MapView mapView) {
Rect mScreenRect = mapView.getIntrinsicScreenRect(null);
int screenWidth = mScreenRect.right - mScreenRect.left;
int screenHeight = mScreenRect.bottom - mScreenRect.top;
BoundingBox bb = mapView.getBoundingBox();
double diagonalInMeters = bb.getDiagonalLengthInMeters();
double diagonalInPixels = Math.sqrt(screenWidth * screenWidth + screenHeight * screenHeight);
double metersInPixel = diagonalInMeters / diagonalInPixels;
mRadiusInMeters = mRadiusInPixels * metersInPixel;
}
}
在您的地图中添加以下代码activity
GeoPoint startPoint = new GeoPoint(20.5992, 72.9342);
/* Drawable clusterIconD = ResourcesCompat.getDrawable(getResources(), R.drawable.cluster, null);
Bitmap clusterIcon = ((BitmapDrawable) Objects.requireNonNull(clusterIconD)).getBitmap();*/
RadiusMarkerClusterer poiMarkers = new RadiusMarkerClusterer(this, this);
// poiMarkers.setIcon(clusterIcon);
poiMarkers.mTextAnchorU = 0.50f;
poiMarkers.mTextAnchorV = 0.50f;
poiMarkers.getTextPaint().setTextSize(12 * getResources().getDisplayMetrics().density);
poiMarkers.mAnchorV = Marker.ANCHOR_CENTER;
poiMarkers.setRadius(500);
mapView.getOverlays().add(poiMarkers);
for (LiveTrackingModel al : list) {
Marker poiMarker = new Marker(mapView);
poiMarker.setTitle(al.getVEHICLE_NUMBER());
poiMarker.setPosition(new GeoPoint(Double.parseDouble(al.getLAT()), Double.parseDouble(al.getLON())));
poiMarker.setIcon(this.getResources().getDrawable(R.drawable.compactor_running));
poiMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
/* InfoWindow infoWindow = new MyInfoWindow(R.layout.bonuspack_bubble, mMapView);
startMarker.setInfoWindow(infoWindow);*/
//poiMarker.setInfoWindow();
//poiMarker.setRelatedObject(poi);
poiMarkers.add(poiMarker);
}
poiMarkers.buildClusterMarker(new StaticCluster(startPoint), mapView);
poiMarkers.clusterer(mapView);
我在 osmdroid 中使用集群。最初有一个大集群。在缩放集群时,集群会分成两个单独的集群。然后在进一步缩放时,这些集群会分解为标记数量较少的较小集群。
我想要的是根据集群拥有的标记数量为集群设置不同的图标。
radiusMarkerClusterer.setRadius(40);
radiusMarkerClusterer.setMaxClusteringZoomLevel(17);
radiusMarkerClusterer.reversedClusters();
for (int i = 0; i < alert.size(); i++) {
position = new GeoPoint(Double.parseDouble(alert.get(i).getLatitude()), Double.parseDouble(alert.get(i).getLongitude()));
marker = new Marker(map);
marker.setPosition(position);
mapController.animateTo(position);
Log.i(TAG, "MArker added to cluster ");
radiusMarkerClusterer.add(marker);
}
map.getOverlays().add(radiusMarkerClusterer);
这就是我现在实现集群的方式。有办法吗?
RadiusMarkerClusterer 不支持不同缩放比例的不同绘图。您需要创建自定义 MarkerClusterer 子类。
查看 RadiusMarkerClusterer 的来源以获取指导和灵感。标记的可绘制对象是在方法 buildClusterMarker
中创建的@Override public Marker buildClusterMarker(StaticCluster cluster, MapView mapView)
如您所见,可以访问 MapView,因此您可以获得当前缩放级别并决定应使用哪个图标。
创建自定义 class RadiusMarkerClusterer。
import android.content.Context;
import android.graphics.*;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v4.content.res.ResourcesCompat;
import android.util.Log;
import android.view.MotionEvent;
import com.kintanpatel.mygmail.R;
import org.osmdroid.bonuspack.clustering.MarkerClusterer;
import org.osmdroid.bonuspack.clustering.StaticCluster;
import org.osmdroid.util.BoundingBox;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.Marker;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Objects;
/**
* Radius-based Clustering algorithm:
* create a cluster using the first point from the cloned list.
* All points that are found within the neighborhood are added to this cluster.
* Then all the neighbors and the main point are removed from the list of points.
* It continues until the list is empty.
* <p>
* Largely inspired from GridMarkerClusterer by M.Kergall
*
* @author sidorovroman92@gmail.com
*/
public class RadiusMarkerClusterer extends MarkerClusterer {
/**
* cluster icon anchor
*/
public float mAnchorU = Marker.ANCHOR_CENTER, mAnchorV = Marker.ANCHOR_CENTER;
/**
* anchor point to draw the number of markers inside the cluster icon
*/
public float mTextAnchorU = Marker.ANCHOR_CENTER, mTextAnchorV = Marker.ANCHOR_CENTER;
protected int mMaxClusteringZoomLevel = 17;
protected int mRadiusInPixels = 100;
protected double mRadiusInMeters;
protected Paint mTextPaint;
private ArrayList<Marker> mClonedMarkers;
private Context mContext;
public RadiusMarkerClusterer(Context ctx) {
super();
mTextPaint = new Paint();
mTextPaint.setColor(Color.WHITE);
mTextPaint.setTextSize(15 * ctx.getResources().getDisplayMetrics().density);
mTextPaint.setFakeBoldText(true);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setAntiAlias(true);
Drawable clusterIconD = ctx.getResources().getDrawable(org.osmdroid.bonuspack.R.drawable.marker_cluster);
Bitmap clusterIcon = ((BitmapDrawable) clusterIconD).getBitmap();
setIcon(clusterIcon);
mContext = ctx;
}
/**
* If you want to change the default text paint (color, size, font)
*/
public Paint getTextPaint() {
return mTextPaint;
}
/**
* Set the radius of clustering in pixels. Default is 100px.
*/
public void setRadius(int radius) {
mRadiusInPixels = radius;
}
/**
* Set max zoom level with clustering. When zoom is higher or equal to this level, clustering is disabled.
* You can put a high value to disable this feature.
*/
public void setMaxClusteringZoomLevel(int zoom) {
mMaxClusteringZoomLevel = zoom;
}
/**
* Radius-Based clustering algorithm
*/
@Override
public ArrayList<org.osmdroid.bonuspack.clustering.StaticCluster> clusterer(MapView mapView) {
ArrayList<org.osmdroid.bonuspack.clustering.StaticCluster> clusters = new ArrayList<org.osmdroid.bonuspack.clustering.StaticCluster>();
convertRadiusToMeters(mapView);
mClonedMarkers = new ArrayList<Marker>(mItems); //shallow copy
while (!mClonedMarkers.isEmpty()) {
Marker m = mClonedMarkers.get(0);
org.osmdroid.bonuspack.clustering.StaticCluster cluster = createCluster(m, mapView);
clusters.add(cluster);
}
return clusters;
}
private org.osmdroid.bonuspack.clustering.StaticCluster createCluster(Marker m, MapView mapView) {
GeoPoint clusterPosition = m.getPosition();
org.osmdroid.bonuspack.clustering.StaticCluster cluster = new org.osmdroid.bonuspack.clustering.StaticCluster(clusterPosition);
cluster.add(m);
mClonedMarkers.remove(m);
if (mapView.getZoomLevel() > mMaxClusteringZoomLevel) {
//above max level => block clustering:
return cluster;
}
Iterator<Marker> it = mClonedMarkers.iterator();
while (it.hasNext()) {
Marker neighbour = it.next();
double distance = clusterPosition.distanceToAsDouble(neighbour.getPosition());
if (distance <= mRadiusInMeters) {
cluster.add(neighbour);
it.remove();
}
}
return cluster;
}
@Override
public Marker buildClusterMarker(org.osmdroid.bonuspack.clustering.StaticCluster cluster, MapView mapView) {
Marker m = new Marker(mapView);
m.setPosition(cluster.getPosition());
m.setInfoWindow(null);
m.setAnchor(mAnchorU, mAnchorV);
Log.e("cluster size", cluster.getSize() + "");
int clusterSize = cluster.getSize();
if (clusterSize < 1000 && clusterSize > 500) {
Drawable clusterIconD = ResourcesCompat.getDrawable(mContext.getResources(), R.drawable.red_cluster, null);
mClusterIcon = ((BitmapDrawable) Objects.requireNonNull(clusterIconD)).getBitmap();
} else if (clusterSize > 50) {
Drawable clusterIconD = ResourcesCompat.getDrawable(mContext.getResources(), R.drawable.red_cluster, null);
mClusterIcon = ((BitmapDrawable) Objects.requireNonNull(clusterIconD)).getBitmap();
} else {
Drawable clusterIconD = ResourcesCompat.getDrawable(mContext.getResources(), R.drawable.cluster, null);
mClusterIcon = ((BitmapDrawable) Objects.requireNonNull(clusterIconD)).getBitmap();
}
Bitmap finalIcon = Bitmap.createBitmap(mClusterIcon.getWidth(), mClusterIcon.getHeight(), mClusterIcon.getConfig());
Canvas iconCanvas = new Canvas(finalIcon);
iconCanvas.drawBitmap(mClusterIcon, 0, 0, null);
String text = "" + cluster.getSize();
int textHeight = (int) (mTextPaint.descent() + mTextPaint.ascent());
iconCanvas.drawText(text,
mTextAnchorU * finalIcon.getWidth(),
mTextAnchorV * finalIcon.getHeight() - textHeight / 2,
mTextPaint);
m.setIcon(new BitmapDrawable(mapView.getContext().getResources(), finalIcon));
// swapFunction(cluster.getSize());
return m;
}
@Override
public void renderer(ArrayList<org.osmdroid.bonuspack.clustering.StaticCluster> clusters, Canvas canvas, MapView mapView) {
for (StaticCluster cluster : clusters) {
if (cluster.getSize() == 1) {
//cluster has only 1 marker => use it as it is:
cluster.setMarker(cluster.getItem(0));
} else {
//only draw 1 Marker at Cluster center, displaying number of Markers contained
Marker m = buildClusterMarker(cluster, mapView);
cluster.setMarker(m);
}
Log.e("cluster size", cluster.getSize() + "");
}
//swapFunction(clusters, mapView);
}
private void convertRadiusToMeters(MapView mapView) {
Rect mScreenRect = mapView.getIntrinsicScreenRect(null);
int screenWidth = mScreenRect.right - mScreenRect.left;
int screenHeight = mScreenRect.bottom - mScreenRect.top;
BoundingBox bb = mapView.getBoundingBox();
double diagonalInMeters = bb.getDiagonalLengthInMeters();
double diagonalInPixels = Math.sqrt(screenWidth * screenWidth + screenHeight * screenHeight);
double metersInPixel = diagonalInMeters / diagonalInPixels;
mRadiusInMeters = mRadiusInPixels * metersInPixel;
}
}
在您的地图中添加以下代码activity
GeoPoint startPoint = new GeoPoint(20.5992, 72.9342);
/* Drawable clusterIconD = ResourcesCompat.getDrawable(getResources(), R.drawable.cluster, null);
Bitmap clusterIcon = ((BitmapDrawable) Objects.requireNonNull(clusterIconD)).getBitmap();*/
RadiusMarkerClusterer poiMarkers = new RadiusMarkerClusterer(this, this);
// poiMarkers.setIcon(clusterIcon);
poiMarkers.mTextAnchorU = 0.50f;
poiMarkers.mTextAnchorV = 0.50f;
poiMarkers.getTextPaint().setTextSize(12 * getResources().getDisplayMetrics().density);
poiMarkers.mAnchorV = Marker.ANCHOR_CENTER;
poiMarkers.setRadius(500);
mapView.getOverlays().add(poiMarkers);
for (LiveTrackingModel al : list) {
Marker poiMarker = new Marker(mapView);
poiMarker.setTitle(al.getVEHICLE_NUMBER());
poiMarker.setPosition(new GeoPoint(Double.parseDouble(al.getLAT()), Double.parseDouble(al.getLON())));
poiMarker.setIcon(this.getResources().getDrawable(R.drawable.compactor_running));
poiMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
/* InfoWindow infoWindow = new MyInfoWindow(R.layout.bonuspack_bubble, mMapView);
startMarker.setInfoWindow(infoWindow);*/
//poiMarker.setInfoWindow();
//poiMarker.setRelatedObject(poi);
poiMarkers.add(poiMarker);
}
poiMarkers.buildClusterMarker(new StaticCluster(startPoint), mapView);
poiMarkers.clusterer(mapView);