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; ingo@385: teichmann@7494: import java.util.ArrayList; teichmann@7494: import java.util.Collections; teichmann@7494: import java.util.Comparator; teichmann@7494: teichmann@7494: import org.dive4elements.river.artifacts.math.Linear; teichmann@7494: ingo@385: import gnu.trove.TIntArrayList; ingo@385: ingo@385: /** ingo@385: * This class represents a pool of data triples that consists of 'W', 'Q' and ingo@385: * 'Day' data. ingo@385: * ingo@385: * @author Ingo Weinzierl ingo@385: */ sascha@727: public class WQDay sascha@727: extends WQ sascha@727: { teichmann@7494: public static final Comparator FIRST_CMP = new Comparator() { teichmann@7494: @Override teichmann@7494: public int compare(double [] a, double [] b) { teichmann@7494: double diff = a[0] - b[0]; teichmann@7494: if (diff < 0d) return -1; teichmann@7494: if (diff > 0d) return +1; teichmann@7494: return 0; teichmann@7494: } teichmann@7494: }; teichmann@7494: teichmann@7494: public static final double EPSILON = 1e-4; teichmann@7494: teichmann@7494: ingo@385: protected TIntArrayList days; ingo@385: ingo@385: public WQDay() { sascha@727: super(""); ingo@385: days = new TIntArrayList(); ingo@385: } ingo@385: ingo@385: public WQDay(int capacity) { sascha@2182: super(capacity); ingo@385: days = new TIntArrayList(capacity); ingo@385: } ingo@385: ingo@686: public WQDay(int [] days, double [] ws, double [] qs) { sascha@727: super(qs, ws, ""); ingo@686: this.days = new TIntArrayList(days); ingo@686: } ingo@686: ingo@385: ingo@385: public void add(int day, double w, double q) { sascha@727: super.add(w, q); ingo@385: days.add(day); ingo@385: } ingo@385: ingo@1689: ingo@1689: public boolean isIncreasing() { teichmann@7484: return size() == 0 || getDay(0) < getDay(size()-1); ingo@1689: } ingo@1689: ingo@1689: ingo@385: public int getDay(int idx) { ingo@686: return days.getQuick(idx); ingo@385: } ingo@385: teichmann@7494: private static final Double interpolateX(ArrayList dxs, double x) { teichmann@7494: teichmann@7494: Collections.sort(dxs, FIRST_CMP); teichmann@7494: teichmann@7494: if (Math.abs(x - dxs.get(0)[1]) < EPSILON) { teichmann@7494: return dxs.get(0)[0]; teichmann@7494: } teichmann@7494: teichmann@7494: for (int i = 1, S = dxs.size(); i < S; ++i) { teichmann@7494: double [] curr = dxs.get(i); teichmann@7494: if (Math.abs(x - curr[1]) < EPSILON) { teichmann@7494: return curr[0]; teichmann@7494: } teichmann@7494: teichmann@7494: double [] prev = dxs.get(i-1); teichmann@7494: double x1 = Math.min(prev[1], curr[1]); teichmann@7494: double x2 = Math.max(prev[1], curr[1]); teichmann@7494: if (x > x1 && x < x2) { teichmann@7494: return Linear.linear( teichmann@7494: x, teichmann@7494: prev[1], curr[1], teichmann@7494: prev[0], curr[0]); teichmann@7494: } teichmann@7494: } teichmann@7494: teichmann@7494: return null; teichmann@7494: } teichmann@7494: teichmann@7494: public Double interpolateDayByW(double w) { teichmann@7494: teichmann@7494: int S = days.size(); teichmann@7494: teichmann@7494: if (S == 0) { teichmann@7494: return null; teichmann@7494: } teichmann@7494: teichmann@7494: ArrayList dws = new ArrayList(S); teichmann@7494: teichmann@7494: for (int i = 0; i < S; ++i) { teichmann@7494: dws.add(new double[] { getDay(i), getW(i) }); teichmann@7494: } teichmann@7494: teichmann@7494: return interpolateX(dws, w); teichmann@7494: } teichmann@7494: teichmann@7494: public Double interpolateDayByQ(double q) { teichmann@7494: teichmann@7494: int S = days.size(); teichmann@7494: teichmann@7494: if (S == 0) { teichmann@7494: return null; teichmann@7494: } teichmann@7494: teichmann@7494: ArrayList dqs = new ArrayList(S); teichmann@7494: teichmann@7494: for (int i = 0; i < S; ++i) { teichmann@7494: dqs.add(new double[] { getDay(i), getQ(i) }); teichmann@7494: } teichmann@7494: teichmann@7494: return interpolateX(dqs, q); teichmann@7494: } teichmann@7494: sascha@727: @Override ingo@686: public void removeNaNs() { ingo@686: ingo@686: int dest = 0; sascha@2182: int N = ws.size(); ingo@686: ingo@686: for (int i = 0; i < N; ++i) { sascha@2182: double wi = ws.getQuick(i); sascha@2182: double qi = qs.getQuick(i); ingo@686: sascha@727: if (Double.isNaN(wi) || Double.isNaN(qi)) { ingo@686: continue; ingo@686: } ingo@686: ingo@686: days.setQuick(dest, days.getQuick(i)); sascha@2182: ws.setQuick(dest, wi); sascha@2182: qs.setQuick(dest, qi); ingo@686: ++dest; ingo@686: } ingo@686: ingo@686: if (dest < N) { ingo@686: days.remove(dest, N-dest); sascha@2182: ws .remove(dest, N-dest); sascha@2182: qs .remove(dest, N-dest); ingo@686: } ingo@385: } ingo@385: } ingo@385: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :