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.minfo; rrenkert@4521: rrenkert@4521: import java.util.ArrayList; rrenkert@4521: import java.util.Collections; rrenkert@4521: import java.util.HashMap; rrenkert@4521: import java.util.List; rrenkert@4521: import java.util.Map; rrenkert@4521: import java.util.Set; rrenkert@4521: rrenkert@4521: import org.apache.log4j.Logger; rrenkert@4521: rrenkert@4521: rrenkert@4521: public class SedimentDensity rrenkert@4521: { rrenkert@4521: private static final Logger logger = Logger rrenkert@4521: .getLogger(SedimentDensity.class); rrenkert@4521: rrenkert@4521: private Map> densities; rrenkert@4521: private List years; rrenkert@4521: rrenkert@4521: public SedimentDensity() { rrenkert@4521: this.densities = new HashMap>(); rrenkert@4521: this.years = new ArrayList(); rrenkert@4521: } rrenkert@4521: rrenkert@4521: public Map> getDensities() { rrenkert@4521: return densities; rrenkert@4521: } rrenkert@4521: rrenkert@4521: public void setDensities(Map> densities) { rrenkert@4521: this.densities = densities; rrenkert@4521: } rrenkert@4521: rrenkert@4521: public void addDensity(double km, double density, int year) { rrenkert@4521: logger.debug("adding " + year); rrenkert@4521: if (this.densities.containsKey(year)) { rrenkert@4521: List list = this.densities.get(year); rrenkert@4521: list.add(new SedimentDensityValue(km, density, year)); rrenkert@4521: } rrenkert@4521: else { rrenkert@4521: List list = rrenkert@4521: new ArrayList(); rrenkert@4521: list.add(new SedimentDensityValue(km, density, year)); rrenkert@4521: densities.put(year, list); rrenkert@4521: } rrenkert@4521: if (!this.years.contains(new Integer(year))) { rrenkert@4521: logger.debug("new year"); rrenkert@4521: years.add(new Integer(year)); rrenkert@4521: } rrenkert@4521: } rrenkert@4521: rrenkert@4521: public List getYears() { rrenkert@4521: return years; rrenkert@4521: } rrenkert@4521: rrenkert@4521: public void setYears(List years) { rrenkert@4521: this.years = years; rrenkert@4521: } rrenkert@4521: felix@6937: /** felix@6937: * Get the density at year. felix@6937: * measured densities are valid until the next measurement. felix@6937: * if no measurement was found 1.8 is returned. felix@6937: */ rrenkert@4521: public double getDensity(double km, int year) { rrenkert@4521: Collections.sort(this.years); felix@6937: if (this.years.size() == 1 && years.get(0) <= year) { tom@6910: logger.debug("get density from year " + year + " at km " + km); felix@6937: return getDensityAtKm(densities.get(years.get(0)), km); rrenkert@4521: } felix@6937: else if (this.years.size() > 1) { rrenkert@4521: for (int i = 0; i < years.size() -1; i++) { rrenkert@4521: int y1 = years.get(i); rrenkert@4521: int y2 = years.get(i + 1); felix@6938: if (year >= y1 && year < y2) { rrenkert@4521: return getDensityAtKm(densities.get(y1), km); rrenkert@4521: } felix@6938: else if (year >= y2 && i == years.size() -1) { rrenkert@4521: return getDensityAtKm(densities.get(y2), km); rrenkert@4521: } rrenkert@4521: } rrenkert@4521: } rrenkert@5712: return 1.8d; rrenkert@4521: } rrenkert@4521: rrenkert@4521: private double getDensityAtKm( rrenkert@4521: List values, rrenkert@4521: double km rrenkert@4521: ) { felix@6758: boolean found = false; rrenkert@4521: SedimentDensityValue prev = null; rrenkert@4521: SedimentDensityValue next = null; rrenkert@4521: for (SedimentDensityValue sdv: values) { tom@6910: logger.debug("year: " + sdv.getYear()); rrenkert@4521: if (sdv.getKm() == km) { rrenkert@4521: prev = sdv; rrenkert@4521: found = true; rrenkert@4521: break; rrenkert@4521: } rrenkert@4521: if (sdv.getKm() > km) { rrenkert@4521: next = sdv; rrenkert@4521: break; rrenkert@4521: } rrenkert@4521: prev = sdv; rrenkert@4521: } rrenkert@4521: if (found) { rrenkert@4521: return prev.getDensity(); rrenkert@4521: } rrenkert@4521: else { rrenkert@4521: return spline(prev, next, km); rrenkert@4521: } rrenkert@4521: } rrenkert@4521: rrenkert@4521: private double spline( rrenkert@4521: SedimentDensityValue prev, rrenkert@4521: SedimentDensityValue next, rrenkert@4521: double km rrenkert@4521: ) { rrenkert@4521: double lower = prev.getKm(); rrenkert@4521: double upper = next.getKm(); rrenkert@4521: double upperDensity = next.getDensity(); rrenkert@4521: double lowerDensity = prev.getDensity(); rrenkert@4521: rrenkert@4521: double m =(upperDensity - lowerDensity)/(upper - lower) * km; rrenkert@4521: double b = lowerDensity - rrenkert@4521: ((upperDensity - lowerDensity)/(upper - lower) * lower); rrenkert@4521: return (m * km) + b; rrenkert@4521: } rrenkert@4521: rrenkert@4521: public void cleanUp() { rrenkert@4521: Set keys = densities.keySet(); rrenkert@4521: for (Integer key : keys) { rrenkert@4521: List list = densities.get(key); rrenkert@4521: if (list.size() == 0) { rrenkert@4521: return; rrenkert@4521: } rrenkert@4521: List cleaned = rrenkert@4521: new ArrayList(); rrenkert@4521: double prevkm = list.get(0).getKm(); rrenkert@4521: int counter = 0; rrenkert@4521: double sum = 0d; rrenkert@4521: for (SedimentDensityValue value : list) { rrenkert@4521: if (value.getKm() == prevkm) { rrenkert@4521: sum += value.getDensity(); rrenkert@4521: counter++; rrenkert@4521: } rrenkert@4521: else { rrenkert@4521: cleaned.add(new SedimentDensityValue( rrenkert@4521: prevkm, rrenkert@4521: sum / counter, rrenkert@4521: value.getYear())); rrenkert@4521: sum = value.getDensity(); rrenkert@4521: counter = 1; rrenkert@4521: } rrenkert@4521: prevkm = value.getKm(); rrenkert@4521: } rrenkert@4521: this.densities.put(key, cleaned); rrenkert@4521: } rrenkert@4521: } rrenkert@4521: }