changeset 1085:07878836ee0d

Plot "real" (respecting parameters) W and Q MainValues, yet in wrong scale. flys-artifacts/trunk@2588 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Fri, 26 Aug 2011 08:49:18 +0000
parents 583314dafdb6
children 825ea312116d
files flys-artifacts/ChangeLog 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/artifacts/model/MainValuesWFacet.java flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java flys-artifacts/src/main/java/de/intevation/flys/jfree/StickyAxisAnnotation.java
diffstat 7 files changed, 304 insertions(+), 108 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Fri Aug 26 08:07:47 2011 +0000
+++ b/flys-artifacts/ChangeLog	Fri Aug 26 08:49:18 2011 +0000
@@ -1,3 +1,25 @@
+2011-08-26  Felix Wolfsteller <felix.wolfsteller@intevation.de>
+
+	Also plot "W"-MainValues (on vertical axis), take correct parameters, but
+	do not convert to correct scale (cm vs NN+m).
+
+	* src/main/java/de/intevation/flys/jfree/StickyAxisAnnotation.java:
+	  Naive attempt at allowing the vertical axis to be sticked at.
+
+	* src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java:
+	  Store Q and W MainValues separately, add them to plot as annotations.
+
+	* src/main/java/de/intevation/flys/artifacts/MainValuesArtifact.java:
+	  Serve the MainValues, parameterized on river and location, Q and W.
+	  Removed Facet-implementation.
+
+	* src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java:
+	  Updated Facet Types.
+
+	* src/main/java/de/intevation/flys/artifacts/model/MainValuesQFacet.java:
+	  src/main/java/de/intevation/flys/artifacts/model/MainValuesWFacet.java:
+	  New, trivial facets, extracted from MainValuesArtifact.
+
 2011-08-26  Ingo Weinzierl <ingo@intevation.de>
 
 	* src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java: Call
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/MainValuesArtifact.java	Fri Aug 26 08:07:47 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/MainValuesArtifact.java	Fri Aug 26 08:49:18 2011 +0000
@@ -7,21 +7,23 @@
 
 import org.w3c.dom.Document;
 
-import de.intevation.artifactdatabase.state.DefaultFacet;
 import de.intevation.artifactdatabase.state.Facet;
 import de.intevation.artifactdatabase.state.DefaultOutput;
 import de.intevation.artifactdatabase.state.State;
+import de.intevation.artifactdatabase.data.StateData;
 
 import de.intevation.artifacts.Artifact;
 import de.intevation.artifacts.ArtifactFactory;
-import de.intevation.artifacts.CallContext;
 import de.intevation.artifacts.CallMeta;
 import de.intevation.flys.artifacts.model.RiverFactory;
 
-import de.intevation.flys.artifacts.model.FacetTypes;
+import de.intevation.flys.artifacts.model.MainValuesWFacet;
+import de.intevation.flys.artifacts.model.MainValuesQFacet;
+import de.intevation.artifactdatabase.data.DefaultStateData;
 import de.intevation.flys.artifacts.states.StaticState;
 
 import de.intevation.flys.model.Gauge;
+import de.intevation.flys.model.MainValue;
 import de.intevation.flys.model.River;
 
 
@@ -73,17 +75,18 @@
     protected void initialize(Artifact artifact, Object context, CallMeta meta) {
         logger.debug("MainValuesArtifact.initialize");
         WINFOArtifact winfo = (WINFOArtifact) artifact;
-        River river = winfo.getRiver();
-        double location = winfo.getLocations()[0]; // Ort der Abflusskurve
-
-        logger.error("Location: " + location);
-        Gauge gauge = river.determineGaugeByPosition(location);
+        //River river = winfo.getRiver();
+        double location = winfo.getLocations()[0];
+        logger.debug("MainValues.location: " + location);
+        addData("location", new DefaultStateData("location", null, null,
+                    String.valueOf(location)));
+        addData("river", winfo.getData("river"));
     }
 
 
     /**
      * Get a list containing the one and only State.
-     * @param context ignored.
+     * @param  context ignored.
      * @return list with one and only state.
      */
     @Override
@@ -128,7 +131,10 @@
         else {
             state = new StaticState();
             List<Facet> fs = new ArrayList<Facet>();
-            fs.add(new MainValuesFacet());
+            Facet qfacet = new MainValuesQFacet();
+            Facet wfacet = new MainValuesWFacet();
+            fs.add(qfacet);
+            fs.add(wfacet);
             // TODO check if facets and outputs already exist.
             // TODO also check, this is usually done in initialize, too.
             facets.put(state.getID(), fs);
@@ -148,67 +154,56 @@
         return state;
     }
 
+    /**
+     * Get the river.
+     * @todo resolve, this is a duplicate of WINFOArtifact.
+     */
+    public River getRiver() {
+        StateData dRiver = getData("river");
 
-    public List getMainValues() {
-        River river = RiverFactory.getRiver("Saar");
-        logger.warn("Go to river " + river);
-        double location = 5.0f;
-        Gauge gauge = river.determineGaugeByPosition(location);
-        return gauge.getMainValues();
+        return dRiver != null
+            ? RiverFactory.getRiver((String) dRiver.getValue())
+            : null;
     }
 
+    protected Gauge getGauge() {
+        River river = getRiver();
 
-    /* FACET IMPLEMENTATION */
-    // TODO evaluate whether DefaultFacet can do.
-    static class MainValuesFacet
-    extends      DefaultFacet
-    implements   FacetTypes {
-
-        public MainValuesFacet() {
-            description = "facet.discharge_curves.mainvalues.description";
-            name = COMPUTED_DISCHARGE_MAINVALUES;
-            //Resources.getMsg(meta, I18N_DESCRIPTION, I18N_DESCRIPTION));
-            index = 0;
+        if (river == null) {
+            return null;
         }
 
+        double location = Double.parseDouble(
+                (String)getData("location").getValue());
 
-        /**
-         * Returns the description of this facet.
-         *
-         * @return the description of this facet.
-         */
-        @Override
-        public String getDescription() {
-            // TODO remove, is part of DefaultFacet.
-            return "facet.mainvalues";
+        return river.determineGaugeByPosition(location);
+    }
+
+    public List<MainValue> getMainValuesQ() {
+        List<MainValue> filteredList = new ArrayList<MainValue>();
+        Gauge gauge = getGauge();
+        if (gauge != null) {
+            List<MainValue> orig = gauge.getMainValues();
+            for (MainValue mv : orig) {
+                if (mv.getMainValue().getType().getName().equals("Q")) {
+                    filteredList.add(mv);
+                }
+            }
         }
- 
- 
-        /**
-         * Returns the data this facet requires.
-         *
-         * @param artifact the owner artifact.
-         * @param context  the CallContext (ignored).
-         *
-         * @return the data.
-         */
-        @Override
-        public Object getData(Artifact artifact, CallContext context) {
-            MainValuesArtifact mvArtifact = (MainValuesArtifact) artifact;
-            return mvArtifact.getMainValues();
+        return filteredList;
+    }
+
+    public List<MainValue> getMainValuesW() {
+        List<MainValue> filteredList = new ArrayList<MainValue>();
+        Gauge gauge = getGauge();
+        if (gauge != null) {
+            List<MainValue> orig = gauge.getMainValues();
+            for (MainValue mv : orig) {
+                if (mv.getMainValue().getType().getName().equals("W")) {
+                    filteredList.add(mv);
+                }
+            }
         }
- 
-
-        /**
-         * Create a deep copy of this Facet.
-         * @return a deep copy.
-         */
-        @Override
-        public MainValuesFacet deepCopy() {
-            MainValuesFacet copy = new MainValuesFacet();
-            copy.set(this);
-            return copy;
-        }
+        return filteredList;
     }
- 
 }
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java	Fri Aug 26 08:07:47 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java	Fri Aug 26 08:49:18 2011 +0000
@@ -15,7 +15,8 @@
     String LONGITUDINAL_ANNOTATION = "longitudinal_section.annotations";
 
     String COMPUTED_DISCHARGE_Q = "computed_discharge_curve.q";
-    String COMPUTED_DISCHARGE_MAINVALUES = "computed_discharge_curve.mainvalues";
+    String COMPUTED_DISCHARGE_MAINVALUES_Q = "computed_discharge_curve.mainvalues.q";
+    String COMPUTED_DISCHARGE_MAINVALUES_W = "computed_discharge_curve.mainvalues.w";
 
     String DISCHARGE_CURVE = "discharge_curve.curve";
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MainValuesQFacet.java	Fri Aug 26 08:49:18 2011 +0000
@@ -0,0 +1,50 @@
+package de.intevation.flys.artifacts.model;
+
+import de.intevation.artifacts.Artifact;
+import de.intevation.artifacts.CallContext;
+import de.intevation.artifactdatabase.state.DefaultFacet;
+import de.intevation.flys.artifacts.model.FacetTypes;
+import de.intevation.flys.artifacts.MainValuesArtifact;
+
+/**
+ * Facet to show Main Q Values.
+ */
+public class MainValuesQFacet
+extends      DefaultFacet
+implements   FacetTypes {
+
+    /** Trivial Constructor. */
+    public MainValuesQFacet() {
+        //Resources.getMsg(meta, I18N_DESCRIPTION, I18N_DESCRIPTION));
+        description = "facet.discharge_curves.mainvalues.description";
+        name = COMPUTED_DISCHARGE_MAINVALUES_Q;
+        index = 0;
+    }
+
+
+    /**
+     * Returns the data this facet requires.
+     *
+     * @param artifact the owner artifact.
+     * @param context  the CallContext (ignored).
+     *
+     * @return the data.
+     */
+    @Override
+    public Object getData(Artifact artifact, CallContext context) {
+        MainValuesArtifact mvArtifact = (MainValuesArtifact) artifact;
+        return mvArtifact.getMainValuesQ();
+    }
+
+
+    /**
+     * Create a deep copy of this Facet.
+     * @return a deep copy.
+     */
+    @Override
+    public MainValuesQFacet deepCopy() {
+        MainValuesQFacet copy = new MainValuesQFacet();
+        copy.set(this);
+        return copy;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MainValuesWFacet.java	Fri Aug 26 08:49:18 2011 +0000
@@ -0,0 +1,51 @@
+package de.intevation.flys.artifacts.model;
+
+import de.intevation.artifacts.Artifact;
+import de.intevation.artifacts.CallContext;
+import de.intevation.artifactdatabase.state.DefaultFacet;
+import de.intevation.flys.artifacts.model.FacetTypes;
+import de.intevation.flys.artifacts.MainValuesArtifact;
+
+/**
+ * Facet to show Main W Values.
+ */
+public class MainValuesWFacet
+extends      DefaultFacet
+implements   FacetTypes {
+
+    /** Trivial Constructor. */
+    public MainValuesWFacet() {
+        //Resources.getMsg(meta, I18N_DESCRIPTION, I18N_DESCRIPTION));
+        description = "facet.discharge_curves.mainvalues.description";
+        name = COMPUTED_DISCHARGE_MAINVALUES_W;
+        index = 0;
+    }
+
+
+    /**
+     * Returns the data this facet requires.
+     *
+     * @param artifact the owner artifact.
+     * @param context  the CallContext (ignored).
+     *
+     * @return the data.
+     */
+    @Override
+    public Object getData(Artifact artifact, CallContext context) {
+        MainValuesArtifact mvArtifact = (MainValuesArtifact) artifact;
+        return mvArtifact.getMainValuesW();
+    }
+
+
+    /**
+     * Create a deep copy of this Facet.
+     * @return a deep copy.
+     */
+    @Override
+    public MainValuesWFacet deepCopy() {
+        MainValuesWFacet copy = new MainValuesWFacet();
+        copy.set(this);
+        return copy;
+    }
+}
+
--- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java	Fri Aug 26 08:07:47 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveGenerator.java	Fri Aug 26 08:49:18 2011 +0000
@@ -1,5 +1,4 @@
 package de.intevation.flys.exports;
-
 import org.apache.log4j.Logger;
 
 import java.util.ArrayList;
@@ -12,7 +11,6 @@
 import org.jfree.data.xy.XYSeries;
 import org.jfree.chart.axis.ValueAxis;
 import org.jfree.chart.plot.XYPlot;
-import org.jfree.ui.TextAnchor;
 
 import de.intevation.artifacts.Artifact;
 
@@ -21,6 +19,7 @@
 import de.intevation.flys.artifacts.FLYSArtifact;
 import de.intevation.flys.artifacts.model.FacetTypes;
 import de.intevation.flys.artifacts.model.WQKms;
+
 import de.intevation.flys.jfree.StickyAxisAnnotation;
 
 import de.intevation.flys.model.MainValue;
@@ -51,14 +50,21 @@
     public static final String I18N_CHART_TITLE_DEFAULT = "Abflusskurve";
     public static final String I18N_YAXIS_LABEL_DEFAULT = "W [NN + m]";
 
-    /** List of MainValues (Annotations in plot). */
-    protected static List<MainValue> mainValues;
+    /** List of W MainValues (Annotations in plot). */
+    protected static List<MainValue> mainValuesW;
+
+    /** List of Q MainValues (Annotations in plot). */
+    protected static List<MainValue> mainValuesQ;
+
+    // TODO Add pseudodataseries for having mainvalue-text in legend.
+    // TODO Let theme pass through to annotations-facets.
 
 
     /** Trivial Constructor. */
     public ComputedDischargeCurveGenerator () {
         super();
-        mainValues = new ArrayList<MainValue>();
+        mainValuesQ = new ArrayList<MainValue>();
+        mainValuesW = new ArrayList<MainValue>();
     }
 
 
@@ -94,14 +100,22 @@
 
         logger.debug("ComputedDischargeCurveGenerator.doOut: " + name);
 
+        if (name == null) {
+            logger.warn("Broken facet in computed discharge out generation.");
+            return;
+        }
+
         FLYSArtifact flys = (FLYSArtifact) artifact;
         Facet        f    = flys.getNativeFacet(facet);
 
         if (name.equals(COMPUTED_DISCHARGE_Q)) {
             doQOut((WQKms) f.getData(artifact, context), attr);
         }
-        else if (name.equals(COMPUTED_DISCHARGE_MAINVALUES)) {
-            doMainValueAnnotations(f.getData(artifact, context), attr);
+        else if (name.equals(COMPUTED_DISCHARGE_MAINVALUES_Q)) {
+            doMainValueWAnnotations(f.getData(artifact, context), attr);
+        }
+        else if (name.equals(COMPUTED_DISCHARGE_MAINVALUES_W)) {
+            doMainValueQAnnotations(f.getData(artifact, context), attr);
         }
         else {
             logger.warn("Unknown facet type for computed discharge: " + name);
@@ -111,10 +125,20 @@
 
 
     /**
-     * Add MainValues as annotations to plot.
+     * Store W MainValues as annotations for later plotting.
      */
-    protected void doMainValueAnnotations(Object o, Document theme) {
-        this.mainValues = (List<MainValue>) o;
+    protected void doMainValueWAnnotations(Object o, Document theme) {
+        logger.debug("ComputedDischargeCurveGenerator set W MainValues.");
+        this.mainValuesW = (List<MainValue>) o;
+    }
+
+    
+    /**
+     * Store Q MainValues as annotations for later plotting.
+     */
+    protected void doMainValueQAnnotations(Object o, Document theme) {
+        logger.debug("ComputedDischargeCurveGenerator set Q MainValues.");
+        this.mainValuesQ = (List<MainValue>) o;
     }
 
 
@@ -136,27 +160,19 @@
      */
     protected void redoAnnotations(XYPlot plot, ValueAxis axis) {
         plot.clearAnnotations();
-        ValueAxis yAxis = plot.getRangeAxis();
-        float posY = 140.f;
-        if (yAxis != null) {
-            posY = (float) yAxis.getRange().getLowerBound();
-            // Add some (2%) space between Text and axis.
-            // TODO have all the position logic in StickyAxisAnnotation
-            //      (then merge LongitudinalSectioNGenerator).
-            posY += 0.02f * (yAxis.getRange().getUpperBound()
-                        - yAxis.getRange().getLowerBound());
+        // Add all MainValues as annotations.
+        for (MainValue mv: mainValuesQ) {
+            float pos = mv.getValue().floatValue();
+            String text = mv.getMainValue().getName();
+            StickyAxisAnnotation ta = new StickyAxisAnnotation(text, pos,
+                    StickyAxisAnnotation.SimpleAxis.X_AXIS);
+            plot.getRenderer().addAnnotation(ta);
         }
-        // Add all MainValues as annotations.
-        // TODO Implement and handle second facet for annotations on
-        //      vertical axis.
-        for (MainValue mv: mainValues) {
-            if (mv.getMainValue().getType().getName() == "W") {
-                continue;
-            }
-            float posX = mv.getValue().floatValue();
-
+        for (MainValue mv: mainValuesW) {
+            float pos = mv.getValue().floatValue();
             String text = mv.getMainValue().getName();
-            StickyAxisAnnotation ta = new StickyAxisAnnotation(text, posX, posY);
+            StickyAxisAnnotation ta = new StickyAxisAnnotation(text, pos,
+                 StickyAxisAnnotation.SimpleAxis.Y_AXIS);
             plot.getRenderer().addAnnotation(ta);
         }
     }
--- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/StickyAxisAnnotation.java	Fri Aug 26 08:07:47 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/jfree/StickyAxisAnnotation.java	Fri Aug 26 08:49:18 2011 +0000
@@ -11,7 +11,6 @@
 import org.jfree.chart.annotations.XYTextAnnotation;
 import org.jfree.chart.axis.ValueAxis;
 import org.jfree.chart.util.LineUtilities;
-import org.jfree.text.TextUtilities;
 import org.jfree.chart.plot.PlotOrientation;
 import org.jfree.chart.plot.XYPlot;
 import org.jfree.chart.entity.XYAnnotationEntity;
@@ -19,6 +18,10 @@
 import org.jfree.chart.ChartRenderingInfo;
 import org.jfree.chart.plot.Plot;
 
+import org.jfree.data.Range;
+
+import org.jfree.text.TextUtilities;
+
 import org.jfree.ui.RectangleEdge;
 import org.jfree.ui.TextAnchor;
 
@@ -43,6 +46,9 @@
     /** Which axis to stick to. */
     protected SimpleAxis stickyAxis = SimpleAxis.X_AXIS;
 
+    /** The 1-dimensional position of this annotation. */
+    protected float pos;
+
 
     /**
      * Trivial constructor.
@@ -50,20 +56,39 @@
      * @param text Text to display.
      * @param x    X-position in dataspace (typical horizontal, in km).
      * @param y    Y-position in dataspace (typical vertical, in m).
+     * @deprecated
      */
     public StickyAxisAnnotation(String text, float x, float y) {
         super(text, x, y);
         setStickyAxis(SimpleAxis.X_AXIS);
     }
 
+
+    /**
+     * Constructor with given explicit axis.
+     * @param text       the text to display.
+     * @param pos        the position at which to draw the text and mark.
+     * @param stickyAxis the axis at which to stick (and to which 'pos' is
+     *                   relative).
+     */
+    public StickyAxisAnnotation(String text, float pos, SimpleAxis stickAxis) {
+        super(text, pos, pos);
+        setStickyAxis(stickAxis);
+        this.pos = pos;
+    }
+
+    /**
+     * Legacy-Constructor.
+     * @deprecated
+     */
     public StickyAxisAnnotation(String text, float x, float y,
             SimpleAxis stickAxis) {
         super(text, x, y);
         setStickyAxis(stickAxis);
+        this.pos = x;
     }
 
 
-
     /**
      * Sets the "sticky axis" (whether to draw annotations at the
      * X- or the Y-Axis.
@@ -76,6 +101,10 @@
             this.setRotationAngle(270f * (Math.PI / 180f));
             this.setRotationAnchor(TextAnchor.CENTER_LEFT);
             this.setTextAnchor(TextAnchor.CENTER_LEFT);
+        } else {
+            this.setRotationAngle(0f * (Math.PI / 180f));
+            this.setRotationAnchor(TextAnchor.CENTER_LEFT);
+            this.setTextAnchor(TextAnchor.CENTER_LEFT);
         }
     }
 
@@ -131,15 +160,28 @@
         g2.setPaint(this.paint);
         g2.setStroke(this.stroke);
         */
-        j2DY1 = (float) RectangleEdge.coordinate(dataArea, domainEdge);
-        double rangeLow = rangeAxis.getRange().getLowerBound();
-        // Line ends at 1.5% of full distance.
-        j2DY2 = (float) rangeAxis.valueToJava2D(
-                  (1f - 0.015f) * rangeLow + 0.015f * 
-                  rangeAxis.getRange().getUpperBound(),
-                 dataArea, rangeEdge);
-        j2DX1 = (float) domainAxis.valueToJava2D(x, dataArea, domainEdge);
-        j2DX2 = j2DX1;
+        if (this.stickyAxis == SimpleAxis.X_AXIS) {
+            j2DY1 = (float) RectangleEdge.coordinate(dataArea, domainEdge);
+            double rangeLow = rangeAxis.getRange().getLowerBound();
+            // Line ends at 1.5% of full distance.
+            j2DY2 = (float) rangeAxis.valueToJava2D(
+                      (1f - 0.015f) * rangeLow + 0.015f * 
+                      rangeAxis.getRange().getUpperBound(),
+                     dataArea, rangeEdge);
+            j2DX1 = (float) domainAxis.valueToJava2D(x, dataArea, domainEdge);
+            j2DX2 = j2DX1;
+        } else {
+            j2DX1 = (float) RectangleEdge.coordinate(dataArea, rangeEdge);
+            Range domainRange = domainAxis.getRange();
+            double rangeLow = domainRange.getLowerBound();
+            // Line ends at 1.5% of full distance.
+            j2DX2 = (float) domainAxis.valueToJava2D(
+                      (1f - 0.015f) * rangeLow + 0.015f * 
+                      domainRange.getUpperBound(),
+                     dataArea, domainEdge);
+            j2DY1 = (float) rangeAxis.valueToJava2D(pos, dataArea, rangeEdge);
+            j2DY2 = j2DY1;
+        }
 
         Line2D line = new Line2D.Float(j2DX1, j2DY1, j2DX2, j2DY2);
 
@@ -187,10 +229,29 @@
             plot.getDomainAxisLocation(), orientation);
         RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(
             plot.getRangeAxisLocation(), orientation);
-        float anchorX = (float) domainAxis.valueToJava2D(
-            getX(), dataArea, domainEdge);
-        float anchorY = (float) rangeAxis.valueToJava2D(
-            getY(), dataArea, rangeEdge);
+        float anchorX = 0f;
+        float anchorY = 0.0f;
+        if (this.stickyAxis == SimpleAxis.X_AXIS) {
+            // Text starts at 1.5% of full distance.
+            float rangeLow = (float) rangeAxis.getRange().getLowerBound();
+            float y = rangeLow + 0.02f * ((float)
+                    rangeAxis.getRange().getUpperBound() - rangeLow);
+            setY(y);
+
+            anchorX = (float) domainAxis.valueToJava2D(
+                getX(), dataArea, domainEdge);
+            anchorY = (float) rangeAxis.valueToJava2D(
+                getY(), dataArea, rangeEdge);
+        } else {
+            float rangeLow = (float) domainAxis.getRange().getLowerBound();
+            float x = rangeLow + 0.02f * ((float)
+                    domainAxis.getRange().getUpperBound() - rangeLow);
+            setX(x);
+            anchorX = (float) domainAxis.valueToJava2D(
+                getX(), dataArea, domainEdge);
+            anchorY = (float) rangeAxis.valueToJava2D(
+                getY(), dataArea, rangeEdge);
+        }
         if (orientation == PlotOrientation.HORIZONTAL) {
             float tempAnchor = anchorX;
             anchorX = anchorY;

http://dive4elements.wald.intevation.org