changeset 7034:557cb3a3d772 generator-refactoring

Combine AxisDataset implementations and remove / simplify handling code. Tested with longitudinal section and hist. discharges should be ok.
author Andre Heinecke <aheinecke@intevation.de>
date Wed, 18 Sep 2013 10:12:47 +0200 (2013-09-18)
parents 0d91a6598a89
children 5c6fd2c010dd
files artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator.java artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator2.java artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java artifacts/src/main/java/org/dive4elements/river/jfree/AxisDataset.java
diffstat 5 files changed, 139 insertions(+), 286 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator.java	Tue Sep 17 16:49:37 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator.java	Wed Sep 18 10:12:47 2013 +0200
@@ -30,6 +30,7 @@
 import org.dive4elements.river.jfree.Style;
 import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
 import org.dive4elements.river.jfree.StyledSeries;
+import org.dive4elements.river.jfree.AxisDataset;
 import org.dive4elements.river.model.River;
 import org.dive4elements.river.themes.LineStyle;
 import org.dive4elements.river.themes.TextStyle;
@@ -149,26 +150,6 @@
 
 
 
-    public interface AxisDataset {
-
-        void addDataset(XYDataset dataset);
-
-        XYDataset[] getDatasets();
-
-        boolean isEmpty();
-
-        void setRange(Range range);
-
-        Range getRange();
-
-        boolean isArea(XYDataset dataset);
-
-        void setPlotAxisIndex(int idx);
-
-        int getPlotAxisIndex();
-
-    } // end of AxisDataset interface
-
 
 
     /**
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator2.java	Tue Sep 17 16:49:37 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator2.java	Wed Sep 18 10:12:47 2013 +0200
@@ -30,6 +30,7 @@
 import org.dive4elements.river.jfree.Style;
 import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
 import org.dive4elements.river.jfree.StyledSeries;
+import org.dive4elements.river.jfree.AxisDataset;
 import org.dive4elements.river.model.River;
 import org.dive4elements.river.themes.LineStyle;
 import org.dive4elements.river.themes.TextStyle;
@@ -147,30 +148,6 @@
         String getId(int idx);
     } // end of YAxisWalker interface
 
-
-
-    public interface AxisDataset {
-
-        void addDataset(XYDataset dataset);
-
-        XYDataset[] getDatasets();
-
-        boolean isEmpty();
-
-        void setRange(Range range);
-
-        Range getRange();
-
-        boolean isArea(XYDataset dataset);
-
-        void setPlotAxisIndex(int idx);
-
-        int getPlotAxisIndex();
-
-    } // end of AxisDataset interface
-
-
-
     /**
      * Default constructor that initializes internal data structures.
      */
--- a/artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java	Tue Sep 17 16:49:37 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java	Wed Sep 18 10:12:47 2013 +0200
@@ -16,6 +16,7 @@
 import org.dive4elements.river.jfree.RiverAnnotation;
 import org.dive4elements.river.jfree.StyledTimeSeries;
 import org.dive4elements.river.jfree.TimeBounds;
+import org.dive4elements.river.jfree.AxisDataset;
 import org.dive4elements.river.themes.ThemeDocument;
 
 import java.awt.Color;
@@ -60,126 +61,6 @@
 public abstract class TimeseriesChartGenerator
 extends               ChartGenerator {
 
-    /**
-     * Inner class TimeseriesAxisDataset stores TimeSeriesCollection.
-     */
-    public class TimeseriesAxisDataset implements AxisDataset {
-
-        protected int axisSymbol;
-
-        protected List<TimeSeriesCollection> datasets;
-
-        protected Range range;
-
-        protected int plotAxisIndex;
-
-        public TimeseriesAxisDataset(int axisSymbol) {
-            this.axisSymbol = axisSymbol;
-            this.datasets   = new ArrayList<TimeSeriesCollection>();
-        }
-
-
-        @Override
-        public void addDataset(XYDataset dataset) {
-            if (!(dataset instanceof TimeSeriesCollection)) {
-                logger.warn("Skip non TimeSeriesCollection dataset.");
-                return;
-            }
-
-            TimeSeriesCollection tsc = (TimeSeriesCollection) dataset;
-
-            datasets.add(tsc);
-            mergeRanges(tsc);
-        }
-
-
-        @Override
-        public XYDataset[] getDatasets() {
-            return datasets.toArray(new XYDataset[datasets.size()]);
-        }
-
-
-        @Override
-        public boolean isEmpty() {
-            return datasets.isEmpty();
-        }
-
-
-        @Override
-        public void setRange(Range range) {
-            this.range = range;
-        }
-
-
-        @Override
-        public Range getRange() {
-            return range;
-        }
-
-
-        @Override
-        public void setPlotAxisIndex(int plotAxisIndex) {
-            this.plotAxisIndex = plotAxisIndex;
-        }
-
-
-        @Override
-        public int getPlotAxisIndex() {
-            return plotAxisIndex;
-        }
-
-
-        @Override
-        public boolean isArea(XYDataset dataset) {
-            logger.warn("This AxisDataset doesn't support Areas yet!");
-            return false;
-        }
-
-
-        protected void mergeRanges(TimeSeriesCollection dataset) {
-            logger.debug("Range before merging: " + range);
-            Range subRange = null;
-
-            // Determine min/max of range axis.
-            for (int i = 0; i < dataset.getSeriesCount(); i++) {
-                if (dataset.getSeries(i).getItemCount() == 0) {
-                    continue;
-                }
-                double min = Double.MAX_VALUE;
-                double max = -Double.MAX_VALUE;
-                TimeSeries series = dataset.getSeries(i);
-                for (int j = 0; j < series.getItemCount(); j++) {
-                    double tmp = series.getValue(j).doubleValue();
-                    min = tmp < min ? tmp : min;
-                    max = tmp > max ? tmp : max;
-                }
-                if (subRange != null) {
-                    subRange = new Range(
-                        min < subRange.getLowerBound() ?
-                            min : subRange.getLowerBound(),
-                        max > subRange.getUpperBound() ?
-                            max : subRange.getUpperBound());
-                }
-                else {
-                    subRange = new Range(min, max);
-                }
-            }
-
-            // Avoid merging NaNs, as they take min/max place forever.
-            if (subRange == null ||
-                Double.isNaN(subRange.getLowerBound()) ||
-                Double.isNaN(subRange.getUpperBound())) {
-                return;
-            }
-            if (range == null) {
-                range = subRange;
-                return;
-            }
-            range = Range.combine(range, subRange);
-        }
-
-    } // end of TimeseriesAxisDataset class
-
     protected List<Marker> domainMarker;
 
     protected List<Marker> valueMarker;
@@ -389,14 +270,14 @@
 
 
     /**
-     * This method creates new instances of TimeseriesAxisDataset.
+     * This method creates new instances of AxisDataset.
      *
-     * @param idx The symbol for the new TimeseriesAxisDataset.
+     * @param idx The symbol for the new AxisDataset.
      */
     @Override
     protected AxisDataset createAxisDataset(int idx) {
         logger.debug("Create a new AxisDataset for index: " + idx);
-        return new TimeseriesAxisDataset(idx);
+        return new AxisDataset(idx);
     }
 
 
--- a/artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java	Tue Sep 17 16:49:37 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java	Wed Sep 18 10:12:47 2013 +0200
@@ -46,6 +46,7 @@
 import org.dive4elements.river.jfree.RiverAnnotation;
 import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
 import org.dive4elements.river.jfree.StyledXYSeries;
+import org.dive4elements.river.jfree.AxisDataset;
 import org.dive4elements.river.themes.ThemeDocument;
 
 
@@ -66,115 +67,6 @@
  */
 public abstract class XYChartGenerator extends ChartGenerator {
 
-    public class XYAxisDataset implements AxisDataset {
-        /** Symbolic integer, but also coding the priority (0 goes first). */
-        protected int axisSymbol;
-
-        /** List of assigned datasets (in order). */
-        protected List<XYDataset> datasets;
-
-        /** Range to use to include all given datasets. */
-        protected Range range;
-
-        /** Index of axis in plot. */
-        protected int plotAxisIndex;
-
-        /** Create AxisDataset. */
-        public XYAxisDataset(int symb) {
-            this.axisSymbol = symb;
-            datasets        = new ArrayList<XYDataset>();
-        }
-
-        /** Merge (or create given range with range so far (if any). */
-        private void mergeRanges(Range subRange) {
-            // Avoid merging NaNs, as they take min/max place forever.
-            if (subRange == null ||
-                Double.isNaN(subRange.getLowerBound()) ||
-                Double.isNaN(subRange.getUpperBound())) {
-                return;
-            }
-            if (range == null) {
-                range = subRange;
-                return;
-            }
-            range = Range.combine(range, subRange);
-        }
-
-
-        /** Add a dataset to internal list for this axis. */
-        @Override
-        public void addDataset(XYDataset dataset) {
-            datasets.add(dataset);
-            includeYRange(((XYSeriesCollection) dataset).getSeries(0));
-        }
-
-        /** Add a dataset, include its range. */
-        public void addDataset(XYSeries series) {
-            addDataset(new XYSeriesCollection(series));
-        }
-
-
-        /** Set Range for this axis. */
-        @Override
-        public void setRange(Range range) {
-            this.range = range;
-        }
-
-
-        /** Get Range for this axis. */
-        @Override
-        public Range getRange() {
-            return range;
-        }
-
-
-        /** Get Array of Datasets. */
-        @Override
-        public XYDataset[] getDatasets() {
-            return datasets.toArray(new XYDataset[datasets.size()]);
-        }
-
-
-        /** Add a Dataset that describes an area. */
-        public void addArea(StyledAreaSeriesCollection series) {
-            this.datasets.add(series);
-            List<?> allSeries = series.getSeries();
-            /* We do not include the bounds/ranges, if the area includes
-             * points at "infinity"/BIG_DOUBLE_VALUE, the charts extents are
-             * expanded to include these very small/big value.
-             * This is especially used when showing "area above axis". */
-        }
-
-        /** True if to be rendered as area. */
-        @Override
-        public boolean isArea(XYDataset series) {
-            return (series instanceof StyledAreaSeriesCollection);
-        }
-
-        /** Adjust range to include given dataset. */
-        public void includeYRange(XYSeries dataset) {
-            mergeRanges(new Range(dataset.getMinY(), dataset.getMaxY()));
-        }
-
-        /** True if no datasets given. */
-        @Override
-        public boolean isEmpty() {
-            return this.datasets.isEmpty();
-        }
-
-        /** Set the 'real' axis index that this axis is mapped to. */
-        @Override
-        public void setPlotAxisIndex(int axisIndex) {
-            this.plotAxisIndex = axisIndex;
-        }
-
-        /** Get the 'real' axis index that this axis is mapped to. */
-        @Override
-        public int getPlotAxisIndex() {
-            return this.plotAxisIndex;
-        }
-    } // class AxisDataset
-
     /** Enumerator over existing axes. */
     @Override
     protected abstract YAxisWalker getYAxisWalker();
@@ -415,8 +307,8 @@
 
     @Override
     protected AxisDataset createAxisDataset(int idx) {
-        logger.debug("Create new XYAxisDataset for index: " + idx);
-        return new XYAxisDataset(idx);
+        logger.debug("Create new AxisDataset for index: " + idx);
+        return new AxisDataset(idx);
     }
 
 
@@ -481,7 +373,7 @@
             return;
         }
 
-        XYAxisDataset axisDataset = (XYAxisDataset) getAxisDataset(index);
+        AxisDataset axisDataset = (AxisDataset) getAxisDataset(index);
 
         if (visible) {
             axisDataset.addArea(area);
@@ -510,13 +402,7 @@
 
         addAxisDataset(new XYSeriesCollection(series), index, visible);
 
-        XYAxisDataset axisDataset = (XYAxisDataset) getAxisDataset(index);
-
-        if (!visible) {
-            // Do this also when not visible to have axis scaled by default such
-            // that every data-point could be seen (except for annotations).
-            axisDataset.includeYRange(series);
-        }
+        AxisDataset axisDataset = (AxisDataset) getAxisDataset(index);
     }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/AxisDataset.java	Wed Sep 18 10:12:47 2013 +0200
@@ -0,0 +1,128 @@
+/* Copyright (C) 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * XYDatasethis file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUXYDatasetELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.jfree;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.lang.Math;
+
+import org.jfree.data.Range;
+import org.jfree.data.RangeInfo;
+import org.jfree.data.xy.XYDataset;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+import org.jfree.data.time.TimeSeriesCollection;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Axis datasets.
+ */
+public class AxisDataset
+{
+    private static Logger logger = Logger.getLogger(AxisDataset.class);
+
+    /** Symbolic integer, but also coding the priority (0 goes first). */
+    protected int axisSymbol;
+
+    /** List of assigned datasets (in order). */
+    protected List<XYDataset> datasets;
+
+    /** Range to use to include all given datasets. */
+    protected Range range;
+
+    /** Index of axis in plot. */
+    protected int plotAxisIndex;
+
+    protected boolean rangeDirty;
+
+    /** Create AxisDataset. */
+    public AxisDataset(int symb) {
+        axisSymbol = symb;
+        datasets   = new ArrayList<XYDataset>();
+    }
+
+    /** Add a dataset to internal list for this axis. */
+    public void addDataset(XYDataset dataset) {
+        datasets.add(dataset);
+        rangeDirty = true;
+    }
+
+    /** Add a dataset. */
+    public void addDataset(XYSeries series) {
+        addDataset(new XYSeriesCollection(series));
+    }
+
+    public void setRange(Range val) {
+        range = val;
+    }
+
+    /** Get Range for the range axis of this dataset. */
+    public Range getRange() {
+        if (range != null && !rangeDirty) {
+            return range;
+        }
+        /* Calculate the min / max of all series */
+        for (XYDataset dataset: datasets) {
+            Range newRange = null;
+            if (dataset instanceof StyledAreaSeriesCollection) {
+                /* We do not include areas in the range calculation because
+                 * they are used with very large / small values to draw areas
+                 * with axis boundaries */
+                continue;
+            } else if (dataset instanceof RangeInfo) {
+                /* The usual case for most series */
+                newRange = ((RangeInfo) dataset).getRangeBounds(false);
+            } else if (dataset instanceof TimeSeriesCollection) {
+                /* Lalala <3 Jfreechart's class hirarchy */
+                newRange = ((TimeSeriesCollection) dataset).getRangeBounds(false);
+            }
+
+            /* Now we only expand as we also only add new data */
+            if (range == null) {
+                range = newRange;
+            } else {
+                range = Range.combineIgnoringNaN(range, newRange);
+            }
+        }
+        rangeDirty = false;
+        return range;
+    }
+
+    /** Get Array of Datasets. */
+    public XYDataset[] getDatasets() {
+        return datasets.toArray(new XYDataset[datasets.size()]);
+    }
+
+    /** True if to be rendered as area. */
+    public boolean isArea(XYDataset series) {
+        return (series instanceof StyledAreaSeriesCollection);
+    }
+
+    /** True if no datasets given. */
+    public boolean isEmpty() {
+        return datasets.isEmpty();
+    }
+
+    /** Set the 'real' axis index that this axis is mapped to. */
+    public void setPlotAxisIndex(int axisIndex) {
+        plotAxisIndex = axisIndex;
+    }
+
+    /** Get the 'real' axis index that this axis is mapped to. */
+    public int getPlotAxisIndex() {
+        return plotAxisIndex;
+    }
+
+    /** Add a Dataset that describes an area. */
+    public void addArea(StyledAreaSeriesCollection series) {
+        addDataset(series);
+    }
+
+}

http://dive4elements.wald.intevation.org