/* * Copyright 2010, 2011, 2012 mapsforge.org * * This program is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ package org.mapsforge.android.maps.overlay; import org.mapsforge.core.model.BoundingBox; import org.mapsforge.core.model.GeoPoint; import org.mapsforge.core.model.Point; import org.mapsforge.core.util.MercatorProjection; import android.graphics.Canvas; import android.graphics.Paint; /** * A {@code Circle} consists of a center {@link GeoPoint} and a non-negative radius in meters. * <p> * A {@code Circle} holds two {@link Paint} objects to allow for different outline and filling. These paints define * drawing parameters such as color, stroke width, pattern and transparency. {@link Paint#setAntiAlias Anti-aliasing} * should be enabled to minimize visual distortions and to improve the overall drawing quality. */ public class Circle implements OverlayItem { private static void checkRadius(float radius) { if (radius < 0) { throw new IllegalArgumentException("radius must not be negative: " + radius); } } private static double metersToPixels(double latitude, float meters, byte zoom) { double groundResolution = MercatorProjection.calculateGroundResolution(latitude, zoom); return meters / groundResolution; } private GeoPoint geoPoint; private Paint paintFill; private Paint paintStroke; private float radius; /** * @param geoPoint * the initial center point of this circle (may be null). * @param radius * the initial non-negative radius of this circle in meters. * @param paintFill * the initial {@code Paint} used to fill this circle (may be null). * @param paintStroke * the initial {@code Paint} used to stroke this circle (may be null). * @throws IllegalArgumentException * if the given {@code radius} is negative. */ public Circle(GeoPoint geoPoint, float radius, Paint paintFill, Paint paintStroke) { checkRadius(radius); this.geoPoint = geoPoint; this.radius = radius; this.paintFill = paintFill; this.paintStroke = paintStroke; } @Override public synchronized boolean draw(BoundingBox boundingBox, byte zoomLevel, Canvas canvas, Point canvasPosition) { if (this.geoPoint == null || (this.paintStroke == null && this.paintFill == null)) { return false; } double latitude = this.geoPoint.latitude; double longitude = this.geoPoint.longitude; float pixelX = (float) (MercatorProjection.longitudeToPixelX(longitude, zoomLevel) - canvasPosition.x); float pixelY = (float) (MercatorProjection.latitudeToPixelY(latitude, zoomLevel) - canvasPosition.y); float radiusInPixel = (float) metersToPixels(latitude, this.radius, zoomLevel); if (this.paintStroke != null) { canvas.drawCircle(pixelX, pixelY, radiusInPixel, this.paintStroke); } if (this.paintFill != null) { canvas.drawCircle(pixelX, pixelY, radiusInPixel, this.paintFill); } return true; } /** * @return the center point of this circle (may be null). */ public synchronized GeoPoint getGeoPoint() { return this.geoPoint; } /** * @return the {@code Paint} used to fill this circle (may be null). */ public synchronized Paint getPaintFill() { return this.paintFill; } /** * @return the {@code Paint} used to stroke this circle (may be null). */ public synchronized Paint getPaintStroke() { return this.paintStroke; } /** * @return the non-negative radius of this circle in meters. */ public synchronized float getRadius() { return this.radius; } /** * @param geoPoint * the new center point of this circle (may be null). */ public synchronized void setGeoPoint(GeoPoint geoPoint) { this.geoPoint = geoPoint; } /** * @param paintFill * the new {@code Paint} used to fill this circle (may be null). */ public synchronized void setPaintFill(Paint paintFill) { this.paintFill = paintFill; } /** * @param paintStroke * the new {@code Paint} used to stroke this circle (may be null). */ public synchronized void setPaintStroke(Paint paintStroke) { this.paintStroke = paintStroke; } /** * @param radius * the new non-negative radius of this circle in meters. * @throws IllegalArgumentException * if the given {@code radius} is negative. */ public synchronized void setRadius(float radius) { checkRadius(radius); this.radius = radius; } }