Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java @ 2161:c68f4f227c09
Somewhat unified Annotation handling, use jfreechart-house-toolkit instead of custom StickyAxisAnnotation.
flys-artifacts/trunk@3747 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Felix Wolfsteller <felix.wolfsteller@intevation.de> |
---|---|
date | Mon, 23 Jan 2012 10:44:34 +0000 |
parents | 2336927cb096 |
children | 105097966111 |
comparison
equal
deleted
inserted
replaced
2160:8428de5846e8 | 2161:c68f4f227c09 |
---|---|
29 import org.jfree.chart.ChartFactory; | 29 import org.jfree.chart.ChartFactory; |
30 import org.jfree.chart.JFreeChart; | 30 import org.jfree.chart.JFreeChart; |
31 import org.jfree.chart.LegendItem; | 31 import org.jfree.chart.LegendItem; |
32 import org.jfree.chart.LegendItemCollection; | 32 import org.jfree.chart.LegendItemCollection; |
33 import org.jfree.chart.annotations.XYBoxAnnotation; | 33 import org.jfree.chart.annotations.XYBoxAnnotation; |
34 import org.jfree.chart.annotations.XYLineAnnotation; | |
34 import org.jfree.chart.annotations.XYTextAnnotation; | 35 import org.jfree.chart.annotations.XYTextAnnotation; |
35 import org.jfree.chart.axis.NumberAxis; | 36 import org.jfree.chart.axis.NumberAxis; |
36 import org.jfree.chart.axis.ValueAxis; | 37 import org.jfree.chart.axis.ValueAxis; |
37 import org.jfree.chart.plot.PlotOrientation; | 38 import org.jfree.chart.plot.PlotOrientation; |
38 import org.jfree.chart.plot.XYPlot; | 39 import org.jfree.chart.plot.XYPlot; |
39 import org.jfree.chart.renderer.xy.XYItemRenderer; | |
40 import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; | 40 import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; |
41 import org.jfree.data.Range; | 41 import org.jfree.data.Range; |
42 import org.jfree.data.xy.XYSeries; | 42 import org.jfree.data.xy.XYSeries; |
43 import org.jfree.data.xy.XYSeriesCollection; | 43 import org.jfree.data.xy.XYSeriesCollection; |
44 import org.jfree.data.xy.XYDataset; | 44 import org.jfree.data.xy.XYDataset; |
45 | 45 |
46 import org.jfree.ui.RectangleInsets; | 46 import org.jfree.ui.RectangleInsets; |
47 import org.jfree.ui.TextAnchor; | |
47 | 48 |
48 import de.intevation.artifacts.CallContext; | 49 import de.intevation.artifacts.CallContext; |
49 | 50 |
50 import de.intevation.artifactdatabase.state.Facet; | 51 import de.intevation.artifactdatabase.state.Facet; |
51 import de.intevation.artifactdatabase.state.Settings; | 52 import de.intevation.artifactdatabase.state.Settings; |
54 import de.intevation.flys.exports.ChartExportHelper; | 55 import de.intevation.flys.exports.ChartExportHelper; |
55 import de.intevation.flys.jfree.EnhancedLineAndShapeRenderer; | 56 import de.intevation.flys.jfree.EnhancedLineAndShapeRenderer; |
56 import de.intevation.flys.jfree.FLYSAnnotation; | 57 import de.intevation.flys.jfree.FLYSAnnotation; |
57 import de.intevation.flys.jfree.StableXYDifferenceRenderer; | 58 import de.intevation.flys.jfree.StableXYDifferenceRenderer; |
58 import de.intevation.flys.jfree.StickyAxisAnnotation; | 59 import de.intevation.flys.jfree.StickyAxisAnnotation; |
60 import de.intevation.flys.jfree.CollisionFreeXYTextAnnotation; | |
59 import de.intevation.flys.jfree.StyledAreaSeriesCollection; | 61 import de.intevation.flys.jfree.StyledAreaSeriesCollection; |
60 import de.intevation.flys.jfree.StyledXYSeries; | 62 import de.intevation.flys.jfree.StyledXYSeries; |
61 | 63 |
62 import de.intevation.flys.utils.ThemeAccess; | 64 import de.intevation.flys.utils.ThemeAccess; |
63 | 65 |
505 //debugDatasets(plot); | 507 //debugDatasets(plot); |
506 | 508 |
507 recoverEmptyPlot(plot); | 509 recoverEmptyPlot(plot); |
508 preparePointRanges(plot); | 510 preparePointRanges(plot); |
509 | 511 |
510 addAnnotationsToRenderer(plot); | |
511 | |
512 //debugAxis(plot); | 512 //debugAxis(plot); |
513 | 513 |
514 localizeAxes(plot); | 514 localizeAxes(plot); |
515 adjustAxes(plot); | 515 adjustAxes(plot); |
516 autoZoom(plot); | 516 autoZoom(plot); |
517 | 517 |
518 // These have to go after the autozoom. | 518 // These have to go after the autozoom. |
519 addBoxAnnotations(plot); | 519 addAnnotationsToRenderer(plot); |
520 | 520 |
521 return chart; | 521 return chart; |
522 } | 522 } |
523 | 523 |
524 | 524 |
970 } | 970 } |
971 | 971 |
972 return null; | 972 return null; |
973 } | 973 } |
974 | 974 |
975 | 975 public LegendItem createLegendItem(Document theme, String name) { |
976 /** | 976 // OPTIMIZE Pass font, parsed Theme items. |
977 * Add annotations to Renderer. | 977 ThemeAccess themeAccess = new ThemeAccess(theme); |
978 */ | 978 Color color = themeAccess.parseLineColorField(); |
979 protected void addAnnotationsToRenderer(XYPlot plot) { | 979 LegendItem li = new LegendItem(name, color); |
980 plot.clearAnnotations(); | 980 li.setLabelFont(createLegendLabelFont()); |
981 | 981 return li; |
982 if (annotations == null) { | 982 } |
983 logger.debug("No Annotations given."); | 983 |
984 return; | 984 |
985 } | 985 /** |
986 | 986 * Get "lowest" X Value for first axis. This value is exactly at the |
987 Font labelFont = createLegendLabelFont(); | 987 * border of the plot. |
988 | 988 * @return lowest value on first 'x'-axis. |
989 LegendItemCollection lic = new LegendItemCollection(); | 989 */ |
990 LegendItemCollection old = plot.getFixedLegendItems(); | 990 protected double getLowestXValue(XYPlot plot) { |
991 | 991 ValueAxis axis = plot.getDomainAxis(); |
992 XYItemRenderer renderer = plot.getRenderer(0); | 992 if (axis == null) { |
993 | 993 logger.warn("No X-Axis to find lowest value for."); |
994 for (FLYSAnnotation fa: annotations) { | 994 } |
995 Document theme = fa.getTheme(); | 995 return axis.getRange().getLowerBound(); |
996 | 996 } |
997 ThemeAccess themeAccess = new ThemeAccess(theme); | 997 |
998 | 998 |
999 Color color = themeAccess.parseLineColorField(); | 999 /** |
1000 int lineWidth = themeAccess.parseLineWidth(); | 1000 * Get "lowest" X Value for first axis. This value is exactly at the |
1001 | 1001 * border of the plot. |
1002 LegendItem li = new LegendItem(fa.getLabel(), color); | 1002 * @return highest value on first 'x'-axis. |
1003 li.setLabelFont(labelFont); | 1003 */ |
1004 | 1004 protected double getUppestXValue(XYPlot plot) { |
1005 lic.add(li); | 1005 ValueAxis axis = plot.getDomainAxis(); |
1006 | 1006 if (axis == null) { |
1007 for (XYTextAnnotation ta: fa.getTextAnnotations()) { | 1007 logger.warn("No first Y-Axis to find uppest value for."); |
1008 if(ta instanceof StickyAxisAnnotation) { | 1008 } |
1009 StickyAxisAnnotation sta = (StickyAxisAnnotation)ta; | 1009 return axis.getRange().getUpperBound(); |
1010 sta.applyTheme(themeAccess); | |
1011 renderer.addAnnotation(sta); | |
1012 } | |
1013 else { | |
1014 ta.setPaint(color); | |
1015 ta.setOutlineStroke(new BasicStroke((float) lineWidth)); | |
1016 renderer.addAnnotation(ta); | |
1017 } | |
1018 } | |
1019 } | |
1020 | |
1021 // (Re-)Add prior legend entries. | |
1022 if (old != null) { | |
1023 old.addAll(lic); | |
1024 } | |
1025 else { | |
1026 old = lic; | |
1027 } | |
1028 | |
1029 plot.setFixedLegendItems(old); | |
1030 } | 1010 } |
1031 | 1011 |
1032 | 1012 |
1033 /** | 1013 /** |
1034 * Get "lowest" Y Value for first axis. This value is exactly at the | 1014 * Get "lowest" Y Value for first axis. This value is exactly at the |
1082 return new Color(255, 0, 0); | 1062 return new Color(255, 0, 0); |
1083 } | 1063 } |
1084 } | 1064 } |
1085 | 1065 |
1086 | 1066 |
1087 /** Add box annotations (currently, only hyk zones). */ | 1067 /** |
1088 public void addBoxAnnotations(XYPlot plot) { | 1068 * Add a text and a line annotation. |
1089 logger.debug("XYChartGenerator.addBoxAnnotations"); | 1069 */ |
1070 public void addStickyAnnotation( | |
1071 StickyAxisAnnotation annotation, | |
1072 XYPlot plot, | |
1073 Area area, | |
1074 ThemeAccess.LineStyle lineStyle, | |
1075 ThemeAccess.TextStyle textStyle | |
1076 ) { | |
1077 // OPTIMIZE pre-calculate area-related values | |
1078 final float TEXT_OFF = 0.03f; | |
1079 final float LINE_OFF = 0.02f; | |
1080 | |
1081 XYLineAnnotation lineAnnotation = null; | |
1082 XYTextAnnotation textAnnotation = null; | |
1083 | |
1084 if (annotation.atX()) { | |
1085 textAnnotation = new CollisionFreeXYTextAnnotation( | |
1086 annotation.getText(), annotation.getPos(), area.ofGround(TEXT_OFF)); | |
1087 // OPTIMIZE externalize the calculation involving PI. | |
1088 textAnnotation.setRotationAngle(270f*Math.PI/180f); | |
1089 // Style the line. | |
1090 if (lineStyle != null) { | |
1091 lineAnnotation = new XYLineAnnotation(annotation.getPos(), | |
1092 area.atGround(), annotation.getPos(), area.ofGround(LINE_OFF), | |
1093 new BasicStroke(lineStyle.getWidth()),lineStyle.getColor()); | |
1094 } | |
1095 else { | |
1096 lineAnnotation = new XYLineAnnotation(annotation.getPos(), | |
1097 area.atGround(), annotation.getPos(), area.ofGround(LINE_OFF)); | |
1098 } | |
1099 } | |
1100 else { | |
1101 textAnnotation = new CollisionFreeXYTextAnnotation( | |
1102 annotation.getText(), area.ofLeft(TEXT_OFF), annotation.getPos()); | |
1103 // Style the line. | |
1104 if (lineStyle != null) { | |
1105 lineAnnotation = new XYLineAnnotation(area.atLeft(), | |
1106 annotation.getPos(), area.ofLeft(LINE_OFF), | |
1107 annotation.getPos(), new BasicStroke(lineStyle.getWidth()), | |
1108 lineStyle.getColor()); | |
1109 } | |
1110 else { | |
1111 lineAnnotation = new XYLineAnnotation(area.atLeft(), | |
1112 annotation.getPos(), area.ofLeft(LINE_OFF), annotation.getPos()); | |
1113 } | |
1114 } | |
1115 | |
1116 // Style the text. | |
1117 if (textStyle != null) { | |
1118 textStyle.apply(textAnnotation); | |
1119 } | |
1120 | |
1121 // Add the Annotations to renderer. | |
1122 textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT); | |
1123 textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT); | |
1124 | |
1125 plot.getRenderer().addAnnotation(textAnnotation, | |
1126 org.jfree.ui.Layer.BACKGROUND); | |
1127 plot.getRenderer().addAnnotation(lineAnnotation, | |
1128 org.jfree.ui.Layer.BACKGROUND); | |
1129 } | |
1130 | |
1131 | |
1132 /** Add annotations (Sticky, Text and hyk zones). */ | |
1133 public void addAnnotationsToRenderer(XYPlot plot) { | |
1134 logger.debug("XYChartGenerator.addAnnotationsToRenderer"); | |
1090 | 1135 |
1091 if (annotations == null) { | 1136 if (annotations == null) { |
1092 logger.debug("XYChartGenerator.addBoxAnnotations: no annotations."); | 1137 logger.debug("XYChartGenerator.addBoxAnnotations: no annotations."); |
1093 return; | 1138 return; |
1094 } | 1139 } |
1095 | 1140 |
1096 // Paints for the boxes/lines. | 1141 // Paints for the boxes/lines. |
1097 Stroke basicStroke = new BasicStroke(1.0f); | 1142 Stroke basicStroke = new BasicStroke(1.0f); |
1098 | 1143 |
1099 Paint linePaint = new Color(255,0,0,60); | 1144 Paint linePaint = new Color(255, 0,0,60); |
1100 Paint fillPaint = new Color(0,255,0,60); | 1145 Paint fillPaint = new Color(0, 255,0,60); |
1101 Paint tranPaint = new Color(0,0,0,0); | 1146 Paint tranPaint = new Color(0, 0,0, 0); |
1102 | 1147 |
1103 // Pre-calculated positions on y axis. | 1148 // OPTMIMIZE: Pre-calculate positions |
1104 double fillPercent = 0.03; | 1149 Area area = new Area( |
1105 double low = getLowestYValue(plot); | 1150 plot.getDomainAxis(0).getRange(), |
1106 double up = getUppestYValue(plot); | 1151 plot.getRangeAxis().getRange()); |
1107 double upb = low + (up - low) * fillPercent; | 1152 |
1108 double upt = low + (up - low) * fillPercent/2.0d; | 1153 // Walk over all Annotation sets. |
1109 | |
1110 | |
1111 for (FLYSAnnotation fa: annotations) { | 1154 for (FLYSAnnotation fa: annotations) { |
1155 | |
1112 // Access text styling, if any. | 1156 // Access text styling, if any. |
1113 Document theme = fa.getTheme(); | 1157 Document theme = fa.getTheme(); |
1114 ThemeAccess.TextStyle textStyle = null; | 1158 ThemeAccess.TextStyle textStyle = null; |
1159 ThemeAccess.LineStyle lineStyle = null; | |
1160 | |
1161 // Get Themeing information and add legend item. | |
1115 if (theme != null) { | 1162 if (theme != null) { |
1116 ThemeAccess themeAccess = new ThemeAccess(theme); | 1163 ThemeAccess themeAccess = new ThemeAccess(theme); |
1117 textStyle = themeAccess.parseTextStyle(); | 1164 textStyle = themeAccess.parseTextStyle(); |
1118 } | 1165 lineStyle = themeAccess.parseLineStyle(); |
1119 | 1166 LegendItemCollection lic = new LegendItemCollection(); |
1120 // For each zone, create a box to fill with color, a box to draw | 1167 LegendItemCollection old = plot.getFixedLegendItems(); |
1121 // the lines and a text to display the type. | 1168 lic.add(createLegendItem(theme, fa.getLabel())); |
1169 // (Re-)Add prior legend entries. | |
1170 if (old != null) { | |
1171 old.addAll(lic); | |
1172 } | |
1173 else { | |
1174 old = lic; | |
1175 } | |
1176 plot.setFixedLegendItems(old); | |
1177 } | |
1178 | |
1179 // The 'Sticky' Annotations (at axis, with line and text). | |
1180 for (StickyAxisAnnotation sta: fa.getAxisTextAnnotations()) { | |
1181 addStickyAnnotation(sta, plot, area, lineStyle, textStyle); | |
1182 } | |
1183 | |
1184 // The not yet implemented other Text Annotations. | |
1185 for (XYTextAnnotation ta: fa.getTextAnnotations()) { | |
1186 // TODO implement, one we have textannotations | |
1187 } | |
1188 | |
1189 // Hyks. | |
1122 for (HYKFactory.Zone zone: fa.getBoxes()) { | 1190 for (HYKFactory.Zone zone: fa.getBoxes()) { |
1191 // For each zone, create a box to fill with color, a box to draw | |
1192 // the lines and a text to display the type. | |
1123 fillPaint = colorForHYKZone(zone.getName()); | 1193 fillPaint = colorForHYKZone(zone.getName()); |
1124 | 1194 |
1125 XYBoxAnnotation boxA = new XYBoxAnnotation(zone.getFrom(), low, | 1195 XYBoxAnnotation boxA = new XYBoxAnnotation(zone.getFrom(), area.atGround(), |
1126 zone.getTo(), upb, basicStroke, tranPaint, fillPaint); | 1196 zone.getTo(), area.ofGround(0.03f), basicStroke, tranPaint, fillPaint); |
1127 XYBoxAnnotation boxB = new XYBoxAnnotation(zone.getFrom(), low, | 1197 XYBoxAnnotation boxB = new XYBoxAnnotation(zone.getFrom(), area.atGround(), |
1128 zone.getTo(), up, basicStroke, fillPaint, tranPaint); | 1198 zone.getTo(), area.atTop(), basicStroke, fillPaint, tranPaint); |
1129 | 1199 |
1130 XYTextAnnotation tex = new XYTextAnnotation(zone.getName(), | 1200 XYTextAnnotation tex = new XYTextAnnotation(zone.getName(), |
1131 zone.getFrom() + (zone.getTo() - zone.getFrom()) / 2.0d, | 1201 zone.getFrom() + (zone.getTo() - zone.getFrom()) / 2.0d, |
1132 upt); | 1202 area.ofGround(0.015f)); |
1133 if (textStyle != null) { | 1203 if (textStyle != null) { |
1134 textStyle.apply(tex); | 1204 textStyle.apply(tex); |
1135 } | 1205 } |
1136 | 1206 |
1137 plot.getRenderer().addAnnotation(boxA); | 1207 plot.getRenderer().addAnnotation(boxA, org.jfree.ui.Layer.BACKGROUND); |
1138 plot.getRenderer().addAnnotation(boxB); | 1208 plot.getRenderer().addAnnotation(boxB, org.jfree.ui.Layer.BACKGROUND); |
1139 plot.getRenderer().addAnnotation(tex); | 1209 plot.getRenderer().addAnnotation(tex, org.jfree.ui.Layer.BACKGROUND); |
1140 } | 1210 } |
1141 } | 1211 } |
1142 } | 1212 } |
1143 | 1213 |
1144 | 1214 |
1551 axisSections.add(ySection); | 1621 axisSections.add(ySection); |
1552 } | 1622 } |
1553 | 1623 |
1554 return axisSections; | 1624 return axisSections; |
1555 } | 1625 } |
1626 | |
1627 | |
1628 /** Two Ranges that span a rectangular area. */ | |
1629 public static class Area { | |
1630 protected Range xRange; | |
1631 protected Range yRange; | |
1632 | |
1633 public Area(Range rangeX, Range rangeY) { | |
1634 this.xRange = rangeX; | |
1635 this.yRange = rangeY; | |
1636 } | |
1637 | |
1638 public double ofLeft(double percent) { | |
1639 return xRange.getLowerBound() | |
1640 + xRange.getLength() * percent; | |
1641 } | |
1642 | |
1643 public double ofGround(double percent) { | |
1644 return yRange.getLowerBound() | |
1645 + yRange.getLength() * percent; | |
1646 } | |
1647 | |
1648 public double atTop() { | |
1649 return yRange.getUpperBound(); | |
1650 } | |
1651 | |
1652 public double atGround() { | |
1653 return yRange.getLowerBound(); | |
1654 } | |
1655 | |
1656 public double atLeft() { | |
1657 return xRange.getLowerBound(); | |
1658 } | |
1659 } | |
1556 } | 1660 } |
1557 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : | 1661 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |