/*
* Copyright (C) 2011 United States Government as represented by the Administrator of the
* National Aeronautics and Space Administration.
* All Rights Reserved.
*/
package gov.nasa.worldwind.util;
import gov.nasa.worldwind.geom.*;
/**
* A collection of useful math methods, all static.
*
* @author tag
* @version $Id$
*/
public class WWMath
{
public static final double SECOND_TO_MILLIS = 1000.0;
public static final double MINUTE_TO_MILLIS = 60.0 * SECOND_TO_MILLIS;
public static final double HOUR_TO_MILLIS = 60.0 * MINUTE_TO_MILLIS;
public static final double DAY_TO_MILLIS = 24.0 * HOUR_TO_MILLIS;
public static final double METERS_TO_KILOMETERS = 1e-3;
public static final double METERS_TO_MILES = 0.000621371192;
public static final double METERS_TO_NAUTICAL_MILES = 0.000539956803;
public static final double METERS_TO_YARDS = 1.0936133;
public static final double METERS_TO_FEET = 3.280839895;
public static final double SQUARE_METERS_TO_SQUARE_KILOMETERS = 1e-6;
public static final double SQUARE_METERS_TO_SQUARE_MILES = 3.86102159e-7;
public static final double SQUARE_METERS_TO_SQUARE_YARDS = 1.19599005;
public static final double SQUARE_METERS_TO_SQUARE_FEET = 10.7639104;
public static final double SQUARE_METERS_TO_HECTARES = 1e-4;
public static final double SQUARE_METERS_TO_ACRES = 0.000247105381;
public static final LatLon LONGITUDE_OFFSET_180 = LatLon.fromDegrees(0, 180);
/**
* Convenience method to compute the log base 2 of a value.
*
* @param value the value to take the log of.
*
* @return the log base 2 of the specified value.
*/
public static double logBase2(double value)
{
return Math.log(value) / Math.log(2d);
}
/**
* Convenience method for testing whether a value is a power of two.
*
* @param value the value to test for power of 2
*
* @return true if power of 2, else false
*/
public static boolean isPowerOfTwo(int value)
{
return (value == powerOfTwoCeiling(value));
}
/**
* Returns the value that is the nearest power of 2 greater than or equal to the given value.
*
* @param reference the reference value. The power of 2 returned is greater than or equal to this value.
*
* @return the value that is the nearest power of 2 greater than or equal to the reference value
*/
public static int powerOfTwoCeiling(int reference)
{
int power = (int) Math.ceil(Math.log(reference) / Math.log(2d));
return (int) Math.pow(2d, power);
}
/**
* Returns the value that is the nearest power of 2 less than or equal to the given value.
*
* @param reference the reference value. The power of 2 returned is less than or equal to this value.
*
* @return the value that is the nearest power of 2 less than or equal to the reference value
*/
public static int powerOfTwoFloor(int reference)
{
int power = (int) Math.floor(Math.log(reference) / Math.log(2d));
return (int) Math.pow(2d, power);
}
/**
* Populate an array with the successive powers of a number.
*
* @param base the number whose powers to compute.
* @param numPowers the number of powers to compute.
*
* @return an array containing the requested values. Each element contains the value b^i, where b is the base and i
* is the element number (0, 1, etc.).
*/
protected static int[] computePowers(int base, int numPowers)
{
int[] powers = new int[numPowers];
powers[0] = 1;
for (int i = 1; i < numPowers; i++)
{
powers[i] += base * powers[i - 1];
}
return powers;
}
/**
* Clamps a value to a given range.
*
* @param v the value to clamp.
* @param min the floor.
* @param max the ceiling
*
* @return the nearest value such that min <= v <= max.
*/
public static double clamp(double v, double min, double max)
{
return v < min ? min : v > max ? max : v;
}
/**
* Clamps an integer value to a given range.
*
* @param v the value to clamp.
* @param min the floor.
* @param max the ceiling
*
* @return the nearest value such that min <= v <= max.
*/
public static int clamp(int v, int min, int max)
{
return v < min ? min : v > max ? max : v;
}
/**
* Returns the interpolation factor for <code>v</code> given the specified range <code>[x, y]</code>. The
* interpolation factor is a number between 0 and 1 (inclusive), representing the value's relative position between
* <code>x</code> and <code>y</code>. For example, 0 corresponds to <code>x</code>, 1 corresponds to <code>y</code>,
* and anything in between corresponds to a linear combination of <code>x</code> and <code>y</code>.
*
* @param v the value to compute the interpolation factor for.
* @param x the first value.
* @param y the second value.
*
* @return the interpolation factor for <code>v</code> given the specified range <code>[x, y]</code>
*/
public static double computeInterpolationFactor(double v, double x, double y)
{
return clamp((v - x) / (y - x), 0d, 1d);
}
/**
* Returns the linear interpolation of <code>x</code> and <code>y</code> according to the function: <code>(1 - a) *
* x + a * y</code>. The interpolation factor <code>a</code> defines the weight given to each value, and is clamped
* to the range [0, 1]. If <code>a</code> is 0 or less, this returns x. If <code>a</code> is 1 or more, this returns
* <code>y</code>. Otherwise, this returns the linear interpolation of <code>x</code> and <code>y</code>. For
* example, when <code>a</code> is <code>0.5</code> this returns <code>(x + y)/2</code>.
*
* @param a the interpolation factor.
* @param x the first value.
* @param y the second value.
*
* @return the linear interpolation of <code>x</code> and <code>y</code>.
*/
public static double mix(double a, double x, double y)
{
double t = clamp(a, 0d, 1d);
return x + t * (y - x);
}
/**
* Returns the smooth hermite interpolation of <code>x</code> and <code>y</code> according to the function: <code>(1
* - t) * x + t * y</code>, where <code>t = a * a * (3 - 2 * a)</code>. The interpolation factor <code>a</code>
* defines the weight given to each value, and is clamped to the range [0, 1]. If <code>a</code> is 0 or less, this
* returns <code>x</code>. If <code>a</code> is 1 or more, this returns <code>y</code>. Otherwise, this returns the
* smooth hermite interpolation of <code>x</code> and <code>y</code>. Like the linear function {@link #mix(double,
* double, double)}, when <code>a</code> is <code>0.5</code> this returns <code>(x + y)/2</code>. But unlike the
* linear function, the hermite function's slope gradually increases when <code>a</code> is near 0, then gradually
* decreases when <code>a</code> is near 1. This is a useful property where a more gradual transition from
* <code>x</code> to <code>y</code> is desired.
*
* @param a the interpolation factor.
* @param x the first value.
* @param y the second value.
*
* @return the smooth hermite interpolation of <code>x</code> and <code>y</code>.
*/
public static double mixSmooth(double a, double x, double y)
{
double t = clamp(a, 0d, 1d);
t = t * t * (3d - 2d * t);
return x + t * (y - x);
}
/**
* converts meters to feet.
*
* @param meters the value in meters.
*
* @return the value converted to feet.
*/
public static double convertMetersToFeet(double meters)
{
return (meters * METERS_TO_FEET);
}
/**
* converts meters to miles.
*
* @param meters the value in meters.
*
* @return the value converted to miles.
*/
public static double convertMetersToMiles(double meters)
{
return (meters * METERS_TO_MILES);
}
/**
* Converts distance in feet to distance in meters.
*
* @param feet the distance in feet.
*
* @return the distance converted to meters.
*/
public static double convertFeetToMeters(double feet)
{
return (feet / METERS_TO_FEET);
}
/**
* Converts time in seconds to time in milliseconds.
*
* @param seconds time in seconds.
*
* @return time in milliseconds.
*/
public static double convertSecondsToMillis(double seconds)
{
return (seconds * SECOND_TO_MILLIS);
}
/**
* Converts time in milliseconds to time in seconds.
*
* @param millis time in milliseconds.
*
* @return time in seconds.
*/
public static double convertMillisToSeconds(double millis)
{
return millis / SECOND_TO_MILLIS;
}
/**
* Converts time in minutes to time in milliseconds.
*
* @param minutes time in minutes.
*
* @return time in milliseconds.
*/
public static double convertMinutesToMillis(double minutes)
{
return (minutes * MINUTE_TO_MILLIS);
}
/**
* Converts time in milliseconds to time in minutes.
*
* @param millis time in milliseconds.
*
* @return time in minutes.
*/
public static double convertMillisToMinutes(double millis)
{
return millis / MINUTE_TO_MILLIS;
}
/**
* Converts time in hours to time in milliseconds.
*
* @param hours time in hours.
*
* @return time in milliseconds.
*/
public static double convertHoursToMillis(double hours)
{
return (hours * HOUR_TO_MILLIS);
}
/**
* Converts time in milliseconds to time in hours.
*
* @param mills time in milliseconds.
*
* @return time in hours.
*/
public static double convertMillisToHours(double mills)
{
return mills / HOUR_TO_MILLIS;
}
/**
* Convert time in days to time in milliseconds.
*
* @param millis time in days.
*
* @return time in milliseconds.
*/
public static double convertDaysToMillis(double millis)
{
return millis * DAY_TO_MILLIS;
}
/**
* Convert time in milliseconds to time in days.
*
* @param millis time in milliseconds.
*
* @return time in days.
*/
public static double convertMillisToDays(double millis)
{
return millis / DAY_TO_MILLIS;
}
}