Skip to content

Commit

Permalink
Fix for bug #64, exception on extreme zoom on NumberAxis
Browse files Browse the repository at this point in the history
  • Loading branch information
jfree committed Oct 24, 2020
1 parent a397509 commit 71b03d8
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 22 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ History

##### Version 1.5.1 (not yet released)
- modify buffer in ChartPanel to handle high DPI displays (bug #170);
- fix for exception on extreme zoom on NumberAxis (bug #64);
- added Catalan translations (PR #117);
- fix for LayeredBarRenderer (bug #169);
- migrated to JUnit 5.
Expand Down
48 changes: 28 additions & 20 deletions src/main/java/org/jfree/chart/axis/NumberAxis.java
Original file line number Diff line number Diff line change
Expand Up @@ -844,27 +844,36 @@ protected void selectHorizontalAutoTickUnit(Graphics2D g2,

TickUnit unit = getTickUnit();
TickUnitSource tickUnitSource = getStandardTickUnits();
// we should use the current tick unit if it gives a count in the range
// 2 to 40 otherwise just estimate one that will give a count <= 20

// we should start with the current tick unit if it gives a count in
// the range 3 to 40 otherwise estimate one that will give a count <= 10
double length = getRange().getLength();
int count = (int) (length / unit.getSize());
if (count < 2 || count > 40) {
unit = tickUnitSource.getCeilingTickUnit(length / 20);
if (count < 3 || count > 40) {
unit = tickUnitSource.getCeilingTickUnit(length / 10);
}
double tickLabelWidth = estimateMaximumTickLabelWidth(g2, unit);

// now consider the label size relative to the width of the tick unit
// and make a guess at the ideal size
TickUnit unit1 = tickUnitSource.getCeilingTickUnit(unit);
double unit1Width = lengthToJava2D(unit1.getSize(), dataArea, edge);

// then extrapolate...
double tickLabelWidth = estimateMaximumTickLabelWidth(g2, unit1);
double unit1Width = lengthToJava2D(unit1.getSize(), dataArea, edge);
NumberTickUnit unit2 = (NumberTickUnit) unit1;
double guess = (tickLabelWidth / unit1Width) * unit1.getSize();
NumberTickUnit unit2 = (NumberTickUnit)
tickUnitSource.getCeilingTickUnit(guess);
double unit2Width = lengthToJava2D(unit2.getSize(), dataArea, edge);

tickLabelWidth = estimateMaximumTickLabelWidth(g2, unit2);
if (tickLabelWidth > unit2Width) {
unit2 = (NumberTickUnit) tickUnitSource.getLargerTickUnit(unit2);

// due to limitations of double precision, when you zoom very far into
// a chart, eventually the visible axis range will get reported as
// having length 0, and then 'guess' above will be infinite ... in that
// case we'll just stick with the tick unit we have, it's better than
// throwing an exception
// https://github.com/jfree/jfreechart/issues/64
if (Double.isFinite(guess)) {
unit2 = (NumberTickUnit) tickUnitSource.getCeilingTickUnit(guess);
double unit2Width = lengthToJava2D(unit2.getSize(), dataArea, edge);
tickLabelWidth = estimateMaximumTickLabelWidth(g2, unit2);
if (tickLabelWidth > unit2Width) {
unit2 = (NumberTickUnit) tickUnitSource.getLargerTickUnit(unit2);
}
}
setTickUnit(unit2, false, false);
}
Expand Down Expand Up @@ -901,7 +910,6 @@ protected void selectVerticalAutoTickUnit(Graphics2D g2,
if (tickLabelHeight > unit2Height) {
unit2 = (NumberTickUnit) tickUnits.getLargerTickUnit(unit2);
}

setTickUnit(unit2, false, false);

}
Expand Down Expand Up @@ -1006,8 +1014,8 @@ protected List refreshTicksHorizontal(Graphics2D g2,
}
}

Tick tick = new NumberTick(new Double(currentTickValue),
tickLabel, anchor, rotationAnchor, angle);
Tick tick = new NumberTick(currentTickValue, tickLabel, anchor,
rotationAnchor, angle);
result.add(tick);
double nextTickValue = lowestTickValue + ((i + 1) * size);
for (int minorTick = 1; minorTick < minorTickSpaces;
Expand Down Expand Up @@ -1106,8 +1114,8 @@ protected List refreshTicksVertical(Graphics2D g2,
}
}

Tick tick = new NumberTick(new Double(currentTickValue),
tickLabel, anchor, rotationAnchor, angle);
Tick tick = new NumberTick(currentTickValue, tickLabel, anchor,
rotationAnchor, angle);
result.add(tick);

double nextTickValue = lowestTickValue + ((i + 1) * size);
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/jfree/chart/axis/NumberTickUnit.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ public boolean equals(Object obj) {
*/
@Override
public String toString() {
return "[size=" + this.valueToString(this.getSize()) + "]";
return "[NumberTickUnit: size=" + this.valueToString(this.getSize())
+ ", formatter=" + this.formatter + "]";
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
* -------------------------
* NumberTickUnitSource.java
* -------------------------
* (C) Copyright 2014, by Object Refinery Limited.
* (C) Copyright 2014-2020, by Object Refinery Limited.
*
* Original Author: David Gilbert (for Object Refinery Limited);
* Contributor(s): -;
Expand Down

0 comments on commit 71b03d8

Please sign in to comment.