-
Notifications
You must be signed in to change notification settings - Fork 1
/
CoordsUtils.h
174 lines (139 loc) · 5.01 KB
/
CoordsUtils.h
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
#pragma once
#include <Arduino.h>
#include <array>
#include <exception>
#include <stdexcept>
#include <string>
#include <tuple>
#include <functional>
#include <utility>
#include <vector>
namespace coords {
struct RA {
constexpr RA(double h, double m, double s) : h(h), m(m), s(s) {}
// accepts hh:mm:ss.ss format
RA(std::string ra) {
auto hoursEnd = ra.find(':');
if (hoursEnd == std::string::npos) {
throw std::invalid_argument("Invalid RA format. Must be hh:mm:ss.ss");
}
h = atof(ra.substr(0, hoursEnd).c_str());
hoursEnd++;
auto minutesEnd = ra.find(':', hoursEnd);
if (minutesEnd == std::string::npos) {
throw std::invalid_argument("Invalid RA format. Must be hh:mm:ss.ss");
}
m = atof(ra.substr(hoursEnd, minutesEnd - hoursEnd).c_str());
minutesEnd++;
s = atof(ra.substr(minutesEnd, ra.length() - minutesEnd).c_str());
}
double h, m, s;
constexpr double deg() const {
return h * 15 + (m * 15) / 60 + (s * 15) / 3600;
}
constexpr double rad() const {
return deg() * DEG_TO_RAD;
}
std::string str() const {
char buf[32];
snprintf(buf, sizeof(buf), "%dh%dm%.2fs", static_cast<int>(h), static_cast<int>(m), s);
return std::string(buf);
}
};
struct Dec {
constexpr Dec(double d, double m, double s) : d(d), m(m), s(s) {}
// accepts ddd,mm,ss.ss format
Dec(std::string dec) {
auto degEnd = dec.find(',');
if (degEnd == std::string::npos) {
throw std::invalid_argument("Invalid Dec format. Must be ddd,mm,ss.ss");
}
d = atof(dec.substr(0, degEnd).c_str());
degEnd++;
auto minutesEnd = dec.find(',', degEnd);
if (minutesEnd == std::string::npos) {
throw std::invalid_argument("Invalid Dec format. Must be ddd,mm,ss.ss");
}
m = atof(dec.substr(degEnd, minutesEnd - degEnd).c_str());
minutesEnd++;
s = atof(dec.substr(minutesEnd, dec.length() - minutesEnd).c_str());
}
double d, m ,s;
constexpr double deg() const {
return d + m / 60 + s / 3600;
}
constexpr double rad() const {
return deg() * DEG_TO_RAD;
}
std::string str() const {
char buf[32];
snprintf(buf, sizeof(buf), "%d^%d\'%.2f\"", static_cast<int>(d), static_cast<int>(m), s);
return std::string(buf);
}
};
RA degToRA(double deg) {
static constexpr const auto hoursFactor = 15.0;
static constexpr const auto minutesFactor = 15.0/60;
static constexpr const auto secondsFactor = 15.0/3600;
auto hours = std::floor(deg / hoursFactor);
deg = std::fmod(deg, hoursFactor);
auto minutes = std::floor(deg / minutesFactor);
deg = std::fmod(deg, minutesFactor);
auto seconds = deg / secondsFactor;
return RA{hours, minutes, seconds};
}
Dec degToDec(double deg) {
static constexpr const auto degreesFactor = 1.0;
static constexpr const auto minutesFactor = 1.0/60;
static constexpr const auto secondsFactor = 1.0/3600;
auto degrees = std::floor(deg / degreesFactor);
deg = std::fmod(deg, degreesFactor);
auto minutes = std::floor(deg / minutesFactor);
deg = std::fmod(deg, minutesFactor);
auto seconds = deg / secondsFactor;
return Dec{degrees, minutes, seconds};
}
struct CelestialObjectBase {
constexpr CelestialObjectBase(const char* name, RA ra, Dec dec) : name_(name), ra_(std::move(ra)), dec_(std::move(dec)) {}
const char* name_;
RA ra_;
Dec dec_;
};
template<typename CelestialObjectType>
struct CelestialObject : public CelestialObjectBase {
constexpr CelestialObject(CelestialObjectType key, const char* name, RA ra, Dec dec)
: key_(key), CelestialObjectBase(name, std::move(ra), std::move(dec)) {}
CelestialObjectType key_;
};
// radians per second
constexpr const double EARTH_ANG_SPEED = 7.292115 * pow(10,-5);
std::pair<double, double> rotatePoint(std::pair<double, double> point, double angle, std::pair<double, double> pivot = {0, 0}) {
// TODO can be optimized: do not compute twice sin, cos, and others
return {
(point.first - pivot.first)*cos(angle) - (point.second - pivot.second)*sin(angle) + pivot.first,
(point.first - pivot.first)*sin(angle) + (point.second - pivot.second)*cos(angle) + pivot.second
};
}
std::pair<double, double> translatePoint(std::pair<double, double> point, std::pair<double, double> delta) {
return {
point.first + delta.first,
point.second + delta.second
};
}
std::pair<double,double> lineFrom2Points(std::pair<double, double> point1, std::pair<double, double> point2) {
// TODO can be optimized: do not compute twice some expressions
return {
(point1.second - point2.second)/(point1.first - point2.first),
point1.second - (point1.second - point2.second)/(point1.first - point2.first)*point1.first
};
}
double angleFrom2Lines(double a1, double a2) {
return atan((a2 - a1)/(1 + a1*a2));
}
std::pair<double, double> deltaXdeltaYFrom2Points(std::pair<double, double> point1, std::pair<double, double> point2, double angle = 0) {
return {
point2.first - point1.first*cos(angle) + point1.second*sin(angle),
point2.second - point1.first*sin(angle) - point1.second*cos(angle)
};
}
}