/* * This is part of Geomajas, a GIS framework, http://www.geomajas.org/. * * Copyright 2008-2015 Geosparc nv, http://www.geosparc.com/, Belgium. * * The program is available in open source according to the GNU Affero * General Public License. All contributions in this program are covered * by the Geomajas Contributors License Agreement. For full licensing * details, see LICENSE.txt in the project root. */ package org.geomajas.gwt.client.spatial.geometry; import org.geomajas.geometry.Coordinate; import org.geomajas.gwt.client.spatial.Bbox; import org.geomajas.gwt.client.spatial.Mathlib; import org.geomajas.layer.LayerType; /** * LineString client-side GWT object. * * @author Pieter De Graef */ public class LineString extends AbstractGeometry { private static final long serialVersionUID = 1311848562135714815L; private Coordinate[] coordinates; // ------------------------------------------------------------------------- // Constructor // ------------------------------------------------------------------------- LineString(int srid, int precision) { super(srid, precision); } LineString(int srid, int precision, Coordinate[] coordinates) { super(srid, precision); this.coordinates = coordinates; } // ------------------------------------------------------------------------- // Class specific functions: // ------------------------------------------------------------------------- /** * Return a coordinate, or null. * * @param n * Index in the geometry. This can be an integer value or an array of values. * @return A coordinate or null. */ public Coordinate getCoordinateN(int n) { if (isEmpty()) { return null; } if (n >= 0 && n < coordinates.length) { return coordinates[n]; } return null; } /** * Checks whether or not the ring is closed. * * @return Returns true if the first coordinate equals the last coordinate. */ public boolean isClosed() { return !isEmpty() && getCoordinateN(0).equals(getCoordinateN(getNumPoints() - 1)); } // ------------------------------------------------------------------------- // Geometry implementation: // ------------------------------------------------------------------------- /** * Calculate whether or not this geometry intersects with another. (calculates simple line intersections) * * @param geometry * The other geometry to check for intersection. * @return Returns true or false. */ public boolean intersects(Geometry geometry) { if (geometry == null || isEmpty() || geometry.isEmpty()) { return false; } if (geometry.getNumGeometries() > 1) { for (int n = 0; n < geometry.getNumGeometries(); n++) { if (intersects(geometry.getGeometryN(n))) { return true; } } } else { final Coordinate[] coords = geometry.getCoordinates(); if (coords.length > 1 && coordinates.length > 1) { for (int i = 0; i < coordinates.length - 1; i++) { for (int j = 0; j < coords.length - 1; j++) { if (Mathlib.lineIntersects(coordinates[i], coordinates[i + 1], coords[j], coords[j + 1])) { return true; } } if (Mathlib.touches(geometry, coordinates[i])) { return true; } } } else { // TODO implement me } } return false; } public Coordinate[] getCoordinates() { return coordinates; } void setCoordinates(Coordinate[] coordinates) { this.coordinates = coordinates; } @Override public Object clone() { // NOSONAR super.clone() not supported by GWT return getGeometryFactory().createLineString(coordinates); } /** * Return the geometry itself. * * @param n * integer value...doesn't matter. * * @return this */ public Geometry getGeometryN(int n) { return this; } public int getNumPoints() { if (isEmpty()) { return 0; } return coordinates.length; } /** * Return the length of the LineString. */ public double getLength() { double len = 0; if (!isEmpty()) { for (int i = 0; i < coordinates.length - 1; i++) { double deltaX = coordinates[i + 1].getX() - coordinates[i].getX(); double deltaY = coordinates[i + 1].getY() - coordinates[i].getY(); len += Math.sqrt(deltaX * deltaX + deltaY * deltaY); } } return len; } /** * The centroid is also known as the "center of gravity" or the "center of mass". * * @return Return the center point. */ public Coordinate getCentroid() { if (isEmpty()) { return null; } double sumX = 0; double sumY = 0; double totalLength = 0; for (int i = 0; i < coordinates.length - 1; i++) { double length = coordinates[i].distance(coordinates[i + 1]); totalLength += length; double midx = (coordinates[i].getX() + coordinates[i + 1].getX()) / 2; sumX += length * midx; double midy = (coordinates[i].getY() + coordinates[i + 1].getY()) / 2; sumY += length * midy; } return new Coordinate(sumX / totalLength, sumY / totalLength); } /** * Return the minimal distance between this coordinate and any line segment of the geometry. * * @return Return the minimal distance */ public double getDistance(Coordinate coordinate) { double minDistance = Double.MAX_VALUE; if (!isEmpty()) { for (int i = 0; i < this.coordinates.length - 1; i++) { double dist = Mathlib.distance(this.coordinates[i], this.coordinates[i + 1], coordinate); if (dist < minDistance) { minDistance = dist; } } } return minDistance; } /** * A linestring is valid if isEmpty() == true or coordinates.length != 1. */ public boolean isValid() { return isEmpty() || (coordinates.length != 1); } public boolean isEmpty() { return coordinates == null || coordinates.length == 0; } /** * The area of a LineString is always 0. */ public double getArea() { return 0; } public Bbox getBounds() { if (isEmpty()) { return null; } double minX = Double.MAX_VALUE; double minY = Double.MAX_VALUE; double maxX = -Double.MAX_VALUE; double maxY = -Double.MAX_VALUE; for (Coordinate coordinate : coordinates) { if (coordinate.getX() < minX) { minX = coordinate.getX(); } if (coordinate.getY() < minY) { minY = coordinate.getY(); } if (coordinate.getX() > maxX) { maxX = coordinate.getX(); } if (coordinate.getY() > maxY) { maxY = coordinate.getY(); } } return new Bbox(minX, minY, maxX - minX, maxY - minY); } public Coordinate getCoordinate() { if (isEmpty()) { return null; } return coordinates[0]; } public LayerType getLayerType() { return LayerType.LINESTRING; } public String toWkt() { if (isEmpty()) { return "LINESTRING EMPTY"; } String wkt = "LINESTRING ("; for (int i = 0; i < coordinates.length; i++) { if (i > 0) { wkt += ", "; } wkt += coordinates[i].getX() + " " + coordinates[i].getY(); } return wkt + ")"; } }