gernotbelger@8915: /** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde gernotbelger@8915: * Software engineering by gernotbelger@8915: * Björnsen Beratende Ingenieure GmbH gernotbelger@8915: * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt gernotbelger@8915: * gernotbelger@8915: * This file is Free Software under the GNU AGPL (>=v3) gernotbelger@8915: * and comes with ABSOLUTELY NO WARRANTY! Check out the gernotbelger@8915: * documentation coming with Dive4Elements River for details. gernotbelger@8915: */ gernotbelger@8915: package org.dive4elements.river.artifacts.sinfo.tkhstate; gernotbelger@8915: gernotbelger@8915: import java.util.ArrayList; gernotbelger@8915: import java.util.Collection; gernotbelger@8915: import java.util.Collections; gernotbelger@8915: import java.util.List; gernotbelger@8915: import java.util.Map.Entry; gernotbelger@8915: import java.util.NavigableMap; gernotbelger@8915: import java.util.TreeMap; gernotbelger@8915: gernotbelger@8915: import org.apache.commons.lang.math.DoubleRange; gernotbelger@8915: import org.dive4elements.river.artifacts.math.Linear; gernotbelger@8915: import org.dive4elements.river.artifacts.model.Calculation; gernotbelger@8915: import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo; gernotbelger@8915: import org.dive4elements.river.model.BedHeight; gernotbelger@8915: import org.dive4elements.river.model.BedHeightValue; gernotbelger@8915: import org.dive4elements.river.model.River; gernotbelger@8915: gernotbelger@8915: /** gernotbelger@8915: * Provides bed heigts for vcarious calculations. gernotbelger@8915: * gernotbelger@8915: * @author Gernot Belger gernotbelger@8915: */ gernotbelger@8915: public final class BedHeightsFinder { gernotbelger@8915: gernotbelger@8915: private final BedHeightInfo info; gernotbelger@8915: gernotbelger@8915: private final NavigableMap values; gernotbelger@8915: gernotbelger@8915: /** gernotbelger@8915: * Create specific bed heights used in tkh-calculation gernotbelger@8915: * gernotbelger@8915: * @param problems gernotbelger@8915: */ gernotbelger@8915: public static Collection createTkhBedHeights(final River river, final Calculation problems, final DoubleRange range) { gernotbelger@8915: // FIXME: determine relevant bed-heights by river: read from some configuration file gernotbelger@8915: // '3' is already the right one for demo-model == '"DGM-2004_Epoche-2-SOBEK"' gernotbelger@8915: final int bedheightId = 3; gernotbelger@8915: gernotbelger@8915: final Collection bedHeights = Collections.singletonList(BedHeight.getBedHeightById(bedheightId)); gernotbelger@8915: gernotbelger@8915: // TODO: check for overlapping ranges... and provide a warning message, else we get problems later gernotbelger@8915: gernotbelger@8915: final List result = new ArrayList<>(bedHeights.size()); gernotbelger@8915: gernotbelger@8915: for (final BedHeight bedHeight : bedHeights) { gernotbelger@8915: result.add(createBedHeights(bedHeight, range)); gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: return result; gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: /** gernotbelger@8915: * Creates a {@link BedHeightsFinder} for a dataset from the database, specified by its id. gernotbelger@8915: * gernotbelger@8915: * @return null if no bed height with the given id exists. gernotbelger@8915: */ gernotbelger@8915: public static BedHeightsFinder forId(final int id, final DoubleRange range) { gernotbelger@8915: gernotbelger@8915: final BedHeight bedHeight = BedHeight.getBedHeightById(id); gernotbelger@8915: if (bedHeight == null) gernotbelger@8915: return null; gernotbelger@8915: gernotbelger@8915: return BedHeightsFinder.createBedHeights(bedHeight, range); gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: /** gernotbelger@8915: * Create a finder for a given bed height. gernotbelger@8915: * gernotbelger@8915: * @param range gernotbelger@8915: */ gernotbelger@8915: private static BedHeightsFinder createBedHeights(final BedHeight bedHeight, final DoubleRange range) { gernotbelger@8915: gernotbelger@8915: // FIXME: sort by station, but in what direction? gernotbelger@8915: // FIXME: using river.getKmUp()? gernotbelger@8915: final NavigableMap values = new TreeMap<>(); gernotbelger@8915: gernotbelger@8915: for (final BedHeightValue bedHeightValue : bedHeight.getValues()) { gernotbelger@8915: final Double station = bedHeightValue.getStation(); gernotbelger@8915: if (station != null && range.containsDouble(station)) { gernotbelger@8915: gernotbelger@8915: if (bedHeightValue.getHeight() != null) gernotbelger@8915: values.put(station, bedHeightValue); gernotbelger@8915: } gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: final BedHeightInfo info = BedHeightInfo.from(bedHeight); gernotbelger@8915: gernotbelger@8915: return new BedHeightsFinder(info, values); gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: private BedHeightsFinder(final BedHeightInfo info, final NavigableMap values) { gernotbelger@8915: this.info = info; gernotbelger@8915: this.values = values; gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: public BedHeightInfo getInfo() { gernotbelger@8915: return this.info; gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: public Collection getStations() { gernotbelger@8915: return this.values.keySet(); gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: public double getMeanBedHeight(final double km) { gernotbelger@8915: gernotbelger@8915: if (this.values.containsKey(km)) gernotbelger@8915: return this.values.get(km).getHeight(); gernotbelger@8915: gernotbelger@8915: final Entry floorEntry = this.values.floorEntry(km); gernotbelger@8915: final Entry ceilingEntry = this.values.ceilingEntry(km); gernotbelger@8915: gernotbelger@8915: if (floorEntry == null || ceilingEntry == null) gernotbelger@8915: return Double.NaN; gernotbelger@8915: gernotbelger@8915: final double floorKm = floorEntry.getKey(); gernotbelger@8915: final double floorHeight = floorEntry.getValue().getHeight(); gernotbelger@8915: final double ceilKm = ceilingEntry.getKey(); gernotbelger@8915: final double ceilHeight = ceilingEntry.getValue().getHeight(); gernotbelger@8915: gernotbelger@8915: // FIXME: check if we always want that... gernotbelger@8915: gernotbelger@8915: return Linear.linear(km, floorKm, ceilKm, floorHeight, ceilHeight); gernotbelger@8915: } gernotbelger@8915: }