All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jxmapviewer.viewer.util.GeoUtil Maven / Gradle / Ivy

/*
 * 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.jxmapviewer.viewer.util;

import java.awt.Dimension;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.HashSet;
import java.util.Set;

import org.jxmapviewer.JXMapViewer;
import org.jxmapviewer.viewer.GeoBounds;
import org.jxmapviewer.viewer.GeoPosition;
import org.jxmapviewer.viewer.TileFactory;
import org.jxmapviewer.viewer.TileFactoryInfo;

/**
 * These are math utilities for converting between pixels, tiles, and geographic coordinates. Implements a Google Maps
 * style mercator projection.
 * @author joshy
 */
public final class GeoUtil
{
    /**
     * @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, TileFactoryInfo info)
    {
        return new Dimension(info.getMapWidthInTilesAtZoom(zoom), info.getMapWidthInTilesAtZoom(zoom));
    }

    /**
     * @param x the x value 
     * @param y the y value
     * @param zoomLevel the zoom level
     * @param info the tile factory info
     * @return true if this point in tiles 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 pixels. 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 coordinate
     */
    public static Point2D getBitmapCoordinate(GeoPosition c, int zoomLevel, TileFactoryInfo info)
    {
        return getBitmapCoordinate(c.getLatitude(), c.getLongitude(), zoomLevel, info);
    }

    /**
     * Given a position (latitude/longitude pair) and a zoom level, return the appropriate point in pixels. The
     * zoom level is necessary because pixel coordinates are in terms of the zoom level
     * @param latitude the latitude
     * @param longitude the longitude
     * @param zoomLevel the zoom level to extract the pixel coordinate for
     * @param info the tile factory info
     * @return the coordinate
     */
    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 coordinate in pixels
     * @param zoom the zoom level
     * @param info the tile factory info
     * @return a geo position
     */
    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(flat, flon);
        return wc;
    }

    /**
     * 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 GeoPosition objects.
     * @param mapViewer The map viewer.
     * @return Returns the set of two GeoPosition objects that represent the north west and south east
     * corners of the map.
     */
    private static Set getMapGeoBounds(JXMapViewer mapViewer)
    {
        Set set = new HashSet();
        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;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy