diff artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/ChannelFinder.java @ 9432:d194c5b24bf8

Added bundu bzws w calculation and longitudinal sections of wspl and depth
author mschaefer
date Mon, 20 Aug 2018 09:46:02 +0200
parents
children ac41551a8e4d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/ChannelFinder.java	Mon Aug 20 09:46:02 2018 +0200
@@ -0,0 +1,155 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.artifacts.bundu.bezugswst;
+
+import java.util.Map.Entry;
+import java.util.NavigableMap;
+import java.util.TreeMap;
+
+import org.dive4elements.river.artifacts.math.Linear;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.sinfo.Channel;
+import org.dive4elements.river.model.sinfo.ChannelValue;
+
+/**
+ * Provides channel depth and height of a river
+ *
+ * @author Matthias Schäfer
+ */
+public final class ChannelFinder {
+
+    /***** TYPES *****/
+
+    public enum ChannelValueType {
+        depth {
+            @Override
+            public Double getValue(final ChannelValue channelValue) {
+                return channelValue.getDepth();
+            }
+        },
+        width {
+            @Override
+            public Double getValue(final ChannelValue channelValue) {
+                return channelValue.getWidth();
+            }
+        };
+
+        public abstract Double getValue(final ChannelValue channelValue);
+    }
+
+    /***** FIELDS *****/
+
+    // private static Logger log = Logger.getLogger(ChannelFinder.class);
+
+    private static double MAX_DISTANCE_KM = 1;
+
+    private final NavigableMap<Double, ChannelValue> values = new TreeMap<>();
+
+    private Calculation problems;
+
+
+    /***** CONSTRUCTORS *****/
+
+    private ChannelFinder(final Calculation problems, final Channel channel) {
+
+        this.problems = problems;
+
+        for (final ChannelValue v : channel.getValues()) {
+            this.values.put(v.getStation(), v);
+        }
+    }
+
+    /***** METHODS *****/
+
+    /**
+     * Loads the channel values for a river and year
+     *
+     * @return Whether the load has been successful
+     */
+    public static ChannelFinder loadValues(final Calculation problems, final River river, final int year) {
+        final Channel channel = Channel.getSeries(river, year);
+        if (channel != null)
+            return new ChannelFinder(problems, channel);
+
+        problems.addProblem("channelfinder.empty");
+        return null;
+    }
+
+
+    /***** METHODS *****/
+
+    /**
+     * Searches the channel depth of a station
+     */
+    public double getDepth(final double station) {
+        final double value = interpolateChannel(station, ChannelValueType.depth);
+        if (Double.isNaN(value))
+            reportProblem(station);
+        return value;
+    }
+
+    /**
+     * Searches the channel width of a station
+     */
+    public double getWidth(final double station) {
+        final double value = interpolateChannel(station, ChannelValueType.width);
+        if (Double.isNaN(value))
+            reportProblem(station);
+        return value;
+    }
+
+    /**
+     * Searches and interpolates a channel value for a km
+     */
+    private double interpolateChannel(final double km, final ChannelValueType 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, ChannelValue> floorEntry = this.values.floorEntry(km);
+        final Entry<Double, ChannelValue> ceilingEntry = this.values.ceilingEntry(km);
+
+        if ((floorEntry == null) || (ceilingEntry == null))
+            return Double.NaN;
+
+        final double floorKm = floorEntry.getKey().doubleValue();
+        final double ceilKm = ceilingEntry.getKey().doubleValue();
+
+        /* 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;
+        }
+
+        final Double floorHeight = type.getValue(floorEntry.getValue());
+        final Double ceilingHeight = type.getValue(ceilingEntry.getValue());
+
+        if (floorHeight == null || ceilingHeight == null)
+            return Double.NaN;
+
+        return Linear.linear(km, floorKm, ceilKm, floorHeight, ceilingHeight);
+    }
+
+    private void reportProblem(final double km) {
+
+        if (this.problems == null)
+            return;
+
+        this.problems.addProblem(km, "channelfinder.missing");
+
+        // report problem only once
+        this.problems = null;
+    }
+}
\ No newline at end of file

http://dive4elements.wald.intevation.org