changeset 2163:105097966111

Theoretically allow annotations on second y ais. Practically allow Q MainValues on Q Axis in Duration Curves. flys-artifacts/trunk@3750 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Mon, 23 Jan 2012 14:18:53 +0000
parents df70f14af981
children d548e2e13524
files flys-artifacts/ChangeLog flys-artifacts/doc/conf/artifacts/winfo.xml flys-artifacts/doc/conf/themes.xml flys-artifacts/src/main/java/de/intevation/flys/artifacts/MainValuesArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MainValuesQFacet.java flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java flys-artifacts/src/main/java/de/intevation/flys/jfree/StickyAxisAnnotation.java
diffstat 9 files changed, 173 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Mon Jan 23 11:06:06 2012 +0000
+++ b/flys-artifacts/ChangeLog	Mon Jan 23 14:18:53 2012 +0000
@@ -1,3 +1,37 @@
+2012-01-23  Felix Wolfsteller	<felix.wolfsteller@intevation.de>
+
+	Fix flys/issue452 (Annotations at second y-axis).
+
+	* src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java:
+	  Added new type (duration_curve.mainvalues.q).
+	
+	* doc/conf/themes.xml: Added theme mapping for new facet type.
+
+	* src/main/java/de/intevation/flys/artifacts/MainValuesArtifact.java:
+	  Create another Facet.
+
+	* doc/conf/artifacts/winfo.xml: Added new facet type to compatibility
+	  list.
+
+	* src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java:
+	  Handle new Facet.
+
+	* src/main/java/de/intevation/flys/jfree/StickyAxisAnnotation.java:
+	  Added field to be able to remember which axis to stick to.
+
+	* src/main/java/de/intevation/flys/artifacts/model/MainValuesQFacet.java:
+	  Tell Annotations to stick to Q axis in the special duration_curve
+	  environment.
+
+	* src/main/java/de/intevation/flys/exports/XYChartGenerator.java:
+	  (AxisDataset): Added plotAxisIndex to now have a
+			 two-way-association.
+	  Tell own axisDatasets to which 'jfreechart'-axis they are assigned.
+	  Evaluate which axis the StickyAxisAnnotations should be sticked to,
+	  and calculate text and line positions accordingly.
+	  Removed junk.
+
+
 2012-01-23  Felix Wolfsteller	<felix.wolfsteller@intevation.de>
 
 	Fix compilation.
--- a/flys-artifacts/doc/conf/artifacts/winfo.xml	Mon Jan 23 11:06:06 2012 +0000
+++ b/flys-artifacts/doc/conf/artifacts/winfo.xml	Mon Jan 23 14:18:53 2012 +0000
@@ -189,7 +189,7 @@
                     <facets>
                         <facet name="duration_curve.w" description="facet.duration_curve.w"/>
                         <facet name="duration_curve.q" description="facet.duration_curve.q"/>
-                        <facet name="computed_discharge_curve.mainvalues.q" description="Q Main Values"/>
+                        <facet name="duration_curve.mainvalues.q" description="Q Main Values at optional second axis"/>
                         <facet name="computed_discharge_curve.mainvalues.w" description="W Main Values"/>
                     </facets>
                 </outputmode>
--- a/flys-artifacts/doc/conf/themes.xml	Mon Jan 23 11:06:06 2012 +0000
+++ b/flys-artifacts/doc/conf/themes.xml	Mon Jan 23 14:18:53 2012 +0000
@@ -918,6 +918,7 @@
         <mapping from="discharge_longitudinal_section.q" to="DischargeLongitudinalSectionQ"/>
         <mapping from="computed_discharge_curve.mainvalues.q" to="ComputedDischargeCurveQ"/>
         <mapping from="computed_discharge_curve.mainvalues.w" to="ComputedDischargeCurveW"/>
+        <mapping from="duration_curve.mainvalues.q" to="ComputedDischargeCurveQ"/>
         <mapping from="mainvalues.q" to="ComputedDischargeCurveQ"/>
         <mapping from="mainvalues.w" to="ComputedDischargeCurveW"/>
         <mapping from="longitudinal_section.annotations" to="Annotations"/>
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/MainValuesArtifact.java	Mon Jan 23 11:06:06 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/MainValuesArtifact.java	Mon Jan 23 14:18:53 2012 +0000
@@ -78,6 +78,13 @@
         logger.debug("MainValuesArtifact.setup");
         state = new StaticState(STATIC_STATE_NAME);
 
+        Facet qfacet0 = new MainValuesQFacet(
+            DURATION_MAINVALUES_Q,
+            Resources.getMsg(
+                callMeta,
+                "facet.discharge_curves.mainvalues.q",
+                "facet.discharge_curves.mainvalues.q"),
+            false);
         Facet qfacet1 = new MainValuesQFacet(
             COMPUTED_DISCHARGE_MAINVALUES_Q,
             Resources.getMsg(
@@ -108,6 +115,7 @@
             true);
 
         List<Facet> fs = new ArrayList<Facet>();
+        fs.add(qfacet0);
         fs.add(qfacet1);
         fs.add(qfacet2);
         fs.add(wfacet1);
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java	Mon Jan 23 11:06:06 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java	Mon Jan 23 14:18:53 2012 +0000
@@ -76,6 +76,7 @@
 
     String DURATION_W = "duration_curve.w";
     String DURATION_Q = "duration_curve.q";
+    String DURATION_MAINVALUES_Q = "duration_curve.mainvalues.q";
 
     String STATIC_WQ    = "other.wq";
     String STATIC_WQ_ANNOTATIONS = "other.wq.annotations";
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MainValuesQFacet.java	Mon Jan 23 11:06:06 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MainValuesQFacet.java	Mon Jan 23 14:18:53 2012 +0000
@@ -13,6 +13,8 @@
 import de.intevation.flys.jfree.FLYSAnnotation;
 import de.intevation.flys.jfree.StickyAxisAnnotation;
 
+import de.intevation.flys.exports.DurationCurveGenerator;
+
 /**
  * Facet to show Main Q Values.
  * TODO Join with W implementation.
@@ -27,9 +29,9 @@
     /** Trivial Constructor. */
     public MainValuesQFacet(String name, String description, boolean atGauge) {
         this.description = description;
-        this.name = name;
-        this.index = 0;
-        this.isAtGauge = atGauge;
+        this.name        = name;
+        this.index       = 0;
+        this.isAtGauge   = atGauge;
     }
 
 
@@ -45,14 +47,26 @@
     public Object getData(Artifact artifact, CallContext context) {
         MainValuesArtifact mvArtifact = (MainValuesArtifact) artifact;
 
-        List<NamedDouble>      qs = mvArtifact.getMainValuesQ(isAtGauge);
+        List<NamedDouble>          qs = mvArtifact.getMainValuesQ(isAtGauge);
         List<StickyAxisAnnotation> xy = new ArrayList<StickyAxisAnnotation>();
 
-        for (NamedDouble q: qs) {
-            xy.add(new StickyAxisAnnotation(
-                q.getName(),
-                (float) q.getValue(),
-                StickyAxisAnnotation.SimpleAxis.X_AXIS));
+        // Rather specific case, Q-Annotations at a maybe second yaxis.
+        if (this.name.equals(DURATION_MAINVALUES_Q)) {
+            for (NamedDouble q: qs) {
+                xy.add(new StickyAxisAnnotation(
+                    q.getName(),
+                    (float) q.getValue(),
+                    StickyAxisAnnotation.SimpleAxis.Y_AXIS,
+                    DurationCurveGenerator.YAXIS.Q.idx));
+            }
+        }
+        else {
+            for (NamedDouble q: qs) {
+                xy.add(new StickyAxisAnnotation(
+                    q.getName(),
+                    (float) q.getValue(),
+                    StickyAxisAnnotation.SimpleAxis.X_AXIS));
+            }
         }
 
         return new FLYSAnnotation(description, xy);
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java	Mon Jan 23 11:06:06 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java	Mon Jan 23 14:18:53 2012 +0000
@@ -36,7 +36,7 @@
     public static enum YAXIS {
         W(0),
         Q(1);
-        protected int idx;
+        public int idx;
         private YAXIS(int c) {
            idx = c;
         }
@@ -182,7 +182,7 @@
         else if (name.equals(DURATION_Q)) {
             doQOut((WQDay) artifactFacet.getData(context), attr, visible);
         }
-        else if (name.equals(COMPUTED_DISCHARGE_MAINVALUES_Q)
+        else if (name.equals(DURATION_MAINVALUES_Q)
                 || name.equals(MAINVALUES_Q)
                 || name.equals(COMPUTED_DISCHARGE_MAINVALUES_W)
                 || name.equals(MAINVALUES_W)
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java	Mon Jan 23 11:06:06 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java	Mon Jan 23 14:18:53 2012 +0000
@@ -90,6 +90,8 @@
         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 AxisDataset(int symb) {
@@ -136,6 +138,16 @@
         public boolean isEmpty() {
             return this.datasets.isEmpty();
         }
+
+        /** Set the 'real' axis index that this axis is mapped to. */
+        public void setPlotAxisIndex(int axisIndex) {
+            this.plotAxisIndex = axisIndex;
+        }
+
+        /** Get the 'real' axis index that this axis is mapped to. */
+        public int getPlotAxisIndex() {
+            return this.plotAxisIndex;
+        }
     } // class AxisDataset
 
 
@@ -618,6 +630,7 @@
                         axisDataset.isArea((XYSeriesCollection)dataset));
                     datasetIndex++;
                 }
+                axisDataset.setPlotAxisIndex(axisIndex);
                 axisIndex++;
             }
         }
@@ -626,8 +639,9 @@
 
     /**
      * Registers an area to be drawn.
-     * @param lower the lower curve to draw the area from.
-     * @param upper the upper curve to draw the ara from.
+     * @param area Area to be drawn.
+     * @param index 'axis index'
+     * @param visible Whether or not to be visible (important for range calculations).
      */
     public void addAreaSeries(StyledAreaSeriesCollection area, int index, boolean visible) {
         if (area == null) {
@@ -655,7 +669,7 @@
      * Add given series if visible, if not visible adjust ranges (such that
      * all points in data would be plotted once visible).
      * @param series the dataseries to include in plot.
-     * @param index  index of the series and of its axis.
+     * @param index  ('symbolic') 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) {
@@ -982,62 +996,6 @@
     }
 
 
-    /**
-     * Get "lowest" X Value for first axis. This value is exactly at the
-     * border of the plot.
-     * @return lowest value on first 'x'-axis.
-     */
-    protected double getLowestXValue(XYPlot plot) {
-        ValueAxis axis = plot.getDomainAxis();
-        if (axis == null) {
-            logger.warn("No X-Axis to find lowest value for.");
-        }
-        return axis.getRange().getLowerBound();
-    }
-
-
-    /**
-     * Get "lowest" X Value for first axis. This value is exactly at the
-     * border of the plot.
-     * @return highest value on first 'x'-axis.
-     */
-    protected double getUppestXValue(XYPlot plot) {
-        ValueAxis axis = plot.getDomainAxis();
-        if (axis == null) {
-            logger.warn("No first Y-Axis to find uppest value for.");
-        }
-        return axis.getRange().getUpperBound();
-    }
-
-
-    /**
-     * Get "lowest" Y Value for first axis. This value is exactly at the
-     * border of the plot.
-     * @return lowest value on first 'y'-axis.
-     */
-    protected double getLowestYValue(XYPlot plot) {
-        ValueAxis yaxis = plot.getRangeAxis(0);
-        if (yaxis == null) {
-            logger.warn("No first Y-Axis to find lowest value for.");
-        }
-        return yaxis.getRange().getLowerBound();
-    }
-
-
-    /**
-     * Get "lowest" Y Value for first axis. This value is exactly at the
-     * border of the plot.
-     * @return highest value on first 'y'-axis.
-     */
-    protected double getUppestYValue(XYPlot plot) {
-        ValueAxis yaxis = plot.getRangeAxis(0);
-        if (yaxis == null) {
-            logger.warn("No first Y-Axis to find uppest value for.");
-        }
-        return yaxis.getRange().getUpperBound();
-    }
-
-
     /** Get color for hyk zones by their type (which is the name). */
     public Paint colorForHYKZone(String zoneName) {
         if (zoneName.startsWith("R")) {
@@ -1081,6 +1039,8 @@
         XYLineAnnotation lineAnnotation = null;
         XYTextAnnotation textAnnotation = null;
 
+        int rendererIndex = 0;
+
         if (annotation.atX()) {
             textAnnotation = new CollisionFreeXYTextAnnotation(
                 annotation.getText(), annotation.getPos(), area.ofGround(TEXT_OFF));
@@ -1091,25 +1051,69 @@
                 lineAnnotation = new XYLineAnnotation(annotation.getPos(),
                     area.atGround(), annotation.getPos(), area.ofGround(LINE_OFF),
                     new BasicStroke(lineStyle.getWidth()),lineStyle.getColor());
+                textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT);
+                textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
             }
             else {
                 lineAnnotation = new XYLineAnnotation(annotation.getPos(),
                     area.atGround(), annotation.getPos(), area.ofGround(LINE_OFF));
+                textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT);
+                textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
             }
         }
         else {
-            textAnnotation = new CollisionFreeXYTextAnnotation(
-                annotation.getText(), area.ofLeft(TEXT_OFF), annotation.getPos());
-            // Style the line.
-            if (lineStyle != null) {
-                lineAnnotation = new XYLineAnnotation(area.atLeft(),
-                    annotation.getPos(), area.ofLeft(LINE_OFF),
-                    annotation.getPos(), new BasicStroke(lineStyle.getWidth()),
-                    lineStyle.getColor());
+            // Do the more complicated case where we stick to the Y-Axis.
+            // There is one nasty case (duration curves, where annotations
+            // might stick to the second y-axis).
+            AxisDataset dataset = this.datasets.get(
+                new Integer(annotation.getAxisSymbol()));
+            if (dataset == null) {
+                logger.warn("Annotation should stick to unfindable y-axis: "
+                    + annotation.getAxisSymbol());
+                rendererIndex = 0;
             }
             else {
-                lineAnnotation = new XYLineAnnotation(area.atLeft(),
-                    annotation.getPos(), area.ofLeft(LINE_OFF), annotation.getPos());
+                rendererIndex = dataset.getPlotAxisIndex();
+            }
+
+            if (rendererIndex != 0) {
+                // OPTIMIZE: Pass a different area to this function,
+                //           do the adding to renderer outside (let this
+                //           function return the annotations).
+                //           Note that this path is travelled rarely.
+                Area area2 = new Area(plot.getDomainAxis(), plot.getRangeAxis(rendererIndex));
+                textAnnotation = new CollisionFreeXYTextAnnotation(
+                    annotation.getText(), area2.ofRight(TEXT_OFF), annotation.getPos());
+                textAnnotation.setRotationAnchor(TextAnchor.CENTER_RIGHT);
+                textAnnotation.setTextAnchor(TextAnchor.CENTER_RIGHT);
+                // Style the line.
+                if (lineStyle != null) {
+                    lineAnnotation = new XYLineAnnotation(area2.ofRight(LINE_OFF),
+                        annotation.getPos(), area2.atRight(),
+                        annotation.getPos(), new BasicStroke(lineStyle.getWidth()),
+                        lineStyle.getColor());
+                }
+                else {
+                    lineAnnotation = new XYLineAnnotation(area2.atRight(),
+                        annotation.getPos(), area2.ofRight(LINE_OFF), annotation.getPos());
+                }
+            }
+            else {
+                textAnnotation = new CollisionFreeXYTextAnnotation(
+                    annotation.getText(), area.ofLeft(TEXT_OFF), annotation.getPos());
+                textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT);
+                textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
+                // Style the line.
+                if (lineStyle != null) {
+                    lineAnnotation = new XYLineAnnotation(area.atLeft(),
+                        annotation.getPos(), area.ofLeft(LINE_OFF),
+                        annotation.getPos(), new BasicStroke(lineStyle.getWidth()),
+                        lineStyle.getColor());
+                }
+                else {
+                    lineAnnotation = new XYLineAnnotation(area.atLeft(),
+                        annotation.getPos(), area.ofLeft(LINE_OFF), annotation.getPos());
+                }
             }
         }
 
@@ -1119,12 +1123,9 @@
         }
 
         // Add the Annotations to renderer.
-        textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT);
-        textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
-
-        plot.getRenderer().addAnnotation(textAnnotation,
+        plot.getRenderer(rendererIndex).addAnnotation(textAnnotation,
             org.jfree.ui.Layer.BACKGROUND);
-        plot.getRenderer().addAnnotation(lineAnnotation,
+        plot.getRenderer(rendererIndex).addAnnotation(lineAnnotation,
             org.jfree.ui.Layer.BACKGROUND);
     }
 
@@ -1635,11 +1636,21 @@
             this.yRange = rangeY;
         }
 
+        public Area(ValueAxis axisX, ValueAxis axisY) {
+            this.xRange = axisX.getRange();
+            this.yRange = axisY.getRange();
+        }
+
         public double ofLeft(double percent) {
             return xRange.getLowerBound()
                 + xRange.getLength() * percent;
         }
 
+        public double ofRight(double percent) {
+            return xRange.getUpperBound()
+                - xRange.getLength() * percent;
+        }
+
         public double ofGround(double percent) {
             return yRange.getLowerBound()
                 + yRange.getLength() * percent;
@@ -1653,6 +1664,10 @@
             return yRange.getLowerBound();
         }
 
+        public double atRight() {
+            return xRange.getUpperBound();
+        }
+
         public double atLeft() {
             return xRange.getLowerBound();
         }
--- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/StickyAxisAnnotation.java	Mon Jan 23 11:06:06 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/jfree/StickyAxisAnnotation.java	Mon Jan 23 14:18:53 2012 +0000
@@ -21,6 +21,9 @@
         Y_AXIS  /** Usually "vertical". */
     }
 
+    /** The "symbolic" integer representing which axis to stick to. */
+    protected int axisSymbol;
+
     /** Which axis to stick to. */
     protected SimpleAxis stickyAxis = SimpleAxis.X_AXIS;
 
@@ -49,9 +52,16 @@
      */
     public StickyAxisAnnotation(String text, float pos, SimpleAxis stickAxis
     ) {
+        this(text, pos, stickAxis, 0);
+    }
+
+    public StickyAxisAnnotation(String text, float pos, SimpleAxis stickAxis,
+            int axisSymbol
+    ) {
         setStickyAxis(stickAxis);
         this.text   = text;
         this.pos    = pos;
+        this.axisSymbol = axisSymbol;
     }
 
 
@@ -81,5 +91,9 @@
     public String getText() {
         return this.text;
     }
+
+    public int getAxisSymbol() {
+        return this.axisSymbol;
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org