diff --git a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/scatter/ScatterChart04.java b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/scatter/ScatterChart04.java index af059ccc50867e8b8a9cd6201eca0deffc2b6b45..ff2d0bd33c58b8d1b07ff6cfa49ccdacbdec1a63 100644 --- a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/scatter/ScatterChart04.java +++ b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/scatter/ScatterChart04.java @@ -36,6 +36,7 @@ import com.xeiam.xchart.demo.charts.ExampleChart; * <li>Using ChartBuilder to Make a Chart * <li>List<Number> data sets * <li>Setting Series Marker and Marker Color + * <li>Using a custom decimal pattern */ public class ScatterChart04 implements ExampleChart { @@ -55,7 +56,7 @@ public class ScatterChart04 implements ExampleChart { List<Double> yData = new ArrayList<Double>(); List<Double> errorBars = new ArrayList<Double>(); for (int i = 0; i <= size; i++) { - xData.add(((double) i) / 100000000); + xData.add(((double) i) / 1000000); yData.add(10 * Math.exp(-i)); errorBars.add(Math.random() + .3); } @@ -67,6 +68,7 @@ public class ScatterChart04 implements ExampleChart { chart.getStyleManager().setChartTitleVisible(false); chart.getStyleManager().setLegendVisible(false); chart.getStyleManager().setAxisTitlesVisible(false); + chart.getStyleManager().setXAxisDecimalPattern("0.0000000"); // Series Series series = chart.addSeries("10^(-x)", xData, yData, errorBars); diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTick.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTick.java index 6331a8fd115b071e5e7aab4a36f3ddc331f91216..8870dd45c1b54527bb00103d1401fce15bd7746d 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTick.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTick.java @@ -15,6 +15,7 @@ */ package com.xeiam.xchart.internal.chartpart; +import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.util.List; @@ -74,7 +75,7 @@ public class AxisTick implements ChartPart { // System.out.println("workingspace= " + workingSpace); } - System.out.println("AxisTick: " + axis.getDirection()); + // System.out.println("AxisTick: " + axis.getDirection()); // System.out.println("workingSpace: " + workingSpace); axisTickCalculator = getAxisTickCalculator(workingSpace); @@ -95,8 +96,8 @@ public class AxisTick implements ChartPart { ); - // g.setColor(Color.red); - // g.draw(bounds); + g.setColor(Color.red); + g.draw(bounds); } else if (axis.getDirection() == Axis.Direction.X && getChartPainter().getStyleManager().isXAxisTicksVisible()) { @@ -106,8 +107,9 @@ public class AxisTick implements ChartPart { bounds = new Rectangle2D.Double(axisTickMarks.getBounds().getX(), axisTickMarks.getBounds().getY(), axisTickLabels.getBounds().getWidth(), axisTickMarks.getBounds().getHeight() + getChartPainter().getStyleManager().getAxisTickPadding() + axisTickLabels.getBounds().getHeight()); - // g.setColor(Color.red); - // g.draw(bounds); + + g.setColor(Color.red); + g.draw(bounds); } diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickCalculator.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickCalculator.java index 8f5d5723ca996ea9a7d939c8b781dc1f17e52fee..10d7685fa8efbc16ccbb84afadb35db10aa72bd3 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickCalculator.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickCalculator.java @@ -142,6 +142,7 @@ public abstract class AxisTickCalculator { sampleLabel = tickLabels.get(i); } } + // System.out.println("longestLabel: " + sampleLabel); TextLayout textLayout = new TextLayout(sampleLabel, styleManager.getAxisTickLabelsFont(), new FontRenderContext(null, true, false)); AffineTransform rot = styleManager.getXAxisLabelRotation() == 0 ? null : AffineTransform.getRotateInstance(-1 * Math.toRadians(styleManager.getXAxisLabelRotation())); @@ -151,7 +152,7 @@ public abstract class AxisTickCalculator { // System.out.println("largestLabelWidth: " + largestLabelWidth); // System.out.println("tickSpacingHint: " + tickSpacingHint); - return (largestLabelWidth * 1.8 < tickSpacingHint); + return (largestLabelWidth * 1.6 < tickSpacingHint); } } diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickDateCalculator.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickDateCalculator.java index fbc7f0218f04a3f60cc7f14a04c8817e446fb6b3..f128202bd7f51d3fbabb56c77c0e230d27dbb2a4 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickDateCalculator.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickDateCalculator.java @@ -58,14 +58,13 @@ public class AxisTickDateCalculator extends AxisTickCalculator { // Can tickSpacingHint be intelligently calculated by looking at the label data? // YES. Generate the labels first, see if they "look" OK and reiterate with an increased tickSpacingHint // TODO apply this to other Axis types including bar charts - // TODO only do this for the X-Axis - int tickSpacingHint = styleManager.getXAxisTickMarkSpacingHint() - 10; + int tickSpacingHint = styleManager.getXAxisTickMarkSpacingHint() - 5; do { - System.out.println("calulating ticks..."); + // System.out.println("calculating ticks..."); tickLabels.clear(); tickLocations.clear(); - tickSpacingHint += 10; + tickSpacingHint += 5; long gridStepHint = (long) (span / tickSpace * tickSpacingHint); long timeUnit = dateFormatter.getTimeUnit(gridStepHint); @@ -85,10 +84,13 @@ public class AxisTickDateCalculator extends AxisTickCalculator { // generate all tickLabels and tickLocations from the first to last position for (double value = firstPosition; value <= maxValue + 2 * gridStep; value = value + gridStep) { - tickLabels.add(dateFormatter.formatDate(value, timeUnit)); - // here we convert tickPosition finally to plot space, i.e. pixels - double tickLabelPosition = margin + ((value - minValue) / (maxValue - minValue) * tickSpace); - tickLocations.add(tickLabelPosition); + if (value <= maxValue && value >= minValue) { + + tickLabels.add(dateFormatter.formatDate(value, timeUnit)); + // here we convert tickPosition finally to plot space, i.e. pixels + double tickLabelPosition = margin + ((value - minValue) / (maxValue - minValue) * tickSpace); + tickLocations.add(tickLabelPosition); + } } } while (!willLabelsFitInTickSpaceHint(tickLabels, tickSpacingHint)); } diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickNumericalCalculator.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickNumericalCalculator.java index 99f7fe2ef508e354692da6d50de9107b4411ce5d..79142c095385ee713909225efc88e4a62cfbcc87 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickNumericalCalculator.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickNumericalCalculator.java @@ -59,96 +59,96 @@ public class AxisTickNumericalCalculator extends AxisTickCalculator { // tick space - a percentage of the working space available for ticks double tickSpace = styleManager.getAxisTickSpacePercentage() * workingSpace; // in plot space - // where the tick should begin in the working space in pixels - double margin = Utils.getTickStartOffset(workingSpace, tickSpace); // in plot space double gridStep = getGridStepForDecimal(tickSpace); - - BigDecimal gridStep = BigDecimal.valueOf(getNumericalGridStep(tickSpace)); - // System.out.println("***gridStep: " + gridStep); - BigDecimal cleanedGridStep = gridStep.setScale(10, RoundingMode.HALF_UP).stripTrailingZeros(); // chop off any double imprecision - // System.out.println("cleanedGridStep: " + cleanedGridStep); - BigDecimal firstPosition = BigDecimal.valueOf(getFirstPosition(cleanedGridStep.doubleValue())); - // System.out.println("firstPosition: " + firstPosition); // chop off any double imprecision - BigDecimal cleanedFirstPosition = firstPosition.setScale(10, RoundingMode.HALF_UP).stripTrailingZeros(); // chop off any double imprecision - // System.out.println("cleanedFirstPosition: " + cleanedFirstPosition); - - // generate all tickLabels and tickLocations from the first to last position - for (BigDecimal value = cleanedFirstPosition; value.compareTo(BigDecimal.valueOf(maxValue + 2 * cleanedGridStep.doubleValue())) < 0; value = value.add(cleanedGridStep)) { - - // System.out.println(value); - String tickLabel = numberFormatter.formatNumber(value, minValue, maxValue, axisDirection); - // System.out.println(tickLabel); - tickLabels.add(tickLabel); - - // here we convert tickPosition finally to plot space, i.e. pixels - double tickLabelPosition = margin + ((value.doubleValue() - minValue) / (maxValue - minValue) * tickSpace); - tickLocations.add(tickLabelPosition); - } - } - - /** - * Determine the grid step for the data set given the space in pixels allocated for the axis - * - * @param tickSpace in plot space - * @return - */ - private double getNumericalGridStep(double tickSpace) { - // this prevents an infinite loop when the plot gets sized really small. if (tickSpace < 10) { - return 1.0; + return; } + // where the tick should begin in the working space in pixels + double margin = Utils.getTickStartOffset(workingSpace, tickSpace); // in plot space double gridStep = getGridStepForDecimal(tickSpace); // the span of the data double span = Math.abs(maxValue - minValue); // in data space - int tickMarkSpaceHint = (axisDirection == Direction.X ? styleManager.getXAxisTickMarkSpacingHint() : styleManager.getYAxisTickMarkSpacingHint()); + ////////////////////////// + + int tickSpacingHint = (axisDirection == Direction.X ? styleManager.getXAxisTickMarkSpacingHint() : styleManager.getYAxisTickMarkSpacingHint()) - 5; - // for very short plots, squeeze some more ticks in than normal + // for very short plots, squeeze some more ticks in than normal into the Y-Axis if (axisDirection == Direction.Y && tickSpace < 160) { - tickMarkSpaceHint = 25; + tickSpacingHint = 25 - 5; } + do { + + // System.out.println("calculating ticks..."); + tickLabels.clear(); + tickLocations.clear(); + tickSpacingHint += 5; + double gridStepHint = span / tickSpace * tickSpacingHint; + + // gridStepHint --> significand * 10 ** exponent + // e.g. 724.1 --> 7.241 * 10 ** 2 + double significand = gridStepHint; + int exponent = 0; + if (significand == 0) { + exponent = 1; + } + else if (significand < 1) { + while (significand < 1) { + significand *= 10.0; + exponent--; + } + } + else { + while (significand >= 10 || significand == Double.NEGATIVE_INFINITY) { + significand /= 10.0; + exponent++; + } + } - double gridStepHint = span / tickSpace * tickMarkSpaceHint; - - // gridStepHint --> significand * 10 ** exponent - // e.g. 724.1 --> 7.241 * 10 ** 2 - double significand = gridStepHint; - int exponent = 0; - if (significand == 0) { - exponent = 1; - } - else if (significand < 1) { - while (significand < 1) { - significand *= 10.0; - exponent--; + // calculate the grid step with hint. + double gridStep; + if (significand > 7.5) { + // gridStep = 10.0 * 10 ** exponent + gridStep = 10.0 * Utils.pow(10, exponent); } - } - else { - while (significand >= 10 || significand == Double.NEGATIVE_INFINITY) { - significand /= 10.0; - exponent++; + else if (significand > 3.5) { + // gridStep = 5.0 * 10 ** exponent + gridStep = 5.0 * Utils.pow(10, exponent); } - } + else if (significand > 1.5) { + // gridStep = 2.0 * 10 ** exponent + gridStep = 2.0 * Utils.pow(10, exponent); + } + else { + // gridStep = 1.0 * 10 ** exponent + gridStep = Utils.pow(10, exponent); + } + ////////////////////////// + BigDecimal gridStepBigDecimal = BigDecimal.valueOf(gridStep); + // System.out.println("***gridStep: " + gridStep); + BigDecimal cleanedGridStep = gridStepBigDecimal.setScale(10, RoundingMode.HALF_UP).stripTrailingZeros(); // chop off any double imprecision + // System.out.println("cleanedGridStep: " + cleanedGridStep); + BigDecimal firstPosition = BigDecimal.valueOf(getFirstPosition(cleanedGridStep.doubleValue())); + // System.out.println("firstPosition: " + firstPosition); // chop off any double imprecision + BigDecimal cleanedFirstPosition = firstPosition.setScale(10, RoundingMode.HALF_UP).stripTrailingZeros(); // chop off any double imprecision + // System.out.println("cleanedFirstPosition: " + cleanedFirstPosition); + + // generate all tickLabels and tickLocations from the first to last position + for (BigDecimal value = cleanedFirstPosition; value.compareTo(BigDecimal.valueOf(maxValue + 2 * cleanedGridStep.doubleValue())) < 0; value = value.add(cleanedGridStep)) { + + if (value.compareTo(BigDecimal.valueOf(maxValue)) <= 0 && value.compareTo(BigDecimal.valueOf(minValue)) >= 0) { + // System.out.println(value); + String tickLabel = numberFormatter.formatNumber(value, minValue, maxValue, axisDirection); + // System.out.println(tickLabel); + tickLabels.add(tickLabel); + + // here we convert tickPosition finally to plot space, i.e. pixels + double tickLabelPosition = margin + ((value.doubleValue() - minValue) / (maxValue - minValue) * tickSpace); + tickLocations.add(tickLabelPosition); + } + } + } while (!willLabelsFitInTickSpaceHint(tickLabels, tickSpacingHint)); - // calculate the grid step with hint. - double gridStep; - if (significand > 7.5) { - // gridStep = 10.0 * 10 ** exponent - gridStep = 10.0 * Utils.pow(10, exponent); - } - else if (significand > 3.5) { - // gridStep = 5.0 * 10 ** exponent - gridStep = 5.0 * Utils.pow(10, exponent); - } - else if (significand > 1.5) { - // gridStep = 2.0 * 10 ** exponent - gridStep = 2.0 * Utils.pow(10, exponent); - } - else { - // gridStep = 1.0 * 10 ** exponent - gridStep = Utils.pow(10, exponent); - } - return gridStep; } }