net.di2e.ecdr.commons.util.GeospatialUtils.java Source code

Java tutorial

Introduction

Here is the source code for net.di2e.ecdr.commons.util.GeospatialUtils.java

Source

/**
 * Copyright (C) 2014 Cohesive Integrations, LLC (info@cohesiveintegrations.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.di2e.ecdr.commons.util;

import org.apache.commons.lang.StringUtils;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.geometry.BoundingBox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import com.vividsolutions.jts.io.WKTWriter;

import java.util.List;

/**
 * Utility Class for geospatial related functions
 */
public final class GeospatialUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(GeospatialUtils.class);
    private static final Integer MAX_LAT = 90;
    private static final Integer MIN_LAT = -90;
    private static final Integer MAX_LON = 180;
    private static final Integer MIN_LON = -180;
    private static final Integer MAX_ROTATION = 360;
    private static final double LAT_DEGREE_M = 111325;

    private GeospatialUtils() {
    }

    /**
     * Converts from a opensearch geo extension polygon which is defined in latitude, longitude pairs, in clockwise
     * order around the polygon, with the last point being the same as the first in order to close the polygon.
     * 
     * @param polygon
     * @return WKT String representation of the polygon
     */
    public static String polygonToWKT(String polygon) {
        StringBuilder wkt = new StringBuilder("POLYGON((");
        int coordinatePair = 0;
        String[] coords = polygon.split(",");
        int size = coords.length;
        LOGGER.trace("Trying to convert polygon with value [{}] to WKT", polygon);
        for (int i = size - 1; i >= 0; i--) {
            coordinatePair++;
            if (coordinatePair == 2) {
                wkt.append(" ");
            } else if (coordinatePair > 2) {
                wkt.append(",");
                coordinatePair = 1;
            }
            wkt.append(StringUtils.trimToEmpty(coords[i]));
        }
        wkt.append("))");
        LOGGER.trace("Converted polygon with value [{}] to WKT [{}]", polygon, wkt);
        return wkt.toString();
    }

    public static String polygonToBBox(String wkt) throws ParseException {
        LOGGER.trace("Trying to convert the wkt [{}] into a bounding box", wkt);
        WKTReader reader = new WKTReader();
        Geometry geo = reader.read(wkt);
        if (!geo.isRectangle()) {
            geo = geo.getEnvelope();
            WKTWriter writer = new WKTWriter();
            String bbox = writer.write(geo);
            LOGGER.debug("Convert the following wkt [{}] into a bounding box wkt [{}]", wkt, bbox);
            wkt = bbox;
        }
        return wkt;
    }

    public static String circleToBBox(String wktPoint, double radius) throws ParseException {
        WKTReader reader = new WKTReader();
        Geometry geo = reader.read(wktPoint);
        Point point = geo.getCentroid();
        GeoLocation geoLocation = GeoLocation.fromDegrees(point.getY(), point.getX());
        GeoLocation[] boxLocs = geoLocation.boundingCoordinates(radius);
        return "POLYGON((" + boxLocs[0].getLongitudeInDegrees() + " " + boxLocs[0].getLatitudeInDegrees() + ", "
                + boxLocs[1].getLongitudeInDegrees() + " " + boxLocs[0].getLatitudeInDegrees() + ", "
                + boxLocs[1].getLongitudeInDegrees() + " " + boxLocs[1].getLatitudeInDegrees() + ", "
                + boxLocs[0].getLongitudeInDegrees() + " " + boxLocs[1].getLatitudeInDegrees() + ", "
                + boxLocs[0].getLongitudeInDegrees() + " " + boxLocs[0].getLatitudeInDegrees() + "))";
    }

    /**
     * Converts a point to a WKT-based string.
     *
     * @param point Point to convert to WKT.
     * @return WKT String.
     */
    public static String pointToWKT(org.opengis.geometry.primitive.Point point) {
        return JTS.toGeometry(point.getDirectPosition()).toText();
    }

    /**
     * Converts a boundingbox to a WKT-based string.
     *
     * @param bbox BoundingBox to convert to WKT.
     * @return WKT String.
     */
    public static String bboxToWKT(BoundingBox bbox) {
        return JTS.toGeometry(bbox).toText();
    }

    /**
     * Converts a list of points into a geotools-based bounding box.
     *
     * @param points List of points, should only include the 'upper-left' and 'lower-right' points in that order.
     *               Code will not look at any other points that are passed in.
     * @return BoundingBox if transformation works, null otherwise.
     */
    public static BoundingBox pointsToBBox(List<org.opengis.geometry.primitive.Point> points) {
        BoundingBox bbox = null;
        if (!points.isEmpty()) {
            org.opengis.geometry.primitive.Point point1 = points.get(0);
            org.opengis.geometry.primitive.Point point2 = points.get(1);
            bbox = new ReferencedEnvelope(point1.getDirectPosition().getCoordinate()[0],
                    point2.getDirectPosition().getCoordinate()[0], point1.getDirectPosition().getCoordinate()[1],
                    point2.getDirectPosition().getCoordinate()[1], DefaultGeographicCRS.WGS84);
        }
        return bbox;
    }

}