Mercurial > dive4elements > river
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; |