changeset 6381:df1a3826c691

SedimentLoadCalculation: Calculate and set Total Load values ind a brutal range merging manner.
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Fri, 21 Jun 2013 11:41:10 +0200
parents dc23ffb9d82c
children 43ef4943e0c2
files artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadCalculation.java
diffstat 1 files changed, 170 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadCalculation.java	Fri Jun 21 11:34:22 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadCalculation.java	Fri Jun 21 11:41:10 2013 +0200
@@ -18,6 +18,7 @@
 import org.dive4elements.river.artifacts.access.SedimentLoadAccess;
 import org.dive4elements.river.artifacts.model.Calculation;
 import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.Range;
 
 
 /** Calculate sediment load. */
@@ -292,40 +293,181 @@
             logger.warn("Some problem, not calculating total load.");
             return load;
         }
-        double nextStep = 0;
-        for(double km : load.getKms()) {
+        return partialTotal(load);
+    }
+
+
+    /** Returns true if all fraction values except SuspSediment are unset. */
+    private boolean hasOnlySuspSediment(SedimentLoadFraction fraction) {
+        return (fraction.getSuspSediment() != 0d &&
+            fraction.getCoarse() == 0d &&
+            fraction.getFineMiddle() == 0d &&
+            fraction.getSand() == 0d &&
+            fraction.getSuspSand() == 0d);
+    }
+
+
+    /** Returns true if all fraction values except SuspSediment are set. */
+    private boolean hasButSuspSediment(SedimentLoadFraction fraction) {
+        return (fraction.getSuspSediment() == 0d &&
+            fraction.getCoarse() != 0d &&
+            fraction.getFineMiddle() != 0d &&
+            fraction.getSand() != 0d &&
+            fraction.getSuspSand() != 0d);
+    }
+
+
+    /** Returns true if all fraction needed for total calculation are set. */
+    private boolean complete(SedimentLoadFraction fraction) {
+        return (fraction.getCoarse() != 0d &&
+                fraction.getFineMiddle() != 0d &&
+                fraction.getSand() != 0d &&
+                fraction.getSuspSand() != 0d &&
+                fraction.getSuspSediment() != 0d);
+    }
+
+
+    /**
+     * Set total values in load.
+     * Therefore, run over the kms and find ranges where either all
+     * or all Geschiebe or just the Schwebstoff fractions are set.
+     * Merge these ranges and add (maybe new) respective fractions to
+     * load.
+     * @param load SedimentLoad to add total values (and ranges) to.
+     * @return input param load.
+     */
+    private SedimentLoad partialTotal(SedimentLoad load) {
+        SedimentLoad fairLoad = load;
+
+        Range lastOtherRange = null;
+        double lastOtherValue = 0d;
+
+        Range lastSuspSedimentRange = null;
+        double lastSuspSedimentValue = 0d;
+
+        for (double km: load.getKms()) {
+            logger.debug ("Trying to add at km " + km);
             SedimentLoadFraction fraction = load.getFraction(km);
-            double total = 0d;
-            if ((fraction.getCoarse() <= 0d && load.hasCoarse())){
-                addProblem(km, "missing.data.coarse");
-                continue;
-            }
-            if (fraction.getFineMiddle() <= 0d && load.hasFineMiddle()) {
-                addProblem(km, "missing.data.fine_middle");
-                continue;
-            }
-            if (fraction.getSand() <= 0d && load.hasSand()) {
-                addProblem(km, "missing data.sand");
-                continue;
+            if (complete(fraction)) {
+                double total = fraction.getCoarse() +
+                    fraction.getFineMiddle() +
+                    fraction.getSand() +
+                    fraction.getSuspSand() +
+                    fraction.getSuspSediment();
+                // Easiest case. Add values up and set'em.
+                if (fraction.getCoarseRange().equals(
+                    fraction.getSuspSedimentRange())) {
+                    lastOtherRange = null;
+                    lastSuspSedimentRange = null;
+                    fairLoad.setTotal(km, total, fraction.getCoarseRange());
+                }
+                else {
+                    // Need to split a range.
+                    if (fraction.getCoarseRange().getEnd()
+                        < fraction.getSuspSedimentRange().getEnd()) {
+                        // Schwebstoff is longer.
+                        // Adjust and remember schwebstoffs range and value.
+                        lastSuspSedimentRange = (Range) fraction.getSuspSedimentRange().clone();
+                        lastSuspSedimentRange.setStart(fraction.getCoarseRange().getEnd());
+                        lastSuspSedimentValue = fraction.getSuspSediment();
+                        lastOtherRange = null;
+                        fairLoad.setTotal(km, total, fraction.getCoarseRange());
+                    }
+                    else {
+                        // Geschiebe is longer.
+                        // Adjust and remember other values.
+                        lastOtherRange = (Range) fraction.getSuspSedimentRange().clone();
+                        lastOtherRange.setStart(fraction.getSuspSedimentRange().getEnd());
+                        lastOtherValue = (total - fraction.getSuspSediment());
+                        lastSuspSedimentRange = null;
+                        fairLoad.setTotal(km, total, fraction.getSuspSedimentRange());
+                    }
+                }
             }
-            if (fraction.getSuspSand() <= 0d && load.hasSuspSand()) {
-                addProblem(km, "missing.data.susp_sand");
-                continue;
-            }
-            if (fraction.getSuspSediment() <= 0d && load.hasSuspSediment()) {
-                addProblem(km, "missing.data.susp_sediment");
-                continue;
+            else if (hasOnlySuspSediment(fraction) && lastOtherRange != null) {
+                // Split stuff.
+                Range suspSedimentRange = fraction.getSuspSedimentRange();
+                // if intersects with last other range, cool! merge and add!
+                if (lastOtherRange.contains(km)) {
+                    double maxStart = 0d;
+                    double minEnd = 0d;
+                    maxStart = Math.max(suspSedimentRange.getStart(),
+                        lastOtherRange.getStart());
+
+                    minEnd = Math.min(suspSedimentRange.getEnd(),
+                        lastOtherRange.getEnd());
+                    double total = lastOtherValue + fraction.getSuspSediment();
+                    Range totalRange = new Range(maxStart, minEnd);
+                    if (suspSedimentRange.getEnd() > lastOtherRange.getEnd()) {
+                        lastSuspSedimentRange = (Range) suspSedimentRange.clone();
+                        lastSuspSedimentRange.setStart(lastOtherRange.getEnd());
+                        lastSuspSedimentValue = fraction.getSuspSediment();
+                        lastOtherRange = null;
+                    }
+                    else {
+                        // Other is "longer".
+                        lastOtherRange.setStart(suspSedimentRange.getEnd());
+                        lastSuspSedimentRange = null;
+                    }
+                    if (Math.abs(suspSedimentRange.getEnd() - lastOtherRange.getEnd()) < 0.1d) {
+                        lastOtherRange = null;
+                        lastSuspSedimentRange = null;
+                    }
+                    fairLoad.setTotal(km, total + fraction.getSuspSediment(), totalRange);
+                }
+                else {
+                    lastSuspSedimentRange = suspSedimentRange;
+                    lastSuspSedimentValue = fraction.getSuspSediment();
+                    lastOtherRange = null;
+                }
             }
-            total += fraction.getCoarse() +
-                fraction.getFineMiddle() +
-                fraction.getSand() +
-                fraction.getSuspSand() +
-                fraction.getSuspSediment();
-            load.setTotal(km, total, fraction.getTotalRange());
+            else if (hasButSuspSediment(fraction) && lastSuspSedimentRange != null) {
+                // If intersects with last suspsed range, merge and add
+                double total = fraction.getCoarse() +
+                    fraction.getFineMiddle() +
+                    fraction.getSand() +
+                    fraction.getSuspSand() +
+                    lastSuspSedimentValue;
+                double maxStart = Math.max(fraction.getCoarseRange().getStart(),
+                    lastSuspSedimentRange.getStart());
+                if (lastSuspSedimentRange.contains(km)) {
+                    double minEnd = Math.min(fraction.getCoarseRange().getEnd(),
+                        lastSuspSedimentRange.getEnd());
+                    Range totalRange = new Range(maxStart, minEnd);
+                    if (lastSuspSedimentRange.getEnd() > fraction.getCoarseRange().getEnd()) {
+                        // SuspSed longer.
+                        lastSuspSedimentRange.setStart(fraction.getCoarseRange().getEnd());
+                        lastOtherRange = null;
+                    }
+                    else {
+                        // Other longer
+                        lastOtherRange = (Range) fraction.getCoarseRange().clone();
+                        lastOtherRange.setStart(lastSuspSedimentRange.getEnd());
+                        lastSuspSedimentRange = null;
+                        lastOtherValue = total - lastSuspSedimentValue;
+                    }
+                    if (Math.abs(lastSuspSedimentRange.getEnd() - lastOtherRange.getEnd()) < 0.1d) {
+                        lastOtherRange = null;
+                        lastSuspSedimentRange = null;
+                    }
+                    fairLoad.setTotal(km, total, totalRange);
+                }
+                else {
+                    // Ranges are disjoint.
+                    lastOtherRange = fraction.getCoarseRange();
+                    lastOtherValue = total - fraction.getSuspSediment();
+                    lastSuspSedimentRange = null;
+                }
+            }
+            else {
+                // Some values are missing or no intersection with former values.
+                // Stay as we are.
+            }
         }
-        return load;
+        return fairLoad;
     }
 
+
     private SedimentLoad calculateUnit(SedimentLoad load, int year) {
         SedimentDensity density =
             SedimentDensityFactory.getSedimentDensity(river, kmLow, kmUp, year);

http://dive4elements.wald.intevation.org