comparison gnv-artifacts/src/main/java/de/intevation/gnv/chart/VerticalProfileChart.java @ 540:80630520e25a

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

http://dive4elements.wald.intevation.org