teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.artifacts.access; felix@4647: gernotbelger@9070: import org.apache.commons.lang.math.DoubleRange; felix@4647: import org.apache.log4j.Logger; teichmann@5867: import org.dive4elements.river.artifacts.D4EArtifact; teichmann@5831: import org.dive4elements.river.artifacts.WINFOArtifact; gernotbelger@9070: import org.dive4elements.river.utils.DoubleUtil; teichmann@5865: import org.dive4elements.river.utils.RiverUtils; felix@4647: gernotbelger@9070: import gnu.trove.TDoubleArrayList; felix@4850: teichmann@5865: /** For the moment, light-weight wrapper around RiverUtils. */ teichmann@5865: // TODO employ 'Caching' like other Accesses, remove usage of RiverUtils. gernotbelger@9070: public class RangeAccess extends RiverAccess { teichmann@8202: private static Logger log = Logger.getLogger(RangeAccess.class); felix@4647: gernotbelger@9070: public static enum KM_MODE { gernotbelger@9070: RANGE, LOCATIONS, NONE gernotbelger@9070: }; felix@4852: andre@8562: /** The default step width between the start end end kilometer. */ andre@8562: public static final double DEFAULT_KM_STEPS = 0.1; andre@8562: felix@4852: double[] kmRange; felix@4852: felix@4824: Double from; felix@4824: felix@4824: Double to; felix@4824: felix@4825: Double step; felix@4825: felix@4852: private KM_MODE mode; felix@4852: teichmann@7055: public RangeAccess() { teichmann@7055: } felix@4647: gernotbelger@9070: public RangeAccess(final D4EArtifact artifact) { felix@4647: super(artifact); felix@4647: } felix@4647: felix@4852: /** Evaluate the ld_mode data of artifact. */ felix@4852: public KM_MODE getKmRangeMode() { gernotbelger@9070: if (this.mode != null) { gernotbelger@9070: return this.mode; felix@4852: } gernotbelger@9070: final String modeData = getString("ld_mode"); felix@4852: felix@4852: if (modeData == null || modeData.length() == 0) { gernotbelger@9070: this.mode = KM_MODE.NONE; gernotbelger@9070: } else if (modeData.equals("distance")) { gernotbelger@9070: this.mode = KM_MODE.RANGE; gernotbelger@9070: } else if (modeData.equals("locations")) { gernotbelger@9070: this.mode = KM_MODE.LOCATIONS; gernotbelger@9070: } else { gernotbelger@9070: this.mode = KM_MODE.NONE; felix@4852: } teichmann@5282: gernotbelger@9070: return this.mode; gernotbelger@9070: } gernotbelger@9070: gernotbelger@9070: public final DoubleRange getRange() { gernotbelger@9070: final double from = getFrom(); gernotbelger@9070: final double to = getTo(); gernotbelger@9070: return new DoubleRange(from, to); felix@4852: } felix@4852: andre@8755: /** Check if the calculation mode is Range. */ andre@8755: public boolean isRange() { andre@8755: return getKmRangeMode() == KM_MODE.RANGE; andre@8755: } andre@8755: felix@4850: /** felix@4850: * Return sorted array of locations at which stuff was calculated felix@4850: * (from ld_locations data), null if not parameterized this way. felix@4850: */ felix@4850: public double[] getLocations() { gernotbelger@9070: final String locationStr = getString("ld_locations"); felix@4850: felix@4850: if (locationStr == null || locationStr.length() == 0) { felix@4850: if (getArtifact() instanceof WINFOArtifact) { gernotbelger@9070: final WINFOArtifact winfo = (WINFOArtifact) getArtifact(); gernotbelger@9070: if (winfo.getReferenceStartKm() != null && winfo.getReferenceEndKms() != null) { gernotbelger@9070: return new double[] { winfo.getReferenceStartKm().doubleValue(), winfo.getReferenceEndKms()[0] }; gernotbelger@9070: } else if (winfo.getReferenceStartKm() != null) { gernotbelger@9070: return new double[] { winfo.getReferenceStartKm().doubleValue(), winfo.getReferenceStartKm().doubleValue() }; felix@5665: } felix@4850: } felix@4850: return null; felix@4850: } felix@4850: gernotbelger@9070: final String[] tmp = locationStr.split(" "); gernotbelger@9070: final TDoubleArrayList locations = new TDoubleArrayList(); felix@4850: gernotbelger@9070: for (final String l : tmp) { felix@4850: try { felix@4850: locations.add(Double.parseDouble(l)); felix@4850: } gernotbelger@9070: catch (final NumberFormatException nfe) { teichmann@8202: log.debug(nfe.getLocalizedMessage(), nfe); felix@4850: } felix@4850: } felix@4850: felix@4850: locations.sort(); felix@4850: felix@4850: return locations.toNativeArray(); felix@4850: } felix@4850: teichmann@6988: public boolean hasFrom() { gernotbelger@9070: return this.from != null || (this.from = getDouble("ld_from")) != null; teichmann@6988: } teichmann@6988: teichmann@6988: public boolean hasTo() { gernotbelger@9070: return this.to != null || (this.to = getDouble("ld_to")) != null; teichmann@6988: } teichmann@6988: gernotbelger@9070: /* gernotbelger@9070: * If left_to_right is set to true this returns gernotbelger@9070: * the smaller value of from and to. gernotbelger@9070: */ gernotbelger@9070: public double getFrom(final boolean left_to_right) { andre@8646: if (!left_to_right) { andre@8646: return getFrom(); andre@8646: } gernotbelger@9070: final double from = getFrom(); gernotbelger@9070: final double to = getTo(); andre@8646: return from > to ? to : from; andre@8646: } felix@4850: felix@7262: /** Return ld_from data (in km). If not found, the min. */ felix@4824: public double getFrom() { gernotbelger@9070: if (this.from == null) { gernotbelger@9070: this.from = getDouble("ld_from"); felix@4824: } felix@4824: teichmann@8202: if (log.isDebugEnabled()) { gernotbelger@9070: log.debug("from from data: '" + this.from + "'"); felix@7262: } felix@7262: gernotbelger@9070: if (this.from == null) { tom@8310: log.warn("No 'from' found. Assume min of river."); felix@7262: return getRiver().determineMinMaxDistance()[0]; felix@4827: } felix@4827: gernotbelger@9070: return this.from.doubleValue(); felix@4824: } felix@4824: gernotbelger@9070: /* gernotbelger@9070: * If left_to_right is set to true this returns gernotbelger@9070: * the larger value of from and to. gernotbelger@9070: */ gernotbelger@9070: public double getTo(final boolean left_to_right) { andre@8646: if (!left_to_right) { andre@8646: return getTo(); andre@8646: } gernotbelger@9070: final double from = getFrom(); gernotbelger@9070: final double to = getTo(); andre@8646: return from > to ? from : to; andre@8646: } felix@4824: felix@7262: /** Return ld_to data (in km), if not found, the max. */ felix@4824: public double getTo() { gernotbelger@9070: if (this.to == null) { gernotbelger@9070: this.to = getDouble("ld_to"); felix@4824: } felix@4827: teichmann@8202: if (log.isDebugEnabled()) { gernotbelger@9070: log.debug("to from data: '" + this.to + "'"); felix@7262: } felix@7262: gernotbelger@9070: if (this.to == null) { tom@8310: log.warn("No 'to' found. Assume max of river."); felix@7262: return getRiver().determineMinMaxDistance()[1]; felix@4827: } felix@4827: gernotbelger@9070: return this.to.doubleValue(); felix@4824: } felix@4824: felix@4825: /** Step width for calculation. */ felix@4825: public Double getStep() { felix@4825: gernotbelger@9070: if (this.step == null) { gernotbelger@9070: this.step = getDouble("ld_step"); felix@4825: } felix@4825: teichmann@8202: if (log.isDebugEnabled()) { gernotbelger@9070: log.debug("step: '" + this.step + "'"); felix@4825: } felix@4825: gernotbelger@9070: return this.step; felix@4825: } felix@4825: felix@4647: /** felix@4647: * Get min and max kilometer, independent of parametization felix@4647: * (ld_from/to vs ld_locations). felix@4647: */ felix@4647: public double[] getKmRange() { felix@4853: // TODO store kmRange in field. felix@4853: switch (getKmRangeMode()) { gernotbelger@9070: case RANGE: { gernotbelger@9070: return getKmFromTo(); gernotbelger@9070: } gernotbelger@9070: gernotbelger@9070: case LOCATIONS: { gernotbelger@9070: final double[] locs = getLocations(); gernotbelger@9070: // if no locations, nPE. gernotbelger@9070: if (locs == null) { gernotbelger@9070: log.warn("no locations to get km range from."); gernotbelger@9070: return new double[] { Double.NaN, Double.NaN }; gernotbelger@9070: } gernotbelger@9070: return new double[] { locs[0], locs[locs.length - 1] }; gernotbelger@9070: } gernotbelger@9070: gernotbelger@9070: case NONE: { gernotbelger@9070: final double[] locs = getLocations(); gernotbelger@9070: if (locs != null) { gernotbelger@9070: return new double[] { locs[0], locs[locs.length - 1] }; gernotbelger@9070: } else { felix@4853: return getKmFromTo(); felix@4853: } gernotbelger@9070: } felix@4853: } felix@4853: felix@4853: return new double[] { Double.NaN, Double.NaN }; felix@4647: } felix@4647: felix@4647: public double[] getKmFromTo() { gernotbelger@9070: return RiverUtils.getKmFromTo(this.getArtifact()); felix@4647: } andre@8562: andre@8562: /** andre@8562: * Returns the selected Kms in steps as specified. andre@8562: * andre@8562: * @return Each step for this range. andre@8562: */ andre@8562: public double[] getKmSteps() { andre@8562: double step = getStep(); andre@8562: andre@8562: // transform step from 'm' into 'km' andre@8562: step = step / 1000; andre@8562: andre@8562: if (step == 0d) { andre@8562: step = DEFAULT_KM_STEPS; andre@8562: } andre@8562: andre@8562: return DoubleUtil.explode(getFrom(), getTo(), step); andre@8562: } felix@4647: } felix@4647: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :