001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.filter.function;
017:
018: import java.io.IOException;
019: import java.util.logging.Level;
020:
021: import org.geotools.feature.FeatureCollection;
022: import org.geotools.feature.visitor.AverageVisitor;
023: import org.geotools.feature.visitor.CalcResult;
024: import org.geotools.feature.visitor.StandardDeviationVisitor;
025: import org.geotools.util.NullProgressListener;
026:
027: /**
028: * Breaks a FeatureCollection into classes using the standard deviation classification method.
029: *
030: * @author Cory Horner, Refractions Research Inc.
031: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/filter/function/StandardDeviationFunction.java $
032: */
033: public class StandardDeviationFunction extends ClassificationFunction {
034:
035: public int getArgCount() {
036: return 2;
037: }
038:
039: public StandardDeviationFunction() {
040: setName("StandardDeviation");
041: }
042:
043: private Object calculate(FeatureCollection featureCollection) {
044: try {
045: int classNum = getClasses();
046: // find the average
047: AverageVisitor averageVisit = new AverageVisitor(
048: getExpression());
049: if (progress == null)
050: progress = new NullProgressListener();
051: featureCollection.accepts(averageVisit, progress);
052: if (progress.isCanceled())
053: return null;
054: CalcResult calcResult = averageVisit.getResult();
055: if (calcResult == null)
056: return null;
057: double average = calcResult.toDouble();
058: // find the standard deviation
059: StandardDeviationVisitor sdVisit = new StandardDeviationVisitor(
060: getExpression(), average);
061: featureCollection.accepts(sdVisit, progress);
062: if (progress.isCanceled())
063: return null;
064: calcResult = sdVisit.getResult();
065: if (calcResult == null)
066: return null;
067: double standardDeviation = calcResult.toDouble();
068: //figure out the min and max values
069: Double min[] = new Double[classNum];
070: Double max[] = new Double[classNum];
071: for (int i = 0; i < classNum; i++) {
072: min[i] = getMin(i, classNum, average, standardDeviation);
073: max[i] = getMax(i, classNum, average, standardDeviation);
074: }
075: return new RangedClassifier(min, max);
076: } catch (IOException e) {
077: LOGGER.log(Level.SEVERE,
078: "StandardDeviationFunction calculate failed", e);
079: return null;
080: }
081: }
082:
083: public Object evaluate(Object feature) {
084: if (!(feature instanceof FeatureCollection)) {
085: return null;
086: }
087: return calculate((FeatureCollection) feature);
088: }
089:
090: private Double getMin(int index, int numClasses, double average,
091: double standardDeviation) {
092: if (index <= 0 || index >= numClasses)
093: return null;
094: return new Double(average
095: - (((numClasses / 2.0) - index) * standardDeviation));
096: }
097:
098: private Double getMax(int index, int numClasses, double average,
099: double standardDeviation) {
100: if (index < 0 || index >= numClasses - 1)
101: return null;
102: return new Double(
103: average
104: - (((numClasses / 2.0) - 1 - index) * standardDeviation));
105: }
106: }
|