# HG changeset patch # User mschaefer # Date 1531909201 -7200 # Node ID 465347d129907fab579c620aabd71f01299a42ac # Parent e5367900dd6d07d025eb3639303b1b046aa21685 Station specific calculation of flood duration curve and infrastructure annotations diff -r e5367900dd6d -r 465347d12990 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java Tue Jul 17 19:48:28 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java Wed Jul 18 12:20:01 2018 +0200 @@ -9,11 +9,14 @@ */ package org.dive4elements.river.artifacts.sinfo.flood_duration; +import java.util.List; + import org.apache.commons.lang.math.DoubleRange; import org.dive4elements.artifacts.CallContext; import org.dive4elements.river.artifacts.WINFOArtifact; import org.dive4elements.river.artifacts.model.Calculation; import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.WQDay; import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.artifacts.sinfo.SINFOArtifact; import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider; @@ -21,6 +24,7 @@ import org.dive4elements.river.artifacts.sinfo.tkhstate.WinfoArtifactWrapper; import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils; import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; +import org.dive4elements.river.jfree.StickyAxisAnnotation; import org.dive4elements.river.model.River; /** @@ -74,4 +78,40 @@ final FloodDurationCalculator calculator = new FloodDurationCalculator(this.context, riverInfoProvider); calculator.execute(problems, label, calcRange, riverside, winfo, results); } + + /** + * Calculates the flood duration curve of a station + */ + public WQDay calcStationCurve(final double station, final SINFOArtifact sinfo) { + + /* access input data */ + final FloodDurationAccess access = new FloodDurationAccess(sinfo); + final River river = access.getRiver(); + final DoubleRange calcRange = access.getRange(); + final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange); + + final Calculation problems = new Calculation(); + + // Calculate the selected main values, if any + /* misuse winfo-artifact to calculate waterlevels in the same way */ + final WINFOArtifact winfo = new WinfoArtifactWrapper(sinfo); + winfo.addStringData("ld_locations", Double.toString(station)); + + final FloodDurationCalculator calculator = new FloodDurationCalculator(this.context, infoProvider); + if (!Double.isNaN(station)) + return calculator.calcWQDays(problems, station, winfo); + else + return calculator.calcWQDays(problems, calcRange.getMinimumFloat(), winfo); + } + + /** + * Calculates the annotations of the infrastructure(s) of a station for a flood duration calculation + */ + public List calcInfrastructureAnnotations(final double station, final FloodDurationCalculationResult result) { + + final Calculation problems = new Calculation(); + + final FloodDurationCalculator calculator = new FloodDurationCalculator(this.context, null); + return calculator.calcInfrastructureAnnotations(problems, station, result); + } } \ No newline at end of file diff -r e5367900dd6d -r 465347d12990 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java Tue Jul 17 19:48:28 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java Wed Jul 18 12:20:01 2018 +0200 @@ -53,23 +53,23 @@ return this.mainValueQAnnotations; } - private StickyAxisAnnotation infrastructureWAnnotation; - - public StickyAxisAnnotation getInfrastructureWAnnotation() { - return this.infrastructureWAnnotation; - } - - public void setInfrastructureWAnnotation(final StickyAxisAnnotation infrastructureWAnnotation) { - this.infrastructureWAnnotation = infrastructureWAnnotation; - } - - private StickyAxisAnnotation infrastructureQAnnotation; - - public StickyAxisAnnotation getInfrastructureQAnnotation() { - return this.infrastructureQAnnotation; - } - - public void setInfrastructureQAnnotation(final StickyAxisAnnotation infrastructureQAnnotation) { - this.infrastructureQAnnotation = infrastructureQAnnotation; - } + // private StickyAxisAnnotation infrastructureWAnnotation; + // + // public StickyAxisAnnotation getInfrastructureWAnnotation() { + // return this.infrastructureWAnnotation; + // } + // + // public void setInfrastructureWAnnotation(final StickyAxisAnnotation infrastructureWAnnotation) { + // this.infrastructureWAnnotation = infrastructureWAnnotation; + // } + // + // private StickyAxisAnnotation infrastructureQAnnotation; + // + // public StickyAxisAnnotation getInfrastructureQAnnotation() { + // return this.infrastructureQAnnotation; + // } + // + // public void setInfrastructureQAnnotation(final StickyAxisAnnotation infrastructureQAnnotation) { + // this.infrastructureQAnnotation = infrastructureQAnnotation; + // } } \ No newline at end of file diff -r e5367900dd6d -r 465347d12990 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java Tue Jul 17 19:48:28 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java Wed Jul 18 12:20:01 2018 +0200 @@ -10,6 +10,7 @@ package org.dive4elements.river.artifacts.sinfo.flood_duration; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -118,18 +119,17 @@ mainValueLabels[i] = wqkmsArray[i].getName(); results.addResult(new FloodDurationCalculationResult(label, mainValueLabels, this.rows), problems); - calcWQDays(problems, stationsSorted[0], AttributeKey.LEFT, winfo, results); - - calcMainValueAnnotations(problems, 0, AttributeKey.LEFT, wqkmsArray, results); - - calcInfrastructureAnnotations(problems, this.rows.get(0), wqkmsArray, results); + // calcWQDays(problems, stationsSorted[0], AttributeKey.LEFT, winfo, results); + // + // calcMainValueAnnotations(problems, 0, AttributeKey.LEFT, wqkmsArray, results); + // + // calcInfrastructureAnnotations(problems, this.rows.get(0), wqkmsArray, results); } /** - * Calculate duration curve for a station and add to result collection + * Calculates the duration curve for a station */ - private void calcWQDays(final Calculation problems, final double station, final AttributeKey riverside, final WINFOArtifact winfo, - final FloodDurationCalculationResults results) { + public WQDay calcWQDays(final Calculation problems, final double station, final WINFOArtifact winfo) { // Same processing as in W-Info DurationCurveState winfo.addStringData("ld_locations", Double.toString(station)); @@ -144,13 +144,13 @@ ws[j] = underflow.getW(i); qs[j] = underflow.getQ(i); } - results.setDurationCurve(new WQDay(days, ws, qs)); + return new WQDay(days, ws, qs); } /** * Calculate the data for the W and Q main value lines in the duration curve chart and add to result collection */ - private void calcMainValueAnnotations(final Calculation problems, final int stationIndex, final AttributeKey riverside, + public void calcMainValueAnnotations(final Calculation problems, final int stationIndex, final AttributeKey riverside, final WQKms[] wqkmsArray, final FloodDurationCalculationResults results) { // Same way as in MainValueWFacet and ..QFacet, but special label handling @@ -178,28 +178,70 @@ * Calculate the data for the W and Q lines in the duration curve chart for the infrastructure height and add to result * collection */ - private void calcInfrastructureAnnotations(final Calculation problems, final ResultRow row, final WQKms[] wqkmsArray, - final FloodDurationCalculationResults results) { + public List calcInfrastructureAnnotations(final Calculation problems, final double station, + final FloodDurationCalculationResult result) { - if (row.getValue(SInfoResultType.infrastructuretype) == null) { - results.setInfrastructureWAnnotation(null); - results.setInfrastructureQAnnotation(null); - return; + // Search the station in the previously calculated result rows and terminate if no infrastructure row found + double station1 = station; + if (Double.isNaN(station)) { + for (final ResultRow row : result.getRows()) { + station1 = row.getDoubleValue(GeneralResultType.station); + break; + } + } + final List stationRows = searchStation(station1, result.getRows()); + if (stationRows.isEmpty() || (stationRows.get(0).getValue(SInfoResultType.infrastructuretype) == null)) { + return null; } // Same way as in MainValueWFacet and ..QFacet + final List annotations = new ArrayList<>(); + for (final ResultRow row : stationRows) { + annotations.add(calcWAnnotation(row)); + annotations.add(calcQAnnotation(row)); + } + return annotations; + } + + /** + * Searches the one or two rows of a station in a result rows collection + */ + private List searchStation(final double station, final Collection rows) { + final List found = new ArrayList<>(); + for (final ResultRow row : rows) { + if (row.getDoubleValue(GeneralResultType.station) > station + 0.0001) + break; + else if (row.getDoubleValue(GeneralResultType.station) > station - 0.0001) + found.add(row); + } + return found; + } + + /** + * Calculates the Q annotation lines of an infrastructure + */ + private StickyAxisAnnotation calcQAnnotation(final ResultRow row) { final String label = Resources.getMsg(this.context.getMeta(), "sinfo.chart.flood_duration.curve.infrastructure", "sinfo.chart.flood_duration.curve.infrastructure", SInfoResultType.infrastructuretype.exportValue(this.context, row.getValue(SInfoResultType.infrastructuretype)) + ", " + SInfoResultType.riverside.exportValue(this.context, row.getValue(SInfoResultType.riverside))); - final StickyAxisAnnotation qAnnotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.floodDischarge), + final StickyAxisAnnotation annotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.floodDischarge), SimpleAxis.Y_AXIS, FloodDurationCurveGenerator.YAXIS.Q.idx); - FloodDurationMainValuesQFacet.setHitPoint(results.getDurationCurve(), qAnnotation); - final StickyAxisAnnotation wAnnotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.infrastructureHeight), + annotation.setHitPoint((float) row.getDoubleValue(SInfoResultType.floodDuration)); + return annotation; + } + + /** + * Calculates the W annotation lines of an infrastructure + */ + private StickyAxisAnnotation calcWAnnotation(final ResultRow row) { + final String label = Resources.getMsg(this.context.getMeta(), "sinfo.chart.flood_duration.curve.infrastructure", + "sinfo.chart.flood_duration.curve.infrastructure", + SInfoResultType.infrastructuretype.exportValue(this.context, row.getValue(SInfoResultType.infrastructuretype)) + + ", " + SInfoResultType.riverside.exportValue(this.context, row.getValue(SInfoResultType.riverside))); + final StickyAxisAnnotation annotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.infrastructureHeight), SimpleAxis.Y_AXIS, FloodDurationCurveGenerator.YAXIS.W.idx); - FloodDurationMainValuesWFacet.setHitPoint(results.getDurationCurve(), wAnnotation); - - results.setInfrastructureQAnnotation(qAnnotation); - results.setInfrastructureWAnnotation(wAnnotation); + annotation.setHitPoint((float) row.getDoubleValue(SInfoResultType.floodDuration)); + return annotation; } /** diff -r e5367900dd6d -r 465347d12990 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveFacet.java Tue Jul 17 19:48:28 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveFacet.java Wed Jul 18 12:20:01 2018 +0200 @@ -17,6 +17,7 @@ import org.dive4elements.artifacts.CallContext; import org.dive4elements.river.artifacts.D4EArtifact; import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.sinfo.SINFOArtifact; import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; @@ -59,7 +60,8 @@ // TODO: entweder in data.getDurationCurve() reingeben, oder bei FloodDurationCalculationResults auswerten... // TODO: was ist aus perfromanz/speicher-sicht besser? - return data.getDurationCurve(); + // return data.getDurationCurve(); + return new FloodDurationCalculation(context).calcStationCurve(currentKm, (SINFOArtifact) flys); } /** diff -r e5367900dd6d -r 465347d12990 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationInfrastructureFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationInfrastructureFacet.java Tue Jul 17 19:48:28 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationInfrastructureFacet.java Wed Jul 18 12:20:01 2018 +0200 @@ -10,7 +10,8 @@ package org.dive4elements.river.artifacts.sinfo.flood_duration; -import java.util.ArrayList; +import static org.dive4elements.river.exports.injector.InjectorConstants.CURRENT_KM; + import java.util.List; import org.apache.log4j.Logger; @@ -60,17 +61,42 @@ final FloodDurationCalculationResults data = (FloodDurationCalculationResults) res.getData(); - final List annotations = new ArrayList<>(); - annotations.add(data.getInfrastructureWAnnotation()); - annotations.add(data.getInfrastructureQAnnotation()); - if (annotations.get(0) != null) { - this.description = annotations.get(0).getText(); // TODO Diagramm-Aktualisierung auslösen + // final List annotations = new ArrayList<>(); + // annotations.add(data.getInfrastructureWAnnotation()); + // annotations.add(data.getInfrastructureQAnnotation()); + + final double currentKm = getCurrentKm(context); + + final List annotations = new FloodDurationCalculation(context).calcInfrastructureAnnotations(currentKm, + data.getResults().get(this.index)); + if (annotations != null) { return new RiverAnnotation(this.description, annotations); } else return null; } + /** + * Returns the current km from the context. + * If the context is null or doesn't contain a currentKm + * then a double value of -1 will be returned. + * + * @param context + * The CallContext instance + * @return the current km as double + */ + // FIXME: copied from org.dive4elements.river.artifacts.model.fixings.FixingsFacet + private double getCurrentKm(final CallContext context) { + if (context == null) + return Double.NaN; + + final Double dkm = (Double) context.getContextValue(CURRENT_KM); + if (dkm == null) + return Double.NaN; + + return dkm.doubleValue(); + } + /** * Create a deep copy of this Facet. diff -r e5367900dd6d -r 465347d12990 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationMainValuesWFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationMainValuesWFacet.java Tue Jul 17 19:48:28 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationMainValuesWFacet.java Wed Jul 18 12:20:01 2018 +0200 @@ -8,6 +8,8 @@ package org.dive4elements.river.artifacts.sinfo.flood_duration; +import static org.dive4elements.river.exports.injector.InjectorConstants.CURRENT_KM; + import org.apache.log4j.Logger; import org.dive4elements.artifactdatabase.state.DefaultFacet; import org.dive4elements.artifacts.Artifact; @@ -71,9 +73,32 @@ final FloodDurationCalculationResults data = (FloodDurationCalculationResults) res.getData(); + final double currentKm = getCurrentKm(context); + return new RiverAnnotation(this.description, data.getMainValueWAnnotations()); } + /** + * Returns the current km from the context. + * If the context is null or doesn't contain a currentKm + * then a double value of -1 will be returned. + * + * @param context + * The CallContext instance + * @return the current km as double + */ + // FIXME: copied from org.dive4elements.river.artifacts.model.fixings.FixingsFacet + private double getCurrentKm(final CallContext context) { + if (context == null) + return Double.NaN; + + final Double dkm = (Double) context.getContextValue(CURRENT_KM); + if (dkm == null) + return Double.NaN; + + return dkm.doubleValue(); + } + /** * Create a deep copy of this Facet.