diff --git a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/scatter/ScatterChart01.java b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/scatter/ScatterChart01.java index 2357bd6a586a27136ab871c8d4b58bb55afefb29..04b51cfea8d3bc1a7f1e88f1c47351fe4167061d 100644 --- a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/scatter/ScatterChart01.java +++ b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/scatter/ScatterChart01.java @@ -33,6 +33,7 @@ import com.xeiam.xchart.demo.charts.ExampleChart; * <li>ChartType.Scatter * <li>Series data as a Set * <li>Setting marker size + * <li>Formatting of negative numbers with large magnitude but small differences */ public class ScatterChart01 implements ExampleChart { @@ -52,7 +53,7 @@ public class ScatterChart01 implements ExampleChart { int size = 1000; for (int i = 0; i < size; i++) { xData.add(random.nextGaussian()); - yData.add(random.nextGaussian()); + yData.add(-100 + random.nextGaussian()); } // Create Chart diff --git a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/scatter/ScatterChart02.java b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/scatter/ScatterChart02.java index 777065cf0ad35b262674a7e536c58ea42b28ba44..a84211ce3de2ae20107b74ce33c33bb003f224bb 100644 --- a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/scatter/ScatterChart02.java +++ b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/scatter/ScatterChart02.java @@ -33,6 +33,7 @@ import com.xeiam.xchart.demo.charts.ExampleChart; * <li>Scatter chart * <li>Logarithmic X-Axis * <li>Place legend at Inside-NW position + * <li>Formatting of number with large magnitude but small differences * * @author timmolter */ diff --git a/xchart/src/main/java/com/xeiam/xchart/StyleManager.java b/xchart/src/main/java/com/xeiam/xchart/StyleManager.java index 07984c8efa14c7c6c3b8b240244451ad9aa7d8a5..c623e480350491c418988d3f1322d14a5644bf3a 100644 --- a/xchart/src/main/java/com/xeiam/xchart/StyleManager.java +++ b/xchart/src/main/java/com/xeiam/xchart/StyleManager.java @@ -1097,9 +1097,9 @@ public class StyleManager { * * @param pattern - the pattern describing the decimal format */ - public void setDecimalPattern(String normalDecimalPattern) { + public void setDecimalPattern(String decimalPattern) { - this.decimalPattern = normalDecimalPattern; + this.decimalPattern = decimalPattern; } public String getDecimalPattern() { diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickBarChartCalculator.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickBarChartCalculator.java index fa02636631695697c3a141cbd3f01394065b0c3b..bc2242e227b2d6ebf547cff31b51e78e178f75f2 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickBarChartCalculator.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickBarChartCalculator.java @@ -108,8 +108,6 @@ public class AxisTickBarChartCalculator extends AxisTickCalculator { NumberFormatter numberFormatter = null; DateFormatter dateFormatter = null; - String pattern = numberFormatter.getFormatPattern(minValue, maxValue); - if (chartPainter.getAxisPair().getXAxis().getAxisType() == AxisType.Number) { numberFormatter = new NumberFormatter(styleManager); } @@ -120,7 +118,7 @@ public class AxisTickBarChartCalculator extends AxisTickCalculator { for (Object category : categories) { if (chartPainter.getAxisPair().getXAxis().getAxisType() == AxisType.Number) { - tickLabels.add(numberFormatter.formatNumber((Double) category, pattern)); + tickLabels.add(numberFormatter.formatNumber((Double) category, minValue, maxValue)); } else if (chartPainter.getAxisPair().getXAxis().getAxisType() == AxisType.Date) { long span = (long) Math.abs(maxValue - minValue); // in data space @@ -141,8 +139,6 @@ public class AxisTickBarChartCalculator extends AxisTickCalculator { NumberFormatter numberFormatter = null; DateFormatter dateFormatter = null; - String pattern = numberFormatter.getFormatPattern(minValue, maxValue); - if (chartPainter.getAxisPair().getXAxis().getAxisType() == AxisType.Number) { numberFormatter = new NumberFormatter(styleManager); } @@ -153,7 +149,7 @@ public class AxisTickBarChartCalculator extends AxisTickCalculator { for (double tickPosition = firstPosition; tickPosition <= maxValue; tickPosition = tickPosition + gridStep) { if (chartPainter.getAxisPair().getXAxis().getAxisType() == AxisType.Number) { - tickLabels.add(numberFormatter.formatNumber(tickPosition, pattern)); + tickLabels.add(numberFormatter.formatNumber(tickPosition, minValue, maxValue)); } else if (chartPainter.getAxisPair().getXAxis().getAxisType() == AxisType.Date) { long span = (long) Math.abs(maxValue - minValue); // in data space diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickLogarithmicCalculator.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickLogarithmicCalculator.java index c06cc803af91a3b6918c51eabcc63150aafe7a80..771a6f2424166d3f7233db16d423c1816216f827 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickLogarithmicCalculator.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickLogarithmicCalculator.java @@ -46,11 +46,9 @@ public class AxisTickLogarithmicCalculator extends AxisTickCalculator { private void calculate() { - String pattern = numberFormatter.getFormatPattern(minValue, maxValue); - // a check if all axis data are the exact same values if (minValue == maxValue) { - tickLabels.add(numberFormatter.formatNumber(maxValue, pattern)); + tickLabels.add(numberFormatter.formatNumber(maxValue, minValue, maxValue)); tickLocations.add(workingSpace / 2.0); return; } @@ -113,7 +111,7 @@ public class AxisTickLogarithmicCalculator extends AxisTickCalculator { // only add labels for the decades if (Math.abs(Math.log10(j) % 1) < 0.00000001) { - tickLabels.add(numberFormatter.formatNumber(j, pattern)); + tickLabels.add(numberFormatter.formatLogNumber(j)); } else { tickLabels.add(null); 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 2b4672b45c322edb4df852d14b9d1511037cd04b..3467ca53b217f65e2d3587f7ffd2a8fd4869aea2 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 @@ -48,11 +48,9 @@ public class AxisTickNumericalCalculator extends AxisTickCalculator { private void calculate() { - String pattern = numberFormatter.getFormatPattern(minValue, maxValue); - // a check if all axis data are the exact same values if (minValue == maxValue) { - tickLabels.add(numberFormatter.formatNumber(maxValue, pattern)); + tickLabels.add(numberFormatter.formatNumber(maxValue, minValue, maxValue)); tickLocations.add(workingSpace / 2.0); return; } @@ -69,7 +67,7 @@ public class AxisTickNumericalCalculator extends AxisTickCalculator { // generate all tickLabels and tickLocations from the first to last position for (BigDecimal tickPosition = firstPosition; tickPosition.compareTo(BigDecimal.valueOf(maxValue + gridStep.doubleValue() * 0.2)) <= 0; tickPosition = tickPosition.add(gridStep)) { - tickLabels.add(numberFormatter.formatNumber(tickPosition.doubleValue(), pattern)); + tickLabels.add(numberFormatter.formatNumber(tickPosition.doubleValue(), minValue, maxValue)); // here we convert tickPosition finally to plot space, i.e. pixels double tickLabelPosition = margin + ((tickPosition.doubleValue() - minValue) / (maxValue - minValue) * tickSpace); tickLocations.add(tickLabelPosition); diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/NumberFormatter.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/NumberFormatter.java index 087de22c89d798f26a05031a08eccac7116264e6..dc526b56fd1a77c4fccbdbdfc3b7650c011f4f8f 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/NumberFormatter.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/NumberFormatter.java @@ -35,36 +35,43 @@ public class NumberFormatter { this.styleManager = styleManager; } - public String getFormatPattern(double min, double max) { + public String getFormatPattern(double value, double min, double max) { + System.out.println("value: " + value); System.out.println("min: " + min); System.out.println("max: " + max); double difference = max - min; - int placeOfDifference = (int) Math.floor(Math.log(difference) / Math.log(10)) + 1; - int placeOfSmallest = (int) Math.floor(Math.log(Math.min(Math.abs(min), Math.abs(max))) / Math.log(10)) + 1; + int placeOfDifference; + if (difference == 0.0) { + placeOfDifference = 0; + } + else { + placeOfDifference = (int) Math.floor(Math.log(difference) / Math.log(10)); + } + int placeOfValue = (int) Math.floor(Math.log(value) / Math.log(10)); System.out.println("difference: " + difference); System.out.println("placeOfDifference: " + placeOfDifference); - System.out.println("placeOfSmallest: " + placeOfSmallest); + System.out.println("placeOfValue: " + placeOfValue); if (placeOfDifference <= 4 && placeOfDifference >= -4) { System.out.println("getNormalDecimalPattern"); - return getNormalDecimalPattern(placeOfSmallest, placeOfDifference); + return getNormalDecimalPattern(placeOfValue, placeOfDifference); } else { System.out.println("getScientificDecimalPattern"); - return getScientificDecimalPattern(placeOfSmallest, placeOfDifference); + return getScientificDecimalPattern(placeOfValue, placeOfDifference); } } - private String getNormalDecimalPattern(int placeOfMin, int placeOfDifference) { + private String getNormalDecimalPattern(int placeOfValue, int placeOfDifference) { int maxNumPlaces = 15; StringBuilder sb = new StringBuilder(); for (int i = maxNumPlaces - 1; i >= -1 * maxNumPlaces; i--) { - if (i < placeOfMin && i >= placeOfDifference - 2) { + if (i < placeOfValue && i >= placeOfDifference) { sb.append("0"); } else { @@ -81,10 +88,10 @@ public class NumberFormatter { return sb.toString(); } - private String getScientificDecimalPattern(int placeOfMin, int placeOfDifference) { + private String getScientificDecimalPattern(int placeOfValue, int placeOfDifference) { StringBuilder sb = new StringBuilder(); - for (int i = placeOfMin; i >= 0; i--) { + for (int i = placeOfValue; i >= 0; i--) { sb.append("0"); if (i == placeOfDifference) { sb.append("."); @@ -101,12 +108,48 @@ public class NumberFormatter { * @param value * @return */ - public String formatNumber(double value, String pattern) { + public String formatNumber(double value, double min, double max) { + + NumberFormat numberFormat = NumberFormat.getNumberInstance(styleManager.getLocale()); + + String decimalPattern; + + if (styleManager.getDatePattern() == null) { + + decimalPattern = getFormatPattern(value, min, max); + } + else { + decimalPattern = styleManager.getDecimalPattern(); + } + + DecimalFormat normalFormat = (DecimalFormat) numberFormat; + normalFormat.applyPattern(decimalPattern); + return normalFormat.format(value); + + } + + /** + * Format a log number value for log Axes which show only decade tick labels. if the override patterns are null, it uses defaults + * + * @param value + * @return + */ + public String formatLogNumber(double value) { NumberFormat numberFormat = NumberFormat.getNumberInstance(styleManager.getLocale()); + String decimalPattern; + + if (styleManager.getDatePattern() == null) { + + decimalPattern = "0E0"; + } + else { + decimalPattern = styleManager.getDatePattern(); + } + DecimalFormat normalFormat = (DecimalFormat) numberFormat; - normalFormat.applyPattern(styleManager.getDecimalPattern() == null ? pattern : styleManager.getDecimalPattern()); + normalFormat.applyPattern(decimalPattern); return normalFormat.format(value); } diff --git a/xchart/src/test/java/com/xeiam/xchart/NumberFormatterTest2.java b/xchart/src/test/java/com/xeiam/xchart/NumberFormatterTest2.java deleted file mode 100644 index 0f6853aa20951b5de95d9afbc34e52fdbf7800d9..0000000000000000000000000000000000000000 --- a/xchart/src/test/java/com/xeiam/xchart/NumberFormatterTest2.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright 2011 - 2014 Xeiam LLC. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.xeiam.xchart; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.MatcherAssert.assertThat; - -import org.junit.Test; - -import com.xeiam.xchart.internal.chartpart.NumberFormatter; - -/** - * @author timmolter - */ -public class NumberFormatterTest2 { - - @Test - public void testNumberFormatting() { - - StyleManager styleManager = new StyleManager(); - NumberFormatter numberFormatter = new NumberFormatter(styleManager); - - String pattern = numberFormatter.getFormatPattern(1000000, 1000010); - System.out.println(pattern); - assertThat(pattern, equalTo("00000.00E0")); - } - -}