/*
* 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.Mathlib;
/**
* LinearRing client-side GWT object.
*
* @author Pieter De Graef
*/
public class LinearRing extends LineString {
private static final long serialVersionUID = 4314580899552986922L;
// -------------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------------
LinearRing(int srid, int precision) {
super(srid, precision);
}
LinearRing(int srid, int precision, Coordinate[] coordinates) {
super(srid, precision, coordinates);
}
// -------------------------------------------------------------------------
// Geometry implementation:
// -------------------------------------------------------------------------
@Override
public Object clone() { // NOSONAR super.clone() not supported by GWT
return getGeometryFactory().createLinearRing(getCoordinates());
}
/**
* Return true.
*/
public boolean isSimple() {
return true;
}
/**
* Checks to see if the last coordinate equals the first. Should always be the case!
*/
public boolean isClosed() {
if (isEmpty()) {
return false;
}
if (getNumPoints() == 1) {
return false;
}
Coordinate[] coordinates = getCoordinates();
return coordinates[0].equals(coordinates[coordinates.length - 1]);
}
/**
* An empty LinearRing is valid. Furthermore this object must be closed and must not self-intersect.
*/
public boolean isValid() {
if (isEmpty()) {
return true;
}
if (!isClosed()) {
return false;
}
Coordinate[] coordinates = getCoordinates();
if (coordinates.length < 4) {
return false;
}
for (int i = 0; i < coordinates.length - 1; i++) {
for (int j = 0; j < coordinates.length - 1; j++) {
if (Mathlib.lineIntersects(coordinates[i], coordinates[i + 1], coordinates[j], coordinates[j + 1])) {
return false;
}
}
}
return true;
}
/**
* Since a LinearRing is closed, it has an area.
*/
public double getArea() {
return Math.abs(getSignedArea());
}
/**
* 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 area = getSignedArea();
double x = 0;
double y = 0;
Coordinate[] coordinates = getCoordinates();
for (int i = 1; i < coordinates.length; i++) {
double x1 = coordinates[i - 1].getX();
double y1 = coordinates[i - 1].getY();
double x2 = coordinates[i].getX();
double y2 = coordinates[i].getY();
x += (x1 + x2) * (x1 * y2 - x2 * y1);
y += (y1 + y2) * (x1 * y2 - x2 * y1);
}
x = x / (6 * area);
y = y / (6 * area);
return new Coordinate(x, y);
}
private double getSignedArea() {
if (isEmpty()) {
return 0;
}
double area = 0;
Coordinate[] coordinates = getCoordinates();
for (int i = 1; i < coordinates.length; i++) {
double x1 = coordinates[i - 1].getX();
double y1 = coordinates[i - 1].getY();
double x2 = coordinates[i].getX();
double y2 = coordinates[i].getY();
area += x1 * y2 - x2 * y1;
}
return area / 2;
}
}