Skip to content

Commit 852b316

Browse files
committed
0.1.7 version
1 parent 48dbbdb commit 852b316

File tree

8 files changed

+981
-1
lines changed

8 files changed

+981
-1
lines changed

Angle.cpp

Lines changed: 332 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,332 @@
1+
//
2+
// FILE: Angle.cpp
3+
// AUTHOR: Rob Tillaart
4+
// VERSION: 0.1.7
5+
// PURPOSE: library for Angle math for Arduino
6+
// URL: https://github.com/RobTillaart/Angle
7+
// http://forum.arduino.cc/index.php?topic=339402
8+
//
9+
// Released to the public domain
10+
// 0.1.7 2020-03-26 refactor #pragma once
11+
// 0.1.06 - fixed bug negative values.
12+
// 0.1.05 - added AngleFormat proxy added 03/03/15 by Christoper Andrews.
13+
// 0.1.04 - changed thousands in tenthousands, string constructor
14+
// 0.1.03 - added URL, fromRadians [TEST]
15+
// 0.1.02 - added toRadians() + fix compare()
16+
// 0.1.01 - cleanup a bit
17+
// 0.1.00 - initial version
18+
19+
#include "Angle.h"
20+
21+
AngleFormat::AngleFormat( const Angle &ref, AngleFormatMode format )
22+
: angle(ref), mode(format) {}
23+
24+
size_t AngleFormat::printTo(Print& p) const
25+
{
26+
return angle.printTo( p, mode );
27+
}
28+
29+
Angle::Angle(int dd, int mm, int ss, int tt) // todo optimize
30+
{
31+
neg = false;
32+
d = dd;
33+
m = mm;
34+
s = ss;
35+
t = tt;
36+
// TODO
37+
// normalize();
38+
// assume only one (largest) parameter is negative at most...
39+
if (d < 0) { d = -d; neg = true; }
40+
if (m < 0) { m = -m; neg = true; }
41+
if (s < 0) { s = -s; neg = true; }
42+
if (t < 0) { t = -t; neg = true; }
43+
while (t >= 10000) { s++; t -= 10000; }
44+
while (s >= 60) { m++; s -= 60; }
45+
while (m >= 60) { d++; m -= 60; }
46+
if (d == 0 && m == 0 && s == 0 && t == 0) neg = false;
47+
}
48+
49+
Angle::Angle(const double alpha)
50+
{
51+
double a = alpha;
52+
neg = (alpha < 0);
53+
if (neg) a = -a;
54+
55+
d = int(a);
56+
a = a - d;
57+
// unsigned long p = a * 3600000L;
58+
// 3600 000 = 2^7 • 3^2 • 5^5 = 128 * 28125
59+
// 2^7 = 128 will only affect exponent - no loss precision
60+
// 28125 is less digits so less loss of significant digits.
61+
// upgraded to 4 decimal seconds
62+
// 36 000 000L = 256 * 140625
63+
a = a * 256;
64+
unsigned long p = round(a * 140625.0);
65+
t = p % 10000UL;
66+
p = p / 10000UL;
67+
s = p % 60UL;
68+
m = p / 60UL;
69+
}
70+
71+
Angle::Angle(char * str)
72+
{
73+
uint32_t yy = 0;
74+
uint8_t d_cnt = 0;
75+
neg = false;
76+
// parse whole degrees
77+
char *p = str;
78+
d = 0;
79+
// skip crap
80+
while (!isdigit(*p) && (*p != '-')) p++;
81+
// process sign
82+
if (*p == '-')
83+
{
84+
neg = true;
85+
p++;
86+
}
87+
if (*p == '+') p++;
88+
// parse whole part into degrees;
89+
while (isdigit(*p))
90+
{
91+
d *= 10;
92+
d += (*p - '0');
93+
p++;
94+
}
95+
// parse decimal part into an uint32_t
96+
if (*p != '\0')
97+
{
98+
p++; // skip .
99+
while (isdigit(*p) && d_cnt < 9)
100+
{
101+
d_cnt++;
102+
yy *= 10;
103+
yy += (*p - '0');
104+
p++;
105+
}
106+
}
107+
// make sure we have 9 decimal places.
108+
while (d_cnt < 9)
109+
{
110+
d_cnt++;
111+
yy *= 10;
112+
}
113+
// convert float to degrees. 1000000000 ~> 36000000 -> /250 * 9
114+
// yy = yy * 4 / 125 + yy / 250; // just keeps the math within 32 bits
115+
yy = yy * 4 / 125;
116+
yy = yy + (yy + 4)/ 8; // just keeps the math within 32 bits
117+
// split yy in m, s, tt
118+
t = yy % 10000UL;
119+
yy = yy / 10000UL;
120+
s = yy % 60;
121+
m = yy / 60;
122+
}
123+
124+
// PRINTING
125+
size_t Angle::printTo(Print& p, AngleFormatMode mode) const
126+
{
127+
unsigned char c = mode;
128+
char separator[4] = ".\'\""; // "..."; // ALT-0176 = ° 179.59.59.9999
129+
130+
size_t n = 0;
131+
if (neg) n += p.print('-');
132+
n += p.print(d);
133+
n += p.print(separator[0]);
134+
if( --c )
135+
{
136+
if (m < 10) n += p.print('0');
137+
n += p.print(m);
138+
n += p.print(separator[1]);
139+
if( --c )
140+
{
141+
if (s < 10) n += p.print('0');
142+
n += p.print(s);
143+
n += p.print(separator[2]);
144+
if( --c )
145+
{
146+
if (t < 1000) n += p.print('0');
147+
if (t < 100) n += p.print('0');
148+
if (t < 10) n += p.print('0');
149+
n += p.print(t);
150+
}
151+
}
152+
}
153+
return n;
154+
};
155+
156+
double Angle::toDouble(void)
157+
{
158+
long v = t + s * 10000UL + m * 600000UL;
159+
double val = ((1.0 / 140625.0) / 256) * v + d;
160+
if (neg) val = -val;
161+
return val;
162+
}
163+
164+
// NEGATE
165+
Angle Angle::operator - ()
166+
{
167+
Angle temp = *this;
168+
if (temp.d == 0 && temp.m == 0 && temp.s == 0 && temp.t == 0)
169+
{
170+
temp.neg = false;
171+
}
172+
else
173+
{
174+
temp.neg = !neg;
175+
}
176+
return temp;
177+
};
178+
179+
// BASIC MATH
180+
Angle Angle::operator + (const Angle &a) // TOCHECK
181+
{
182+
return addHelper(a);
183+
}
184+
185+
Angle& Angle::operator += (const Angle &a) // TOCHECK
186+
{
187+
*this = addHelper(a);
188+
return *this;
189+
}
190+
191+
Angle Angle::addHelper(const Angle &a) // TOCHECK
192+
{
193+
Angle temp = *this;
194+
if (temp.neg == a.neg)
195+
{
196+
temp.d += a.d;
197+
temp.m += a.m;
198+
temp.s += a.s;
199+
temp.t += a.t;
200+
}
201+
else
202+
{
203+
temp.d -= a.d;
204+
temp.m -= a.m;
205+
temp.s -= a.s;
206+
temp.t -= a.t;
207+
}
208+
temp.normalize();
209+
210+
return temp;
211+
}
212+
213+
Angle Angle::operator - (const Angle &a) // TOCHECK
214+
{
215+
return subHelper(a);
216+
}
217+
218+
Angle& Angle::operator -= (const Angle &a) // TOCHECK
219+
{
220+
*this = subHelper(a);
221+
return *this;
222+
}
223+
224+
Angle Angle::subHelper(const Angle &a) // TOCHECK
225+
{
226+
Angle temp = *this;
227+
if (temp.neg == a.neg)
228+
{
229+
temp.d -= a.d;
230+
temp.m -= a.m;
231+
temp.s -= a.s;
232+
temp.t -= a.t;
233+
}
234+
else
235+
{
236+
temp.d += a.d;
237+
temp.m += a.m;
238+
temp.s += a.s;
239+
temp.t += a.t;
240+
}
241+
temp.normalize();
242+
return temp;
243+
}
244+
245+
Angle Angle::operator * (const double dd)
246+
{
247+
return Angle(this->toDouble() * dd);
248+
}
249+
250+
Angle Angle::operator / (const double dd)
251+
{
252+
return Angle(this->toDouble() / dd);
253+
}
254+
255+
Angle& Angle::operator *= (const double dd)
256+
{
257+
*this = this->toDouble() * dd;
258+
return *this;
259+
}
260+
261+
Angle& Angle::operator /= (const double dd)
262+
{
263+
*this = this->toDouble() / dd;
264+
return *this;
265+
}
266+
267+
// !! can divide by zero
268+
double Angle::operator / (Angle& a)
269+
{
270+
double f = this->toDouble();
271+
double g = a.toDouble();
272+
return f/g;
273+
}
274+
275+
///////////////////////////////////////////////////////////
276+
//
277+
// PRIVATE
278+
//
279+
int Angle::compare(const Angle &a, const Angle &b)
280+
{
281+
// check sign first
282+
if (!a.neg && b.neg) return 1;
283+
if (a.neg && !b.neg) return -1;
284+
// check abs value
285+
int rv = 0;
286+
if (a.d > b.d) rv = 1;
287+
else if (a.d < b.d) rv = -1;
288+
else if (a.m > b.m) rv = 1;
289+
else if (a.m < b.m) rv = -1;
290+
else if (a.s > b.s) rv = 1;
291+
else if (a.s < b.s) rv = -1;
292+
else if (a.t > b.t) rv = 1;
293+
else if (a.t < b.t) rv = -1;
294+
295+
if (rv != 0 && a.neg) rv = -rv;
296+
return rv;
297+
}
298+
299+
void Angle::normalize() // TOCHECK
300+
{
301+
while (t < 0) { s--; t += 10000; }
302+
while (t >= 10000) { s++; t -= 10000; }
303+
while (s < 0) { m--; s += 60; }
304+
while (s >= 60) { m++; s -= 60; }
305+
while (m < 0) { d--; m += 60; }
306+
while (m >= 60) { d++; m -= 60; }
307+
308+
if (d < 0)
309+
{
310+
if (t != 0)
311+
{
312+
t = 10000 - t;
313+
s++;
314+
}
315+
if (s != 0)
316+
{
317+
s = (60 - s) % 60;
318+
m++;
319+
}
320+
if (m != 0)
321+
{
322+
m = (60 - m) % 60;
323+
d++;
324+
}
325+
d = -d;
326+
neg = !neg;
327+
}
328+
329+
if (d == 0 && m == 0 && s == 0 && t == 0) neg = false;
330+
}
331+
332+
// --- END OF FILE ---

0 commit comments

Comments
 (0)