Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTable.java @ 339:4509ba8fae68
Implementation of "Abflusskurve/Abflusstafel" calculation.
flys-artifacts/trunk@1738 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Wed, 20 Apr 2011 14:26:51 +0000 |
parents | 64cfbd631f29 |
children | 79401797f4e1 |
comparison
equal
deleted
inserted
replaced
338:cf84f0f926e9 | 339:4509ba8fae68 |
---|---|
13 import java.util.Comparator; | 13 import java.util.Comparator; |
14 import java.util.List; | 14 import java.util.List; |
15 import java.util.Collections; | 15 import java.util.Collections; |
16 import java.util.Iterator; | 16 import java.util.Iterator; |
17 | 17 |
18 import org.apache.log4j.Logger; | |
19 | |
20 import org.apache.commons.math.analysis.interpolation.SplineInterpolator; | |
21 | |
22 import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction; | |
23 | |
24 import org.apache.commons.math.ArgumentOutsideDomainException; | |
25 | |
18 import org.hibernate.Session; | 26 import org.hibernate.Session; |
19 import org.hibernate.Query; | 27 import org.hibernate.Query; |
20 import org.hibernate.SQLQuery; | 28 import org.hibernate.SQLQuery; |
21 | 29 |
22 import org.hibernate.type.StandardBasicTypes; | 30 import org.hibernate.type.StandardBasicTypes; |
23 | 31 |
24 public class WstValueTable | 32 public class WstValueTable |
25 implements Serializable | 33 implements Serializable |
26 { | 34 { |
35 private static Logger log = Logger.getLogger(WstValueTable.class); | |
27 | 36 |
28 // TODO: put this into a property file | 37 // TODO: put this into a property file |
29 public static final String SQL_POS_WQ = | 38 public static final String SQL_POS_WQ = |
30 "SELECT position, w, q, column_pos" + | 39 "SELECT position, w, q, column_pos" + |
31 " FROM wst_value_table" + | 40 " FROM wst_value_table" + |
32 " WHERE wst_id = :wst_id"; | 41 " WHERE wst_id = :wst_id"; |
42 | |
43 public static final double DEFAULT_STEP_WIDTH = 0.01; | |
33 | 44 |
34 public static class Column | 45 public static class Column |
35 implements Serializable | 46 implements Serializable |
36 { | 47 { |
37 protected String name; | 48 protected String name; |
186 double d = km - other.km; | 197 double d = km - other.km; |
187 if (d < 0.0) return -1; | 198 if (d < 0.0) return -1; |
188 if (d > 0.0) return +1; | 199 if (d > 0.0) return +1; |
189 return 0; | 200 return 0; |
190 } | 201 } |
202 | |
203 public double [][] cloneWQs() { | |
204 return new double [][] { | |
205 (double [])ws.clone(), | |
206 (double [])ws.clone() }; | |
207 } | |
208 | |
209 public double [][] interpolateWQ(Row other, double km, double stepWidth) { | |
210 | |
211 int W1 = ascendingWs(); | |
212 int W2 = other.ascendingWs(); | |
213 | |
214 int W = Math.min(W1, W2); | |
215 | |
216 if (W < 1) { | |
217 return new double[2][0]; | |
218 } | |
219 | |
220 double factor = factor(km, this.km, other.km); | |
221 | |
222 double minW = weight(factor, ws[0], other.ws[0]); | |
223 double maxW = weight(factor, ws[W-1], other.ws[W-1]); | |
224 | |
225 if (minW > maxW) { | |
226 double t = minW; | |
227 minW = maxW; | |
228 maxW = t; | |
229 } | |
230 double [] x = new double[W]; | |
231 double [] y = new double[W]; | |
232 | |
233 for (int i = 0; i < W; ++i) { | |
234 x[i] = weight(factor, ws[i], other.ws[i]); | |
235 y[i] = weight(factor, qs[i], other.qs[i]); | |
236 } | |
237 | |
238 SplineInterpolator interpolator = new SplineInterpolator(); | |
239 PolynomialSplineFunction spline = interpolator.interpolate(x, y); | |
240 | |
241 double [] outWs = | |
242 new double[(int)Math.ceil((maxW - minW)/stepWidth)]; | |
243 double [] outQs = | |
244 new double[outWs.length]; | |
245 | |
246 try { | |
247 double w = minW; | |
248 for (int i = 0; i < outWs.length; ++i, w += stepWidth) { | |
249 outQs[i] = spline.value(outWs[i] = w); | |
250 } | |
251 } | |
252 catch (ArgumentOutsideDomainException aode) { | |
253 log.error("Spline interpolation failed.", aode); | |
254 } | |
255 | |
256 return new double [][] { outWs, outQs }; | |
257 | |
258 } | |
259 | |
260 public double [][] interpolateWQ(double stepWidth) { | |
261 int W = ascendingWs(); // ignore back jumps | |
262 | |
263 if (W < 1) { | |
264 return new double[2][0]; | |
265 } | |
266 | |
267 double [] x = new double[W]; | |
268 double [] y = new double[W]; | |
269 | |
270 for (int i = 0; i < W; ++i) { | |
271 x[i] = ws[i]; | |
272 y[i] = qs[i]; | |
273 } | |
274 | |
275 SplineInterpolator interpolator = new SplineInterpolator(); | |
276 | |
277 PolynomialSplineFunction spline = interpolator.interpolate(x, y); | |
278 | |
279 double minW = ws[0]; | |
280 double maxW = ws[W-1]; | |
281 | |
282 double [] outWs = | |
283 new double[(int)Math.ceil((maxW - minW)/stepWidth)]; | |
284 double [] outQs = | |
285 new double[outWs.length]; | |
286 | |
287 try { | |
288 double w = minW; | |
289 for (int i = 0; i < outWs.length; ++i, w += stepWidth) { | |
290 outQs[i] = spline.value(outWs[i] = w); | |
291 } | |
292 } | |
293 catch (ArgumentOutsideDomainException aode) { | |
294 log.error("Spline interpolation failed.", aode); | |
295 } | |
296 | |
297 return new double [][] { outWs, outQs }; | |
298 } | |
299 | |
300 public int ascendingWs() { | |
301 if (ws.length < 2) { | |
302 return ws.length; | |
303 } | |
304 | |
305 int idx = 1; | |
306 | |
307 for (; idx < ws.length; ++idx) { | |
308 if (Double.isNaN(ws[idx]) || ws[idx] < ws[idx-1]) { | |
309 return idx; | |
310 } | |
311 } | |
312 | |
313 return idx; | |
314 } | |
315 | |
316 public double [][] weightWQs(Row other, double km) { | |
317 int W = Math.min(ws.length, other.ws.length); | |
318 double factor = factor(km, this.km, other.km); | |
319 | |
320 double [] outWs = new double[W]; | |
321 double [] outQs = new double[W]; | |
322 | |
323 for (int i = 0; i < W; ++i) { | |
324 outWs[i] = weight(factor, ws[i], other.ws[i]); | |
325 outQs[i] = weight(factor, qs[i], other.qs[i]); | |
326 } | |
327 | |
328 return new double [][] { outWs, outQs }; | |
329 } | |
191 } | 330 } |
192 // class Row | 331 // class Row |
193 | 332 |
194 protected List<Row> rows; | 333 protected List<Row> rows; |
195 | 334 |
230 km, qs, ws); | 369 km, qs, ws); |
231 } | 370 } |
232 } | 371 } |
233 | 372 |
234 return ws; | 373 return ws; |
374 } | |
375 | |
376 | |
377 public double [][] interpolateWQ(double km) { | |
378 return interpolateWQ(km, DEFAULT_STEP_WIDTH, true); | |
379 } | |
380 | |
381 public double [][] interpolateWQ( | |
382 double km, | |
383 double stepWidth, | |
384 boolean checkAscending | |
385 ) { | |
386 int rowIndex = Collections.binarySearch(rows, new Row(km)); | |
387 | |
388 if (rowIndex >= 0) { // direct row match | |
389 Row row = rows.get(rowIndex); | |
390 return checkAscending | |
391 ? row.interpolateWQ(stepWidth) | |
392 : row.cloneWQs(); | |
393 } | |
394 | |
395 rowIndex = -rowIndex -1; | |
396 | |
397 if (rowIndex < 1 || rowIndex >= rows.size()) { | |
398 // do not extrapolate | |
399 return new double[2][0]; | |
400 } | |
401 | |
402 Row r1 = rows.get(rowIndex-1); | |
403 Row r2 = rows.get(rowIndex); | |
404 | |
405 return checkAscending | |
406 ? r1.interpolateWQ(r2, km, stepWidth) | |
407 : r1.weightWQs(r2, km); | |
235 } | 408 } |
236 | 409 |
237 public static WstValueTable getTable(River river) { | 410 public static WstValueTable getTable(River river) { |
238 return getTable(river, 0); | 411 return getTable(river, 0); |
239 } | 412 } |