view artifacts/src/main/java/org/dive4elements/river/artifacts/access/RangeAccess.java @ 9099:850ce16034e9

2.3.4.1.10 Berechnung mit Start-km > End-km
author gernotbelger
date Mon, 28 May 2018 13:22:45 +0200
parents 611a523fc42f
children 8cc192731c7d
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
 * Software engineering by Intevation GmbH
 *
 * 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.access;

import org.apache.commons.lang.math.DoubleRange;
import org.apache.log4j.Logger;
import org.dive4elements.river.artifacts.D4EArtifact;
import org.dive4elements.river.artifacts.WINFOArtifact;
import org.dive4elements.river.utils.DoubleUtil;
import org.dive4elements.river.utils.RiverUtils;

import gnu.trove.TDoubleArrayList;

/** For the moment, light-weight wrapper around RiverUtils. */
// TODO employ 'Caching' like other Accesses, remove usage of RiverUtils.
public class RangeAccess extends RiverAccess {
    private static Logger log = Logger.getLogger(RangeAccess.class);

    public static enum KM_MODE {
        RANGE, LOCATIONS, NONE
    };

    /** The default step width between the start end end kilometer. */
    public static final double DEFAULT_KM_STEPS = 0.1;

    double[] kmRange;

    Double from;

    Double to;

    Double step;

    private KM_MODE mode;

    public RangeAccess() {
    }

    public RangeAccess(final D4EArtifact artifact) {
        super(artifact);
    }

    /** Evaluate the ld_mode data of artifact. */
    public KM_MODE getKmRangeMode() {
        if (this.mode != null) {
            return this.mode;
        }
        final String modeData = getString("ld_mode");

        if (modeData == null || modeData.length() == 0) {
            this.mode = KM_MODE.NONE;
        } else if (modeData.equals("distance")) {
            this.mode = KM_MODE.RANGE;
        } else if (modeData.equals("locations")) {
            this.mode = KM_MODE.LOCATIONS;
        } else {
            this.mode = KM_MODE.NONE;
        }

        return this.mode;
    }

    public final DoubleRange getRange() {
        final double from = getFrom();
        final double to = getTo();
        return new DoubleRange(from, to);
    }

    /** Check if the calculation mode is Range. */
    public boolean isRange() {
        return getKmRangeMode() == KM_MODE.RANGE;
    }

    /**
     * Return sorted array of locations at which stuff was calculated
     * (from ld_locations data), null if not parameterized this way.
     */
    public double[] getLocations() {
        final String locationStr = getString("ld_locations");

        if (locationStr == null || locationStr.length() == 0) {
            if (getArtifact() instanceof WINFOArtifact) {
                final WINFOArtifact winfo = (WINFOArtifact) getArtifact();
                if (winfo.getReferenceStartKm() != null && winfo.getReferenceEndKms() != null) {
                    return new double[] { winfo.getReferenceStartKm().doubleValue(), winfo.getReferenceEndKms()[0] };
                } else if (winfo.getReferenceStartKm() != null) {
                    return new double[] { winfo.getReferenceStartKm().doubleValue(), winfo.getReferenceStartKm().doubleValue() };
                }
            }
            return null;
        }

        final String[] tmp = locationStr.split(" ");
        final TDoubleArrayList locations = new TDoubleArrayList();

        for (final String l : tmp) {
            try {
                locations.add(Double.parseDouble(l));
            }
            catch (final NumberFormatException nfe) {
                log.debug(nfe.getLocalizedMessage(), nfe);
            }
        }

        locations.sort();

        return locations.toNativeArray();
    }

    public boolean hasFrom() {
        return this.from != null || (this.from = getDouble("ld_from")) != null;
    }

    public boolean hasTo() {
        return this.to != null || (this.to = getDouble("ld_to")) != null;
    }

    /*
     * If left_to_right is set to true this returns
     * the smaller value of from and to.
     */
    public double getFrom(final boolean left_to_right) {
        if (!left_to_right) {
            return getFrom();
        }
        final double from = getFrom();
        final double to = getTo();
        return from > to ? to : from;
    }

    /** Return ld_from data (in km). If not found, the min. */
    public double getFrom() {
        if (this.from == null) {
            this.from = getDouble("ld_from");
        }

        if (log.isDebugEnabled()) {
            log.debug("from from data: '" + this.from + "'");
        }

        if (this.from == null) {
            log.warn("No 'from' found. Assume min of river.");
            return getRiver().determineMinMaxDistance()[0];
        }

        return this.from.doubleValue();
    }

    /*
     * If left_to_right is set to true this returns
     * the larger value of from and to.
     */
    public double getTo(final boolean left_to_right) {
        if (!left_to_right) {
            return getTo();
        }
        final double from = getFrom();
        final double to = getTo();
        return from > to ? from : to;
    }

    /** Return ld_to data (in km), if not found, the max. */
    public double getTo() {
        if (this.to == null) {
            this.to = getDouble("ld_to");
        }

        if (log.isDebugEnabled()) {
            log.debug("to from data: '" + this.to + "'");
        }

        if (this.to == null) {
            log.warn("No 'to' found. Assume max of river.");
            return getRiver().determineMinMaxDistance()[1];
        }

        return this.to.doubleValue();
    }

    /** Step width for calculation. */
    public Double getStep() {

        if (this.step == null) {
            this.step = getDouble("ld_step");
        }

        if (log.isDebugEnabled()) {
            log.debug("step: '" + this.step + "'");
        }

        return this.step;
    }

    /**
     * Get min and max kilometer, independent of parametization
     * (ld_from/to vs ld_locations).
     */
    public double[] getKmRange() {
        // TODO store kmRange in field.
        switch (getKmRangeMode()) {
        case RANGE: {
            return getKmFromTo();
        }

        case LOCATIONS: {
            final double[] locs = getLocations();
            // if no locations, nPE.
            if (locs == null) {
                log.warn("no locations to get km range from.");
                return new double[] { Double.NaN, Double.NaN };
            }
            return new double[] { locs[0], locs[locs.length - 1] };
        }

        case NONE: {
            final double[] locs = getLocations();
            if (locs != null) {
                return new double[] { locs[0], locs[locs.length - 1] };
            } else {
                return getKmFromTo();
            }
        }
        }

        return new double[] { Double.NaN, Double.NaN };
    }

    public double[] getKmFromTo() {
        return RiverUtils.getKmFromTo(this.getArtifact());
    }

    /**
     * Returns the selected Kms in steps as specified.
     *
     * @return Each step for this range.
     */
    public double[] getKmSteps() {
        double step = getStep();

        // transform step from 'm' into 'km'
        step = step / 1000;

        if (step == 0d) {
            step = DEFAULT_KM_STEPS;
        }

        return DoubleUtil.explode(getFrom(), getTo(), step);
    }

    public final double getLowerKm() {
        return Math.min(this.getFrom(), this.getTo());
    }

    public final double getUpperKm() {
        return Math.max(this.getFrom(), this.getTo());
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org