Mercurial > dive4elements > gnv-client
comparison gnv-artifacts/src/main/java/de/intevation/gnv/math/XYColumn.java @ 657:af3f56758f59
merged gnv-artifacts/0.5
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:13:53 +0200 |
parents | bc5901bb4525 |
children | b1f5f2a8840f |
comparison
equal
deleted
inserted
replaced
590:5f5f273c8566 | 657:af3f56758f59 |
---|---|
1 package de.intevation.gnv.math; | |
2 | |
3 import java.util.ArrayList; | |
4 import java.util.List; | |
5 import java.util.Collections; | |
6 | |
7 import org.apache.commons.math.analysis.interpolation.SplineInterpolator; | |
8 import org.apache.commons.math.analysis.interpolation.UnivariateRealInterpolator; | |
9 | |
10 import org.apache.commons.math.analysis.UnivariateRealFunction; | |
11 | |
12 import org.apache.commons.math.MathException; | |
13 import org.apache.commons.math.FunctionEvaluationException; | |
14 | |
15 import org.apache.log4j.Logger; | |
16 | |
17 /** | |
18 * @author Ingo Weinzierl <ingo.weinzierl@intevation.de> | |
19 * @author Sascha L. Teichmann <sascha.teichmann@intevation.de> | |
20 */ | |
21 public class XYColumn | |
22 extends Point2d | |
23 implements UnivariateRealFunction | |
24 { | |
25 private static Logger log = Logger.getLogger(XYColumn.class); | |
26 | |
27 protected List<HeightValue> values; | |
28 | |
29 protected transient UnivariateRealFunction curve; | |
30 | |
31 public XYColumn() { | |
32 values = new ArrayList<HeightValue>(); | |
33 } | |
34 | |
35 public XYColumn(double x, double y, int i, int j) { | |
36 super(x, y, i, j); | |
37 values = new ArrayList<HeightValue>(); | |
38 } | |
39 | |
40 public void add(HeightValue value) { | |
41 values.add(value); | |
42 } | |
43 | |
44 public List<HeightValue> getValues() { | |
45 return values; | |
46 } | |
47 | |
48 public double value(double depth) { | |
49 try { | |
50 if (curve != null) { | |
51 HeightValue h = values.get(0); | |
52 // extrapolate beyond boundaries by repeating | |
53 if (depth > h.z) return h.v; | |
54 h = values.get(values.size()-1); | |
55 if (depth < h.z) return h.v; | |
56 return curve.value(depth); | |
57 } | |
58 } | |
59 catch (FunctionEvaluationException fee) { | |
60 log.error("evaluation failed", fee); | |
61 } | |
62 | |
63 return Double.NaN; | |
64 } | |
65 | |
66 public boolean prepare(XYDepth xyDepth) { | |
67 if (curve == null) { | |
68 int N = values.size(); | |
69 if (N == 0) { | |
70 log.error("no points for interpolation"); | |
71 return false; | |
72 } | |
73 | |
74 if (N == 1) { | |
75 // only one value -> constant function | |
76 curve = new ConstantFunction(values.get(0).v); | |
77 } | |
78 else { // more than on value | |
79 double depth = xyDepth.depth(this); | |
80 Collections.sort(values, HeightValue.INV_Z_COMPARATOR); | |
81 | |
82 // if there is no value at 0 repeat first value | |
83 HeightValue first = values.get(0); | |
84 if (first.z < 0d) { | |
85 values.add(0, new HeightValue(0d, first.v, first.k-1)); | |
86 ++N; | |
87 } | |
88 | |
89 // if there is no value at depth repeat last value | |
90 HeightValue last = values.get(N-1); | |
91 if (last.z > depth) { | |
92 values.add(new HeightValue(depth, last.v, last.k+1)); | |
93 ++N; | |
94 } | |
95 if (N < 3) { // interpolate linear | |
96 first = values.get(0); | |
97 last = values.get(N-1); | |
98 curve = new LinearFunction.Univariate( | |
99 first.z, first.v, | |
100 last.z, last.v); | |
101 } | |
102 else { // higher degree interpolation | |
103 double [] z = new double[N]; | |
104 double [] v = new double[N]; | |
105 for (int i = 0; i < N; ++i) { | |
106 HeightValue h = values.get(N-1-i); | |
107 z[i] = h.z; | |
108 v[i] = h.v; | |
109 } | |
110 try { | |
111 curve = getInterpolator().interpolate(z, v); | |
112 } | |
113 catch (MathException me) { | |
114 log.error("interpolation failed", me); | |
115 return false; | |
116 } | |
117 } | |
118 } | |
119 } | |
120 return true; | |
121 } | |
122 | |
123 protected UnivariateRealInterpolator getInterpolator() { | |
124 return new SplineInterpolator(); | |
125 } | |
126 } | |
127 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: |