2015-08-01 14:36:28 -04:00
|
|
|
//
|
|
|
|
// FILE: Angle.cpp
|
|
|
|
// AUTHOR: Rob Tillaart
|
2015-08-02 07:38:56 -04:00
|
|
|
// VERSION: 0.1.02
|
2015-08-01 14:36:28 -04:00
|
|
|
// PURPOSE: library for Angle math for Arduino
|
2015-08-01 14:44:45 -04:00
|
|
|
// URL:
|
2015-08-01 14:36:28 -04:00
|
|
|
//
|
|
|
|
// Released to the public domain
|
|
|
|
//
|
|
|
|
|
2015-08-02 07:38:56 -04:00
|
|
|
// 0.1.02 - added toRadians() + fix compare()
|
2015-08-01 14:44:45 -04:00
|
|
|
// 0.1.01 - cleanup a bit
|
2015-08-01 14:36:28 -04:00
|
|
|
// 0.1.00 - initial version
|
|
|
|
|
2015-08-02 07:38:56 -04:00
|
|
|
// ideas: - http://forum.arduino.cc/index.php?topic=94507.0
|
|
|
|
// wind directions
|
|
|
|
// bandit at 12 hr
|
|
|
|
// more precise sin(a + b) ?
|
|
|
|
// a = degrees, b = minutes+sec+thou?
|
|
|
|
//
|
|
|
|
|
2015-08-01 14:36:28 -04:00
|
|
|
#include "Angle.h"
|
|
|
|
|
|
|
|
Angle::Angle(const double alpha)
|
|
|
|
{
|
|
|
|
double a = alpha;
|
|
|
|
bool neg = (alpha < 0);
|
|
|
|
if (neg) a = -a;
|
2015-08-01 14:44:45 -04:00
|
|
|
|
2015-08-01 14:36:28 -04:00
|
|
|
d = int(a);
|
|
|
|
a = a - d;
|
2015-08-01 14:44:45 -04:00
|
|
|
// unsigned long p = a * 3600000L;
|
|
|
|
// 3600 000 = 2^7 • 3^2 • 5^5 = 128 * 28125
|
|
|
|
// 2^7 = 128 will only affect exponent - no loss precision
|
|
|
|
// 28125 is less digits so less loss of significant digits.
|
|
|
|
a = a * 128;
|
|
|
|
unsigned long p = round(a * 28125);
|
|
|
|
|
2015-08-01 14:36:28 -04:00
|
|
|
t = p % 1000UL;
|
|
|
|
p = (p - t)/1000UL;
|
|
|
|
s = p % 60UL;
|
|
|
|
m = (p - s)/60UL;
|
2015-08-01 14:44:45 -04:00
|
|
|
|
2015-08-01 14:36:28 -04:00
|
|
|
if (neg) d = -d;
|
|
|
|
}
|
|
|
|
|
|
|
|
// PRINTING
|
|
|
|
size_t Angle::printTo(Print& p) const
|
|
|
|
{
|
|
|
|
size_t n = 0;
|
|
|
|
n += p.print(d);
|
2015-08-02 07:38:56 -04:00
|
|
|
n += p.print('.');
|
2015-08-01 14:44:45 -04:00
|
|
|
if (m < 10) n += p.print('0');
|
|
|
|
n += p.print(m);
|
2015-08-01 14:36:28 -04:00
|
|
|
n += p.print('\'');
|
2015-08-01 14:44:45 -04:00
|
|
|
if (s < 10) n += p.print('0');
|
|
|
|
n += p.print(s);
|
2015-08-01 14:36:28 -04:00
|
|
|
n += p.print('\"');
|
2015-08-01 14:44:45 -04:00
|
|
|
if (t < 100) n += p.print('0');
|
|
|
|
if (t < 10) n += p.print('0');
|
2015-08-01 14:36:28 -04:00
|
|
|
n += p.print(t);
|
2015-08-01 14:44:45 -04:00
|
|
|
|
2015-08-01 14:36:28 -04:00
|
|
|
return n;
|
|
|
|
};
|
|
|
|
|
|
|
|
double Angle::toDouble(void)
|
|
|
|
{
|
2015-08-01 14:44:45 -04:00
|
|
|
long v = t + s * 1000UL + m * 60000UL;
|
2015-08-01 14:36:28 -04:00
|
|
|
double val = ((1.0 / 28125.0) / 128) * v + d;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
// BASIC MATH
|
2015-08-01 14:44:45 -04:00
|
|
|
Angle Angle::operator + (const Angle &a)
|
2015-08-01 14:36:28 -04:00
|
|
|
{
|
2015-08-01 14:44:45 -04:00
|
|
|
return addHelper(a);
|
2015-08-01 14:36:28 -04:00
|
|
|
}
|
|
|
|
|
2015-08-01 14:44:45 -04:00
|
|
|
Angle& Angle::operator += (const Angle &a)
|
2015-08-01 14:36:28 -04:00
|
|
|
{
|
2015-08-01 14:44:45 -04:00
|
|
|
*this = addHelper(a);
|
|
|
|
return *this;
|
2015-08-01 14:36:28 -04:00
|
|
|
}
|
|
|
|
|
2015-08-01 14:44:45 -04:00
|
|
|
Angle Angle::addHelper(const Angle &a)
|
2015-08-01 14:36:28 -04:00
|
|
|
{
|
|
|
|
Angle temp = *this;
|
|
|
|
if (sign(temp.d) == sign(a.d))
|
|
|
|
{
|
|
|
|
temp.d += a.d;
|
|
|
|
temp.m += a.m;
|
|
|
|
temp.s += a.s;
|
|
|
|
temp.t += a.t;
|
|
|
|
}
|
2015-08-01 14:44:45 -04:00
|
|
|
else
|
2015-08-01 14:36:28 -04:00
|
|
|
{
|
2015-08-02 07:38:56 -04:00
|
|
|
temp.d = sign(temp.d) * (abs(temp.d) - abs(a.d));
|
2015-08-01 14:36:28 -04:00
|
|
|
temp.m -= a.m;
|
|
|
|
temp.s -= a.s;
|
|
|
|
temp.t -= a.t;
|
|
|
|
}
|
|
|
|
temp.normalize();
|
2015-08-01 14:44:45 -04:00
|
|
|
return temp;
|
2015-08-01 14:36:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Angle Angle::operator - (const Angle &a)
|
|
|
|
{
|
2015-08-02 07:38:56 -04:00
|
|
|
return subHelper(a);
|
2015-08-01 14:36:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Angle& Angle::operator -= (const Angle &a)
|
2015-08-02 07:38:56 -04:00
|
|
|
{
|
|
|
|
*this = subHelper(a);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Angle Angle::subHelper(const Angle &a)
|
2015-08-01 14:36:28 -04:00
|
|
|
{
|
|
|
|
Angle temp = *this;
|
|
|
|
if (sign(temp.d) == sign(a.d))
|
|
|
|
{
|
|
|
|
temp.d -= a.d;
|
|
|
|
temp.m -= a.m;
|
|
|
|
temp.s -= a.s;
|
|
|
|
temp.t -= a.t;
|
|
|
|
}
|
2015-08-01 14:44:45 -04:00
|
|
|
else
|
2015-08-01 14:36:28 -04:00
|
|
|
{
|
|
|
|
temp.d = sign(temp.d) * (abs(temp.d) + abs(a.d));
|
|
|
|
temp.m += a.m;
|
|
|
|
temp.s += a.s;
|
|
|
|
temp.t += a.t;
|
|
|
|
}
|
|
|
|
temp.normalize();
|
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
Angle Angle::operator * (const double dd)
|
|
|
|
{
|
|
|
|
return Angle(this->toDouble() * dd);
|
|
|
|
}
|
|
|
|
|
|
|
|
Angle Angle::operator / (const double dd)
|
|
|
|
{
|
|
|
|
return Angle(this->toDouble() / dd);
|
|
|
|
}
|
|
|
|
|
|
|
|
Angle& Angle::operator *= (const double dd)
|
|
|
|
{
|
2015-08-02 07:38:56 -04:00
|
|
|
*this = this->toDouble() * dd;
|
2015-08-01 14:36:28 -04:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Angle& Angle::operator /= (const double dd)
|
|
|
|
{
|
2015-08-02 07:38:56 -04:00
|
|
|
*this = this->toDouble() / dd;
|
2015-08-01 14:36:28 -04:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
double Angle::operator / (Angle& a)
|
|
|
|
{
|
|
|
|
double f = this->toDouble();
|
|
|
|
double g = a.toDouble();
|
|
|
|
return f/g;
|
|
|
|
}
|
2015-08-02 07:38:56 -04:00
|
|
|
|
2015-08-01 14:36:28 -04:00
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// PRIVATE
|
|
|
|
//
|
|
|
|
int Angle::compare(const Angle &a, const Angle &b)
|
|
|
|
{
|
|
|
|
if (a.d > b.d) return 1;
|
|
|
|
if (a.d < b.d) return -1;
|
|
|
|
if (a.m > b.m) return 1;
|
|
|
|
if (a.m < b.m) return -1;
|
|
|
|
if (a.s > b.s) return 1;
|
|
|
|
if (a.s < b.s) return -1;
|
|
|
|
if (a.t > b.t) return 1;
|
2015-08-02 07:38:56 -04:00
|
|
|
if (a.t < b.t) return -1;
|
2015-08-01 14:36:28 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Angle::normalize()
|
|
|
|
{
|
|
|
|
bool neg = (d < 0);
|
|
|
|
if (neg) d = -d;
|
|
|
|
while (t < 0) { s--; t += 1000; }
|
|
|
|
while (t >= 1000) { s++; t -= 1000; }
|
|
|
|
while (s < 0) { m--; s += 60; }
|
|
|
|
while (s >= 60) { m++; s -= 60; }
|
|
|
|
while (m < 0) { d--; m += 60; }
|
|
|
|
while (m >= 60) { d++; m -= 60; }
|
|
|
|
if (neg) d = -d;
|
|
|
|
}
|
|
|
|
|
2015-08-01 14:44:45 -04:00
|
|
|
int Angle::sign(int d)
|
2015-08-01 14:36:28 -04:00
|
|
|
{
|
|
|
|
return (d < 0?-1:1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// --- END OF FILE ---
|