/**
 * 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 org.jplot2d.axtick.ArcDmsInterval.Unit;

import java.util.Locale;

/**
 * 
 * @author Jingjing Li
 * 
 */
public class ArcDmsTickCalculator extends AbstractLinearTickCalculator {

	public ArcDmsTickCalculator() {

	}

	protected ArcDmsInterval[] calcCandidateInterval(double rough) {
		ArcDmsInterval itvA, itvB;

		if (rough < Unit.SECOND.angle) {
			rough *= 3600;
			int expn = (int) Math.floor(Math.log10(rough));
			double scale = Math.pow(10, expn);
			/* 1 <= rough/scale < 10 */
			double coeff = rough / scale;
			if (coeff < 2) {
				itvA = new ArcDmsInterval(1, expn);
				itvB = new ArcDmsInterval(2, expn);
			} else if (coeff < 5) {
				itvA = new ArcDmsInterval(2, expn);
				itvB = new ArcDmsInterval(5, expn);
			} else {
				itvA = new ArcDmsInterval(5, expn);
				itvB = new ArcDmsInterval(1, expn + 1);
			}
		} else if (rough < Unit.SECOND.angle * 2) {
			itvA = new ArcDmsInterval(Unit.SECOND, 1);
			itvB = new ArcDmsInterval(Unit.SECOND, 2);
		} else if (rough < Unit.SECOND.angle * 5) {
			itvA = new ArcDmsInterval(Unit.SECOND, 2);
			itvB = new ArcDmsInterval(Unit.SECOND, 5);
		} else if (rough < Unit.SECOND.angle * 10) {
			itvA = new ArcDmsInterval(Unit.SECOND, 5);
			itvB = new ArcDmsInterval(Unit.SECOND, 10);
		} else if (rough < Unit.SECOND.angle * 15) {
			itvA = new ArcDmsInterval(Unit.SECOND, 10);
			itvB = new ArcDmsInterval(Unit.SECOND, 15);
		} else if (rough < Unit.SECOND.angle * 30) {
			itvA = new ArcDmsInterval(Unit.SECOND, 15);
			itvB = new ArcDmsInterval(Unit.SECOND, 30);
		} else if (rough < Unit.MINUTE.angle) {
			itvA = new ArcDmsInterval(Unit.SECOND, 30);
			itvB = new ArcDmsInterval(Unit.MINUTE, 1);
		} else if (rough < Unit.MINUTE.angle * 2) {
			itvA = new ArcDmsInterval(Unit.MINUTE, 1);
			itvB = new ArcDmsInterval(Unit.MINUTE, 2);
		} else if (rough < Unit.MINUTE.angle * 5) {
			itvA = new ArcDmsInterval(Unit.MINUTE, 2);
			itvB = new ArcDmsInterval(Unit.MINUTE, 5);
		} else if (rough < Unit.MINUTE.angle * 10) {
			itvA = new ArcDmsInterval(Unit.MINUTE, 5);
			itvB = new ArcDmsInterval(Unit.MINUTE, 10);
		} else if (rough < Unit.MINUTE.angle * 15) {
			itvA = new ArcDmsInterval(Unit.MINUTE, 10);
			itvB = new ArcDmsInterval(Unit.MINUTE, 15);
		} else if (rough < Unit.MINUTE.angle * 30) {
			itvA = new ArcDmsInterval(Unit.MINUTE, 15);
			itvB = new ArcDmsInterval(Unit.MINUTE, 30);
		} else if (rough < Unit.DEGREE.angle) {
			itvA = new ArcDmsInterval(Unit.MINUTE, 30);
			itvB = new ArcDmsInterval(Unit.DEGREE, 1);
		} else if (rough < Unit.DEGREE.angle * 2) {
			itvA = new ArcDmsInterval(Unit.DEGREE, 1);
			itvB = new ArcDmsInterval(Unit.DEGREE, 2);
		} else if (rough < Unit.DEGREE.angle * 5) {
			itvA = new ArcDmsInterval(Unit.DEGREE, 2);
			itvB = new ArcDmsInterval(Unit.DEGREE, 5);
		} else if (rough < Unit.DEGREE.angle * 10) {
			itvA = new ArcDmsInterval(Unit.DEGREE, 5);
			itvB = new ArcDmsInterval(Unit.DEGREE, 10);
		} else if (rough < Unit.DEGREE.angle * 15) {
			itvA = new ArcDmsInterval(Unit.DEGREE, 10);
			itvB = new ArcDmsInterval(Unit.DEGREE, 15);
		} else if (rough < Unit.DEGREE.angle * 30) {
			itvA = new ArcDmsInterval(Unit.DEGREE, 15);
			itvB = new ArcDmsInterval(Unit.DEGREE, 30);
		} else if (rough < Unit.DEGREE.angle * 45) {
			itvA = new ArcDmsInterval(Unit.DEGREE, 30);
			itvB = new ArcDmsInterval(Unit.DEGREE, 45);
		} else if (rough < Unit.DEGREE.angle * 60) {
			itvA = new ArcDmsInterval(Unit.DEGREE, 45);
			itvB = new ArcDmsInterval(Unit.DEGREE, 60);
		} else if (rough < Unit.DEGREE.angle * 90) {
			itvA = new ArcDmsInterval(Unit.DEGREE, 60);
			itvB = new ArcDmsInterval(Unit.DEGREE, 90);
		} else if (rough < Unit.DEGREE.angle * 180) {
			itvA = new ArcDmsInterval(Unit.DEGREE, 90);
			itvB = new ArcDmsInterval(Unit.DEGREE, 180);
		} else if (rough < Unit.DEGREE.angle * 360) {
			itvA = new ArcDmsInterval(Unit.DEGREE, 180);
			itvB = new ArcDmsInterval(Unit.DEGREE, 360);
		} else {
			itvA = new ArcDmsInterval(Unit.DEGREE, 360);
			itvB = new ArcDmsInterval(Unit.DEGREE, 360);
		}

		return new ArcDmsInterval[] { itvA, itvB };
	}

	public void calcValuesByTickNumber(int tickNumber, int minorTickNumber) {
		ArcDmsInterval intv = (ArcDmsInterval) calcInterval(tickNumber);

		if (minorTickNumber == AUTO_MINORTICK_NUMBER) {
			if (intv.getCoefficient() == 1 && (intv.getUnit() == Unit.MINUTE || intv.getUnit() == Unit.DEGREE)) {
				minorNumber = 0;
			} else {
				minorNumber = calcMinorNumber(intv.getCoefficient(), 3);
			}
		} else {
			minorNumber = minorTickNumber;
		}
		calcValues(interval, 0, minorNumber);
	}

	@Override
	protected int calcMinorNumber(double interval) {

		int s1dInterval;

		if (interval < Unit.SECOND.angle) {
			int mag = (int) Math.floor(Math.log10(interval));
			double coefficient = interval / Math.pow(10, mag);
			double s1dcoef = Math.round(coefficient);
			/*
			 * if the coefficient contains more than 1 significant digit, ignore the minor number
			 */
			if (Math.abs(s1dcoef / coefficient - 1) > DOUBLE_PRECISION_TOLERANCE) {
				s1dInterval = 0;
			} else {
				s1dInterval = (int) s1dcoef;
			}
		} else if (interval < Unit.MINUTE.angle) {
			double secs = interval / Unit.SECOND.angle;
			double s1dcoef = Math.round(secs);
			/*
			 * if the coefficient contains more than 1 significant digit, ignore the minor number
			 */
			if (Math.abs(s1dcoef / secs - 1) > DOUBLE_PRECISION_TOLERANCE) {
				s1dInterval = 0;
			} else {
				s1dInterval = (int) s1dcoef;
			}
		} else if (interval < Unit.DEGREE.angle) {
			double minutes = interval / Unit.MINUTE.angle;
			double s1dcoef = Math.round(minutes);
			/*
			 * if the coefficient contains more than 1 significant digit, ignore the minor number
			 */
			if (Math.abs(s1dcoef / minutes - 1) > DOUBLE_PRECISION_TOLERANCE) {
				s1dInterval = 0;
			} else {
				s1dInterval = (int) s1dcoef;
			}
		} else {
			double degrees = interval / Unit.DEGREE.angle;
			double s1dcoef = Math.round(degrees);
			/*
			 * if the coefficient contains more than 1 significant digit, ignore the minor number
			 */
			if (Math.abs(s1dcoef / degrees - 1) > DOUBLE_PRECISION_TOLERANCE) {
				s1dInterval = 0;
			} else {
				s1dInterval = (int) s1dcoef;
			}
		}

		if (s1dInterval == 0) {
			return 0;
		} else {
			return calcMinorNumber(s1dInterval, 3);
		}

	}

	public ArcDmsFormat calcLabelTextFormat(Object values) {
		if (values instanceof long[]) {
			return new ArcDmsFormat(0);
		}
		if (values instanceof double[]) {
			return new ArcDmsFormat(calcSigFraDigits((double[]) values));
		}
		return null;
	}

	private int calcSigFraDigits(double[] values) {
		/* number of fraction digits */
		int maxFractionDigits = 0;
		for (int i = 0; i < values.length; i++) {
			if (values[i] == 0) {
				continue;
			}

			double v = Math.abs(values[i]) * 3600;

			int mag = (int) Math.floor(Math.log10(v));

			double scale = Math.pow(10, mag);
			double coefficient = v / scale;
			String s = String.format((Locale) null, "%.14f", coefficient);
			/* number of significant digits, eg. the pp1 for 1.1 is 2 */
			int pp1 = lastNon0Idx(s);
			if (maxFractionDigits < pp1 - mag - 1) {
				maxFractionDigits = pp1 - mag - 1;
			}
		}

		return maxFractionDigits;
	}

	/**
	 * Returns the idx that last non-zero. -1 means all 0
	 * 
	 * @param s
	 * @return the idx
	 */
	private static int lastNon0Idx(String s) {
		for (int i = s.length() - 1; i >= 0; i--) {
			if (s.charAt(i) != '0') {
				return i;
			}
		}
		return -1;
	}

	public String calcLabelFormatString(Object values) {
		return "";
	}

	public String getLabelFormate() {
		return "";
	}

}

 

Ads help maintain this website.