comparison artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java @ 9425:3f49835a00c3

Extended CrossSectionFacet so it may fetch different data from within the artifact result. Also allows to have acces to the potentially already computed artifact result via its normal computation cache.
author gernotbelger
date Fri, 17 Aug 2018 15:31:02 +0200
parents f61bc0c63188
children 2b83d3a96703
comparison
equal deleted inserted replaced
9424:da19f1f58d72 9425:3f49835a00c3
6 * documentation coming with Dive4Elements River for details. 6 * documentation coming with Dive4Elements River for details.
7 */ 7 */
8 8
9 package org.dive4elements.river.artifacts; 9 package org.dive4elements.river.artifacts;
10 10
11 import java.io.Serializable;
12 import java.util.Arrays;
13 import java.util.Map;
14
15 import org.apache.log4j.Logger;
11 import org.dive4elements.artifactdatabase.data.StateData; 16 import org.dive4elements.artifactdatabase.data.StateData;
12
13 import org.dive4elements.artifactdatabase.state.Facet; 17 import org.dive4elements.artifactdatabase.state.Facet;
14 import org.dive4elements.artifactdatabase.state.FacetActivity; 18 import org.dive4elements.artifactdatabase.state.FacetActivity;
15
16 import org.dive4elements.artifacts.Artifact; 19 import org.dive4elements.artifacts.Artifact;
17 import org.dive4elements.artifacts.CallContext; 20 import org.dive4elements.artifacts.CallContext;
18
19 import org.dive4elements.artifacts.common.utils.StringUtils; 21 import org.dive4elements.artifacts.common.utils.StringUtils;
20
21 import org.dive4elements.river.artifacts.access.Calculation4Access; 22 import org.dive4elements.river.artifacts.access.Calculation4Access;
23 import org.dive4elements.river.artifacts.access.ComputationRangeAccess;
22 import org.dive4elements.river.artifacts.access.RangeAccess; 24 import org.dive4elements.river.artifacts.access.RangeAccess;
23 import org.dive4elements.river.artifacts.access.RiverAccess; 25 import org.dive4elements.river.artifacts.access.RiverAccess;
24 import org.dive4elements.river.artifacts.access.ComputationRangeAccess; 26 import org.dive4elements.river.artifacts.model.Calculation;
25 import org.dive4elements.river.artifacts.geom.Lines;
26
27 import org.dive4elements.river.artifacts.model.Calculation1; 27 import org.dive4elements.river.artifacts.model.Calculation1;
28 import org.dive4elements.river.artifacts.model.Calculation2; 28 import org.dive4elements.river.artifacts.model.Calculation2;
29 import org.dive4elements.river.artifacts.model.Calculation3; 29 import org.dive4elements.river.artifacts.model.Calculation3;
30 import org.dive4elements.river.artifacts.model.Calculation4; 30 import org.dive4elements.river.artifacts.model.Calculation4;
31 import org.dive4elements.river.artifacts.model.Calculation5; 31 import org.dive4elements.river.artifacts.model.Calculation5;
32 import org.dive4elements.river.artifacts.model.Calculation;
33 import org.dive4elements.river.artifacts.model.CalculationResult; 32 import org.dive4elements.river.artifacts.model.CalculationResult;
34 import org.dive4elements.river.artifacts.model.DischargeTables; 33 import org.dive4elements.river.artifacts.model.DischargeTables;
35 import org.dive4elements.river.artifacts.model.FacetTypes; 34 import org.dive4elements.river.artifacts.model.FacetTypes;
36 import org.dive4elements.river.artifacts.model.WQCKms; 35 import org.dive4elements.river.artifacts.model.WQCKms;
37 import org.dive4elements.river.artifacts.model.WQKms; 36 import org.dive4elements.river.artifacts.model.WQKms;
38 import org.dive4elements.river.artifacts.model.WW; 37 import org.dive4elements.river.artifacts.model.WW;
39 import org.dive4elements.river.artifacts.model.WstValueTable; 38 import org.dive4elements.river.artifacts.model.WstValueTable;
40 import org.dive4elements.river.artifacts.model.WstValueTableFactory; 39 import org.dive4elements.river.artifacts.model.WstValueTableFactory;
41
42 import org.dive4elements.river.artifacts.model.extreme.ExtremeResult; 40 import org.dive4elements.river.artifacts.model.extreme.ExtremeResult;
43
44 import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; 41 import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
45
46 import org.dive4elements.river.model.DischargeTable; 42 import org.dive4elements.river.model.DischargeTable;
47 import org.dive4elements.river.model.FastCrossSectionLine;
48 import org.dive4elements.river.model.Gauge; 43 import org.dive4elements.river.model.Gauge;
49 import org.dive4elements.river.model.River; 44 import org.dive4elements.river.model.River;
50
51 import org.dive4elements.river.utils.DoubleUtil; 45 import org.dive4elements.river.utils.DoubleUtil;
52 import org.dive4elements.river.utils.RiverUtils; 46 import org.dive4elements.river.utils.RiverUtils;
53 47
54 import gnu.trove.TDoubleArrayList; 48 import gnu.trove.TDoubleArrayList;
55
56 import java.awt.geom.Point2D;
57
58 import java.util.Arrays;
59 import java.util.List;
60 import java.util.Map;
61
62 import org.apache.log4j.Logger;
63
64 49
65 /** 50 /**
66 * The default WINFO artifact. 51 * The default WINFO artifact.
67 * 52 *
68 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> 53 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
69 */ 54 */
70 public class WINFOArtifact 55 public class WINFOArtifact extends D4EArtifact implements FacetTypes, WaterLineArtifact {
71 extends D4EArtifact
72 implements FacetTypes, WaterLineArtifact {
73 56
74 /** The log for this class. */ 57 /** The log for this class. */
75 private static Logger log = Logger.getLogger(WINFOArtifact.class); 58 private static Logger log = Logger.getLogger(WINFOArtifact.class);
76 59
77 /** The name of the artifact. */ 60 /** The name of the artifact. */
78 public static final String ARTIFACT_NAME = "winfo"; 61 public static final String ARTIFACT_NAME = "winfo";
79 62
80 /** XPath */ 63 /** XPath */
81 public static final String XPATH_STATIC_UI = 64 public static final String XPATH_STATIC_UI = "/art:result/art:ui/art:static";
82 "/art:result/art:ui/art:static"; 65
83 66 /**
84 /** The default number of steps between the start end end of a selected Q 67 * The default number of steps between the start end end of a selected Q
85 * range. */ 68 * range.
69 */
86 public static final int DEFAULT_Q_STEPS = 30; 70 public static final int DEFAULT_Q_STEPS = 30;
87 71
88 private static final String [] INACTIVES = new String[] { 72 private static final String[] INACTIVES = new String[] { LONGITUDINAL_Q, DURATION_Q, STATIC_WQKMS_Q };
89 LONGITUDINAL_Q,
90 DURATION_Q,
91 STATIC_WQKMS_Q
92 };
93 73
94 static { 74 static {
95 // TODO: Move to configuration. 75 // TODO: Move to configuration.
96 FacetActivity.Registry.getInstance().register( 76 FacetActivity.Registry.getInstance().register(ARTIFACT_NAME, new FacetActivity() {
97 ARTIFACT_NAME, 77 @Override
98 new FacetActivity() { 78 public Boolean isInitialActive(final Artifact artifact, final Facet facet, final String outputName) {
99 @Override 79 final String fname = facet.getName();
100 public Boolean isInitialActive( 80 if ((fname.equals(MAINVALUES_Q) || fname.equals(MAINVALUES_W)) && outputName.equals("computed_discharge_curve")) {
101 Artifact artifact, 81 return Boolean.FALSE;
102 Facet facet,
103 String outputName
104 ) {
105 String fname = facet.getName();
106 if ((fname.equals(MAINVALUES_Q)
107 || fname.equals(MAINVALUES_W))
108 && outputName.equals("computed_discharge_curve"))
109 {
110 return Boolean.FALSE;
111 }
112 return !StringUtils.contains(fname, INACTIVES);
113 } 82 }
114 }); 83 return !StringUtils.contains(fname, INACTIVES);
84 }
85 });
115 } 86 }
116 87
117 /** 88 /**
118 * The default constructor. 89 * The default constructor.
119 */ 90 */
120 public WINFOArtifact() { 91 public WINFOArtifact() {
121 } 92 }
122
123
124 93
125 /** 94 /**
126 * Returns the name of the concrete artifact. 95 * Returns the name of the concrete artifact.
127 * 96 *
128 * @return the name of the concrete artifact. 97 * @return the name of the concrete artifact.
130 @Override 99 @Override
131 public String getName() { 100 public String getName() {
132 return ARTIFACT_NAME; 101 return ARTIFACT_NAME;
133 } 102 }
134 103
135 protected static boolean reportGeneratedWs( 104 protected static boolean reportGeneratedWs(final Calculation report, final double[] ws) {
136 Calculation report,
137 double [] ws
138 ) {
139 if (ws == null || ws.length < 2) { 105 if (ws == null || ws.length < 2) {
140 return false; 106 return false;
141 } 107 }
142 108
143 double lastW = ws[0]; 109 double lastW = ws[0];
144 boolean alreadyReported = false; 110 boolean alreadyReported = false;
145 111
146 for (int i = 1; i < ws.length; ++i) { 112 for (int i = 1; i < ws.length; ++i) {
147 if (Math.abs(lastW - ws[i]) < 1e-5) { 113 if (Math.abs(lastW - ws[i]) < 1e-5) {
148 if (!alreadyReported) { 114 if (!alreadyReported) {
149 alreadyReported = true; 115 alreadyReported = true;
150 report.addProblem("more.than.one.q.for.w", ws[i]); 116 report.addProblem("more.than.one.q.for.w", ws[i]);
151 } 117 }
152 } 118 } else {
153 else {
154 alreadyReported = false; 119 alreadyReported = false;
155 } 120 }
156 lastW = ws[i]; 121 lastW = ws[i];
157 } 122 }
158 123
159 return true; 124 return true;
160 } 125 }
161
162 126
163 // 127 //
164 // METHODS FOR RETRIEVING COMPUTED DATA FOR DIFFERENT CHART TYPES 128 // METHODS FOR RETRIEVING COMPUTED DATA FOR DIFFERENT CHART TYPES
165 // 129 //
166 // 130 //
181 /** 145 /**
182 * Returns the data that is computed by a waterlevel computation. 146 * Returns the data that is computed by a waterlevel computation.
183 * 147 *
184 * @return an array of data triples that consist of W, Q and Kms. 148 * @return an array of data triples that consist of W, Q and Kms.
185 */ 149 */
186 public CalculationResult getWaterlevelData(CallContext context) 150 public CalculationResult getWaterlevelData(final CallContext context) {
187 {
188 log.debug("WINFOArtifact.getWaterlevelData"); 151 log.debug("WINFOArtifact.getWaterlevelData");
189 152
190 String calculationMode = getDataAsString("calculation_mode"); 153 final String calculationMode = getDataAsString("calculation_mode");
191 154
192 // If this WINFO-Artifact has a calculation trait. 155 // If this WINFO-Artifact has a calculation trait.
193 if (calculationMode != null) 156 if (calculationMode != null) {
194 {
195 if (calculationMode.equals("calc.discharge.longitudinal.section")) 157 if (calculationMode.equals("calc.discharge.longitudinal.section"))
196 return getDischargeLongitudinalSectionData(); 158 return getDischargeLongitudinalSectionData();
197 159
198 if (calculationMode.equals("calc.extreme.curve")) 160 if (calculationMode.equals("calc.extreme.curve"))
199 return (CalculationResult)this.compute(context, ComputeType.ADVANCE, false); 161 return (CalculationResult) this.compute(context, ComputeType.ADVANCE, false);
200 162
201 if (calculationMode.equals("calc.w.differences")) 163 if (calculationMode.equals("calc.w.differences"))
202 return (CalculationResult)this.compute(context, ComputeType.ADVANCE, true); 164 return (CalculationResult) this.compute(context, ComputeType.ADVANCE, true);
203 165
204 log.warn("Unhandled calculation_mode " + calculationMode); 166 log.warn("Unhandled calculation_mode " + calculationMode);
205 } 167 }
206 168
207 // Otherwise get it from parameterization. 169 // Otherwise get it from parameterization.
208 // TODO: wrong comment: now always a waterlevle computation is executed; actually there is a calc_mode for that, why dont check? 170 // TODO: wrong comment: now always a waterlevle computation is executed; actually there is a calc_mode for that, why
171 // dont check?
209 return computeWaterlevelData(); 172 return computeWaterlevelData();
210 } 173 }
211 174
212 /** Execu5tes the calculation of 'waterlevel', fetches all input data from this artifact */ 175 /** Execu5tes the calculation of 'waterlevel', fetches all input data from this artifact */
213 private CalculationResult computeWaterlevelData() { 176 private CalculationResult computeWaterlevelData() {
214 final double[] kms = new ComputationRangeAccess(this).getKms(); 177 final double[] kms = new ComputationRangeAccess(this).getKms();
215 if (kms == null) 178 if (kms == null)
216 return error(new WQKms[0], "no.kms.selected"); 179 return error(new WQKms[0], "no.kms.selected");
217 180
218 return computeWaterlevelData(kms); 181 return computeWaterlevelData(kms);
219 } 182 }
220 183
221 /** 184 /**
222 * Execu5tes the calculation of 'waterlevel'. 185 * Execu5tes the calculation of 'waterlevel'.
223 * Allows to override the stations for which the calculation is done. All other inputs are fetched from this artifact. 186 * Allows to override the stations for which the calculation is done. All other inputs are fetched from this artifact.
224 */ 187 */
225 public final CalculationResult computeWaterlevelData(final double kms[]) { 188 public final CalculationResult computeWaterlevelData(final double kms[]) {
226 189
227 final River river = new RiverAccess(this).getRiver(); 190 final River river = new RiverAccess(this).getRiver();
228 if (river == null) 191 if (river == null)
229 return error(new WQKms[0], "no.river.selected"); 192 return error(new WQKms[0], "no.river.selected");
230 193
231 double[] qs = getQs(); 194 double[] qs = getQs();
232 double[] ws = null; 195 double[] ws = null;
233 196
234 Calculation report = new Calculation(); 197 final Calculation report = new Calculation();
235 198
236 if (qs == null) { 199 if (qs == null) {
237 log.debug("Determine Q values based on a set of W values."); 200 log.debug("Determine Q values based on a set of W values.");
238 ws = getWs(); 201 ws = getWs();
239 double [][] qws = getQsForWs(ws, report); 202 final double[][] qws = getQsForWs(ws, report);
240 if (qws == null || qws.length == 0) { 203 if (qws == null || qws.length == 0) {
241 return error(new WQKms[0], "converting.ws.to.qs.failed"); 204 return error(new WQKms[0], "converting.ws.to.qs.failed");
242 } 205 }
243 qs = qws[0]; 206 qs = qws[0];
244 207
245 if (reportGeneratedWs(report, qws[1])) { 208 if (reportGeneratedWs(report, qws[1])) {
246 ws = qws[1]; 209 ws = qws[1];
247 } 210 }
248 } 211 }
249 212
250 WstValueTable wst = WstValueTableFactory.getTable(river); 213 final WstValueTable wst = WstValueTableFactory.getTable(river);
251 if (wst == null) { 214 if (wst == null) {
252 return error(new WQKms[0], "no.wst.for.selected.river"); 215 return error(new WQKms[0], "no.wst.for.selected.river");
253 } 216 }
254 217
255 RangeAccess rangeAccess = new RangeAccess(this); 218 final RangeAccess rangeAccess = new RangeAccess(this);
256 double [] range = rangeAccess.getKmRange(); 219 final double[] range = rangeAccess.getKmRange();
257 if (range == null) { 220 if (range == null) {
258 return error(new WQKms[0], "no.range.found"); 221 return error(new WQKms[0], "no.range.found");
259 } 222 }
260 223
261 double refKm; 224 double refKm;
262 225
263 if (isFreeQ() || isFreeW()) { 226 if (isFreeQ() || isFreeW()) {
264 refKm = range[0]; 227 refKm = range[0];
265 log.debug("'free' calculation (km " + refKm + ")"); 228 log.debug("'free' calculation (km " + refKm + ")");
266 } 229 } else {
267 else { 230 final Gauge gauge = river.determineRefGauge(range, rangeAccess.isRange());
268 Gauge gauge = river.determineRefGauge(
269 range, rangeAccess.isRange());
270 231
271 if (gauge == null) { 232 if (gauge == null) {
272 return error( 233 return error(new WQKms[0], "no.gauge.found.for.km", range[0]);
273 new WQKms[0], "no.gauge.found.for.km", range[0]);
274 } 234 }
275 235
276 refKm = gauge.getStation().doubleValue(); 236 refKm = gauge.getStation().doubleValue();
277 237
278 log.debug( 238 log.debug("reference gauge: " + gauge.getName() + " (km " + refKm + ")");
279 "reference gauge: " + gauge.getName() + " (km " + refKm + ")"); 239 }
280 } 240
281 241 return computeWaterlevelData(kms, qs, ws, wst, refKm, report);
282 return computeWaterlevelData(kms, qs, ws, wst, refKm, report);
283 } 242 }
284 243
285 /** 244 /**
286 * Computes the data of a waterlevel computation based on the interpolation 245 * Computes the data of a waterlevel computation based on the interpolation
287 * in WstValueTable. 246 * in WstValueTable.
288 * 247 *
289 * @param kms The kilometer values. 248 * @param kms
290 * @param qs The discharge values. 249 * The kilometer values.
291 * @param wst The WstValueTable used for the interpolation. 250 * @param qs
251 * The discharge values.
252 * @param wst
253 * The WstValueTable used for the interpolation.
292 * 254 *
293 * @return an array of data triples that consist of W, Q and Kms. 255 * @return an array of data triples that consist of W, Q and Kms.
294 */ 256 */
295 private static CalculationResult computeWaterlevelData( 257 private static CalculationResult computeWaterlevelData(final double[] kms, final double[] qs, final double[] ws, final WstValueTable wst,
296 double [] kms, 258 final double refKm, final Calculation report) {
297 double [] qs,
298 double [] ws,
299 WstValueTable wst,
300 double refKm,
301 Calculation report
302 ) {
303 log.info("WINFOArtifact.computeWaterlevelData"); 259 log.info("WINFOArtifact.computeWaterlevelData");
304 260
305 Calculation1 calc1 = new Calculation1(kms, qs, ws, refKm); 261 final Calculation1 calc1 = new Calculation1(kms, qs, ws, refKm);
306 262
307 if (report != null) { 263 if (report != null) {
308 calc1.addProblems(report); 264 calc1.addProblems(report);
309 } 265 }
310 266
311 return calc1.calculate(wst); 267 return calc1.calculate(wst);
312 } 268 }
313 269
314
315 /** 270 /**
316 * Returns the data that is computed by a duration curve computation. 271 * Returns the data that is computed by a duration curve computation.
317 * 272 *
318 * @return the data computed by a duration curve computation. 273 * @return the data computed by a duration curve computation.
319 */ 274 */
320 public CalculationResult getDurationCurveData() { 275 public CalculationResult getDurationCurveData() {
321 log.debug("WINFOArtifact.getDurationCurveData"); 276 log.debug("WINFOArtifact.getDurationCurveData");
322 277
323 RangeAccess rangeAccess = new RangeAccess(this); 278 final RangeAccess rangeAccess = new RangeAccess(this);
324 279
325 River r = rangeAccess.getRiver(); 280 final River r = rangeAccess.getRiver();
326 if (r == null) { 281 if (r == null) {
327 return error(null, "no.river.selected"); 282 return error(null, "no.river.selected");
328 } 283 }
329 284
330 double[] locations = rangeAccess.getLocations(); 285 final double[] locations = rangeAccess.getLocations();
331 if (locations == null) { 286 if (locations == null) {
332 return error(null, "no.locations.selected"); 287 return error(null, "no.locations.selected");
333 } 288 }
334 289
335 Gauge g = r.determineGaugeByPosition(locations[0]); 290 final Gauge g = r.determineGaugeByPosition(locations[0]);
336 if (g == null) { 291 if (g == null) {
337 return error(null, "no.gauge.selected"); 292 return error(null, "no.gauge.selected");
338 } 293 }
339 294
340 WstValueTable wst = WstValueTableFactory.getTable(r); 295 final WstValueTable wst = WstValueTableFactory.getTable(r);
341 if (wst == null) { 296 if (wst == null) {
342 return error(null, "no.wst.for.river"); 297 return error(null, "no.wst.for.river");
343 } 298 }
344 299
345 return computeDurationCurveData(g, wst, locations[0]); 300 return computeDurationCurveData(g, wst, locations[0]);
346 } 301 }
347 302
348
349 /** 303 /**
350 * Computes the data used to create duration curves. 304 * Computes the data used to create duration curves.
351 * 305 *
352 * @param gauge The selected gauge. 306 * @param gauge
353 * @param location The selected location. 307 * The selected gauge.
308 * @param location
309 * The selected location.
354 * 310 *
355 * @return the computed data. 311 * @return the computed data.
356 */ 312 */
357 private static CalculationResult computeDurationCurveData( 313 private static CalculationResult computeDurationCurveData(final Gauge gauge, final WstValueTable wst, final double location) {
358 Gauge gauge,
359 WstValueTable wst,
360 double location)
361 {
362 log.info("WINFOArtifact.computeDurationCurveData"); 314 log.info("WINFOArtifact.computeDurationCurveData");
363 315
364 Object[] obj = gauge.fetchDurationCurveData(); 316 final Object[] obj = gauge.fetchDurationCurveData();
365 317
366 int[] days = (int[]) obj[0]; 318 final int[] days = (int[]) obj[0];
367 double[] qs = (double[]) obj[1]; 319 final double[] qs = (double[]) obj[1];
368 320
369 Calculation3 calculation = new Calculation3(location, days, qs); 321 final Calculation3 calculation = new Calculation3(location, days, qs);
370 322
371 return calculation.calculate(wst); 323 return calculation.calculate(wst);
372 } 324 }
373 325
374
375 /** 326 /**
376 * Returns the data that is computed by a discharge curve computation. 327 * Returns the data that is computed by a discharge curve computation.
377 * 328 *
378 * @return the data computed by a discharge curve computation. 329 * @return the data computed by a discharge curve computation.
379 */ 330 */
380 public CalculationResult getComputedDischargeCurveData() 331 public CalculationResult getComputedDischargeCurveData() throws NullPointerException {
381 throws NullPointerException
382 {
383 log.debug("WINFOArtifact.getComputedDischargeCurveData"); 332 log.debug("WINFOArtifact.getComputedDischargeCurveData");
384 333
385 River r = RiverUtils.getRiver(this); 334 final River r = RiverUtils.getRiver(this);
386 335
387 if (r == null) { 336 if (r == null) {
388 return error(new WQKms[0], "no.river.selected"); 337 return error(new WQKms[0], "no.river.selected");
389 } 338 }
390 339
391 RangeAccess rangeAccess = new RangeAccess(this); 340 final RangeAccess rangeAccess = new RangeAccess(this);
392 double[] locations = rangeAccess.getLocations(); 341 final double[] locations = rangeAccess.getLocations();
393 342
394 if (locations == null) { 343 if (locations == null) {
395 return error(new WQKms[0], "no.locations.selected"); 344 return error(new WQKms[0], "no.locations.selected");
396 } 345 }
397 346
398 WstValueTable wst = WstValueTableFactory.getTable(r); 347 final WstValueTable wst = WstValueTableFactory.getTable(r);
399 if (wst == null) { 348 if (wst == null) {
400 return error(new WQKms[0], "no.wst.for.river"); 349 return error(new WQKms[0], "no.wst.for.river");
401 } 350 }
402 351
403 return computeDischargeCurveData(wst, locations[0]); 352 return computeDischargeCurveData(wst, locations[0]);
404 } 353 }
405 354
406
407 /** 355 /**
408 * Computes the data used to create computed discharge curves. 356 * Computes the data used to create computed discharge curves.
409 * 357 *
410 * @param wst The WstValueTable that is used for the interpolation (river- 358 * @param wst
359 * The WstValueTable that is used for the interpolation (river-
411 * bound). 360 * bound).
412 * @param location The location where the computation should be based on. 361 * @param location
362 * The location where the computation should be based on.
413 * 363 *
414 * @return an object that contains tuples of W/Q values at the specified 364 * @return an object that contains tuples of W/Q values at the specified
415 * location. 365 * location.
416 */ 366 */
417 private static CalculationResult computeDischargeCurveData( 367 private static CalculationResult computeDischargeCurveData(final WstValueTable wst, final double location) {
418 WstValueTable wst,
419 double location)
420 {
421 log.info("WINFOArtifact.computeDischargeCurveData"); 368 log.info("WINFOArtifact.computeDischargeCurveData");
422 369
423 Calculation2 calculation = new Calculation2(location); 370 final Calculation2 calculation = new Calculation2(location);
424 371
425 return calculation.calculate(wst); 372 return calculation.calculate(wst);
426 } 373 }
427 374
428
429 /** Create CalculationResult with data and message. */ 375 /** Create CalculationResult with data and message. */
430 protected static final CalculationResult error(Object data, String msg) { 376 protected static final CalculationResult error(final Object data, final String msg) {
431 return new CalculationResult(data, new Calculation(msg)); 377 return new CalculationResult(data, new Calculation(msg));
432 } 378 }
433 379
434 /** Create CalculationResult with data and message with args. */ 380 /** Create CalculationResult with data and message with args. */
435 protected static final CalculationResult error( 381 protected static final CalculationResult error(final Object data, final String msg, final Object... args) {
436 Object data,
437 String msg,
438 Object ... args
439 ) {
440 return new CalculationResult(data, new Calculation(msg, args)); 382 return new CalculationResult(data, new Calculation(msg, args));
441 } 383 }
442 384
443
444 /** 385 /**
445 * Returns the data that is computed by a reference curve computation. 386 * Returns the data that is computed by a reference curve computation.
446 * 387 *
447 * @return the data computed by a reference curve computation. 388 * @return the data computed by a reference curve computation.
448 */ 389 */
449 public CalculationResult getReferenceCurveData(CallContext context) { 390 public CalculationResult getReferenceCurveData(final CallContext context) {
450 391
451 Double startKm = getReferenceStartKm(); 392 final Double startKm = getReferenceStartKm();
452 393
453 if (startKm == null) { 394 if (startKm == null) {
454 return error(new WW[0], "no.reference.start.km"); 395 return error(new WW[0], "no.reference.start.km");
455 } 396 }
456 397
457 double [] endKms = getReferenceEndKms(); 398 final double[] endKms = getReferenceEndKms();
458 399
459 if (endKms == null || endKms.length == 0) { 400 if (endKms == null || endKms.length == 0) {
460 return error(new WW[0], "no.reference.end.kms"); 401 return error(new WW[0], "no.reference.end.kms");
461 } 402 }
462 403
463 Calculation5 calc5 = new Calculation5(startKm, endKms); 404 final Calculation5 calc5 = new Calculation5(startKm, endKms);
464 405
465 River r = RiverUtils.getRiver(this); 406 final River r = RiverUtils.getRiver(this);
466 if (r == null) { 407 if (r == null) {
467 return error(new WW[0], "no.river.found"); 408 return error(new WW[0], "no.river.found");
468 } 409 }
469 410
470 WstValueTable wst = WstValueTableFactory.getTable(r); 411 final WstValueTable wst = WstValueTableFactory.getTable(r);
471 if (wst == null) { 412 if (wst == null) {
472 return error(new WW[0], "no.wst.for.river"); 413 return error(new WW[0], "no.wst.for.river");
473 } 414 }
474 415
475 Map<Double, Double> kms2gaugeDatums = r.queryGaugeDatumsKMs(); 416 final Map<Double, Double> kms2gaugeDatums = r.queryGaugeDatumsKMs();
476 417
477 return calc5.calculate(wst, kms2gaugeDatums, context); 418 return calc5.calculate(wst, kms2gaugeDatums, context);
478 } 419 }
479
480 420
481 /** Get reference (start) km. */ 421 /** Get reference (start) km. */
482 public Double getReferenceStartKm() { 422 public Double getReferenceStartKm() {
483 StateData sd = getData("reference_startpoint"); 423 final StateData sd = getData("reference_startpoint");
484 424
485 if (sd == null) { 425 if (sd == null) {
486 log.warn("no reference start given."); 426 log.warn("no reference start given.");
487 return null; 427 return null;
488 } 428 }
497 } 437 }
498 438
499 try { 439 try {
500 return Double.valueOf(input); 440 return Double.valueOf(input);
501 } 441 }
502 catch (NumberFormatException nfe) { 442 catch (final NumberFormatException nfe) {
503 log.warn("reference start string is not numeric."); 443 log.warn("reference start string is not numeric.");
504 } 444 }
505 445
506 return null; 446 return null;
507 } 447 }
508 448
509
510 /** 449 /**
511 * Get end kms for reference curve (null if none). 450 * Get end kms for reference curve (null if none).
512 */ 451 */
513 public double [] getReferenceEndKms() { 452 public double[] getReferenceEndKms() {
514 StateData sd = getData("reference_endpoint"); 453 final StateData sd = getData("reference_endpoint");
515 454
516 if (sd == null) { 455 if (sd == null) {
517 log.warn("no reference end given."); 456 log.warn("no reference end given.");
518 return null; 457 return null;
519 } 458 } else {
520 else {
521 log.debug("Reference end km : " + sd.getValue()); 459 log.debug("Reference end km : " + sd.getValue());
522 } 460 }
523 461
524 String input = (String) sd.getValue(); 462 String input = (String) sd.getValue();
525 463
526 if (input == null || (input = input.trim()).length() == 0) { 464 if (input == null || (input = input.trim()).length() == 0) {
527 log.warn("reference end string is empty."); 465 log.warn("reference end string is empty.");
528 return null; 466 return null;
529 } 467 }
530 468
531 TDoubleArrayList endKms = new TDoubleArrayList(); 469 final TDoubleArrayList endKms = new TDoubleArrayList();
532 470
533 for (String part: input.split("\\s+")) { 471 for (final String part : input.split("\\s+")) {
534 try { 472 try {
535 double km = Double.parseDouble(part); 473 final double km = Double.parseDouble(part);
536 if (!endKms.contains(km)) { 474 if (!endKms.contains(km)) {
537 endKms.add(km); 475 endKms.add(km);
538 } 476 }
539 } 477 }
540 catch (NumberFormatException nfe) { 478 catch (final NumberFormatException nfe) {
541 log.warn("reference end string is not numeric."); 479 log.warn("reference end string is not numeric.");
542 } 480 }
543 } 481 }
544 482
545 return endKms.toNativeArray(); 483 return endKms.toNativeArray();
546 } 484 }
547 485
548
549 /** 486 /**
550 * Get corrected waterline against surface/profile. 487 * Get corrected waterline against surface/profile.
551 */ 488 */
552 private Lines.LineData waterLineC(int idx, FastCrossSectionLine csl) { 489 private double waterLineC(final int idx, final double currentKm) {
553 List<Point2D> points = csl.getPoints(); 490
554 491 final WQKms[] wqckms = (WQKms[]) getDischargeLongitudinalSectionData().getData();
555 WQKms[] wqckms = (WQKms[])
556 getDischargeLongitudinalSectionData().getData();
557 492
558 // Find index of km. 493 // Find index of km.
559 double wishKM = csl.getKm(); 494 final double wishKM = currentKm;
560 495
561 // Find W/C at km, linear naive approach. 496 // Find W/C at km, linear naive approach.
562 WQCKms triple = (WQCKms) wqckms[idx-1]; 497 final WQCKms triple = (WQCKms) wqckms[idx - 1];
563 498
564 if (triple.size() == 0) { 499 if (triple.size() == 0) {
565 log.warn("Calculation of c/waterline is empty."); 500 log.warn("Calculation of c/waterline is empty.");
566 return Lines.createWaterLines(points, 0.0f); 501 return Double.NaN;
567 } 502 }
568 503
569 // Linear seach in WQKms for closest km. 504 // Linear seach in WQKms for closest km.
570 double old_dist_wish = Math.abs(wishKM - triple.getKm(0)); 505 double old_dist_wish = Math.abs(wishKM - triple.getKm(0));
571 double last_c = triple.getC(0); 506 double last_c = triple.getC(0);
572 507
573 for (int i = 0, T = triple.size(); i < T; i++) { 508 for (int i = 0, T = triple.size(); i < T; i++) {
574 double diff = Math.abs(wishKM - triple.getKm(i)); 509 final double diff = Math.abs(wishKM - triple.getKm(i));
575 if (diff > old_dist_wish) { 510 if (diff > old_dist_wish) {
576 break; 511 break;
577 } 512 }
578 last_c = triple.getC(i); 513 last_c = triple.getC(i);
579 old_dist_wish = diff; 514 old_dist_wish = diff;
580 } 515 }
581 516
582 return Lines.createWaterLines(points, last_c); 517 return last_c;
583 } 518 }
584
585 519
586 /** 520 /**
587 * Get points of line describing the surface of water at cross section. 521 * Get points of line describing the surface of water at cross section.
588 * 522 *
589 * @param idx Index for getWaterlevelData. 523 * @param idx
590 * @param csl The profile/surface to fill with water. 524 * Index for getWaterlevelData.
591 * @param nextIgnored Ignored in this implementation of WaterLineArtifact. 525 * @param csl
592 * @param prevIgnored Ignored in this implementation of WaterLineArtifact. 526 * The profile/surface to fill with water.
527 * @param nextIgnored
528 * Ignored in this implementation of WaterLineArtifact.
529 * @param prevIgnored
530 * Ignored in this implementation of WaterLineArtifact.
593 * 531 *
594 * @return an array holding coordinates of points of surface of water ( 532 * @return an array holding coordinates of points of surface of water (
595 * in the form {{x1, x2} {y1, y2}} ). 533 * in the form {{x1, x2} {y1, y2}} ).
596 */ 534 */
597 @Override 535 @Override
598 public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl, 536 public double getWaterLevel(final ComputeType type, final String hash, final String stateId, final double currentKm, final Serializable waterLineIndex,
599 double nextIgnored, double prevIgnored, CallContext context) { 537 final double nextKm, final double prevKm, final CallContext context) {
600 log.debug("getWaterLines(" + idx + ")"); 538
601 539 final int idx = (int) waterLineIndex;
602 List<Point2D> points = csl.getPoints();
603 540
604 // Need W at km 541 // Need W at km
605 Object waterlevelResult = getWaterlevelData(context).getData(); 542 final Object waterlevelResult = getWaterlevelData(context).getData();
606 WQKms [] wqkms; 543 WQKms[] wqkms;
607 544
608 if (waterlevelResult instanceof ExtremeResult) { 545 if (waterlevelResult instanceof ExtremeResult) {
609 wqkms = ((ExtremeResult) waterlevelResult).getWQKms(); 546 wqkms = ((ExtremeResult) waterlevelResult).getWQKms();
610 } 547 } else {
611 else {
612 wqkms = (WQKms[]) waterlevelResult; 548 wqkms = (WQKms[]) waterlevelResult;
613 } 549 }
614 550
615 if (wqkms.length == 0) { 551 if (wqkms.length == 0) {
616 log.error("No WQKms found."); 552 log.error("No WQKms found.");
617 return Lines.createWaterLines(points, 0.0f); 553 return Double.NaN;
618 } 554 }
619 555
620 if (wqkms.length <= idx) { 556 if (wqkms.length <= idx) {
621 log.error("getWaterLines() requested index (" 557 log.error("getWaterLines() requested index (" + idx + " not found.");
622 + idx + " not found."); 558 return waterLineC(idx, currentKm);
623 return waterLineC(idx, csl);
624 } 559 }
625 560
626 // Find W at km, linear naive approach. 561 // Find W at km, linear naive approach.
627 WQKms triple = wqkms[idx]; 562 final WQKms triple = wqkms[idx];
628 563
629 // Find index of km. 564 // Find index of km.
630 double wishKM = csl.getKm(); 565 final double wishKM = currentKm;
631 566
632 if (triple.size() == 0) { 567 if (triple.size() == 0) {
633 log.warn("Calculation of waterline is empty."); 568 log.warn("Calculation of waterline is empty.");
634 return Lines.createWaterLines(points, 0.0f); 569 return Double.NaN;
635 } 570 }
636 571
637 // Early abort if we would need to extrapolate. 572 // Early abort if we would need to extrapolate.
638 int T = triple.size(); 573 final int T = triple.size();
639 double max_km = triple.getKm(T-1), min_km = triple.getKm(0); 574 final double max_km = triple.getKm(T - 1), min_km = triple.getKm(0);
640 if (wishKM < min_km || wishKM > max_km) { 575 if (wishKM < min_km || wishKM > max_km) {
641 // TODO Does this have to be done in the other WaterlineArtifact 576 // TODO Does this have to be done in the other WaterlineArtifact
642 // implementations, too? 577 // implementations, too?
643 log.warn("Will not extrapolate waterlevels."); 578 log.warn("Will not extrapolate waterlevels.");
644 return Lines.createWaterLines(points, 0.0f); 579 return Double.NaN;
645 } 580 }
646
647 int old_idx = 0;
648 581
649 // Linear seach in WQKms for closest km. 582 // Linear seach in WQKms for closest km.
650 double old_dist_wish = Math.abs(wishKM - triple.getKm(0)); 583 double old_dist_wish = Math.abs(wishKM - triple.getKm(0));
651 double last_w = triple.getW(0); 584 double last_w = triple.getW(0);
652 585
653 for (int i = 0; i < T; i++) { 586 for (int i = 0; i < T; i++) {
654 double diff = Math.abs(wishKM - triple.getKm(i)); 587 final double diff = Math.abs(wishKM - triple.getKm(i));
655 if (diff > old_dist_wish) { 588 if (diff > old_dist_wish) {
656 break; 589 break;
657 } 590 }
658 last_w = triple.getW(i); 591 last_w = triple.getW(i);
659 old_dist_wish = diff; 592 old_dist_wish = diff;
660 } 593 }
661 594
662 return Lines.createWaterLines(points, last_w); 595 return last_w;
663 } 596 }
664
665 597
666 /** 598 /**
667 * Returns the Qs for a number of Ws. 599 * Returns the Qs for a number of Ws.
668 * 600 *
669 * @param ws An array of W values. 601 * @param ws
602 * An array of W values.
670 * 603 *
671 * @return an array of Q values. 604 * @return an array of Q values.
672 */ 605 */
673 private double [][] getQsForWs(double[] ws, Calculation report) { 606 private double[][] getQsForWs(final double[] ws, final Calculation report) {
674 607
675 if (ws == null) { 608 if (ws == null) {
676 log.error("getQsForWs: ws == null"); 609 log.error("getQsForWs: ws == null");
677 return null; 610 return null;
678 } 611 }
679 612
680 boolean debug = log.isDebugEnabled(); 613 final boolean debug = log.isDebugEnabled();
681 614
682 if (debug) { 615 if (debug) {
683 log.debug("D4EArtifact.getQsForWs"); 616 log.debug("D4EArtifact.getQsForWs");
684 } 617 }
685 618
686 River r = RiverUtils.getRiver(this); 619 final River r = RiverUtils.getRiver(this);
687 if (r == null) { 620 if (r == null) {
688 log.warn("no river found"); 621 log.warn("no river found");
689 return null; 622 return null;
690 } 623 }
691 624
692 RangeAccess rangeAccess = new RangeAccess(this); 625 final RangeAccess rangeAccess = new RangeAccess(this);
693 double [] range = rangeAccess.getKmRange(); 626 final double[] range = rangeAccess.getKmRange();
694 if (range == null) { 627 if (range == null) {
695 log.warn("no ranges found"); 628 log.warn("no ranges found");
696 return null; 629 return null;
697 } 630 }
698 631
699 if (isFreeW()) { 632 if (isFreeW()) {
700 log.debug("Bezugslinienverfahren I: W auf freier Strecke"); 633 log.debug("Bezugslinienverfahren I: W auf freier Strecke");
701 // The simple case of the "Bezugslinienverfahren" 634 // The simple case of the "Bezugslinienverfahren"
702 // "W auf freier Strecke". 635 // "W auf freier Strecke".
703 WstValueTable wst = WstValueTableFactory.getTable(r); 636 final WstValueTable wst = WstValueTableFactory.getTable(r);
704 if (wst == null) { 637 if (wst == null) {
705 log.warn("no wst value table found"); 638 log.warn("no wst value table found");
706 return null; 639 return null;
707 } 640 }
708 double km = range[0]; 641 final double km = range[0];
709 642
710 TDoubleArrayList outQs = new TDoubleArrayList(ws.length); 643 final TDoubleArrayList outQs = new TDoubleArrayList(ws.length);
711 TDoubleArrayList outWs = new TDoubleArrayList(ws.length); 644 final TDoubleArrayList outWs = new TDoubleArrayList(ws.length);
712 645
713 boolean generatedWs = false; 646 boolean generatedWs = false;
714 647
715 for (int i = 0; i < ws.length; ++i) { 648 for (int i = 0; i < ws.length; ++i) {
716 double w = ws[i]; 649 final double w = ws[i];
717 if (debug) { 650 if (debug) {
718 log.debug("getQsForWs: lookup Q for W: " + w); 651 log.debug("getQsForWs: lookup Q for W: " + w);
719 } 652 }
720 // There could be more than one Q per W. 653 // There could be more than one Q per W.
721 double [] qs = wst.findQsForW(km, w, report); 654 final double[] qs = wst.findQsForW(km, w, report);
722 for (int j = 0; j < qs.length; ++j) { 655 for (int j = 0; j < qs.length; ++j) {
723 outWs.add(ws[i]); 656 outWs.add(ws[i]);
724 outQs.add(qs[j]); 657 outQs.add(qs[j]);
725 } 658 }
726 generatedWs |= qs.length != 1; 659 generatedWs |= qs.length != 1;
728 661
729 if (debug) { 662 if (debug) {
730 log.debug("getQsForWs: number of Qs: " + outQs.size()); 663 log.debug("getQsForWs: number of Qs: " + outQs.size());
731 } 664 }
732 665
733 return new double [][] { 666 return new double[][] { outQs.toNativeArray(), generatedWs ? outWs.toNativeArray() : null };
734 outQs.toNativeArray(),
735 generatedWs ? outWs.toNativeArray() : null };
736 } 667 }
737 668
738 if (debug) { 669 if (debug) {
739 log.debug("range: " + Arrays.toString(range)); 670 log.debug("range: " + Arrays.toString(range));
740 } 671 }
741 672
742 Gauge g = rangeAccess.getRiver().determineRefGauge( 673 final Gauge g = rangeAccess.getRiver().determineRefGauge(range, rangeAccess.isRange());
743 range, rangeAccess.isRange());
744 if (g == null) { 674 if (g == null) {
745 log.warn("no gauge found for km: " + range[0]); 675 log.warn("no gauge found for km: " + range[0]);
746 return null; 676 return null;
747 } 677 }
748 678
749 if (debug) { 679 if (debug) {
750 log.debug("convert w->q with gauge '" + g.getName() + "'"); 680 log.debug("convert w->q with gauge '" + g.getName() + "'");
751 } 681 }
752 682
753 DischargeTable dt = g.fetchMasterDischargeTable(); 683 final DischargeTable dt = g.fetchMasterDischargeTable();
754 684
755 if (dt == null) { 685 if (dt == null) {
756 log.warn("No master discharge table found for gauge '" 686 log.warn("No master discharge table found for gauge '" + g.getName() + "'");
757 + g.getName() + "'"); 687 return null;
758 return null; 688 }
759 } 689
760 690 final double[][] values = DischargeTables.loadDischargeTableValues(dt);
761 double [][] values = DischargeTables.loadDischargeTableValues(dt); 691
762 692 final TDoubleArrayList wsOut = new TDoubleArrayList(ws.length);
763 TDoubleArrayList wsOut = new TDoubleArrayList(ws.length); 693 final TDoubleArrayList qsOut = new TDoubleArrayList(ws.length);
764 TDoubleArrayList qsOut = new TDoubleArrayList(ws.length);
765 694
766 boolean generatedWs = false; 695 boolean generatedWs = false;
767 696
768 for (int i = 0; i < ws.length; i++) { 697 for (int i = 0; i < ws.length; i++) {
769 if (Double.isNaN(ws[i])) { 698 if (Double.isNaN(ws[i])) {
770 log.warn("W is NaN: ignored"); 699 log.warn("W is NaN: ignored");
771 continue; 700 continue;
772 } 701 }
773 double [] qs = DischargeTables.getQsForW(values, ws[i]); 702 final double[] qs = DischargeTables.getQsForW(values, ws[i]);
774 703
775 if (qs.length == 0) { 704 if (qs.length == 0) {
776 log.warn("No Qs found for W = " + ws[i]); 705 log.warn("No Qs found for W = " + ws[i]);
777 } 706 } else {
778 else { 707 for (final double q : qs) {
779 for (double q: qs) {
780 wsOut.add(ws[i]); 708 wsOut.add(ws[i]);
781 qsOut.add(q); 709 qsOut.add(q);
782 } 710 }
783 } 711 }
784 generatedWs |= qs.length != 1; 712 generatedWs |= qs.length != 1;
785 } 713 }
786 714
787 return new double [][] { 715 return new double[][] { qsOut.toNativeArray(), generatedWs ? wsOut.toNativeArray() : null };
788 qsOut.toNativeArray(), 716 }
789 generatedWs ? wsOut.toNativeArray() : null
790 };
791 }
792
793 717
794 /** 718 /**
795 * Returns the selected distance based on a given range (from, to). 719 * Returns the selected distance based on a given range (from, to).
796 * 720 *
797 * @param dFrom The StateData that contains the lower value. 721 * @param dFrom
798 * @param dTo The StateData that contains the upper value. 722 * The StateData that contains the lower value.
723 * @param dTo
724 * The StateData that contains the upper value.
799 * 725 *
800 * @return the selected distance. 726 * @return the selected distance.
801 */ 727 */
802 protected double[] getDistanceByRange(StateData dFrom, StateData dTo) { 728 protected double[] getDistanceByRange(final StateData dFrom, final StateData dTo) {
803 double from = Double.parseDouble((String) dFrom.getValue()); 729 final double from = Double.parseDouble((String) dFrom.getValue());
804 double to = Double.parseDouble((String) dTo.getValue()); 730 final double to = Double.parseDouble((String) dTo.getValue());
805 731
806 return new double[] { from, to }; 732 return new double[] { from, to };
807 } 733 }
808 734
809
810 /** 735 /**
811 * This method returns the Q values. 736 * This method returns the Q values.
812 * 737 *
813 * @return the selected Q values or null, if no Q values are selected. 738 * @return the selected Q values or null, if no Q values are selected.
814 */ 739 */
815 public double[] getQs() { 740 public double[] getQs() {
816 StateData dMode = getData("wq_isq"); 741 final StateData dMode = getData("wq_isq");
817 StateData dSelection = getData("wq_isrange"); 742 final StateData dSelection = getData("wq_isrange");
818 743
819 boolean isRange = dSelection != null 744 final boolean isRange = dSelection != null ? Boolean.valueOf((String) dSelection.getValue()) : false;
820 ? Boolean.valueOf((String)dSelection.getValue())
821 : false;
822 745
823 if (isQ()) { 746 if (isQ()) {
824 if (!isRange) { 747 if (!isRange) {
825 return getSingleWQValues(); 748 return getSingleWQValues();
826 } 749 } else {
827 else {
828 return getWQTriple(); 750 return getWQTriple();
829 } 751 }
830 } 752 } else {
831 else {
832 log.warn("You try to get Qs, but W has been inserted."); 753 log.warn("You try to get Qs, but W has been inserted.");
833 return null; 754 return null;
834 } 755 }
835 } 756 }
836 757
837
838 public boolean isQ() { 758 public boolean isQ() {
839 StateData mode = getData("wq_isq"); 759 final StateData mode = getData("wq_isq");
840 String value = (mode != null) ? (String) mode.getValue() : null; 760 final String value = (mode != null) ? (String) mode.getValue() : null;
841 return value != null ? Boolean.valueOf(value) : false; 761 return value != null ? Boolean.valueOf(value) : false;
842 } 762 }
843 763
844 public boolean isW() { 764 public boolean isW() {
845 StateData mode = getData("wq_isq"); 765 final StateData mode = getData("wq_isq");
846 String value = (mode != null) ? (String) mode.getValue() : null; 766 final String value = (mode != null) ? (String) mode.getValue() : null;
847 return value != null ? !Boolean.valueOf(value) : false; 767 return value != null ? !Boolean.valueOf(value) : false;
848 } 768 }
849 769
850 public boolean isFreeW() { 770 public boolean isFreeW() {
851 if(!isW()) { 771 if (!isW()) {
852 return false; 772 return false;
853 } 773 }
854 StateData mode = getData("wq_isfree"); 774 final StateData mode = getData("wq_isfree");
855 String value = (mode != null) ? (String) mode.getValue() : null; 775 final String value = (mode != null) ? (String) mode.getValue() : null;
856 776
857 return value != null ? Boolean.valueOf(value) : false; 777 return value != null ? Boolean.valueOf(value) : false;
858 } 778 }
859
860 779
861 /** 780 /**
862 * Returns true, if the parameter is set to compute data on a free range. 781 * Returns true, if the parameter is set to compute data on a free range.
863 * Otherwise it returns false, which tells the calculation that it is bound 782 * Otherwise it returns false, which tells the calculation that it is bound
864 * to a gauge. 783 * to a gauge.
865 * 784 *
866 * @return true, if the calculation should compute on a free range otherwise 785 * @return true, if the calculation should compute on a free range otherwise
867 * false and the calculation is bound to a gauge. 786 * false and the calculation is bound to a gauge.
868 */ 787 */
869 public boolean isFreeQ() { 788 public boolean isFreeQ() {
870 if(!isQ()) { 789 if (!isQ()) {
871 return false; 790 return false;
872 } 791 }
873 StateData mode = getData("wq_isfree"); 792 final StateData mode = getData("wq_isfree");
874 String value = (mode != null) ? (String) mode.getValue() : null; 793 final String value = (mode != null) ? (String) mode.getValue() : null;
875 794
876 log.debug("isFreeQ: " + value); 795 log.debug("isFreeQ: " + value);
877 796
878 return value != null && Boolean.valueOf(value); 797 return value != null && Boolean.valueOf(value);
879 } 798 }
880 799
881
882 /** 800 /**
883 * Returns the Q values based on a specified kilometer range. 801 * Returns the Q values based on a specified kilometer range.
884 * 802 *
885 * @param range A 2dim array with lower and upper kilometer range. 803 * @param range
804 * A 2dim array with lower and upper kilometer range.
886 * 805 *
887 * @return an array of Q values. 806 * @return an array of Q values.
888 */ 807 */
889 public double[] getQs(double[] range) { 808 public double[] getQs(final double[] range) {
890 StateData dMode = getData("wq_isq"); 809 final StateData dMode = getData("wq_isq");
891 810
892 if (isQ()) { 811 if (isQ()) {
893 return getWQForDist(range); 812 return getWQForDist(range);
894 } 813 }
895 814
896 log.warn("You try to get Qs, but Ws has been inserted."); 815 log.warn("You try to get Qs, but Ws has been inserted.");
897 return null; 816 return null;
898 } 817 }
899 818
900
901 /** 819 /**
902 * Returns the W values based on a specified kilometer range. 820 * Returns the W values based on a specified kilometer range.
903 * 821 *
904 * @param range A 2dim array with lower and upper kilometer range. 822 * @param range
823 * A 2dim array with lower and upper kilometer range.
905 * 824 *
906 * @return an array of W values. 825 * @return an array of W values.
907 */ 826 */
908 public double[] getWs(double[] range) { 827 public double[] getWs(final double[] range) {
909 if (isW()) { 828 if (isW()) {
910 return getWQForDist(range); 829 return getWQForDist(range);
911 } 830 }
912 831
913 log.warn("You try to get Ws, but Qs has been inserted."); 832 log.warn("You try to get Ws, but Qs has been inserted.");
914 return null; 833 return null;
915 } 834 }
916 835
917
918 /** 836 /**
919 * This method returns the W values. 837 * This method returns the W values.
920 * 838 *
921 * @return the selected W values or null, if no W values are selected. 839 * @return the selected W values or null, if no W values are selected.
922 */ 840 */
923 public double[] getWs() { 841 public double[] getWs() {
924 if (isW()) { 842 if (isW()) {
925 StateData dSingle = getData("wq_single"); 843 final StateData dSingle = getData("wq_single");
926 if (dSingle != null) { 844 if (dSingle != null) {
927 return getSingleWQValues(); 845 return getSingleWQValues();
928 } 846 } else {
929 else {
930 return getWQTriple(); 847 return getWQTriple();
931 } 848 }
932 } 849 } else {
933 else {
934 log.warn("You try to get Ws, but Q has been inserted."); 850 log.warn("You try to get Ws, but Q has been inserted.");
935 return null; 851 return null;
936 } 852 }
937 } 853 }
938 854
939 /** 855 /**
940 * This method returns the given W or Q values for a specific range 856 * This method returns the given W or Q values for a specific range
941 * (inserted in the WQ input panel for discharge longitudinal sections). 857 * (inserted in the WQ input panel for discharge longitudinal sections).
942 * 858 *
943 * @param dist A 2dim array with lower und upper kilometer values. 859 * @param dist
860 * A 2dim array with lower und upper kilometer values.
944 * 861 *
945 * @return an array of W or Q values. 862 * @return an array of W or Q values.
946 */ 863 */
947 protected double[] getWQForDist(double[] dist) { 864 protected double[] getWQForDist(final double[] dist) {
948 log.debug("Search wq values for range: " + dist[0] + " - " + dist[1]); 865 log.debug("Search wq values for range: " + dist[0] + " - " + dist[1]);
949 StateData data = getData("wq_values"); 866 final StateData data = getData("wq_values");
950 867
951 if (data == null) { 868 if (data == null) {
952 log.warn("Missing wq values!"); 869 log.warn("Missing wq values!");
953 return null; 870 return null;
954 } 871 }
955 872
956 String dataString = (String) data.getValue(); 873 final String dataString = (String) data.getValue();
957 String[] ranges = dataString.split(":"); 874 final String[] ranges = dataString.split(":");
958 875
959 for (String range: ranges) { 876 for (final String range : ranges) {
960 String[] parts = range.split(";"); 877 final String[] parts = range.split(";");
961 878
962 double lower = Double.parseDouble(parts[0]); 879 final double lower = Double.parseDouble(parts[0]);
963 double upper = Double.parseDouble(parts[1]); 880 final double upper = Double.parseDouble(parts[1]);
964 881
965 if (lower <= dist[0] && upper >= dist[1]) { 882 if (lower <= dist[0] && upper >= dist[1]) {
966 String[] values = parts[2].split(","); 883 final String[] values = parts[2].split(",");
967 884
968 int num = values.length; 885 final int num = values.length;
969 double[] res = new double[num]; 886 final double[] res = new double[num];
970 887
971 for (int i = 0; i < num; i++) { 888 for (int i = 0; i < num; i++) {
972 try { 889 try {
973 res[i] = Double.parseDouble(values[i]); 890 res[i] = Double.parseDouble(values[i]);
974 } 891 }
975 catch (NumberFormatException nfe) { 892 catch (final NumberFormatException nfe) {
976 log.warn(nfe, nfe); 893 log.warn(nfe, nfe);
977 } 894 }
978 } 895 }
979 896
980 return res; 897 return res;
984 log.warn("Specified range for WQ not found!"); 901 log.warn("Specified range for WQ not found!");
985 902
986 return null; 903 return null;
987 } 904 }
988 905
989
990 /** 906 /**
991 * This method returns an array of inserted WQ triples that consist of from, 907 * This method returns an array of inserted WQ triples that consist of from,
992 * to and the step width. 908 * to and the step width.
993 * 909 *
994 * @return an array of from, to and step width. 910 * @return an array of from, to and step width.
995 */ 911 */
996 protected double[] getWQTriple() { 912 protected double[] getWQTriple() {
997 StateData dFrom = getData("wq_from"); 913 final StateData dFrom = getData("wq_from");
998 StateData dTo = getData("wq_to"); 914 final StateData dTo = getData("wq_to");
999 915
1000 if (dFrom == null || dTo == null) { 916 if (dFrom == null || dTo == null) {
1001 log.warn("Missing start or end value for range."); 917 log.warn("Missing start or end value for range.");
1002 return null; 918 return null;
1003 } 919 }
1004 920
1005 double from = Double.parseDouble((String) dFrom.getValue()); 921 final double from = Double.parseDouble((String) dFrom.getValue());
1006 double to = Double.parseDouble((String) dTo.getValue()); 922 final double to = Double.parseDouble((String) dTo.getValue());
1007 923
1008 StateData dStep = getData("wq_step"); 924 final StateData dStep = getData("wq_step");
1009 925
1010 if (dStep == null) { 926 if (dStep == null) {
1011 log.warn("No step width given. Cannot compute Qs."); 927 log.warn("No step width given. Cannot compute Qs.");
1012 return null; 928 return null;
1013 } 929 }
1014 930
1015 double step = Double.parseDouble((String) dStep.getValue()); 931 double step = Double.parseDouble((String) dStep.getValue());
1016 932
1017 // if no width is given, the DEFAULT_Q_STEPS is used to compute the step 933 // if no width is given, the DEFAULT_Q_STEPS is used to compute the step
1018 // width. Maybe, we should round the value to a number of digits. 934 // width. Maybe, we should round the value to a number of digits.
1019 if (step == 0d) { 935 if (step == 0d) {
1020 double diff = to - from; 936 final double diff = to - from;
1021 step = diff / DEFAULT_Q_STEPS; 937 step = diff / DEFAULT_Q_STEPS;
1022 } 938 }
1023 939
1024 return DoubleUtil.explode(from, to, step); 940 return DoubleUtil.explode(from, to, step);
1025 } 941 }
1026
1027 942
1028 /** 943 /**
1029 * Returns an array of inserted WQ double values stored as whitespace 944 * Returns an array of inserted WQ double values stored as whitespace
1030 * separated list. 945 * separated list.
1031 * 946 *
1032 * @return an array of W or Q values. 947 * @return an array of W or Q values.
1033 */ 948 */
1034 protected double[] getSingleWQValues() { 949 protected double[] getSingleWQValues() {
1035 StateData dSingle = getData("wq_single"); 950 final StateData dSingle = getData("wq_single");
1036 951
1037 if (dSingle == null) { 952 if (dSingle == null) {
1038 log.warn("Cannot determine single WQ values. No data given."); 953 log.warn("Cannot determine single WQ values. No data given.");
1039 return null; 954 return null;
1040 } 955 }
1041 956
1042 String tmp = (String) dSingle.getValue(); 957 final String tmp = (String) dSingle.getValue();
1043 String[] strValues = tmp.split(" "); 958 final String[] strValues = tmp.split(" ");
1044 959
1045 TDoubleArrayList values = new TDoubleArrayList(); 960 final TDoubleArrayList values = new TDoubleArrayList();
1046 961
1047 for (String strValue: strValues) { 962 for (final String strValue : strValues) {
1048 try { 963 try {
1049 values.add(Double.parseDouble(strValue)); 964 values.add(Double.parseDouble(strValue));
1050 } 965 }
1051 catch (NumberFormatException nfe) { 966 catch (final NumberFormatException nfe) {
1052 log.warn(nfe, nfe); 967 log.warn(nfe, nfe);
1053 } 968 }
1054 } 969 }
1055 970
1056 values.sort(); 971 values.sort();

http://dive4elements.wald.intevation.org