/**
* OrbisGIS is a java GIS application dedicated to research in GIScience.
* OrbisGIS is developed by the GIS group of the DECIDE team of the
* Lab-STICC CNRS laboratory, see <http://www.lab-sticc.fr/>.
*
* The GIS group of the DECIDE team is located at :
*
* Laboratoire Lab-STICC – CNRS UMR 6285
* Equipe DECIDE
* UNIVERSITÉ DE BRETAGNE-SUD
* Institut Universitaire de Technologie de Vannes
* 8, Rue Montaigne - BP 561 56017 Vannes Cedex
*
* OrbisGIS is distributed under GPL 3 license.
*
* Copyright (C) 2007-2014 CNRS (IRSTV FR CNRS 2488)
* Copyright (C) 2015-2017 CNRS (Lab-STICC UMR CNRS 6285)
*
* This file is part of OrbisGIS.
*
* OrbisGIS 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.
*
* OrbisGIS 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
* OrbisGIS. If not, see <http://www.gnu.org/licenses/>.
*
* For more information, please consult: <http://www.orbisgis.org/>
* or contact directly:
* info_at_ orbisgis.org
*/
package org.orbisgis.mapeditor.map.geometryUtils;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateSequence;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Polygon;
/**
* This utility class provides some useful methods related to JTS {@link Coordinate} objects.
*
* @author Erwan Bocher
*/
public final class CoordinatesUtils {
/**
* Interpolates a z value (linearly) between the two coordinates.
*
* @param firstCoordinate
* @param lastCoordinate
* @param toBeInterpolated
* @return
*/
public static double interpolate(Coordinate firstCoordinate, Coordinate lastCoordinate, Coordinate toBeInterpolated) {
if (Double.isNaN(firstCoordinate.z)) {
return Double.NaN;
}
if (Double.isNaN(lastCoordinate.z)) {
return Double.NaN;
}
return firstCoordinate.z + (lastCoordinate.z - firstCoordinate.z) * firstCoordinate.distance(toBeInterpolated)
/ (firstCoordinate.distance(toBeInterpolated) + toBeInterpolated.distance(lastCoordinate));
}
public static boolean contains(Coordinate[] coords, Coordinate coord) {
for (Coordinate coordinate : coords) {
if (Double.isNaN(coord.z)) {
return coordinate.equals(coord);
} else {
return coordinate.equals3D(coord);
}
}
return false;
}
/**
* Checks if a coordinate array contains a specific coordinate.
*
* The equality is done only in 2D (z values are not checked).
*
* @param coords
* @param coord
* @return
*/
public static boolean contains2D(Coordinate[] coords, Coordinate coord) {
for (Coordinate coordinate : coords) {
if (coordinate.equals2D(coord)) {
return true;
}
}
return false;
}
/**
* Check if a coordinate array contains a specific coordinate.
*
* The equality is done in 3D (z values ARE checked).
*
* @param coords
* @param coord
* @return
*/
public static boolean contains3D(Coordinate[] coords, Coordinate coord) {
for (Coordinate coordinate : coords) {
if (coordinate.equals3D(coord)) {
return true;
}
}
return false;
}
/**
* Determine the min and max "z" values in an array of Coordinates.
*
* @param cs The array to search.
* @return An array of size 2, index 0 is min, index 1 is max.
*/
public static double[] zMinMax(final Coordinate[] cs) {
double zmin;
double zmax;
boolean validZFound = false;
double[] result = new double[2];
zmin = Double.NaN;
zmax = Double.NaN;
double z;
for (int t = cs.length - 1; t >= 0; t--) {
z = cs[t].z;
if (!(Double.isNaN(z))) {
if (validZFound) {
if (z < zmin) {
zmin = z;
}
if (z > zmax) {
zmax = z;
}
} else {
validZFound = true;
zmin = z;
zmax = z;
}
}
}
result[0] = (zmin);
result[1] = (zmax);
return result;
}
/**
* Find the furthest coordinate in a geometry from a base coordinate
*
* @param base
* @param coords
* @return the base coordinate and the target coordinate
*/
public static Coordinate[] getFurthestCoordinate(Coordinate base, Coordinate[] coords) {
double distanceMax = Double.MIN_VALUE;
Coordinate farCoordinate = null;
for (Coordinate coord : coords) {
double distance = coord.distance(base);
if (distance > distanceMax) {
distanceMax = distance;
farCoordinate = coord;
}
}
if (farCoordinate != null) {
return new Coordinate[]{base, farCoordinate};
} else {
return null;
}
}
/**
* Computes the length of a linestring specified by a sequence of points.
* if a coordinate has a NaN z return 0.
*
* @param pts
* the points specifying the linestring
* @return the length of the linestring
*/
public static double length3D(CoordinateSequence pts) {
// optimized for processing CoordinateSequences
int n = pts.size();
if (n <= 1) {
return 0.0;
}
double len = 0.0;
Coordinate p = new Coordinate();
pts.getCoordinate(0, p);
double x0 = p.x;
double y0 = p.y;
double z0 = p.z;
if (Double.isNaN(z0)) {
return 0.0;
}
for (int i = 1; i < n; i++) {
pts.getCoordinate(i, p);
double x1 = p.x;
double y1 = p.y;
double z1 = p.z;
if (Double.isNaN(z1)) {
return 0.0;
}
double dx = x1 - x0;
double dy = y1 - y0;
double dz = z1 - z0;
len += Math.sqrt(dx * dx + dy * dy + dz * dz);
x0 = x1;
y0 = y1;
z0 = z1;
}
return len;
}
/**
* Returns the 3D length of the geometry
*
*
* @param geom
* @return
*/
public static double length3D(Geometry geom) {
double sum = 0;
for (int i = 0; i < geom.getNumGeometries(); i++) {
Geometry subGeom = geom.getGeometryN(i);
if (subGeom instanceof Polygon) {
sum += length3D((Polygon) subGeom);
} else if (subGeom instanceof LineString) {
sum += length3D((LineString) subGeom);
}
}
return sum;
}
/**
* Returns the 3D perimeter of a line string.
*
* @param lineString
* @return
*/
public static double length3D(LineString lineString) {
return length3D(lineString.getCoordinateSequence());
}
/**
* Returns the 3D perimeter of a polygon
*
* @param polygon
* @return
*/
public static double length3D(Polygon polygon) {
double len = 0.0;
len += length3D(polygon.getExteriorRing().getCoordinateSequence());
for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
len += length3D(polygon.getInteriorRingN(i));
}
return len;
}
/**
* Private constructor for utility class.
*/
private CoordinatesUtils() {
}
}