Mercurial > dive4elements > gnv-client
diff gnv-artifacts/src/main/java/de/intevation/gnv/math/XYColumn.java @ 433:828df3ddb758
Added interpolation capabilities along z axis to XYColumns.
gnv-artifacts/trunk@481 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Wed, 23 Dec 2009 12:20:25 +0000 |
parents | 6a70e8883307 |
children | 0eed5749fd63 |
line wrap: on
line diff
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/math/XYColumn.java Wed Dec 23 09:45:40 2009 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/math/XYColumn.java Wed Dec 23 12:20:25 2009 +0000 @@ -2,6 +2,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Collections; + +import org.apache.commons.math.analysis.interpolation.SplineInterpolator; +import org.apache.commons.math.analysis.interpolation.UnivariateRealInterpolator; + +import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction; + +import org.apache.commons.math.analysis.UnivariateRealFunction; + +import org.apache.commons.math.MathException; +import org.apache.commons.math.FunctionEvaluationException; + +import org.apache.log4j.Logger; /** * @author Ingo Weinzierl <ingo.weinzierl@intevation.de> @@ -9,25 +22,98 @@ */ public class XYColumn extends Point2d +implements UnivariateRealFunction { + private static Logger log = Logger.getLogger(Interpolation2D.class); + protected List<HeightValue> values; + protected transient UnivariateRealFunction curve; + public XYColumn() { + values = new ArrayList<HeightValue>(); } public XYColumn(double x, double y, int i, int j) { super(x, y, i, j); + values = new ArrayList<HeightValue>(); } public void add(HeightValue value) { - if (values == null) { - values = new ArrayList<HeightValue>(); - } values.add(value); } public List<HeightValue> getValues() { return values; } + + public double value(double depth) { + try { + if (curve != null) { + return curve.value(depth); + } + } + catch (FunctionEvaluationException fee) { + log.error("evaluation failed", fee); + } + + return Double.NaN; + } + + public void prepare(XYDepth xyDepth) { + int N = values.size(); + if (curve == null && N > 0) { + if (N == 1) { + // only one value -> constant function + curve = new ConstantFunction(values.get(0).v); + } + else { // more than on value + double depth = xyDepth.depth(this); + Collections.sort(values, HeightValue.INV_Z_COMPARATOR); + + // if there is no value at 0 repeat first value + HeightValue first = values.get(0); + if (first.z < 0d) { + values.add(0, new HeightValue(0d, first.z, first.k-1)); + } + + // if there is no value at depth repeat last value + HeightValue last = values.get(N-1); + if (last.z > depth) { + values.add(new HeightValue(depth, last.z, last.k+1)); + } + N = values.size(); + if (N < 3) { // interpolate linear + first = values.get(0); + last = values.get(N-1); + curve = new LinearFunction.Univariate( + first.z, first.v, + last.z, last.v); + } + else { // higher degree interpolation + double [] z = new double[N]; + double [] v = new double[N]; + for (int i = 0; i < N; ++i) { + HeightValue h = values.get(i); + z[i] = h.z; + v[i] = h.v; + } + try { + curve = getInterpolator().interpolate(z, v); + } + catch (MathException me) { + log.error("interpolation failed", me); + } + } + } + } + else { + log.error("no points for interpolation"); + } + } + + protected UnivariateRealInterpolator getInterpolator() { + return new SplineInterpolator(); + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: