diff artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/BedHeightsFinder.java @ 8964:45f1ad66560e

Code cleanup concerning calculations: improved error handling; improved interpolation; bed heights are now always used for spatial discretisation
author gernotbelger
date Thu, 29 Mar 2018 15:48:17 +0200
parents 798d9dcbccdd
children 439699ff9b2d
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/BedHeightsFinder.java	Wed Mar 28 17:04:20 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/BedHeightsFinder.java	Thu Mar 29 15:48:17 2018 +0200
@@ -24,33 +24,33 @@
 import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo;
 import org.dive4elements.river.model.BedHeight;
 import org.dive4elements.river.model.BedHeightValue;
+import org.dive4elements.river.model.BedHeightValueType;
 import org.dive4elements.river.utils.RiverUtils;
 
 /**
- * Provides bed heigts for vcarious calculations.
+ * Provides bed heights for various calculations.
  *
  * @author Gernot Belger
  */
 public final class BedHeightsFinder {
 
+    private static double MAX_DISTANCE_KM = 1;
+
     private final BedHeightInfo info;
 
     private final NavigableMap<Double, BedHeightValue> values;
 
-    private double meanBedHeight;
-
-    private double minBedHeight;
-
-    private double maxBedHeight;
+    private Calculation problems;
 
     /**
      * Create bed height finders from a collection of bed heights.
      */
-    public static Collection<BedHeightsFinder> createTkhBedHeights(final DoubleRange range, final Collection<BedHeight> bedHeights) {
+    public static Collection<BedHeightsFinder> createTkhBedHeights(final Calculation problems, final DoubleRange range,
+            final Collection<BedHeight> bedHeights) {
         final List<BedHeightsFinder> result = new ArrayList<>(bedHeights.size());
 
         for (final BedHeight bedHeight : bedHeights) {
-            final BedHeightsFinder finder = createBedHeights(bedHeight, range);
+            final BedHeightsFinder finder = createBedHeights(problems, bedHeight, range);
             result.add(finder);
         }
 
@@ -83,13 +83,18 @@
         // BedHeightFactory uses its own (direct) way of accessing the data, with its own implemented data classes.
         // return BedHeightFactory.getHeight(bedheightType, bedheightId, from, to);
 
-        final BedHeightsFinder bedHeight = bedheightId == null ? null : BedHeightsFinder.forId(bedheightId, calcRange);
-        if (bedHeight != null)
-            return bedHeight;
+        final BedHeightsFinder bedHeight = bedheightId == null ? null : BedHeightsFinder.forId(problems, bedheightId, calcRange);
+        if (bedHeight == null) {
+            problems.addProblem("sinfo.bedheightsfinder.notfound", soundingId);
+            return null;
+        }
 
-        // FIXME: 10n
-        problems.addProblem("Failed to access sounding with id '{0}'", soundingId);
-        return null;
+        if (bedHeight.isEmpty()) {
+            problems.addProblem("sinfo.bedheightsfinder.empty");
+            return null;
+        }
+
+        return bedHeight;
     }
 
     /**
@@ -97,21 +102,20 @@
      *
      * @return <code>null</code> if no bed height with the given id exists.
      */
-    private static BedHeightsFinder forId(final int id, final DoubleRange range) {
+    private static BedHeightsFinder forId(final Calculation problems, final int id, final DoubleRange range) {
 
         final BedHeight bedHeight = BedHeight.getBedHeightById(id);
         if (bedHeight == null)
             return null;
 
-        return BedHeightsFinder.createBedHeights(bedHeight, range);
+        return BedHeightsFinder.createBedHeights(problems, bedHeight, range);
     }
 
     /**
      * Create a finder for a given bed height.
      *
-     * @param range
      */
-    private static BedHeightsFinder createBedHeights(final BedHeight bedHeight, final DoubleRange range) {
+    private static BedHeightsFinder createBedHeights(final Calculation problems, final BedHeight bedHeight, final DoubleRange range) {
 
         // FIXME: sort by station, but in what direction?
         // FIXME: using river.getKmUp()?
@@ -128,12 +132,17 @@
 
         final BedHeightInfo info = BedHeightInfo.from(bedHeight);
 
-        return new BedHeightsFinder(info, values);
+        return new BedHeightsFinder(problems, info, values);
     }
 
-    private BedHeightsFinder(final BedHeightInfo info, final NavigableMap<Double, BedHeightValue> values) {
+    private BedHeightsFinder(final Calculation problems, final BedHeightInfo info, final NavigableMap<Double, BedHeightValue> values) {
         this.info = info;
         this.values = values;
+        this.problems = problems;
+    }
+
+    public boolean isEmpty() {
+        return this.values.isEmpty();
     }
 
     public BedHeightInfo getInfo() {
@@ -145,53 +154,46 @@
     }
 
     public double getMeanBedHeight(final double km) {
-        getBedHeights(km);
-        return this.meanBedHeight;
+        return interpolateBedHeights(km, BedHeightValueType.value);
     }
 
     public double getMinBedHeight(final double km) {
-        getBedHeights(km);
-        return this.minBedHeight;
+        return interpolateBedHeights(km, BedHeightValueType.min);
     }
 
     public double getMaxBedHeight(final double km) {
-        getBedHeights(km);
-        return this.maxBedHeight;
+        return interpolateBedHeights(km, BedHeightValueType.max);
     }
 
-    private boolean getBedHeights(final double km) {
-        if (this.values.containsKey(km)) {
-            this.meanBedHeight = (this.values.get(km).getHeight() != null) ? this.values.get(km).getHeight().doubleValue() : Double.NaN;
-            this.minBedHeight = (this.values.get(km).getMinHeight() != null) ? this.values.get(km).getMinHeight().doubleValue() : Double.NaN;
-            this.maxBedHeight = (this.values.get(km).getMaxHeight() != null) ? this.values.get(km).getMaxHeight().doubleValue() : Double.NaN;
-            return true;
+    private double interpolateBedHeights(final double km, final BedHeightValueType type) {
+        if (this.values.containsKey(km))
+        {
+            final Double value = type.getValue(this.values.get(km));
+            return value == null ? Double.NaN : value.doubleValue();
         }
 
         final Entry<Double, BedHeightValue> floorEntry = this.values.floorEntry(km);
         final Entry<Double, BedHeightValue> ceilingEntry = this.values.ceilingEntry(km);
 
-        if (floorEntry == null || ceilingEntry == null) {
-            this.meanBedHeight = Double.NaN;
-            this.minBedHeight = Double.NaN;
-            this.maxBedHeight = Double.NaN;
-            return false;
-        }
+        if (floorEntry == null || ceilingEntry == null)
+            return Double.NaN;
 
         final double floorKm = floorEntry.getKey().doubleValue();
         final double ceilKm = ceilingEntry.getKey().doubleValue();
 
-        // FIXME: check if we always want that...
+        /* report once if the interpolation distance exceeds 1000m */
+        if (Math.abs(floorKm - ceilKm) > MAX_DISTANCE_KM && this.problems != null) {
+            this.problems.addProblem(km, "linearInterpolator.maxdistance", MAX_DISTANCE_KM * 1000);
+            this.problems = null;
+            return Double.NaN;
+        }
 
-        this.meanBedHeight = interpolate(km, floorKm, ceilKm, floorEntry.getValue().getHeight(), ceilingEntry.getValue().getHeight());
-        this.minBedHeight = interpolate(km, floorKm, ceilKm, floorEntry.getValue().getMinHeight(), ceilingEntry.getValue().getMinHeight());
-        this.maxBedHeight = interpolate(km, floorKm, ceilKm, floorEntry.getValue().getMaxHeight(), ceilingEntry.getValue().getMaxHeight());
-        return true;
-    }
+        final Double floorHeight = type.getValue(floorEntry.getValue());
+        final Double ceilingHeight = type.getValue(ceilingEntry.getValue());
 
-    private double interpolate(final double km, final double floorKm, final double ceilKm, final Double floorHeight, final Double ceilHeight) {
-        if ((floorHeight != null) && (ceilHeight != null))
-            return Linear.linear(km, floorKm, ceilKm, floorHeight, ceilHeight);
-        else
+        if (floorHeight == null || ceilingHeight == null)
             return Double.NaN;
+
+        return Linear.linear(km, floorKm, ceilKm, floorHeight, ceilingHeight);
     }
 }
\ No newline at end of file

http://dive4elements.wald.intevation.org