/* * AxisLog10.java of project jchart2d, Axis implementation with log base 10 * display. * Copyright (c) 2007 - 2011 Achim Westermann, created on 20:33:13. * * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * If you modify or optimize the code in a useful way please let me know. * Achim.Westermann@gmx.de * */ package info.monitorenter.gui.chart.axis; import info.monitorenter.gui.chart.IAxisLabelFormatter; import info.monitorenter.gui.chart.ITrace2D; import info.monitorenter.gui.chart.axis.scalepolicy.AxisScalePolicyAutomaticBestFit; import info.monitorenter.gui.chart.axis.scalepolicy.AxisScalePolicyTransformation; import info.monitorenter.gui.chart.labelformatters.LabelFormatterSimple; import java.util.Iterator; /** * An {@link info.monitorenter.gui.chart.axis.AAxis} with log base 10 scaled * display of values. * <p> * <h2>Caution</h2> * This will not work with negative values (Double.NaN is computed for log of * negative values). * <p> * This will even not work with values < 1.0 as the log transformation turns * negative for values < 1.0 and becomes {@link Double#NEGATIVE_INFINITY} with * lim -> 0.0 with more and more turns to a 100 % CPU load. * <p> * * @param <T> * Used to enforce that this instance only accepts * {@link AxisScalePolicyTransformation} and subtypes. * * @author Pieter-Jan Busschaert (contributor) * * @author <a href="mailto:Achim.Westermann@gmx.de">Achim Westermann</a> * * * @version $Revision: 1.15 $ */ public class AxisLog10<T extends AxisScalePolicyTransformation> extends AAxisTransformation<T> { /** Generated <code>serialVersionUID</code>. */ private static final long serialVersionUID = -1783172443489534956L; /** * Creates an instance that uses a {@link LabelFormatterSimple} for formatting * numbers and a {@link AxisScalePolicyAutomaticBestFit} for controlling the * scale. * <p> * */ @SuppressWarnings("unchecked") public AxisLog10() { /* * I consider this necessary cast to T as a bug (compare with declaration if T in class header): */ this(new LabelFormatterSimple(), (T)new AxisScalePolicyTransformation()); } /** * Constructor that uses the given label formatter for formatting labels. * <p> * * @param formatter * needed for formatting labels of this axis. Prefer using simple * implementations like {@link LabelFormatterSimple}, a log axis is * complicated enough to understand. * * @param scalePolicy * controls the ticks/labels and their distance. */ public AxisLog10(final IAxisLabelFormatter formatter, final T scalePolicy) { super(formatter, scalePolicy); } /** * Performs {@link Math#log10(double)} with a check for reaching infinity. * <p> * * The argument should not be negative, so only normalized values (no chart * values but their scaled values or pixel values) should be given here. * <p> * * If the argument is close to zero, the result of log would be * {@link Double#POSITIVE_INFINITY} which is transformed to * {@link Double#MAX_VALUE}. * <p> * * @param in * the value to compute the log base 10 of. * * @return log base 10 for the given value. */ @Override public double transform(final double in) { double toTransform = in; /* * Starting from 1 downwards the transformation of this value becomes * negative, lim -> 0 becomes Double.NEGATIVE_INFINITY, which causes the * "while(true)" 100 % load effect. So everything is disallowed below 1.0. */ if (toTransform < 1) { // allow to transform the input for empty traces or all traces with empty // points: if (this.m_accessor == null) { throw new IllegalStateException("Connect this axis (" + this.getAxisTitle().getTitle() + ") to a chart first before doing this operation."); } Iterator<ITrace2D> itTraces = this.m_accessor.getChart().getTraces().iterator(); if (!itTraces.hasNext()) { toTransform = 1.0; } else { ITrace2D trace; while (itTraces.hasNext()) { trace = itTraces.next(); if (trace.iterator().hasNext()) { // Illegal value for transformation defined by a point added: throw new IllegalArgumentException(this.getClass().getName() + " must not be used with values < 1!"); } } // No illegal point: everything was empty toTransform = 1.0; } } // TODO: change this to Math.log10 as soon as java 1.5 is used: double result = Math.log(toTransform) / Math.log(10); if (Double.isInfinite(result)) { result = Double.MAX_VALUE; } return result; } /** * @see AAxisTransformation#untransform(double) */ @Override public double untransform(final double in) { return Math.pow(10, in); } }