2012-12-19 109 views
6

在Google Maps for Android的V1中,我使用ItemizedOverlay類實現了一種形式的聚類。每個羣集都有一箇中心點(緯度/經度),半徑(以英里爲單位)以及羣集中項目的數量。我使用了ItemizedOverlay.draw(Canvas,MapView,shadow)來繪製使用Canvas對象方法(如drawCircle()和drawText())的集羣。每個簇由包含計數的實心圓圈(根據計數所需的空間大小)和顯示半徑的圓圈組成。替代Google Maps V2 for Android中的ItemizedOverlay?

閱讀V2上的文檔並使用演示應用程序播放後,我看不到等效於ItemizedOverlay,也沒有明顯的選擇。我懷疑要做到這一點的唯一方法是自己維護一個集羣列表,然後子類MapView並提供其onDraw()方法的實現。

我在V2 API中遺漏了哪些東西比繼承MapView更好嗎?

感謝,

馬克

+0

我想過另一種看起來更好的替代方法:使用標記類,但不是提供靜態圖像,而是通過創建所需大小的Bitmap對象並使用Canvas對象繪製它來即時創建圖像。 Mark –

+0

上面的替代方案可能需要省略簇半徑,因爲這會使得整個事物(而不僅僅是包含計數的圓)受到命中測試的影響,從而防止點擊到達半徑圓下面的事物計數圈。 –

+0

使用位圖對象比使用Drawable有更好的性能嗎? –

回答

4

經過一番研究,我還沒有發現比上飛的標記創建位圖或者任何更好的選擇。但我也在地圖上創建了帶多邊形的圓。請注意,這不是真正高性能的解決方案,但對我而言,這是一個不錯的選擇。 代碼示例:

private static final int CIRCLE_POLYGON_VERTICES = 16; 
private static final double EARTH_RADIUS = 6378.1d; 


private List<LatLng> createCirclePolygon(LatLng center, double r) { 
    List<LatLng> res = new ArrayList<LatLng>(CIRCLE_POLYGON_VERTICES); 

    double r_latitude = MathUtils.rad2deg(r/EARTH_RADIUS); 
    double r_longitude = r_latitude/Math.cos(MathUtils.deg2rad(center.latitude)); 

    for (int point = 0; point < CIRCLE_POLYGON_VERTICES + 1; point++) { 
     double theta = Math.PI * ((double)point/(CIRCLE_POLYGON_VERTICES/2)); 
     double circle_x = center.longitude + (r_longitude * Math.cos(theta)); 
     double circle_y = center.latitude + (r_latitude * Math.sin(theta));  

     res.add(new LatLng(circle_y, circle_x)); 
    } 
    return res; 
} 

private Bitmap getClusteredLabel(String cnt, Context ctx) { 
    Resources r = ctx.getResources(); 
    Bitmap res = BitmapFactory.decodeResource(r, R.drawable.map_cluster_bg);   
    res = res.copy(Bitmap.Config.ARGB_8888, true); 
    Canvas c = new Canvas(res); 

    Paint textPaint = new Paint(); 
    textPaint.setAntiAlias(true); 
    textPaint.setTextAlign(Paint.Align.CENTER); 
    textPaint.setTypeface(Typeface.DEFAULT_BOLD); 
    textPaint.setColor(Color.WHITE); 
    textPaint.setTextSize(21);  

    c.drawText(String.valueOf(cnt), res.getWidth()/2, res.getHeight()/2 + textPaint.getTextSize()/3, textPaint); 

    return res; 
} 

public void createClusteredOverlay(MapPinData point, GoogleMap map, Context ctx) { 
    if (point.getCount() > 1) { 
     map.addMarker(new MarkerOptions().position(point.getLatLng()).anchor(0.5f, 0.5f).icon(BitmapDescriptorFactory.fromBitmap(getClusteredLabel(String.valueOf(point.getCount()), ctx)))); 

     map.addPolygon(new PolygonOptions()   
     .addAll(createCirclePolygon(point.getLatLng(), point.getRadius())) 
     .fillColor(Color.argb(50, 0, 0, 10))  
     .strokeWidth(0) 
     ); 
    } else { 
     map.addMarker(new MarkerOptions().position(point.getLatLng()).title(point.getTitle())); 
    } 
} 

我MathUtils方法:

public static double deg2rad(double deg) { 
    return (deg * Math.PI/180.0); 
} 

public static double rad2deg(double rad) { 
    return (rad * 180.0/Math.PI); 
} 

如果你在方圓百里,你應該改變EARTH_RADIUS常數英里,3963 AFAIK。

+0

它看起來像是產生了一些形狀的標記,其中聚類計數在內部繪製,周圍的圓圈表示半徑的近似值,所有這些標記都是相同的尺寸? 如果所有標記具有相同的尺寸並且每個半徑始終可見,那麼這是可行的,並且確保只有標記可以被挖掘。我希望找到一種方法來使用事件作爲繪製半徑的觸發器,但理想事件(長按)不可用於標記。 –

+0

您還可以使用內置方法進行rad <-> deg轉換。 1. Math.toDegrees(angrad)2. Math.toRadians(angdeg) – rajankz

相關問題