ingo@385: package de.intevation.flys.exports; ingo@385: ingo@420: import java.awt.Color; ingo@420: ingo@385: import org.w3c.dom.Document; ingo@385: ingo@385: import org.apache.log4j.Logger; ingo@385: ingo@385: import org.jfree.chart.JFreeChart; ingo@385: import org.jfree.chart.axis.NumberAxis; ingo@385: import org.jfree.chart.plot.XYPlot; ingo@420: import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; ingo@414: import org.jfree.chart.title.TextTitle; ingo@385: import org.jfree.data.xy.XYSeries; ingo@385: import org.jfree.data.xy.XYSeriesCollection; ingo@385: ingo@385: import de.intevation.artifacts.Artifact; ingo@385: ingo@686: import de.intevation.flys.model.River; ingo@686: ingo@385: import de.intevation.flys.artifacts.WINFOArtifact; ingo@385: import de.intevation.flys.artifacts.model.WQDay; ingo@686: import de.intevation.flys.artifacts.resources.Resources; ingo@385: ingo@385: ingo@385: /** ingo@385: * An OutGenerator that generates duration curves. ingo@385: * ingo@385: * @author Ingo Weinzierl ingo@385: */ ingo@385: public class DurationCurveGenerator extends XYChartGenerator { ingo@385: ingo@686: public static final String I18N_DURATION_W = "chart.duration.curve.curve.w"; ingo@686: public static final String I18N_DURATION_Q = "chart.duration.curve.curve.q"; ingo@686: ingo@385: private static Logger logger = ingo@385: Logger.getLogger(DurationCurveGenerator.class); ingo@385: ingo@385: /** The storage for the W series to be drawn in this chart.*/ ingo@385: protected XYSeriesCollection w; ingo@385: ingo@385: /** The storage for the Q series to be drawn in this chart.*/ ingo@385: protected XYSeriesCollection q; ingo@385: ingo@385: ingo@385: public static final String DURATION_CURVE_W = ingo@385: "duration_curve.w"; ingo@385: ingo@385: public static final String DURATION_CURVE_Q = ingo@385: "duration_curve.q"; ingo@385: ingo@408: public static final String I18N_CHART_TITLE = ingo@408: "chart.duration.curve.title"; ingo@408: ingo@414: public static final String I18N_CHART_SUBTITLE = ingo@414: "chart.duration.curve.subtitle"; ingo@414: ingo@408: public static final String I18N_XAXIS_LABEL = ingo@408: "chart.duration.curve.xaxis.label"; ingo@408: ingo@408: public static final String I18N_YAXIS_LABEL = ingo@408: "chart.duration.curve.yaxis.label"; ingo@408: ingo@408: public static final String I18N_CHART_TITLE_DEFAULT = ingo@408: "Dauerlinie"; ingo@408: ingo@408: public static final String I18N_XAXIS_LABEL_DEFAULT = ingo@408: "Unterschreitungsdauer [Tage]"; ingo@408: ingo@408: public static final String I18N_YAXIS_LABEL_DEFAULT = ingo@408: "W [NN + m]"; ingo@408: ingo@385: ingo@385: public DurationCurveGenerator() { ingo@385: super(); ingo@385: ingo@385: this.w = new XYSeriesCollection(); ingo@385: this.q = new XYSeriesCollection(); ingo@385: } ingo@385: ingo@385: ingo@385: protected String getChartTitle() { ingo@408: return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); ingo@385: } ingo@385: ingo@385: ingo@414: @Override ingo@414: protected void addSubtitles(JFreeChart chart) { ingo@414: double[] dist = getRange(); ingo@414: ingo@414: Object[] args = new Object[] { ingo@414: getRiverName(), ingo@414: dist[0] ingo@414: }; ingo@414: ingo@414: String subtitle = msg(I18N_CHART_SUBTITLE, "", args); ingo@414: chart.addSubtitle(new TextTitle(subtitle)); ingo@414: } ingo@414: ingo@414: ingo@385: protected String getXAxisLabel() { ingo@408: return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); ingo@385: } ingo@385: ingo@385: ingo@385: protected String getYAxisLabel() { ingo@408: return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT); ingo@385: } ingo@385: ingo@385: ingo@385: public void addDatasets(JFreeChart chart) { ingo@385: XYPlot plot = (XYPlot) chart.getPlot(); ingo@385: ingo@385: plot.setDataset(0, w); ingo@385: plot.setDataset(1, q); ingo@385: } ingo@385: ingo@385: ingo@420: protected void adjustPlot(XYPlot plot) { ingo@420: super.adjustPlot(plot); ingo@420: ingo@420: // TODO REMOVE THIS CODE, IF WE HAVE INTRODUCED THEMES! ingo@420: XYLineAndShapeRenderer rw = (XYLineAndShapeRenderer) ingo@420: plot.getRendererForDataset(w); ingo@420: ingo@420: XYLineAndShapeRenderer rq = null; ingo@420: try { ingo@420: rq = (XYLineAndShapeRenderer) rw.clone(); ingo@420: } ingo@420: catch (Exception e) { ingo@420: logger.error(e, e); ingo@420: } ingo@420: ingo@420: int wNum = w.getSeriesCount(); ingo@420: int qNum = q.getSeriesCount(); ingo@420: ingo@420: for (int i = 0; i < wNum; i++) { ingo@420: rw.setSeriesPaint(i, Color.BLUE); ingo@420: } ingo@420: ingo@420: for (int i = 0; i < qNum; i++) { ingo@420: rq.setSeriesPaint(i, Color.GREEN); ingo@420: } ingo@420: ingo@420: plot.setRenderer(0, rw); ingo@420: plot.setRenderer(1, rq); ingo@420: } ingo@420: ingo@420: ingo@385: protected void adjustAxes(XYPlot plot) { ingo@385: super.adjustAxes(plot); ingo@385: sascha@665: NumberAxis qAxis = new NumberAxis("Q [m\u00b3/s]"); ingo@385: ingo@686: plot.setRangeAxis(1, qAxis); ingo@686: plot.mapDatasetToRangeAxis(1, 1); ingo@385: } ingo@385: ingo@385: ingo@385: public void doOut(Artifact artifact, String facet, Document attr) { ingo@385: logger.debug("DurationCurveGenerator.doOut: " + facet); ingo@385: ingo@385: if (facet == null || facet.length() == 0) { ingo@385: logger.error("No facet given. Cannot create dataset."); ingo@385: return; ingo@385: } ingo@385: ingo@686: WINFOArtifact winfo = (WINFOArtifact) artifact; ingo@686: River river = winfo.getRiver(); ingo@686: ingo@385: if (facet.equals(DURATION_CURVE_W)) { ingo@686: doWOut(getDurationCurveData(artifact), river.getName()); ingo@385: } ingo@385: else if (facet.equals(DURATION_CURVE_Q)) { ingo@686: doQOut(getDurationCurveData(artifact), river.getName()); ingo@385: } ingo@385: else { ingo@385: logger.warn("Unknown facet name: " + facet); ingo@385: return; ingo@385: } ingo@385: } ingo@385: ingo@385: ingo@385: /** ingo@385: * Creates the series for a duration curve's W facet. ingo@385: * ingo@385: * @param wqdays The WQDay store that contains the Ws. ingo@686: * @param river The name of the river. ingo@385: */ ingo@686: protected void doWOut(WQDay wqdays, String river) { ingo@385: logger.debug("DurationCurveGenerator.doWOut"); ingo@385: ingo@385: // TODO find the correct series name ingo@686: XYSeries series = new XYSeries( ingo@686: getSeriesName(river, DURATION_CURVE_W)); ingo@385: ingo@385: int size = wqdays.size(); ingo@385: for (int i = 0; i < size; i++) { ingo@385: int day = wqdays.getDay(i); ingo@385: double w = wqdays.getW(i); ingo@385: ingo@385: series.add((double) day, w); ingo@385: } ingo@385: ingo@385: this.w.addSeries(series); ingo@385: } ingo@385: ingo@385: ingo@385: /** ingo@385: * Creates the series for a duration curve's Q facet. ingo@385: * ingo@385: * @param wqdays The WQDay store that contains the Qs. ingo@686: * @param river The name of the river. ingo@385: */ ingo@686: protected void doQOut(WQDay wqdays, String river) { ingo@385: logger.debug("DurationCurveGenerator.doQOut"); ingo@385: ingo@385: // TODO find the correct series name ingo@686: XYSeries series = new XYSeries( ingo@686: getSeriesName(river, DURATION_CURVE_Q)); ingo@385: ingo@385: int size = wqdays.size(); ingo@385: for (int i = 0; i < size; i++) { ingo@385: int day = wqdays.getDay(i); ingo@385: double q = wqdays.getQ(i); ingo@385: ingo@385: series.add((double) day, q); ingo@385: } ingo@385: ingo@385: this.q.addSeries(series); ingo@385: } ingo@385: ingo@385: ingo@385: /** ingo@385: * Returns the computed data for a duration curve based on the artifact's ingo@385: * computation method. ingo@385: * ingo@385: * @param artifact The WINFO artifact. ingo@385: * ingo@385: * @return the computed data for a duration curve's W and Q facet. ingo@385: */ ingo@385: protected WQDay getDurationCurveData(Artifact artifact) { ingo@385: WINFOArtifact winfoArtifact = (WINFOArtifact) artifact; ingo@385: return winfoArtifact.getDurationCurveData(); ingo@385: } ingo@686: ingo@686: ingo@686: protected String getSeriesName(String river, String type) { ingo@686: Object[] args = new Object[] { river }; ingo@686: ingo@686: if (type == null || type.length() == 0) { ingo@686: logger.warn("No duration curve type given."); ingo@686: return "n/a"; ingo@686: } ingo@686: else if (type.equals(DURATION_CURVE_W)) { ingo@686: return Resources.getMsg( ingo@686: context.getMeta(), ingo@686: I18N_DURATION_W, ingo@686: "W", ingo@686: args); ingo@686: } ingo@686: else if (type.equals(DURATION_CURVE_Q)) { ingo@686: return Resources.getMsg( ingo@686: context.getMeta(), ingo@686: I18N_DURATION_Q, ingo@686: "W", ingo@686: args); ingo@686: } ingo@686: ingo@686: logger.warn("Could not determine chart curve type: " + type); ingo@686: return type; ingo@686: } ingo@385: } ingo@385: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :