comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java @ 3651:06a65baae494

merged flys-artifacts/2.9
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:43 +0200
parents afc7bfb4800b
children 0623cdf32b38
comparison
equal deleted inserted replaced
3549:6a8f83c538e3 3651:06a65baae494
1 package de.intevation.flys.artifacts;
2
3 import de.intevation.artifactdatabase.state.DefaultOutput;
4 import de.intevation.artifactdatabase.state.Facet;
5 import de.intevation.artifactdatabase.state.FacetActivity;
6 import de.intevation.artifactdatabase.state.State;
7
8 import de.intevation.artifacts.Artifact;
9 import de.intevation.artifacts.ArtifactFactory;
10 import de.intevation.artifacts.CallMeta;
11
12 import de.intevation.artifacts.common.utils.XMLUtils;
13
14 import de.intevation.flys.artifacts.geom.Lines;
15
16 import de.intevation.flys.artifacts.math.Distance;
17 import de.intevation.flys.artifacts.math.Linear;
18
19 import de.intevation.flys.artifacts.model.CrossSectionWaterLineFacet;
20 import de.intevation.flys.artifacts.model.FacetTypes;
21 import de.intevation.flys.artifacts.model.RelativePointFacet;
22 import de.intevation.flys.artifacts.model.WKms;
23 import de.intevation.flys.artifacts.model.WKmsFacet;
24 import de.intevation.flys.artifacts.model.WKmsFactory;
25
26 import de.intevation.flys.artifacts.resources.Resources;
27
28 import de.intevation.flys.artifacts.states.StaticState;
29
30 import de.intevation.flys.model.FastCrossSectionLine;
31
32 import java.awt.geom.Point2D;
33
34 import java.util.ArrayList;
35 import java.util.List;
36
37 import org.apache.log4j.Logger;
38
39 import org.w3c.dom.Document;
40
41 /**
42 * Artifact to access additional "waterlevel"-type of data, like the height
43 * of protective measures (dikes).
44 *
45 * This artifact neglects (Static)FLYSArtifacts capabilities of interaction
46 * with the StateEngine by overriding the getState*-methods.
47 */
48 public class StaticWKmsArtifact
49 extends StaticFLYSArtifact
50 implements FacetTypes, WaterLineArtifact
51 {
52 /** The logger for this class. */
53 private static Logger logger =
54 Logger.getLogger(StaticWKmsArtifact.class);
55
56 private static final String NAME = "staticwkms";
57
58 static {
59 // TODO: Move to configuration.
60 FacetActivity.Registry.getInstance()
61 .register(NAME, FacetActivity.INACTIVE);
62 }
63
64 public static final String STATIC_STATE_NAME =
65 "state.additional_wkms.static";
66
67 /** Data Item name to know whether we are Heighmarks and reveive
68 * some data slightly different. */
69 public static final String DATA_HEIGHT_TYPE =
70 "height_marks";
71
72 /** One and only state to be in. */
73 protected transient State state = null;
74
75
76 /**
77 * Trivial Constructor.
78 */
79 public StaticWKmsArtifact() {
80 logger.debug("StaticWKmsArtifact.StaticWKmsArtifact");
81 }
82
83 @Override
84 public String getName() {
85 return NAME;
86 }
87
88 /**
89 * Gets called from factory, to set things up.
90 */
91 @Override
92 public void setup(
93 String identifier,
94 ArtifactFactory factory,
95 Object context,
96 CallMeta callMeta,
97 Document data)
98 {
99 logger.debug("StaticWKmsArtifact.setup");
100
101 state = new StaticState(STATIC_STATE_NAME);
102
103 if (logger.isDebugEnabled()) {
104 logger.debug(XMLUtils.toString(data));
105 }
106
107 List<Facet> fs = new ArrayList<Facet>();
108 String code = getDatacageIDValue(data);
109
110 // TODO Go for JSON, one day.
111 //ex.: flood_protection-wstv-114-12
112 if (code != null) {
113 String [] parts = code.split("-");
114
115 if (parts.length >= 4) {
116 int col = -1;
117 int wst = Integer.parseInt(parts[3]);
118
119 if (!parts[2].equals("A")) {
120 col = Integer.parseInt(parts[2]);
121 }
122
123 addStringData("col_pos", parts[2]);
124 addStringData("wst_id", parts[3]);
125
126 String wkmsName;
127 if (col >= 0) {
128 wkmsName = WKmsFactory.getWKmsName(col, wst);
129 }
130 else {
131 wkmsName = WKmsFactory.getWKmsName(wst);
132 }
133
134 String name;
135 if (parts[0].equals(HEIGHTMARKS_POINTS)) {
136 name = HEIGHTMARKS_POINTS;
137 addStringData(DATA_HEIGHT_TYPE, "true");
138 }
139 else {
140 name = STATIC_WKMS;
141 }
142
143 String facetDescription = Resources.getMsg(
144 callMeta, wkmsName, wkmsName);
145 Facet wKmsFacet = new WKmsFacet(
146 name,
147 facetDescription);
148 Facet csFacet = new CrossSectionWaterLineFacet(0,
149 facetDescription);
150 Facet rpFacet = new RelativePointFacet(facetDescription);
151
152 fs.add(wKmsFacet);
153 fs.add(csFacet);
154 fs.add(rpFacet);
155 facets.put(state.getID(), fs);
156 }
157 }
158
159 spawnState();
160 super.setup(identifier, factory, context, callMeta, data);
161 }
162
163
164 /**
165 * Initialize the static state with output.
166 * @return static state
167 */
168 protected State spawnState() {
169 state = new StaticState(STATIC_STATE_NAME);
170 List<Facet> fs = facets.get(STATIC_STATE_NAME);
171 DefaultOutput output = new DefaultOutput(
172 "general",
173 "general", "image/png",
174 fs,
175 "chart");
176
177 state.getOutputs().add(output);
178 return state;
179 }
180
181
182 /**
183 * Called via setup.
184 *
185 * @param artifact The master-artifact.
186 */
187 @Override
188 protected void initialize(
189 Artifact artifact,
190 Object context,
191 CallMeta meta)
192 {
193 logger.debug("StaticWKmsArtifact.initialize");
194 FLYSArtifact winfo = (FLYSArtifact) artifact;
195 // TODO: The river is of no interest, so far.
196 addData("river", winfo.getData("river"));
197 }
198
199
200 /**
201 * Get a list containing the one and only State.
202 * @param context ignored.
203 * @return list with one and only state.
204 */
205 @Override
206 protected List<State> getStates(Object context) {
207 ArrayList<State> states = new ArrayList<State>();
208 states.add(getState());
209 return states;
210 }
211
212
213 /**
214 * Get the "current" state (there is but one).
215 * @param cc ignored.
216 * @return the "current" (only possible) state.
217 */
218 @Override
219 public State getCurrentState(Object cc) {
220 return getState();
221 }
222
223
224 /**
225 * Get the only possible state.
226 * @return the state.
227 */
228 protected State getState() {
229 return getState(null, null);
230 }
231
232
233 /**
234 * Get the state.
235 * @param context ignored.
236 * @param stateID ignored.
237 * @return the state.
238 */
239 @Override
240 protected State getState(Object context, String stateID) {
241 return (state != null)
242 ? state
243 : spawnState();
244 }
245
246
247 /**
248 * Get WKms from factory.
249 * @param idx param is not needed (TODO?)
250 * @return WKms according to parameterization (can be null);
251 */
252 public WKms getWKms(int idx) {
253 logger.debug("StaticWKmsArtifact.getWKms");
254
255 return WKmsFactory.getWKms(
256 Integer.parseInt(getDataAsString("col_pos")),
257 Integer.parseInt(getDataAsString("wst_id")));
258 }
259
260
261 /**
262 * Returns W at Km of WKms, linearly interpolated.
263 * Returns -1 if not found.
264 */
265 public static double getWAtKmLin(WKms wkms, double km) {
266 // Uninformed search.
267 int size = wkms.size();
268 int idx = 0;
269 boolean kmIncreasing = (wkms.getKm(0) < wkms.getKm(wkms.size()-1))
270 ? true : false;
271 if (kmIncreasing) {
272 while (idx < size && wkms.getKm(idx) < km) {
273 idx++;
274 }
275 }
276 else {
277 idx = wkms.size() -1;
278 while (idx > 0 && wkms.getKm(idx) > km) {
279 idx--;
280 }
281 }
282
283 if (idx == size -1 || idx == 0) {
284 return -1;
285 }
286
287 // Do linear interpolation
288 int mod = kmIncreasing ? -1 : +1;
289 return Linear.linear(km, wkms.getKm(idx+mod), wkms.getKm(idx), wkms.getW(idx+mod), wkms.getW(idx));
290 }
291
292
293 /**
294 * Get the W at a specific km, only if it is closer to km than to any of
295 * the other given km.
296 * Return Double.NaN otherwise
297 *
298 * @param wkms WKms in which to search for a spatially close W value.
299 * @param km the input km, which is compared to values from wkms.
300 * @param next the next available input km (-1 if unavailable).
301 * @param prev the previous available input km (-1 if unavailable).
302 *
303 * @return W in wkms that is closer to km than to next and prev, or Double.NaN.
304 */
305 public double getWAtCloseKm(WKms wkms, double km, double next, double prev) {
306 int size = wkms.size();
307 for (int i = 0; i < size; i++) {
308 double wkmsKm = wkms.getKm(i);
309 double dist = Distance.distance(wkmsKm, km);
310 if ((prev == -1d || dist <= Distance.distance(wkmsKm, prev))
311 && (next == -1d || dist <= Distance.distance(wkmsKm, next))) {
312 return wkms.getW(i);
313 }
314 }
315
316 return Double.NaN;
317 }
318
319
320 /**
321 * Returns W at Km of WKms, searching linearly.
322 * Returns -1 if not found.
323 * @param wkms the WKms object to search for given km.
324 * @param km The searched km.
325 * @return W at given km if in WKms, -1 if not found.
326 */
327 public static double getWAtKm(WKms wkms, double km) {
328 // Uninformed search, intolerant.
329 double TOLERANCE = 0.0d;
330 int size = wkms.size();
331 for (int i = 0; i < size; i++) {
332 if (Distance.within(wkms.getKm(i), km, TOLERANCE)) {
333 return wkms.getW(i);
334 }
335 }
336
337 return -1;
338 }
339
340
341 /**
342 * Get points of line describing the surface of water at cross section.
343 *
344 * @param idx Index of facet and in wkms array.
345 * @param csl FastCrossSectionLine to compute water surface agains.
346 * @param next The km of the next crosssectionline.
347 * @param prev The km of the previous crosssectionline.
348 *
349 * @return an array holding coordinates of points of surface of water (
350 * in the form {{x1, x2}, {y1, y2}} ).
351 */
352 @Override
353 public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl,
354 double next, double prev
355 ) {
356 logger.debug("getWaterLines(" + idx + ")/" + identifier());
357
358 List<Point2D> points = csl.getPoints();
359
360 WKms wkms = getWKms(0);
361
362 double km = csl.getKm();
363
364 // Find W at km.
365 double wAtKm;
366
367 // If heightmarks, only deliver if data snaps.
368 if (getDataAsString(DATA_HEIGHT_TYPE) != null &&
369 getDataAsString(DATA_HEIGHT_TYPE).equals("true")) {
370 wAtKm = getWAtCloseKm(wkms, km, next, prev);
371 }
372 else {
373 wAtKm = getWAtKm(wkms, km);
374 }
375
376 if (wAtKm == -1 || Double.isNaN(wAtKm)) {
377 logger.warn("Waterlevel at km " + km + " unknown.");
378 return new Lines.LineData(new double[][] {{}}, 0d, 0d);
379 }
380
381 return Lines.createWaterLines(points, wAtKm);
382 }
383 }
384 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org