comparison artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensity.java @ 8064:50102c41151e

Sediment load: Ensure that the lists of values are always ordered station wise. This was a hidden bug. :-/
author Sascha L. Teichmann <teichmann@intevation.de>
date Wed, 30 Jul 2014 18:54:14 +0200
parents 41d9014bfa02
children fdb26fe898dc
comparison
equal deleted inserted replaced
8063:41d9014bfa02 8064:50102c41151e
9 package org.dive4elements.river.artifacts.model.minfo; 9 package org.dive4elements.river.artifacts.model.minfo;
10 10
11 import java.io.Serializable; 11 import java.io.Serializable;
12 import java.util.ArrayList; 12 import java.util.ArrayList;
13 import java.util.Collections; 13 import java.util.Collections;
14 import java.util.Comparator;
14 import java.util.HashMap; 15 import java.util.HashMap;
15 import java.util.Iterator; 16 import java.util.Iterator;
16 import java.util.List; 17 import java.util.List;
17 import java.util.Map; 18 import java.util.Map;
18 import java.util.Set; 19 import java.util.Set;
67 68
68 public Map<Integer, List<SedimentDensityValue>> getDensities() { 69 public Map<Integer, List<SedimentDensityValue>> getDensities() {
69 return densities; 70 return densities;
70 } 71 }
71 72
73 private static final Comparator<SedimentDensityValue> BY_KM =
74 new Comparator<SedimentDensityValue>() {
75 @Override
76 public int compare(SedimentDensityValue a, SedimentDensityValue b) {
77 double diff = a.getKm() - b.getKm();
78 if (diff < 0.0) return -1;
79 if (diff > 0.0) return +1;
80 return 0;
81 }
82 };
83
72 public void addDensity(double km, double density, int year) { 84 public void addDensity(double km, double density, int year) {
73 85
74 logger.debug("adding " + year); 86 logger.debug("adding " + year);
75 87
76 Integer key = Integer.valueOf(year); 88 Integer key = Integer.valueOf(year);
80 if (list == null) { 92 if (list == null) {
81 list = new ArrayList<SedimentDensityValue>(); 93 list = new ArrayList<SedimentDensityValue>();
82 densities.put(key, list); 94 densities.put(key, list);
83 } 95 }
84 96
85 list.add(new SedimentDensityValue(km, density, year)); 97 // Keep list sorted by km.
98 SedimentDensityValue sdv = new SedimentDensityValue(km, density, year);
99 int index = Collections.binarySearch(list, sdv, BY_KM);
100
101 if (index < 0) {
102 // index = -(insertion point) - 1
103 // -(index + 1) = insertion point
104 index = -(index + 1);
105 }
106
107 list.add(index, sdv);
86 } 108 }
87 109
88 /** 110 /**
89 * Get the density at year. 111 * Get the density at year.
90 * Measured densities are valid until the next measurement. 112 * Measured densities are valid until the next measurement.
100 Map.Entry<Integer, List<SedimentDensityValue>> entry = densities.firstEntry(); 122 Map.Entry<Integer, List<SedimentDensityValue>> entry = densities.firstEntry();
101 return entry.getKey() <= year 123 return entry.getKey() <= year
102 ? getDensityAtKm(entry.getValue(), km) 124 ? getDensityAtKm(entry.getValue(), km)
103 : SEDIMNET_DENSITY_FACTOR; 125 : SEDIMNET_DENSITY_FACTOR;
104 } 126 }
127
105 Iterator<Map.Entry<Integer, List<SedimentDensityValue>>> iter = 128 Iterator<Map.Entry<Integer, List<SedimentDensityValue>>> iter =
106 densities.entrySet().iterator(); 129 densities.entrySet().iterator();
107 130
108 Map.Entry<Integer, List<SedimentDensityValue>> last = iter.next(); 131 Map.Entry<Integer, List<SedimentDensityValue>> last = iter.next();
109 132
144 } 167 }
145 168
146 /** Get points km,density (sorted by km), for a given year. */ 169 /** Get points km,density (sorted by km), for a given year. */
147 public double[][] getDensities(int year) 170 public double[][] getDensities(int year)
148 { 171 {
149 TreeMap<Double, Double> map = new TreeMap<Double,Double>();
150 List<SedimentDensityValue> list = densities.get(year); 172 List<SedimentDensityValue> list = densities.get(year);
151 if (list == null) { 173 if (list == null) {
152 return new double[2][0]; 174 return new double[2][0];
153 } 175 }
154 for (SedimentDensityValue sdv: densities.get(year)) { 176 // List is sorted in km.
155 map.put(sdv.getKm(), sdv.getDensity()); 177 double[][] points = new double[2][list.size()];
156 }
157 double[][] points = new double[2][map.size()];
158 int i = 0; 178 int i = 0;
159 for (Map.Entry<Double, Double> kmDens: map.entrySet()) { 179 for (SedimentDensityValue sdv: list) {
160 points[0][i] = kmDens.getKey(); 180 points[0][i] = sdv.getKm();
161 points[1][i] = kmDens.getValue(); 181 points[1][i] = sdv.getDensity();
162 i++; 182 i++;
163 } 183 }
164 184
165 return points; 185 return points;
166 } 186 }
167 187
168 /** Get value at km, interpolated. */ 188 /** Get value at km, interpolated. */
169 private double getDensityAtKm( 189 private static double getDensityAtKm(
170 List<SedimentDensityValue> values, 190 List<SedimentDensityValue> values,
171 double km 191 double km
172 ) { 192 ) {
173 SedimentDensityValue prev = null; 193 SedimentDensityValue prev = null;
174 SedimentDensityValue next = null; 194 SedimentDensityValue next = null;
175 for (SedimentDensityValue sdv: values) { 195 for (SedimentDensityValue sdv: values) {
176 logger.debug("year: " + sdv.getYear());
177 if (Math.abs(sdv.getKm() - km) < 0.00001) { 196 if (Math.abs(sdv.getKm() - km) < 0.00001) {
178 return prev.getDensity(); 197 return prev.getDensity();
179 } 198 }
180 if (sdv.getKm() > km) { 199 if (sdv.getKm() > km) {
181 next = sdv; 200 next = sdv;

http://dive4elements.wald.intevation.org