changeset 3272:31168ac9c7e7

Partial fix for issue694 (heightmarks snap to nearest cross section). flys-artifacts/trunk@4916 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Tue, 10 Jul 2012 15:31:56 +0000
parents 4c4ec9e9650a
children 739aa90eb79e
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/ManualPointsArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionFacet.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java
diffstat 8 files changed, 183 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Tue Jul 10 13:26:13 2012 +0000
+++ b/flys-artifacts/ChangeLog	Tue Jul 10 15:31:56 2012 +0000
@@ -1,3 +1,28 @@
+2012-07-10	Felix Wolfsteller	<felix.wolfsteller@intevation.de>
+
+	Partial fix for issue694 (Heightmarks snap to nearest cross section
+	line).
+
+	* src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java:
+	  Extended signature of getWaterLines to allow behaviour of only
+	  delivering data if it snaps to the km (is closest).
+
+	* src/main/java/de/intevation/flys/artifacts/ManualPointsArtifact.java,
+	  src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java:
+	  Documentation, updated signature of getWaterLines().
+
+	* src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java:
+	  Remember if Heightmarks are displayed, if so deliver data
+	  only if cross-section is closest (snap).
+
+	* src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java:
+	  Make next and previous km of cross-sections available as data.
+
+	* src/main/java/de/intevation/flys/artifacts/model/CrossSectionFacet.java,
+	  src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java:
+	  Provide next and previous cross-section km via blackboard, adjusted
+	  call to getWaterLines.
+
 2012-07-10	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
 
 	* src/main/java/de/intevation/flys/artifacts/model/WstValueTable.java:
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java	Tue Jul 10 13:26:13 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java	Tue Jul 10 15:31:56 2012 +0000
@@ -54,6 +54,12 @@
     /** Name of data item flagging whether we are the newest. */
     public static final String DATA_IS_NEWEST = "cross_section.newest?";
 
+    /** Name of data item storing the previous possible km. */
+    public static final String DATA_PREV_KM = "cross_section.km.previous";
+
+    /** Name of data item storing the next possible km. */
+    public static final String DATA_NEXT_KM = "cross_section.km.next";
+
     /** Own logger. */
     private static final Logger logger =
         Logger.getLogger(CrossSectionArtifact.class);
@@ -98,14 +104,14 @@
             CrossSectionLine csl = csls.get(0);
             // Find min-km of cross sections,
             // then set DATA_KM to min(DATA_KM, minCross).
-            double masterKm = Double.valueOf(getDataAsString(DATA_KM));
-            if (masterKm < csl.getKm().doubleValue()) {
+            double dataKm = Double.valueOf(getDataAsString(DATA_KM));
+            if (dataKm < csl.getKm().doubleValue()) {
                 addStringData(DATA_KM, csl.getKm().toString());
             }
         }
         fs.add(new CrossSectionFacet(0, cs.getDescription()));
 
-        // Find out if we are newest.
+        // Find out if we are newest and become master if so.
         boolean isNewest = CrossSectionFactory.isNewest(cs);
         String newString = (isNewest) ? "1" : "0";
         addStringData(DATA_IS_NEWEST, newString);
@@ -136,6 +142,15 @@
     }
 
 
+    public Double getNextKm() {
+        return getDataAsDouble(DATA_NEXT_KM);
+    }
+
+    public Double getPrevKm() {
+        return getDataAsDouble(DATA_PREV_KM);
+    }
+
+
     /**
      * Create and return a new StaticState with charting output.
      */
@@ -238,6 +253,9 @@
      * Get CrossSectionLine spatially closest to what is specified in the data
      * "cross_section.km", null if considered too far.
      *
+     * It also adds DataItems to store the next and previous (numerically)
+     * values at which cross-section data was recorded.
+     *
      * @return CrossSectionLine closest to "cross_section.km", might be null
      *         if considered too far.
      */
@@ -258,6 +276,9 @@
         Double floor = kms.floorKey(wishKM);
         Double ceil  = kms.ceilingKey(wishKM);
 
+        Double nextKm;
+        Double prevKm;
+
         double floorD = floor != null
             ? Math.abs(floor - wishKM)
             : Double.MAX_VALUE;
@@ -266,13 +287,33 @@
             ? Math.abs(ceil - wishKM)
             : Double.MAX_VALUE;
 
-        double km = floorD < ceilD ? floor : ceil;
+        double km;
+        if (floorD < ceilD) {
+            km = floor;
+        }
+        else {
+            km = ceil;
+        }
 
         // If we are too far from the wished km, return null.
         if (Math.abs(km - wishKM) > TOO_FAR) {
             return null;
         }
 
+        // Store next and previous km.
+        nextKm = kms.higherKey(km);
+        prevKm = kms.lowerKey(km);
+
+        if (prevKm == null) {
+            prevKm = -1d;
+        }
+        if (nextKm == null) {
+            nextKm = -1d;
+        }
+
+        addStringData(DATA_PREV_KM, prevKm.toString());
+        addStringData(DATA_NEXT_KM, nextKm.toString());
+
         return FastCrossSectionLineFactory
             .getCrossSectionLine(crossSection, km);
     }
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/ManualPointsArtifact.java	Tue Jul 10 13:26:13 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/ManualPointsArtifact.java	Tue Jul 10 15:31:56 2012 +0000
@@ -132,9 +132,12 @@
 
     /**
      * Get the water line "surface".
+     * @param index index of facets data.
+     * @param points 'ground' against which to determine water surface.
+     * @param data describing water surface.
      */
     @Override
-    public Lines.LineData getWaterLines(int index, FastCrossSectionLine csl) {
+    public Lines.LineData getWaterLines(int index, FastCrossSectionLine csl, double a, double b) {
         List<Point2D> points = csl.getPoints();
         return Lines.createWaterLines(points, getLine(index));
     }
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java	Tue Jul 10 13:26:13 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java	Tue Jul 10 15:31:56 2012 +0000
@@ -16,6 +16,7 @@
 import de.intevation.artifacts.Artifact;
 import de.intevation.artifacts.ArtifactFactory;
 import de.intevation.artifacts.CallMeta;
+import de.intevation.flys.artifacts.math.Distance;
 import de.intevation.flys.artifacts.math.Linear;
 
 import de.intevation.flys.artifacts.model.CrossSectionWaterLineFacet;
@@ -34,6 +35,7 @@
 
 import de.intevation.flys.model.FastCrossSectionLine;
 
+
 /**
  * Artifact to access additional "waterlevel"-type of data, like the height
  * of protective measures (dikes).
@@ -52,6 +54,11 @@
     public static final String STATIC_STATE_NAME =
         "state.additional_wkms.static";
 
+    /** Data Item name to know whether we are Heighmarks and reveive
+     * some data slightly different. */
+    public static final String DATA_HEIGHT_TYPE =
+        "height_marks";
+
     /** One and only state to be in. */
     protected transient State state = null;
 
@@ -110,6 +117,7 @@
                 String name;
                 if (parts[0].equals(HEIGHTMARKS_POINTS)) {
                     name = HEIGHTMARKS_POINTS;
+                    addStringData(DATA_HEIGHT_TYPE, "true");
                 }
                 else {
                     name = STATIC_WKMS;
@@ -266,6 +274,34 @@
 
 
     /**
+     * Get the W at a specific km, only if it is closer to km than to any of
+     * the other given km.
+     * Return Double.NaN otherwise
+     *
+     * @param wkms WKms in which to search for a spatially close W value.
+     * @param km the input km, which is compared to values from wkms.
+     * @param next the next available input km.
+     * @param prev the previous available input km.
+     *
+     * @return W in wkms that is closer to km than to next and prev, or Double.NaN.
+     */
+    public double getWAtCloseKm(WKms wkms, double km, double next, double prev) {
+        int size = wkms.size();
+        // TODO handle edge cases (with no next or prev).
+        for (int i = 0; i < size; i++) {
+            double wkmsKm = wkms.getKm(i);
+            double dist = Distance.distance(wkmsKm, km);
+            if ((prev != km && dist <= Distance.distance(wkmsKm, prev))
+                && dist <= Distance.distance(wkmsKm, next)) {
+                return wkms.getW(i);    
+            }
+        }
+
+        return Double.NaN;
+    }
+
+
+    /**
      * Returns W at Km of WKms, searching linearly.
      * Returns -1 if not found.
      * @param wkms the WKms object to search for given km.
@@ -273,10 +309,11 @@
      * @return W at given km if in WKms, -1 if not found.
      */
     public static double getWAtKm(WKms wkms, double km) {
-        // Uninformed search.
+        // Uninformed search, intolerant.
+        double TOLERANCE = 0.0d;
         int size = wkms.size();
         for (int i = 0; i < size; i++) {
-            if (wkms.getKm(i) == km) {
+            if (Distance.within(wkms.getKm(i), km, TOLERANCE)) {
                 return wkms.getW(i);
             }
         }
@@ -288,12 +325,19 @@
     /**
      * Get points of line describing the surface of water at cross section.
      *
+     * @param idx Index of facet and in wkms array.
+     * @param csl FastCrossSectionLine to compute water surface agains.
+     * @param next The km of the next crosssectionline.
+     * @param prev The km of the previous crosssectionline.
+     *
      * @return an array holding coordinates of points of surface of water (
      *         in the form {{x1, x2}, {y1, y2}} ).
      */
     @Override
-    public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl) {
-        logger.debug("getWaterLines(" + idx + ")");
+    public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl,
+        double next, double prev
+    ) {
+        logger.debug("getWaterLines(" + idx + ")/" + identifier());
 
         List<Point2D> points = csl.getPoints();
 
@@ -302,8 +346,18 @@
         double km = csl.getKm();
 
         // Find W at km.
-        double wAtKm = getWAtKm(wkms, km);
-        if (wAtKm == -1) {
+        double wAtKm;
+
+        // If heightmarks, only deliver if data snaps.
+        if (getDataAsString(DATA_HEIGHT_TYPE) != null &&
+            getDataAsString(DATA_HEIGHT_TYPE).equals("true")) {
+            wAtKm = getWAtCloseKm(wkms, km, next, prev);
+        }
+        else {
+            wAtKm = getWAtKm(wkms, km);
+        }
+
+        if (wAtKm == -1 || Double.isNaN(wAtKm)) {
             logger.warn("Waterlevel at km " + km + " unknown.");
             return new Lines.LineData(new double[][] {{}}, 0d, 0d);
         }
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java	Tue Jul 10 13:26:13 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java	Tue Jul 10 15:31:56 2012 +0000
@@ -209,7 +209,7 @@
      * in WstValueTable.
      *
      * @param kms The kilometer values.
-     * @param qa The discharge values.
+     * @param qs The discharge values.
      * @param wst The WstValueTable used for the interpolation.
      *
      * @return an array of data triples that consist of W, Q and Kms.
@@ -329,7 +329,8 @@
     /**
      * Computes the data used to create computed discharge curves.
      *
-     * @param wst The WstValueTable that is used for the interpolation.
+     * @param wst The WstValueTable that is used for the interpolation (river-
+     *            bound).
      * @param location The location where the computation should be based on.
      *
      * @return an object that contains tuples of W/Q values at the specified
@@ -346,6 +347,8 @@
         return calculation.calculate(wst);
     }
 
+
+    /** Create CalculationResult with data and message. */
     protected static final CalculationResult error(Object data, String msg) {
         return new CalculationResult(data, new Calculation(msg));
     }
@@ -580,12 +583,15 @@
      *
      * @param idx Index for getWaterlevelData.
      * @param csl The profile/surface to fill with water.
+     * @param nextIgnored Ignored in this implementation of WaterLineArtifact.
+     * @param prevIgnored Ignored in this implementation of WaterLineArtifact.
      *
      * @return an array holding coordinates of points of surface of water (
      *         in the form {{x1, x2} {y1, y2}} ).
      */
     @Override
-    public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl) {
+    public Lines.LineData getWaterLines(int idx, FastCrossSectionLine csl,
+        double nextIgnored, double prevIgnored) {
         logger.debug("getWaterLines(" + idx + ")");
 
         List<Point2D> points = csl.getPoints();
@@ -1188,8 +1194,9 @@
         DURATION_Q
     };
 
+
     /**
-     * Returns the WstValueTable.
+     * Returns the WstValueTable of current river.
      */
     public WstValueTable getWstValueTable() {
         River r = FLYSUtils.getRiver(this);
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java	Tue Jul 10 13:26:13 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WaterLineArtifact.java	Tue Jul 10 15:31:56 2012 +0000
@@ -9,6 +9,6 @@
 
     /** Get points that define a line of a (water)facet against a cross-
      * section. */
-    public Lines.LineData getWaterLines(int facetIdx, FastCrossSectionLine csl);
+    public Lines.LineData getWaterLines(int facetIdx, FastCrossSectionLine csl, double d, double w);
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionFacet.java	Tue Jul 10 13:26:13 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionFacet.java	Tue Jul 10 15:31:56 2012 +0000
@@ -25,6 +25,13 @@
     public static String BLACKBOARD_CS_MASTER_DATA
         = "crosssection.masterprofile.data";
 
+    public static String BLACKBOARD_CS_PREV_KM
+        = "crosssection.masterprofile.km.prev";
+
+    public static String BLACKBOARD_CS_NEXT_KM
+        = "crosssection.masterprofile.km.next";
+
+
     private static Logger logger = Logger.getLogger(CrossSectionFacet.class);
 
     protected ComputeType type;
@@ -43,6 +50,8 @@
         List keys = new ArrayList();
         if (artifact.isMaster()) {
             keys.add(BLACKBOARD_CS_MASTER_DATA);
+            keys.add(BLACKBOARD_CS_PREV_KM);
+            keys.add(BLACKBOARD_CS_NEXT_KM);
         }
         keys.add(artifact.identifier() + getIndex());
         keys.addAll(super.getStaticDataProviderKeys(art));
@@ -71,6 +80,12 @@
         else if (key.equals(artifact.identifier() + getIndex())) {
             return getData(artifact, context);
         }
+        else if (key.equals(BLACKBOARD_CS_NEXT_KM)) {
+            return crossSection.getNextKm();
+        }
+        else if (key.equals(BLACKBOARD_CS_PREV_KM)) {
+            return crossSection.getPrevKm();
+        }
         else {
             Object obj = super.provideBlackboardData(artifact, key, param,
                 context);
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java	Tue Jul 10 13:26:13 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/CrossSectionWaterLineFacet.java	Tue Jul 10 15:31:56 2012 +0000
@@ -24,7 +24,9 @@
 extends      BlackboardDataFacet
 implements   FacetTypes {
 
-    private static Logger logger = Logger.getLogger(CrossSectionWaterLineFacet.class);
+    /** Private logger to use. */
+    private static Logger logger =
+        Logger.getLogger(CrossSectionWaterLineFacet.class);
 
 
     /** Trivial constructor, set (maybe localized) description. */
@@ -33,13 +35,17 @@
     }
 
 
-    /** Trivial constructor, set (maybe localized) description. */
+    /**
+     * Trivial constructor, set (maybe localized) description.
+     * @param idx Index of this facet.
+     * @param name 'type' of this facet.
+     * @param description (maybe) localized user-visible description.
+     */
     public CrossSectionWaterLineFacet(int idx, String name, String description) {
         super(idx, name, description);
     }
 
 
-
     /**
      * Gets waterline (crossed with cross section) of waterlevel.
      */
@@ -54,13 +60,22 @@
         }
 
         Object crossSection = providers.get(0)
-            .provideData(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA, null, context);
+            .provideData(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA,
+                null, context);
+        Object nextKm = providers.get(0).
+            provideData(CrossSectionFacet.BLACKBOARD_CS_NEXT_KM, null, context);
+        Object prevKm = providers.get(0).
+            provideData(CrossSectionFacet.BLACKBOARD_CS_PREV_KM, null, context);
+        if (prevKm == null)
+            prevKm = new Double(-1d);
+        if (nextKm == null)
+            nextKm = new Double(-1d);
 
-        WaterLineArtifact winfo = (WaterLineArtifact)artifact;
+        WaterLineArtifact lineArtifact = (WaterLineArtifact) artifact;
 
         if (crossSection != null) {
-            return winfo.getWaterLines(this.getIndex(),
-                (FastCrossSectionLine) crossSection);
+            return lineArtifact.getWaterLines(this.getIndex(),
+                (FastCrossSectionLine) crossSection, (Double) nextKm, (Double) prevKm);
         }
         else {
             return new Lines.LineData(new double[][] {}, 0d,0d);

http://dive4elements.wald.intevation.org