# HG changeset patch # User Felix Wolfsteller # Date 1371807670 -7200 # Node ID df1a3826c691c8a093d1910363b758b5f825d4b5 # Parent dc23ffb9d82ccd81fe0ec40eedad368cffe93e29 SedimentLoadCalculation: Calculate and set Total Load values ind a brutal range merging manner. diff -r dc23ffb9d82c -r df1a3826c691 artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadCalculation.java --- 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);