/** * Reserve some space on each axis side because we draw a centered label at each extremity. * * @param g2 the graphics device. * @param plot the plot. * @param plotArea the plot area. * @param edge the edge. * @param space the space already reserved. * @return The reserved space. */ public AxisSpace reserveSpace( Graphics2D g2, Plot plot, Rectangle2D plotArea, RectangleEdge edge, AxisSpace space) { this.internalMarkerCycleBoundTick = null; AxisSpace ret = super.reserveSpace(g2, plot, plotArea, edge, space); if (this.internalMarkerCycleBoundTick == null) { return ret; } FontMetrics fm = g2.getFontMetrics(getTickLabelFont()); Rectangle2D r = TextUtilities.getTextBounds(this.internalMarkerCycleBoundTick.getText(), g2, fm); if (RectangleEdge.isTopOrBottom(edge)) { if (isVerticalTickLabels()) { space.add(r.getHeight() / 2, RectangleEdge.RIGHT); } else { space.add(r.getWidth() / 2, RectangleEdge.RIGHT); } } else if (RectangleEdge.isLeftOrRight(edge)) { if (isVerticalTickLabels()) { space.add(r.getWidth() / 2, RectangleEdge.TOP); } else { space.add(r.getHeight() / 2, RectangleEdge.TOP); } } return ret; }
/** * Converts a coordinate from Java 2D space to data space. * * @param java2DValue the coordinate in Java2D space. * @param dataArea the data area. * @param edge the edge. * @return The data value. */ public double java2DToValue(double java2DValue, Rectangle2D dataArea, RectangleEdge edge) { Range range = getRange(); double vmax = range.getUpperBound(); double vp = getCycleBound(); double jmin = 0.0; double jmax = 0.0; if (RectangleEdge.isTopOrBottom(edge)) { jmin = dataArea.getMinX(); jmax = dataArea.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { jmin = dataArea.getMaxY(); jmax = dataArea.getMinY(); } if (isInverted()) { double jbreak = jmax - (vmax - vp) * (jmax - jmin) / this.period; if (java2DValue >= jbreak) { return vp + (jmax - java2DValue) * this.period / (jmax - jmin); } else { return vp - (java2DValue - jmin) * this.period / (jmax - jmin); } } else { double jbreak = (vmax - vp) * (jmax - jmin) / this.period + jmin; if (java2DValue <= jbreak) { return vp + (java2DValue - jmin) * this.period / (jmax - jmin); } else { return vp - (jmax - java2DValue) * this.period / (jmax - jmin); } } }
/** * Converts a data value to a coordinate in Java2D space, assuming that the axis runs along one * edge of the specified plotArea. Note that it is possible for the coordinate to fall outside the * plotArea. * * @param value the data value. * @param plotArea the area for plotting the data. * @param edge the axis location. * @return The Java2D coordinate. */ @Override public double valueToJava2D(double value, Rectangle2D plotArea, RectangleEdge edge) { Range range = getRange(); double axisMin = switchedLog10(range.getLowerBound()); double axisMax = switchedLog10(range.getUpperBound()); double min = 0.0; double max = 0.0; if (RectangleEdge.isTopOrBottom(edge)) { min = plotArea.getMinX(); max = plotArea.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { min = plotArea.getMaxY(); max = plotArea.getMinY(); } value = switchedLog10(value); if (isInverted()) { return max - (((value - axisMin) / (axisMax - axisMin)) * (max - min)); } else { return min + (((value - axisMin) / (axisMax - axisMin)) * (max - min)); } }
/** * Selects an appropriate tick value for the axis. The strategy is to display as many ticks as * possible (selected from an array of 'standard' tick units) without the labels overlapping. * * @param g2 the graphics device. * @param dataArea the area defined by the axes. * @param edge the axis location. * @since 1.0.7 */ protected void selectAutoTickUnit(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge) { if (RectangleEdge.isTopOrBottom(edge)) { selectHorizontalAutoTickUnit(g2, dataArea, edge); } else if (RectangleEdge.isLeftOrRight(edge)) { selectVerticalAutoTickUnit(g2, dataArea, edge); } }
/** * Converts a coordinate in Java2D space to the corresponding data value, assuming that the axis * runs along one edge of the specified plotArea. * * @param java2DValue the coordinate in Java2D space. * @param plotArea the area in which the data is plotted. * @param edge the axis location. * @return The data value. */ @Override public double java2DToValue(double java2DValue, Rectangle2D plotArea, RectangleEdge edge) { Range range = getRange(); double axisMin = switchedLog10(range.getLowerBound()); double axisMax = switchedLog10(range.getUpperBound()); double plotMin = 0.0; double plotMax = 0.0; if (RectangleEdge.isTopOrBottom(edge)) { plotMin = plotArea.getX(); plotMax = plotArea.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { plotMin = plotArea.getMaxY(); plotMax = plotArea.getMinY(); } if (isInverted()) { return switchedPow10( axisMax - ((java2DValue - plotMin) / (plotMax - plotMin)) * (axisMax - axisMin)); } else { return switchedPow10( axisMin + ((java2DValue - plotMin) / (plotMax - plotMin)) * (axisMax - axisMin)); } }
/** * Draws the tick marks for the axis. * * @param g2 the graphics device. * @param state the axis state. * @param dataArea the data area. * @param edge the edge. */ protected void drawTickMarks( Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) { if (RectangleEdge.isTopOrBottom(edge)) { drawTickMarksHorizontal(g2, state, dataArea, edge); } else if (RectangleEdge.isLeftOrRight(edge)) { drawTickMarksVertical(g2, state, dataArea, edge); } }
/** * Calculates the bar thickness. * * @param plotArea the plot area. * @param edge the location. * @return The thickness. */ private double calculateBarThickness(Rectangle2D plotArea, RectangleEdge edge) { double result = 0.0; if (RectangleEdge.isLeftOrRight(edge)) { result = plotArea.getWidth() * this.colorBarThicknessPercent; } else { result = plotArea.getHeight() * this.colorBarThicknessPercent; } return result; }
/** * Calculates the positions of the tick labels for the axis, storing the results in the tick label * list (ready for drawing). * * @param g2 the graphics device. * @param state the axis state. * @param dataArea the area in which the plot should be drawn. * @param edge the location of the axis. * @return A list of ticks. */ @Override public List refreshTicks( Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) { List result = new java.util.ArrayList(); if (RectangleEdge.isTopOrBottom(edge)) { result = refreshTicksHorizontal(g2, dataArea, edge); } else if (RectangleEdge.isLeftOrRight(edge)) { result = refreshTicksVertical(g2, dataArea, edge); } return result; }
/** * Estimates the space (height or width) required to draw the axis. * * @param g2 the graphics device. * @param plot the plot that the axis belongs to. * @param plotArea the area within which the plot (including axes) should be drawn. * @param edge the axis location. * @param space space already reserved. * @return The space required to draw the axis (including pre-reserved space). */ public AxisSpace reserveSpace( Graphics2D g2, Plot plot, Rectangle2D plotArea, RectangleEdge edge, AxisSpace space) { // create a new space object if one wasn't supplied... if (space == null) { space = new AxisSpace(); } // if the axis is not visible, no additional space is required... if (!isVisible()) { return space; } // if the axis has a fixed dimension, return it... double dimension = getFixedDimension(); if (dimension > 0.0) { space.ensureAtLeast(dimension, edge); } // get the axis label size and update the space object... Rectangle2D labelEnclosure = getLabelEnclosure(g2, edge); double labelHeight = 0.0; double labelWidth = 0.0; double tickLabelBandsDimension = 0.0; for (int i = 0; i < this.labelInfo.length; i++) { PeriodAxisLabelInfo info = this.labelInfo[i]; FontMetrics fm = g2.getFontMetrics(info.getLabelFont()); tickLabelBandsDimension += info.getPadding().extendHeight(fm.getHeight()); } if (RectangleEdge.isTopOrBottom(edge)) { labelHeight = labelEnclosure.getHeight(); space.add(labelHeight + tickLabelBandsDimension, edge); } else if (RectangleEdge.isLeftOrRight(edge)) { labelWidth = labelEnclosure.getWidth(); space.add(labelWidth + tickLabelBandsDimension, edge); } // add space for the outer tick labels, if any... double tickMarkSpace = 0.0; if (isTickMarksVisible()) { tickMarkSpace = getTickMarkOutsideLength(); } if (this.minorTickMarksVisible) { tickMarkSpace = Math.max(tickMarkSpace, this.minorTickMarkOutsideLength); } space.add(tickMarkSpace, edge); return space; }
public double java2DToValue(double java2DValue, Rectangle2D area, RectangleEdge edge) { Range range = getRange(); double axisMin = range.getLowerBound(); double axisMax = range.getUpperBound(); double min = 0.0d; double max = 0.0d; if (RectangleEdge.isTopOrBottom(edge)) { min = area.getX(); max = area.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { min = area.getMaxY(); max = area.getY(); } if (isInverted()) { return axisMax - (((java2DValue - min) / (max - min)) * (axisMax - axisMin)); } return (((java2DValue - min) / (max - min)) * (axisMax - axisMin)) + axisMin; }
/** * Returns the maximum of the relevant dimension (height or width) of the subcategory labels. * * @param g2 the graphics device. * @param edge the edge. * @return The maximum dimension. */ private double getMaxDim(Graphics2D g2, RectangleEdge edge) { double result = 0.0; g2.setFont(this.subLabelFont); FontMetrics fm = g2.getFontMetrics(); Iterator iterator = this.subCategories.iterator(); while (iterator.hasNext()) { Comparable subcategory = (Comparable) iterator.next(); String label = subcategory.toString(); Rectangle2D bounds = TextUtilities.getTextBounds(label, g2, fm); double dim = 0.0; if (RectangleEdge.isLeftOrRight(edge)) { dim = bounds.getWidth(); } else { // must be top or bottom dim = bounds.getHeight(); } result = Math.max(result, dim); } return result; }
/** * Converts a coordinate in Java2D space to the corresponding data value, assuming that the axis * runs along one edge of the specified dataArea. * * @param java2DValue the coordinate in Java2D space. * @param area the area in which the data is plotted. * @param edge the edge along which the axis lies. * @return The data value. */ public double java2DToValue(double java2DValue, Rectangle2D area, RectangleEdge edge) { double result = Double.NaN; double min = 0.0; double max = 0.0; double axisMin = this.first.getFirstMillisecond(); double axisMax = this.last.getLastMillisecond(); if (RectangleEdge.isTopOrBottom(edge)) { min = area.getX(); max = area.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { min = area.getMaxY(); max = area.getY(); } if (isInverted()) { result = axisMax - ((java2DValue - min) / (max - min) * (axisMax - axisMin)); } else { result = axisMin + ((java2DValue - min) / (max - min) * (axisMax - axisMin)); } return result; }
/** * Translates a value from data space to Java 2D space. * * @param value the data value. * @param dataArea the data area. * @param edge the edge. * @return The Java 2D value. */ public double valueToJava2D(double value, Rectangle2D dataArea, RectangleEdge edge) { Range range = getRange(); double vmin = range.getLowerBound(); double vmax = range.getUpperBound(); double vp = getCycleBound(); if ((value < vmin) || (value > vmax)) { return Double.NaN; } double jmin = 0.0; double jmax = 0.0; if (RectangleEdge.isTopOrBottom(edge)) { jmin = dataArea.getMinX(); jmax = dataArea.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { jmax = dataArea.getMinY(); jmin = dataArea.getMaxY(); } if (isInverted()) { if (value == vp) { return this.boundMappedToLastCycle ? jmin : jmax; } else if (value > vp) { return jmax - (value - vp) * (jmax - jmin) / this.period; } else { return jmin + (vp - value) * (jmax - jmin) / this.period; } } else { if (value == vp) { return this.boundMappedToLastCycle ? jmax : jmin; } else if (value >= vp) { return jmin + (value - vp) * (jmax - jmin) / this.period; } else { return jmax - (vp - value) * (jmax - jmin) / this.period; } } }
/** * Estimates the space required for the axis, given a specific drawing area. * * @param g2 the graphics device (used to obtain font information). * @param plot the plot that the axis belongs to. * @param plotArea the area within which the axis should be drawn. * @param edge the axis location (top or bottom). * @param space the space already reserved. * @return The space required to draw the axis. */ public AxisSpace reserveSpace( Graphics2D g2, Plot plot, Rectangle2D plotArea, RectangleEdge edge, AxisSpace space) { // create a new space object if one wasn't supplied... if (space == null) { space = new AxisSpace(); } // if the axis is not visible, no additional space is required... if (!isVisible()) { return space; } space = super.reserveSpace(g2, plot, plotArea, edge, space); double maxdim = getMaxDim(g2, edge); if (RectangleEdge.isTopOrBottom(edge)) { space.add(maxdim, edge); } else if (RectangleEdge.isLeftOrRight(edge)) { space.add(maxdim, edge); } return space; }
/** * Converts a data value to a coordinate in Java2D space, assuming that the axis runs along one * edge of the specified dataArea. * * <p>Note that it is possible for the coordinate to fall outside the area. * * @param value the data value. * @param area the area for plotting the data. * @param edge the edge along which the axis lies. * @return The Java2D coordinate. */ public double valueToJava2D(double value, Rectangle2D area, RectangleEdge edge) { double result = Double.NaN; double axisMin = this.first.getFirstMillisecond(); double axisMax = this.last.getLastMillisecond(); if (RectangleEdge.isTopOrBottom(edge)) { double minX = area.getX(); double maxX = area.getMaxX(); if (isInverted()) { result = maxX + ((value - axisMin) / (axisMax - axisMin)) * (minX - maxX); } else { result = minX + ((value - axisMin) / (axisMax - axisMin)) * (maxX - minX); } } else if (RectangleEdge.isLeftOrRight(edge)) { double minY = area.getMinY(); double maxY = area.getMaxY(); if (isInverted()) { result = minY + (((value - axisMin) / (axisMax - axisMin)) * (maxY - minY)); } else { result = maxY - (((value - axisMin) / (axisMax - axisMin)) * (maxY - minY)); } } return result; }
/** * Draws the plot on a Java 2D graphics device (such as the screen or a printer). * * @param g2 the graphics device. * @param cursor the cursor. * @param plotArea the area within which the chart should be drawn. * @param dataArea the area within which the plot should be drawn (a subset of the drawArea). * @param reservedArea the reserved area. * @param edge the color bar location. * @return The new cursor location. */ public double draw( Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, Rectangle2D reservedArea, RectangleEdge edge) { Rectangle2D colorBarArea = null; double thickness = calculateBarThickness(dataArea, edge); if (this.colorBarThickness > 0) { thickness = this.colorBarThickness; // allow fixed thickness } double length = 0.0; if (RectangleEdge.isLeftOrRight(edge)) { length = dataArea.getHeight(); } else { length = dataArea.getWidth(); } if (this.colorBarLength > 0) { length = this.colorBarLength; } if (edge == RectangleEdge.BOTTOM) { colorBarArea = new Rectangle2D.Double( dataArea.getX(), plotArea.getMaxY() + this.outerGap, length, thickness); } else if (edge == RectangleEdge.TOP) { colorBarArea = new Rectangle2D.Double( dataArea.getX(), reservedArea.getMinY() + this.outerGap, length, thickness); } else if (edge == RectangleEdge.LEFT) { colorBarArea = new Rectangle2D.Double( plotArea.getX() - thickness - this.outerGap, dataArea.getMinY(), thickness, length); } else if (edge == RectangleEdge.RIGHT) { colorBarArea = new Rectangle2D.Double( plotArea.getMaxX() + this.outerGap, dataArea.getMinY(), thickness, length); } // update, but dont draw tick marks (needed for stepped colors) this.axis.refreshTicks(g2, new AxisState(), colorBarArea, edge); drawColorBar(g2, colorBarArea, edge); AxisState state = null; if (edge == RectangleEdge.TOP) { cursor = colorBarArea.getMinY(); state = this.axis.draw(g2, cursor, reservedArea, colorBarArea, RectangleEdge.TOP, null); } else if (edge == RectangleEdge.BOTTOM) { cursor = colorBarArea.getMaxY(); state = this.axis.draw(g2, cursor, reservedArea, colorBarArea, RectangleEdge.BOTTOM, null); } else if (edge == RectangleEdge.LEFT) { cursor = colorBarArea.getMinX(); state = this.axis.draw(g2, cursor, reservedArea, colorBarArea, RectangleEdge.LEFT, null); } else if (edge == RectangleEdge.RIGHT) { cursor = colorBarArea.getMaxX(); state = this.axis.draw(g2, cursor, reservedArea, colorBarArea, RectangleEdge.RIGHT, null); } return state.getCursor(); }