【问题标题】:Changing cluster color based on cluster size using osmdroid使用 osmdroid 根据集群大小更改集群颜色
【发布时间】:2018-09-07 17:27:35
【问题描述】:

我正在尝试根据集群大小在我的地图上添加不同颜色的集群。

为此,我子类化 MarkerClusterer并根据我的要求更改了代码。

下面是代码

public class CustomMarkerClusterer extends MarkerClusterer {

protected int mMaxClusteringZoomLevel = 17;
protected int mRadiusInPixels = 100;
protected double mRadiusInMeters;
protected Paint mTextPaint;
private ArrayList<Marker> mClonedMarkers;
private Context context;

/**
 * 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;

public CustomMarkerClusterer(Context ctx) {
    super();
    mTextPaint = new Paint();
    mTextPaint.setColor(Color.BLACK);
    mTextPaint.setTextSize(15 * ctx.getResources().getDisplayMetrics().density);
    mTextPaint.setFakeBoldText(true);
    mTextPaint.setTextAlign(Paint.Align.CENTER);
    mTextPaint.setAntiAlias(true);
    this.context = ctx;
    Drawable clusterIconD = ctx.getResources().getDrawable(R.drawable.cluster2);
    Bitmap clusterIcon = ((BitmapDrawable) clusterIconD).getBitmap();
    setIcon(clusterIcon);
}

/**
 * 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<StaticCluster> clusterer(MapView mapView) {

    ArrayList<StaticCluster> clusters = new ArrayList<StaticCluster>();
    convertRadiusToMeters(mapView);

    mClonedMarkers = new ArrayList<Marker>(mItems); //shallow copy
    while (!mClonedMarkers.isEmpty()) {
        Marker m = mClonedMarkers.get(0);
        StaticCluster cluster = createCluster(m, mapView);
        clusters.add(cluster);
    }
    return clusters;
}

private StaticCluster createCluster(Marker m, MapView mapView) {
    GeoPoint clusterPosition = m.getPosition();

    StaticCluster cluster = new 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(StaticCluster cluster, MapView mapView) {
    Marker m = new Marker(mapView);
    m.setPosition(cluster.getPosition());
    m.setInfoWindow(null);
    m.setAnchor(mAnchorU, mAnchorV);
    Bitmap mutableBitmap=null;

    if (cluster.getSize() < 10) {
        Bitmap icon = Bitmap.createBitmap(((BitmapDrawable) context.getResources().getDrawable(R.drawable.cluster1)).getBitmap());
        mutableBitmap = icon.copy(Bitmap.Config.ARGB_8888, true);

        Canvas iconCanvas = new Canvas(mutableBitmap);
        iconCanvas.drawBitmap(mClusterIcon, 0, 0, null);
        String text = "" + cluster.getSize();
        int textHeight = (int) (mTextPaint.descent() + mTextPaint.ascent());
        iconCanvas.drawText(text,
                mTextAnchorU * icon.getWidth(),
                mTextAnchorV * icon.getHeight() - textHeight / 2,
                mTextPaint);
       // m.setIcon(new BitmapDrawable(mapView.getContext().getResources(), mutableBitmap));
    } else if (cluster.getSize() > 10 && cluster.getSize() < 100) {
        Bitmap icon = Bitmap.createBitmap(((BitmapDrawable) context.getResources().getDrawable(R.drawable.cluster3)).getBitmap());
         mutableBitmap = icon.copy(Bitmap.Config.ARGB_8888, true);
        Canvas iconCanvas = new Canvas(mutableBitmap);
        iconCanvas.drawBitmap(mClusterIcon, 0, 0, null);
        String text = "" + cluster.getSize();
        int textHeight = (int) (mTextPaint.descent() + mTextPaint.ascent());
        iconCanvas.drawText(text,
                mTextAnchorU * icon.getWidth(),
                mTextAnchorV * icon.getHeight() - textHeight / 2,
                mTextPaint);
       // m.setIcon(new BitmapDrawable(mapView.getContext().getResources(), mutableBitmap));
    } else if (cluster.getSize() > 100) {
        Bitmap icon = Bitmap.createBitmap(((BitmapDrawable) context.getResources().getDrawable(R.drawable.cluster2)).getBitmap());
        mutableBitmap = icon.copy(Bitmap.Config.ARGB_8888, true);
        Canvas iconCanvas = new Canvas(mutableBitmap);
        iconCanvas.drawBitmap(mClusterIcon, 0, 0, null);
        String text = "" + cluster.getSize();
        int textHeight = (int) (mTextPaint.descent() + mTextPaint.ascent());
        iconCanvas.drawText(text,
                mTextAnchorU * icon.getWidth(),
                mTextAnchorV * icon.getHeight() - textHeight / 2,
                mTextPaint);
      //  m.setIcon(new BitmapDrawable(mapView.getContext().getResources(), mutableBitmap));
    }
    m.setIcon(new BitmapDrawable(mapView.getContext().getResources(), mutableBitmap));

    return m;
}

@Override
public void renderer(ArrayList<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);
        }
    }
}

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;
}}

buildClusterMarker() 是我尝试根据集群大小为集群分配不同图像的方法。

当我调试代码时它工作正常,但它只设置了在类的构造函数中定义的单色簇。如果我在那里更改图像,它会被更改,但对于所有集群。

【问题讨论】:

    标签: android openstreetmap osmdroid


    【解决方案1】:

    buildClusterMakerMethod()中的代码有3个类似的分支,这里是第一个:

        Bitmap icon = Bitmap.createBitmap(((BitmapDrawable) context.getResources().getDrawable(R.drawable.cluster1)).getBitmap());
        mutableBitmap = icon.copy(Bitmap.Config.ARGB_8888, true);
    
        Canvas iconCanvas = new Canvas(mutableBitmap);
        iconCanvas.drawBitmap(mClusterIcon, 0, 0, null); //<=== HERE
        ...
    

    让我们逐行浏览代码。

    1) 有一个从可绘制的R.drawable.cluster1 创建的位图并存储在icon 变量中。

    2) 图标的副本存储在mutableBitmap 变量中。

    3) mutableBitmap 用于创建画布。这意味着,在画布上执行的所有操作都将被绘制到该位图中。

    4) 原始图标(存储在mClusterIcon 字段中)被绘制在画布上 所需的位图上,从而用构造函数中设置的图标/位图覆盖它。

    这发生在所有 3 个分支上。

    您可以删除所有出现的行(iconCanvas.drawBitmap(mClusterIcon, 0, 0, null); 以解决问题。

    【讨论】:

    • 你能再解释一下吗。没明白你的意思
    • @VivekMishra 我已经编辑了回复并试图使其更清晰。好点了吗?
    • 那么如果我删除了,那么新的图标怎么设置呢?
    • @VivekMishra 新图标应该已经存在了。至少我认为这是第 1 行和第 2 行的目的,不是吗?这两行是你自己写的,它们应该做什么?
    • iconCanvas 我正在使用,因为如果直接使用图像,群集文本计数不可见
    猜你喜欢
    • 2014-09-23
    • 1970-01-01
    • 2021-11-03
    • 2020-11-01
    • 1970-01-01
    • 2015-11-21
    • 2016-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多