/*
* GeoUtil.java
*
* Created on June 26, 2006, 10:44 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.jdesktop.swingx.mapviewer.util;
import java.awt.Dimension;
import java.awt.geom.Point2D;
import java.io.IOException;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.jdesktop.swingx.mapviewer.GeoPosition;
import org.jdesktop.swingx.mapviewer.TileFactoryInfo;
import org.jdesktop.swingx.mapviewer.TileProvider;
import org.w3c.dom.Document;
/**
* These are math utilities for converting between pixels, tiles, and geographic
* coordinates. Implements a Google Maps style mercator projection.
*
* @author joshy
*/
@Deprecated
public final class GeoUtil {
/**
* Get the map size at the given zoom level
*
* @param zoom the zoom level
* @param info the tile factory info
*
* @return the size of the map at the given zoom, in tiles (num tiles tall
* by num tiles wide)
*/
public static Dimension getMapSize(int zoom, TileProvider info) {
return new Dimension(info.getMapWidthInTiles(zoom), info.getMapWidthInTiles(zoom));
}
/**
* Check if parameters specify a valid tile
*
* @param x the tile x ordinate
* @param y the tile y ordinate
* @param zoomLevel the zoom level
* @param info the tile factory info
*
* @return true if this point in <em>tiles</em> is valid at this zoom level.
* For example, if the zoom level is 0 (zoomed all the way out,
* where there is only one tile), then x,y must be 0,0
*/
public static boolean isValidTile(int x, int y, int zoomLevel, TileFactoryInfo info) {
// int x = (int)coord.getX();
// int y = (int)coord.getY();
// if off the map to the top or left
if (x < 0 || y < 0) {
return false;
}
// if of the map to the right
if (info.getMapCenterInPixelsAtZoom(zoomLevel).getX() * 2 <= x
* info.getTileSize(zoomLevel)) {
return false;
}
// if off the map to the bottom
if (info.getMapCenterInPixelsAtZoom(zoomLevel).getY() * 2 <= y
* info.getTileSize(zoomLevel)) {
return false;
}
// if out of zoom bounds
if (zoomLevel < info.getMinimumZoomLevel() || zoomLevel > info.getMaximumZoomLevel()) {
return false;
}
return true;
}
/**
* Given a position (latitude/longitude pair) and a zoom level, return the
* appropriate point in <em>pixels</em>. The zoom level is necessary because
* pixel coordinates are in terms of the zoom level
*
*
* @param c A lat/lon pair
* @param zoomLevel the zoom level to extract the pixel coordinate for
* @param info the tile factory info
*
* @return the position on the map in pixels
*/
public static Point2D getBitmapCoordinate(GeoPosition c, int zoomLevel, TileFactoryInfo info) {
return getBitmapCoordinate(c.getY(), c.getX(), zoomLevel, info);
}
/**
* Given a position (latitude/longitude pair) and a zoom level, return the
* appropriate point in <em>pixels</em>. The zoom level is necessary because
* pixel coordinates are in terms of the zoom level
*
*
* @param latitude
* @param longitude
* @param zoomLevel the zoom level to extract the pixel coordinate for
* @param info the tile factory info
*
* @return the position on the map in pixels
*/
@SuppressWarnings("javadoc")
public static Point2D getBitmapCoordinate(double latitude, double longitude, int zoomLevel,
TileFactoryInfo info) {
double x = info.getMapCenterInPixelsAtZoom(zoomLevel).getX()
+ longitude * info.getLongitudeDegreeWidthInPixels(zoomLevel);
double e = Math.sin(latitude * (Math.PI / 180.0));
if (e > 0.9999) {
e = 0.9999;
}
if (e < -0.9999) {
e = -0.9999;
}
double y = info.getMapCenterInPixelsAtZoom(zoomLevel).getY()
+ 0.5 * Math.log((1 + e) / (1 - e)) * -1
* (info.getLongitudeRadianWidthInPixels(zoomLevel));
return new Point2D.Double(x, y);
}
/**
* convert an on screen pixel coordinate and a zoom level to a geo position
*
* @param pixelCoordinate the pixel coordinate
* @param zoom the zoom level
* @param info the tile factory info
*
* @return the corresponding geo position in WGS84
*/
public static GeoPosition getPosition(Point2D pixelCoordinate, int zoom, TileFactoryInfo info) {
// p(" --bitmap to latlon : " + coord + " " + zoom);
double wx = pixelCoordinate.getX();
double wy = pixelCoordinate.getY();
// this reverses getBitmapCoordinates
double flon = (wx - info.getMapCenterInPixelsAtZoom(zoom).getX())
/ info.getLongitudeDegreeWidthInPixels(zoom);
double e1 = (wy - info.getMapCenterInPixelsAtZoom(zoom).getY())
/ (-1 * info.getLongitudeRadianWidthInPixels(zoom));
double e2 = (2 * Math.atan(Math.exp(e1)) - Math.PI / 2) / (Math.PI / 180.0);
double flat = e2;
GeoPosition wc = new GeoPosition(flon, flat, GeoPosition.WGS_84_EPSG);
return wc;
}
/**
* Convert a street address into a position. Uses the Yahoo GeoCoder. You
* must supply your own yahoo id
*
* @param fields an array of Street, City and State (must be a US state)
* @throws java.io.IOException if the request fails.
* @return the position of this street address
*/
public static GeoPosition getPositionForAddress(String[] fields) throws IOException {
return getPositionForAddress(fields[0], fields[1], fields[2]);
}
/**
* Convert a street address into a position. Uses the Yahoo GeoCoder. You
* must supply your own yahoo id.
*
* @param street Street
* @param city City
* @param state State (must be a US state)
* @throws java.io.IOException if the request fails.
* @return the position of this street address
*/
public static GeoPosition getPositionForAddress(String street, String city, String state)
throws IOException {
try {
URL load = new URL("http://api.local.yahoo.com/MapsService/V1/geocode?"
+ "appid=joshy688" + "&street=" + street.replace(' ', '+') + "&city="
+ city.replace(' ', '+') + "&state=" + state.replace(' ', '+'));
// System.out.println("using address: " + load);
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(load.openConnection().getInputStream());
XPath xpath = XPathFactory.newInstance().newXPath();
// NodeList str =
// (NodeList)xpath.evaluate("//Result",doc,XPathConstants.NODESET);
Double lat = (Double) xpath.evaluate("//Result/Latitude/text()", doc,
XPathConstants.NUMBER);
Double lon = (Double) xpath.evaluate("//Result/Longitude/text()", doc,
XPathConstants.NUMBER);
// System.out.println("got address at: " + lat + " " + lon);
return new GeoPosition(lon, lat, GeoPosition.WGS_84_EPSG);
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IOException(
"Failed to retrieve location information from the internet: " + e.toString());
}
}
/**
* Gets the map bounds.
*
* @param mapViewer The map viewer.
* @return Returns the bounds.
*/
/*
* public static GeoBounds getMapBounds(JXMapViewer mapViewer) { return new
* GeoBounds(getMapGeoBounds(mapViewer)); }
*/
/**
* Gets the bounds as a set of two <code>GeoPosition</code> objects.
*
* @param mapViewer The map viewer.
* @return Returns the set of two <code>GeoPosition</code> objects that
* represent the north west and south east corners of the map.
*/
/*
* private static Set<GeoPosition> getMapGeoBounds(JXMapViewer mapViewer) {
* Set<GeoPosition> set = new HashSet<GeoPosition>(); TileFactory
* tileFactory = mapViewer.getTileFactory(); int zoom = mapViewer.getZoom();
* Rectangle2D bounds = mapViewer.getViewportBounds(); Point2D pt = new
* Point2D.Double(bounds.getX(), bounds.getY());
* set.add(tileFactory.pixelToGeo(pt, zoom)); pt = new
* Point2D.Double(bounds.getX() + bounds.getWidth(), bounds .getY() +
* bounds.getHeight()); set.add(tileFactory.pixelToGeo(pt, zoom)); return
* set; }
*/
}