📄 cyclicnumberaxis.java
字号:
return ret;
}
return super.calculateAnchorPoint(tick, cursor, dataArea, edge);
}
/**
* Builds a list of ticks for the axis. This method is called when the
* axis is at the top or bottom of the chart (so the axis is "horizontal").
*
* @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) {
List result = new java.util.ArrayList();
Font tickLabelFont = getTickLabelFont();
g2.setFont(tickLabelFont);
if (isAutoTickUnitSelection()) {
selectAutoTickUnit(g2, dataArea, edge);
}
double unit = getTickUnit().getSize();
double cycleBound = getCycleBound();
double currentTickValue = Math.ceil(cycleBound / unit) * unit;
double upperValue = getRange().getUpperBound();
boolean cycled = false;
boolean boundMapping = this.boundMappedToLastCycle;
this.boundMappedToLastCycle = false;
CycleBoundTick lastTick = null;
float lastX = 0.0f;
if (upperValue == cycleBound) {
currentTickValue = calculateLowestVisibleTickValue();
cycled = true;
this.boundMappedToLastCycle = true;
}
while (currentTickValue <= upperValue) {
// Cycle when necessary
boolean cyclenow = false;
if ((currentTickValue + unit > upperValue) && !cycled) {
cyclenow = true;
}
double xx = valueToJava2D(currentTickValue, dataArea, edge);
String tickLabel;
NumberFormat formatter = getNumberFormatOverride();
if (formatter != null) {
tickLabel = formatter.format(currentTickValue);
}
else {
tickLabel = getTickUnit().valueToString(currentTickValue);
}
float x = (float) xx;
TextAnchor anchor = null;
TextAnchor rotationAnchor = null;
double angle = 0.0;
if (isVerticalTickLabels()) {
if (edge == RectangleEdge.TOP) {
angle = Math.PI / 2.0;
}
else {
angle = -Math.PI / 2.0;
}
anchor = TextAnchor.CENTER_RIGHT;
// If tick overlap when cycling, update last tick too
if ((lastTick != null) && (lastX == x)
&& (currentTickValue != cycleBound)) {
anchor = isInverted()
? TextAnchor.TOP_RIGHT : TextAnchor.BOTTOM_RIGHT;
result.remove(result.size() - 1);
result.add(new CycleBoundTick(
this.boundMappedToLastCycle, lastTick.getNumber(),
lastTick.getText(), anchor, anchor,
lastTick.getAngle())
);
this.internalMarkerWhenTicksOverlap = true;
anchor = isInverted()
? TextAnchor.BOTTOM_RIGHT : TextAnchor.TOP_RIGHT;
}
rotationAnchor = anchor;
}
else {
if (edge == RectangleEdge.TOP) {
anchor = TextAnchor.BOTTOM_CENTER;
if ((lastTick != null) && (lastX == x)
&& (currentTickValue != cycleBound)) {
anchor = isInverted()
? TextAnchor.BOTTOM_LEFT : TextAnchor.BOTTOM_RIGHT;
result.remove(result.size() - 1);
result.add(new CycleBoundTick(
this.boundMappedToLastCycle, lastTick.getNumber(),
lastTick.getText(), anchor, anchor,
lastTick.getAngle())
);
this.internalMarkerWhenTicksOverlap = true;
anchor = isInverted()
? TextAnchor.BOTTOM_RIGHT : TextAnchor.BOTTOM_LEFT;
}
rotationAnchor = anchor;
}
else {
anchor = TextAnchor.TOP_CENTER;
if ((lastTick != null) && (lastX == x)
&& (currentTickValue != cycleBound)) {
anchor = isInverted()
? TextAnchor.TOP_LEFT : TextAnchor.TOP_RIGHT;
result.remove(result.size() - 1);
result.add(new CycleBoundTick(
this.boundMappedToLastCycle, lastTick.getNumber(),
lastTick.getText(), anchor, anchor,
lastTick.getAngle())
);
this.internalMarkerWhenTicksOverlap = true;
anchor = isInverted()
? TextAnchor.TOP_RIGHT : TextAnchor.TOP_LEFT;
}
rotationAnchor = anchor;
}
}
CycleBoundTick tick = new CycleBoundTick(
this.boundMappedToLastCycle,
new Double(currentTickValue), tickLabel, anchor,
rotationAnchor, angle
);
if (currentTickValue == cycleBound) {
this.internalMarkerCycleBoundTick = tick;
}
result.add(tick);
lastTick = tick;
lastX = x;
currentTickValue += unit;
if (cyclenow) {
currentTickValue = calculateLowestVisibleTickValue();
upperValue = cycleBound;
cycled = true;
this.boundMappedToLastCycle = true;
}
}
this.boundMappedToLastCycle = boundMapping;
return result;
}
/**
* Builds a list of ticks for the axis. This method is called when the
* axis is at the left or right of the chart (so the axis is "vertical").
*
* @param g2 the graphics device.
* @param dataArea the data area.
* @param edge the edge.
*
* @return A list of ticks.
*/
protected List refreshVerticalTicks(Graphics2D g2,
Rectangle2D dataArea,
RectangleEdge edge) {
List result = new java.util.ArrayList();
result.clear();
Font tickLabelFont = getTickLabelFont();
g2.setFont(tickLabelFont);
if (isAutoTickUnitSelection()) {
selectAutoTickUnit(g2, dataArea, edge);
}
double unit = getTickUnit().getSize();
double cycleBound = getCycleBound();
double currentTickValue = Math.ceil(cycleBound / unit) * unit;
double upperValue = getRange().getUpperBound();
boolean cycled = false;
boolean boundMapping = this.boundMappedToLastCycle;
this.boundMappedToLastCycle = true;
NumberTick lastTick = null;
float lastY = 0.0f;
if (upperValue == cycleBound) {
currentTickValue = calculateLowestVisibleTickValue();
cycled = true;
this.boundMappedToLastCycle = true;
}
while (currentTickValue <= upperValue) {
// Cycle when necessary
boolean cyclenow = false;
if ((currentTickValue + unit > upperValue) && !cycled) {
cyclenow = true;
}
double yy = valueToJava2D(currentTickValue, dataArea, edge);
String tickLabel;
NumberFormat formatter = getNumberFormatOverride();
if (formatter != null) {
tickLabel = formatter.format(currentTickValue);
}
else {
tickLabel = getTickUnit().valueToString(currentTickValue);
}
float y = (float) yy;
TextAnchor anchor = null;
TextAnchor rotationAnchor = null;
double angle = 0.0;
if (isVerticalTickLabels()) {
if (edge == RectangleEdge.LEFT) {
anchor = TextAnchor.BOTTOM_CENTER;
if ((lastTick != null) && (lastY == y)
&& (currentTickValue != cycleBound)) {
anchor = isInverted()
? TextAnchor.BOTTOM_LEFT : TextAnchor.BOTTOM_RIGHT;
result.remove(result.size() - 1);
result.add(new CycleBoundTick(
this.boundMappedToLastCycle, lastTick.getNumber(),
lastTick.getText(), anchor, anchor,
lastTick.getAngle())
);
this.internalMarkerWhenTicksOverlap = true;
anchor = isInverted()
? TextAnchor.BOTTOM_RIGHT : TextAnchor.BOTTOM_LEFT;
}
rotationAnchor = anchor;
angle = -Math.PI / 2.0;
}
else {
anchor = TextAnchor.BOTTOM_CENTER;
if ((lastTick != null) && (lastY == y)
&& (currentTickValue != cycleBound)) {
anchor = isInverted()
? TextAnchor.BOTTOM_RIGHT : TextAnchor.BOTTOM_LEFT;
result.remove(result.size() - 1);
result.add(new CycleBoundTick(
this.boundMappedToLastCycle, lastTick.getNumber(),
lastTick.getText(), anchor, anchor,
lastTick.getAngle())
);
this.internalMarkerWhenTicksOverlap = true;
anchor = isInverted()
? TextAnchor.BOTTOM_LEFT : TextAnchor.BOTTOM_RIGHT;
}
rotationAnchor = anchor;
angle = Math.PI / 2.0;
}
}
else {
if (edge == RectangleEdge.LEFT) {
anchor = TextAnchor.CENTER_RIGHT;
if ((lastTick != null) && (lastY == y)
&& (currentTickValue != cycleBound)) {
anchor = isInverted()
? TextAnchor.BOTTOM_RIGHT : TextAnchor.TOP_RIGHT;
result.remove(result.size() - 1);
result.add(new CycleBoundTick(
this.boundMappedToLastCycle, lastTick.getNumber(),
lastTick.getText(), anchor, anchor,
lastTick.getAngle())
);
this.internalMarkerWhenTicksOverlap = true;
anchor = isInverted()
? TextAnchor.TOP_RIGHT : TextAnchor.BOTTOM_RIGHT;
}
rotationAnchor = anchor;
}
else {
anchor = TextAnchor.CENTER_LEFT;
if ((lastTick != null) && (lastY == y)
&& (currentTickValue != cycleBound)) {
anchor = isInverted()
? TextAnchor.BOTTOM_LEFT : TextAnchor.TOP_LEFT;
result.remove(result.size() - 1);
result.add(new CycleBoundTick(
this.boundMappedToLastCycle, lastTick.getNumber(),
lastTick.getText(), anchor, anchor,
lastTick.getAngle())
);
this.internalMarkerWhenTicksOverlap = true;
anchor = isInverted()
? TextAnchor.TOP_LEFT : TextAnchor.BOTTOM_LEFT;
}
rotationAnchor = anchor;
}
}
CycleBoundTick tick = new CycleBoundTick(
this.boundMappedToLastCycle, new Double(currentTickValue),
tickLabel, anchor, rotationAnchor, angle
);
if (currentTickValue == cycleBound) {
this.internalMarkerCycleBoundTick = tick;
}
result.add(tick);
lastTick = tick;
lastY = y;
if (currentTickValue == cycleBound) {
this.internalMarkerCycleBoundTick = tick;
}
currentTickValue += unit;
if (cyclenow) {
currentTickValue = calculateLowestVisibleTickValue();
upperValue = cycleBound;
cycled = true;
this.boundMappedToLastCycle = false;
}
}
this.boundMappedToLastCycle = boundMapping;
return result;
}
/**
* 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);
}
}
}
/**
* 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)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -