d@9612: /** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde d@9612: * Software engineering by d@9612: * Björnsen Beratende Ingenieure GmbH d@9612: * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt d@9612: * d@9612: * This file is Free Software under the GNU AGPL (>=v3) d@9612: * and comes with ABSOLUTELY NO WARRANTY! Check out the d@9612: * documentation coming with Dive4Elements River for details. d@9612: */ d@9612: package org.dive4elements.river.artifacts.sinfo.flood_duration; d@9612: d@9612: import java.util.ArrayList; d@9612: import java.util.Collection; d@9612: import java.util.Collections; d@9612: import java.util.List; d@9612: d@9612: import org.dive4elements.artifacts.CallContext; d@9612: import org.dive4elements.river.artifacts.common.GeneralResultType; d@9612: import org.dive4elements.river.artifacts.common.ResultRow; d@9612: import org.dive4elements.river.artifacts.model.Calculation; d@9612: import org.dive4elements.river.artifacts.resources.Resources; d@9612: import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType; d@9612: import org.dive4elements.river.jfree.StickyAxisAnnotation; d@9612: import org.dive4elements.river.jfree.StickyAxisAnnotation.SimpleAxis; d@9612: import org.dive4elements.river.model.Attribute.AttributeKey; d@9612: d@9612: /** d@9612: * @author Domenico Nardi Tironi d@9612: * d@9612: */ d@9612: public class FacetCalculator { d@9612: d@9612: private static final double DELTA_KM = 0.0001; d@9612: d@9612: private final CallContext m_context; d@9612: d@9612: public FacetCalculator(final CallContext context) { d@9612: this.m_context = context; d@9612: } d@9612: d@9612: /** d@9612: * Calculates the data for the W main value lines in the duration curve chart d@9612: */ d@9612: public List calcMainValueWAnnotations(final Calculation problems, final double station, final FloodDurationCalculationResult result) { d@9612: d@9612: final List stationRows = searchStation(station, result.getAllRows(), AttributeKey.NONE); d@9612: if (stationRows.isEmpty()) d@9612: return Collections.emptyList(); d@9612: d@9612: final List annotations = new ArrayList<>(); d@9612: final ResultRow row = stationRows.get(0); d@9612: final List wqds = (List) row.getValue(SInfoResultType.customMultiRowColWaterlevel); d@9612: for (final DurationWaterlevel wqd : wqds) { d@9612: final String label = !wqd.getBezeichnung().startsWith("W=") ? "W(" + wqd.getBezeichnung() + ")" : wqd.getBezeichnung(); d@9612: final StickyAxisAnnotation annotation = new StickyAxisAnnotation(label, (float) wqd.getWaterlevel(), SimpleAxis.Y_AXIS, d@9612: FloodDurationCurveGenerator.YAXIS.W.idx); d@9612: annotation.setHitPoint((float) wqd.getFloodDurDaysPerYear()); d@9612: annotations.add(annotation); d@9612: } d@9612: return annotations; d@9612: } d@9612: d@9612: /** d@9612: * Calculates the data for the Q main value lines in the duration curve chart d@9612: * d@9612: * @param infrastructure d@9612: */ d@9612: public List calcMainValueQAnnotations(final Calculation problems, final double station, final FloodDurationCalculationResult result) { d@9612: d@9612: final List stationRows = searchStation(station, result.getAllRows(), AttributeKey.NONE); d@9612: if (stationRows.isEmpty()) d@9612: return Collections.emptyList(); d@9612: d@9612: final ResultRow row = stationRows.get(0); d@9612: final List annotations = new ArrayList<>(); d@9612: final List wqds = (List) row.getValue(SInfoResultType.customMultiRowColWaterlevel); d@9612: for (final DurationWaterlevel wqd : wqds) { d@9612: final String label = wqd.getBezeichnung().startsWith("W=") ? "Q(" + wqd.getBezeichnung() + ")" : wqd.getBezeichnung(); d@9612: final StickyAxisAnnotation annotation = new StickyAxisAnnotation(label, (float) wqd.getDischarge(), SimpleAxis.Y_AXIS, d@9612: FloodDurationCurveGenerator.YAXIS.Q.idx); d@9612: annotation.setHitPoint((float) wqd.getFloodDurDaysPerYear()); d@9612: annotations.add(annotation); d@9612: } d@9612: return annotations; d@9612: } d@9612: d@9612: /** d@9612: * Find and return the W or Q annotation(s) of a station and a riverside in a previously calculated result d@9612: * d@9612: * @param key d@9612: */ d@9612: public List calcInfrastructureAnnotations(final Calculation problems, final double station, final boolean isW, d@9612: final FloodDurationCalculationResult result, final AttributeKey riverside) { d@9612: d@9612: final List stationRows = searchStation(station, result.getAllRows(), riverside); d@9612: if (stationRows.isEmpty()) d@9612: return Collections.emptyList(); d@9612: d@9612: // Same way as in MainValueWFacet and ..QFacet d@9612: final List annotations = new ArrayList<>(); d@9612: for (final ResultRow row : stationRows) { d@9612: if (isW) d@9612: annotations.add(calcInfrastructureWAnnotation(row)); d@9612: else d@9612: annotations.add(calcInfrastructureQAnnotation(row)); d@9612: } d@9612: return annotations; d@9612: } d@9612: d@9612: /** d@9612: * Calculates the Q annotation lines of an infrastructure d@9612: */ d@9612: private StickyAxisAnnotation calcInfrastructureQAnnotation(final ResultRow row) { d@9612: final String label = Resources.getMsg(this.m_context.getMeta(), "sinfo.chart.flood_duration.curve.infrastructure", mschaefer@9614: "sinfo.chart.flood_duration.curve.infrastructure", getInfrastructureLabel(row)); d@9612: final StickyAxisAnnotation annotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.floodDischarge), SimpleAxis.Y_AXIS, d@9612: FloodDurationCurveGenerator.YAXIS.Q.idx); d@9612: annotation.setHitPoint((float) row.getDoubleValue(SInfoResultType.floodDuration)); d@9612: return annotation; d@9612: } d@9612: d@9612: /** d@9612: * Calculates the W annotation lines of an infrastructure d@9612: */ d@9612: private StickyAxisAnnotation calcInfrastructureWAnnotation(final ResultRow row) { d@9612: final String label = Resources.getMsg(this.m_context.getMeta(), "sinfo.chart.flood_duration.curve.infrastructure", mschaefer@9614: "sinfo.chart.flood_duration.curve.infrastructure", getInfrastructureLabel(row)); d@9612: final StickyAxisAnnotation annotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.infrastructureHeight), d@9612: SimpleAxis.Y_AXIS, FloodDurationCurveGenerator.YAXIS.W.idx); d@9612: annotation.setHitPoint((float) row.getDoubleValue(SInfoResultType.floodDuration)); d@9612: return annotation; d@9612: } d@9612: d@9612: /** mschaefer@9614: * Builds the label of the type and bank location of the infrastructure of a result row mschaefer@9614: */ mschaefer@9614: private String getInfrastructureLabel(final ResultRow row) { mschaefer@9614: return SInfoResultType.getInfrastructureLabel(this.m_context, (String) row.getValue(SInfoResultType.infrastructuregroup), mschaefer@9614: (String) row.getValue(SInfoResultType.infrastructuretype), (AttributeKey) row.getValue(SInfoResultType.riverside)); mschaefer@9614: } mschaefer@9614: mschaefer@9614: /** d@9612: * Searches the one or two rows of a station in a result rows collection d@9612: * d@9612: * @param m_riverside d@9612: */ d@9612: private List searchStation(final double station, final Collection rows, final AttributeKey riverside) { d@9612: d@9612: final double searchStation = findSearchStation(rows, station, riverside); d@9612: if (Double.isNaN(searchStation)) d@9612: return Collections.emptyList(); d@9612: d@9612: final List found = new ArrayList<>(); d@9612: d@9612: for (final ResultRow row : rows) { // rows are not sorted d@9612: final String riversideStr = String.valueOf(row.getValue(SInfoResultType.riverside)); d@9612: if (riversideStr.equals("null")) d@9612: continue; d@9612: d@9612: if (Math.abs(row.getDoubleValue(GeneralResultType.station) - station) > DELTA_KM) d@9612: continue; d@9612: d@9612: if (riverside.equals(AttributeKey.NONE) || riverside.equals(AttributeKey.valueOf(String.valueOf(row.getValue(SInfoResultType.riverside))))) d@9612: found.add(row); d@9612: } d@9612: return found; d@9612: } d@9612: d@9612: @Deprecated d@9612: private double findSearchStation(final Collection rows, final double station, final AttributeKey riverside) { d@9612: d@9612: if (!Double.isNaN(station)) d@9612: return station; d@9612: d@9612: for (final ResultRow row : rows) { d@9612: final String riversideStr = String.valueOf(row.getValue(SInfoResultType.riverside)); d@9612: if (riversideStr.equals("null")) d@9612: continue; d@9612: d@9612: if (riverside.equals(AttributeKey.NONE) || riverside.equals(AttributeKey.valueOf(riversideStr))) d@9612: return row.getDoubleValue(GeneralResultType.station); d@9612: } d@9612: d@9612: return Double.NaN; d@9612: } d@9612: }