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