9252
|
1 /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde |
|
2 * Software engineering by Intevation GmbH |
|
3 * |
|
4 * This file is Free Software under the GNU AGPL (>=v3) |
|
5 * and comes with ABSOLUTELY NO WARRANTY! Check out the |
|
6 * documentation coming with Dive4Elements River for details. |
|
7 */ |
|
8 |
|
9 package org.dive4elements.river.artifacts.sinfo.flood_duration; |
|
10 |
|
11 import java.awt.Font; |
|
12 import java.awt.geom.Point2D; |
|
13 |
|
14 import org.apache.log4j.Logger; |
|
15 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; |
|
16 import org.dive4elements.artifacts.CallContext; |
|
17 import org.dive4elements.river.artifacts.model.CalculationResult; |
|
18 import org.dive4elements.river.artifacts.model.FacetTypes; |
|
19 import org.dive4elements.river.artifacts.model.WQDay; |
|
20 import org.dive4elements.river.exports.IdentifiableNumberAxis; |
|
21 import org.dive4elements.river.exports.XYChartGenerator; |
|
22 import org.dive4elements.river.jfree.Bounds; |
|
23 import org.dive4elements.river.jfree.RiverAnnotation; |
|
24 import org.dive4elements.river.jfree.StyledXYSeries; |
|
25 import org.dive4elements.river.themes.ThemeDocument; |
|
26 import org.jfree.chart.axis.NumberAxis; |
|
27 import org.jfree.chart.axis.ValueAxis; |
|
28 import org.jfree.chart.plot.XYPlot; |
|
29 import org.jfree.data.Range; |
|
30 import org.jfree.data.xy.XYSeries; |
|
31 |
|
32 |
|
33 /** |
|
34 * An OutGenerator that generates duration curves. |
|
35 * |
|
36 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> |
|
37 */ |
|
38 public class FloodDurationCurveGenerator |
|
39 extends XYChartGenerator |
|
40 implements FacetTypes |
|
41 { |
|
42 public static enum YAXIS { |
|
43 W(0), |
|
44 Q(1); |
|
45 public int idx; |
|
46 private YAXIS(final int c) { |
|
47 this.idx = c; |
|
48 } |
|
49 } |
|
50 |
|
51 /** Local log. */ |
|
52 private static Logger log = |
|
53 Logger.getLogger(FloodDurationCurveGenerator.class); |
|
54 |
|
55 public static final String I18N_CHART_TITLE = "sinfo.chart.flood_duration.curve.section.title"; |
|
56 |
|
57 public static final String I18N_CHART_SUBTITLE = "chart.duration.curve.subtitle"; |
|
58 |
|
59 public static final String I18N_XAXIS_LABEL = "sinfo.chart.flood_duration.curve.xaxis.label"; |
|
60 |
|
61 public static final String I18N_YAXIS_LABEL_W = "chart.duration.curve.yaxis.label.w"; |
|
62 |
|
63 public static final String I18N_YAXIS_LABEL_Q = "chart.duration.curve.yaxis.label.q"; |
|
64 |
|
65 public static final String I18N_CHART_TITLE_DEFAULT = "Dauerlinie"; |
|
66 |
|
67 public static final String I18N_XAXIS_LABEL_DEFAULT = "Überflutungsdauer [d/a]"; |
|
68 |
|
69 |
|
70 public FloodDurationCurveGenerator() { |
|
71 super(); |
|
72 } |
|
73 |
|
74 |
|
75 /** |
|
76 * Create Axis for given index. |
|
77 * @return axis with according internationalized label. |
|
78 */ |
|
79 @Override |
|
80 protected NumberAxis createYAxis(final int index) { |
|
81 final Font labelFont = new Font("Tahoma", Font.BOLD, 14); |
|
82 final String label = getYAxisLabel(index); |
|
83 |
|
84 final NumberAxis axis = createNumberAxis(index, label); |
|
85 if (index == YAXIS.W.idx) { |
|
86 axis.setAutoRangeIncludesZero(false); |
|
87 } |
|
88 axis.setLabelFont(labelFont); |
|
89 return axis; |
|
90 } |
|
91 |
|
92 |
|
93 @Override |
|
94 protected String getDefaultChartTitle(final CallContext context) { |
|
95 return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); |
|
96 } |
|
97 |
|
98 |
|
99 @Override |
|
100 protected String getDefaultChartSubtitle(final CallContext context) { |
|
101 |
|
102 final double[] dist = getRange(); |
|
103 return msg(I18N_CHART_SUBTITLE, "", getRiverName(), dist[0]); |
|
104 } |
|
105 |
|
106 |
|
107 @Override |
|
108 protected String getDefaultXAxisLabel(final CallContext context) { |
|
109 return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); |
|
110 } |
|
111 |
|
112 |
|
113 @Override |
|
114 protected String getDefaultYAxisLabel(final int index) { |
|
115 |
|
116 String label = "default"; |
|
117 if (index == YAXIS.W.idx) { |
|
118 label = msg(I18N_YAXIS_LABEL_W, I18N_YAXIS_LABEL_W, getRiverUnit()); |
|
119 } |
|
120 else if (index == YAXIS.Q.idx) { |
|
121 label = msg(I18N_YAXIS_LABEL_Q); |
|
122 } |
|
123 return label; |
|
124 } |
|
125 |
|
126 |
|
127 @Override |
|
128 protected boolean zoomX(final XYPlot plot, final ValueAxis axis, final Bounds bounds, final Range x) { |
|
129 |
|
130 final boolean zoomin = super.zoom(plot, axis, bounds, x); |
|
131 if (!zoomin) |
|
132 axis.setLowerBound(0d); |
|
133 // axis.setUpperBound(364); |
|
134 return zoomin; |
|
135 } |
|
136 |
|
137 |
|
138 /** |
|
139 * This method overrides the method in the parent class to set the lower |
|
140 * bounds of the Q axis to 0. This axis should never display negative |
|
141 * values on its own. |
|
142 */ |
|
143 @Override |
|
144 protected boolean zoomY(final XYPlot plot, final ValueAxis axis, final Bounds bounds, final Range x) { |
|
145 |
|
146 final boolean zoomin = super.zoom(plot, axis, bounds, x); |
|
147 if (!zoomin && axis instanceof IdentifiableNumberAxis) { |
|
148 final String id = ((IdentifiableNumberAxis) axis).getId(); |
|
149 if (YAXIS.Q.toString().equals(id)) |
|
150 axis.setLowerBound(0d); |
|
151 } |
|
152 return zoomin; |
|
153 } |
|
154 |
|
155 |
|
156 @Override |
|
157 public void doOut(final ArtifactAndFacet artifactFacet, final ThemeDocument attr, final boolean visible) { |
|
158 |
|
159 final String name = artifactFacet.getFacetName(); |
|
160 |
|
161 log.debug("FloodDurationCurveGenerator.doOut: " + name); |
|
162 |
|
163 if (name == null || name.length() == 0) { |
|
164 log.error("No facet given. Cannot create dataset."); |
|
165 return; |
|
166 } |
|
167 |
|
168 final CallContext context = getContext(); |
|
169 |
|
170 if (name.equals(DURATION_W)) { |
|
171 doWOut((WQDay) ((CalculationResult) artifactFacet.getData(context)).getData(), artifactFacet, attr, visible); |
|
172 } |
|
173 else if (name.equals(DURATION_Q)) { |
|
174 doQOut((WQDay) ((CalculationResult) artifactFacet.getData(context)).getData(), artifactFacet, attr, visible); |
|
175 } |
|
176 else if (name.equals(MAINVALUES_Q) || name.equals(MAINVALUES_W)) { |
|
177 doAnnotations((RiverAnnotation) artifactFacet.getData(context), artifactFacet, attr, visible); |
|
178 } |
|
179 else if (name.equals(RELATIVE_POINT)) { |
|
180 doPointOut((Point2D) artifactFacet.getData(context), artifactFacet, attr, visible); |
|
181 } |
|
182 else if (FacetTypes.IS.MANUALPOINTS(name)) { |
|
183 doPoints(artifactFacet.getData(context), artifactFacet, attr, visible, YAXIS.W.idx); |
|
184 } |
|
185 else { |
|
186 log.warn("Unknown facet name: " + name); |
|
187 return; |
|
188 } |
|
189 } |
|
190 |
|
191 /** |
|
192 * Creates the series for a duration curve's W facet. |
|
193 * |
|
194 * @param wqdays The WQDay store that contains the Ws. |
|
195 * @param theme |
|
196 */ |
|
197 protected void doWOut(final WQDay wqdays, final ArtifactAndFacet aaf, final ThemeDocument theme, final boolean visible) { |
|
198 |
|
199 // log.debug("DurationCurveGenerator.doWOut"); |
|
200 final XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); |
|
201 final int size = wqdays.size(); |
|
202 for (int i = 0; i < size; i++) { |
|
203 final int day = wqdays.getDay(i); |
|
204 final double w = wqdays.getW(i); |
|
205 series.add(day, w); |
|
206 } |
|
207 addAxisSeries(series, YAXIS.W.idx, visible); |
|
208 } |
|
209 |
|
210 protected void doPointOut(final Point2D point, final ArtifactAndFacet aandf, final ThemeDocument theme, final boolean visible) { |
|
211 |
|
212 // log.debug("DurationCurveGenerator.doPointOut"); |
|
213 final XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); |
|
214 series.add(point.getX(), point.getY()); |
|
215 addAxisSeries(series, YAXIS.W.idx, visible); |
|
216 } |
|
217 |
|
218 |
|
219 /** |
|
220 * Creates the series for a duration curve's Q facet. |
|
221 * |
|
222 * @param wqdays The WQDay store that contains the Qs. |
|
223 * @param theme |
|
224 */ |
|
225 protected void doQOut(final WQDay wqdays, final ArtifactAndFacet aaf, final ThemeDocument theme, final boolean visible) { |
|
226 |
|
227 // log.debug("DurationCurveGenerator.doQOut"); |
|
228 final XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); |
|
229 final int size = wqdays.size(); |
|
230 for (int i = 0; i < size; i++) { |
|
231 final int day = wqdays.getDay(i); |
|
232 final double q = wqdays.getQ(i); |
|
233 series.add(day, q); |
|
234 } |
|
235 addAxisSeries(series, YAXIS.Q.idx, visible); |
|
236 } |
|
237 |
|
238 |
|
239 @Override |
|
240 protected YAxisWalker getYAxisWalker() { |
|
241 return new YAxisWalker() { |
|
242 @Override |
|
243 public int length() { |
|
244 return YAXIS.values().length; |
|
245 } |
|
246 |
|
247 @Override |
|
248 public String getId(final int idx) { |
|
249 final YAXIS[] yaxes = YAXIS.values(); |
|
250 return yaxes[idx].toString(); |
|
251 } |
|
252 }; |
|
253 } |
|
254 |
|
255 // MainValue-Annotations should be visualized by |
|
256 // a line that goes to the curve itself. |
|
257 } |
|
258 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |