/* * 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.Rect; import android.graphics.drawable.Drawable; /** * A {@code Marker} draws a {@link Drawable} at a given geographical position. */ public class Marker implements OverlayItem { /** * Sets the bounds of the given drawable so that (0,0) is the center of its bounding box. * * @param drawable * the drawable whose bounds should be set. * @return the given drawable with set bounds. */ public static Drawable boundCenter(Drawable drawable) { int intrinsicWidth = drawable.getIntrinsicWidth(); int intrinsicHeight = drawable.getIntrinsicHeight(); drawable.setBounds(intrinsicWidth / -2, intrinsicHeight / -2, intrinsicWidth / 2, intrinsicHeight / 2); return drawable; } /** * Sets the bounds of the given drawable so that (0,0) is the center of its bottom row. * * @param drawable * the drawable whose bounds should be set. * @return the given drawable with set bounds. */ public static Drawable boundCenterBottom(Drawable drawable) { int intrinsicWidth = drawable.getIntrinsicWidth(); int intrinsicHeight = drawable.getIntrinsicHeight(); drawable.setBounds(intrinsicWidth / -2, -intrinsicHeight, intrinsicWidth / 2, 0); return drawable; } private static boolean intersect(Canvas canvas, float left, float top, float right, float bottom) { return right >= 0 && left <= canvas.getWidth() && bottom >= 0 && top <= canvas.getHeight(); } private Drawable drawable; private GeoPoint geoPoint; /** * @param geoPoint * the initial geographical coordinates of this marker (may be null). * @param drawable * the initial {@code Drawable} of this marker (may be null). */ public Marker(GeoPoint geoPoint, Drawable drawable) { this.geoPoint = geoPoint; this.drawable = drawable; } @Override public synchronized boolean draw(BoundingBox boundingBox, byte zoomLevel, Canvas canvas, Point canvasPosition) { if (this.geoPoint == null || this.drawable == null) { return false; } double latitude = this.geoPoint.latitude; double longitude = this.geoPoint.longitude; int pixelX = (int) (MercatorProjection.longitudeToPixelX(longitude, zoomLevel) - canvasPosition.x); int pixelY = (int) (MercatorProjection.latitudeToPixelY(latitude, zoomLevel) - canvasPosition.y); Rect drawableBounds = this.drawable.copyBounds(); int left = pixelX + drawableBounds.left; int top = pixelY + drawableBounds.top; int right = pixelX + drawableBounds.right; int bottom = pixelY + drawableBounds.bottom; if (!intersect(canvas, left, top, right, bottom)) { return false; } this.drawable.setBounds(left, top, right, bottom); this.drawable.draw(canvas); this.drawable.setBounds(drawableBounds); return true; } /** * @return the {@code Drawable} of this marker (may be null). */ public synchronized Drawable getDrawable() { return this.drawable; } /** * @return the geographical coordinates of this marker (may be null). */ public synchronized GeoPoint getGeoPoint() { return this.geoPoint; } /** * @param drawable * the new {@code Drawable} of this marker (may be null). */ public synchronized void setDrawable(Drawable drawable) { this.drawable = drawable; } /** * @param geoPoint * the new geographical coordinates of this marker (may be null). */ public synchronized void setGeoPoint(GeoPoint geoPoint) { this.geoPoint = geoPoint; } }