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.model; sascha@650: teichmann@5831: import org.dive4elements.river.model.DischargeTable; teichmann@5831: import org.dive4elements.river.model.Gauge; teichmann@5831: import org.dive4elements.river.model.River; sascha@3441: teichmann@5831: import org.dive4elements.river.utils.DoubleUtil; sascha@3419: sascha@650: import java.io.Serializable; sascha@650: sascha@3419: import java.util.ArrayList; sascha@3441: import java.util.Collections; sascha@3439: import java.util.Comparator; sascha@3419: import java.util.List; sascha@650: sascha@3419: import org.apache.log4j.Logger; sascha@655: felix@5150: /** A Range with values and a reference point. */ sascha@650: public class Segment sascha@650: implements Serializable sascha@650: { sascha@3441: private static Logger log = Logger.getLogger(Segment.class); sascha@650: sascha@3439: public static final Comparator REF_CMP = sascha@3439: new Comparator() { sascha@3439: @Override sascha@3439: public int compare(Segment a, Segment b) { sascha@3439: double d = a.referencePoint - b.referencePoint; sascha@3439: if (d < 0d) return -1; sascha@3439: return d > 0d ? +1 : 0; sascha@3439: } sascha@3439: }; sascha@3439: sascha@650: protected double from; sascha@650: protected double to; sascha@650: protected double [] values; sascha@655: protected double [] backup; sascha@655: protected double referencePoint; sascha@650: sascha@650: public Segment() { sascha@650: } sascha@650: sascha@655: public Segment(double referencePoint) { sascha@655: this.referencePoint = referencePoint; sascha@655: } sascha@655: sascha@650: public Segment(double from, double to, double [] values) { sascha@650: this.from = from; sascha@650: this.to = to; sascha@650: this.values = values; sascha@650: } sascha@650: sascha@650: public boolean isUp() { sascha@650: return from < to; sascha@650: } sascha@650: felix@5107: /** Checks whether given km lies inside the to/from bounds of this segment. */ sascha@3449: public boolean inside(double km) { sascha@3552: return from < to sascha@3449: ? km >= from && km <= to sascha@3449: : km >= to && km <= from; sascha@3449: } sascha@3449: sascha@3419: @Override sascha@650: public String toString() { sascha@650: StringBuilder sb = new StringBuilder("Segment: ["); sascha@650: sb.append("from: ").append(from).append("; to: ") sascha@670: .append(to) sascha@670: .append("; ref: ").append(referencePoint) sascha@670: .append("; values: ("); sascha@650: for (int i = 0; i < values.length; ++i) { sascha@650: if (i > 0) sb.append(", "); sascha@650: sb.append(values[i]); sascha@650: } sascha@650: sb.append(")]"); sascha@650: return sb.toString(); sascha@650: } sascha@650: sascha@655: public void setFrom(double from) { sascha@655: this.from = from; sascha@655: } sascha@655: sascha@655: public void backup() { sascha@3419: backup = values != null sascha@3419: ? (double [])values.clone() sascha@3419: : null; sascha@655: } sascha@655: sascha@3449: public double [] getBackup() { sascha@3449: return backup; sascha@3449: } sascha@3449: sascha@655: public double getFrom() { sascha@655: return from; sascha@655: } sascha@655: sascha@655: public void setTo(double to) { sascha@655: this.to = to; sascha@655: } sascha@655: sascha@655: public double getTo() { sascha@655: return to; sascha@655: } sascha@655: sascha@655: public void setValues(double [] values) { sascha@655: this.values = values; sascha@655: } sascha@655: sascha@655: public double [] getValues() { sascha@655: return values; sascha@655: } sascha@655: sascha@3449: public int numValues() { sascha@3449: return values.length; sascha@3449: } sascha@3449: sascha@655: public void setReferencePoint(double referencePoint) { sascha@655: this.referencePoint = referencePoint; sascha@655: } sascha@655: sascha@655: public double getReferencePoint() { sascha@655: return referencePoint; sascha@655: } sascha@655: felix@5107: /** Use DoubleUtil to parse Segments. */ sascha@650: public static List parseSegments(String input) { sascha@650: sascha@3776: final List segments = new ArrayList(); sascha@650: sascha@3776: DoubleUtil.parseSegments(input, new DoubleUtil.SegmentCallback() { sascha@3776: @Override sascha@3776: public void newSegment(double from, double to, double [] values) { sascha@650: segments.add(new Segment(from, to, values)); sascha@650: } sascha@3776: }); sascha@650: sascha@650: return segments; sascha@650: } sascha@3441: sascha@3441: public static boolean setReferencePointConvertQ( sascha@3441: List segments, sascha@3441: River river, sascha@3441: boolean isQ, sascha@3441: Calculation report sascha@3441: ) { sascha@3441: int numResults = -1; sascha@3441: sascha@3441: boolean success = true; sascha@3441: sascha@3441: // assign reference points sascha@3441: for (Segment segment: segments) { sascha@3441: Gauge gauge = river.maxOverlap(segment.getFrom(), segment.getTo()); sascha@3441: sascha@3441: if (gauge == null) { sascha@3441: log.warn("no gauge found. Defaults to mid point."); sascha@3441: segment.setReferencePoint( sascha@3441: 0.5*(segment.getFrom()+segment.getTo())); sascha@3441: } sascha@3441: else { sascha@3441: double ref = gauge.getStation().doubleValue(); sascha@3441: log.debug( sascha@3441: "reference gauge: " + gauge.getName() + sascha@3441: " (km " + ref + ")"); sascha@3441: segment.setReferencePoint(ref); sascha@3441: } sascha@3441: sascha@3441: double [] values = segment.values; sascha@3441: sascha@3441: if (numResults == -1) { sascha@3441: numResults = values.length; sascha@3441: } sascha@3441: else if (numResults != values.length) { sascha@3441: log.warn("wrong length of values"); sascha@3441: return false; sascha@3441: } sascha@3441: sascha@3441: // convert to Q if needed sascha@3441: if (!isQ && gauge != null) { sascha@3441: sascha@3441: DischargeTable dt = gauge.fetchMasterDischargeTable(); sascha@3441: sascha@3441: double [][] table = aheinecke@6301: DischargeTables.loadDischargeTableValues(dt); sascha@3441: sascha@3441: // need the original values for naming sascha@3441: segment.backup(); sascha@3441: sascha@3441: for (int i = 0; i < values.length; ++i) { aheinecke@6301: double w = values[i] * 100.0; sascha@3441: double [] qs = DischargeTables.getQsForW(table, w); sascha@3441: if (qs.length == 0) { sascha@3441: log.warn("No Qs found for W = " + values[i]); rrenkert@5117: report.addProblem("cannot.find.q.for.w", values[i]); sascha@3441: values[i] = Double.NaN; sascha@3441: success = false; sascha@3441: } sascha@3441: else { sascha@3441: values[i] = qs[0]; sascha@3441: if (qs.length > 1) { sascha@3441: log.warn( sascha@3441: "More than one Q found for W = " + values[i]); sascha@3441: } sascha@3441: } sascha@3441: } sascha@3441: } sascha@3441: } // for all segments sascha@3441: sascha@3441: Collections.sort(segments, Segment.REF_CMP); sascha@3441: sascha@3441: return success; sascha@3441: } sascha@650: } sascha@650: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :