Package org.locationtech.udig.catalog.internal.wmt.tile

Source Code of org.locationtech.udig.catalog.internal.wmt.tile.OSMTile$OSMTileFactory

/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2010, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.catalog.internal.wmt.tile;

import java.net.MalformedURLException;
import java.net.URL;

import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.crs.DefaultGeographicCRS;

import com.vividsolutions.jts.geom.Coordinate;

import org.locationtech.udig.catalog.internal.wmt.Trace;
import org.locationtech.udig.catalog.internal.wmt.WMTPlugin;
import org.locationtech.udig.catalog.internal.wmt.tile.OSMTile.OSMTileName.OSMZoomLevel;
import org.locationtech.udig.catalog.internal.wmt.wmtsource.OSMSource;
import org.locationtech.udig.catalog.internal.wmt.wmtsource.WMTSource;
import org.locationtech.udig.core.internal.CorePlugin;


public class OSMTile extends WMTTile {
    private OSMTileName tileName;
    private OSMSource osmSource;
   
    public OSMTile(int x, int y, OSMZoomLevel zoomLevel, OSMSource osmSource) {
        this(new OSMTileName(x, y, zoomLevel, osmSource), osmSource);
    }
   
    public OSMTile(OSMTileName tileName, OSMSource osmSource){
        super(OSMTile.getExtentFromTileName(tileName), tileName);
       
        this.tileName = tileName;
        this.osmSource = osmSource;
    }
   
    public OSMTile getRightNeighbour() {
        return new OSMTile(tileName.getRightNeighbour(), osmSource);
    }
   
    public OSMTile getLowerNeighbour() {
        return new OSMTile(tileName.getLowerNeighbour(), osmSource);
    }
   
    public Coordinate getCenter() {
        return new Coordinate(
                tile2lon(tileName.getX() + 0.5, tileName.zoomLevel.getZoomLevel()),
                tile2lat(tileName.getY() + 0.5, tileName.zoomLevel.getZoomLevel())
                );
    }
   
   
    @Override
    public boolean equals( Object obj ) {
        if (!(obj instanceof OSMTile)) return false;
       
        OSMTile other = (OSMTile) obj;
       
        return tileName.equals(other.tileName);
    }
   
    //region Get extent from tile-name       
    /**
     * Returns the bounding box of a tile by the given tile name.
     *
     * see:
     * http://wiki.openstreetmap.org/wiki/Tilenames#compute_bounding_box_for_tile_number
     *
     * @param tileName
     * @return BoundingBox for a tile
     */
    public static ReferencedEnvelope getExtentFromTileName(OSMTileName tileName) {
        ReferencedEnvelope extent = new ReferencedEnvelope(
                tile2lon(tileName.getX(), tileName.zoomLevel.getZoomLevel()),
                tile2lon(tileName.getX() + 1, tileName.zoomLevel.getZoomLevel()),
                tile2lat(tileName.getY(), tileName.zoomLevel.getZoomLevel()),
                tile2lat(tileName.getY() + 1, tileName.zoomLevel.getZoomLevel()),
                DefaultGeographicCRS.WGS84);
       
        return extent;
    }
   
    private static double tile2lon(double x, int z) {       
        return (x / Math.pow(2.0, z) * 360.0) - 180;
    }

    private static double tile2lat(double y, int z) {
        double n = Math.PI - ((2.0 * Math.PI * y) / Math.pow(2.0, z));       
        return 180.0 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
    }
    //endregion
   


    public static class OSMTileFactory extends WMTTileFactory {

        //region Get tile from coordinate
        /**
         * Finds out the tile which contains the coordinate at a given zoom level.
         *
         * see:
         * http://wiki.openstreetmap.org/wiki/Tilenames#Java
         *
         * @param lat y
         * @param lon x
         * @param zoomLevel
         * @param wmtSource
         * @return
         */
        public OSMTile getTileFromCoordinate(double lat, double lon,
                WMTZoomLevel zoomLevel, WMTSource wmtSource) {
            // normalize latitude and longitude
            lat = WMTTileFactory.normalizeDegreeValue(lat, 90);
            lon = WMTTileFactory.normalizeDegreeValue(lon, 180);
           
            /**
             * Because the latitude is only valid in
             * 85.0511 °N to 85.0511 °S (http://wiki.openstreetmap.org/wiki/Tilenames#X_and_Y),
             * we have to correct if necessary.
             */
            lat = WMTTileFactory.moveInRange(lat, -85.0511, 85.0511);
           
            int xTile = (int) Math.floor((lon + 180) / 360 * (1 << zoomLevel.getZoomLevel()));
            int yTile = (int) Math.floor(
                    (1 - Math.log(Math.tan(lat * Math.PI / 180) + 1
                    / Math.cos(lat * Math.PI / 180))
                    / Math.PI)
                    / 2 * (1 << zoomLevel.getZoomLevel())
                );
           
            WMTPlugin.debug("[OSMTile.getTileFromCoordinate] " + zoomLevel.getZoomLevel() + //$NON-NLS-1$
                "/" + xTile +  "/" + yTile + " lon: " + lon + " lat: " + lat, Trace.OSM)//$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
           
            return new OSMTile(xTile, yTile, (OSMZoomLevel) zoomLevel, (OSMSource) wmtSource);
        }  
        //endregion

        public WMTZoomLevel getZoomLevel(int zoomLevel, WMTSource wmtSource) {
            return new OSMTileName.OSMZoomLevel(zoomLevel);
        }
       
    }
   
    /**
     * A small helper class which stores the tile-name.
     *
     * @author to.srwn
     * @since 1.1.0
     */
    public static class OSMTileName extends WMTTileName{
        private OSMZoomLevel zoomLevel;
        private OSMSource osmSource;
               
        public OSMTileName(int x, int y, OSMZoomLevel zoomLevel, OSMSource source) {
            super(zoomLevel, x, y, source);
            this.zoomLevel = zoomLevel;
            this.osmSource = source;
        }
       
        /**
         * Generates the url for a tile:
         * <pre>
         * For example:
         * http://tile.openstreetmap.org/{zoom-level}/{x}/{y}.png
         * </pre>
         *
         * @param osmSource
         * @return
         */
        public URL getTileUrl() {
            try {
                return new URL(null,
                        osmSource.getTileUrl(zoomLevel.getZoomLevel(),
                                getX(),
                                getY()),
                        CorePlugin.RELAXED_HANDLER);
            } catch (MalformedURLException e) {
                WMTPlugin.log("[OSMTile] Could not create the url for tile (Zoom: " + zoomLevel.getZoomLevel() + //$NON-NLS-1$
                        ", X: " + getX() + ", " + getY(), e); //$NON-NLS-1$ //$NON-NLS-2$
            }
           
            return null;
        }
       
        public OSMTileName getRightNeighbour() {
            return new OSMTileName(
                        WMTTileName.arithmeticMod((getX()+1), zoomLevel.getMaxTilePerRowNumber()),
                        getY(),
                        zoomLevel,
                        osmSource);
        }
       
        public OSMTileName getLowerNeighbour() {
            return new OSMTileName(
                        getX(),
                        WMTTileName.arithmeticMod((getY()+1), zoomLevel.getMaxTilePerColNumber()),
                        zoomLevel,
                        osmSource);
        }
       
        public String toString() {
            return zoomLevel.getZoomLevel() + "/" + getX() + "/" + getY(); //$NON-NLS-1$ //$NON-NLS-2$
        }
       
        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof OSMTileName)) return false;
           
            OSMTileName other = (OSMTileName) obj;
           
            return (getX() == other.getX()) && (getY() == other.getY()) && zoomLevel.equals(other.zoomLevel);
        }

        /**
         * Small helper class which wraps the zoom-level and
         * the maximum tile-number for x and y in this zoom-level.
         *
         * http://tile.openstreetmap.org/{zoom-level}/{x}/{y}.png
         *
         * @author to.srwn
         * @since 1.1.0
         */
        public static class OSMZoomLevel extends WMTZoomLevel{
          
            public OSMZoomLevel(int zoomLevel) {
                super(zoomLevel);
            }
          
            /**
             * The maximum tile-number:
             *
             * For example at zoom-level 2, the tilenames are in the following range:
             * 2/0/0 - 2/3/3
             *
             * (zoom-level/x/y): zoom-level/2^(zoom-level)-1/2^(zoom-level)-1)
             */
            @Override
            public int calculateMaxTilePerColNumber(int zoomLevel) {
                return (1 << zoomLevel); // 2 ^ (zoomLevel)
            }

            @Override
            public int calculateMaxTilePerRowNumber(int zoomLevel) {
                return calculateMaxTilePerColNumber(zoomLevel);
            }  
        }
       
    }

}
TOP

Related Classes of org.locationtech.udig.catalog.internal.wmt.tile.OSMTile$OSMTileFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.