package nl.tudelft.simulation.jstats.charts.histogram; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import org.jfree.chart.axis.AxisSpace; import org.jfree.chart.axis.AxisState; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.plot.Plot; import org.jfree.chart.plot.PlotRenderingInfo; import org.jfree.chart.plot.XYPlot; import org.jfree.ui.RectangleEdge; /** * The histogram domainAxis defines the x-Axis of a histogram. *

* (c) copyright 2002-2004 Delft University of Technology , the * Netherlands.
* See for project information www.simulation.tudelft.nl
* License of use: Lesser General Public License (LGPL) , no * warranty. * @author Alexander Verbraeck
* Peter Jacobs * @version $Revision: 1.1 $ $Date: 2010/08/10 11:39:02 $ * @since 1.5 */ public class HistogramDomainAxis extends NumberAxis { /** labels refers to the labels to be printed. */ protected String[] labels = null; /** maxLabelHeight refers to the maximum label heigth. */ protected double maxLabelHeight = -1; /** * constructs a new HistogramDomainAxis. * @param parent the plot to which this axis belongs * @param label the label of the axis * @param domain the domain * @param numberOfBins the numberOfBins */ public HistogramDomainAxis(final XYPlot parent, final String label, final double[] domain, final int numberOfBins) { super(label); this.setAutoRange(false); double binWidth = (domain[1] - domain[0]) / numberOfBins * 1.0; this.setLowerBound(domain[0] - binWidth); this.setUpperBound(domain[1] + binWidth); this.setVerticalTickLabels(true); // Let's copy the font etc from the y-axis this.setLabelFont(parent.getRangeAxis().getLabelFont()); this.setTickLabelFont(parent.getRangeAxis().getTickLabelFont()); this.labels = this.createLabels(domain, numberOfBins); } /** {@inheritDoc} */ @Override public double valueToJava2D(final double value, final Rectangle2D dataArea, final RectangleEdge edge) { double ratio = (value - this.getLowerBound()) / (this.getUpperBound() - this.getLowerBound()); return dataArea.getX() + ratio * (dataArea.getWidth()); } /** {@inheritDoc} */ @Override public double java2DToValue(final double value, final Rectangle2D dataArea, final RectangleEdge edge) { double ratio = (value - dataArea.getX()) / dataArea.getWidth(); return this.getLowerBound() + ratio * (this.getUpperBound() - this.getLowerBound()); } /** {@inheritDoc} */ @Override public AxisSpace reserveSpace(final Graphics2D g2, final Plot dataPlot, final Rectangle2D dataArea, final RectangleEdge edge, final AxisSpace axisSpace) { if (this.maxLabelHeight == -1) { g2.setFont(this.getTickLabelFont()); // If we have not yet measured the heigth of the labels for (int i = 0; i < this.labels.length; i++) { // we draw 90degrees rotated, so heigth = width double height = g2.getFont().getStringBounds(this.labels[i], g2.getFontRenderContext()).getWidth(); if (height > this.maxLabelHeight) { this.maxLabelHeight = height + 3; } } } AxisSpace result = new AxisSpace(); result.add(this.maxLabelHeight, RectangleEdge.BOTTOM); return result; } /** * creates the labels for the axis * @param domain the domain of the histogram * @param numberOfBins the number of bins * @return the result */ private String[] createLabels(final double[] domain, final int numberOfBins) { String[] result = new String[numberOfBins + 2]; NumberFormat formatter = NumberFormat.getInstance(); formatter.setMaximumFractionDigits(2); double binWidth = (domain[1] - domain[0]) / numberOfBins * 1.0; double start = domain[0]; for (int i = 1; i < numberOfBins + 1; i++) { result[i] = formatter.format(start); start = start + binWidth; } // Let's write infinity and -infinity DecimalFormatSymbols symbols = new DecimalFormatSymbols(); result[0] = "-" + symbols.getInfinity(); result[numberOfBins + 1] = symbols.getInfinity(); return result; } /** {@inheritDoc} */ @Override public AxisState draw(final Graphics2D g2, final double cursor, final Rectangle2D plotArea, final Rectangle2D dataArea, final RectangleEdge edge, final PlotRenderingInfo arg5) { g2.setColor(Color.BLACK); g2.setFont(this.getTickLabelFont()); double labelWidth = g2.getFont().getStringBounds(this.labels[0], g2.getFontRenderContext()).getHeight(); double width = dataArea.getWidth() / (this.labels.length) * 1.0; double x = dataArea.getX() + 0.5 * width; double y = dataArea.getY() + dataArea.getHeight(); g2.translate(x, y); g2.rotate(-Math.PI / 2.0); double offset = 0.0; for (int i = 0; i < this.labels.length; i++) { double labelHeight = g2.getFont().getStringBounds(this.labels[i], g2.getFontRenderContext()).getWidth() + 3; g2.drawString(this.labels[i], Math.round(-labelHeight), Math.round(offset + 0.33 * labelWidth)); offset = offset + width; } g2.rotate(Math.PI / 2.0); g2.translate(-x, -y); return new AxisState(); } }