-
Notifications
You must be signed in to change notification settings - Fork 2
/
degree.h
372 lines (327 loc) · 14.1 KB
/
degree.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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
//. degree.h - 角度と時間の変換
// Copyright (C) 1997,1998,1999,2000 hkuno
// mailto:hkuno.kuno@nifty.ne.jp
#ifndef DEGREE_H_
#define DEGREE_H_
#include <iostream>
#include <cmath>
#include "defs.h"
namespace util {
using namespace std;
//------------------------------------------------------------------------
//.----- 定数 PI (π) ----------------------------------------------------
//------------------------------------------------------------------------
extern const double PI; // π
extern const double DD2RAD; // π/180
extern const double HH2RAD; // π/12
extern const double DS2RAD; // π/180/3600
extern const double HS2RAD; // π/12/3600
extern const double RAD2DD; // 180/π
extern const double RAD2HH; // 12/π
extern const double RAD2DS; // 180*3600/π
extern const double RAD2HS; // 12*3600/π
//------------------------------------------------------------------------
//.----- fmod1, fmod2 : 丸め変換 -----------------------------------------
//------------------------------------------------------------------------
//. fmod1(x, r) - x を r で剰余を得て [0...r) の範囲に丸める
//. fmod2(x, r) - x を r で剰余を得て [-r/2...r/2) の範囲に丸める
// ※rは正の数であること
double fmod1(double x, double r);
double fmod2(double x, double r);
//------------------------------------------------------------------------
//.----- round : 四捨五入 ------------------------------------------------
//------------------------------------------------------------------------
//. round(x) - 小数部を四捨五入して整数を得る
double round(double x);
//. round(x, point) - 小数部point-1桁を四捨五入し、小数部をpoint桁に丸める
double round(double x, int point);
//------------------------------------------------------------------------
//.----- sec2ims, min2im : 分秒変換 --------------------------------------
//------------------------------------------------------------------------
//. sec2ims(sec, sign, i, m, s) - 秒(sec)の値を符号、度分秒(i,m,s)に分ける
//. min2im(min, sign, i, m) - 分(min)の値を符号、度分(i,m)に分ける
// ※符号は0以上を '+' とする
void sec2ims(double sec, char& sign, double& i, double& m, double& s);
void sec2ims(double sec, char& sign, int& i, int& m, double& s);
void min2im (double sec, char& sign, double& i, double& m);
void min2im (double sec, char& sign, int& i, double& m);
//------------------------------------------------------------------------
//.----- dms2xx : 度分秒の変換 -------------------------------------------
//------------------------------------------------------------------------
//. dms2dd(d,m,s) - 度分秒を度の小数にする
//. dms2ds(d,m,s) - 度分秒を度秒にする
//. dms2rad(d,m,s) - 度分秒をラジアンにする
// ※d,m,sは正の値であること
inline double dms2dd(double d, double m=0, double s=0) {
return d + m / 60 + s / 3600;
}
inline double dms2ds(double d, double m=0, double s=0) {
return d * 3600 + m * 60 + s;
}
inline double dms2rad(double d, double m=0, double s=0) {
return dms2ds(d, m, s) * DS2RAD;
}
//------------------------------------------------------------------------
//.----- hms2xx : 時分秒の変換 -------------------------------------------
//------------------------------------------------------------------------
//. hms2hh(h,m,s) - 時分秒を時の小数にする
//. hms2hs(h,m,s) - 時分秒を時秒にする
//. hms2rad(h,m,s) - 時分秒をラジアンにする
// ※h,m,sは正の値であること
inline double hms2hh(double h, double m=0, double s=0) {
return h + m / 60 + s / 3600;
}
inline double hms2hs(double h, double m=0, double s=0) {
return h * 3600 + m * 60 + s;
}
inline double hms2rad(double h, double m=0, double s=0) {
return hms2hs(h, m, s) * HS2RAD;
}
//------------------------------------------------------------------------
//.----- ds2xxx, hs2xxx : 度と時の単位変換、丸め -------------------------
//------------------------------------------------------------------------
//. dd2rad(dd) - 度 を ラジアン にする
//. hh2rad(hh) - 時 を ラジアン にする
//. ds2rad(ds) - 度秒 を ラジアン にする
//. hs2rad(hs) - 時秒 を ラジアン にする
//. rad2dd(dd) - ラジアン を 度 にする
//. rad2hh(hh) - ラジアン を 時 にする
//. rad2ds(ds) - ラジアン を 度秒 にする
//. rad2hs(hs) - ラジアン を 時秒 にする
//. dd2mod1(dd) - 度 を [0...360) の範囲に丸める
//. hh2mod1(dd) - 時 を [0...24) の範囲に丸める
//. ds2mod1(ds) - 度秒 を [0...360*3600) の範囲に丸める
//. hs2mod1(ds) - 時秒 を [0...24*3600) の範囲に丸める
//. rad2mod1(rad) - ラジアン を [0...2π) の範囲に丸める
//. dd2mod2(dd) - 度 を [-180...180) の範囲に丸める
//. ds2mod2(ds) - 度秒 を [-180*3600...180*3600) の範囲に丸める
//. rad2mod2(rad) - ラジアン を [-π...π) の範囲に丸める
inline double dd2rad(double dd) { return dd * DD2RAD; }
inline double hh2rad(double hh) { return hh * HH2RAD; }
inline double ds2rad(double ds) { return ds * DS2RAD; }
inline double hs2rad(double hs) { return hs * HS2RAD; }
inline double rad2dd(double rad) { return rad * RAD2DD; }
inline double rad2hh(double rad) { return rad * RAD2HH; }
inline double rad2ds(double rad) { return rad * RAD2DS; }
inline double rad2hs(double rad) { return rad * RAD2HS; }
inline double dd2mod1(double dd) { return fmod1(dd, 360); }
inline double ds2mod1(double ds) { return fmod1(ds, 360*3600L); }
inline double hh2mod1(double hh) { return fmod1(hh, 24); }
inline double hs2mod1(double hs) { return fmod1(hs, 24*3600L); }
inline double rad2mod1(double rad) { return fmod1(rad, 2*PI); }
inline double dd2mod2(double dd) { return fmod2(dd, 360); }
inline double ds2mod2(double ds) { return fmod2(ds, 360*3600L); }
inline double rad2mod2(double rad) { return fmod2(rad, 2*PI); }
//------------------------------------------------------------------------
//.----- class asXxxx : ダミー型 -----------------------------------------
//------------------------------------------------------------------------
// コンストラクタに渡すダミー型。別の引数で渡す数値型の意味付けをする。
class asRadian {};
class asHh {};
class asHm {};
class asHs {};
class asDs {};
class asDm {};
class asDd {};
//------------------------------------------------------------------------
//.----- class Degree : 角度 ---------------------------------------------
//------------------------------------------------------------------------
class Degree {
double ds; // 角秒[″] 1°の3600倍。
public:
//----- コンストラクタ -------------------------------------------
Degree()
: ds(0) {}
explicit Degree(double ds)
: ds(ds) {}
Degree(double x, asRadian) { setRadian(x); }
Degree(double x, asHh) { setHh(x); }
Degree(double x, asHm) { setHm(x); }
Degree(double x, asHs) { setHs(x); }
Degree(double x, asDd) { setDegree(x); }
Degree(double x, asDm) { setMinute(x); }
Degree(double x, asDs) { setSec(x); }
Degree(double d, double m, double s)
: ds(d * 3600 + m * 60 + s) { }
Degree(const Degree& a)
: ds(a.ds) {}
Degree& operator=(const Degree& a) {
ds = a.ds; return *this;
}
//----- 負数 -----------------------------------------------------
friend Degree operator-(const Degree& a) {
return Degree(-a.ds);
}
//----- 加減算 ---------------------------------------------------
Degree& operator+=(const Degree& a) {
ds += a.ds; return *this;
}
Degree& operator-=(const Degree& a) {
ds -= a.ds; return *this;
}
friend Degree operator+(const Degree& a, const Degree& b) {
return Degree(a.ds + b.ds);
}
friend Degree operator-(const Degree& a, const Degree& b) {
return Degree(a.ds - b.ds);
}
//----- 係数乗除算 -----------------------------------------------
Degree& operator*=(double k) {
ds *= k; return *this;
}
Degree& operator/=(double k) {
ds /= k; return *this;
}
friend Degree operator*(const Degree& a, double k) {
return Degree(a.ds * k);
}
friend Degree operator*(double k, const Degree& a) {
return Degree(a.ds * k);
}
friend Degree operator/(const Degree& a, double k) {
return Degree(a.ds / k);
}
//----- 関係演算 -------------------------------------------------
bool operator==(const Degree& a) const { return ds == a.ds; }
bool operator!=(const Degree& a) const { return ds != a.ds; }
bool operator< (const Degree& a) const { return ds < a.ds; }
bool operator<=(const Degree& a) const { return ds <= a.ds; }
bool operator> (const Degree& a) const { return ds > a.ds; }
bool operator>=(const Degree& a) const { return ds >= a.ds; }
//----- 正負判定 -------------------------------------------------
// 0以上の判定は !isMinus()で可能.
// 0以下の判定は !isPlus()で可能.
bool isZero() const { return ds == 0; }
bool isPlus() const { return ds > 0; } // 0より大
bool isMinus() const { return ds < 0; } // 0より小
//----- 符号反転、逆数 -------------------------------------------
void setNeg() { ds = -ds; }
void setInv() { ds = 1 / ds; }
//----- 角度の丸め -----------------------------------------------
//. mod360 - 360度の範囲で角度を丸め、 [0°...360°) とする
void mod360() { ds = fmod1(ds, 360*3600L); }
//. mod180 - ±180度の範囲で角度を丸め、[-180°...180°) とする
void mod180() { ds = fmod2(ds, 360*3600L); }
//. mod90 - ±180度の範囲で角度を丸め、さらに±90度以上は角度を折り返してtrueを返す
// 緯度に対してtrueが返るときは、経度に180度加える必要がある
bool mod90() {
mod180();
if (ds > 90*3600L) {
ds = 180*3600L - ds; return true;
}
else if (ds < -90*3600L) {
ds = -180*3600L - ds; return true;
}
else
return false;
}
//----- 角度の定数加算 -------------------------------------------
void add180() { ds += 180 * 3600L; }
void sub180() { ds -= 180 * 3600L; }
void add90() { ds += 90 * 3600L; }
void sub90() { ds -= 90 * 3600L; }
//----- 角度取得・設定 -------------------------------------------
//. 角度 [°]
double degree() const { return ds / 3600; }
void setDegree(double d) { ds = d * 3600; }
//. 角度分 [′]
double minute() const { return ds / 60; }
void setMinute(double m) { ds = m * 60; }
//. 角度秒 [″]
double sec() const { return ds; }
void setSec(double s) { ds = s; }
//. 時角時 [h]
double hh() const { return ds / (15*3600L); }
void setHh(double h) { ds = h * (15*3600L); }
//. 時角分 [m]
double hm() const { return ds / (15*60); }
void setHm(double m) { ds = m * (15*60); }
//. 時角秒 [s]
double hs() const { return ds / 15; }
void setHs(double s) { ds = s * 15; }
//. ラジアン
double radian() const { return ds * DS2RAD; }
void setRadian(double rad) { ds = rad * RAD2DS; }
//----- 分秒を分離して設定・取得する -----------------------------
//. 度分秒
void setDms(double d, double m, double s) {
ds = d * 3600 + m * 60 + s;
}
void getDms(char& sign, double& d, double& m, double& s) const {
sec2ims(ds, sign, d, m, s);
}
void getDms(char& sign, int& d, int& m, double& s) const {
sec2ims(ds, sign, d, m, s);
}
void getDms(char& sign, int& d, int& m, double& s, int point) const {
sec2ims(round(ds, point), sign, d, m, s);
}
void getDm(char& sign, double& d, double& m) const {
min2im(minute(), sign, d, m);
}
void getDm(char& sign, int& d, double& m) const {
min2im(minute(), sign, d, m);
}
void getDm(char& sign, int& d, double& m, int point) const {
min2im(round(minute(), point), sign, d, m);
}
//. 時分秒(時角)
void setHms(double h, double m, double s) {
ds = (h * 3600 + m * 60 + s) * 15;
}
void getHms(char& sign, double& h, double& m, double& s) const {
sec2ims(hs(), sign, h, m, s);
}
void getHms(char& sign, int& h, int& m, double& s) const {
sec2ims(hs(), sign, h, m, s);
}
void getHms(char& sign, int& h, int& m, double& s, int point) const {
sec2ims(round(hs(), point), sign, h, m, s);
}
void getHm(char& sign, double& h, double& m) const {
min2im(hm(), sign, h, m);
}
void getHm(char& sign, int& h, double& m) const {
min2im(hm(), sign, h, m);
}
void getHm(char& sign, int& h, double& m, int point) const {
min2im(round(hm(), point), sign, h, m);
}
//----- 文字列化 -------------------------------------------------
ostream& printDegree(ostream& o) const;
ostream& printRadian(ostream& o) const;
ostream& printDms(ostream& o) const;
ostream& printHms(ostream& o) const;
friend ostream& operator<<(ostream& o, const Degree& a) {
return a.printDegree(o);
}
int sprintDms(char* buf, const char* fmt, int point=0) const; // "%c%02dd %02dm %02.0fs"
int sprintDm (char* buf, const char* fmt, int point=1) const; // "%c%02dd %04.1fm"
int sprintHms(char* buf, const char* fmt, int point=0) const; // "%02dh %02dm %02.0fs"
int sprintHm (char* buf, const char* fmt, int point=1) const; // "%02dh %04.1fm"
//----- 文字列解析 -----------------------------------------------
static Degree parseDms(const char* p);
static Degree parseHms(const char* p);
//----- 三角関数 -------------------------------------------------
friend double sin(const Degree& a) { return ::sin(a.radian()); }
friend double cos(const Degree& a) { return ::cos(a.radian()); }
friend double tan(const Degree& a) { return ::tan(a.radian()); }
void setArcSin(double x) { setRadian(asin(x)); }
void setArcCos(double x) { setRadian(acos(x)); }
void setArcTan(double x) { setRadian(atan(x)); }
void setArcTan2(double y, double x) { setRadian(atan2(y, x)); }
};//endclass Degree
// 緯度経度の値を、緯度±90度、経度±180度に正規化する
inline void normLtLg(Degree& lt, Degree& lg) {
if (lt.mod90())
lg.add180();
lg.mod180();
}
// 赤経赤緯の値を、赤緯±90度、赤経0~360度に正規化する
inline void normRaDec(Degree& ra, Degree& dec) {
if (dec.mod90())
ra.add180();
ra.mod360();
}
}//endnamespace util
#endif // DEGREE_H_