Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/exports/TimeseriesChartGenerator.java @ 2330:594885703687
Picked changes r4015:4026 from trunk.
flys-artifacts/tags/2.6@4028 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Fri, 10 Feb 2012 11:18:27 +0000 |
parents | 6aeb71517136 |
children | 44dc117aa2b7 c7b0dfa6a52c |
comparison
equal
deleted
inserted
replaced
2329:d999062c20e6 | 2330:594885703687 |
---|---|
9 | 9 |
10 import org.apache.log4j.Logger; | 10 import org.apache.log4j.Logger; |
11 | 11 |
12 import org.jfree.chart.ChartFactory; | 12 import org.jfree.chart.ChartFactory; |
13 import org.jfree.chart.JFreeChart; | 13 import org.jfree.chart.JFreeChart; |
14 import org.jfree.chart.axis.ValueAxis; | |
14 import org.jfree.chart.plot.XYPlot; | 15 import org.jfree.chart.plot.XYPlot; |
15 | 16 |
16 import org.jfree.data.Range; | 17 import org.jfree.data.Range; |
17 import org.jfree.data.time.TimeSeriesCollection; | 18 import org.jfree.data.time.TimeSeriesCollection; |
18 import org.jfree.data.general.Series; | 19 import org.jfree.data.general.Series; |
19 import org.jfree.data.xy.XYDataset; | 20 import org.jfree.data.xy.XYDataset; |
21 | |
22 import de.intevation.flys.jfree.Bounds; | |
23 import de.intevation.flys.jfree.DoubleBounds; | |
24 import de.intevation.flys.jfree.TimeBounds; | |
20 | 25 |
21 | 26 |
22 /** | 27 /** |
23 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> | 28 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> |
24 */ | 29 */ |
104 | 109 |
105 | 110 |
106 protected void mergeRanges(TimeSeriesCollection dataset) { | 111 protected void mergeRanges(TimeSeriesCollection dataset) { |
107 logger.debug("Range after merging: " + range); | 112 logger.debug("Range after merging: " + range); |
108 | 113 |
109 Range[] xyRanges = ChartHelper.getRanges(dataset); | 114 Bounds[] xyRanges = ChartHelper.getBounds(dataset); |
110 range = Range.combine(range, xyRanges[1]); | 115 |
116 // TODO COMBINE BOUNDS! | |
111 | 117 |
112 logger.debug("Range after merging: " + range); | 118 logger.debug("Range after merging: " + range); |
113 } | 119 } |
114 | 120 |
115 } // end of TimeseriesAxisDataset class | 121 } // end of TimeseriesAxisDataset class |
118 | 124 |
119 private static final Logger logger = | 125 private static final Logger logger = |
120 Logger.getLogger(TimeseriesChartGenerator.class); | 126 Logger.getLogger(TimeseriesChartGenerator.class); |
121 | 127 |
122 | 128 |
123 protected Map<Integer, Range> xRanges; | 129 public static final int AXIS_SPACE = 5; |
124 | 130 |
125 protected Map<Integer, Range> yRanges; | 131 |
132 protected Map<Integer, Bounds> xRanges; | |
133 | |
134 protected Map<Integer, Bounds> yRanges; | |
126 | 135 |
127 | 136 |
128 | 137 |
129 /** | 138 /** |
130 * The default constructor that initializes internal datastructures. | 139 * The default constructor that initializes internal datastructures. |
131 */ | 140 */ |
132 public TimeseriesChartGenerator() { | 141 public TimeseriesChartGenerator() { |
133 super(); | 142 super(); |
134 | 143 |
135 xRanges = new HashMap<Integer, Range>(); | 144 xRanges = new HashMap<Integer, Bounds>(); |
136 yRanges = new HashMap<Integer, Range>(); | 145 yRanges = new HashMap<Integer, Bounds>(); |
137 } | 146 } |
138 | 147 |
139 | 148 |
140 | 149 |
141 @Override | 150 @Override |
159 plot.setBackgroundPaint(Color.WHITE); | 168 plot.setBackgroundPaint(Color.WHITE); |
160 | 169 |
161 addSubtitles(chart); | 170 addSubtitles(chart); |
162 addDatasets(plot); | 171 addDatasets(plot); |
163 | 172 |
173 adaptZoom(plot); | |
174 | |
164 return chart; | 175 return chart; |
165 } | 176 } |
166 | 177 |
167 | 178 |
168 @Override | 179 @Override |
169 protected Series getSeriesOf(XYDataset dataset, int idx) { | 180 protected Series getSeriesOf(XYDataset dataset, int idx) { |
170 return ((TimeSeriesCollection) dataset).getSeries(idx); | 181 return ((TimeSeriesCollection) dataset).getSeries(idx); |
171 } | 182 } |
172 | 183 |
173 | 184 |
174 @Override | 185 // TODO DECLARE IN UPPER CLASS AND ADD OVERRIDE ANNOTATION |
186 protected Bounds getXRange(int axis) { | |
187 return xRanges.get(Integer.valueOf(axis)); | |
188 } | |
189 | |
190 | |
191 @Override | |
192 // TODO setXRange should always await a Bounds instance! | |
193 // TODO SHOULD BE REMOVED WHEN DEFINED IN UPPER CLASS | |
175 protected void setXRange(int axis, Range range) { | 194 protected void setXRange(int axis, Range range) { |
176 xRanges.put(Integer.valueOf(axis), range); | 195 // do nothing here, we will use setXRange(int, Bounds) now |
177 } | 196 } |
178 | 197 |
179 | 198 |
180 @Override | 199 @Override |
200 // TODO setYRange should always await a Bounds instance! | |
181 protected void setYRange(int axis, Range range) { | 201 protected void setYRange(int axis, Range range) { |
182 yRanges.put(Integer.valueOf(axis), range); | 202 if (range == null) { |
203 logger.warn("Range is null!"); | |
204 return; | |
205 } | |
206 | |
207 setYBounds(Integer.valueOf(axis), new DoubleBounds( | |
208 range.getLowerBound(), | |
209 range.getUpperBound())); | |
183 } | 210 } |
184 | 211 |
185 | 212 |
186 /** | 213 /** |
187 * This method creates new instances of TimeseriesAxisDataset. | 214 * This method creates new instances of TimeseriesAxisDataset. |
193 logger.debug("Create a new AxisDataset for index: " + idx); | 220 logger.debug("Create a new AxisDataset for index: " + idx); |
194 return new TimeseriesAxisDataset(idx); | 221 return new TimeseriesAxisDataset(idx); |
195 } | 222 } |
196 | 223 |
197 | 224 |
225 // TODO THIS SHOULD BE DONE IN AN UPPER CLASS! | |
226 @Override | |
227 public void addAxisDataset(XYDataset dataset, int idx, boolean visible) { | |
228 if (dataset == null || idx < 0) { | |
229 return; | |
230 } | |
231 | |
232 AxisDataset axisDataset = getAxisDataset(idx); | |
233 | |
234 Bounds[] bounds = ChartHelper.getBounds((TimeSeriesCollection)dataset); | |
235 | |
236 if (bounds == null) { | |
237 logger.warn("Skip XYDataset for Axis (invalid ranges): " + idx); | |
238 return; | |
239 } | |
240 | |
241 if (visible) { | |
242 if (logger.isDebugEnabled()) { | |
243 logger.debug("Add new AxisDataset at index: " + idx); | |
244 logger.debug("X extent: " + bounds[0]); | |
245 logger.debug("Y extent: " + bounds[1]); | |
246 } | |
247 | |
248 axisDataset.addDataset(dataset); | |
249 } | |
250 | |
251 combineXRanges(bounds[0], 0); | |
252 combineYRanges(bounds[1], idx); | |
253 } | |
254 | |
255 | |
198 /** | 256 /** |
199 * Effect: extend range of x axis to include given limits. | 257 * Effect: extend range of x axis to include given limits. |
200 * @param range the given ("minimal") range. | 258 * @param range the given ("minimal") range. |
201 * @param index index of axis to be merged. | 259 * @param index index of axis to be merged. |
202 */ | 260 */ |
203 @Override | 261 @Override |
204 protected void combineXRanges(Range range, int index) { | 262 protected void combineXRanges(Range range, int index) { |
205 if (range != null) { | 263 throw new RuntimeException( |
206 Range old = xRanges.get(index); | 264 "TimeseriesChartGenerator.combineXRanges is not implemented!"); |
265 } | |
266 | |
267 | |
268 protected void combineXRanges(Bounds bounds, int index) { | |
269 if (bounds != null) { | |
270 Bounds old = getXRange(index); | |
207 | 271 |
208 if (old != null) { | 272 if (old != null) { |
209 range = Range.combine(old, range); | 273 bounds = bounds.combine(old); |
210 } | 274 } |
211 | 275 |
212 xRanges.put(index, range); | 276 setXBounds(index, bounds); |
213 } | 277 } |
214 } | 278 } |
215 | 279 |
216 | 280 |
281 protected void combineYRanges(Bounds bounds, int index) { | |
282 if (bounds != null) { | |
283 Bounds old = getYBounds(index); | |
284 | |
285 if (old != null) { | |
286 bounds = bounds.combine(old); | |
287 } | |
288 | |
289 setYBounds(index, bounds); | |
290 } | |
291 } | |
292 | |
293 | |
294 // TODO REPLACE THIS METHOD WITH getBoundsForAxis(index) | |
217 @Override | 295 @Override |
218 public Range[] getRangesForAxis(int index) { | 296 public Range[] getRangesForAxis(int index) { |
219 logger.debug("Return ranges for axis at: " + index); | 297 // TODO |
220 | 298 Bounds[] bounds = getBoundsForAxis(index); |
221 Range rx = xRanges.get(Integer.valueOf(0)); | 299 |
222 Range ry = yRanges.get(Integer.valueOf(index)); | 300 return new Range[] { |
301 new Range( | |
302 bounds[0].getLower().doubleValue(), | |
303 bounds[0].getUpper().doubleValue()), | |
304 new Range( | |
305 bounds[1].getLower().doubleValue(), | |
306 bounds[1].getUpper().doubleValue()) | |
307 }; | |
308 } | |
309 | |
310 | |
311 @Override | |
312 public Bounds getXBounds(int axis) { | |
313 return xRanges.get(axis); | |
314 } | |
315 | |
316 | |
317 @Override | |
318 protected void setXBounds(int axis, Bounds bounds) { | |
319 xRanges.put(axis, bounds); | |
320 } | |
321 | |
322 | |
323 @Override | |
324 public Bounds getYBounds(int axis) { | |
325 return yRanges.get(axis); | |
326 } | |
327 | |
328 | |
329 @Override | |
330 protected void setYBounds(int axis, Bounds bounds) { | |
331 yRanges.put(axis, bounds); | |
332 } | |
333 | |
334 | |
335 public Bounds[] getBoundsForAxis(int index) { | |
336 logger.debug("Return x and y bounds for axis at: " + index); | |
337 | |
338 Bounds rx = getXBounds(Integer.valueOf(index)); | |
339 Bounds ry = getYBounds(Integer.valueOf(index)); | |
223 | 340 |
224 if (rx == null) { | 341 if (rx == null) { |
225 logger.warn("Range for x axis not set." + | 342 logger.warn("Range for x axis not set." + |
226 " Using default values: 0 - 1."); | 343 " Using default values: 0 - 1."); |
227 rx = new Range(0, 1); | 344 rx = new TimeBounds(0l, 1l); |
228 } | 345 } |
346 | |
229 if (ry == null) { | 347 if (ry == null) { |
230 logger.warn("Range for y" + index + | 348 logger.warn("Range for y axis not set." + |
231 " axis not set. Using default values: 0 - 1."); | 349 " Using default values: 0 - 1."); |
232 ry = new Range(0, 1); | 350 ry = new DoubleBounds(0l, 1l); |
233 } | 351 } |
234 | 352 |
235 logger.debug("X Range is: " + rx); | 353 logger.debug("X Bounds at index " + index + " is: " + rx); |
236 logger.debug("Y Range is: " + ry); | 354 logger.debug("Y Bounds at index " + index + " is: " + ry); |
237 | 355 |
238 return new Range[] {rx, ry}; | 356 return new Bounds[] {rx, ry}; |
357 } | |
358 | |
359 | |
360 public Bounds getDomainAxisRange() { | |
361 String[] ranges = getDomainAxisRangeFromRequest(); | |
362 | |
363 if (ranges == null || ranges.length < 2) { | |
364 logger.debug("No zoom range for domain axis specified."); | |
365 return null; | |
366 } | |
367 | |
368 if (ranges[0] == null || ranges[1] == null) { | |
369 logger.warn("Invalid ranges for domain axis specified!"); | |
370 return null; | |
371 } | |
372 | |
373 try { | |
374 double lower = Double.parseDouble(ranges[0]); | |
375 double upper = Double.parseDouble(ranges[1]); | |
376 | |
377 return new DoubleBounds(lower, upper); | |
378 } | |
379 catch (NumberFormatException nfe) { | |
380 logger.warn("Invalid ranges for domain axis specified: " + nfe); | |
381 } | |
382 | |
383 return null; | |
384 } | |
385 | |
386 | |
387 public Bounds getValueAxisRange() { | |
388 String[] ranges = getValueAxisRangeFromRequest(); | |
389 | |
390 if (ranges == null || ranges.length < 2) { | |
391 logger.debug("No zoom range for domain axis specified."); | |
392 return null; | |
393 } | |
394 | |
395 if (ranges[0] == null || ranges[1] == null) { | |
396 logger.warn("Invalid ranges for domain axis specified!"); | |
397 return null; | |
398 } | |
399 | |
400 try { | |
401 double lower = Double.parseDouble(ranges[0]); | |
402 double upper = Double.parseDouble(ranges[1]); | |
403 | |
404 return new DoubleBounds(lower, upper); | |
405 } | |
406 catch (NumberFormatException nfe) { | |
407 logger.warn("Invalid ranges for domain axis specified: " + nfe); | |
408 } | |
409 | |
410 return null; | |
411 } | |
412 | |
413 | |
414 protected void adaptZoom(XYPlot plot) { | |
415 logger.debug("Adapt zoom of Timeseries chart."); | |
416 | |
417 zoomX(plot, plot.getDomainAxis(), getXRange(0), getDomainAxisRange()); | |
418 | |
419 Bounds valueAxisBounds = getValueAxisRange(); | |
420 | |
421 for (int j = 0, n = plot.getRangeAxisCount(); j < n; j++) { | |
422 zoomY( | |
423 plot, | |
424 plot.getRangeAxis(j), | |
425 getYBounds(j), | |
426 valueAxisBounds); | |
427 } | |
428 } | |
429 | |
430 | |
431 protected void zoomX( | |
432 XYPlot plot, | |
433 ValueAxis axis, | |
434 Bounds total, | |
435 Bounds user | |
436 ) { | |
437 if (logger.isDebugEnabled()) { | |
438 logger.debug("== Zoom X axis =="); | |
439 logger.debug(" Total axis range : " + total); | |
440 logger.debug(" User defined range: " + user); | |
441 } | |
442 | |
443 if (user != null) { | |
444 long min = total.getLower().longValue(); | |
445 long max = total.getUpper().longValue(); | |
446 long diff = max > min ? max - min : min - max; | |
447 | |
448 long newMin = (long) Math.round(min + user.getLower().doubleValue() * diff); | |
449 long newMax = (long) Math.round(min + user.getUpper().doubleValue() * diff); | |
450 | |
451 TimeBounds newBounds = new TimeBounds(newMin, newMax); | |
452 | |
453 logger.debug(" Zoom axis to: " + newBounds); | |
454 | |
455 newBounds.applyBounds(axis, AXIS_SPACE); | |
456 } | |
457 else { | |
458 logger.debug("No user specified zoom values found!"); | |
459 total.applyBounds(axis, AXIS_SPACE); | |
460 } | |
461 } | |
462 | |
463 | |
464 protected void zoomY( | |
465 XYPlot plot, | |
466 ValueAxis axis, | |
467 Bounds total, | |
468 Bounds user | |
469 ) { | |
470 if (logger.isDebugEnabled()) { | |
471 logger.debug("== Zoom Y axis =="); | |
472 logger.debug(" Total axis range : " + total); | |
473 logger.debug(" User defined range: " + user); | |
474 } | |
475 | |
476 if (user != null) { | |
477 double min = total.getLower().doubleValue(); | |
478 double max = total.getUpper().doubleValue(); | |
479 double diff = max > min ? max - min : min - max; | |
480 | |
481 double newMin = min + user.getLower().doubleValue() * diff; | |
482 double newMax = min + user.getUpper().doubleValue() * diff; | |
483 | |
484 DoubleBounds newBounds = new DoubleBounds(newMin, newMax); | |
485 | |
486 logger.debug(" Zoom axis to: " + newBounds); | |
487 | |
488 newBounds.applyBounds(axis, AXIS_SPACE); | |
489 } | |
490 else { | |
491 logger.debug("No user specified zoom values found!"); | |
492 total.applyBounds(axis, AXIS_SPACE); | |
493 } | |
239 } | 494 } |
240 } | 495 } |
241 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : | 496 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |