ingo@2237: package de.intevation.flys.exports;
ingo@2237: 
ingo@2237: import org.jfree.data.Range;
ingo@2237: import org.jfree.data.xy.XYDataset;
ingo@2587: import org.jfree.data.xy.XYSeriesCollection;
ingo@2394: import org.jfree.data.time.RegularTimePeriod;
ingo@2394: import org.jfree.data.time.TimeSeriesCollection;
ingo@2394: import org.jfree.data.time.TimeSeries;
ingo@2237: 
ingo@2241: import org.apache.log4j.Logger;
ingo@2241: 
ingo@2394: import de.intevation.flys.jfree.Bounds;
ingo@2394: import de.intevation.flys.jfree.DoubleBounds;
ingo@2394: import de.intevation.flys.jfree.TimeBounds;
ingo@2394: 
ingo@2237: 
ingo@2237: /**
ingo@2237:  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
ingo@2237:  */
ingo@2237: public class ChartHelper {
ingo@2237: 
ingo@2241:     private static final Logger logger = Logger.getLogger(ChartHelper.class);
ingo@2241: 
ingo@2241: 
ingo@2237:     /**
ingo@2237:      * This method returns the ranges of the XYDataset <i>dataset</i> as array
ingo@2237:      * with [xrange, yrange].
ingo@2237:      *
ingo@2237:      * @param dataset The dataset which should be evaluated.
ingo@2237:      *
ingo@2237:      * @return an array with x and y ranges.
ingo@2237:      */
ingo@2587:     public static Bounds[] getBounds(XYSeriesCollection dataset) {
ingo@2241:         int seriesCount = dataset != null ? dataset.getSeriesCount() : 0;
ingo@2241: 
ingo@2241:         if (seriesCount == 0) {
ingo@2241:             logger.warn("Dataset is empty or has no Series set.");
ingo@2237:             return null;
ingo@2237:         }
ingo@2237: 
ingo@2241:         boolean foundValue = false;
ingo@2241: 
ingo@2237:         double minX = Double.MAX_VALUE;
ingo@2237:         double maxX = -Double.MAX_VALUE;
ingo@2237:         double minY = Double.MAX_VALUE;
ingo@2237:         double maxY = -Double.MAX_VALUE;
ingo@2237: 
ingo@2241:         for (int i = 0, m = seriesCount; i < m; i++) {
ingo@2237:             for (int j = 0, n = dataset.getItemCount(i); j < n; j++) {
ingo@2237:                 double x = dataset.getXValue(i, j);
ingo@2237:                 double y = dataset.getYValue(i, j);
ingo@2237: 
ingo@2241:                 if (Double.isNaN(x) || Double.isNaN(y)) {
ingo@2241:                     logger.warn("Item " + j + " in Series " + i + " is broken");
ingo@2241:                     continue;
ingo@2241:                 }
ingo@2241: 
ingo@2241:                 foundValue = true;
ingo@2241: 
ingo@2237:                 if (x < minX) {
ingo@2237:                     minX = x;
ingo@2237:                 }
ingo@2237: 
ingo@2237:                 if (x > maxX) {
ingo@2237:                     maxX = x;
ingo@2237:                 }
ingo@2237: 
ingo@2237:                 if (y < minY) {
ingo@2237:                     minY = y;
ingo@2237:                 }
ingo@2237: 
ingo@2237:                 if (y > maxY) {
ingo@2237:                     maxY = y;
ingo@2237:                 }
ingo@2237:             }
ingo@2237:         }
ingo@2237: 
ingo@2241:         return foundValue
ingo@2587:             ? new Bounds[] {
ingo@2587:                     new DoubleBounds(minX, maxX),
ingo@2587:                     new DoubleBounds(minY, maxY) }
ingo@2241:             : null;
ingo@2241:     }
ingo@2241: 
ingo@2241: 
ingo@2587:     public static Bounds[] getBounds(XYDataset dataset) {
ingo@2587:         if (dataset instanceof XYSeriesCollection) {
ingo@2587:             return getBounds((XYSeriesCollection) dataset);
ingo@2587:         }
ingo@2587:         else if(dataset instanceof TimeSeriesCollection) {
ingo@2587:             return getBounds((TimeSeriesCollection) dataset);
ingo@2587:         }
ingo@2587:         else {
ingo@2587:             logger.warn("Unknown XYDataset instance: " + dataset.getClass());
ingo@2587:             return null;
ingo@2587:         }
ingo@2587:     }
ingo@2587: 
ingo@2587: 
ingo@2394:     public static Bounds[] getBounds(TimeSeriesCollection collection) {
ingo@2394:         int seriesCount = collection != null ? collection.getSeriesCount() : 0;
ingo@2394: 
ingo@2394:         if (seriesCount == 0) {
ingo@2394:             logger.warn("TimeSeriesCollection is empty or has no Series set.");
ingo@2394:             return null;
ingo@2394:         }
ingo@2394: 
ingo@2394:         boolean foundValue = false;
ingo@2394: 
ingo@2394:         long lowerX = Long.MAX_VALUE;
ingo@2394:         long upperX = -Long.MAX_VALUE;
ingo@2394: 
ingo@2394:         double lowerY = Double.MAX_VALUE;
ingo@2394:         double upperY = -Double.MAX_VALUE;
ingo@2394: 
ingo@2394:         for (int i = 0, m = seriesCount; i < m; i++) {
ingo@2394:             TimeSeries series = collection.getSeries(i);
ingo@2394: 
ingo@2394:             for (int j = 0, n = collection.getItemCount(i); j < n; j++) {
ingo@2394:                 RegularTimePeriod rtp = series.getTimePeriod(j);
ingo@2394: 
ingo@2394:                 if (rtp == null) {
ingo@2394:                     continue;
ingo@2394:                 }
ingo@2394: 
ingo@2394:                 foundValue = true;
ingo@2394: 
ingo@2394:                 long start = rtp.getFirstMillisecond();
ingo@2394:                 long end   = rtp.getLastMillisecond();
ingo@2394: 
ingo@2394:                 if (start < lowerX) {
ingo@2394:                     lowerX = start;
ingo@2394:                 }
ingo@2394: 
ingo@2394:                 if (end > upperX) {
ingo@2394:                     upperX = end;
ingo@2394:                 }
ingo@2394: 
ingo@2394:                 double y = series.getValue(j).doubleValue();
ingo@2394: 
ingo@2394:                 lowerY = Math.min(lowerY, y);
ingo@2394:                 upperY = Math.max(upperY, y);
ingo@2394:             }
ingo@2394:         }
ingo@2394: 
ingo@2394:         if (foundValue) {
ingo@2394:             return new Bounds[] {
ingo@2394:                 new TimeBounds(lowerX, upperX),
ingo@2394:                 new DoubleBounds(lowerY, upperY)
ingo@2394:             };
ingo@2394:         }
ingo@2394: 
ingo@2394:         return null;
ingo@2394:     }
ingo@2394: 
ingo@2394: 
ingo@2241:     /**
ingo@2241:      * Expand range by percent.
ingo@2241:      *
ingo@2241:      * @param range The range to expand.
ingo@2241:      * @param percent The percentage to expand.
ingo@2241:      *
ingo@2241:      * @param an expanded range.
ingo@2241:      */
ingo@2241:     public static Range expandRange(Range range, double percent) {
ingo@2241:         if (range == null) {
ingo@2241:             return null;
ingo@2241:         }
ingo@2241: 
ingo@2241:         double value  = range.getLowerBound();
ingo@2241:         double expand = Math.abs(value / 100 * percent);
ingo@2241: 
ingo@2241:         return expand != 0
ingo@2241:             ? new Range(value-expand, value+expand)
ingo@2241:             : new Range(-0.01 * percent, 0.01 * percent);
ingo@2237:     }
ingo@2237: }
ingo@2237: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :