comparison flys-artifacts/src/main/java/de/intevation/flys/exports/XYChartGenerator.java @ 2163:105097966111

Theoretically allow annotations on second y ais. Practically allow Q MainValues on Q Axis in Duration Curves. flys-artifacts/trunk@3750 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Mon, 23 Jan 2012 14:18:53 +0000
parents c68f4f227c09
children a79d5cd26083
comparison
equal deleted inserted replaced
2162:df70f14af981 2163:105097966111
88 protected int axisSymbol; 88 protected int axisSymbol;
89 /** List of assigned datasets (in order). */ 89 /** List of assigned datasets (in order). */
90 protected List<XYDataset> datasets; 90 protected List<XYDataset> datasets;
91 /** Range to use to include all given datasets. */ 91 /** Range to use to include all given datasets. */
92 protected Range range; 92 protected Range range;
93 /** Index of axis in plot. */
94 protected int plotAxisIndex;
93 95
94 /** Create AxisDataset. */ 96 /** Create AxisDataset. */
95 public AxisDataset(int symb) { 97 public AxisDataset(int symb) {
96 this.axisSymbol = symb; 98 this.axisSymbol = symb;
97 datasets = new ArrayList<XYDataset>(); 99 datasets = new ArrayList<XYDataset>();
133 } 135 }
134 136
135 /** True if no datasets given. */ 137 /** True if no datasets given. */
136 public boolean isEmpty() { 138 public boolean isEmpty() {
137 return this.datasets.isEmpty(); 139 return this.datasets.isEmpty();
140 }
141
142 /** Set the 'real' axis index that this axis is mapped to. */
143 public void setPlotAxisIndex(int axisIndex) {
144 this.plotAxisIndex = axisIndex;
145 }
146
147 /** Get the 'real' axis index that this axis is mapped to. */
148 public int getPlotAxisIndex() {
149 return this.plotAxisIndex;
138 } 150 }
139 } // class AxisDataset 151 } // class AxisDataset
140 152
141 153
142 /** 154 /**
616 applyThemes(plot, (XYSeriesCollection) dataset, 628 applyThemes(plot, (XYSeriesCollection) dataset,
617 datasetIndex, 629 datasetIndex,
618 axisDataset.isArea((XYSeriesCollection)dataset)); 630 axisDataset.isArea((XYSeriesCollection)dataset));
619 datasetIndex++; 631 datasetIndex++;
620 } 632 }
633 axisDataset.setPlotAxisIndex(axisIndex);
621 axisIndex++; 634 axisIndex++;
622 } 635 }
623 } 636 }
624 } 637 }
625 638
626 639
627 /** 640 /**
628 * Registers an area to be drawn. 641 * Registers an area to be drawn.
629 * @param lower the lower curve to draw the area from. 642 * @param area Area to be drawn.
630 * @param upper the upper curve to draw the ara from. 643 * @param index 'axis index'
644 * @param visible Whether or not to be visible (important for range calculations).
631 */ 645 */
632 public void addAreaSeries(StyledAreaSeriesCollection area, int index, boolean visible) { 646 public void addAreaSeries(StyledAreaSeriesCollection area, int index, boolean visible) {
633 if (area == null) { 647 if (area == null) {
634 logger.warn("Cannot yet render above/under curve."); 648 logger.warn("Cannot yet render above/under curve.");
635 return; 649 return;
653 667
654 /** 668 /**
655 * Add given series if visible, if not visible adjust ranges (such that 669 * Add given series if visible, if not visible adjust ranges (such that
656 * all points in data would be plotted once visible). 670 * all points in data would be plotted once visible).
657 * @param series the dataseries to include in plot. 671 * @param series the dataseries to include in plot.
658 * @param index index of the series and of its axis. 672 * @param index ('symbolic') index of the series and of its axis.
659 * @param visible whether or not the data should be plotted. 673 * @param visible whether or not the data should be plotted.
660 */ 674 */
661 public void addAxisSeries(XYSeries series, int index, boolean visible) { 675 public void addAxisSeries(XYSeries series, int index, boolean visible) {
662 if (series == null) { 676 if (series == null) {
663 return; 677 return;
977 ThemeAccess themeAccess = new ThemeAccess(theme); 991 ThemeAccess themeAccess = new ThemeAccess(theme);
978 Color color = themeAccess.parseLineColorField(); 992 Color color = themeAccess.parseLineColorField();
979 LegendItem li = new LegendItem(name, color); 993 LegendItem li = new LegendItem(name, color);
980 li.setLabelFont(createLegendLabelFont()); 994 li.setLabelFont(createLegendLabelFont());
981 return li; 995 return li;
982 }
983
984
985 /**
986 * Get "lowest" X Value for first axis. This value is exactly at the
987 * border of the plot.
988 * @return lowest value on first 'x'-axis.
989 */
990 protected double getLowestXValue(XYPlot plot) {
991 ValueAxis axis = plot.getDomainAxis();
992 if (axis == null) {
993 logger.warn("No X-Axis to find lowest value for.");
994 }
995 return axis.getRange().getLowerBound();
996 }
997
998
999 /**
1000 * Get "lowest" X Value for first axis. This value is exactly at the
1001 * border of the plot.
1002 * @return highest value on first 'x'-axis.
1003 */
1004 protected double getUppestXValue(XYPlot plot) {
1005 ValueAxis axis = plot.getDomainAxis();
1006 if (axis == null) {
1007 logger.warn("No first Y-Axis to find uppest value for.");
1008 }
1009 return axis.getRange().getUpperBound();
1010 }
1011
1012
1013 /**
1014 * Get "lowest" Y Value for first axis. This value is exactly at the
1015 * border of the plot.
1016 * @return lowest value on first 'y'-axis.
1017 */
1018 protected double getLowestYValue(XYPlot plot) {
1019 ValueAxis yaxis = plot.getRangeAxis(0);
1020 if (yaxis == null) {
1021 logger.warn("No first Y-Axis to find lowest value for.");
1022 }
1023 return yaxis.getRange().getLowerBound();
1024 }
1025
1026
1027 /**
1028 * Get "lowest" Y Value for first axis. This value is exactly at the
1029 * border of the plot.
1030 * @return highest value on first 'y'-axis.
1031 */
1032 protected double getUppestYValue(XYPlot plot) {
1033 ValueAxis yaxis = plot.getRangeAxis(0);
1034 if (yaxis == null) {
1035 logger.warn("No first Y-Axis to find uppest value for.");
1036 }
1037 return yaxis.getRange().getUpperBound();
1038 } 996 }
1039 997
1040 998
1041 /** Get color for hyk zones by their type (which is the name). */ 999 /** Get color for hyk zones by their type (which is the name). */
1042 public Paint colorForHYKZone(String zoneName) { 1000 public Paint colorForHYKZone(String zoneName) {
1079 final float LINE_OFF = 0.02f; 1037 final float LINE_OFF = 0.02f;
1080 1038
1081 XYLineAnnotation lineAnnotation = null; 1039 XYLineAnnotation lineAnnotation = null;
1082 XYTextAnnotation textAnnotation = null; 1040 XYTextAnnotation textAnnotation = null;
1083 1041
1042 int rendererIndex = 0;
1043
1084 if (annotation.atX()) { 1044 if (annotation.atX()) {
1085 textAnnotation = new CollisionFreeXYTextAnnotation( 1045 textAnnotation = new CollisionFreeXYTextAnnotation(
1086 annotation.getText(), annotation.getPos(), area.ofGround(TEXT_OFF)); 1046 annotation.getText(), annotation.getPos(), area.ofGround(TEXT_OFF));
1087 // OPTIMIZE externalize the calculation involving PI. 1047 // OPTIMIZE externalize the calculation involving PI.
1088 textAnnotation.setRotationAngle(270f*Math.PI/180f); 1048 textAnnotation.setRotationAngle(270f*Math.PI/180f);
1089 // Style the line. 1049 // Style the line.
1090 if (lineStyle != null) { 1050 if (lineStyle != null) {
1091 lineAnnotation = new XYLineAnnotation(annotation.getPos(), 1051 lineAnnotation = new XYLineAnnotation(annotation.getPos(),
1092 area.atGround(), annotation.getPos(), area.ofGround(LINE_OFF), 1052 area.atGround(), annotation.getPos(), area.ofGround(LINE_OFF),
1093 new BasicStroke(lineStyle.getWidth()),lineStyle.getColor()); 1053 new BasicStroke(lineStyle.getWidth()),lineStyle.getColor());
1054 textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT);
1055 textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
1094 } 1056 }
1095 else { 1057 else {
1096 lineAnnotation = new XYLineAnnotation(annotation.getPos(), 1058 lineAnnotation = new XYLineAnnotation(annotation.getPos(),
1097 area.atGround(), annotation.getPos(), area.ofGround(LINE_OFF)); 1059 area.atGround(), annotation.getPos(), area.ofGround(LINE_OFF));
1060 textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT);
1061 textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
1098 } 1062 }
1099 } 1063 }
1100 else { 1064 else {
1101 textAnnotation = new CollisionFreeXYTextAnnotation( 1065 // Do the more complicated case where we stick to the Y-Axis.
1102 annotation.getText(), area.ofLeft(TEXT_OFF), annotation.getPos()); 1066 // There is one nasty case (duration curves, where annotations
1103 // Style the line. 1067 // might stick to the second y-axis).
1104 if (lineStyle != null) { 1068 AxisDataset dataset = this.datasets.get(
1105 lineAnnotation = new XYLineAnnotation(area.atLeft(), 1069 new Integer(annotation.getAxisSymbol()));
1106 annotation.getPos(), area.ofLeft(LINE_OFF), 1070 if (dataset == null) {
1107 annotation.getPos(), new BasicStroke(lineStyle.getWidth()), 1071 logger.warn("Annotation should stick to unfindable y-axis: "
1108 lineStyle.getColor()); 1072 + annotation.getAxisSymbol());
1073 rendererIndex = 0;
1109 } 1074 }
1110 else { 1075 else {
1111 lineAnnotation = new XYLineAnnotation(area.atLeft(), 1076 rendererIndex = dataset.getPlotAxisIndex();
1112 annotation.getPos(), area.ofLeft(LINE_OFF), annotation.getPos()); 1077 }
1078
1079 if (rendererIndex != 0) {
1080 // OPTIMIZE: Pass a different area to this function,
1081 // do the adding to renderer outside (let this
1082 // function return the annotations).
1083 // Note that this path is travelled rarely.
1084 Area area2 = new Area(plot.getDomainAxis(), plot.getRangeAxis(rendererIndex));
1085 textAnnotation = new CollisionFreeXYTextAnnotation(
1086 annotation.getText(), area2.ofRight(TEXT_OFF), annotation.getPos());
1087 textAnnotation.setRotationAnchor(TextAnchor.CENTER_RIGHT);
1088 textAnnotation.setTextAnchor(TextAnchor.CENTER_RIGHT);
1089 // Style the line.
1090 if (lineStyle != null) {
1091 lineAnnotation = new XYLineAnnotation(area2.ofRight(LINE_OFF),
1092 annotation.getPos(), area2.atRight(),
1093 annotation.getPos(), new BasicStroke(lineStyle.getWidth()),
1094 lineStyle.getColor());
1095 }
1096 else {
1097 lineAnnotation = new XYLineAnnotation(area2.atRight(),
1098 annotation.getPos(), area2.ofRight(LINE_OFF), annotation.getPos());
1099 }
1100 }
1101 else {
1102 textAnnotation = new CollisionFreeXYTextAnnotation(
1103 annotation.getText(), area.ofLeft(TEXT_OFF), annotation.getPos());
1104 textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT);
1105 textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
1106 // Style the line.
1107 if (lineStyle != null) {
1108 lineAnnotation = new XYLineAnnotation(area.atLeft(),
1109 annotation.getPos(), area.ofLeft(LINE_OFF),
1110 annotation.getPos(), new BasicStroke(lineStyle.getWidth()),
1111 lineStyle.getColor());
1112 }
1113 else {
1114 lineAnnotation = new XYLineAnnotation(area.atLeft(),
1115 annotation.getPos(), area.ofLeft(LINE_OFF), annotation.getPos());
1116 }
1113 } 1117 }
1114 } 1118 }
1115 1119
1116 // Style the text. 1120 // Style the text.
1117 if (textStyle != null) { 1121 if (textStyle != null) {
1118 textStyle.apply(textAnnotation); 1122 textStyle.apply(textAnnotation);
1119 } 1123 }
1120 1124
1121 // Add the Annotations to renderer. 1125 // Add the Annotations to renderer.
1122 textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT); 1126 plot.getRenderer(rendererIndex).addAnnotation(textAnnotation,
1123 textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT);
1124
1125 plot.getRenderer().addAnnotation(textAnnotation,
1126 org.jfree.ui.Layer.BACKGROUND); 1127 org.jfree.ui.Layer.BACKGROUND);
1127 plot.getRenderer().addAnnotation(lineAnnotation, 1128 plot.getRenderer(rendererIndex).addAnnotation(lineAnnotation,
1128 org.jfree.ui.Layer.BACKGROUND); 1129 org.jfree.ui.Layer.BACKGROUND);
1129 } 1130 }
1130 1131
1131 1132
1132 /** Add annotations (Sticky, Text and hyk zones). */ 1133 /** Add annotations (Sticky, Text and hyk zones). */
1633 public Area(Range rangeX, Range rangeY) { 1634 public Area(Range rangeX, Range rangeY) {
1634 this.xRange = rangeX; 1635 this.xRange = rangeX;
1635 this.yRange = rangeY; 1636 this.yRange = rangeY;
1636 } 1637 }
1637 1638
1639 public Area(ValueAxis axisX, ValueAxis axisY) {
1640 this.xRange = axisX.getRange();
1641 this.yRange = axisY.getRange();
1642 }
1643
1638 public double ofLeft(double percent) { 1644 public double ofLeft(double percent) {
1639 return xRange.getLowerBound() 1645 return xRange.getLowerBound()
1640 + xRange.getLength() * percent; 1646 + xRange.getLength() * percent;
1641 } 1647 }
1642 1648
1649 public double ofRight(double percent) {
1650 return xRange.getUpperBound()
1651 - xRange.getLength() * percent;
1652 }
1653
1643 public double ofGround(double percent) { 1654 public double ofGround(double percent) {
1644 return yRange.getLowerBound() 1655 return yRange.getLowerBound()
1645 + yRange.getLength() * percent; 1656 + yRange.getLength() * percent;
1646 } 1657 }
1647 1658
1651 1662
1652 public double atGround() { 1663 public double atGround() {
1653 return yRange.getLowerBound(); 1664 return yRange.getLowerBound();
1654 } 1665 }
1655 1666
1667 public double atRight() {
1668 return xRange.getUpperBound();
1669 }
1670
1656 public double atLeft() { 1671 public double atLeft() {
1657 return xRange.getLowerBound(); 1672 return xRange.getLowerBound();
1658 } 1673 }
1659 } 1674 }
1660 } 1675 }

http://dive4elements.wald.intevation.org