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 :