Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/jfree/EnhancedLineAndShapeRenderer.java @ 2651:9e9eb9d97548
Initial transition configuration and artifact/state stubs for fixation
analysis.
flys-artifacts/trunk@4312 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Raimund Renkert <raimund.renkert@intevation.de> |
---|---|
date | Thu, 26 Apr 2012 15:08:51 +0000 |
parents | 6f5fc3de0d48 |
children | fa363aac788b |
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.data.xy.XYSeriesCollection; import org.jfree.ui.RectangleEdge; import org.jfree.util.BooleanList; import org.jfree.util.ShapeUtilities; /** * Renderer with additional the additional functionality of renderering minima * and/or maxima of dataseries contained in datasets. */ public class EnhancedLineAndShapeRenderer extends XYLineAndShapeRenderer { /** Own logger. */ private static final Logger logger = Logger.getLogger(EnhancedLineAndShapeRenderer.class); protected BooleanList isMinimumShapeVisible; protected BooleanList isMaximumShapeVisible; protected BooleanList showLineLabel; protected Map<Integer, Double> seriesMinimum; protected Map<Integer, Double> seriesMinimumX; protected Map<Integer, Double> seriesMaximum; public EnhancedLineAndShapeRenderer(boolean lines, boolean shapes) { super(lines, shapes); this.isMinimumShapeVisible = new BooleanList(); this.isMaximumShapeVisible = new BooleanList(); this.showLineLabel = new BooleanList(); this.seriesMinimum = new HashMap<Integer, Double>(); this.seriesMaximum = new HashMap<Integer, Double>(); this.seriesMinimumX = 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; // OPTIMIZE: instead of calculating minimum and maximum for every // point, calculate it just once (assume that dataset // content does not change during rendering). // NOTE: Above OPTIMIZE might already be fulfilled to most extend. 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); } } // TODO labeling of waterlevels could happen here, too. } // if (getItemShapeVisible(dataset, series, item)) 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)); } // Draw label of line. if (isShowLineLabel(series) && isMinimumX (dataset, series, item)) { String waterlevelLabel = ((XYSeriesCollection) dataset).getSeries(series) .getKey().toString(); // TODO Force water of some German rivers to flow direction mountains. g2.drawString(waterlevelLabel, (float)xx, (float)yy-3f); } 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); } /** Whether or not a label should be shown for series. */ public boolean isShowLineLabel(int series) { if (this.showLineLabel.size() <= series) { return false; } return showLineLabel.getBoolean(series); } /** Sets whether or not a label should be shown for series. */ public void setShowLineLabel(boolean showLineLabel, int series) { this.showLineLabel.setBoolean(series, showLineLabel); } /** * True if the given item of given dataset has the smallest * X value within this set. */ public boolean isMinimumX(XYDataset dataset, int series, int item) { return dataset.getXValue(series, item) == getMinimumX(dataset, series); } /** * Get Minimum X Value of a given series in a dataset. * The value is stored for later use if queried the first time. */ public double getMinimumX(XYDataset dataset, int series) { Integer key = Integer.valueOf(series); Double old = seriesMinimumX.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.getXValue(series, i); if (tmpValue < min) { min = tmpValue; } } seriesMinimumX.put(key, Double.valueOf(min)); return min; } /** * True if the given item of given dataset has the smallest * Y value within this set. */ public boolean isMinimum(XYDataset dataset, int series, int item) { return dataset.getYValue(series, item) == getMinimum(dataset, series); } /** * Get Minimum Y Value of a given series in a dataset. * The value is stored for later use if queried the first time. */ 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; } /** * True if the given item of given dataset has the biggest * Y value within this set. */ public boolean isMaximum(XYDataset dataset, int series, int item) { return dataset.getYValue(series, item) == getMaximum(dataset, series); } /** * Get maximum Y Value of a given series in a dataset. * The value is stored for later use if queried the first time. */ 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 :