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 :

http://dive4elements.wald.intevation.org