changeset 1931:7c52e9cb2a72

Allow more than two datasets and more flexibility with axes in plots. Based on patch by S. Teichmann. flys-artifacts/trunk@3312 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Thu, 24 Nov 2011 07:20:46 +0000
parents de0c2bbb27f9
children 17e18948fe5e
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeCurveGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/WDifferencesCurveGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java
diffstat 9 files changed, 202 insertions(+), 124 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Wed Nov 23 14:09:29 2011 +0000
+++ b/flys-artifacts/ChangeLog	Thu Nov 24 07:20:46 2011 +0000
@@ -1,3 +1,30 @@
+2011-11-24  Felix Wolfsteller <felix.wolfsteller@intevation.de>
+
+	In XYChartGenerators allow more than two datasets.
+	Assign axis to indices of datasets, do not show axis if corresponding
+	dataset is set to be not visible.
+	Do proper axis-setting in LongitudinalSectionGenerator only (other
+	will follow). Based on a patch by Sascha Teichmann.
+
+	* src/main/java/de/intevation/flys/exports/XYChartGenerator.java:
+	  Keep relation between index and dataset, once its added. Compute
+	  ranges per index. Allow subclasses to override createAxes to specify
+	  internationalized labels etc.
+	
+	* src/main/java/de/intevation/flys/exports/DischargeCurveGenerator.java,
+	  src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java,
+	  src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java,
+	  src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java,
+	  src/main/java/de/intevation/flys/exports/WDifferencesCurveGenerator.java,
+	  src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionGenerator.java:
+	  Add datasets to first index.
+
+	* src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java:
+	  Implement createYAxis to create correct first, second and third
+	  axis. Added enum to easy identification of axis. Stripped down
+	  adjustAxis which was used to create second axis.
+	  Add datasets at correct indices.
+
 2011-11-23  Felix Wolfsteller <felix.wolfsteller@intevation.de>
 
 	* src/main/java/de/intevation/flys/artifacts/datacage/templating/StackFrames.java,
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java	Wed Nov 23 14:09:29 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java	Thu Nov 24 07:20:46 2011 +0000
@@ -144,7 +144,7 @@
         XYSeries series = new StyledXYSeries(facet.getDescription(), theme);
         StyledSeriesBuilder.addPoints(series, data);
 
-        addFirstAxisSeries(series, visible);
+        addAxisSeries(series, 0, visible);
     }
 
     /**
@@ -161,7 +161,7 @@
         XYSeries series = new StyledXYSeries(facet.getDescription(), theme);
         StyledSeriesBuilder.addPointsQW(series, wqkms);
 
-        addFirstAxisSeries(series, visible);
+        addAxisSeries(series, 0, visible);
     }
 
 
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java	Wed Nov 23 14:09:29 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/CrossSectionGenerator.java	Thu Nov 24 07:20:46 2011 +0000
@@ -194,7 +194,7 @@
 
         StyledSeriesBuilder.addPoints(series, (double [][]) o);
 
-        addFirstAxisSeries(series, visible);
+        addAxisSeries(series, 0, visible);
     }
 
 
@@ -216,7 +216,7 @@
 
         StyledSeriesBuilder.addPoints(series, (double [][]) o);
 
-        addFirstAxisSeries(series, visible);
+        addAxisSeries(series, 0, visible);
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeCurveGenerator.java	Wed Nov 23 14:09:29 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeCurveGenerator.java	Thu Nov 24 07:20:46 2011 +0000
@@ -171,7 +171,7 @@
 
         StyledSeriesBuilder.addPointsQW(series, wqkms);
 
-        addFirstAxisSeries(series, visible);
+        addAxisSeries(series, 0, visible);
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionGenerator.java	Wed Nov 23 14:09:29 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/DischargeLongitudinalSectionGenerator.java	Thu Nov 24 07:20:46 2011 +0000
@@ -108,7 +108,7 @@
                 series.add(wqckms.getKm(i), wqckms.getC(i));
             }
 
-            addFirstAxisSeries(series, visible);
+            addAxisSeries(series, 0, visible);
         }
 
         if (wqckms.guessWaterIncreasing()) {
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java	Wed Nov 23 14:09:29 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java	Thu Nov 24 07:20:46 2011 +0000
@@ -184,7 +184,7 @@
             series.add((double) day, w);
         }
 
-        addFirstAxisSeries(series, visible);
+        addAxisSeries(series, 0, visible);
     }
 
 
@@ -209,7 +209,7 @@
             series.add((double) day, q);
         }
 
-        addSecondAxisSeries(series, visible);
+        addAxisSeries(series, 1, visible);
     }
 
 
@@ -238,5 +238,7 @@
         logger.warn("Could not determine chart curve type: " + type);
         return type;
     }
+
+    // MainValue-Annotations should be visualized by a line that goes to the curve itself.
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java	Wed Nov 23 14:09:29 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java	Thu Nov 24 07:20:46 2011 +0000
@@ -39,6 +39,16 @@
 extends      XYChartGenerator
 implements   FacetTypes
 {
+    public static enum YAXIS {
+        W(0),
+        Q(1),
+        D(2);
+        protected int idx;
+        private YAXIS(int c) {
+           idx = c;
+        }
+    }
+
     /** The logger that is used in this generator. */
     private static Logger logger =
         Logger.getLogger(LongitudinalSectionGenerator.class);
@@ -161,6 +171,29 @@
 
 
     /**
+     * Create Axis for given index.
+     * @return axis with according internationalized label.
+     */
+    @Override
+    protected NumberAxis createYAxis(int index) {
+        Font labelFont = new Font("Tahoma", Font.BOLD, 14);
+        String label = "default";
+        if (index == YAXIS.W.idx) {
+            label = getYAxisLabel();
+        }
+        else if (index == YAXIS.Q.idx) {
+            label = msg(get2YAxisLabelKey(), get2YAxisDefaultLabel());
+        }
+        else if (index == YAXIS.D.idx) {
+            // TODO: diff label
+            label = "TODO: diff";
+        }
+        NumberAxis axis = new NumberAxis(label);
+        axis.setLabelFont(labelFont);
+        return axis;
+    }
+
+    /**
      * Get default value for the second Y-Axis' label (if no translation was
      * found).
      */
@@ -178,23 +211,11 @@
 
 
     /**
-     * Adjust the axis to meet LongitudinalSection diagram demands.
-     * (e.g. add second Y-axis with internationalized label, trigger
-     * inversion).
-     * @param see get2YAxisLabelKey, get2YAxisDefaultLabel
+     * Trigger inversion.
      */
     @Override
     protected void adjustAxes(XYPlot plot) {
         super.adjustAxes(plot);
-
-        NumberAxis qAxis = new NumberAxis(
-            msg(get2YAxisLabelKey(), get2YAxisDefaultLabel()));
-
-        plot.setRangeAxis(1, qAxis);
-
-        Font font = plot.getRangeAxis(0).getLabelFont();
-        qAxis.setLabelFont(font);
-
         invertXAxis(plot.getDomainAxis());
     }
 
@@ -321,7 +342,7 @@
 
         StyledSeriesBuilder.addPoints(series, wkms);
 
-        addFirstAxisSeries(series, visible);
+        addAxisSeries(series, YAXIS.W.idx, visible);
 
         if (wkms instanceof WQKms) {
             if (needInvertAxis((WQKms) wkms)) {
@@ -359,7 +380,7 @@
 
         StyledSeriesBuilder.addPoints(series, wkms);
 
-        addSecondAxisSeries(series, visible);
+        addAxisSeries(series, YAXIS.D.idx, visible);
         if (DataUtil.guessWaterIncreasing(wkms.allWs())) {
             setInverted(true);
         }
@@ -389,7 +410,7 @@
 
         StyledSeriesBuilder.addPoints(series, wqkms);
 
-        addSecondAxisSeries(series, visible);
+        addAxisSeries(series, YAXIS.Q.idx, visible);
 
         if (needInvertAxis(wqkms)) {
             setInverted(true);
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/WDifferencesCurveGenerator.java	Wed Nov 23 14:09:29 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/WDifferencesCurveGenerator.java	Thu Nov 24 07:20:46 2011 +0000
@@ -5,6 +5,7 @@
 import org.jfree.chart.title.TextTitle;
 
 import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.NumberAxis;
 import org.jfree.chart.plot.XYPlot;
 import org.jfree.data.xy.XYSeries;
 import org.jfree.data.Range;
@@ -189,7 +190,7 @@
         // Note: the only difference in the super-implementation
         //  (in LongitudinalSectionGenerator) is here (adds with
         //  addFirstAxisSeries() .
-        addSecondAxisSeries(series, visible);
+        addAxisSeries(series, 3, visible);
 
         if (wkms instanceof WQKms) {
             if (needInvertAxis((WQKms) wkms)) {
@@ -245,12 +246,18 @@
 
         StyledSeriesBuilder.addPoints(series, wkms);
 
-        addFirstAxisSeries(series, visible);
+        addAxisSeries(series, 0, visible);
         if (DataUtil.guessWaterIncreasing(wkms.allWs())) {
             setInverted(true);
         }
     }
 
+    @Override
+    protected NumberAxis createYAxis(int index) {
+        String s = "" + index;
+        return new NumberAxis(s);
+    }
+
     /**
      * Disable Longitudinals behaviour to include "0" in the Q axis.
      *
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java	Wed Nov 23 14:09:29 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java	Thu Nov 24 07:20:46 2011 +0000
@@ -10,8 +10,10 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.TreeMap;
 import java.util.List;
 import java.util.Map;
+import java.util.SortedMap;
 
 import org.w3c.dom.Document;
 
@@ -31,6 +33,7 @@
 import org.jfree.data.Range;
 import org.jfree.data.xy.XYSeries;
 import org.jfree.data.xy.XYSeriesCollection;
+import org.jfree.data.xy.XYDataset;
 
 import org.jfree.ui.RectangleInsets;
 
@@ -52,11 +55,8 @@
     /** The logger that is used in this generator. */
     private static Logger logger = Logger.getLogger(XYChartGenerator.class);
 
-    /** SeriesCollection used for the first axis. */
-    protected XYSeriesCollection first;
-
-    /** SeriesCollection used for the second axis. */
-    protected XYSeriesCollection second;
+    /** Map of datasets ("index"). */
+    protected SortedMap<Integer, List<XYDataset>> datasets;
 
     /** List of annotations to insert in plot. */
     protected List<FLYSAnnotation> annotations;
@@ -71,6 +71,13 @@
     public static final float DEFAULT_GRID_LINE_WIDTH = 0.3f;
 
 
+    public XYChartGenerator() {
+        xRanges  = new HashMap<Integer, Range>();
+        yRanges  = new HashMap<Integer, Range>();
+        datasets = new TreeMap<Integer, List<XYDataset>>();
+    }
+
+
     /**
      * Returns the title of a chart.
      *
@@ -157,10 +164,9 @@
             false,
             false);
 
+        XYPlot plot = (XYPlot) chart.getPlot();
         chart.setBackgroundPaint(Color.WHITE);
-        chart.getPlot().setBackgroundPaint(Color.WHITE);
-
-        XYPlot plot = (XYPlot) chart.getPlot();
+        plot.setBackgroundPaint(Color.WHITE);
 
         addDatasets(plot);
         addAnnotations(plot);
@@ -169,6 +175,7 @@
         localizeAxes(plot);
 
         removeEmptyRangeAxes(plot);
+        createAxes(plot);
         adjustAxes(plot);
 
         preparePointRanges(plot);
@@ -181,73 +188,67 @@
 
 
     /**
-     * Add first and second dataset to plot.
+     * Add datasets to plot.
      * @param plot plot to add datasets to.
      */
     protected void addDatasets(XYPlot plot) {
-        if (first != null) {
-            logger.debug("Set the first axis dataset.");
-            plot.setDataset(0, first);
-        }
-        if (second != null) {
-            logger.debug("Set the second axis dataset.");
-            plot.setDataset(1, second);
-        }
-    }
-
-
-    public void addFirstAxisSeries(XYSeries series, boolean visible) {
-        if (first == null) {
-            first = new XYSeriesCollection();
-        }
-
-        if (series != null) {
-            if (visible) {
-                first.addSeries(series);
+        int count = 0;
+        for (Map.Entry<Integer, List<XYDataset>> entry: datasets.entrySet()) {
+            List<Integer> axisList = new ArrayList<Integer>(1);
+            axisList.add(entry.getKey());
+            for (XYDataset dataset: entry.getValue()) {
+                int index = count++;
+                plot.setDataset(index, dataset);
+                plot.mapDatasetToRangeAxes(index, axisList);
             }
-
-            combineYRanges(new Range(series.getMinY(), series.getMaxY()), 0);
-            combineXRanges(new Range(series.getMinX(), series.getMaxX()), 0);
         }
     }
 
 
-    public void addSecondAxisSeries(XYSeries series, boolean visible) {
-        if (second == null) {
-            second = new XYSeriesCollection();
-        }
-
-        if (series != null) {
-            if (visible) {
-                second.addSeries(series);
-            }
-
-            combineYRanges(new Range(series.getMinY(), series.getMaxY()), 1);
-            combineXRanges(new Range(series.getMinX(), series.getMaxX()), 0);
-        }
-    }
-
-
-    private void combineXRanges(Range range, int index) {
-        Integer key = Integer.valueOf(index);
-
-        if (xRanges == null) {
-            xRanges = new HashMap<Integer, Range>();
-            xRanges.put(key, range);
+    /**
+     * Add given series.
+     * @param series the dataseries to include in plot.
+     * @param index  index of the series and of its axis.
+     * @param visible whether or not the data should be plotted.
+     */
+    public void addAxisSeries(XYSeries series, int index, boolean visible) {
+        if (series == null) {
             return;
         }
 
-        Range newX = null;
-        Range oldX = xRanges.get(key);
+        if (visible) {
+            XYSeriesCollection collection = new XYSeriesCollection(series);
 
-        if (oldX != null) {
-            newX = Range.combine(oldX, range);
-        }
-        else {
-            newX = range;
+            List<XYDataset> dataset = datasets.get(index);
+
+            if (dataset == null) {
+                dataset = new ArrayList<XYDataset>();
+                datasets.put(index, dataset);
+            }
+
+            dataset.add(collection);
         }
 
-        xRanges.put(key, newX);
+        // Do this also when not visible to have axis scaled by default such
+        // that every data-point could be seen (except for annotations).
+        combineXRanges(new Range(series.getMinX(), series.getMaxX()), 0);
+        combineYRanges(new Range(series.getMinY(), series.getMaxY()), index);
+    }
+
+    /**
+     * Effect: extend range of x axis to include given limits.
+     * @param range the given ("minimal") range.
+     * @param index index of axis to be merged.
+     */
+    private void combineXRanges(Range range, int index) {
+
+        Range old = xRanges.get(index);
+
+        if (old != null) {
+            range = Range.combine(old, range);
+        }
+
+        xRanges.put(index, range);
     }
 
 
@@ -255,25 +256,14 @@
      * @param range the new range.
      */
     private void combineYRanges(Range range, int index) {
-        Integer key = Integer.valueOf(index);
 
-        if (yRanges == null) {
-            yRanges = new HashMap<Integer, Range>();
-            yRanges.put(key, range);
-            return;
+        Range old = yRanges.get(index);
+
+        if (old != null) {
+            range = Range.combine(old, range);
         }
 
-        Range newY = null;
-        Range oldY = yRanges.get(key);
-
-        if (oldY != null) {
-            newY = Range.combine(oldY, range);
-        }
-        else {
-            newY = range;
-        }
-
-        yRanges.put(key, newY);
+        yRanges.put(index, range);
     }
 
 
@@ -293,17 +283,47 @@
     }
 
 
+    /**
+     * Create y-axes.
+     */
+    public void createAxes(XYPlot plot) {
+        logger.debug("XYChartGenerator.createAxes");
+        Integer last = datasets.lastKey();
+
+        if (last != null) {
+            for (int i = last; i >= 0; --i) {
+                if (datasets.containsKey(i)) {
+                    plot.setRangeAxis(i, createYAxis(i));
+                }
+            }
+        }
+    }
+
+    /**
+     * Create Y (range) axis for given index.
+     * Shall be overriden by subclasses.
+     */
+    protected NumberAxis createYAxis(int index) {
+        NumberAxis axis = new NumberAxis("default axis");
+        return axis;
+    }
+
     private void removeEmptyRangeAxes(XYPlot plot) {
-        if (first == null) {
-            plot.setRangeAxis(0, null);
-        }
+        Integer last = datasets.lastKey();
 
-        if (second == null) {
-            plot.setRangeAxis(1, null);
+        if (last != null) {
+            for (int i = last-1; i >= 0; --i) {
+                if (!datasets.containsKey(i)) {
+                    plot.setRangeAxis(i, null);
+                }
+            }
         }
     }
 
 
+    /**
+     * Expands X and Y axes if only a point is shown.
+     */
     private void preparePointRanges(XYPlot plot) {
         for (int i = 0, num = plot.getDomainAxisCount(); i < num; i++) {
             Integer key = Integer.valueOf(i);
@@ -325,6 +345,9 @@
     }
 
 
+    /**
+     * Expand range by percent.
+     */
     public static Range expandRange(Range range, double percent) {
         if (range == null) {
             return null;
@@ -479,14 +502,18 @@
 
 
     /**
-     * Adjusts the axes of a plot.
+     * Adjusts the axes of a plot (the first axis does not include zero).
      *
      * @param plot The XYPlot of the chart.
      */
     protected void adjustAxes(XYPlot plot) {
         NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
-
-        yAxis.setAutoRangeIncludesZero(false);
+        if (yAxis == null) {
+            logger.warn("No Axis to setAutoRangeIncludeZero.");
+        }
+        else {
+            yAxis.setAutoRangeIncludesZero(false);
+        }
     }
 
 
@@ -508,14 +535,6 @@
         plot.setRangeGridlinesVisible(true);
 
         plot.setAxisOffset(new RectangleInsets(0d, 0d, 0d, 0d));
-
-        if (plot.getDataset(0) != null) {
-            plot.mapDatasetToRangeAxis(0, 0);
-        }
-
-        if (plot.getDataset(1) != null) {
-            plot.mapDatasetToRangeAxis(1, 1);
-        }
     }
 
 
@@ -581,12 +600,14 @@
 
 
     protected void applyThemes(XYPlot plot) {
-        if (first != null) {
-            applyThemes(plot, first, 0);
-        }
 
-        if (second != null) {
-            applyThemes(plot, second, 1);
+        for (Map.Entry<Integer, List<XYDataset>> entry: datasets.entrySet()) {
+            int axis = entry.getKey();
+            for (XYDataset dataset: entry.getValue()) {
+                if (dataset instanceof XYSeriesCollection) {
+                    applyThemes(plot, (XYSeriesCollection)dataset, axis);
+                }
+            }
         }
     }
 

http://dive4elements.wald.intevation.org