📄 logaxis.java
字号:
* @return A value along the axis scale.
*/
public double java2DToValue(double java2DValue, Rectangle2D area,
RectangleEdge edge) {
Range range = getRange();
double axisMin = calculateLog(range.getLowerBound());
double axisMax = calculateLog(range.getUpperBound());
double min = 0.0;
double max = 0.0;
if (RectangleEdge.isTopOrBottom(edge)) {
min = area.getX();
max = area.getMaxX();
}
else if (RectangleEdge.isLeftOrRight(edge)) {
min = area.getMaxY();
max = area.getY();
}
double log = 0.0;
if (isInverted()) {
log = axisMax - (java2DValue - min) / (max - min)
* (axisMax - axisMin);
}
else {
log = axisMin + (java2DValue - min) / (max - min)
* (axisMax - axisMin);
}
return calculateValue(log);
}
/**
* Converts a value on the axis scale to a Java2D coordinate relative to
* the given <code>area</code>, based on the axis running along the
* specified <code>edge</code>.
*
* @param value the data value.
* @param area the area.
* @param edge the edge.
*
* @return The Java2D coordinate corresponding to <code>value</code>.
*/
public double valueToJava2D(double value, Rectangle2D area,
RectangleEdge edge) {
Range range = getRange();
double axisMin = calculateLog(range.getLowerBound());
double axisMax = calculateLog(range.getUpperBound());
value = calculateLog(value);
double min = 0.0;
double max = 0.0;
if (RectangleEdge.isTopOrBottom(edge)) {
min = area.getX();
max = area.getMaxX();
}
else if (RectangleEdge.isLeftOrRight(edge)) {
max = area.getMinY();
min = area.getMaxY();
}
if (isInverted()) {
return max
- ((value - axisMin) / (axisMax - axisMin)) * (max - min);
}
else {
return min
+ ((value - axisMin) / (axisMax - axisMin)) * (max - min);
}
}
/**
* Configures the axis. This method is typically called when an axis
* is assigned to a new plot.
*/
public void configure() {
if (isAutoRange()) {
autoAdjustRange();
}
}
/**
* Adjusts the axis range to match the data range that the axis is
* required to display.
*/
protected void autoAdjustRange() {
Plot plot = getPlot();
if (plot == null) {
return; // no plot, no data
}
if (plot instanceof ValueAxisPlot) {
ValueAxisPlot vap = (ValueAxisPlot) plot;
Range r = vap.getDataRange(this);
if (r == null) {
r = getDefaultAutoRange();
}
double upper = r.getUpperBound();
double lower = Math.max(r.getLowerBound(), this.smallestValue);
double range = upper - lower;
// if fixed auto range, then derive lower bound...
double fixedAutoRange = getFixedAutoRange();
if (fixedAutoRange > 0.0) {
lower = Math.max(upper - fixedAutoRange, this.smallestValue);
}
else {
// ensure the autorange is at least <minRange> in size...
double minRange = getAutoRangeMinimumSize();
if (range < minRange) {
double expand = (minRange - range) / 2;
upper = upper + expand;
lower = lower - expand;
}
// apply the margins - these should apply to the exponent range
double logUpper = calculateLog(upper);
double logLower = calculateLog(lower);
double logRange = logUpper - logLower;
logUpper = logUpper + getUpperMargin() * logRange;
logLower = logLower - getLowerMargin() * logRange;
upper = calculateValue(logUpper);
lower = calculateValue(logLower);
}
setRange(new Range(lower, upper), false, false);
}
}
/**
* Draws the axis on a Java 2D graphics device (such as the screen or a
* printer).
*
* @param g2 the graphics device (<code>null</code> not permitted).
* @param cursor the cursor location (determines where to draw the axis).
* @param plotArea the area within which the axes and plot should be drawn.
* @param dataArea the area within which the data should be drawn.
* @param edge the axis location (<code>null</code> not permitted).
* @param plotState collects information about the plot
* (<code>null</code> permitted).
*
* @return The axis state (never <code>null</code>).
*/
public AxisState draw(Graphics2D g2, double cursor, Rectangle2D plotArea,
Rectangle2D dataArea, RectangleEdge edge,
PlotRenderingInfo plotState) {
AxisState state = null;
// if the axis is not visible, don't draw it...
if (!isVisible()) {
state = new AxisState(cursor);
// even though the axis is not visible, we need ticks for the
// gridlines...
List ticks = refreshTicks(g2, state, dataArea, edge);
state.setTicks(ticks);
return state;
}
state = drawTickMarksAndLabels(g2, cursor, plotArea, dataArea, edge);
state = drawLabel(getLabel(), g2, plotArea, dataArea, edge, state);
return state;
}
/**
* 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.
*
*/
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;
}
/**
* Returns a list of ticks for an axis at the top or bottom of the chart.
*
* @param g2 the graphics device.
* @param dataArea the data area.
* @param edge the edge.
*
* @return A list of ticks.
*/
protected List refreshTicksHorizontal(Graphics2D g2, Rectangle2D dataArea,
RectangleEdge edge) {
Range range = getRange();
List ticks = new ArrayList();
Font tickLabelFont = getTickLabelFont();
g2.setFont(tickLabelFont);
if (isAutoTickUnitSelection()) {
selectAutoTickUnit(g2, dataArea, edge);
}
double start = Math.floor(calculateLog(getLowerBound()));
double end = Math.ceil(calculateLog(getUpperBound()));
double current = start;
while (current <= end) {
double v = calculateValue(current);
if (range.contains(v)) {
ticks.add(new NumberTick(TickType.MAJOR, v, createTickLabel(v),
TextAnchor.TOP_CENTER, TextAnchor.CENTER, 0.0));
}
// add minor ticks (for gridlines)
double next = Math.pow(this.base, current
+ this.tickUnit.getSize());
for (int i = 1; i < this.minorTickCount; i++) {
double minorV = v + i * ((next - v) / this.minorTickCount);
if (range.contains(minorV)) {
ticks.add(new NumberTick(TickType.MINOR, minorV,
"", TextAnchor.TOP_CENTER, TextAnchor.CENTER, 0.0));
}
}
current = current + this.tickUnit.getSize();
}
return ticks;
}
/**
* Returns a list of ticks for an axis at the left or right of the chart.
*
* @param g2 the graphics device.
* @param dataArea the data area.
* @param edge the edge.
*
* @return A list of ticks.
*/
protected List refreshTicksVertical(Graphics2D g2, Rectangle2D dataArea,
RectangleEdge edge) {
Range range = getRange();
List ticks = new ArrayList();
Font tickLabelFont = getTickLabelFont();
g2.setFont(tickLabelFont);
if (isAutoTickUnitSelection()) {
selectAutoTickUnit(g2, dataArea, edge);
}
double start = Math.floor(calculateLog(getLowerBound()));
double end = Math.ceil(calculateLog(getUpperBound()));
double current = start;
while (current <= end) {
double v = calculateValue(current);
if (range.contains(v)) {
ticks.add(new NumberTick(TickType.MINOR, v, createTickLabel(v),
TextAnchor.CENTER_RIGHT, TextAnchor.CENTER, 0.0));
}
// add minor ticks (for gridlines)
double next = Math.pow(this.base, current
+ this.tickUnit.getSize());
for (int i = 1; i < this.minorTickCount; i++) {
double minorV = v + i * ((next - v) / this.minorTickCount);
if (range.contains(minorV)) {
ticks.add(new NumberTick(TickType.MINOR, minorV, "",
TextAnchor.CENTER_RIGHT, TextAnchor.CENTER, 0.0));
}
}
current = current + this.tickUnit.getSize();
}
return ticks;
}
/**
* 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);
}
}
/**
* 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -