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 }

http://dive4elements.wald.intevation.org