view artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensity.java @ 6758:67182bde34cd

issue1436: Remove wrong condition where previous value does not exist but is accessed.
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Tue, 06 Aug 2013 16:39:41 +0200
parents af13ceeba52a
children a58a1a520948
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */

package org.dive4elements.river.artifacts.model.minfo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;


public class SedimentDensity
{
    private static final Logger logger = Logger
        .getLogger(SedimentDensity.class);

    private Map<Integer, List<SedimentDensityValue>> densities;
    private List<Integer> years;

    public SedimentDensity() {
        this.densities = new HashMap<Integer, List<SedimentDensityValue>>();
        this.years = new ArrayList<Integer>();
    }

    public Map<Integer, List<SedimentDensityValue>> getDensities() {
        return densities;
    }

    public void setDensities(Map<Integer, List<SedimentDensityValue>> densities) {
        this.densities = densities;
    }

    public void addDensity(double km, double density, int year) {
        logger.debug("adding " + year);
        if (this.densities.containsKey(year)) {
            List<SedimentDensityValue> list = this.densities.get(year);
            list.add(new SedimentDensityValue(km, density, year));
        }
        else {
            List<SedimentDensityValue> list =
                new ArrayList<SedimentDensityValue>();
            list.add(new SedimentDensityValue(km, density, year));
            densities.put(year, list);
        }
        if (!this.years.contains(new Integer(year))) {
            logger.debug("new year");
            years.add(new Integer(year));
        }
    }

    public List<Integer> getYears() {
        return years;
    }

    public void setYears(List<Integer> years) {
        this.years = years;
    }

    public double getDensity(double km, int year) {
        Collections.sort(this.years);
        if (this.years.size() == 1) {
            return getDensityAtKm(densities.get(year), km);
        }
        else {
            for (int i = 0; i < years.size() -1; i++) {
                int y1 = years.get(i);
                int y2 = years.get(i + 1);
                int mid = Math.round((y1 + y2) / 2);
                if (year < mid) {
                    return getDensityAtKm(densities.get(y1), km);
                }
                else if (i == years.size() -1) {
                    continue;
                }
                else {
                    return getDensityAtKm(densities.get(y2), km);
                }
            }
        }
        return 1.8d;
    }

    private double getDensityAtKm(
        List<SedimentDensityValue> values,
        double km
    ) {
        boolean found = false;
        SedimentDensityValue prev = null;
        SedimentDensityValue next = null;
        for (SedimentDensityValue sdv: values) {
logger.debug("year: " + sdv.getYear());
            if (sdv.getKm() == km) {
                prev = sdv;
                found = true;
                break;
            }
            if (sdv.getKm() > km) {
                next = sdv;
                break;
            }
            prev = sdv;
        }
        if (found) {
            return prev.getDensity();
        }
        else {
            return spline(prev, next, km);
        }
    }

    private double spline(
        SedimentDensityValue prev,
        SedimentDensityValue next,
        double km
    ) {
        double lower = prev.getKm();
        double upper = next.getKm();
        double upperDensity = next.getDensity();
        double lowerDensity = prev.getDensity();

        double m =(upperDensity - lowerDensity)/(upper - lower) * km;
        double b = lowerDensity -
            ((upperDensity - lowerDensity)/(upper - lower) * lower);
        return (m * km) + b;
    }

    public void cleanUp() {
        Set<Integer> keys = densities.keySet();
        for (Integer key : keys) {
            List<SedimentDensityValue> list = densities.get(key);
            if (list.size() == 0) {
                return;
            }
            List<SedimentDensityValue> cleaned =
                new ArrayList<SedimentDensityValue>();
            double prevkm = list.get(0).getKm();
            int counter = 0;
            double sum = 0d;
            for (SedimentDensityValue value : list) {
                if (value.getKm() == prevkm) {
                    sum += value.getDensity();
                    counter++;
                }
                else {
                    cleaned.add(new SedimentDensityValue(
                        prevkm,
                        sum / counter,
                        value.getYear()));
                    sum = value.getDensity();
                    counter = 1;
                }
                prevkm = value.getKm();
            }
            this.densities.put(key, cleaned);
        }
    }
}

http://dive4elements.wald.intevation.org