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.tkhcalculation; gernotbelger@8915: gernotbelger@8915: import org.apache.commons.lang.math.DoubleRange; gernotbelger@8915: import org.apache.commons.math.FunctionEvaluationException; gernotbelger@8915: import org.apache.commons.math.analysis.UnivariateRealFunction; gernotbelger@8915: import org.dive4elements.river.artifacts.model.QKms; gernotbelger@8915: import org.dive4elements.river.artifacts.model.WKms; gernotbelger@8915: import org.dive4elements.river.artifacts.model.WQKms; gernotbelger@8915: import org.dive4elements.river.utils.DoubleUtil; gernotbelger@8915: gernotbelger@8931: import gnu.trove.TDoubleDoubleHashMap; gernotbelger@8931: gernotbelger@8915: /** gernotbelger@8915: * @author Gernot Belger gernotbelger@8915: */ gernotbelger@8915: public final class DischargeValuesFinder { gernotbelger@8915: gernotbelger@8915: private final UnivariateRealFunction qInterpolator; gernotbelger@8931: gernotbelger@8931: private final TDoubleDoubleHashMap exactValues; gernotbelger@8931: gernotbelger@8915: private final QKms qKms; gernotbelger@8915: gernotbelger@8915: /** gernotbelger@8915: * Create an instance from a {@link WKms} object. If the given {@link WKms} is not a {@link WQKms}, a finder that always gernotbelger@8915: * returns {@link Double#NaN} is returned. gernotbelger@8915: */ gernotbelger@8915: public static DischargeValuesFinder fromKms(final WKms wstKms) { gernotbelger@8915: if (!(wstKms instanceof QKms)) { gernotbelger@8915: return new DischargeValuesFinder(null); gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: final QKms qKms = (QKms) wstKms; gernotbelger@8915: gernotbelger@8915: return new DischargeValuesFinder(qKms); gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: public DischargeValuesFinder(final QKms qKms) { gernotbelger@8915: this.qKms = qKms; gernotbelger@8931: gernotbelger@8946: if (qKms == null) { gernotbelger@8946: this.qInterpolator = null; gernotbelger@8946: this.exactValues = null; gernotbelger@8946: } else { gernotbelger@8946: this.qInterpolator = DoubleUtil.getLinearInterpolator(qKms.allKms(), qKms.allQs()); gernotbelger@8946: gernotbelger@8946: this.exactValues = new TDoubleDoubleHashMap(qKms.size()); gernotbelger@8946: gernotbelger@8946: for (int i = 0; i < qKms.size(); i++) { gernotbelger@8946: final double station = qKms.getKm(i); gernotbelger@8946: final double discharge = qKms.getQ(i); gernotbelger@8946: this.exactValues.put(station, discharge); gernotbelger@8946: } gernotbelger@8931: } gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: /** gernotbelger@8915: * If this provider may return valid data at all. gernotbelger@8915: */ gernotbelger@8915: public boolean isValid() { gernotbelger@8915: return this.qInterpolator != null; gernotbelger@8915: } gernotbelger@8915: gernotbelger@8915: public DoubleRange getRange() { gernotbelger@8915: return new DoubleRange(this.qKms.allQs().min(), this.qKms.allQs().max()); gernotbelger@8915: } gernotbelger@8915: gernotbelger@8946: public double getDischarge(final double station) { gernotbelger@8931: gernotbelger@8946: try { gernotbelger@8946: // IMPORTANT: we first try to retrieve the exact value if it is present, to avoid rounding changes due to interpolation. gernotbelger@8946: // This is important because in the WaterlevelExporter code, these values are double-compared (with '==' ...) in order gernotbelger@8946: // to find the corresponding main-value. gernotbelger@8946: if (this.exactValues != null && this.exactValues.contains(station)) gernotbelger@8946: return this.exactValues.get(station); gernotbelger@8931: gernotbelger@8946: if (this.qInterpolator == null) gernotbelger@8946: return Double.NaN; gernotbelger@8946: gernotbelger@8946: return this.qInterpolator.value(station); gernotbelger@8946: } gernotbelger@8946: catch (final FunctionEvaluationException e) { gernotbelger@8946: e.printStackTrace(); gernotbelger@8946: return Double.NaN; gernotbelger@8946: } gernotbelger@8915: } gernotbelger@8915: }