/** * 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; } }