Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java @ 1038:4dcc635d6ca6
Extracted and renamed CustomAnnotation to StickyAxisAnnotation. Also removed
needless imports.
flys-artifacts/trunk@2499 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Felix Wolfsteller <felix.wolfsteller@intevation.de> |
---|---|
date | Wed, 17 Aug 2011 12:53:55 +0000 |
parents | 75cf1b11c97e |
children | 5411a33014e0 |
comparison
equal
deleted
inserted
replaced
1037:75cf1b11c97e | 1038:4dcc635d6ca6 |
---|---|
1 package de.intevation.flys.exports; | 1 package de.intevation.flys.exports; |
2 | 2 |
3 import java.util.ArrayList; | 3 import java.util.ArrayList; |
4 import java.util.Iterator; | |
5 import java.util.List; | 4 import java.util.List; |
6 | 5 |
7 import org.apache.log4j.Logger; | 6 import org.apache.log4j.Logger; |
8 | 7 |
9 import java.awt.Shape; | |
10 import java.awt.geom.Rectangle2D; | |
11 import java.awt.geom.Line2D; | |
12 | |
13 import org.jfree.chart.annotations.XYLineAnnotation; | |
14 import org.jfree.chart.annotations.XYTextAnnotation; | |
15 import org.jfree.chart.JFreeChart; | 8 import org.jfree.chart.JFreeChart; |
16 import org.jfree.chart.axis.NumberAxis; | 9 import org.jfree.chart.axis.NumberAxis; |
17 import org.jfree.chart.axis.ValueAxis; | 10 import org.jfree.chart.axis.ValueAxis; |
18 import org.jfree.chart.plot.XYPlot; | 11 import org.jfree.chart.plot.XYPlot; |
19 import org.jfree.chart.title.TextTitle; | 12 import org.jfree.chart.title.TextTitle; |
20 import org.jfree.data.Range; | 13 import org.jfree.data.Range; |
21 import org.jfree.data.xy.XYSeries; | 14 import org.jfree.data.xy.XYSeries; |
22 import org.jfree.ui.TextAnchor; | 15 import org.jfree.ui.TextAnchor; |
23 import org.jfree.chart.plot.PlotRenderingInfo; | |
24 import org.jfree.text.TextUtilities; | |
25 import org.jfree.chart.entity.XYAnnotationEntity; | |
26 import org.jfree.chart.plot.PlotOrientation; | |
27 import org.jfree.ui.RectangleEdge; | |
28 import org.jfree.chart.plot.Plot; | |
29 import org.jfree.chart.ChartRenderingInfo; | |
30 import org.jfree.chart.util.LineUtilities; | |
31 | 16 |
32 import org.w3c.dom.Document; | 17 import org.w3c.dom.Document; |
33 | 18 |
34 import de.intevation.artifacts.Artifact; | 19 import de.intevation.artifacts.Artifact; |
35 | 20 |
39 | 24 |
40 import de.intevation.flys.artifacts.model.FacetTypes; | 25 import de.intevation.flys.artifacts.model.FacetTypes; |
41 import de.intevation.flys.artifacts.model.WQKms; | 26 import de.intevation.flys.artifacts.model.WQKms; |
42 | 27 |
43 import de.intevation.flys.model.Annotation; | 28 import de.intevation.flys.model.Annotation; |
44 | |
45 /** | |
46 * Custom Annotations class that is drawn only if no collisions with other | |
47 * already drawn CustomAnnotations in current plot are found. | |
48 * Draws a given text and a line to it from either axis. | |
49 */ | |
50 class CustomAnnotation extends XYTextAnnotation { | |
51 | |
52 /** Logger for this class. */ | |
53 private static Logger logger = | |
54 Logger.getLogger(CustomAnnotation.class); | |
55 | |
56 /** Simplified view on axes. */ | |
57 public static enum SimpleAxis { | |
58 X_AXIS, /** Usually "horizontal". */ | |
59 Y_AXIS /** Usually "vertical". */ | |
60 } | |
61 | |
62 /** Which axis to stick to. */ | |
63 protected SimpleAxis stickyAxis = SimpleAxis.X_AXIS; | |
64 | |
65 | |
66 /** | |
67 * Trivial constructor. | |
68 * | |
69 * @param text Text to display. | |
70 * @param x X-position in dataspace (typical horizontal, in km). | |
71 * @param y Y-position in dataspace (typical vertical, in m). | |
72 */ | |
73 public CustomAnnotation(String text, float x, float y) { | |
74 super(text, x, y); | |
75 } | |
76 | |
77 | |
78 /** | |
79 * Sets the "sticky axis" (whether to draw annotations at the | |
80 * X- or the Y-Axis. | |
81 * | |
82 * @param stickyAxis axis to stick to. | |
83 */ | |
84 public void setStickyAxis(SimpleAxis stickyAxis) { | |
85 this.stickyAxis = stickyAxis; | |
86 } | |
87 | |
88 | |
89 /** | |
90 * Draws a small line at axis where this annotation resides. | |
91 * | |
92 * @param g2 the graphics device. | |
93 * @param dataArea the data area. | |
94 * @param domainAxis the domain axis. | |
95 * @param rangeAxis the range axis. | |
96 * @param domainEdge the domain edge. | |
97 * @param rangeEdge the range edge. | |
98 * @param orientation the plot orientation. | |
99 */ | |
100 protected void drawAxisMark( | |
101 java.awt.Graphics2D g2, | |
102 java.awt.geom.Rectangle2D dataArea, | |
103 ValueAxis domainAxis, | |
104 ValueAxis rangeAxis, | |
105 RectangleEdge domainEdge, | |
106 RectangleEdge rangeEdge, | |
107 PlotOrientation orientation) { | |
108 float j2DX1 = 0.0f; | |
109 float j2DX2 = 0.0f; | |
110 float j2DY1 = 0.0f; | |
111 float j2DY2 = 0.0f; | |
112 float x = (float) getX(); | |
113 float y = (float) getY(); | |
114 /* When dependent on X/Y-Axis and orientation, following | |
115 can be used as a base: | |
116 if (orientation == PlotOrientation.VERTICAL) { | |
117 j2DX1 = (float) domainAxis.valueToJava2D(x, dataArea, | |
118 domainEdge); | |
119 j2DY1 = (float) rangeAxis.valueToJava2D(y, dataArea, | |
120 rangeEdge); | |
121 j2DX2 = (float) domainAxis.valueToJava2D(x, dataArea, | |
122 domainEdge); | |
123 j2DY2 = (float) rangeAxis.valueToJava2D(y, dataArea, | |
124 rangeEdge); | |
125 } | |
126 else if (orientation == PlotOrientation.HORIZONTAL) { | |
127 j2DY1 = (float) domainAxis.valueToJava2D(x, dataArea, | |
128 domainEdge); | |
129 j2DX1 = (float) rangeAxis.valueToJava2D(y, dataArea, | |
130 rangeEdge); | |
131 j2DY2 = (float) domainAxis.valueToJava2D(x, dataArea, | |
132 domainEdge); | |
133 j2DX2 = (float) rangeAxis.valueToJava2D(y, dataArea, | |
134 rangeEdge); | |
135 } | |
136 | |
137 g2.setPaint(this.paint); | |
138 g2.setStroke(this.stroke); | |
139 */ | |
140 j2DY1 = (float) RectangleEdge.coordinate(dataArea, domainEdge); | |
141 j2DY2 = j2DY1 - 0.10f * (float) | |
142 (rangeAxis.getRange().getUpperBound() | |
143 - rangeAxis.getRange().getLowerBound()); | |
144 j2DX1 = (float) domainAxis.valueToJava2D(x, dataArea, domainEdge); | |
145 j2DX2 = j2DX1; | |
146 | |
147 Line2D line = new Line2D.Float(j2DX1, j2DY1, j2DX2, j2DY2); | |
148 | |
149 // line is clipped to avoid JRE bug 6574155, for more info | |
150 // see JFreeChart bug 2221495 | |
151 boolean visible = LineUtilities.clipLine(line, dataArea); | |
152 if (visible) { | |
153 g2.draw(line); | |
154 } | |
155 } | |
156 | |
157 | |
158 /** | |
159 * Draw the Annotiation if it does not collide with other already drawn | |
160 * Annotations. | |
161 * | |
162 * @param g2 the graphics device. | |
163 * @param plot the plot. | |
164 * @param dataArea the data area. | |
165 * @param domainAxis the domain axis. | |
166 * @param rangeAxis the range axis. | |
167 * @param rendererIndex the render index. | |
168 * @param info state information, escpecially collects info about | |
169 * already drawn shapes (and thus annotations), used | |
170 * for collision detection. | |
171 */ | |
172 @Override | |
173 public void draw( | |
174 java.awt.Graphics2D g2, | |
175 XYPlot plot, | |
176 java.awt.geom.Rectangle2D dataArea, | |
177 ValueAxis domainAxis, | |
178 ValueAxis rangeAxis, | |
179 int rendererIndex, | |
180 PlotRenderingInfo info) { | |
181 | |
182 if (info == null) | |
183 return; | |
184 | |
185 // Calculate the bounding box. | |
186 ChartRenderingInfo chartInfo = info.getOwner(); | |
187 | |
188 PlotOrientation orientation = plot.getOrientation(); | |
189 RectangleEdge domainEdge = Plot.resolveDomainAxisLocation( | |
190 plot.getDomainAxisLocation(), orientation); | |
191 RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation( | |
192 plot.getRangeAxisLocation(), orientation); | |
193 float anchorX = (float) domainAxis.valueToJava2D( | |
194 getX(), dataArea, domainEdge); | |
195 float anchorY = (float) rangeAxis.valueToJava2D( | |
196 getY(), dataArea, rangeEdge); | |
197 if (orientation == PlotOrientation.HORIZONTAL) { | |
198 float tempAnchor = anchorX; | |
199 anchorX = anchorY; | |
200 anchorY = tempAnchor; | |
201 } | |
202 | |
203 // Always draw the small line at axis. | |
204 drawAxisMark(g2, dataArea, domainAxis, rangeAxis, domainEdge, | |
205 rangeEdge, orientation); | |
206 | |
207 g2.setFont(getFont()); | |
208 Shape hotspot = TextUtilities.calculateRotatedStringBounds( | |
209 getText(), g2, anchorX, anchorY, getTextAnchor(), | |
210 getRotationAngle(), getRotationAnchor()); | |
211 Rectangle2D hotspotBox = hotspot.getBounds2D(); | |
212 // Check for collisions with other XYAnnotations. | |
213 for (Iterator i = chartInfo.getEntityCollection().iterator(); | |
214 i.hasNext(); ) { | |
215 Object next = i.next(); | |
216 // Collision with other stuff than XYAnnotations are okay. | |
217 if (next instanceof XYAnnotationEntity) { | |
218 XYAnnotationEntity drawnShape = (XYAnnotationEntity) next; | |
219 if (drawnShape.getArea().intersects(hotspotBox)) { | |
220 // Found collision, early stop. | |
221 return; | |
222 } | |
223 } | |
224 } | |
225 | |
226 // Actuall drawing. | |
227 if (getBackgroundPaint() != null) { | |
228 g2.setPaint(getBackgroundPaint()); | |
229 g2.fill(hotspot); | |
230 } | |
231 g2.setPaint(getPaint()); | |
232 TextUtilities.drawRotatedString(getText(), g2, anchorX, anchorY, | |
233 getTextAnchor(), getRotationAngle(), getRotationAnchor()); | |
234 // Draw outline. | |
235 if (false) { | |
236 g2.setStroke(getOutlineStroke()); | |
237 g2.setPaint(getOutlinePaint()); | |
238 g2.draw(hotspot); | |
239 } | |
240 | |
241 // Add info that we have drawn this Annotation. | |
242 addEntity(info, hotspot, rendererIndex, getToolTipText(), getURL()); | |
243 } | |
244 } | |
245 | 29 |
246 | 30 |
247 /** | 31 /** |
248 * An OutGenerator that generates discharge curves. | 32 * An OutGenerator that generates discharge curves. |
249 * | 33 * |
355 * @param axis the value axis. | 139 * @param axis the value axis. |
356 */ | 140 */ |
357 protected void redoAnnotations(XYPlot plot, ValueAxis axis) { | 141 protected void redoAnnotations(XYPlot plot, ValueAxis axis) { |
358 plot.clearAnnotations(); | 142 plot.clearAnnotations(); |
359 // TODO Position calculation could/should be done in | 143 // TODO Position calculation could/should be done in |
360 // the CustomAnnotation-Implementation itself. | 144 // the StickyAxisAnnotation-Implementation itself. |
361 ValueAxis yAxis = plot.getRangeAxis(); | 145 ValueAxis yAxis = plot.getRangeAxis(); |
362 float posY = 140.f; | 146 float posY = 140.f; |
363 if (yAxis != null) { | 147 if (yAxis != null) { |
364 posY = (float) yAxis.getRange().getLowerBound(); | 148 posY = (float) yAxis.getRange().getLowerBound(); |
365 posYLess = posY; | |
366 // Add some (2%) space between Text and axis. | 149 // Add some (2%) space between Text and axis. |
367 posY += 0.02f * (yAxis.getRange().getUpperBound() | 150 posY += 0.02f * (yAxis.getRange().getUpperBound() |
368 - yAxis.getRange().getLowerBound()); | 151 - yAxis.getRange().getLowerBound()); |
369 } | 152 } |
370 | 153 |
371 // Add all annotations. | 154 // Add all annotations. |
372 for (Annotation a: annotations) { | 155 for (Annotation a: annotations) { |
373 float posX = (float) a.getRange().getA().doubleValue(); | 156 float posX = (float) a.getRange().getA().doubleValue(); |
374 String text = a.getPosition().getValue(); | 157 String text = a.getPosition().getValue(); |
375 | 158 |
376 XYTextAnnotation ta = new CustomAnnotation(text, posX, posY); | 159 StickyAxisAnnotation ta = new StickyAxisAnnotation(text, posX, posY); |
377 double rotation = 270.0f * (Math.PI / 180.0f); | 160 double rotation = 270.0f * (Math.PI / 180.0f); |
378 ta.setRotationAngle(rotation); | 161 ta.setRotationAngle(rotation); |
379 ta.setRotationAnchor(TextAnchor.CENTER_LEFT); | 162 ta.setRotationAnchor(TextAnchor.CENTER_LEFT); |
380 ta.setTextAnchor(TextAnchor.CENTER_LEFT); | 163 ta.setTextAnchor(TextAnchor.CENTER_LEFT); |
381 plot.getRenderer().addAnnotation(ta); | 164 plot.getRenderer().addAnnotation(ta); |