📄 logarithmicaxis.java
字号:
/* =========================================================== * JFreeChart : a free chart library for the Java(tm) platform * =========================================================== * * (C) Copyright 2000-2004, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jfreechart/index.html * * This library is free software; you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Foundation; * either version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with this * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. * * [Java is a trademark or registered trademark of Sun Microsystems, Inc. * in the United States and other countries.] * * -------------------- * LogarithmicAxis.java * -------------------- * (C) Copyright 2000-2004, by Object Refinery Limited and Contributors. * * Original Author: Michael Duffy / Eric Thomas; * Contributor(s): David Gilbert (for Object Refinery Limited); * David M. O'Donnell; * Scott Sams; * * $Id: LogarithmicAxis.java,v 1.29 2004/06/03 14:24:21 mungady Exp $ * * Changes * ------- * 14-Mar-2002 : Version 1 contributed by Michael Duffy (DG); * 19-Apr-2002 : drawVerticalString(...) is now drawRotatedString(...) in RefineryUtilities (DG); * 23-Apr-2002 : Added a range property (DG); * 15-May-2002 : Modified to be able to deal with negative and zero values (via new * 'adjustedLog10()' method); occurrences of "Math.log(10)" changed to "LOG10_VALUE"; * changed 'intValue()' to 'longValue()' in 'refreshTicks()' to fix label-text value * out-of-range problem; removed 'draw()' method; added 'autoRangeMinimumSize' check; * added 'log10TickLabelsFlag' parameter flag and implementation (ET); * 25-Jun-2002 : Removed redundant import (DG); * 25-Jul-2002 : Changed order of parameters in ValueAxis constructor (DG); * 16-Jul-2002 : Implemented support for plotting positive values arbitrarily * close to zero (added 'allowNegativesFlag' flag) (ET). * 05-Sep-2002 : Updated constructor reflecting changes in the Axis class (DG); * 02-Oct-2002 : Fixed errors reported by Checkstyle (DG); * 08-Nov-2002 : Moved to new package com.jrefinery.chart.axis (DG); * 22-Nov-2002 : Bug fixes from David M. O'Donnell (DG); * 14-Jan-2003 : Changed autoRangeMinimumSize from Number --> double (DG); * 20-Jan-2003 : Removed unnecessary constructors (DG); * 26-Mar-2003 : Implemented Serializable (DG); * 08-May-2003 : Fixed plotting of datasets with lower==upper bounds when * 'minAutoRange' is very small; added 'strictValuesFlag' * and default functionality of throwing a runtime exception * if 'allowNegativesFlag' is false and any values are less * than or equal to zero; added 'expTickLabelsFlag' and * changed to use "1e#"-style tick labels by default * ("10^n"-style tick labels still supported via 'set' * method); improved generation of tick labels when range of * values is small; changed to use 'NumberFormat.getInstance()' * to create 'numberFormatterObj' (ET); * 14-May-2003 : Merged HorizontalLogarithmicAxis and VerticalLogarithmicAxis (DG); * 29-Oct-2003 : Added workaround for font alignment in PDF output (DG); * 07-Nov-2003 : Modified to use new NumberTick class (DG); * 08-Apr-2004 : Use numberFormatOverride if set - see patch 930139 (DG); * */package org.jfree.chart.axis;import java.awt.Graphics2D;import java.awt.geom.Rectangle2D;import java.text.DecimalFormat;import java.text.NumberFormat;import java.util.List;import org.jfree.chart.plot.Plot;import org.jfree.chart.plot.ValueAxisPlot;import org.jfree.data.Range;import org.jfree.ui.RectangleEdge;import org.jfree.ui.TextAnchor;/** * A numerical axis that uses a logarithmic scale. * * @author Michael Duffy */public class LogarithmicAxis extends NumberAxis { /** Useful constant for log(10). */ public static final double LOG10_VALUE = Math.log(10.0); /** Smallest arbitrarily-close-to-zero value allowed. */ public static final double SMALL_LOG_VALUE = 1e-100; /** Flag set true to allow negative values in data. */ protected boolean allowNegativesFlag = false; /** Flag set true make axis throw exception if any values are * <= 0 and 'allowNegativesFlag' is false. */ protected boolean strictValuesFlag = true; /** Number formatter for generating numeric strings. */ protected final NumberFormat numberFormatterObj = NumberFormat.getInstance(); /** Flag set true for "1e#"-style tick labels. */ protected boolean expTickLabelsFlag = false; /** Flag set true for "10^n"-style tick labels. */ protected boolean log10TickLabelsFlag = true; /** Helper flag for log axis processing. */ protected boolean smallLogFlag = false; /** * Creates a new axis. * * @param label the axis label. */ public LogarithmicAxis(String label) { super(label); setupNumberFmtObj(); //setup number formatter obj } /** * Sets the 'allowNegativesFlag' flag; true to allow negative values * in data, false to be able to plot positive values arbitrarily close to zero. * * @param flgVal the new value of the flag. */ public void setAllowNegativesFlag(boolean flgVal) { this.allowNegativesFlag = flgVal; } /** * Returns the 'allowNegativesFlag' flag; true to allow negative values * in data, false to be able to plot positive values arbitrarily close * to zero. * * @return the flag. */ public boolean getAllowNegativesFlag() { return this.allowNegativesFlag; } /** * Sets the 'strictValuesFlag' flag; if true and 'allowNegativesFlag' * is false then this axis will throw a runtime exception if any of its * values are less than or equal to zero; if false then the axis will * adjust for values less than or equal to zero as needed. * * @param flgVal true for strict enforcement. */ public void setStrictValuesFlag(boolean flgVal) { this.strictValuesFlag = flgVal; } /** * Returns the 'strictValuesFlag' flag; if true and 'allowNegativesFlag' * is false then this axis will throw a runtime exception if any of its * values are less than or equal to zero; if false then the axis will * adjust for values less than or equal to zero as needed. * * @return true if strict enforcement is enabled. */ public boolean getStrictValuesFlag() { return this.strictValuesFlag; } /** * Sets the 'expTickLabelsFlag' flag. If the 'log10TickLabelsFlag' * is false then this will set whether or not "1e#"-style tick labels * are used. The default is to use "1e#"-style tick labels. * * @param flgVal true for "1e#"-style tick labels, false for * log10 or regular numeric tick labels. */ public void setExpTickLabelsFlag(boolean flgVal) { this.expTickLabelsFlag = flgVal; setupNumberFmtObj(); //setup number formatter obj } /** * Returns the 'expTickLabelsFlag' flag. * * @return true for "1e#"-style tick labels, false for log10 or * regular numeric tick labels. */ public boolean getExpTickLabelsFlag() { return this.expTickLabelsFlag; } /** * Sets the 'log10TickLabelsFlag' flag. The default value is false. * * @param flag true for "10^n"-style tick labels, false for "1e#"-style * or regular numeric tick labels. */ public void setLog10TickLabelsFlag(boolean flag) { this.log10TickLabelsFlag = flag; } /** * Returns the 'log10TickLabelsFlag' flag. * * @return true for "10^n"-style tick labels, false for "1e#"-style * or regular numeric tick labels. */ public boolean getLog10TickLabelsFlag() { return this.log10TickLabelsFlag; } /** * Overridden version that calls original and then sets up flag for * log axis processing. * * @param range the new range. */ public void setRange(Range range) { super.setRange(range); // call parent method setupSmallLogFlag(); // setup flag based on bounds values } /** * Sets up flag for log axis processing. Set true if negative values * not allowed and the lower bound is between 0 and 10. */ protected void setupSmallLogFlag() { // set flag true if negative values not allowed and the // lower bound is between 0 and 10: final double lowerVal = getRange().getLowerBound(); this.smallLogFlag = (!this.allowNegativesFlag && lowerVal < 10.0 && lowerVal > 0.0); } /** * Sets up the number formatter object according to the * 'expTickLabelsFlag' flag. */ protected void setupNumberFmtObj() { if (this.numberFormatterObj instanceof DecimalFormat) { //setup for "1e#"-style tick labels or regular // numeric tick labels, depending on flag: ((DecimalFormat) this.numberFormatterObj).applyPattern( this.expTickLabelsFlag ? "0E0" : "0.###" ); } } /** * Returns the log10 value, depending on if values between 0 and * 1 are being plotted. If negative values are not allowed and * the lower bound is between 0 and 10 then a normal log is * returned; otherwise the returned value is adjusted if the * given value is less than 10. * * @param val the value. * * @return log<sub>10</sub>(val). */ protected double switchedLog10(double val) { return this.smallLogFlag ? Math.log(val) / LOG10_VALUE : adjustedLog10(val); } /** * Returns an adjusted log10 value for graphing purposes. The first * adjustment is that negative values are changed to positive during * the calculations, and then the answer is negated at the end. The * second is that, for values less than 10, an increasingly large * (0 to 1) scaling factor is added such that at 0 the value is * adjusted to 1, resulting in a returned result of 0. * * @param val value for which log10 should be calculated. * * @return an adjusted log<sub>10</sub>(val). */ public double adjustedLog10(double val) { final boolean negFlag = (val < 0.0); if (negFlag) { val = -val; // if negative then set flag and make positive } if (val < 10.0) { // if < 10 then val += (10.0 - val) / 10; //increase so 0 translates to 0 } //return value; negate if original value was negative: return negFlag ? -(Math.log(val) / LOG10_VALUE) : (Math.log(val) / LOG10_VALUE); } /** * Returns the largest (closest to positive infinity) double value that is * not greater than the argument, is equal to a mathematical integer and * satisfying the condition that log base 10 of the value is an integer * (i.e., the value returned will be a power of 10: 1, 10, 100, 1000, etc.). * * @param lower a double value below which a floor will be calcualted. * * @return 10<sup>N</sup> with N .. { 1 ... } */ protected double computeLogFloor(double lower) { double logFloor; if (this.allowNegativesFlag) { //negative values are allowed if (lower > 10.0) { //parameter value is > 10 // The Math.log() function is based on e not 10. logFloor = Math.log(lower) / LOG10_VALUE; logFloor = Math.floor(logFloor); logFloor = Math.pow(10, logFloor); } else if (lower < -10.0) { //parameter value is < -10 //calculate log using positive value: logFloor = Math.log(-lower) / LOG10_VALUE; //calculate floor using negative value: logFloor = Math.floor(-logFloor); //calculate power using positive value; then negate logFloor = -Math.pow(10, -logFloor); } else { //parameter value is -10 > val < 10 logFloor = Math.floor(lower); //use as-is } } else { //negative values not allowed if (lower > 0.0) { //parameter value is > 0 // The Math.log() function is based on e not 10. logFloor = Math.log(lower) / LOG10_VALUE; logFloor = Math.floor(logFloor); logFloor = Math.pow(10, logFloor); } else { //parameter value is <= 0 logFloor = Math.floor(lower); //use as-is } } return logFloor; } /** * Returns the smallest (closest to negative infinity) double value that is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -