comparison artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation4.java @ 5838:5aa05a7a34b7

Rename modules to more fitting names.
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 15:23:37 +0200
parents flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation4.java@bd047b71ab37
children 4897a58c8746
comparison
equal deleted inserted replaced
5837:d9901a08d0a6 5838:5aa05a7a34b7
1 package org.dive4elements.river.artifacts.model;
2
3 import org.dive4elements.river.artifacts.access.Calculation4Access;
4
5 import org.dive4elements.river.artifacts.math.BackJumpCorrector;
6 import org.dive4elements.river.artifacts.math.Function;
7 import org.dive4elements.river.artifacts.math.Identity;
8 import org.dive4elements.river.artifacts.math.Linear;
9
10 import org.dive4elements.river.artifacts.model.RiverFactory;
11
12 import org.dive4elements.river.artifacts.model.WstValueTable.QPosition;
13
14 import org.dive4elements.river.model.River;
15
16 import org.dive4elements.river.utils.DoubleUtil;
17
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.List;
21
22 import org.apache.log4j.Logger;
23
24 public class Calculation4
25 extends Calculation
26 {
27 private static Logger logger = Logger.getLogger(Calculation4.class);
28
29 public static final double MINIMAL_STEP_WIDTH = 1e-5;
30
31 protected List<Segment> segments;
32
33 protected boolean isQ;
34 protected double from;
35 protected double to;
36 protected double step;
37 protected String river;
38
39 public Calculation4() {
40 }
41
42 public Calculation4(Calculation4Access access) {
43 logger.debug("Calculation4Access.cnst");
44 String river = access.getRiver();
45 List<Segment> segments = access.getSegments();
46 double [] range = access.getFromToStep();
47 boolean isQ = access.isQ();
48
49 if (river == null) {
50 addProblem("no.river.selected");
51 }
52
53 if (range == null) {
54 addProblem("no.range.found");
55 }
56
57 if (segments == null || segments.isEmpty()) {
58 addProblem("cannot.create.segments");
59 }
60
61 if (!hasProblems()) {
62 this.river = river;
63 this.segments = segments;
64 this.from = range[0];
65 this.to = range[1];
66 this.step = range[2];
67 this.isQ = isQ;
68 }
69 }
70
71 public CalculationResult calculate() {
72 if (hasProblems()) {
73 return new CalculationResult(new WQKms[0], this);
74 }
75
76 WstValueTable table = null;
77 River r = RiverFactory.getRiver(river);
78 if (r == null) {
79 addProblem("no.river.found");
80 }
81 else {
82 table = WstValueTableFactory.getTable(r);
83 if (table == null) {
84 addProblem("no.wst.for.river");
85 }
86 else {
87 Segment.setReferencePointConvertQ(segments, r, isQ, this);
88 }
89 }
90
91 return hasProblems()
92 ? new CalculationResult(new WQKms[0], this)
93 : innerCalculate(table);
94 }
95
96 protected CalculationResult innerCalculate(WstValueTable table) {
97 boolean debug = logger.isDebugEnabled();
98
99 if (debug) {
100 logger.debug(
101 "calculate from " + from + " to " + to + " step " + step);
102 logger.debug("# segments: " + segments.size());
103 for (Segment segment: segments) {
104 logger.debug(" " + segment);
105 }
106 }
107
108 int numResults = segments.get(0).values.length;
109
110 if (numResults < 1) {
111 logger.debug("no values given");
112 addProblem("no.values.given");
113 return new CalculationResult(new WQKms[0], this);
114 }
115
116
117 WQKms [] results = new WQKms[numResults];
118 for (int i = 0; i < results.length; ++i) {
119 results[i] = new WQKms();
120 }
121
122 if (Math.abs(step) < MINIMAL_STEP_WIDTH) {
123 step = MINIMAL_STEP_WIDTH;
124 }
125
126 if (from > to) {
127 step = -step;
128 }
129
130 QPosition [] qPositions = new QPosition[numResults];
131
132 Function [] functions = new Function[numResults];
133
134 double [] out = new double[2];
135
136 Segment sentinel = new Segment(Double.MAX_VALUE);
137 Segment s1 = sentinel, s2 = sentinel;
138
139 for (double pos = from;
140 from < to ? pos <= to : pos >= to;
141 pos = DoubleUtil.round(pos + step)
142 ) {
143 if (pos < s1.referencePoint || pos > s2.referencePoint) {
144 if (debug) {
145 logger.debug("need to find new interval for " + pos);
146 }
147 // find new interval
148 if (pos <= segments.get(0).referencePoint) {
149 // before first segment -> "gleichwertig"
150 if (debug) {
151 logger.debug("before first segment -> gleichwertig");
152 }
153 Segment first = segments.get(0);
154 double [] values = first.values;
155 double refPos = first.referencePoint;
156 for (int i = 0; i < qPositions.length; ++i) {
157 qPositions[i] = table.getQPosition(
158 refPos, values[i]);
159 }
160 sentinel.setReferencePoint(-Double.MAX_VALUE);
161 s1 = sentinel;
162 s2 = segments.get(0);
163 Arrays.fill(functions, Identity.IDENTITY);
164 }
165 else if (pos >= segments.get(segments.size()-1).referencePoint) {
166 // after last segment -> "gleichwertig"
167 if (debug) {
168 logger.debug("after last segment -> gleichwertig");
169 }
170 Segment last = segments.get(segments.size()-1);
171 double [] values = last.values;
172 double refPos = last.referencePoint;
173 for (int i = 0; i < qPositions.length; ++i) {
174 qPositions[i] = table.getQPosition(
175 refPos, values[i]);
176 }
177 sentinel.setReferencePoint(Double.MAX_VALUE);
178 s1 = last;
179 s2 = sentinel;
180 Arrays.fill(functions, Identity.IDENTITY);
181 }
182 else { // "ungleichwertig"
183 // find matching interval
184 if (debug) {
185 logger.debug("in segments -> ungleichwertig");
186 }
187 s1 = s2 = null;
188 for (int i = 1, N = segments.size(); i < N; ++i) {
189 Segment si1 = segments.get(i-1);
190 Segment si = segments.get(i);
191 if (debug) {
192 logger.debug("check " + pos + " in " +
193 si1.referencePoint + " - " + si.referencePoint);
194 }
195 if (pos >= si1.referencePoint
196 && pos <= si. referencePoint) {
197 s1 = si1;
198 s2 = si;
199 break;
200 }
201 }
202
203 if (s1 == null) {
204 throw new IllegalStateException("no interval found");
205 }
206
207 Segment anchor, free;
208
209 if (from > to) { anchor = s1; free = s2; }
210 else { anchor = s2; free = s1; }
211
212 // build transforms based on "gleichwertiger" phase
213 for (int i = 0; i < qPositions.length; ++i) {
214 QPosition qi = table.getQPosition(
215 anchor.referencePoint,
216 anchor.values[i]);
217
218 if ((qPositions[i] = qi) == null) {
219 addProblem(pos, "cannot.find.q", anchor.values[i]);
220 functions[i] = Identity.IDENTITY;
221 }
222 else {
223 double qA = table.getQ(qi, anchor.referencePoint);
224 double qF = table.getQ(qi, free .referencePoint);
225
226 functions[i] = Double.isNaN(qA) || Double.isNaN(qF)
227 ? Identity.IDENTITY
228 : new Linear(
229 qA, qF,
230 anchor.values[i], free.values[i]);
231
232 if (debug) {
233 logger.debug(
234 anchor.referencePoint + ": " +
235 qA + " -> " + functions[i].value(qA) +
236 " / " + free.referencePoint + ": " +
237 qF + " -> " + functions[i].value(qF));
238 }
239 }
240 } // build transforms
241 } // "ungleichwertiges" interval
242 } // find matching interval
243
244 for (int i = 0; i < qPositions.length; ++i) {
245 QPosition qPosition = qPositions[i];
246
247 if (qPosition == null) {
248 continue;
249 }
250
251 if (table.interpolate(pos, out, qPosition, functions[i])) {
252 results[i].add(out[0], out[1], pos);
253 }
254 else {
255 addProblem(pos, "cannot.interpolate.w.q");
256 }
257 }
258 }
259
260 // Backjump correction
261 for (int i = 0; i < results.length; ++i) {
262 BackJumpCorrector bjc = new BackJumpCorrector();
263
264 double [] ws = results[i].getWs();
265 double [] kms = results[i].getKms();
266
267 if (bjc.doCorrection(kms, ws, this)) {
268 results[i] = new WQCKms(results[i], bjc.getCorrected());
269 }
270 }
271
272 // Name the curves.
273 for (int i = 0; i < results.length; ++i) {
274 results[i].setName(createName(i));
275 }
276
277 // Generate the "Umhuellende".
278 ConstantWQKms [] infoldings =
279 generateInfolding(table, results, from, to, step);
280
281 // TODO: Use qkms in a new result type.
282 WQKms [] newResults = new WQKms[results.length + infoldings.length];
283 System.arraycopy(
284 results, 0, newResults, 0, results.length);
285 System.arraycopy(
286 infoldings, 0, newResults, results.length, infoldings.length);
287
288 return new CalculationResult(newResults, this);
289 }
290
291 protected ConstantWQKms [] generateInfolding(
292 WstValueTable wst,
293 WQKms [] results,
294 double from,
295 double to,
296 double step
297 ) {
298 WstValueTable.Column [] columns = wst.getColumns();
299
300 InfoldingColumns ic = new InfoldingColumns(columns);
301 ic.markInfoldingColumns(results);
302
303 List<ConstantWQKms> infoldings = new ArrayList<ConstantWQKms>();
304
305 boolean [] infoldingColumns = ic.getInfoldingColumns();
306
307 double [] kms = null;
308 double [] ws = null;
309
310 for (int i = 0; i < infoldingColumns.length; ++i) {
311 if (!infoldingColumns[i]) {
312 continue;
313 }
314
315 if (kms == null) {
316 kms = DoubleUtil.explode(from, to, step);
317 ws = new double[kms.length];
318 }
319
320 QRangeTree.QuickQFinder qf =
321 columns[i].getQRangeTree().new QuickQFinder();
322
323 int numProblemsBefore = numProblems();
324 double [] qs = qf.findQs(kms, this);
325
326 String name = columns[i].getName();
327 ConstantWQKms infolding = new ConstantWQKms(kms, qs, ws, name);
328
329 if (numProblems() > numProblemsBefore) {
330 infolding.removeNaNs();
331 }
332
333 infoldings.add(infolding);
334 }
335
336 for (int i = 0; i < infoldings.size(); i++) {
337 String name = infoldings.get(i).getName();
338 // TODO: i18n
339 if (i == 0) {
340 infoldings.get(i).setName("untere Umh\u00fcllende " + name);
341 }
342 else if (i == infoldings.size() - 1) {
343 infoldings.get(i).setName("obere Umh\u00fcllende " + name);
344 }
345 else {
346 infoldings.get(i).setName("geschnitten " + name);
347 }
348 }
349 return infoldings.toArray(new ConstantWQKms[infoldings.size()]);
350 }
351
352 // TODO: issue1109/2, merge with FixRealizingCalculation
353 protected String createName(int index) {
354 // TODO: i18n
355 StringBuilder sb = new StringBuilder(isQ ? "Q" : "W");
356 sb.append(" benutzerdefiniert (");
357 for (int i = 0, N = segments.size(); i < N; ++i) {
358 if (i > 0) {
359 sb.append("; ");
360 }
361 Segment segment = segments.get(i);
362 sb.append((segment.backup != null
363 ? segment.backup
364 : segment.values)[index]);
365 }
366 sb.append(')');
367 return sb.toString();
368 }
369 }
370 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org