Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/jfree/EnhancedLineAndShapeRenderer.java @ 2612:49cfa5c66651
Squashed performance bug introduced in rev4070. Now CSV export is about 245 times faster.
flys-artifacts/trunk@4195 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Wed, 04 Apr 2012 10:32:45 +0000 |
parents | 74c02dbf17ca |
children | 42b05a4bed25 |
line wrap: on
line source
package de.intevation.flys.jfree; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.Shape; import java.awt.geom.Rectangle2D; import java.util.HashMap; import java.util.Map; import org.apache.log4j.Logger; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.entity.EntityCollection; import org.jfree.chart.plot.CrosshairState; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.xy.XYDataset; import org.jfree.ui.RectangleEdge; import org.jfree.util.BooleanList; import org.jfree.util.ShapeUtilities; public class EnhancedLineAndShapeRenderer extends XYLineAndShapeRenderer { private static final Logger logger = Logger.getLogger(EnhancedLineAndShapeRenderer.class); protected BooleanList isMinimumShapeVisible; protected BooleanList isMaximumShapeVisible; protected Map<Integer, Double> seriesMinimum; protected Map<Integer, Double> seriesMaximum; public EnhancedLineAndShapeRenderer(boolean lines, boolean shapes) { super(lines, shapes); this.isMinimumShapeVisible = new BooleanList(); this.isMaximumShapeVisible = new BooleanList(); this.seriesMinimum = new HashMap<Integer, Double>(); this.seriesMaximum = new HashMap<Integer, Double>(); } public boolean getItemShapeVisible(XYDataset dataset, int series, int item){ if (super.getItemShapeVisible(series, item)) { return true; } if (isMinimumShapeVisible(series) && isMinimum(dataset, series, item)) { return true; } if (isMaximumShapeVisible(series) && isMaximum(dataset, series, item)) { return true; } return false; } public Shape getMaximumShape(int series, int column) { return new Rectangle2D.Double(-5d, -5d, 10d, 10d); } public Shape getMinimumShape(int series, int column) { return new Rectangle2D.Double(-5d, -5d, 10d, 10d); } public Paint getMaximumFillPaint(int series, int column) { Paint p = getItemPaint(series, column); if (p instanceof Color) { Color c = (Color) p; Color b = c; for (int i = 0; i < 2; i++) { b = b.darker(); } return b; } logger.warn("Item paint is no instance of Color!"); return p; } public Paint getMinimumFillPaint(int series, int column) { Paint p = getItemPaint(series, column); if (p instanceof Color) { Color c = (Color) p; Color b = c; for (int i = 0; i < 2; i++) { b = b.darker(); } return b; } logger.warn("Item paint is no instance of Color!"); return p; } /** * Overrides XYLineAndShapeRenderer.drawSecondaryPass() to call an adapted * method getItemShapeVisible() which now takes an XYDataset. So, 99% of * code equal the code in XYLineAndShapeRenderer. */ @Override protected void drawSecondaryPass( Graphics2D g2, XYPlot plot, XYDataset dataset, int pass, int series, int item, ValueAxis domainAxis, Rectangle2D dataArea, ValueAxis rangeAxis, CrosshairState crosshairState, EntityCollection entities ) { Shape entityArea = null; // get the data point... double x1 = dataset.getXValue(series, item); double y1 = dataset.getYValue(series, item); if (Double.isNaN(y1) || Double.isNaN(x1)) { return; } PlotOrientation orientation = plot.getOrientation(); RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation); double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation); if (getItemShapeVisible(dataset, series, item)) { Shape shape = null; boolean isMinimum = isMinimumShapeVisible(series) && isMinimum(dataset, series, item); boolean isMaximum = isMaximumShapeVisible(series) && isMaximum(dataset, series, item); if (isMinimum) { logger.debug("Create a Minimum shape."); shape = getMinimumShape(series, item); } else if (isMaximum) { logger.debug("Create a Maximum shape."); shape = getMaximumShape(series, item); } else { shape = getItemShape(series, item); } if (orientation == PlotOrientation.HORIZONTAL) { shape = ShapeUtilities.createTranslatedShape(shape, transY1, transX1); } else if (orientation == PlotOrientation.VERTICAL) { shape = ShapeUtilities.createTranslatedShape(shape, transX1, transY1); } entityArea = shape; if (shape.intersects(dataArea)) { if (getItemShapeFilled(series, item)) { if (getUseFillPaint()) { g2.setPaint(getItemFillPaint(series, item)); } else { g2.setPaint(getItemPaint(series, item)); } g2.fill(shape); } if (getDrawOutlines()) { if (getUseOutlinePaint()) { g2.setPaint(getItemOutlinePaint(series, item)); } else { g2.setPaint(getItemPaint(series, item)); } g2.setStroke(getItemOutlineStroke(series, item)); g2.draw(shape); } if (isMinimum) { g2.setPaint(getMinimumFillPaint(series, item)); g2.fill(shape); g2.setPaint(getItemOutlinePaint(series, item)); g2.setStroke(getItemOutlineStroke(series, item)); g2.draw(shape); } else if (isMaximum) { g2.setPaint(getMaximumFillPaint(series, item)); g2.fill(shape); g2.setPaint(getItemOutlinePaint(series, item)); g2.setStroke(getItemOutlineStroke(series, item)); g2.draw(shape); } } } double xx = transX1; double yy = transY1; if (orientation == PlotOrientation.HORIZONTAL) { xx = transY1; yy = transX1; } // draw the item label if there is one... if (isItemLabelVisible(series, item)) { drawItemLabel(g2, orientation, dataset, series, item, xx, yy, (y1 < 0.0)); } int domainAxisIndex = plot.getDomainAxisIndex(domainAxis); int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis); updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex, rangeAxisIndex, transX1, transY1, orientation); // add an entity for the item, but only if it falls within the data // area... if (entities != null && isPointInRect(dataArea, xx, yy)) { addEntity(entities, entityArea, dataset, series, item, xx, yy); } } public void setIsMinimumShapeVisisble(int series, boolean isVisible) { this.isMinimumShapeVisible.setBoolean(series, isVisible); } public boolean isMinimumShapeVisible(int series) { if (this.isMinimumShapeVisible.size() <= series) { return false; } return isMinimumShapeVisible.getBoolean(series); } public void setIsMaximumShapeVisible(int series, boolean isVisible) { this.isMaximumShapeVisible.setBoolean(series, isVisible); } public boolean isMaximumShapeVisible(int series) { if (this.isMaximumShapeVisible.size() <= series) { return false; } return isMaximumShapeVisible.getBoolean(series); } public boolean isMinimum(XYDataset dataset, int series, int item) { return dataset.getYValue(series, item) == getMinimum(dataset, series); } public double getMinimum(XYDataset dataset, int series) { Integer key = Integer.valueOf(series); Double old = seriesMinimum.get(key); if (old != null) { return old.doubleValue(); } logger.debug("Compute minimum of Series: " + series); double min = Double.MAX_VALUE; for (int i = 0, n = dataset.getItemCount(series); i < n; i++) { double tmpValue = dataset.getYValue(series, i); if (tmpValue < min) { min = tmpValue; } } seriesMinimum.put(key, Double.valueOf(min)); return min; } public boolean isMaximum(XYDataset dataset, int series, int item) { return dataset.getYValue(series, item) == getMaximum(dataset, series); } public double getMaximum(XYDataset dataset, int series) { Integer key = Integer.valueOf(series); Double old = seriesMaximum.get(key); if (old != null) { return old.doubleValue(); } logger.debug("Compute maximum of Series: " + series); double max = -Double.MAX_VALUE; for (int i = 0, n = dataset.getItemCount(series); i < n; i++) { double tmpValue = dataset.getYValue(series, i); if (tmpValue > max) { max = tmpValue; } } seriesMaximum.put(key, Double.valueOf(max)); return max; } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :