/* * <copyright> * Copyright 2010 BBN Technologies * </copyright> */ package com.bbn.openmap.dataAccess.mapTile; import java.awt.geom.Point2D; import com.bbn.openmap.proj.coords.GeoCoordTransformation; import com.bbn.openmap.proj.coords.LatLonPoint; import com.bbn.openmap.proj.coords.MercatorUVGCT; /** * The implementation of TileCoordinateTransformation for OpenStreetMap tile * coordinate layout. * * @author dietrick */ public class OSMMapTileCoordinateTransform extends AbstractMapTileCoordinateTransform { /** * @param latlon a Point2D whose x component is the longitude and y * component is the latitude * @param zoom Tile Map Service (TMS) style zoom level (0-19 usually) * @param ret LatLonPoint to fill and return, to avoid allocating return * object. * @return The "tile number" whose x and y components each are floating * point numbers that represent the distance in number of tiles from * the origin of the whole map at this zoom level. At zoom=0, the * lat,lon point of 0,0 maps to 0.5,0.5 since there is only one tile * at zoom level 0. */ public Point2D latLonToTileUV(Point2D latlon, int zoom, Point2D ret) { if (ret == null) { ret = new Point2D.Double(); } ret.setLocation(((latlon.getX() + 180.0) / 360.0 * Math.pow(2.0, zoom)), ((1.0 - Math.log(Math.tan(latlon.getY() * Math.PI / 180.0) + (1.0 / Math.cos(latlon.getY() * Math.PI / 180.0))) / Math.PI) / 2.0 * (Math.pow(2, zoom)))); return ret; // Much slower! // transform.setZoomLevel(zoom); // return transform.forward(latlon.getY(), latlon.getX(), ret); } /** * @param tileUV a Point2D whose x,y coordinates represent the distance in * number of tiles (each 256x256) from the origin (where the origin * is 90lat,-180lon) * @param zoom Tile Map Service (TMS) style zoom level (0-19 usually) * @param ret LatLonPoint to fill and return, to avoid allocating return * object. * @return a Point2D whose x coordinate is the longitude and y coordinate is * the latitude */ public LatLonPoint tileUVToLatLon(Point2D tileUV, int zoom, LatLonPoint ret) { if (ret == null) { ret = new LatLonPoint.Double(); } ret.setLocation(360.0 / Math.pow(2.0, zoom) * tileUV.getX() - 180.0, -90.0 + 360.0 / Math.PI * Math.atan(Math.exp((-2.0 * Math.PI * tileUV.getY()) / Math.pow(2.0, zoom) + Math.PI))); return ret; // Much slower! // transform.setZoomLevel(zoom); // return transform.inverse(tileUV.getX(), tileUV.getY(), ret); } /** * Given a projection, provide the upper, lower, left and right tile * coordinates that cover the projection area. * * @param upperLeft lat/lon coordinate of upper left corner of bounding box. * @param lowerRight lat/lon coordinate of lower right corner of bounding * box. * @param zoomLevel zoom level of desired tiles. * @return int[], in top, left, bottom and right order. */ public int[] getTileBoundsForProjection(Point2D upperLeft, Point2D lowerRight, int zoomLevel) { Point2D uvul = latLonToTileUV(upperLeft, zoomLevel); Point2D uvlr = latLonToTileUV(lowerRight, zoomLevel); int[] ret = new int[4]; int uvleft = (int) Math.floor(uvul.getX()); int uvright = (int) Math.ceil(uvlr.getX()); int uvup = (int) Math.floor(uvul.getY()); if (uvup < 0) { uvup = 0; } int uvbottom = (int) Math.ceil(uvlr.getY()); ret[0] = uvup; ret[1] = uvleft; ret[2] = uvbottom; ret[3] = uvright; return ret; } /** * @return if y coordinates for tiles increase as pixel values increase. */ public boolean isYDirectionUp() { return false; } /* * (non-Javadoc) * * @see * com.bbn.openmap.dataAccess.mapTile.MapTileCoordinateTransform#getTransform * () */ public GeoCoordTransformation getTransform(int zoomLevel) { return new MercatorUVGCT.OSM(zoomLevel); } }