comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java @ 3272:31168ac9c7e7

Partial fix for issue694 (heightmarks snap to nearest cross section). flys-artifacts/trunk@4916 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Tue, 10 Jul 2012 15:31:56 +0000
parents ed07dd55f487
children 739aa90eb79e
comparison
equal deleted inserted replaced
3271:4c4ec9e9650a 3272:31168ac9c7e7
14 import de.intevation.artifactdatabase.state.State; 14 import de.intevation.artifactdatabase.state.State;
15 15
16 import de.intevation.artifacts.Artifact; 16 import de.intevation.artifacts.Artifact;
17 import de.intevation.artifacts.ArtifactFactory; 17 import de.intevation.artifacts.ArtifactFactory;
18 import de.intevation.artifacts.CallMeta; 18 import de.intevation.artifacts.CallMeta;
19 import de.intevation.flys.artifacts.math.Distance;
19 import de.intevation.flys.artifacts.math.Linear; 20 import de.intevation.flys.artifacts.math.Linear;
20 21
21 import de.intevation.flys.artifacts.model.CrossSectionWaterLineFacet; 22 import de.intevation.flys.artifacts.model.CrossSectionWaterLineFacet;
22 import de.intevation.flys.artifacts.model.FacetTypes; 23 import de.intevation.flys.artifacts.model.FacetTypes;
23 import de.intevation.flys.artifacts.model.RelativePointFacet; 24 import de.intevation.flys.artifacts.model.RelativePointFacet;
31 import de.intevation.artifacts.common.utils.XMLUtils; 32 import de.intevation.artifacts.common.utils.XMLUtils;
32 33
33 import de.intevation.flys.artifacts.geom.Lines; 34 import de.intevation.flys.artifacts.geom.Lines;
34 35
35 import de.intevation.flys.model.FastCrossSectionLine; 36 import de.intevation.flys.model.FastCrossSectionLine;
37
36 38
37 /** 39 /**
38 * Artifact to access additional "waterlevel"-type of data, like the height 40 * Artifact to access additional "waterlevel"-type of data, like the height
39 * of protective measures (dikes). 41 * of protective measures (dikes).
40 * 42 *
50 Logger.getLogger(StaticWKmsArtifact.class); 52 Logger.getLogger(StaticWKmsArtifact.class);
51 53
52 public static final String STATIC_STATE_NAME = 54 public static final String STATIC_STATE_NAME =
53 "state.additional_wkms.static"; 55 "state.additional_wkms.static";
54 56
57 /** Data Item name to know whether we are Heighmarks and reveive
58 * some data slightly different. */
59 public static final String DATA_HEIGHT_TYPE =
60 "height_marks";
61
55 /** One and only state to be in. */ 62 /** One and only state to be in. */
56 protected transient State state = null; 63 protected transient State state = null;
57 64
58 65
59 /** 66 /**
108 } 115 }
109 116
110 String name; 117 String name;
111 if (parts[0].equals(HEIGHTMARKS_POINTS)) { 118 if (parts[0].equals(HEIGHTMARKS_POINTS)) {
112 name = HEIGHTMARKS_POINTS; 119 name = HEIGHTMARKS_POINTS;
120 addStringData(DATA_HEIGHT_TYPE, "true");
113 } 121 }
114 else { 122 else {
115 name = STATIC_WKMS; 123 name = STATIC_WKMS;
116 } 124 }
117 125
264 return Linear.linear(km, wkms.getKm(idx+mod), wkms.getKm(idx), wkms.getW(idx+mod), wkms.getW(idx)); 272 return Linear.linear(km, wkms.getKm(idx+mod), wkms.getKm(idx), wkms.getW(idx+mod), wkms.getW(idx));
265 } 273 }
266 274
267 275
268 /** 276 /**
277 * Get the W at a specific km, only if it is closer to km than to any of
278 * the other given km.
279 * Return Double.NaN otherwise
280 *
281 * @param wkms WKms in which to search for a spatially close W value.
282 * @param km the input km, which is compared to values from wkms.
283 * @param next the next available input km.
284 * @param prev the previous available input km.
285 *
286 * @return W in wkms that is closer to km than to next and prev, or Double.NaN.
287 */
288 public double getWAtCloseKm(WKms wkms, double km, double next, double prev) {
289 int size = wkms.size();
290 // TODO handle edge cases (with no next or prev).
291 for (int i = 0; i < size; i++) {
292 double wkmsKm = wkms.getKm(i);
293 double dist = Distance.distance(wkmsKm, km);
294 if ((prev != km && dist <= Distance.distance(wkmsKm, prev))
295 && dist <= Distance.distance(wkmsKm, next)) {
296 return wkms.getW(i);
297 }
298 }
299
300 return Double.NaN;
301 }
302
303
304 /**
269 * Returns W at Km of WKms, searching linearly. 305 * Returns W at Km of WKms, searching linearly.
270 * Returns -1 if not found. 306 * Returns -1 if not found.
271 * @param wkms the WKms object to search for given km. 307 * @param wkms the WKms object to search for given km.
272 * @param km The searched km. 308 * @param km The searched km.
273 * @return W at given km if in WKms, -1 if not found. 309 * @return W at given km if in WKms, -1 if not found.
274 */ 310 */
275 public static double getWAtKm(WKms wkms, double km) { 311 public static double getWAtKm(WKms wkms, double km) {
276 // Uninformed search. 312 // Uninformed search, intolerant.
313 double TOLERANCE = 0.0d;
277 int size = wkms.size(); 314 int size = wkms.size();
278 for (int i = 0; i < size; i++) { 315 for (int i = 0; i < size; i++) {
279 if (wkms.getKm(i) == km) { 316 if (Distance.within(wkms.getKm(i), km, TOLERANCE)) {
280 return wkms.getW(i); 317 return wkms.getW(i);
281 } 318 }
282 } 319 }
283 320
284 return -1; 321 return -1;
285 } 322 }
286 323
287 324
288 /** 325 /**
289 * Get points of line describing the surface of water at cross section. 326 * Get points of line describing the surface of water at cross section.
327 *
328 * @param idx Index of facet and in wkms array.
329 * @param csl FastCrossSectionLine to compute water surface agains.
330 * @param next The km of the next crosssectionline.
331 * @param prev The km of the previous crosssectionline.
290 * 332 *
291 * @return an array holding coordinates of points of surface of water ( 333 * @return an array holding coordinates of points of surface of water (
292 * in the form {{x1, x2}, {y1, y2}} ). 334 * in the form {{x1, x2}, {y1, y2}} ).
293 */ 335 */
294 @Override 336 @Override
295 public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl) { 337 public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl,
296 logger.debug("getWaterLines(" + idx + ")"); 338 double next, double prev
339 ) {
340 logger.debug("getWaterLines(" + idx + ")/" + identifier());
297 341
298 List<Point2D> points = csl.getPoints(); 342 List<Point2D> points = csl.getPoints();
299 343
300 WKms wkms = getWKms(0); 344 WKms wkms = getWKms(0);
301 345
302 double km = csl.getKm(); 346 double km = csl.getKm();
303 347
304 // Find W at km. 348 // Find W at km.
305 double wAtKm = getWAtKm(wkms, km); 349 double wAtKm;
306 if (wAtKm == -1) { 350
351 // If heightmarks, only deliver if data snaps.
352 if (getDataAsString(DATA_HEIGHT_TYPE) != null &&
353 getDataAsString(DATA_HEIGHT_TYPE).equals("true")) {
354 wAtKm = getWAtCloseKm(wkms, km, next, prev);
355 }
356 else {
357 wAtKm = getWAtKm(wkms, km);
358 }
359
360 if (wAtKm == -1 || Double.isNaN(wAtKm)) {
307 logger.warn("Waterlevel at km " + km + " unknown."); 361 logger.warn("Waterlevel at km " + km + " unknown.");
308 return new Lines.LineData(new double[][] {{}}, 0d, 0d); 362 return new Lines.LineData(new double[][] {{}}, 0d, 0d);
309 } 363 }
310 364
311 return Lines.createWaterLines(points, wAtKm); 365 return Lines.createWaterLines(points, wAtKm);

http://dive4elements.wald.intevation.org