# HG changeset patch # User Felix Wolfsteller # Date 1313572580 0 # Node ID e6aff80b59ff42fb4860e69e854b9173c93f367a # Parent 9f69a5f0af98f3bb1251f2e31b4e9b96a70a4f59 Added proof-of-concept collision detection for text annotations. flys-artifacts/trunk@2497 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 9f69a5f0af98 -r e6aff80b59ff flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Tue Aug 16 13:24:50 2011 +0000 +++ b/flys-artifacts/ChangeLog Wed Aug 17 09:16:20 2011 +0000 @@ -1,3 +1,18 @@ +2011-08-16 Felix Wolfsteller + + Implemented proof-of-concept collision-detection when drawing + CustomAnnotations (text only). + + * src/main/java/de/intevation/flys/exports/ChartExportHelper.java: + Pass a fresh ChartRenderingInfo-Object to createBufferedImage, such that + information can be collected while rendering. + + * src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java: + Exploit the fact that XYTextAnnotation already registers drawn shape in the + ChartRenderingInfo if it exists and either an URL or tooltip is set. + Before drawing, calculate own shape and compare against already registered + shapes. + 2011-08-16 Felix Wolfsteller Implemented (yet dummy) custom Annotation class. diff -r 9f69a5f0af98 -r e6aff80b59ff flys-artifacts/src/main/java/de/intevation/flys/exports/ChartExportHelper.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ChartExportHelper.java Tue Aug 16 13:24:50 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/ChartExportHelper.java Wed Aug 17 09:16:20 2011 +0000 @@ -27,6 +27,7 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; +import org.jfree.chart.ChartRenderingInfo; import javax.imageio.ImageIO; @@ -89,9 +90,11 @@ { log.info("export chart as png"); + ChartRenderingInfo info = new ChartRenderingInfo(); + ImageIO.write( chart.createBufferedImage( - width, height, Transparency.BITMASK, null + width, height, Transparency.BITMASK, info ), format, out diff -r 9f69a5f0af98 -r e6aff80b59ff flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java Tue Aug 16 13:24:50 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/LongitudinalSectionGenerator.java Wed Aug 17 09:16:20 2011 +0000 @@ -1,10 +1,14 @@ package de.intevation.flys.exports; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import org.apache.log4j.Logger; +import java.awt.Shape; +import java.awt.geom.Rectangle2D; + import org.jfree.chart.annotations.XYLineAnnotation; import org.jfree.chart.annotations.XYTextAnnotation; import org.jfree.chart.JFreeChart; @@ -16,6 +20,12 @@ import org.jfree.data.xy.XYSeries; import org.jfree.ui.TextAnchor; import org.jfree.chart.plot.PlotRenderingInfo; +import org.jfree.text.TextUtilities; +import org.jfree.chart.entity.XYAnnotationEntity; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.ui.RectangleEdge; +import org.jfree.chart.plot.Plot; +import org.jfree.chart.ChartRenderingInfo; import org.w3c.dom.Document; @@ -49,9 +59,20 @@ /** - * Yet trivial draw without implementing any CustomAnnotation-specific - * feature. + * Draw the Annotiation if it does not collide with other already drawn + * Annotations. + * + * @param g2 the graphics device. + * @param plot the plot. + * @param dataArea the data area. + * @param domainAxis the domain axis. + * @param rangeAxis the range axis. + * @param rendererIndex the render index. + * @param info state information, escpecially collects info about + * already drawn shapes (and thus annotations), used + * for collision detection. */ + @Override public void draw( java.awt.Graphics2D g2, XYPlot plot, @@ -60,6 +81,52 @@ ValueAxis rangeAxis, int rendererIndex, PlotRenderingInfo info) { + + if (info == null) + return; + + // Calculate bounding box as in super.draw(). + // TODO overwrite draw such that even if the annotation gets painted + // the bounding box has to be calculated only once. + ChartRenderingInfo chartInfo = info.getOwner(); + + PlotOrientation orientation = plot.getOrientation(); + RectangleEdge domainEdge = Plot.resolveDomainAxisLocation( + plot.getDomainAxisLocation(), orientation); + RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation( + plot.getRangeAxisLocation(), orientation); + float anchorX = (float) domainAxis.valueToJava2D( + getX(), dataArea, domainEdge); + float anchorY = (float) rangeAxis.valueToJava2D( + getY(), dataArea, rangeEdge); + if (orientation == PlotOrientation.HORIZONTAL) { + float tempAnchor = anchorX; + anchorX = anchorY; + anchorY = tempAnchor; + } + + Shape hotspot = TextUtilities.calculateRotatedStringBounds( + getText(), g2, anchorX, anchorY, getTextAnchor(), + getRotationAngle(), getRotationAnchor()); + Rectangle2D hotspotBox = hotspot.getBounds2D(); + + // Check for collisions with other XYAnnotations. + for (Iterator i = chartInfo.getEntityCollection().iterator(); + i.hasNext(); ) { + Object next = i.next(); + // Collision with other stuff than XYAnnotations are okay. + if (next instanceof XYAnnotationEntity) { + XYAnnotationEntity drawnShape = (XYAnnotationEntity) next; + if (drawnShape.getArea().intersects(hotspotBox)) { + // Found collision, early stop. + return; + } + } + } + + // Set URL of current annotation. This will let super.draw() add + // the relevant info to the PlotRenderingInfo. + setURL(""); super.draw(g2, plot, dataArea, domainAxis, rangeAxis, rendererIndex, info); } } @@ -182,13 +249,10 @@ posY += 0.1f * (yAxis.getRange().getUpperBound() - yAxis.getRange().getLowerBound()); } - double freeFrom = axis.getRange().getLowerBound(); - //logger.warn("Axis lower Bound: " + freeFrom); - // Assuming ordered annotations. + // Add all annotations. for (Annotation a: annotations) { float posX = (float) a.getRange().getA().doubleValue(); - if (posX < freeFrom) { continue; } String text = a.getPosition().getValue(); XYTextAnnotation ta = new CustomAnnotation(text, posX, posY); @@ -197,9 +261,9 @@ ta.setRotationAnchor(TextAnchor.CENTER_LEFT); ta.setTextAnchor(TextAnchor.CENTER_LEFT); plot.getRenderer().addAnnotation(ta); + // TODO Merge XYLineAnnotation and CustomAnnotation. XYLineAnnotation la = new XYLineAnnotation(posX, 0, posX, posY); plot.getRenderer().addAnnotation(la); - freeFrom += 2.0; } }