/* * 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; import org.mapsforge.core.model.GeoPoint; import org.mapsforge.core.model.MapPosition; import org.mapsforge.core.util.MercatorProjection; import android.graphics.Point; class MapViewProjection implements Projection { private static final String INVALID_MAP_VIEW_DIMENSIONS = "invalid MapView dimensions"; private final MapView mapView; MapViewProjection(MapView mapView) { this.mapView = mapView; } @Override public GeoPoint fromPixels(int x, int y) { if (this.mapView.getWidth() <= 0 || this.mapView.getHeight() <= 0) { return null; } MapPosition mapPosition = this.mapView.getMapPosition().getMapPosition(); // calculate the pixel coordinates of the top left corner GeoPoint geoPoint = mapPosition.geoPoint; double pixelX = MercatorProjection.longitudeToPixelX(geoPoint.getLongitude(), mapPosition.zoomLevel); double pixelY = MercatorProjection.latitudeToPixelY(geoPoint.getLatitude(), mapPosition.zoomLevel); pixelX -= this.mapView.getWidth() >> 1; pixelY -= this.mapView.getHeight() >> 1; // convert the pixel coordinates to a GeoPoint and return it double lat = MercatorProjection.pixelYToLatitude(pixelY + y, mapPosition.zoomLevel); double lon = MercatorProjection.pixelXToLongitude(pixelX + x, mapPosition.zoomLevel); if (lat < -90 || lat > 90) { return new GeoPoint(0, 0); } if (lon < -180 || lon > 180) { return new GeoPoint(0, 0); } return new GeoPoint(lat, lon); } @Override public int getLatitudeSpan() { if (this.mapView.getWidth() > 0 && this.mapView.getHeight() > 0) { GeoPoint top = fromPixels(0, 0); GeoPoint bottom = fromPixels(0, this.mapView.getHeight()); return Math.abs(top.latitudeE6 - bottom.latitudeE6); } throw new IllegalStateException(INVALID_MAP_VIEW_DIMENSIONS); } @Override public int getLongitudeSpan() { if (this.mapView.getWidth() > 0 && this.mapView.getHeight() > 0) { GeoPoint left = fromPixels(0, 0); GeoPoint right = fromPixels(this.mapView.getWidth(), 0); return Math.abs(left.longitudeE6 - right.longitudeE6); } throw new IllegalStateException(INVALID_MAP_VIEW_DIMENSIONS); } @Override public float metersToPixels(float meters, byte zoom) { double latitude = this.mapView.getMapPosition().getMapCenter().getLatitude(); double groundResolution = MercatorProjection.calculateGroundResolution(latitude, zoom); return (float) (meters * (1 / groundResolution)); } @Override public Point toPixels(GeoPoint in, Point out) { if (this.mapView.getWidth() <= 0 || this.mapView.getHeight() <= 0) { return null; } MapPosition mapPosition = this.mapView.getMapPosition().getMapPosition(); // calculate the pixel coordinates of the top left corner GeoPoint geoPoint = mapPosition.geoPoint; double pixelX = MercatorProjection.longitudeToPixelX(geoPoint.getLongitude(), mapPosition.zoomLevel); double pixelY = MercatorProjection.latitudeToPixelY(geoPoint.getLatitude(), mapPosition.zoomLevel); pixelX -= this.mapView.getWidth() >> 1; pixelY -= this.mapView.getHeight() >> 1; if (out == null) { // create a new point and return it return new Point( (int) (MercatorProjection.longitudeToPixelX(in.getLongitude(), mapPosition.zoomLevel) - pixelX), (int) (MercatorProjection.latitudeToPixelY(in.getLatitude(), mapPosition.zoomLevel) - pixelY)); } // reuse the existing point out.x = (int) (MercatorProjection.longitudeToPixelX(in.getLongitude(), mapPosition.zoomLevel) - pixelX); out.y = (int) (MercatorProjection.latitudeToPixelY(in.getLatitude(), mapPosition.zoomLevel) - pixelY); return out; } @Override public Point toPoint(GeoPoint in, Point out, byte zoom) { if (out == null) { // create a new point and return it return new Point((int) MercatorProjection.longitudeToPixelX(in.getLongitude(), zoom), (int) MercatorProjection.latitudeToPixelY(in.getLatitude(), zoom)); } // reuse the existing point out.x = (int) MercatorProjection.longitudeToPixelX(in.getLongitude(), zoom); out.y = (int) MercatorProjection.latitudeToPixelY(in.getLatitude(), zoom); return out; } }