comparison artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixWQCurveGenerator.java @ 7691:fa4fbd66e752

(issue1579) Fix axes syncronisation at Gauges The SyncNumberAxis was completely broken. It only synced in one direction and even that did not work correctly when data was added to the axis (and the syncAxis rescaled but forgot the old axis) then there were lots of ways to bypass that scaling. And i also think the trans calculation was wrong. It has been replaced by a "mostly" simple method to just keep the W in M and W in CM+Datum axes in sync. I say "Mostly" because it had to deal with the Bounds interface.
author Andre Heinecke <aheinecke@intevation.de>
date Fri, 13 Dec 2013 19:03:00 +0100
parents 4dbbdf0c8b2c
children 75ef6963f1c9
comparison
equal deleted inserted replaced
7690:4bbd222e6b7f 7691:fa4fbd66e752
45 import org.dive4elements.river.artifacts.model.fixings.QWD; 45 import org.dive4elements.river.artifacts.model.fixings.QWD;
46 import org.dive4elements.river.artifacts.model.fixings.QWI; 46 import org.dive4elements.river.artifacts.model.fixings.QWI;
47 import org.dive4elements.river.artifacts.resources.Resources; 47 import org.dive4elements.river.artifacts.resources.Resources;
48 import org.dive4elements.river.exports.ChartGenerator; 48 import org.dive4elements.river.exports.ChartGenerator;
49 import org.dive4elements.river.exports.DischargeCurveGenerator; 49 import org.dive4elements.river.exports.DischargeCurveGenerator;
50 import org.dive4elements.river.exports.SyncNumberAxis;
51 import org.dive4elements.river.exports.StyledSeriesBuilder; 50 import org.dive4elements.river.exports.StyledSeriesBuilder;
52 import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; 51 import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation;
53 import org.dive4elements.river.jfree.RiverAnnotation; 52 import org.dive4elements.river.jfree.RiverAnnotation;
54 import org.dive4elements.river.jfree.JFreeUtil; 53 import org.dive4elements.river.jfree.JFreeUtil;
55 import org.dive4elements.river.jfree.StickyAxisAnnotation; 54 import org.dive4elements.river.jfree.StickyAxisAnnotation;
58 import org.dive4elements.river.model.River; 57 import org.dive4elements.river.model.River;
59 import org.dive4elements.river.themes.ThemeDocument; 58 import org.dive4elements.river.themes.ThemeDocument;
60 import org.dive4elements.river.utils.RiverUtils; 59 import org.dive4elements.river.utils.RiverUtils;
61 import org.dive4elements.river.java2d.ShapeUtils; 60 import org.dive4elements.river.java2d.ShapeUtils;
62 61
62 import org.dive4elements.river.jfree.Bounds;
63 import org.dive4elements.river.jfree.DoubleBounds;
64
65 import org.jfree.data.Range;
66
63 /** 67 /**
64 * Generator for WQ fixing charts. 68 * Generator for WQ fixing charts.
65 * @author <a href="mailto:christian.lins@intevation.de">Christian Lins</a> 69 * @author <a href="mailto:christian.lins@intevation.de">Christian Lins</a>
66 */ 70 */
67 public class FixWQCurveGenerator 71 public class FixWQCurveGenerator
109 113
110 114
111 /** Needed to access data to create subtitle. */ 115 /** Needed to access data to create subtitle. */
112 protected D4EArtifact artifact; 116 protected D4EArtifact artifact;
113 117
114 // TODO dupe of ComputedDischargeCurveGenerator
115 protected SyncNumberAxis secondYAxis;
116 // TODO dupe of ComputedDischargeCurveGenerator
117 protected NumberAxis firstYAxis;
118
119
120 /**
121 * Create Y (range) axis for given index, here with a special axis
122 * that depends on other axis (does translation and scaling for
123 * special case at gauge in cm).
124 */
125 // TODO dupe of ComputedDischargeCurveGenerator
126 @Override
127 protected NumberAxis createYAxis(int index) {
128 logger.debug("createYAxis: " + index);
129 if (index == 1) {
130 firstYAxis = super.createYAxis(1);
131 if (secondYAxis != null) {
132 secondYAxis.setProxyAxis(firstYAxis);
133 }
134 return firstYAxis;
135 }
136 YAxisWalker walker = getYAxisWalker();
137
138 Font labelFont = new Font(
139 DEFAULT_FONT_NAME,
140 Font.BOLD,
141 getYAxisFontSize(index));
142
143 SyncNumberAxis axis = new SyncNumberAxis(
144 walker.getId(index),
145 getYAxisLabel(index),
146 firstYAxis);
147
148 axis.setAutoRangeIncludesZero(false);
149 axis.setLabelFont(labelFont);
150 axis.setTickLabelFont(labelFont);
151 axis.setShift((double)-getCurrentGaugeDatum());
152
153 secondYAxis = axis;
154 return axis;
155 }
156
157 /** Returns value != 0 if the current km is not at a gauge. */ 118 /** Returns value != 0 if the current km is not at a gauge. */
158 public double getCurrentGaugeDatum() { 119 public double getCurrentGaugeDatum() {
159 Object ckm = context.getContextValue(CURRENT_KM); 120 Object ckm = context.getContextValue(CURRENT_KM);
160 if (ckm != null) { 121 if (ckm != null) {
161 return DischargeCurveGenerator.getCurrentGaugeDatum( 122 return DischargeCurveGenerator.getCurrentGaugeDatum(
170 protected void adjustAxes(XYPlot plot) { 131 protected void adjustAxes(XYPlot plot) {
171 super.adjustAxes(plot); 132 super.adjustAxes(plot);
172 if (getCurrentGaugeDatum() != 0d) { 133 if (getCurrentGaugeDatum() != 0d) {
173 // Show the W[*m] axis even if there is no data. 134 // Show the W[*m] axis even if there is no data.
174 plot.setRangeAxis(1, createYAxis(YAXIS.W.idx)); 135 plot.setRangeAxis(1, createYAxis(YAXIS.W.idx));
175 } 136 syncWAxisRanges();
137 }
138 }
139
140 // XXX This is a copy of DischargeCurveGenerator syncWAxisRanges
141 // even without fancy Q Symetry this class should inherit
142 // from there..
143 protected void syncWAxisRanges() {
144 // Syncronizes the ranges of both W Axes to make sure
145 // that the Data matches for both axes.
146 Bounds boundsInMGauge = getYBounds(YAXIS.W.idx);
147 Bounds boundsInCM = getYBounds(YAXIS.WCm.idx);
148
149 // XXX Q-Symetry: I am assuming here that there can only
150 // be a fixed Range for WinM as this is currently the only
151 // thing that is configureable.
152 Range fixedWinMRange = getRangeForAxisFromSettings(
153 getYAxisWalker().getId(YAXIS.W.idx));
154
155 // The combination of Range and Bounds is crazy..
156 if (fixedWinMRange != null) {
157 boundsInMGauge = new DoubleBounds(fixedWinMRange.getLowerBound(),
158 fixedWinMRange.getUpperBound());
159 }
160
161 logger.debug("Syncing Axis Bounds. Bounds W: " + boundsInMGauge.toString() +
162 " Bounds Wcm: " + boundsInCM.toString());
163
164 double datum = getCurrentGaugeDatum();
165
166 // Convert boundsInMGauge to Datum+cm
167 double convertedLower = ((Double)boundsInMGauge.getLower() - datum) * 100;
168 double convertedUpper = ((Double)boundsInMGauge.getUpper() - datum) * 100;
169 Bounds convertedBounds = new DoubleBounds(convertedLower, convertedUpper);
170
171 // Now combine both Ranges
172 boundsInCM = boundsInCM.combine(convertedBounds);
173
174 // Recalculate absolute bounds
175 boundsInMGauge = new DoubleBounds((Double)boundsInCM.getLower() / 100d + datum,
176 (Double)boundsInCM.getUpper() / 100d + datum);
177
178 // Set the new combined bounds
179 setYBounds(YAXIS.W.idx, boundsInMGauge);
180 setYBounds(YAXIS.WCm.idx, boundsInCM);
181 logger.debug("Synced Bounds W: " + boundsInMGauge.toString() +
182 " Bounds Wcm: " + boundsInCM.toString());
176 } 183 }
177 184
178 @Override 185 @Override
179 public void doOut(ArtifactAndFacet aaf, ThemeDocument doc, boolean visible) { 186 public void doOut(ArtifactAndFacet aaf, ThemeDocument doc, boolean visible) {
180 logger.debug("doOut: " + aaf.getFacetName()); 187 logger.debug("doOut: " + aaf.getFacetName());

http://dive4elements.wald.intevation.org