/**
 * Copyright 2010-2013 Jingjing Li.
 *
 * This file is part of jplot2d.
 *
 * jplot2d 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 3 of the
 * License, or any later version.
 *
 * jplot2d 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 General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with jplot2d. If not, see .
 */
package org.jplot2d.axtick;

import java.util.Locale;

import org.jplot2d.util.Range;

/**
 * A calculator to calculate tick values and minor tick values
 * 
 * @author Jingjing Li
 */
public abstract class LongTickCalculator extends TickCalculator {

	protected long lo, hi;

	protected boolean inverted;

	public Range getRange() {
		if (!inverted) {
			return new Range.Long(lo, hi);
		} else {
			return new Range.Long(hi, lo);
		}
	}

	public void setRange(Range range) {
		if (range instanceof Range.Long) {
			long start = ((Range.Long) range).start;
			long end = ((Range.Long) range).end;
			this.setRange(start, end);
		} else {
			double start = range.getStart();
			double end = range.getEnd();
			if (Double.isNaN(start) || Double.isInfinite(start) || Double.isNaN(end) || Double.isInfinite(end)) {
				throw new IllegalArgumentException("Range cannot start or end on NaN/Infinite value");
			}
			if (start < end) {
				this.setRange((long) Math.floor(start), (long) Math.ceil(end));
			} else {
				this.setRange((long) Math.ceil(start), (long) Math.floor(end));
			}
		}
	}

	protected void setRange(long start, long end) {
		boolean inverted = start > end;

		if (!inverted) {
			lo = start;
			hi = end;
		} else {
			lo = end;
			hi = start;
		}
	}

	public abstract long[] getValues();

	public abstract long[] getMinorValues();

	/**
	 * Calculate the tick values by the given interval and minor ticks number. The minor ticks number is a proposed
	 * value, and may be different from actual minor ticks number returned by {@link #getMinorNumber()}.
	 * 
	 * @param interval
	 * @param offset
	 * @param minorTickNumber
	 *            if the given number is {@link #AUTO_MINORTICK_NUMBER}, the tick number is derived from interval.
	 */
	public void calcValuesByTickInterval(double interval, double offset, int minorTickNumber) {
		calcValuesByTickInterval(Math.round(interval), Math.round(offset), minorTickNumber);
	}

	public abstract void calcValuesByTickInterval(long interval, long offset, int minorTickNumber);

	public int[] getInRangeValuesIdx(Object v) {
		if (v instanceof long[]) {
			return getInRangeValuesIdx((long[]) v);
		}
		throw new IllegalArgumentException();
	}

	private int[] getInRangeValuesIdx(long[] v) {
		long expandLo = lo;
		long expandHi = hi;

		int[] m = new int[v.length];
		int j = 0;
		for (int i = 0; i < v.length; i++) {
			if (expandLo <= v[i] && v[i] <= expandHi) {
				m[j++] = i;
			}
		}

		if (j == v.length) {
			// all in range selection
			return m;
		} else {
			int[] result = new int[j];
			System.arraycopy(m, 0, result, 0, j);
			return result;
		}
	}

	public String calcLabelFormatString(Object valueArray) {

		long[] values = (long[]) valueArray;

		int maxMag = Integer.MIN_VALUE;
		/* number of significant digits */
		int maxPrec = 0;

		for (int i = 0; i < values.length; i++) {
			if (values[i] == 0) {
				continue;
			}

			long v = Math.abs(values[i]);

			int mag = (int) Math.floor(Math.log10(v));
			if (maxMag < mag) {
				maxMag = mag;
			}

			String s = String.format((Locale) null, "%d", v);
			/* number of significant digits. eg. pp1 for 1100 is 2 */
			int pp1 = 0;
			for (int ci = s.length() - 1; ci >= 0; ci--) {
				if (s.charAt(ci) != '0') {
					pp1 = ci + 1;
					break;
				}
			}

			if (maxPrec < pp1) {
				maxPrec = pp1;
			}
		}

		/* the number of 0 we can save */
		int n0 = maxMag - maxPrec + 1;
		if (n0 < 4 && maxMag < 6) {
			return "%d";
		} else {
			return "%." + (maxPrec - 1) + "m";
		}

	}

}

 

Ads help maintain this website.