/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2005-2008, 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.filter.function;
import java.io.IOException;
import java.util.logging.Level;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.visitor.AverageVisitor;
import org.geotools.feature.visitor.CalcResult;
import org.geotools.feature.visitor.StandardDeviationVisitor;
import org.geotools.util.NullProgressListener;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
/**
* Breaks a FeatureCollection<SimpleFeatureType, SimpleFeature> into classes using the standard deviation classification method.
*
* @author Cory Horner, Refractions Research Inc.
* @source $URL$
*/
public class StandardDeviationFunction extends ClassificationFunction {
public int getArgCount() {
return 2;
}
public StandardDeviationFunction() {
setName("StandardDeviation");
}
private Object calculate(FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection) {
try {
int classNum = getClasses();
// find the average
AverageVisitor averageVisit = new AverageVisitor(getExpression());
if (progress == null) progress = new NullProgressListener();
featureCollection.accepts(averageVisit, progress);
if (progress.isCanceled()) return null;
CalcResult calcResult = averageVisit.getResult();
if (calcResult == null) return null;
double average = calcResult.toDouble();
// find the standard deviation
StandardDeviationVisitor sdVisit = new StandardDeviationVisitor(getExpression(), average);
featureCollection.accepts(sdVisit, progress);
if (progress.isCanceled()) return null;
calcResult = sdVisit.getResult();
if (calcResult == null) return null;
double standardDeviation = calcResult.toDouble();
//figure out the min and max values
Double min[] = new Double[classNum];
Double max[] = new Double[classNum];
for (int i = 0; i < classNum; i++) {
min[i] = getMin(i, classNum, average, standardDeviation);
max[i] = getMax(i, classNum, average, standardDeviation);
}
return new RangedClassifier(min, max);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "StandardDeviationFunction calculate failed", e);
return null;
}
}
public Object evaluate(Object feature) {
if (!(feature instanceof FeatureCollection)) {
return null;
}
return calculate((FeatureCollection<SimpleFeatureType, SimpleFeature>) feature);
}
private Double getMin(int index, int numClasses, double average, double standardDeviation) {
if (index <= 0 || index >= numClasses)
return null;
return new Double(average - (((numClasses / 2.0) - index) * standardDeviation));
}
private Double getMax(int index, int numClasses, double average, double standardDeviation) {
if (index < 0 || index >= numClasses - 1)
return null;
return new Double(average - (((numClasses / 2.0) - 1 - index) * standardDeviation));
}
}