Mercurial > dive4elements > river
view artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/ChannelFinder.java @ 9446:e60584f2a531
Added bundu bzws calculation for missing volumes (masses still not yet ready) and results1/2/3
author | mschaefer |
---|---|
date | Tue, 21 Aug 2018 18:19:35 +0200 |
parents | d194c5b24bf8 |
children | ac41551a8e4d |
line wrap: on
line source
/** 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; } }