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

org.hortonmachine.gears.utils.CrsUtilities Maven / Gradle / Ivy

There is a newer version: 0.10.8
Show newest version
/*
 * This file is part of HortonMachine (http://www.hortonmachine.org)
 * (C) HydroloGIS - www.hydrologis.com 
 * 
 * The HortonMachine 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.hortonmachine.gears.utils;

import java.awt.geom.Point2D;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.GeodeticCalculator;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.hortonmachine.gears.libs.exceptions.ModelsIOException;
import org.hortonmachine.gears.utils.files.FileUtilities;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;

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

/**
 * Utilities for CRS.
 *
 * @author Andrea Antonello (www.hydrologis.com)
 * @since 0.7.0
 */
public class CrsUtilities {

    public static final CoordinateReferenceSystem WGS84 = DefaultGeographicCRS.WGS84;
    public static final int WGS84_SRID = 4326;

    public static final ReferencedEnvelope WORLD = new ReferencedEnvelope(-180, 180, -90, 90, WGS84);

    /**
     * Fill the prj file with the actual map projection.
     *
     * @param filePath  the path to the regarding data or prj file.
     * @param extention the extention of the data file. If null, the crs is written to filePath directly.
     * @param crs       the {@link CoordinateReferenceSystem} to write.
     *
     * @throws IOException
     */
    @SuppressWarnings("nls")
    public static void writeProjectionFile( String filePath, String extention, CoordinateReferenceSystem crs )
            throws IOException {
        /*
         * fill a prj file
         */
        String prjPath = null;
        if (extention != null && filePath.toLowerCase().endsWith("." + extention)) {
            int dotLoc = filePath.lastIndexOf(".");
            prjPath = filePath.substring(0, dotLoc);
            prjPath = prjPath + ".prj";
        } else {
            if (!filePath.endsWith(".prj")) {
                prjPath = filePath + ".prj";
            } else {
                prjPath = filePath;
            }
        }

        try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(prjPath))) {
            bufferedWriter.write(crs.toWKT());
        }
    }

    /**
     * Reads a {@link CoordinateReferenceSystem} from a prj file.
     *
     * @param filePath  the path to the prj file or the connected datafile it sidecar file for.
     * @param extension the extension of the data file. If null it is assumed to be prj.
     *
     * @return the read {@link CoordinateReferenceSystem}.
     *
     * @throws Exception
     */
    @SuppressWarnings("nls")
    public static CoordinateReferenceSystem readProjectionFile( String filePath, String extension ) throws Exception {
        CoordinateReferenceSystem crs = null;
        String prjPath = null;
        String filePathLower = filePath.trim().toLowerCase();
        if (filePathLower.endsWith(".prj")) {
            // it is the prj file
            prjPath = filePath;
        } else if (extension != null && filePathLower.endsWith("." + extension)) {
            // datafile was supplied (substitute extension)
            int dotLoc = filePath.lastIndexOf(".");
            prjPath = filePath.substring(0, dotLoc);
            prjPath = prjPath + ".prj";
        } else {
            prjPath = filePath + ".prj";
        }

        File prjFile = new File(prjPath);
        if (!prjFile.exists()) {
            throw new ModelsIOException("The prj file doesn't exist: " + prjPath, "CRSUTILITIES");
        }
        String wkt = FileUtilities.readFile(prjFile);
        crs = CRS.parseWKT(wkt);
        return crs;
    }

    /**
     * Reproject a set of geometries
     *
     * @param from       the starting crs
     * @param to         the destination crs
     * @param geometries the array of geometries, wrapped into an Object array
     *
     * @throws Exception
     */
    public static void reproject( CoordinateReferenceSystem from, CoordinateReferenceSystem to, Object[] geometries )
            throws Exception {
        MathTransform mathTransform = CRS.findMathTransform(from, to);

        for( int i = 0; i < geometries.length; i++ ) {
            geometries[i] = JTS.transform((Geometry) geometries[i], mathTransform);
        }
    }

    /**
     * Reproject a set of coordinates.
     *
     * @param from        the starting crs
     * @param to          the destination crs
     * @param coordinates the array of coordinates, wrapped into an Object array
     *
     * @throws Exception
     */
    public static void reproject( CoordinateReferenceSystem from, CoordinateReferenceSystem to, Coordinate[] coordinates )
            throws Exception {
        MathTransform mathTransform = CRS.findMathTransform(from, to);

        for( int i = 0; i < coordinates.length; i++ ) {
            coordinates[i] = JTS.transform(coordinates[i], coordinates[i], mathTransform);
        }
    }

    /**
     * Get the code from a {@link CoordinateReferenceSystem}.
     *
     * @param crs the crs to get the code from.
     *
     * @return the code, that can be used with {@link CRS#decode(String)} to recreate the crs.
     *
     * @throws Exception
     */
    public static String getCodeFromCrs( CoordinateReferenceSystem crs ) throws Exception {
        String code = null;
        try {
            Integer epsg = CRS.lookupEpsgCode(crs, true);
            code = "EPSG:" + epsg; //$NON-NLS-1$
        } catch (Exception e) {
            // try non epsg
            code = CRS.lookupIdentifier(crs, true);
        }
        return code;
    }

    /**
     * Get the {@link CoordinateReferenceSystem} from a epsg srid number. 
     * 
     * @param srid the srid number.
     * @return the crs or null.
     */
    public static CoordinateReferenceSystem getCrsFromSrid( int srid ) {
        return getCrsFromSrid(srid, null);
    }

    public static CoordinateReferenceSystem getCrsFromSrid( int srid, Boolean doLatitudeFirst ) {
        if (srid == 4326 && doLatitudeFirst == null) {
            return WGS84;
        }
        try {
            if (doLatitudeFirst == null) {
                return CRS.decode("EPSG:" + srid);
            } else {
                return CRS.decode("EPSG:" + srid, doLatitudeFirst);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Get the {@link CoordinateReferenceSystem} from an epsg definition. 
     * 
     * @param epsgPlusCode the code as EPSG:4326
     * @param doLatitudeFirst see {@link CRS#decode(String, boolean)}
     * @return the crs.
     */
    public static CoordinateReferenceSystem getCrsFromEpsg( String epsgPlusCode, Boolean doLatitudeFirst ) {
        String sridString = epsgPlusCode.replaceFirst("EPSG:", "").replaceFirst("epsg:", "");
        int srid = Integer.parseInt(sridString);
        return getCrsFromSrid(srid, doLatitudeFirst);
    }

    public static CoordinateReferenceSystem getCrsFromEpsg( String epsgPlusCode ) {
        return getCrsFromEpsg(epsgPlusCode, null);
    }

    /**
     * Converts meters to degrees, based on a given coordinate in 90 degrees direction.
     * 
     * @param meters the meters to convert.
     * @param c the position to consider.
     * @return the converted degrees.
     */
    public static double getMetersAsWGS84( double meters, Coordinate c ) {
        GeodeticCalculator gc = new GeodeticCalculator(DefaultGeographicCRS.WGS84);
        gc.setStartingGeographicPoint(c.x, c.y);
        gc.setDirection(90, meters);
        Point2D destinationGeographicPoint = gc.getDestinationGeographicPoint();
        double degrees = Math.abs(destinationGeographicPoint.getX() - c.x);
        return degrees;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy