/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2014, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotools.process.spatialstatistics.distribution;
import java.util.logging.Logger;
import org.geotools.process.spatialstatistics.operations.GeneralOperation;
import org.geotools.util.logging.Logging;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.filter.expression.Expression;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
/**
* Abstract Disribution Operator
*
* @author Minpa Lee, MangoSystem
*
* @source $URL$
*/
public abstract class AbstractDisributionOperator extends GeneralOperation {
protected static final Logger LOGGER = Logging.getLogger(AbstractDisributionOperator.class);
protected final String ALL = "ALL";
protected double getValue(SimpleFeature feature, Expression expression, double defaultValue) {
if (expression == null) {
return defaultValue;
}
Double dblVal = expression.evaluate(feature, Double.class);
if (dblVal == null || dblVal.isNaN() || dblVal.isInfinite()) {
return defaultValue;
} else {
return dblVal.doubleValue();
}
}
protected String getCaseValue(SimpleFeature feature, Expression expression) {
if (expression == null) {
return ALL;
}
String caseValue = expression.evaluate(feature, String.class);
if (caseValue == null || caseValue.isEmpty()) {
return ALL;
} else {
return caseValue;
}
}
/**
* The center of gravity for a inputGeometry.
*
* @param inputGeometry
* @return
*/
protected Coordinate getTrueCentroid(Geometry inputGeometry) {
// For line and polygon features, feature centroids are used in distance computations.
// For multipoints, polylines, or polygons with multiple parts, the centroid is computed
// using the weighted mean center of all feature parts.
// The weighting for point features is 1, for line features is length, and for polygon
// features is area.
double sumX = 0.0;
double sumY = 0.0;
double weightSum = 0.0;
if (inputGeometry instanceof Point) {
return inputGeometry.getCentroid().getCoordinate();
} else if (inputGeometry instanceof LineString) {
return inputGeometry.getCentroid().getCoordinate();
} else if (inputGeometry instanceof Polygon) {
return inputGeometry.getCentroid().getCoordinate();
} else if (inputGeometry instanceof MultiPoint) {
MultiPoint mp = (MultiPoint) inputGeometry;
for (int k = 0; k < mp.getNumGeometries(); k++) {
Coordinate cen = mp.getGeometryN(k).getCoordinate();
weightSum += 1;
sumX += cen.x;
sumY += cen.y;
}
return new Coordinate(sumX / weightSum, sumY / weightSum);
} else if (inputGeometry instanceof MultiLineString) {
MultiLineString ml = (MultiLineString) inputGeometry;
for (int k = 0; k < ml.getNumGeometries(); k++) {
Geometry lineString = ml.getGeometryN(k);
Coordinate cen = lineString.getCentroid().getCoordinate();
final double length = lineString.getLength();
weightSum += length;
sumX += cen.x * length;
sumY += cen.y * length;
}
return new Coordinate(sumX / weightSum, sumY / weightSum);
} else if (inputGeometry instanceof MultiPolygon) {
MultiPolygon mp = (MultiPolygon) inputGeometry;
for (int k = 0; k < mp.getNumGeometries(); k++) {
Geometry polygon = mp.getGeometryN(k);
Coordinate cen = polygon.getCentroid().getCoordinate();
final double area = polygon.getArea();
weightSum += area;
sumX += cen.x * area;
sumY += cen.y * area;
}
return new Coordinate(sumX / weightSum, sumY / weightSum);
} else if (inputGeometry instanceof GeometryCollection) {
GeometryCollection gc = (GeometryCollection) inputGeometry;
for (int k = 0; k < gc.getNumGeometries(); k++) {
Coordinate cen = getTrueCentroid(gc.getGeometryN(k));
weightSum += 1;
sumX += cen.x;
sumY += cen.y;
}
return new Coordinate(sumX / weightSum, sumY / weightSum);
}
return inputGeometry.getCentroid().getCoordinate();
}
}