comparison gnv-artifacts/src/main/java/de/intevation/gnv/chart/VerticalProfileChart.java @ 376:d8f3ef441bf2

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

http://dive4elements.wald.intevation.org