comparison gnv-artifacts/src/main/java/de/intevation/gnv/chart/VerticalProfileChart.java @ 657:af3f56758f59

merged gnv-artifacts/0.5
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:13:53 +0200
parents b98d1adee7a6
children 79401c871da4
comparison
equal deleted inserted replaced
590:5f5f273c8566 657:af3f56758f59
1 package de.intevation.gnv.chart;
2
3 import java.util.Collection;
4 import java.util.HashMap;
5 import java.util.Map;
6 import java.util.Iterator;
7 import java.util.Locale;
8
9 import org.apache.log4j.Logger;
10
11 import org.jfree.chart.ChartTheme;
12 import org.jfree.chart.axis.Axis;
13 import org.jfree.chart.axis.NumberAxis;
14 import org.jfree.chart.plot.XYPlot;
15 import org.jfree.chart.plot.PlotOrientation;
16 import org.jfree.data.Range;
17 import org.jfree.data.general.Series;
18 import org.jfree.data.xy.XYSeries;
19 import org.jfree.data.xy.XYSeriesCollection;
20
21 import de.intevation.gnv.geobackend.base.Result;
22 import de.intevation.gnv.state.describedata.KeyValueDescibeData;
23
24
25 /**
26 * @author Ingo Weinzierl <ingo.weinzierl@intevation.de>
27 */
28 public class VerticalProfileChart
29 extends AbstractXYLineChart
30 {
31 public static final String DEFAULT_AXIS = "KPOSITION";
32
33 private static Logger log = Logger.getLogger(VerticalProfileChart.class);
34
35 protected final double PERCENTAGE = 5.0;
36 protected final double GAP_MAX_LEVEL = Math.sqrt(2.0);
37 protected final int GAP_MAX_VALUES = 60;
38
39 /** Map to store max ranges of each parameter (axis.setAutoRange(true)
40 * doesn't seem to work properly. */
41 protected Map values;
42
43
44 public VerticalProfileChart(
45 ChartLabels labels,
46 ChartTheme theme,
47 Collection parameters,
48 Collection measurements,
49 Collection dates,
50 Collection result,
51 Collection timeGaps,
52 Locale locale,
53 boolean linesVisible,
54 boolean shapesVisible
55 ) {
56 this.labels = labels;
57 this.theme = theme;
58 this.parameters = parameters;
59 this.measurements = measurements;
60 this.dates = dates;
61 this.resultSet = result;
62 this.timeGaps = timeGaps;
63 this.locale = locale;
64 this.PLOT_ORIENTATION = PlotOrientation.HORIZONTAL;
65 this.linesVisible = linesVisible;
66 this.shapesVisible = shapesVisible;
67 this.datasets = new HashMap();
68 this.ranges = new HashMap();
69 this.values = new HashMap();
70 }
71
72
73 protected void initData() {
74 log.debug("init data for VerticalProfileChart");
75
76 String breakPoint1 = null;
77 String breakPoint2 = null;
78 String breakPoint3 = null;
79
80 Iterator iter = resultSet.iterator();
81 Result row = null;
82 String seriesName = null;
83 String parameter = null;
84 XYSeries series = null;
85
86 int idx = 0;
87 int startPos = 0;
88 int endPos = 0;
89 double startValue = 0;
90 double endValue = 0;
91
92 Result[] results =
93 (Result[]) resultSet.toArray(new Result[resultSet.size()]);
94
95 while (iter.hasNext()) {
96 row = (Result) iter.next();
97
98 // add current data to plot and prepare for next one
99 if (!row.getString("GROUP1").equals(breakPoint1) ||
100 !row.getString("GROUP2").equals(breakPoint2) ||
101 !row.getString("GROUP3").equals(breakPoint3)
102 ) {
103 log.debug("prepare data/plot for next dataset");
104
105 if(series != null) {
106 gapDetection(results, series, startPos, endPos);
107 addSeries(series, parameter, idx);
108
109 startPos = endPos +1;
110 }
111
112 // prepare variables for next plot
113 breakPoint1 = row.getString("GROUP1");
114 breakPoint2 = row.getString("GROUP2");
115 breakPoint3 = row.getString("GROUP3");
116
117 seriesName = createSeriesName(
118 breakPoint1,
119 breakPoint2,
120 breakPoint3
121 );
122 parameter = findParameter(seriesName);
123
124 log.debug("next dataset is '" + seriesName + "'");
125 series = new XYSeries(seriesName);
126 }
127
128 addValue(row, series);
129 Object x = getValue(row);
130 Double y = row.getDouble("YORDINATE");
131 if (x != null && y != null) {
132 storeMaxRange(ranges, y, parameter);
133 storeMaxValue(values, x, parameter);
134 }
135 endPos++;
136 }
137
138 if (results.length == 0)
139 return;
140
141 gapDetection(results, series, startPos, endPos);
142 addSeries(series, parameter, idx);
143
144 addDatasets();
145 }
146
147
148 protected Object getValue(Result row) {
149 return row.getDouble("XORDINATE");
150 }
151
152
153 protected void gapDetection(
154 Result[] results,
155 Series series,
156 int startPos,
157 int endPos
158 ) {
159 double startValue = results[startPos].getDouble("XORDINATE");
160 double endValue = results[endPos-1].getDouble("XORDINATE");
161 if (results[0].getInteger("DATAID") == 2)
162 addGapsOnGrid(results, series, startPos, endPos);
163 else
164 addGaps(results, series, startValue, endValue, startPos, endPos);
165 }
166
167
168 protected void prepareRangeAxis(String seriesKey, int idx) {
169 XYPlot plot = chart.getXYPlot();
170 NumberAxis xAxis = (NumberAxis) plot.getDomainAxis();
171
172 Range xRange = (Range) values.get(seriesKey);
173 xAxis.setRange(Range.expand(xRange, LOWER_MARGIN, UPPER_MARGIN));
174 log.debug("Max X-Range of dataset is: " + xRange.toString());
175 }
176
177
178 protected void addValue(Result row, Series series) {
179 ((XYSeries) series).add(
180 row.getDouble("XORDINATE"),
181 row.getDouble("YORDINATE")
182 );
183 }
184
185
186 protected void addSeries(Series series, String parameter, int idx) {
187 log.debug("add series (" + parameter + ")to chart");
188
189 if (series == null) {
190 log.warn("no data to add");
191 return;
192 }
193
194 XYSeriesCollection xysc = null;
195
196 if (datasets.containsKey(parameter))
197 xysc = (XYSeriesCollection) datasets.get(parameter);
198 else
199 xysc = new XYSeriesCollection();
200
201 xysc.addSeries((XYSeries) series);
202 datasets.put(parameter, xysc);
203 }
204
205
206 protected void addDatasets() {
207 Iterator iter = parameters.iterator();
208 XYPlot plot = chart.getXYPlot();
209 int idx = 0;
210
211 XYSeriesCollection xysc = null;
212 KeyValueDescibeData data = null;
213 String key = null;
214 while (iter.hasNext()) {
215 data = (KeyValueDescibeData) iter.next();
216 key = data.getValue();
217
218 if (datasets.containsKey(key)) {
219 xysc = (XYSeriesCollection)datasets.get(key);
220 plot.setDataset(idx, xysc );
221 log.debug("Added " + key + " parameter to plot.");
222 prepareAxis(key, idx);
223 prepareRangeAxis(key, idx);
224 adjustRenderer(
225 idx++,
226 xysc.getSeriesCount(),
227 linesVisible,
228 shapesVisible
229 );
230 }
231 }
232 }
233
234
235 protected void storeMaxValue(Map values, Object val, String parameter) {
236 double value = ((Double) val).doubleValue();
237 Range range = null;
238
239 range = values.containsKey(parameter)
240 ? (Range) values.get(parameter)
241 : new Range(value, value);
242
243 double lower = range.getLowerBound();
244 double upper = range.getUpperBound();
245
246 lower = value < lower ? value : lower;
247 upper = value > upper ? value : upper;
248
249 values.put(parameter, new Range(lower, upper));
250 }
251
252
253 protected void localizeDomainAxis(Axis axis, Locale locale) {
254 // call localizeRangeAxis from superclass which formats NumberAxis
255 super.localizeRangeAxis(axis, locale);
256 }
257
258
259 protected String createSeriesName(
260 String breakPoint1,
261 String breakPoint2,
262 String breakPoint3
263 ) {
264 log.debug("create seriesname of verticalprofile chart");
265 return findValueTitle(parameters, breakPoint1) +
266 " " +
267 findValueTitle(measurements, breakPoint2) +
268 "m";
269 }
270
271
272 protected void addGapsOnGrid(
273 Result[] results,
274 Series series,
275 int startPos,
276 int endPos
277 ) {
278 String axis = null;
279
280 if (results.length > (startPos+1)) {
281 axis = getDependendAxisName(
282 results[startPos],
283 results[startPos+1]
284 );
285 }
286 else {
287 axis = DEFAULT_AXIS;
288 }
289
290 double range = 0;
291 int last = 0;
292 int current = 0;
293
294 for (int i = startPos+1; i < endPos; i++) {
295 last = results[i-1].getInteger(axis);
296 current = results[i].getInteger(axis);
297
298 boolean detected = gridDetection(last, current);
299
300 if (detected) {
301 double xOld = results[i-1].getDouble("XORDINATE");
302 double xNow = results[i].getDouble("XORDINATE");
303 log.debug("Gap detected on grid between "+ xOld +" and "+ xNow);
304 ((XYSeries) series).add(xOld+0.0001, null);
305 }
306 }
307 }
308
309
310 protected void addGaps(
311 Result[] results,
312 Series series,
313 double startValue,
314 double endValue,
315 int startPos,
316 int endPos
317 ) {
318
319 double last = 0;
320 double current = 0;
321 int num = results.length;
322
323 for (int i = startPos+1; i < endPos; i++) {
324 boolean detected = false;
325
326 last = results[i-1].getDouble("YORDINATE");
327 current = results[i].getDouble("YORDINATE");
328
329 // gap detection for more than GAP_MAX_VALUES values
330 if (num > GAP_MAX_VALUES)
331 detected = simpleDetection(startValue, endValue, last, current);
332 // gap detection for less than GAP_MAX_VALUES values
333 else
334 detected = specialDetection(
335 startValue,
336 endValue,
337 last,
338 current,
339 num
340 );
341
342 if (detected) {
343 log.info("Gap between " + last + " and " + current);
344 ((XYSeries) series).add((last+current)/2, null);
345 }
346 }
347 }
348
349
350 protected boolean simpleDetection(
351 double start,
352 double end,
353 double last,
354 double current
355 ) {
356 double delta = Math.abs(end - start);
357 double smallDelta = Math.abs(current - last);
358
359 return (smallDelta > delta / 100 * PERCENTAGE);
360 }
361
362
363 protected boolean specialDetection(
364 double start,
365 double end,
366 double last,
367 double current,
368 int count
369 ) {
370 double delta = Math.abs(end - start);
371 double smallDelta = Math.abs(current - last);
372
373 return (smallDelta > (3.0 / (count - 1) * delta));
374 }
375
376
377 protected boolean gridDetection(double last, double current) {
378 if (log.isDebugEnabled()) {
379 log.debug("######################################################");
380 log.debug("Parameters for gap detection");
381 log.debug("Defined gap size for grids: " + GAP_MAX_LEVEL);
382 log.debug("1st value to compare: " + last);
383 log.debug("2nd value to compare: " + current);
384 log.debug("Difference: " + Math.abs(current - last));
385 }
386 return (Math.abs(current - last) > GAP_MAX_LEVEL);
387 }
388
389
390 protected String getDependendAxisName(Result first, Result second) {
391 return "KPOSITION";
392 }
393 }
394 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org