view artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhcalculation/DischargeValuesFinder.java @ 8931:b10f8415798c

Trying to avoid symptoms of == double comparison
author gernotbelger
date Tue, 06 Mar 2018 17:04:17 +0100
parents d9dbf0b74bc2
children 5d5d482da3e9
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.sinfo.tkhcalculation;

import org.apache.commons.lang.math.DoubleRange;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.dive4elements.river.artifacts.model.QKms;
import org.dive4elements.river.artifacts.model.WKms;
import org.dive4elements.river.artifacts.model.WQKms;
import org.dive4elements.river.utils.DoubleUtil;

import gnu.trove.TDoubleDoubleHashMap;

/**
 * @author Gernot Belger
 */
public final class DischargeValuesFinder {

    private final UnivariateRealFunction qInterpolator;

    private final TDoubleDoubleHashMap exactValues;

    private final QKms qKms;

    /**
     * Create an instance from a {@link WKms} object. If the given {@link WKms} is not a {@link WQKms}, a finder that always
     * returns {@link Double#NaN} is returned.
     */
    public static DischargeValuesFinder fromKms(final WKms wstKms) {
        if (!(wstKms instanceof QKms)) {
            return new DischargeValuesFinder(null);
        }

        final QKms qKms = (QKms) wstKms;

        return new DischargeValuesFinder(qKms);
    }

    public DischargeValuesFinder(final QKms qKms) {
        this.qKms = qKms;
        this.qInterpolator = qKms == null ? null : DoubleUtil.getLinearInterpolator(qKms.allKms(), qKms.allQs());

        this.exactValues = new TDoubleDoubleHashMap(qKms.size());

        for (int i = 0; i < qKms.size(); i++) {
            final double station = qKms.getKm(i);
            final double discharge = qKms.getQ(i);
            this.exactValues.put(station, discharge);
        }
    }

    /**
     * If this provider may return valid data at all.
     */
    public boolean isValid() {
        return this.qInterpolator != null;
    }

    public DoubleRange getRange() {
        return new DoubleRange(this.qKms.allQs().min(), this.qKms.allQs().max());
    }

    public double getDischarge(final double station) throws FunctionEvaluationException {

        // IMPORTANT: we first try to retreive the exact value if it is present, to avoid rounding changes due to interpolation.
        // This is important because in the WaterlevelExporter code, these values are double-compared (with '==' ...) in order
        // to find the corresponding main-value.
        if (this.exactValues.contains(station))
            return this.exactValues.get(station);

        return this.qInterpolator.value(station);
    }
}

http://dive4elements.wald.intevation.org