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

org.jgrasstools.gears.modules.r.tmsgenerator.OpenstreetmapImageCreator Maven / Gradle / Ivy

The newest version!
/*
 * This file is part of JGrasstools (http://www.jgrasstools.org)
 * (C) HydroloGIS - www.hydrologis.com 
 * 
 * JGrasstools is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package org.jgrasstools.gears.modules.r.tmsgenerator;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.URL;

import javax.imageio.ImageIO;

import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.jgrasstools.gears.io.vectorreader.OmsVectorReader;
import org.jgrasstools.gears.libs.monitor.IJGTProgressMonitor;
import org.jgrasstools.gears.libs.monitor.LogProgressMonitor;
import org.jgrasstools.gears.utils.CrsUtilities;
import org.jgrasstools.gears.utils.files.FileUtilities;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;

import com.vividsolutions.jts.geom.Coordinate;

public class OpenstreetmapImageCreator {

    private static final String EPSG_MERCATOR = "EPSG:3857";
    private String inServiceUrl;
    private int zoomLevel;
    private ReferencedEnvelope mercatorBounds;
    private IJGTProgressMonitor pm;
    private File outFile;

    /**
     * @param inServiceUrl The OSM tile service to use (XXX, YYY, ZZZ will be substituted by tile indexes and zoom level).
     * @param zoomLevel The zoom level to use.
     * @param inBounds The area to consider in 3875.
     * @param pm The progress monitor.
     * @return the image.
     * @throws Exception
     */
    public OpenstreetmapImageCreator( String inServiceUrl, int zoomLevel, ReferencedEnvelope mercatorBounds, File outFile,
            IJGTProgressMonitor pm ) {
        this.inServiceUrl = inServiceUrl;
        this.zoomLevel = zoomLevel;
        this.mercatorBounds = mercatorBounds;
        this.outFile = outFile;
        this.pm = pm;
    }

    public void generate() throws Exception {

        CoordinateReferenceSystem mercatorCrs = CrsUtilities.getCrsFromEpsg(EPSG_MERCATOR, null);
        CoordinateReferenceSystem latLongCrs = DefaultGeographicCRS.WGS84;

        ReferencedEnvelope llBounds = mercatorBounds.transform(latLongCrs, true);

        double w = llBounds.getMinX();
        double e = llBounds.getMaxX();
        double s = llBounds.getMinY();
        double n = llBounds.getMaxY();

        int[] ulTileNumber = getTileXY(n, w, zoomLevel);
        int[] lrTileNumber = getTileXY(s, e, zoomLevel);

        int startXTile = ulTileNumber[0];
        int startYTile = ulTileNumber[1];

        int endXTile = lrTileNumber[0];
        int endYTile = lrTileNumber[1];

        BoundingBox bbUL = tile2boundingBox(startXTile, startYTile, zoomLevel);
        double imageW = bbUL.west;
        double imageN = bbUL.north;
        BoundingBox bbLR = tile2boundingBox(endXTile, endYTile, zoomLevel);
        double imageS = bbLR.south;
        double imageE = bbLR.east;

        int tileCols = endXTile - startXTile + 1;
        int tileRows = endYTile - startYTile + 1;

        int tileSize = 256;

        int height = tileRows * tileSize;
        int width = tileCols * tileSize;
        BufferedImage outImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = (Graphics2D) outImage.getGraphics();

        pm.beginTask("Generating tiles at zoom level: " + zoomLevel + " with tiles: " + tileCols + "x" + tileRows,
                (endXTile - startXTile + 1));
        int runningX = 0;
        for( int x = startXTile; x <= endXTile; x++ ) {
            int runningY = 0;
            for( int y = startYTile; y <= endYTile; y++ ) {

                // int[] tmsNUms = getTileXY(y, x, zoomLevel);

                String tmp = inServiceUrl.replaceFirst("ZZZ", String.valueOf(zoomLevel));
                tmp = tmp.replaceFirst("XXX", String.valueOf(x));
                tmp = tmp.replaceFirst("YYY", String.valueOf(y));

                URL url = new URL(tmp);
                try {
                    BufferedImage tileImage = ImageIO.read(url);

                    g2d.drawImage(tileImage, null, runningX, runningY);

                } catch (Exception ex) {
                    pm.errorMessage("Unable to get image: " + tmp);
                }
                runningY += tileSize;
            }
            runningX += tileSize;
            pm.worked(1);
        }
        pm.done();

        g2d.dispose();

        String nameL = outFile.getName().toLowerCase();
        if (nameL.endsWith("png")) {
            ImageIO.write(outImage, "png", outFile);
        } else if (nameL.endsWith("jpg")) {
            ImageIO.write(outImage, "jpg", outFile);
        } else if (nameL.endsWith("tiff")) {
            ImageIO.write(outImage, "tiff", outFile);
        }

        MathTransform transform = CRS.findMathTransform(latLongCrs, mercatorCrs);

        Coordinate llES = new Coordinate(imageE, imageS);
        Coordinate llWN = new Coordinate(imageW, imageN);
        Coordinate osmES = JTS.transform(llES, null, transform);
        Coordinate osmWN = JTS.transform(llWN, null, transform);

        // create tfw
        double dx = (osmES.x - osmWN.x) / width;
        double dy = (osmWN.y - osmES.y) / height;
        StringBuilder sb = new StringBuilder();
        sb.append(dx).append("\n");
        sb.append("0.00000000").append("\n");
        sb.append("0.00000000").append("\n");
        sb.append(-dy).append("\n");
        sb.append(osmWN.x).append("\n");
        sb.append(osmWN.y).append("\n");

        String fileName = FileUtilities.getNameWithoutExtention(outFile);

        File folder = outFile.getParentFile();

        File tfwFile = new File(folder, fileName + ".tfw");

        FileUtilities.writeFile(sb.toString(), tfwFile);

        // create prj
        File prjFile = new File(folder, fileName + ".prj");
        FileUtilities.writeFile(mercatorCrs.toWKT(), prjFile);

    }

    private static int[] getTileXY( final double lat, final double lon, final int zoom ) {
        int xtile = (int) Math.floor((lon + 180) / 360 * (1 << zoom));
        int ytile = (int) Math.floor(
                (1 - Math.log(Math.tan(Math.toRadians(lat)) + 1 / Math.cos(Math.toRadians(lat))) / Math.PI) / 2 * (1 << zoom));
        if (xtile < 0)
            xtile = 0;
        if (xtile >= (1 << zoom))
            xtile = ((1 << zoom) - 1);
        if (ytile < 0)
            ytile = 0;
        if (ytile >= (1 << zoom))
            ytile = ((1 << zoom) - 1);
        return new int[]{xtile, ytile};
    }

    private class BoundingBox {
        double north;
        double south;
        double east;
        double west;
    }

    private BoundingBox tile2boundingBox( final int x, final int y, final int zoom ) {
        BoundingBox bb = new BoundingBox();
        bb.north = tile2lat(y, zoom);
        bb.south = tile2lat(y + 1, zoom);
        bb.west = tile2lon(x, zoom);
        bb.east = tile2lon(x + 1, zoom);
        return bb;
    }

    private static double tile2lon( int x, int z ) {
        return x / Math.pow(2.0, z) * 360.0 - 180.0;
    }

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

    public static void main( String[] args ) throws Exception {
        String outFile = "/home/hydrologis/Dropbox/hydrologis/lavori/2015_05_bim_sarcamincio/shape_3857/image_output/osm15.png";

        String bounds = "/home/hydrologis/Dropbox/hydrologis/lavori/2015_05_bim_sarcamincio/shape_3857/area.shp";
        String inServiceUrl = "http://a.tile.opencyclemap.org/cycle/ZZZ/XXX/YYY.png";
        // String inServiceUrl = "http://a.tile.openstreetmap.org/ZZZ/XXX/YYY.png";

        ReferencedEnvelope env = OmsVectorReader.readVector(bounds).getBounds();

        OpenstreetmapImageCreator c = new OpenstreetmapImageCreator(inServiceUrl, 15, env, new File(outFile),
                new LogProgressMonitor());
        c.generate();

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy