Mercurial > dive4elements > gnv-client
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 : |