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

org.jgrasstools.gears.modules.r.tmsgenerator.OmsOnlineTilesDownloader 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 static org.jgrasstools.gears.libs.modules.JGTConstants.RASTERPROCESSING;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;

import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.jgrasstools.gears.libs.exceptions.ModelsIOException;
import org.jgrasstools.gears.libs.modules.JGTConstants;
import org.jgrasstools.gears.libs.modules.JGTModel;
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 static org.jgrasstools.gears.modules.r.tmsgenerator.OmsOnlineTilesDownloader.*;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;

import oms3.annotations.Author;
import oms3.annotations.Description;
import oms3.annotations.Documentation;
import oms3.annotations.Execute;
import oms3.annotations.In;
import oms3.annotations.Keywords;
import oms3.annotations.Label;
import oms3.annotations.License;
import oms3.annotations.Name;
import oms3.annotations.Status;
import oms3.annotations.UI;

@Description(OMSONLINETILESDOWNLOADER_DESCRIPTION)
@Documentation(OMSONLINETILESDOWNLOADER_DOCUMENTATION)
@Author(name = OMSONLINETILESDOWNLOADER_AUTHORNAMES, contact = OMSONLINETILESDOWNLOADER_AUTHORCONTACTS)
@Keywords(OMSONLINETILESDOWNLOADER_KEYWORDS)
@Label(OMSONLINETILESDOWNLOADER_LABEL)
@Name(OMSONLINETILESDOWNLOADER_NAME)
@Status(OMSONLINETILESDOWNLOADER_STATUS)
@License(OMSONLINETILESDOWNLOADER_LICENSE)
@UI(OMSONLINETILESDOWNLOADER_UI)
public class OmsOnlineTilesDownloader extends JGTModel {

    @Description(OMSONLINETILESDOWNLOADER_inServiceUrl_DESCRIPTION)
    @In
    public String inServiceUrl = null;

    @Description(OMSONLINETILESDOWNLOADER_pType_DESCRIPTION)
    @In
    public int pType = 0;

    @Description(OMSONLINETILESDOWNLOADER_pName_DESCRIPTION)
    @In
    public String pName = "tmstiles";

    @Description(OMSONLINETILESDOWNLOADER_pMinzoom_DESCRIPTION)
    @In
    public Integer pMinzoom = null;

    @Description(OMSONLINETILESDOWNLOADER_pMaxzoom_DESCRIPTION)
    @In
    public Integer pMaxzoom = null;

    @Description(OMSONLINETILESDOWNLOADER_pNorth_DESCRIPTION)
    @UI(JGTConstants.PROCESS_NORTH_UI_HINT)
    @In
    public Double pNorth = null;

    @Description(OMSONLINETILESDOWNLOADER_pSouth_DESCRIPTION)
    @UI(JGTConstants.PROCESS_SOUTH_UI_HINT)
    @In
    public Double pSouth = null;

    @Description(OMSONLINETILESDOWNLOADER_pWest_DESCRIPTION)
    @UI(JGTConstants.PROCESS_WEST_UI_HINT)
    @In
    public Double pWest = null;

    @Description(OMSONLINETILESDOWNLOADER_pEast_DESCRIPTION)
    @UI(JGTConstants.PROCESS_EAST_UI_HINT)
    @In
    public Double pEast = null;

    @Description(OMSONLINETILESDOWNLOADER_pEpsg_DESCRIPTION)
    @UI(JGTConstants.CRS_UI_HINT)
    @In
    public String pEpsg;

    @Description(OMSONLINETILESDOWNLOADER_doLenient_DESCRIPTION)
    @In
    public boolean doLenient = true;

    @Description(OMSONLINETILESDOWNLOADER_inPath_DESCRIPTION)
    @In
    public String inPath;
    
    public static final String OMSONLINETILESDOWNLOADER_DESCRIPTION = "Module for the downloading of map tiles.";
    public static final String OMSONLINETILESDOWNLOADER_DOCUMENTATION = "";
    public static final String OMSONLINETILESDOWNLOADER_KEYWORDS = "Raster, Vector, TMS, Tiles";
    public static final String OMSONLINETILESDOWNLOADER_LABEL = RASTERPROCESSING;
    public static final String OMSONLINETILESDOWNLOADER_NAME = "tmsdownloader";
    public static final int OMSONLINETILESDOWNLOADER_STATUS = 10;
    public static final String OMSONLINETILESDOWNLOADER_LICENSE = "General Public License Version 3 (GPLv3)";
    public static final String OMSONLINETILESDOWNLOADER_AUTHORNAMES = "Andrea Antonello";
    public static final String OMSONLINETILESDOWNLOADER_AUTHORCONTACTS = "http://www.hydrologis.com";
    public static final String OMSONLINETILESDOWNLOADER_UI = "hide";
    public static final String OMSONLINETILESDOWNLOADER_inServiceUrl_DESCRIPTION = "An optional online tile service to include (XXX, YYY, ZZZ will be substituted by tile indexes and zoom level).";
    public static final String OMSONLINETILESDOWNLOADER_pType_DESCRIPTION = "The type of tile source (0 = TMS, 1 = google).";
    public static final String OMSONLINETILESDOWNLOADER_pName_DESCRIPTION = "A name of the tile source.";
    public static final String OMSONLINETILESDOWNLOADER_pMinzoom_DESCRIPTION = "The min zoom for which to generate tiles.";
    public static final String OMSONLINETILESDOWNLOADER_pMaxzoom_DESCRIPTION = "The max zoom for which to generate tiles.";
    public static final String OMSONLINETILESDOWNLOADER_pNorth_DESCRIPTION = "The north bound of the region to consider.";
    public static final String OMSONLINETILESDOWNLOADER_pSouth_DESCRIPTION = "The south bound of the region to consider.";
    public static final String OMSONLINETILESDOWNLOADER_pWest_DESCRIPTION = "The west bound of the region to consider.";
    public static final String OMSONLINETILESDOWNLOADER_pEast_DESCRIPTION = "The east bound of the region to consider.";
    public static final String OMSONLINETILESDOWNLOADER_pEpsg_DESCRIPTION = "The coordinate reference system of the bound coordinates (ex. EPSG:4328).";
    public static final String OMSONLINETILESDOWNLOADER_doLenient_DESCRIPTION = "Switch that set to true allows for some error due to different datums. If set to false, it won't reproject without Bursa Wolf parameters.";
    public static final String OMSONLINETILESDOWNLOADER_inPath_DESCRIPTION = "The folder inside which to create the tiles.";


    private boolean doDryrun = false;

    private static final String EPSG_MERCATOR = "EPSG:3857";
    private static final String EPSG_LATLONG = "EPSG:4326";

    @Execute
    public void process() throws Exception {
        checkNull(inPath, inServiceUrl, pEpsg, pMinzoom, pMaxzoom, pWest, pEast, pSouth, pNorth);

        CoordinateReferenceSystem boundsCrs = CrsUtilities.getCrsFromEpsg(pEpsg, null);
        CoordinateReferenceSystem mercatorCrs = CrsUtilities.getCrsFromEpsg(EPSG_MERCATOR, null);
        CoordinateReferenceSystem latLongCrs = CrsUtilities.getCrsFromEpsg(EPSG_LATLONG, null);

        ReferencedEnvelope inBounds = new ReferencedEnvelope(pWest, pEast, pSouth, pNorth, boundsCrs);

        MathTransform in2MercatorTransform = CRS.findMathTransform(boundsCrs, mercatorCrs);
        Envelope mercatorEnvelope = JTS.transform(inBounds, in2MercatorTransform);
        ReferencedEnvelope mercatorBounds = new ReferencedEnvelope(mercatorEnvelope, mercatorCrs);

        MathTransform transform = CRS.findMathTransform(boundsCrs, latLongCrs);
        Envelope latLongBounds = JTS.transform(inBounds, transform);
        Coordinate latLongCentre = latLongBounds.centre();

        File inFolder = new File(inPath);
        File baseFolder = new File(inFolder, pName);

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

        GlobalMercator mercator = new GlobalMercator();

        for( int z = pMinzoom; z <= pMaxzoom; z++ ) {

            // get ul and lr tile number in GOOGLE tiles
            int[] llTileXY = mercator.GoogleTile(s, w, z);
            int[] urTileXY = mercator.GoogleTile(n, e, z);

            int startXTile = Math.min(llTileXY[0], urTileXY[0]);
            int endXTile = Math.max(llTileXY[0], urTileXY[0]);
            int startYTile = Math.min(llTileXY[1], urTileXY[1]);
            int endYTile = Math.max(llTileXY[1], urTileXY[1]);

            int tileNum = 0;

            ReferencedEnvelope levelBounds = new ReferencedEnvelope();

            pm.beginTask("Generating tiles at zoom level: " + z, (endXTile - startXTile + 1));
            for( int i = startXTile; i <= endXTile; i++ ) {

                for( int j = startYTile; j <= endYTile; j++ ) {
                    tileNum++;

                    double[] bounds = mercator.TileLatLonBounds(i, j, z);
                    double west = bounds[0];
                    double south = bounds[1];
                    double east = bounds[2];
                    double north = bounds[3];

                    ReferencedEnvelope tmpBounds = new ReferencedEnvelope(west, east, south, north, latLongCrs);
                    levelBounds.expandToInclude(tmpBounds);

                    if (!doDryrun) {
                        int[] onlineTileNumbers = {i, j};
                        int[] fileNameTileNumbers = {i, j};
                        // switch( pType ) {
                        // case 1:
                        // need to convert in TMS format
                        int[] tmsNUms = mercator.TMSTileFromGoogleTile(i, j, z);
                        fileNameTileNumbers = tmsNUms;

                        // break;
                        // case 0:
                        // default:
                        // break;
                        // }

                        File imageFolder = new File(baseFolder, z + "/" + fileNameTileNumbers[0]);
                        if (!imageFolder.exists()) {
                            if (!imageFolder.mkdirs()) {
                                throw new ModelsIOException("Unable to create folder:" + imageFolder, this);
                            }
                        }
                        File imageFile = new File(imageFolder, fileNameTileNumbers[1] + ".png");
                        if (imageFile.exists()) {
                            continue;
                        }

                        String tmp = inServiceUrl.replaceFirst("ZZZ", String.valueOf(z));
                        tmp = tmp.replaceFirst("XXX", String.valueOf(onlineTileNumbers[0]));
                        tmp = tmp.replaceFirst("YYY", String.valueOf(onlineTileNumbers[1]));
                        // System.out.println(tmp);

                        URL url = new URL(tmp);
                        InputStream imgStream = null;
                        OutputStream out = null;
                        try {
                            imgStream = url.openStream();
                            out = new FileOutputStream(imageFile);
                            int read = 0;
                            byte[] bytes = new byte[1024];
                            while( (read = imgStream.read(bytes)) != -1 ) {
                                out.write(bytes, 0, read);
                            }
                        } catch (Exception ex) {
                            pm.errorMessage("Unable to get image: " + tmp);
                        } finally {
                            if (imgStream != null)
                                imgStream.close();
                            if (out != null) {
                                out.flush();
                                out.close();
                            }
                        }
                    }
                }
                pm.worked(1);
            }
            pm.done();

            pm.message("Zoom level: " + z + " has " + tileNum + " tiles.");
            pm.message("Boundary covered at Zoom level: " + z + ": " + levelBounds);
            pm.message("Total boundary wanted: " + mercatorBounds);
        }

        StringBuilder properties = new StringBuilder();
        properties.append("url=").append(pName).append("/ZZZ/XXX/YYY.png\n");
        properties.append("minzoom=").append(pMinzoom).append("\n");
        properties.append("maxzoom=").append(pMaxzoom).append("\n");
        properties.append("center=").append(latLongCentre.x).append(" ").append(latLongCentre.y).append("\n");
        properties.append("type=tms").append("\n");

        File propFile = new File(inFolder, pName + ".mapurl");
        FileUtilities.writeFile(properties.toString(), propFile);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy