1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
package tim.prune.data;
public class FractionalSeconds
{
private final long _numerator;
private final byte _divisorDigits;
public FractionalSeconds(long inDegrees, long inDegFrac, int inDigits)
{
// Limit digits to maximum 13 to stop longs from overflowing
int digits = inDigits;
long degFrac = inDegFrac;
while (digits > 13)
{
digits--;
degFrac = degFrac / 10L;
}
long degDenom = getMultiplier(digits);
_numerator = (inDegrees * degDenom + degFrac) * 60L * 60L;
_divisorDigits = (byte) digits;
}
public FractionalSeconds(long inDegrees, long inMinutes, long inMinFrac, int inDigits)
{
long minDenom = getMultiplier(inDigits);
_numerator = ((inDegrees * 60L + inMinutes) * minDenom + inMinFrac) * 60L;
_divisorDigits = (byte) inDigits;
}
public FractionalSeconds(long inDegrees, long inMinutes, long inSeconds, long inSecFrac, int inDigits)
{
long secDenom = getMultiplier(inDigits);
_numerator = ((inDegrees * 60L + inMinutes) * 60L + inSeconds) * secDenom + inSecFrac;
_divisorDigits = (byte) inDigits;
}
public static FractionalSeconds fromDouble(double inDegrees, int inNumDigits)
{
double value = Math.abs(inDegrees) * getMultiplier(inNumDigits);
long numerator = (long) (value * 60.0 * 60.0);
return new FractionalSeconds(numerator, (byte) inNumDigits);
}
private FractionalSeconds(long inNumerator, byte inNumDigits)
{
_numerator = inNumerator;
_divisorDigits = inNumDigits;
}
public int getTotalSeconds()
{
long seconds = _numerator / getMultiplier(_divisorDigits);
return (int) seconds;
}
public int getWholeDegrees() {
return getTotalSeconds() / 60 / 60;
}
public int getWholeMinutes() {
return (getTotalSeconds() / 60) % 60;
}
public int getWholeSeconds() {
return getTotalSeconds() % 60;
}
public String getFractionDegrees() {
return getFractionString(_numerator / 60L / 60L, _divisorDigits);
}
public String getFractionDegrees(int inNumDigits)
{
if (inNumDigits != _divisorDigits) {
return roundToSeconds(inNumDigits).divideBy(3600L).getFractionSeconds();
}
return getFractionDegrees();
}
public String getFractionMinutes() {
return getFractionString(_numerator / 60L, _divisorDigits);
}
public String getFractionMinutes(int inNumDigits)
{
if (inNumDigits != _divisorDigits) {
return roundToSeconds(inNumDigits).divideBy(60L).getFractionSeconds();
}
return getFractionMinutes();
}
public String getFractionSeconds() {
return getFractionString(_numerator, _divisorDigits);
}
public String getFractionSeconds(int inNumDigits) {
return roundToSeconds(inNumDigits).getFractionSeconds();
}
public double getDouble() {
return _numerator * 1.0 / getMultiplier(_divisorDigits) / 3600.0;
}
public FractionalSeconds roundToDegrees(int inNumDigits) {
return roundTo(60L * 60L, inNumDigits);
}
public FractionalSeconds roundToMinutes(int inNumDigits) {
return roundTo(60L, inNumDigits);
}
public FractionalSeconds roundToSeconds(int inNumDigits) {
return roundTo(1L, inNumDigits);
}
private FractionalSeconds roundTo(long inMultFactor, int inNumDigits)
{
if (inNumDigits > _divisorDigits)
{
long num = _numerator * getMultiplier(inNumDigits - _divisorDigits);
return new FractionalSeconds(num, (byte) inNumDigits);
}
else if (inNumDigits < _divisorDigits)
{
long factor = getMultiplier(_divisorDigits - inNumDigits);
long num = _numerator + factor / 2L * inMultFactor;
return new FractionalSeconds(num / factor, (byte) inNumDigits);
}
return this;
}
private FractionalSeconds divideBy(long divisor) {
return new FractionalSeconds(_numerator / divisor, _divisorDigits);
}
private static String getFractionString(long inNumerator, byte inDivisorDigits)
{
if (inDivisorDigits == 0) {
return "";
}
long factor = getMultiplier(inDivisorDigits);
long remainder = inNumerator % factor;
return String.format("%0" + inDivisorDigits + "d", remainder);
}
/** Return the multiplier given the number of digits */
private static long getMultiplier(int inNumDigits)
{
int numDigits = inNumDigits;
long value = 1L;
while (numDigits > 0) {
numDigits--;
value = value * 10L;
}
return value;
}
public boolean isWithinOneEightyDegrees()
{
final long oneEighty = 180L * 60L * 60L * getMultiplier(_divisorDigits);
return _numerator <= oneEighty;
}
public FractionalSeconds wrapToThreeSixtyDegrees() {
return new FractionalSeconds(_numerator % getThreeSixtyDegrees(), _divisorDigits);
}
private long getThreeSixtyDegrees() {
return 360L * 60L * 60L * getMultiplier(_divisorDigits);
}
public FractionalSeconds invert() {
return new FractionalSeconds(getThreeSixtyDegrees() - _numerator, _divisorDigits);
}
}
|