comparison flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java @ 2020:4f7f781e4481

Improved area rendering workflow. flys-artifacts/trunk@3475 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Tue, 20 Dec 2011 06:47:08 +0000
parents 79b15491177a
children 7bc9293de4e6
comparison
equal deleted inserted replaced
2019:aa3e7ed1fa46 2020:4f7f781e4481
1 package de.intevation.flys.exports; 1 package de.intevation.flys.exports;
2 2
3 import java.awt.BasicStroke; 3 import java.awt.BasicStroke;
4 import java.awt.Color; 4 import java.awt.Color;
5 import java.awt.Paint;
5 import java.awt.Stroke; 6 import java.awt.Stroke;
7 import java.awt.TexturePaint;
8
9 import java.awt.geom.Rectangle2D;
10
11 import java.awt.image.BufferedImage;
6 12
7 import java.io.IOException; 13 import java.io.IOException;
8 14
9 import java.text.NumberFormat; 15 import java.text.NumberFormat;
10 16
64 * 70 *
65 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> 71 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
66 */ 72 */
67 public abstract class XYChartGenerator extends ChartGenerator { 73 public abstract class XYChartGenerator extends ChartGenerator {
68 74
75 // TODO Consider storing the renderer here.
69 private class AxisDataset { 76 private class AxisDataset {
70 /** Symbolic integer, but also coding the priority (0 goes first). */ 77 /** Symbolic integer, but also coding the priority (0 goes first). */
71 protected int axisSymbol; 78 protected int axisSymbol;
72 /** List of assigned datasets (in order). */ 79 /** List of assigned datasets (in order). */
73 protected List<XYDataset> datasets; 80 protected List<XYDataset> datasets;
74 /** Range to use to include all given datasets. */ 81 /** Range to use to include all given datasets. */
75 protected Range range; 82 protected Range range;
76 /** List of datasets that are "area datasets" (these will be also
77 * present in the datasets list). */
78 List<XYDataset> areaDatasets;
79 83
80 /** Create AxisDataset. */ 84 /** Create AxisDataset. */
81 public AxisDataset(int symb) { 85 public AxisDataset(int symb) {
82 this.axisSymbol = symb; 86 this.axisSymbol = symb;
83 datasets = new ArrayList<XYDataset>(); 87 datasets = new ArrayList<XYDataset>();
84 areaDatasets = new ArrayList<XYDataset>();
85 } 88 }
86 89
87 /** Merge (or create given range with range so far (if any). */ 90 /** Merge (or create given range with range so far (if any). */
88 private void mergeRanges(Range subRange) { 91 private void mergeRanges(Range subRange) {
89 // Avoid merging NaNs, as they take min/max place forever. 92 // Avoid merging NaNs, as they take min/max place forever.
103 public void addDataset(XYSeries dataset) { 106 public void addDataset(XYSeries dataset) {
104 this.datasets.add(new XYSeriesCollection(dataset)); 107 this.datasets.add(new XYSeriesCollection(dataset));
105 includeYRange(dataset); 108 includeYRange(dataset);
106 } 109 }
107 110
108 /** Add an area dataset. */ 111 public void addArea(StyledAreaSeriesCollection series) {
109 public void addAreaDataset(XYSeries series1, XYSeries series2) { 112 this.datasets.add(series);
110 XYSeriesCollection collection = new XYSeriesCollection();
111 collection.addSeries(series1);
112 collection.addSeries(series2);
113 this.datasets.add(collection);
114 this.areaDatasets.add(collection);
115 // TODO include Range ...
116 } 113 }
117 114
118 /** True if to be renedered as area. */ 115 /** True if to be renedered as area. */
119 public boolean isArea(XYSeriesCollection series) { 116 public boolean isArea(XYSeriesCollection series) {
120 return areaDatasets.contains(series); 117 return (series instanceof StyledAreaSeriesCollection);
121 } 118 }
122 119
123 /** Adjust range to include given dataset. */ 120 /** Adjust range to include given dataset. */
124 public void includeYRange(XYSeries dataset) { 121 public void includeYRange(XYSeries dataset) {
125 mergeRanges(new Range(dataset.getMinY(), dataset.getMaxY())); 122 mergeRanges(new Range(dataset.getMinY(), dataset.getMaxY()));
140 int length(); 137 int length();
141 String getId(int idx); 138 String getId(int idx);
142 } 139 }
143 140
144 141
142 /** Override to make axis information available. */
145 protected YAxisWalker getYAxisWalker() { 143 protected YAxisWalker getYAxisWalker() {
146 return new YAxisWalker() { 144 return new YAxisWalker() {
145 /** Get number of items. */
147 @Override 146 @Override
148 public int length() { 147 public int length() {
149 return 0; 148 return 0;
150 } 149 }
151 150
151 /** Get identifier for this index. */
152 @Override 152 @Override
153 public String getId(int idx) { 153 public String getId(int idx) {
154 return null; 154 return null;
155 } 155 }
156 }; 156 };
434 /** 434 /**
435 * Registers an area to be drawn. 435 * Registers an area to be drawn.
436 * @param lower the lower curve to draw the area from. 436 * @param lower the lower curve to draw the area from.
437 * @param upper the upper curve to draw the ara from. 437 * @param upper the upper curve to draw the ara from.
438 */ 438 */
439 public void addAreaSeries(Object lower, Object upper, int index, boolean visible) { 439 public void addAreaSeries(StyledAreaSeriesCollection area, int index, boolean visible) {
440 if (lower == null && upper == null) { 440 if (area == null) {
441 logger.warn("Cannot yet render above/under curve."); 441 logger.warn("Cannot yet render above/under curve.");
442 return; 442 return;
443 } 443 }
444 AxisDataset axisDataset = datasets.get(index); 444 AxisDataset axisDataset = datasets.get(index);
445 445
446 if (axisDataset == null) { 446 if (axisDataset == null) {
447 axisDataset = new AxisDataset(index); 447 axisDataset = new AxisDataset(index);
448 datasets.put(index, axisDataset); 448 datasets.put(index, axisDataset);
449 } 449 }
450 450
451 if (visible) 451 if (visible) {
452 axisDataset.addAreaDataset((XYSeries) lower, (XYSeries) upper); 452 axisDataset.addArea(area);
453 }
453 else { 454 else {
454 // TODO only range merging. 455 // TODO only range merging.
455 } 456 }
456 //TODO range merging. 457 //TODO range merging.
457 } 458 }
459
458 460
459 /** 461 /**
460 * Add given series if visible, if not visible adjust ranges (such that 462 * Add given series if visible, if not visible adjust ranges (such that
461 * all points in data would be plotted once visible). 463 * all points in data would be plotted once visible).
462 * @param series the dataseries to include in plot. 464 * @param series the dataseries to include in plot.
784 786
785 plot.setAxisOffset(new RectangleInsets(0d, 0d, 0d, 0d)); 787 plot.setAxisOffset(new RectangleInsets(0d, 0d, 0d, 0d));
786 } 788 }
787 789
788 790
791 /** Override to handle subtitle adding. */
789 protected void addSubtitles(JFreeChart chart) { 792 protected void addSubtitles(JFreeChart chart) {
790 // override this method in subclasses that need subtitles 793 // override this method in subclasses that need subtitles
791 } 794 }
792 795
793 796
861 boolean isArea 864 boolean isArea
862 ) { 865 ) {
863 LegendItemCollection lic = new LegendItemCollection(); 866 LegendItemCollection lic = new LegendItemCollection();
864 LegendItemCollection anno = plot.getFixedLegendItems(); 867 LegendItemCollection anno = plot.getFixedLegendItems();
865 868
869 int retidx = idx;
870
871 if (isArea) {
872 logger.debug("Registering an 'area'renderer at idx: " + idx);
873 StyledAreaSeriesCollection area = (StyledAreaSeriesCollection) series;
874
875 StableXYDifferenceRenderer dRenderer = new StableXYDifferenceRenderer();
876 if (area.getMode() == StyledAreaSeriesCollection.FILL_MODE.UNDER) {
877 dRenderer.setPositivePaint(createTransparentPaint());
878 }
879 plot.setRenderer(idx, dRenderer);
880
881 area.applyTheme(dRenderer);
882
883 LegendItem legendItem = dRenderer.getLegendItem(idx, 0);
884 if (legendItem != null) {
885 lic.add(legendItem);
886 }
887 else {
888 logger.warn("Could not get LegentItem for renderer: "
889 + idx + ", series-idx " + 0);
890 }
891 if (anno != null) {
892 lic.addAll(anno);
893 }
894 plot.setFixedLegendItems(lic);
895 return retidx + 1;
896 }
897
866 XYLineAndShapeRenderer renderer = getRenderer(plot, idx); 898 XYLineAndShapeRenderer renderer = getRenderer(plot, idx);
867 int retidx = idx;
868
869 if (isArea) {
870 logger.debug("Registering an 'area'renderer.");
871 plot.setRenderer(retidx, new StableXYDifferenceRenderer());
872 // TODO to legend entry
873 // TODO to styling
874 return retidx +1;
875 }
876 899
877 for (int s = 0, num = series.getSeriesCount(); s < num; s++) { 900 for (int s = 0, num = series.getSeriesCount(); s < num; s++) {
878 XYSeries serie = series.getSeries(s); 901 XYSeries serie = series.getSeries(s);
879 902
880 if (serie instanceof StyledXYSeries) { 903 if (serie instanceof StyledXYSeries) {
886 // the chart area. 909 // the chart area.
887 if (serie.getItemCount() == 1) { 910 if (serie.getItemCount() == 1) {
888 renderer.setSeriesShapesVisible(s, true); 911 renderer.setSeriesShapesVisible(s, true);
889 } 912 }
890 913
891 LegendItem li = renderer.getLegendItem(idx, s); 914 LegendItem legendItem = renderer.getLegendItem(idx, s);
892 if (li != null) { 915 if (legendItem != null) {
893 lic.add(li); 916 lic.add(legendItem);
894 } 917 }
895 else { 918 else {
896 logger.warn("Could not get LegentItem for renderer: " 919 logger.warn("Could not get LegentItem for renderer: "
897 + idx + ", series-idx " + s); 920 + idx + ", series-idx " + s);
898 } 921 }
922 // TODO: why that? isnt renderer set per dataset not per series?
899 retidx++; 923 retidx++;
900 } 924 }
901 925
902 if (anno != null) { 926 if (anno != null) {
903 lic.addAll(anno); 927 lic.addAll(anno);
909 933
910 return retidx; 934 return retidx;
911 } 935 }
912 936
913 937
938 /** Returns a transparently textured paint. */
939 // TODO why not use a transparent color?
940 protected static Paint createTransparentPaint() {
941 BufferedImage texture = new BufferedImage(
942 1, 1, BufferedImage.TYPE_4BYTE_ABGR);
943
944 return new TexturePaint(
945 texture, new Rectangle2D.Double(0d, 0d, 0d, 0d));
946 }
947
948
914 /** 949 /**
915 * Get renderer, from plot or cloned default renderer otherwise. 950 * Get renderer, from plot or cloned default renderer otherwise.
916 */ 951 */
917 protected XYLineAndShapeRenderer getRenderer(XYPlot plot, int idx) { 952 protected XYLineAndShapeRenderer getRenderer(XYPlot plot, int idx) {
953 // !TODO what if its a differencerenderer?!
954 logger.debug("getRenderer: " + idx);
918 XYLineAndShapeRenderer r = 955 XYLineAndShapeRenderer r =
919 (XYLineAndShapeRenderer) plot.getRenderer(idx); 956 (XYLineAndShapeRenderer) plot.getRenderer(idx);
920 957
921 if (r != null) { 958 if (r != null) {
922 return r; 959 return r;

http://dive4elements.wald.intevation.org