teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.exports; ingo@1679: teichmann@5831: import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; teichmann@5831: import org.dive4elements.artifactdatabase.state.Facet; teichmann@5867: import org.dive4elements.river.artifacts.D4EArtifact; teichmann@5831: import org.dive4elements.river.artifacts.StaticWKmsArtifact; teichmann@5831: import org.dive4elements.river.artifacts.WINFOArtifact; teichmann@5831: import org.dive4elements.river.artifacts.model.FacetTypes; teichmann@5831: import org.dive4elements.river.artifacts.model.WKms; teichmann@5831: import org.dive4elements.river.artifacts.model.WQKms; rrenkert@8181: import org.dive4elements.river.exports.process.MiscDischargeProcessor; teichmann@5864: import org.dive4elements.river.jfree.RiverAnnotation; teichmann@5831: import org.dive4elements.river.jfree.StickyAxisAnnotation; teichmann@5831: import org.dive4elements.river.jfree.StyledXYSeries; felix@1850: teichmann@6905: import org.dive4elements.river.themes.ThemeDocument; teichmann@5865: import org.dive4elements.river.utils.RiverUtils; felix@5420: christian@3409: import java.util.ArrayList; christian@3409: import java.util.List; christian@3409: felix@6423: import org.jfree.data.xy.XYSeries; felix@6423: christian@3409: import org.apache.log4j.Logger; felix@6423: ingo@392: ingo@392: /** felix@6879: * An OutGenerator that generates discharge curves, also at locations felix@6879: * not at a gauge. ingo@392: * ingo@392: * @author Ingo Weinzierl ingo@392: */ ingo@696: public class ComputedDischargeCurveGenerator ingo@696: extends DischargeCurveGenerator ingo@696: implements FacetTypes ingo@696: { teichmann@8202: /** The log used in this generator. */ teichmann@8202: private static Logger log = ingo@392: Logger.getLogger(ComputedDischargeCurveGenerator.class); ingo@392: ingo@408: public static final String I18N_CHART_TITLE = ingo@408: "chart.computed.discharge.curve.title"; ingo@408: ingo@414: public static final String I18N_CHART_SUBTITLE = ingo@414: "chart.computed.discharge.curve.subtitle"; ingo@414: ingo@408: public static final String I18N_YAXIS_LABEL = ingo@408: "chart.computed.discharge.curve.yaxis.label"; ingo@408: ingo@408: public static final String I18N_CHART_TITLE_DEFAULT = "Abflusskurve"; ingo@408: public static final String I18N_YAXIS_LABEL_DEFAULT = "W [NN + m]"; ingo@408: felix@1083: /** Trivial Constructor. */ felix@1083: public ComputedDischargeCurveGenerator () { felix@1083: super(); felix@1083: } felix@1083: ingo@408: ingo@392: @Override ingo@2048: protected String getDefaultChartTitle() { ingo@408: return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); ingo@400: } ingo@400: ingo@400: ingo@400: @Override ingo@2048: protected String getDefaultChartSubtitle() { felix@1113: double[] dist = getRange(); ingo@414: ingo@414: Object[] args = new Object[] { ingo@414: getRiverName(), ingo@414: dist[0] ingo@414: }; ingo@414: ingo@1989: return msg(I18N_CHART_SUBTITLE, "", args); ingo@1989: } ingo@1989: ingo@1989: felix@6423: ingo@1989: @Override ingo@2051: protected String getDefaultYAxisLabel(int pos) { teichmann@5867: D4EArtifact flys = (D4EArtifact) master; felix@5420: teichmann@5865: String unit = RiverUtils.getRiver(flys).getWstUnit().getName(); felix@6454: if (pos == 0 && getCurrentGaugeDatum() != 0) felix@6446: unit = "cm"; felix@5420: felix@5420: return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT, new Object[] { unit }); ingo@400: } ingo@400: felix@6424: /** felix@2731: * Process data, build up plot. felix@2731: */ ingo@400: @Override ingo@1684: public void doOut( felix@1944: ArtifactAndFacet artifactFacet, teichmann@6905: ThemeDocument attr, felix@1944: boolean visible ingo@1684: ) { felix@1944: String name = artifactFacet.getFacetName(); ingo@393: teichmann@8202: log.debug("ComputedDischargeCurveGenerator.doOut: " + name); ingo@393: felix@1085: if (name == null) { teichmann@8202: log.warn("Broken facet in computed discharge out generation."); felix@1085: return; felix@1085: } felix@1085: rrenkert@8181: MiscDischargeProcessor dProcessor = new MiscDischargeProcessor(getRange()[0]); felix@6901: if (dProcessor.canHandle(name)) { felix@6901: dProcessor.doOut(this, artifactFacet, attr, visible, YAXIS.W.idx); felix@6901: } felix@6901: else if (name.equals(COMPUTED_DISCHARGE_Q)) { felix@6429: doDischargeQOut((WQKms) artifactFacet.getData(context), artifactFacet, attr, visible); ingo@696: } felix@1901: else if (name.equals(STATIC_WQ)) { ingo@2605: doWQOut(artifactFacet.getData(context), artifactFacet, attr, visible); felix@1901: } felix@1915: else if (name.equals(STATIC_WQ_ANNOTATIONS)) { ingo@2325: doWQAnnotations( ingo@2325: artifactFacet.getData(context), ingo@2325: artifactFacet, ingo@2325: attr, ingo@2325: visible); felix@1915: } felix@6790: else if (STATIC_WKMS_INTERPOL.equals(name) || felix@6790: HEIGHTMARKS_POINTS.equals(name) || felix@6790: STATIC_WQKMS_W.equals(name)) { ingo@2325: doWAnnotations( ingo@2325: artifactFacet.getData(context), ingo@2325: artifactFacet, ingo@2325: attr, ingo@2325: visible); felix@1921: } felix@2769: else if (name.equals(STATIC_WKMS)) { felix@2769: doWAnnotations( felix@2769: artifactFacet.getData(context), felix@2769: artifactFacet, felix@2769: attr, felix@2769: visible); felix@2769: } felix@2206: else if (FacetTypes.IS.MANUALPOINTS(name)) { felix@2206: doPoints(artifactFacet.getData(context), ingo@2325: artifactFacet, felix@2206: attr, visible, YAXIS.W.idx); felix@2206: } felix@2731: else if (name.equals(DISCHARGE_CURVE)) { felix@2731: doDischargeOut( felix@2731: (WINFOArtifact) artifactFacet.getArtifact(), felix@2731: artifactFacet.getData(context), felix@2731: artifactFacet.getFacetDescription(), felix@2731: attr, felix@2731: visible); felix@2731: } ingo@696: else { teichmann@8202: log.warn("Unknown facet type for computed discharge: " + name); ingo@696: return; ingo@696: } ingo@696: } ingo@696: felix@2206: felix@1901: /** felix@1901: * Add WQ Data to plot. felix@6789: * @param wq data as double[][] felix@1901: */ felix@1901: protected void doWQOut( felix@6789: Object wq, ingo@2605: ArtifactAndFacet aaf, teichmann@6905: ThemeDocument theme, ingo@2605: boolean visible felix@1901: ) { teichmann@8202: log.debug("ComputedDischargeCurveGenerator: doWQOut"); ingo@2605: XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); felix@7623: if (wq instanceof double[][]) { felix@7623: double [][] data = (double [][]) wq; felix@7623: StyledSeriesBuilder.addPoints(series, data, true); felix@7623: } else if (wq instanceof WQKms) { felix@7623: WQKms wqkms = (WQKms) wq; felix@7623: StyledSeriesBuilder.addPointsQW(series, (WQKms) wq); felix@7623: } felix@1902: felix@1933: addAxisSeries(series, YAXIS.W.idx, visible); felix@1901: } ingo@696: felix@1944: felix@1083: /** felix@6429: * Add discharge Q-Series to plot, scale if at gauge. felix@6429: * @param wqkms actual data felix@6429: * @param theme theme to use. felix@6429: */ felix@6429: protected void doDischargeQOut( felix@6429: WQKms wqkms, felix@6429: ArtifactAndFacet aaf, teichmann@6905: ThemeDocument theme, felix@6429: boolean visible felix@6429: ) { teichmann@8202: log.debug("ComputedDischargeCurveGenerator: doDischargeQOut"); felix@6429: XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); felix@6429: felix@6445: double subtractPNP = getCurrentGaugeDatum(); felix@6429: felix@6445: if (subtractPNP == 0d) { felix@6429: StyledSeriesBuilder.addPointsQW(series, wqkms); felix@6429: addAxisSeries(series, YAXIS.W.idx, visible); felix@6429: } felix@6429: else { felix@6429: XYSeries series2 = new StyledXYSeries(aaf.getFacetDescription(), theme); felix@6429: StyledSeriesBuilder.addPointsQW(series2, wqkms); felix@6429: addAxisSeries(series2, YAXIS.W.idx, false); felix@6429: felix@6429: // Use second axis... felix@6429: StyledSeriesBuilder.addPointsQW(series, wqkms, -subtractPNP, 100d); felix@6429: addAxisSeries(series, YAXIS.WCm.idx, visible); felix@6429: } felix@6429: } felix@6429: felix@6429: felix@6429: /** felix@6464: * Add W/Q-Series to plot. felix@1083: * @param wqkms actual data felix@1083: * @param theme theme to use. felix@1083: */ ingo@1712: protected void doQOut( ingo@2605: WQKms wqkms, ingo@2605: ArtifactAndFacet aaf, teichmann@6905: ThemeDocument theme, ingo@2605: boolean visible ingo@1712: ) { teichmann@8202: log.debug("ComputedDischargeCurveGenerator: doQOut (add W/Q data)."); ingo@2605: XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); felix@1902: StyledSeriesBuilder.addPointsQW(series, wqkms); ingo@393: felix@1933: addAxisSeries(series, YAXIS.W.idx, visible); ingo@393: } felix@1915: felix@1915: felix@1915: /** felix@1915: * Add WQ-Annotations to plot. felix@1915: * @param wqkms actual data felix@1915: * @param theme theme to use. felix@1915: */ felix@1915: protected void doWQAnnotations( felix@1915: Object wqkms, ingo@2325: ArtifactAndFacet aandf, teichmann@6905: ThemeDocument theme, felix@1915: boolean visible felix@1915: ) { felix@2161: List xy = new ArrayList(); felix@1915: double [][] data = (double [][]) wqkms; felix@1915: for (int i = 0; i< data[0].length; i++) { felix@3054: // TODO we need linear interpolation? ingo@2325: xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), felix@1915: (float) data[0][i], StickyAxisAnnotation.SimpleAxis.X_AXIS)); ingo@2325: xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), felix@1915: (float) data[1][i], StickyAxisAnnotation.SimpleAxis.Y_AXIS)); felix@1915: } felix@1915: teichmann@5864: doAnnotations(new RiverAnnotation(aandf.getFacetDescription(), xy), ingo@2325: aandf, theme, visible); felix@1915: } felix@1921: felix@1944: felix@1921: /** felix@1921: * Add W-Annotations to plot. felix@2570: * @param wqkms actual data (double[][]). felix@1921: * @param theme theme to use. felix@1921: */ felix@1921: protected void doWAnnotations( felix@1921: Object wqkms, ingo@2325: ArtifactAndFacet aandf, teichmann@6905: ThemeDocument theme, felix@1921: boolean visible felix@1921: ) { ingo@2325: Facet facet = aandf.getFacet(); ingo@2325: felix@2161: List xy = new ArrayList(); felix@2731: // Try to find them as WKms as well... felix@2731: if (wqkms instanceof double[][]) { teichmann@8202: log.debug("its double[][] time, baby"); felix@2731: double [][] data = (double [][]) wqkms; felix@3054: // TODO Do we need interpolation? felix@2731: for (int i = 0; i< data[0].length; i++) { felix@2731: xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), felix@2731: (float) data[1][i], StickyAxisAnnotation.SimpleAxis.Y_AXIS)); felix@2731: } felix@2731: teichmann@5864: doAnnotations(new RiverAnnotation(facet.getDescription(), xy), felix@2731: aandf, theme, visible); felix@2731: } felix@2731: else { teichmann@8202: log.debug("its wkms time, baby"); felix@2731: WKms data = (WKms) wqkms; felix@3054: // Assume its WKms. teichmann@4047: // XXX DEAD CODE // double location = getRange()[0]; felix@4036: double w = StaticWKmsArtifact.getWAtKmLin(data, getRange()[0]); ingo@2325: xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(), felix@3054: (float) w, StickyAxisAnnotation.SimpleAxis.Y_AXIS)); felix@2731: teichmann@5864: doAnnotations(new RiverAnnotation(facet.getDescription(), xy), felix@2731: aandf, theme, visible); felix@1921: } felix@1921: } ingo@392: } ingo@392: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :