Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation4.java @ 3468:f37e7e8907cb
merged flys-artifacts/2.8.1
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:39 +0200 |
parents | 22790758b132 |
children | 39885bdfc6fc |
comparison
equal
deleted
inserted
replaced
3387:5ffad8bde8ad | 3468:f37e7e8907cb |
---|---|
1 package de.intevation.flys.artifacts.model; | |
2 | |
3 import de.intevation.flys.artifacts.math.BackJumpCorrector; | |
4 import de.intevation.flys.artifacts.math.Function; | |
5 import de.intevation.flys.artifacts.math.Identity; | |
6 import de.intevation.flys.artifacts.math.Linear; | |
7 | |
8 import de.intevation.flys.artifacts.model.WstValueTable.QPosition; | |
9 | |
10 import de.intevation.flys.model.River; | |
11 | |
12 import de.intevation.flys.utils.DoubleUtil; | |
13 | |
14 import java.util.Arrays; | |
15 import java.util.List; | |
16 | |
17 import org.apache.log4j.Logger; | |
18 | |
19 public class Calculation4 | |
20 extends Calculation | |
21 { | |
22 private static Logger logger = Logger.getLogger(Calculation4.class); | |
23 | |
24 public static final double MINIMAL_STEP_WIDTH = 1e-5; | |
25 | |
26 protected List<Segment> segments; | |
27 | |
28 protected boolean isQ; | |
29 | |
30 public Calculation4() { | |
31 } | |
32 | |
33 public Calculation4(List<Segment> segments, River river, boolean isQ) { | |
34 | |
35 this.segments = segments; | |
36 this.isQ = isQ; | |
37 | |
38 Segment.setReferencePointConvertQ(segments, river, isQ, this); | |
39 } | |
40 | |
41 public CalculationResult calculate( | |
42 WstValueTable table, | |
43 double from, double to, double step | |
44 ) { | |
45 boolean debug = logger.isDebugEnabled(); | |
46 | |
47 if (debug) { | |
48 logger.debug( | |
49 "calculate from " + from + " to " + to + " step " + step); | |
50 logger.debug("# segments: " + segments.size()); | |
51 for (Segment segment: segments) { | |
52 logger.debug(" " + segment); | |
53 } | |
54 } | |
55 | |
56 if (segments.isEmpty()) { | |
57 logger.debug("no segments found"); | |
58 addProblem("no.segments.found"); | |
59 return new CalculationResult(new WQKms[0], this); | |
60 } | |
61 | |
62 int numResults = segments.get(0).values.length; | |
63 | |
64 if (numResults < 1) { | |
65 logger.debug("no values given"); | |
66 addProblem("no.values.given"); | |
67 return new CalculationResult(new WQKms[0], this); | |
68 } | |
69 | |
70 | |
71 WQKms [] results = new WQKms[numResults]; | |
72 for (int i = 0; i < results.length; ++i) { | |
73 results[i] = new WQKms(); | |
74 } | |
75 | |
76 if (Math.abs(step) < MINIMAL_STEP_WIDTH) { | |
77 step = MINIMAL_STEP_WIDTH; | |
78 } | |
79 | |
80 if (from > to) { | |
81 step = -step; | |
82 } | |
83 | |
84 QPosition [] qPositions = new QPosition[numResults]; | |
85 | |
86 Function [] functions = new Function[numResults]; | |
87 | |
88 double [] out = new double[2]; | |
89 | |
90 Segment sentinel = new Segment(Double.MAX_VALUE); | |
91 Segment s1 = sentinel, s2 = sentinel; | |
92 | |
93 for (double pos = from; | |
94 from < to ? pos <= to : pos >= to; | |
95 pos = DoubleUtil.round(pos + step) | |
96 ) { | |
97 if (pos < s1.referencePoint || pos > s2.referencePoint) { | |
98 if (debug) { | |
99 logger.debug("need to find new interval for " + pos); | |
100 } | |
101 // find new interval | |
102 if (pos <= segments.get(0).referencePoint) { | |
103 // before first segment -> "gleichwertig" | |
104 if (debug) { | |
105 logger.debug("before first segment -> gleichwertig"); | |
106 } | |
107 Segment first = segments.get(0); | |
108 double [] values = first.values; | |
109 double refPos = first.referencePoint; | |
110 for (int i = 0; i < qPositions.length; ++i) { | |
111 qPositions[i] = table.getQPosition( | |
112 refPos, values[i]); | |
113 } | |
114 sentinel.setReferencePoint(-Double.MAX_VALUE); | |
115 s1 = sentinel; | |
116 s2 = segments.get(0); | |
117 Arrays.fill(functions, Identity.IDENTITY); | |
118 } | |
119 else if (pos >= segments.get(segments.size()-1).referencePoint) { | |
120 // after last segment -> "gleichwertig" | |
121 if (debug) { | |
122 logger.debug("after last segment -> gleichwertig"); | |
123 } | |
124 Segment last = segments.get(segments.size()-1); | |
125 double [] values = last.values; | |
126 double refPos = last.referencePoint; | |
127 for (int i = 0; i < qPositions.length; ++i) { | |
128 qPositions[i] = table.getQPosition( | |
129 refPos, values[i]); | |
130 } | |
131 sentinel.setReferencePoint(Double.MAX_VALUE); | |
132 s1 = last; | |
133 s2 = sentinel; | |
134 Arrays.fill(functions, Identity.IDENTITY); | |
135 } | |
136 else { // "ungleichwertig" | |
137 // find matching interval | |
138 if (debug) { | |
139 logger.debug("in segments -> ungleichwertig"); | |
140 } | |
141 s1 = s2 = null; | |
142 for (int i = 1, N = segments.size(); i < N; ++i) { | |
143 Segment si1 = segments.get(i-1); | |
144 Segment si = segments.get(i); | |
145 if (debug) { | |
146 logger.debug("check " + pos + " in " + | |
147 si1.referencePoint + " - " + si.referencePoint); | |
148 } | |
149 if (pos >= si1.referencePoint | |
150 && pos <= si. referencePoint) { | |
151 s1 = si1; | |
152 s2 = si; | |
153 break; | |
154 } | |
155 } | |
156 | |
157 if (s1 == null) { | |
158 throw new IllegalStateException("no interval found"); | |
159 } | |
160 | |
161 Segment anchor, free; | |
162 | |
163 if (from > to) { anchor = s1; free = s2; } | |
164 else { anchor = s2; free = s1; } | |
165 | |
166 // build transforms based on "gleichwertiger" phase | |
167 for (int i = 0; i < qPositions.length; ++i) { | |
168 QPosition qi = table.getQPosition( | |
169 anchor.referencePoint, | |
170 anchor.values[i]); | |
171 | |
172 if ((qPositions[i] = qi) == null) { | |
173 addProblem(pos, "cannot.find.q", anchor.values[i]); | |
174 functions[i] = Identity.IDENTITY; | |
175 } | |
176 else { | |
177 double qA = table.getQ(qi, anchor.referencePoint); | |
178 double qF = table.getQ(qi, free .referencePoint); | |
179 | |
180 functions[i] = Double.isNaN(qA) || Double.isNaN(qF) | |
181 ? Identity.IDENTITY | |
182 : new Linear( | |
183 qA, qF, | |
184 anchor.values[i], free.values[i]); | |
185 | |
186 if (debug) { | |
187 logger.debug( | |
188 anchor.referencePoint + ": " + | |
189 qA + " -> " + functions[i].value(qA) + | |
190 " / " + free.referencePoint + ": " + | |
191 qF + " -> " + functions[i].value(qF)); | |
192 } | |
193 } | |
194 } // build transforms | |
195 } // "ungleichwertiges" interval | |
196 } // find matching interval | |
197 | |
198 for (int i = 0; i < qPositions.length; ++i) { | |
199 QPosition qPosition = qPositions[i]; | |
200 | |
201 if (qPosition == null) { | |
202 continue; | |
203 } | |
204 | |
205 if (table.interpolate(pos, out, qPosition, functions[i])) { | |
206 results[i].add(out[0], out[1], pos); | |
207 } | |
208 else { | |
209 addProblem(pos, "cannot.interpolate.w.q"); | |
210 } | |
211 } | |
212 } | |
213 | |
214 // Backjump correction | |
215 for (int i = 0; i < results.length; ++i) { | |
216 BackJumpCorrector bjc = new BackJumpCorrector(); | |
217 | |
218 double [] ws = results[i].getWs(); | |
219 double [] kms = results[i].getKms(); | |
220 | |
221 if (bjc.doCorrection(kms, ws, this)) { | |
222 results[i] = new WQCKms(results[i], bjc.getCorrected()); | |
223 } | |
224 } | |
225 | |
226 // name the curves | |
227 for (int i = 0; i < results.length; ++i) { | |
228 results[i].setName(createName(i)); | |
229 } | |
230 | |
231 return new CalculationResult(results, this); | |
232 } | |
233 | |
234 protected String createName(int index) { | |
235 // TODO: i18n | |
236 StringBuilder sb = new StringBuilder(isQ ? "Q" : "W"); | |
237 sb.append(" benutzerdefiniert ("); | |
238 for (int i = 0, N = segments.size(); i < N; ++i) { | |
239 if (i > 0) { | |
240 sb.append("; "); | |
241 } | |
242 Segment segment = segments.get(i); | |
243 sb.append((segment.backup != null | |
244 ? segment.backup | |
245 : segment.values)[index]); | |
246 } | |
247 sb.append(')'); | |
248 return sb.toString(); | |
249 } | |
250 } | |
251 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |