package org.mapsforge.android.maps; import java.util.ArrayList; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; /** * CirclesOverlay is a special Overlay to display a series of circles on top of * the map. The radius of a circle is specified in meters and will be * automatically converted to pixels at each redraw. *

* All rendering parameters like color, stroke width, pattern and transparency * can be configured via the two {@link android.graphics.Paint Paint} objects in * the {@link #CircleOverlay(Paint,Paint)} constructor. */ public class CirclesOverlay extends Overlay { private static final String THREAD_NAME = "CirclesOverlay"; private byte cachedZoomLevel; private Paint fillPaint; private Paint outlinePaint; private final Path path; private ArrayList center; private ArrayList radius; private ArrayList cachedCenterPosition; /** * Constructs a new CircleOverlay. * * @param fillPaint * the paint object which will be used to fill the overlay. * @param outlinePaint * the paint object which will be used to draw the outline of the * overlay. */ public CirclesOverlay(Paint fillPaint, Paint outlinePaint) { this.path = new Path(); this.center = new ArrayList(); this.radius = new ArrayList(); this.cachedCenterPosition = new ArrayList(); setPaint(fillPaint, outlinePaint); } public synchronized void reset() { this.center = new ArrayList(); this.radius = new ArrayList(); this.cachedCenterPosition = new ArrayList(); path.reset(); super.requestRedraw(); } /** * Sets the parameters of the circle. * * @param center * the geographical coordinates of the centre point. * @param radius * the radius of the circle in meters. */ public synchronized void addCircleData(GeoPoint center, float radius) { this.center.add(center); this.radius.add(radius); this.cachedCenterPosition.add(new Point()); this.cachedZoomLevel = Byte.MIN_VALUE; super.requestRedraw(); } /** * Sets the paint objects which will be used to draw the overlay. * * @param fillPaint * the paint object which will be used to fill the overlay. * @param outlinePaint * the paint object which will be used to draw the outline of the * overlay. */ public synchronized void setPaint(Paint fillPaint, Paint outlinePaint) { this.fillPaint = fillPaint; this.outlinePaint = outlinePaint; } @Override protected synchronized void drawOverlayBitmap(Canvas canvas, Point drawPosition, Projection projection, byte drawZoomLevel) { if (this.center.size() == 0 || this.radius.size() == 0) { // no valid parameters to draw the circle return; } else if (this.fillPaint == null && this.outlinePaint == null) { // no paint to draw return; } // make sure that the cached centre position is valid if (drawZoomLevel != this.cachedZoomLevel) { for (int i = 0; i < center.size(); i++) { Point cachedPoint = projection.toPoint(this.center.get(i), this.cachedCenterPosition.get(i), drawZoomLevel); this.cachedCenterPosition.set(i, cachedPoint); } this.cachedZoomLevel = drawZoomLevel; } // assemble the path this.path.reset(); for (int i = 0; i < cachedCenterPosition.size(); i++) { float radius_meters = projection.metersToPixels(this.radius.get(i), drawZoomLevel); this.path.addCircle(this.cachedCenterPosition.get(i).x - drawPosition.x, this.cachedCenterPosition.get(i).y - drawPosition.y, radius_meters, Path.Direction.CCW); } // draw the path on the canvas if (this.fillPaint != null) { canvas.drawPath(this.path, this.fillPaint); } if (this.outlinePaint != null) { canvas.drawPath(this.path, this.outlinePaint); } } @Override protected String getThreadName() { return THREAD_NAME; } }