comparison artifacts/src/main/java/org/dive4elements/river/exports/CrossSectionGenerator.java @ 5838:5aa05a7a34b7

Rename modules to more fitting names.
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 15:23:37 +0200
parents flys-artifacts/src/main/java/org/dive4elements/river/exports/CrossSectionGenerator.java@bd047b71ab37
children 4897a58c8746
comparison
equal deleted inserted replaced
5837:d9901a08d0a6 5838:5aa05a7a34b7
1 package org.dive4elements.river.exports;
2
3 import java.awt.BasicStroke;
4 import java.awt.Color;
5 import java.awt.Paint;
6 import java.awt.Stroke;
7 import java.text.NumberFormat;
8 import java.util.List;
9
10 import org.apache.log4j.Logger;
11 import org.jfree.chart.LegendItemCollection;
12 import org.jfree.chart.annotations.XYBoxAnnotation;
13 import org.jfree.chart.annotations.XYTextAnnotation;
14 import org.jfree.chart.plot.XYPlot;
15 import org.jfree.data.xy.XYSeries;
16 import org.w3c.dom.Document;
17
18 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
19 import org.dive4elements.artifacts.DataProvider;
20 import org.dive4elements.river.artifacts.FLYSArtifact;
21 import org.dive4elements.river.artifacts.geom.Lines;
22 import org.dive4elements.river.artifacts.model.CrossSectionFacet;
23 import org.dive4elements.river.artifacts.model.FacetTypes;
24 import org.dive4elements.river.artifacts.model.HYKFactory;
25 import org.dive4elements.river.artifacts.resources.Resources;
26 import org.dive4elements.river.jfree.FLYSAnnotation;
27 import org.dive4elements.river.jfree.StyledXYSeries;
28 import org.dive4elements.river.model.FastCrossSectionLine;
29 import org.dive4elements.river.themes.LineStyle;
30 import org.dive4elements.river.themes.TextStyle;
31 import org.dive4elements.river.themes.ThemeAccess;
32 import org.dive4elements.river.utils.FLYSUtils;
33 import org.dive4elements.river.utils.Formatter;
34 import org.dive4elements.river.utils.ThemeUtil;
35
36
37 /**
38 * An OutGenerator that generates cross section graphs.
39 */
40 public class CrossSectionGenerator
41 extends LongitudinalSectionGenerator
42 implements FacetTypes
43 {
44 /** The logger that is used in this generator. */
45 private static Logger logger =
46 Logger.getLogger(CrossSectionGenerator.class);
47
48 public static final String I18N_CHART_TITLE =
49 "chart.cross_section.title";
50
51 public static final String I18N_CHART_SUBTITLE =
52 "chart.cross_section.subtitle";
53
54 public static final String I18N_XAXIS_LABEL =
55 "chart.cross_section.xaxis.label";
56
57 public static final String I18N_YAXIS_LABEL =
58 "chart.cross_section.yaxis.label";
59
60 public static final String I18N_CHART_TITLE_DEFAULT = "Querprofildiagramm";
61 public static final String I18N_XAXIS_LABEL_DEFAULT = "Abstand [m]";
62 public static final String I18N_YAXIS_LABEL_DEFAULT = "W [NN + m]";
63
64
65 /** Trivial Constructor. */
66 public CrossSectionGenerator() {
67 super();
68 }
69
70
71 @Override
72 protected YAxisWalker getYAxisWalker() {
73 return new YAxisWalker() {
74 @Override
75 public int length() {
76 return 1;
77 }
78
79 /** Get identifier for this index. */
80 @Override
81 public String getId(int idx) {
82 return "W";
83 }
84 };
85 }
86
87
88 /**
89 * Get localized chart title.
90 */
91 @Override
92 public String getDefaultChartTitle() {
93 Object[] i18n_msg_args = new Object[] {
94 getRiverName()
95 };
96 return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT, i18n_msg_args);
97 }
98
99
100 /** Always return default subtitle. */
101 @Override
102 protected String getChartSubtitle() {
103 // XXX NOTE: overriding this method disables ChartSettings subtitle!
104 // The default implementation of this method in ChartGenerator returns
105 // the subtitle changed via the chart settings dialog. This method
106 // always returns the subtitle containing river and km, NEVER the
107 // ChartSettings subtitle!
108 return getDefaultChartSubtitle();
109 }
110
111
112 /** Get Charts default subtitle. */
113 @Override
114 protected String getDefaultChartSubtitle() {
115 List<DataProvider> providers =
116 context.getDataProvider(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA);
117 double km = 0d;
118 if (providers.size() > 0) {
119 FastCrossSectionLine csl = (FastCrossSectionLine) providers.get(0).
120 provideData(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA,
121 null, context);
122 km = csl == null ? -1 : csl.getKm();
123 }
124
125 Object[] args = new Object[] {
126 getRiverName(),
127 km
128 };
129
130 logger.debug("Locale: " + Resources.getLocale(context.getMeta()));
131
132 return msg(I18N_CHART_SUBTITLE, "", args);
133 }
134
135
136 /** Get color for hyk zones by their type (which is the name). */
137 protected Paint colorForHYKZone(String zoneName) {
138 if (zoneName.startsWith("R")) {
139 // Brownish.
140 return new Color(153, 60, 0);
141 }
142 else if (zoneName.startsWith("V")) {
143 // Greenish.
144 return new Color(0, 255, 0);
145 }
146 else if (zoneName.startsWith("B")) {
147 // Grayish.
148 return new Color(128, 128, 128);
149 }
150 else if (zoneName.startsWith("H")) {
151 // Blueish.
152 return new Color(0, 0, 255);
153 }
154 else {
155 // Default.
156 logger.debug("Unknown zone type found.");
157 return new Color(255, 0, 0);
158 }
159 }
160
161 @Override
162 protected void addAnnotationsToRenderer(XYPlot plot) {
163 super.addAnnotationsToRenderer(plot);
164
165 // Paints for the boxes/lines.
166 Stroke basicStroke = new BasicStroke(1.0f);
167
168 // XXX: DEAD CODE // Paint linePaint = new Color(255, 0,0,60);
169 Paint fillPaint = new Color(0, 255,0,60);
170 Paint tranPaint = new Color(0, 0,0, 0);
171
172 // OPTMIMIZE: Pre-calculate positions
173 ChartArea area = new ChartArea(
174 plot.getDomainAxis(0).getRange(),
175 plot.getRangeAxis().getRange());
176
177 for(FLYSAnnotation fa : this.annotations) {
178
179 // Access text styling, if any.
180 Document theme = fa.getTheme();
181 TextStyle textStyle = null;
182 // XXX: DEAD CODE // LineStyle lineStyle = null;
183
184 // Get Themeing information and add legend item.
185 if (theme != null) {
186 ThemeAccess themeAccess = new ThemeAccess(theme);
187 textStyle = themeAccess.parseTextStyle();
188 // XXX: DEAD CODE // lineStyle = themeAccess.parseLineStyle();
189 if (fa.getLabel() != null) {
190 LegendItemCollection lic = new LegendItemCollection();
191 LegendItemCollection old = plot.getFixedLegendItems();
192 lic.add(createLegendItem(theme, fa.getLabel()));
193 // (Re-)Add prior legend entries.
194 if (old != null) {
195 old.addAll(lic);
196 }
197 else {
198 old = lic;
199 }
200 plot.setFixedLegendItems(old);
201 }
202 }
203
204 // Hyks.
205 for (HYKFactory.Zone zone: fa.getBoxes()) {
206 // For each zone, create a box to fill with color, a box to draw
207 // the lines and a text to display the type.
208 fillPaint = colorForHYKZone(zone.getName());
209
210 XYBoxAnnotation boxA = new XYBoxAnnotation(zone.getFrom(), area.atGround(),
211 zone.getTo(), area.ofGround(0.03f), basicStroke, tranPaint, fillPaint);
212 XYBoxAnnotation boxB = new XYBoxAnnotation(zone.getFrom(), area.atGround(),
213 zone.getTo(), area.atTop(), basicStroke, fillPaint, tranPaint);
214
215 XYTextAnnotation tex = new XYTextAnnotation(zone.getName(),
216 zone.getFrom() + (zone.getTo() - zone.getFrom()) / 2.0d,
217 area.ofGround(0.015f));
218 if (textStyle != null) {
219 textStyle.apply(tex);
220 }
221
222 plot.getRenderer().addAnnotation(boxA, org.jfree.ui.Layer.BACKGROUND);
223 plot.getRenderer().addAnnotation(boxB, org.jfree.ui.Layer.BACKGROUND);
224 plot.getRenderer().addAnnotation(tex, org.jfree.ui.Layer.BACKGROUND);
225 }
226 }
227 }
228
229 @Override
230 protected String getDefaultXAxisLabel() {
231 return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT);
232 }
233
234
235 @Override
236 protected String getDefaultYAxisLabel(int pos) {
237 FLYSArtifact flys = (FLYSArtifact) master;
238
239 String unit = FLYSUtils.getRiver(flys).getWstUnit().getName();
240
241 return msg(I18N_YAXIS_LABEL,
242 I18N_YAXIS_LABEL_DEFAULT,
243 new Object[] { unit });
244 }
245
246
247 /**
248 * Let one facet do its job.
249 */
250 @Override
251 public void doOut(
252 ArtifactAndFacet artifactFacet,
253 Document attr,
254 boolean visible
255 ) {
256 String name = artifactFacet.getFacetName();
257
258 logger.debug("CrossSectionGenerator.doOut: " + name);
259
260 if (name == null) {
261 logger.error("No facet name for doOut(). No output generated!");
262 return;
263 }
264
265 if (name.equals(CROSS_SECTION)) {
266 doCrossSectionOut(
267 artifactFacet.getData(context),
268 artifactFacet.getFacetDescription(),
269 attr,
270 visible);
271 }
272 else if (name.equals(CROSS_SECTION_WATER_LINE)) {
273 doCrossSectionWaterLineOut(
274 artifactFacet.getData(context),
275 artifactFacet.getFacetDescription(),
276 attr,
277 visible);
278 }
279 else if (FacetTypes.IS.AREA(name)) {
280 doArea(artifactFacet.getData(context),
281 artifactFacet,
282 attr,
283 visible);
284 }
285 else if (name.equals(HYK)) {
286 doHyk(artifactFacet.getData(context),
287 artifactFacet.getFacetDescription(),
288 attr,
289 visible);
290 }
291 else if (FacetTypes.IS.MANUALLINE(name)) {
292 doCrossSectionWaterLineOut(
293 artifactFacet.getData(context),
294 artifactFacet.getFacetDescription(),
295 attr,
296 visible);
297 }
298 else if (FacetTypes.IS.MANUALPOINTS(name)) {
299 doPoints(artifactFacet.getData(context),
300 artifactFacet,
301 attr, visible, YAXIS.W.idx);
302 }
303 else {
304 logger.warn("CrossSection.doOut: Unknown facet name: " + name);
305 return;
306 }
307 }
308
309
310 /** Look up the axis identifier for a given facet type. */
311 @Override
312 public int axisIdxForFacet(String facetName) {
313 // TODO Where to add thid axis too.
314 return 0;
315 }
316
317
318 /**
319 * Do cross sections waterline out.
320 *
321 * @param seriesName name of the data (line) to display in legend.
322 * @param theme Theme for the data series.
323 */
324 protected void doCrossSectionWaterLineOut(
325 Object o,
326 String seriesName,
327 Document theme,
328 boolean visible
329 ) {
330 logger.debug("CrossSectionGenerator.doCrossSectionWaterLineOut");
331
332 Lines.LineData lines = (Lines.LineData) o;
333 // DO NOT SORT DATA! This destroys the gaps indicated by NaNs.
334 StyledXYSeries series = new StyledXYSeries(seriesName, false, theme);
335
336 if (!ThemeUtil.parseShowLineLabel(theme)) {
337 series.setLabel("");
338 }
339 if (ThemeUtil.parseShowWidth(theme)) {
340 NumberFormat nf = Formatter.getMeterFormat(this.context);
341 String labelAdd = "b=" + nf.format(lines.width) + "m";
342 if (series.getLabel().length() == 0) {
343 series.setLabel(labelAdd);
344 }
345 else {
346 series.setLabel(series.getLabel() + ", " + labelAdd);
347 }
348 }
349 if (ThemeUtil.parseShowLevel(theme) && lines.points.length > 1
350 && lines.points[1].length > 0) {
351 NumberFormat nf = Formatter.getMeterFormat(this.context);
352 FLYSArtifact flys = (FLYSArtifact) master;
353
354 String unit = FLYSUtils.getRiver(flys).getWstUnit().getName();
355
356 String labelAdd = "W=" + nf.format(lines.points[1][0]) + unit;
357 if (series.getLabel().length() == 0) {
358 series.setLabel(labelAdd);
359 }
360 else {
361 series.setLabel(series.getLabel() + ", " + labelAdd);
362 }
363 }
364 if (ThemeUtil.parseShowMiddleHeight(theme) && lines.width != 0) {
365 NumberFormat nf = Formatter.getMeterFormat(this.context);
366 String labelAdd = "T=" + nf.format(lines.area / lines.width) + "m";
367 // : " + lines.area + "/" + lines.width);
368 if (series.getLabel().length() == 0) {
369 series.setLabel(labelAdd);
370 }
371 else {
372 series.setLabel(series.getLabel() + ", " + labelAdd);
373 }
374 }
375
376 StyledSeriesBuilder.addPoints(series, lines.points, false);
377
378 addAxisSeries(series, 0, visible);
379 }
380
381
382 /** Add HYK-Annotations (colorize and label some areas, draw lines. */
383 protected void doHyk(
384 Object o,
385 String seriesName,
386 Document theme,
387 boolean visible
388 ) {
389 logger.debug("CrossSectionGenerator.doHyk");
390
391 List<HYKFactory.Zone> zones = (List<HYKFactory.Zone>) o;
392
393 if (zones == null || zones.isEmpty()) {
394 logger.warn("CrossSectionGenerator.doHYK: empty zone list received.");
395 return;
396 }
397
398 // Actual Styling is done in XYChartGenerator.
399 if (visible) {
400 addAnnotations(new FLYSAnnotation(seriesName, null, zones, theme));
401 }
402 }
403
404
405 /**
406 * Do cross sections out.
407 *
408 * @param seriesName name of the data (line) to display in legend.
409 * @param theme Theme for the data series.
410 */
411 protected void doCrossSectionOut(
412 Object o,
413 String seriesName,
414 Document theme,
415 boolean visible
416 ) {
417 logger.debug("CrossSectionGenerator.doCrossSectionOut");
418
419 XYSeries series = new StyledXYSeries(seriesName, theme);
420
421 StyledSeriesBuilder.addPoints(series, (double [][]) o, false);
422
423 addAxisSeries(series, 0, visible);
424 }
425
426
427 /**
428 * Creates a new <i>ChartSection</i>.
429 *
430 * Overridden to prevent inclusion of subtitle.
431 *
432 * @return a new <i>ChartSection</i>.
433 */
434 @Override
435 protected ChartSection buildChartSection() {
436 ChartSection chartSection = new ChartSection();
437 chartSection.setTitle(getChartTitle());
438 chartSection.setDisplayGrid(isGridVisible());
439 chartSection.setDisplayLogo(showLogo());
440 chartSection.setLogoVPlacement(logoVPlace());
441 chartSection.setLogoHPlacement(logoHPlace());
442 return chartSection;
443 }
444 }
445 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org