Mercurial > dive4elements > river
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); |