-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcoord.go
1272 lines (992 loc) · 37.6 KB
/
coord.go
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
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright 2022 HE Boliang
// All rights reserved.
package gofa
// Coord
// Galactic Coordinates
/*
Icrs2g Transformation from ICRS to Galactic Coordinates.
Given:
dr float64 ICRS right ascension (radians)
dd float64 ICRS declination (radians)
Returned:
dl float64 galactic longitude (radians)
db float64 galactic latitude (radians)
Notes:
1) The IAU 1958 system of Galactic coordinates was defined with
respect to the now obsolete reference system FK4 B1950.0. When
interpreting the system in a modern context, several factors have
to be taken into account:
. The inclusion in FK4 positions of the E-terms of aberration.
. The distortion of the FK4 proper motion system by differential
Galactic rotation.
. The use of the B1950.0 equinox rather than the now-standard
J2000.0.
. The frame bias between ICRS and the J2000.0 mean place system.
The Hipparcos Catalogue (Perryman & ESA 1997) provides a rotation
matrix that transforms directly between ICRS and Galactic
coordinates with the above factors taken into account. The
matrix is derived from three angles, namely the ICRS coordinates
of the Galactic pole and the longitude of the ascending node of
the galactic equator on the ICRS equator. They are given in
degrees to five decimal places and for canonical purposes are
regarded as exact. In the Hipparcos Catalogue the matrix
elements are given to 10 decimal places (about 20 microarcsec).
In the present SOFA function the matrix elements have been
recomputed from the canonical three angles and are given to 30
decimal places.
2) The inverse transformation is performed by the function G2icrs.
Called:
Anp normalize angle into range 0 to 2pi
Anpm normalize angle into range +/- pi
S2c spherical coordinates to unit vector
Rxp product of r-matrix and p-vector
C2s p-vector to spherical
Reference:
Perryman M.A.C. & ESA, 1997, ESA SP-1200, The Hipparcos and Tycho
catalogues. Astrometric and photometric star catalogues
derived from the ESA Hipparcos Space Astrometry Mission. ESA
Publications Division, Noordwijk, Netherlands.
*/
func Icrs2g(dr, dd float64, dl, db *float64) {
var v1, v2 [3]float64
/*
L2,B2 system of galactic coordinates in the form presented in the
Hipparcos Catalogue. In degrees:
P = 192.85948 right ascension of the Galactic north pole in ICRS
Q = 27.12825 declination of the Galactic north pole in ICRS
R = 32.93192 Galactic longitude of the ascending node of
the Galactic equator on the ICRS equator
ICRS to galactic rotation matrix, obtained by computing
R_3(-R) R_1(pi/2-Q) R_3(pi/2+P) to the full precision shown:
*/
r := [3][3]float64{
{-0.054875560416215368492398900454, -0.873437090234885048760383168409, -0.483835015548713226831774175116},
{+0.494109427875583673525222371358, -0.444829629960011178146614061616, +0.746982244497218890527388004556},
{-0.867666149019004701181616534570, -0.198076373431201528180486091412, +0.455983776175066922272100478348},
}
/* Spherical to Cartesian. */
S2c(dr, dd, &v1)
/* ICRS to Galactic. */
Rxp(r, v1, &v2)
/* Cartesian to spherical. */
C2s(v2, dl, db)
/* Express in conventional ranges. */
*dl = Anp(*dl)
*db = Anpm(*db)
}
/*
G2icrsTransformation from Galactic Coordinates to ICRS.
Given:
dl float64 galactic longitude (radians)
db float64 galactic latitude (radians)
Returned:
dr float64 ICRS right ascension (radians)
dd float64 ICRS declination (radians)
Notes:
1) The IAU 1958 system of Galactic coordinates was defined with
respect to the now obsolete reference system FK4 B1950.0. When
interpreting the system in a modern context, several factors have
to be taken into account:
. The inclusion in FK4 positions of the E-terms of aberration.
. The distortion of the FK4 proper motion system by differential
Galactic rotation.
. The use of the B1950.0 equinox rather than the now-standard
J2000.0.
. The frame bias between ICRS and the J2000.0 mean place system.
The Hipparcos Catalogue (Perryman & ESA 1997) provides a rotation
matrix that transforms directly between ICRS and Galactic
coordinates with the above factors taken into account. The
matrix is derived from three angles, namely the ICRS coordinates
of the Galactic pole and the longitude of the ascending node of
the galactic equator on the ICRS equator. They are given in
degrees to five decimal places and for canonical purposes are
regarded as exact. In the Hipparcos Catalogue the matrix
elements are given to 10 decimal places (about 20 microarcsec).
In the present SOFA function the matrix elements have been
recomputed from the canonical three angles and are given to 30
decimal places.
2) The inverse transformation is performed by the function Icrs2g.
Called:
Anp normalize angle into range 0 to 2pi
Anpm normalize angle into range +/- pi
S2c spherical coordinates to unit vector
Trxp product of transpose of r-matrix and p-vector
C2s p-vector to spherical
Reference:
Perryman M.A.C. & ESA, 1997, ESA SP-1200, The Hipparcos and Tycho
catalogues. Astrometric and photometric star catalogues
derived from the ESA Hipparcos Space Astrometry Mission. ESA
Publications Division, Noordwijk, Netherlands.
*/
func G2icrs(dl, db float64, dr, dd *float64) {
var v1, v2 [3]float64
/*
L2,B2 system of galactic coordinates in the form presented in the
Hipparcos Catalogue. In degrees:
P = 192.85948 right ascension of the Galactic north pole in ICRS
Q = 27.12825 declination of the Galactic north pole in ICRS
R = 32.93192 Galactic longitude of the ascending node of
the Galactic equator on the ICRS equator
ICRS to galactic rotation matrix, obtained by computing
R_3(-R) R_1(pi/2-Q) R_3(pi/2+P) to the full precision shown:
*/
r := [3][3]float64{
{-0.054875560416215368492398900454, -0.873437090234885048760383168409, -0.483835015548713226831774175116},
{+0.494109427875583673525222371358, -0.444829629960011178146614061616, +0.746982244497218890527388004556},
{-0.867666149019004701181616534570, -0.198076373431201528180486091412, +0.455983776175066922272100478348},
}
/* Spherical to Cartesian. */
S2c(dl, db, &v1)
/* Galactic to ICRS. */
Trxp(r, v1, &v2)
/* Cartesian to spherical. */
C2s(v2, dr, dd)
/* Express in conventional ranges. */
*dr = Anp(*dr)
*dd = Anpm(*dd)
}
/*
Ae2hd Horizon to equatorial coordinates, transform azimuth and altitude to hour angle and declination.
Given:
az float64 azimuth
el float64 altitude (informally, elevation)
phi float64 site latitude
Returned:
ha float64 hour angle (local)
dec float64 declination
Notes:
1) All the arguments are angles in radians.
2) The sign convention for azimuth is north zero, east +pi/2.
3) HA is returned in the range +/-pi. Declination is returned in
the range +/-pi/2.
4) The latitude phi is pi/2 minus the angle between the Earth's
rotation axis and the adopted zenith. In many applications it
will be sufficient to use the published geodetic latitude of the
site. In very precise (sub-arcsecond) applications, phi can be
corrected for polar motion.
5) The azimuth az must be with respect to the rotational north pole,
as opposed to the ITRS pole, and an azimuth with respect to north
on a map of the Earth's surface will need to be adjusted for
polar motion if sub-arcsecond accuracy is required.
6) Should the user wish to work with respect to the astronomical
zenith rather than the geodetic zenith, phi will need to be
adjusted for deflection of the vertical (often tens of
arcseconds), and the zero point of ha will also be affected.
7) The transformation is the same as Ve = Ry(phi-pi/2)*Rz(pi)*Vh,
where Ve and Vh are lefthanded unit vectors in the (ha,dec) and
(az,el) systems respectively and Rz and Ry are rotations about
first the z-axis and then the y-axis. (n.b. Rz(pi) simply
reverses the signs of the x and y components.) For efficiency,
the algorithm is written out rather than calling other utility
functions. For applications that require even greater
efficiency, additional savings are possible if constant terms
such as functions of latitude are computed once and for all.
8) Again for efficiency, no range checking of arguments is carried
out.
*/
func Ae2hd(az, el, phi float64, ha, dec *float64) {
var sa, ca, se, ce, sp, cp, x, y, z, r float64
/* Useful trig functions. */
sa = sin(az)
ca = cos(az)
se = sin(el)
ce = cos(el)
sp = sin(phi)
cp = cos(phi)
/* HA,Dec unit vector. */
x = -ca*ce*sp + se*cp
y = -sa * ce
z = ca*ce*cp + se*sp
/* To spherical. */
r = sqrt(x*x + y*y)
if r != 0.0 {
*ha = atan2(y, x)
} else {
*ha = 0.0
}
*dec = atan2(z, r)
}
/*
Hd2ae Equatorial to horizon coordinates: transform hour angle and declination to azimuth and altitude.
Given:
ha float64 hour angle (local)
dec float64 declination
phi float64 site latitude
Returned:
az float64 azimuth
el float64 altitude (informally, elevation)
Notes:
1) All the arguments are angles in radians.
2) Azimuth is returned in the range 0-2pi; north is zero, and east
is +pi/2. Altitude is returned in the range +/- pi/2.
3) The latitude phi is pi/2 minus the angle between the Earth's
rotation axis and the adopted zenith. In many applications it
will be sufficient to use the published geodetic latitude of the
site. In very precise (sub-arcsecond) applications, phi can be
corrected for polar motion.
4) The returned azimuth az is with respect to the rotational north
pole, as opposed to the ITRS pole, and for sub-arcsecond
accuracy will need to be adjusted for polar motion if it is to
be with respect to north on a map of the Earth's surface.
5) Should the user wish to work with respect to the astronomical
zenith rather than the geodetic zenith, phi will need to be
adjusted for deflection of the vertical (often tens of
arcseconds), and the zero point of the hour angle ha will also
be affected.
6) The transformation is the same as Vh = Rz(pi)*Ry(pi/2-phi)*Ve,
where Vh and Ve are lefthanded unit vectors in the (az,el) and
(ha,dec) systems respectively and Ry and Rz are rotations about
first the y-axis and then the z-axis. (n.b. Rz(pi) simply
reverses the signs of the x and y components.) For efficiency,
the algorithm is written out rather than calling other utility
functions. For applications that require even greater
efficiency, additional savings are possible if constant terms
such as functions of latitude are computed once and for all.
7) Again for efficiency, no range checking of arguments is carried
out.
*/
func Hd2ae(ha, dec, phi float64, az, el *float64) {
var sh, ch, sd, cd, sp, cp, x, y, z, r, a float64
/* Useful trig functions. */
sh = sin(ha)
ch = cos(ha)
sd = sin(dec)
cd = cos(dec)
sp = sin(phi)
cp = cos(phi)
/* Az,Alt unit vector. */
x = -ch*cd*sp + sd*cp
y = -sh * cd
z = ch*cd*cp + sd*sp
/* To spherical. */
r = sqrt(x*x + y*y)
if r != 0.0 {
a = atan2(y, x)
} else {
a = 0.0
}
if a < 0.0 {
*az = a + D2PI
} else {
*az = a
}
*el = atan2(z, r)
}
/*
Hd2pa Parallactic angle for a given hour angle and declination.
Given:
ha float64 hour angle
dec float64 declination
phi float64 site latitude
Returned (function value):
float64 parallactic angle
Notes:
1) All the arguments are angles in radians.
2) The parallactic angle at a point in the sky is the position
angle of the vertical, i.e. the angle between the directions to
the north celestial pole and to the zenith respectively.
3) The result is returned in the range -pi to +pi.
4) At the pole itself a zero result is returned.
5) The latitude phi is pi/2 minus the angle between the Earth's
rotation axis and the adopted zenith. In many applications it
will be sufficient to use the published geodetic latitude of the
site. In very precise (sub-arcsecond) applications, phi can be
corrected for polar motion.
6) Should the user wish to work with respect to the astronomical
zenith rather than the geodetic zenith, phi will need to be
adjusted for deflection of the vertical (often tens of
arcseconds), and the zero point of the hour angle ha will also
be affected.
Reference:
Smart, W.M., "Spherical Astronomy", Cambridge University Press,
6th edition (Green, 1977), p49.
*/
func Hd2pa(ha, dec, phi float64) float64 {
var cp, cqsz, sqsz float64
cp = cos(phi)
sqsz = cp * sin(ha)
cqsz = sin(phi)*cos(dec) - cp*sin(dec)*cos(ha)
if sqsz != 0.0 || cqsz != 0.0 {
return atan2(sqsz, cqsz)
}
return 0.0
}
/*
Ecm06 ICRS equatorial to ecliptic rotation matrix, IAU 2006.
Given:
date1,date2 float64 TT as a 2-part Julian date (Note 1)
Returned:
rm [3][3]float64 ICRS to ecliptic rotation matrix
Notes:
1) The TT date date1+date2 is a Julian Date, apportioned in any
convenient way between the two arguments. For example,
JD(TT)=2450123.7 could be expressed in any of these ways,
among others:
date1 date2
2450123.7 0.0 (JD method)
2451545.0 -1421.3 (J2000 method)
2400000.5 50123.2 (MJD method)
2450123.5 0.2 (date & time method)
The JD method is the most natural and convenient to use in
cases where the loss of several decimal digits of resolution
is acceptable. The J2000 method is best matched to the way
the argument is handled internally and will deliver the
optimum resolution. The MJD method and the date & time methods
are both good compromises between resolution and convenience.
2) The matrix is in the sense
E_ep = rm x P_ICRS,
where P_ICRS is a vector with respect to ICRS right ascension
and declination axes and E_ep is the same vector with respect to
the (inertial) ecliptic and equinox of date.
3) P_ICRS is a free vector, merely a direction, typically of unit
magnitude, and not bound to any particular spatial origin, such
as the Earth, Sun or SSB. No assumptions are made about whether
it represents starlight and embodies astrometric effects such as
parallax or aberration. The transformation is approximately that
between mean J2000.0 right ascension and declination and ecliptic
longitude and latitude, with only frame bias (always less than
25 mas) to disturb this classical picture.
Called:
Obl06 mean obliquity, IAU 2006
Pmat06 PB matrix, IAU 2006
Ir initialize r-matrix to identity
Rx rotate around X-axis
Rxr product of two r-matrices
*/
func Ecm06(date1, date2 float64, rm *[3][3]float64) {
var ob float64
var bp, e [3][3]float64
/* Obliquity, IAU 2006. */
ob = Obl06(date1, date2)
/* Precession-bias matrix, IAU 2006. */
Pmat06(date1, date2, &bp)
/* Equatorial of date to ecliptic matrix. */
Ir(&e)
Rx(ob, &e)
/* ICRS to ecliptic coordinates rotation matrix, IAU 2006. */
Rxr(e, bp, rm)
}
/*
Eqec06 Transformation from ICRS equatorial coordinates to ecliptic coordinates
(mean equinox and ecliptic of date) using IAU 2006 precession model.
Given:
date1,date2 float64 TT as a 2-part Julian date (Note 1)
dr,dd float64 ICRS right ascension and declination (radians)
Returned:
dl,db float64 ecliptic longitude and latitude (radians)
Notes:
1) The TT date date1+date2 is a Julian Date, apportioned in any
convenient way between the two arguments. For example,
JD(TT)=2450123.7 could be expressed in any of these ways,
among others:
date1 date2
2450123.7 0.0 (JD method)
2451545.0 -1421.3 (J2000 method)
2400000.5 50123.2 (MJD method)
2450123.5 0.2 (date & time method)
The JD method is the most natural and convenient to use in
cases where the loss of several decimal digits of resolution
is acceptable. The J2000 method is best matched to the way
the argument is handled internally and will deliver the
optimum resolution. The MJD method and the date & time methods
are both good compromises between resolution and convenience.
2) No assumptions are made about whether the coordinates represent
starlight and embody astrometric effects such as parallax or
aberration.
3) The transformation is approximately that from mean J2000.0 right
ascension and declination to ecliptic longitude and latitude
(mean equinox and ecliptic of date), with only frame bias (always
less than 25 mas) to disturb this classical picture.
Called:
S2c spherical coordinates to unit vector
Ecm06 J2000.0 to ecliptic rotation matrix, IAU 2006
Rxp product of r-matrix and p-vector
C2s unit vector to spherical coordinates
Anp normalize angle into range 0 to 2pi
Anpm normalize angle into range +/- pi
*/
func Eqec06(date1, date2 float64, dr, dd float64, dl, db *float64) {
var rm [3][3]float64
var v1, v2 [3]float64
var a, b float64
/* Spherical to Cartesian. */
S2c(dr, dd, &v1)
/* Rotation matrix, ICRS equatorial to ecliptic. */
Ecm06(date1, date2, &rm)
/* The transformation from ICRS to ecliptic. */
Rxp(rm, v1, &v2)
/* Cartesian to spherical. */
C2s(v2, &a, &b)
/* Express in conventional ranges. */
*dl = Anp(a)
*db = Anpm(b)
}
/*
Eceq06 Transformation from ecliptic coordinates (mean equinox and ecliptic
of date) to ICRS RA,Dec, using the IAU 2006 precession model.
Given:
date1,date2 float64 TT as a 2-part Julian date (Note 1)
dl,db float64 ecliptic longitude and latitude (radians)
Returned:
dr,dd float64 ICRS right ascension and declination (radians)
Notes:
1) The TT date date1+date2 is a Julian Date, apportioned in any
convenient way between the two arguments. For example,
JD(TT)=2450123.7 could be expressed in any of these ways,
among others:
date1 date2
2450123.7 0.0 (JD method)
2451545.0 -1421.3 (J2000 method)
2400000.5 50123.2 (MJD method)
2450123.5 0.2 (date & time method)
The JD method is the most natural and convenient to use in
cases where the loss of several decimal digits of resolution
is acceptable. The J2000 method is best matched to the way
the argument is handled internally and will deliver the
optimum resolution. The MJD method and the date & time methods
are both good compromises between resolution and convenience.
2) No assumptions are made about whether the coordinates represent
starlight and embody astrometric effects such as parallax or
aberration.
3) The transformation is approximately that from ecliptic longitude
and latitude (mean equinox and ecliptic of date) to mean J2000.0
right ascension and declination, with only frame bias (always
less than 25 mas) to disturb this classical picture.
Called:
S2c spherical coordinates to unit vector
Ecm06 J2000.0 to ecliptic rotation matrix, IAU 2006
Trxp product of transpose of r-matrix and p-vector
C2s unit vector to spherical coordinates
Anp normalize angle into range 0 to 2pi
Anpm normalize angle into range +/- pi
*/
func Eceq06(date1, date2 float64, dl, db float64, dr, dd *float64) {
var rm [3][3]float64
var v1, v2 [3]float64
var a, b float64
/* Spherical to Cartesian. */
S2c(dl, db, &v1)
/* Rotation matrix, ICRS equatorial to ecliptic. */
Ecm06(date1, date2, &rm)
/* The transformation from ecliptic to ICRS. */
Trxp(rm, v1, &v2)
/* Cartesian to spherical. */
C2s(v2, &a, &b)
/* Express in conventional ranges. */
*dr = Anp(a)
*dd = Anpm(b)
}
/*
Ltecm ICRS equatorial to ecliptic rotation matrix, long-term.
Given:
epj float64 Julian epoch (TT)
Returned:
rm [3][3]float64 ICRS to ecliptic rotation matrix
Notes:
1) The matrix is in the sense
E_ep = rm x P_ICRS,
where P_ICRS is a vector with respect to ICRS right ascension
and declination axes and E_ep is the same vector with respect to
the (inertial) ecliptic and equinox of epoch epj.
2) P_ICRS is a free vector, merely a direction, typically of unit
magnitude, and not bound to any particular spatial origin, such
as the Earth, Sun or SSB. No assumptions are made about whether
it represents starlight and embodies astrometric effects such as
parallax or aberration. The transformation is approximately that
between mean J2000.0 right ascension and declination and ecliptic
longitude and latitude, with only frame bias (always less than
25 mas) to disturb this classical picture.
3) The Vondrak et al. (2011, 2012) 400 millennia precession model
agrees with the IAU 2006 precession at J2000.0 and stays within
100 microarcseconds during the 20th and 21st centuries. It is
accurate to a few arcseconds throughout the historical period,
worsening to a few tenths of a degree at the end of the
+/- 200,000 year time span.
Called:
Ltpequ equator pole, long term
Ltpecl ecliptic pole, long term
Pxp vector product
Pn normalize vector
References:
Vondrak, J., Capitaine, N. and Wallace, P., 2011, New precession
expressions, valid for long time intervals, Astron.Astrophys. 534,
A22
Vondrak, J., Capitaine, N. and Wallace, P., 2012, New precession
expressions, valid for long time intervals (Corrigendum),
Astron.Astrophys. 541, C1
*/
func Ltecm(epj float64, rm *[3][3]float64) {
/* Frame bias (IERS Conventions 2010, Eqs. 5.21 and 5.33) */
dx := -0.016617 * DAS2R
de := -0.0068192 * DAS2R
dr := -0.0146 * DAS2R
var p, z, w, x, y [3]float64
var s float64
/* Equator pole. */
Ltpequ(epj, &p)
/* Ecliptic pole (bottom row of equatorial to ecliptic matrix). */
Ltpecl(epj, &z)
/* Equinox (top row of matrix). */
Pxp(p, z, &w)
Pn(w, &s, &x)
/* Middle row of matrix. */
Pxp(z, x, &y)
/* Combine with frame bias. */
rm[0][0] = x[0] - x[1]*dr + x[2]*dx
rm[0][1] = x[0]*dr + x[1] + x[2]*de
rm[0][2] = -x[0]*dx - x[1]*de + x[2]
rm[1][0] = y[0] - y[1]*dr + y[2]*dx
rm[1][1] = y[0]*dr + y[1] + y[2]*de
rm[1][2] = -y[0]*dx - y[1]*de + y[2]
rm[2][0] = z[0] - z[1]*dr + z[2]*dx
rm[2][1] = z[0]*dr + z[1] + z[2]*de
rm[2][2] = -z[0]*dx - z[1]*de + z[2]
}
/*
Lteqec Transformation from ICRS equatorial coordinates to ecliptic coordinates
(mean equinox and ecliptic of date) using a long-term precession model.
Given:
epj float64 Julian epoch (TT)
dr,dd float64 ICRS right ascension and declination (radians)
Returned:
dl,db float64 ecliptic longitude and latitude (radians)
Notes:
1) No assumptions are made about whether the coordinates represent
starlight and embody astrometric effects such as parallax or
aberration.
2) The transformation is approximately that from mean J2000.0 right
ascension and declination to ecliptic longitude and latitude
(mean equinox and ecliptic of date), with only frame bias (always
less than 25 mas) to disturb this classical picture.
3) The Vondrak et al. (2011, 2012) 400 millennia precession model
agrees with the IAU 2006 precession at J2000.0 and stays within
100 microarcseconds during the 20th and 21st centuries. It is
accurate to a few arcseconds throughout the historical period,
worsening to a few tenths of a degree at the end of the
+/- 200,000 year time span.
Called:
S2c spherical coordinates to unit vector
Ltecm J2000.0 to ecliptic rotation matrix, long term
Rxp product of r-matrix and p-vector
C2s unit vector to spherical coordinates
Anp normalize angle into range 0 to 2pi
Anpm normalize angle into range +/- pi
References:
Vondrak, J., Capitaine, N. and Wallace, P., 2011, New precession
expressions, valid for long time intervals, Astron.Astrophys. 534,
A22
Vondrak, J., Capitaine, N. and Wallace, P., 2012, New precession
expressions, valid for long time intervals (Corrigendum),
Astron.Astrophys. 541, C1
*/
func Lteqec(epj float64, dr, dd float64, dl, db *float64) {
var rm [3][3]float64
var v1, v2 [3]float64
var a, b float64
/* Spherical to Cartesian. */
S2c(dr, dd, &v1)
/* Rotation matrix, ICRS equatorial to ecliptic. */
Ltecm(epj, &rm)
/* The transformation from ICRS to ecliptic. */
Rxp(rm, v1, &v2)
/* Cartesian to spherical. */
C2s(v2, &a, &b)
/* Express in conventional ranges. */
*dl = Anp(a)
*db = Anpm(b)
}
/*
Lteceq Transformation from ecliptic coordinates (mean equinox and ecliptic
of date) to ICRS RA,Dec, using a long-term precession model.
Given:
epj float64 Julian epoch (TT)
dl,db float64 ecliptic longitude and latitude (radians)
Returned:
dr,dd float64 ICRS right ascension and declination (radians)
Notes:
1) No assumptions are made about whether the coordinates represent
starlight and embody astrometric effects such as parallax or
aberration.
2) The transformation is approximately that from ecliptic longitude
and latitude (mean equinox and ecliptic of date) to mean J2000.0
right ascension and declination, with only frame bias (always
less than 25 mas) to disturb this classical picture.
3) The Vondrak et al. (2011, 2012) 400 millennia precession model
agrees with the IAU 2006 precession at J2000.0 and stays within
100 microarcseconds during the 20th and 21st centuries. It is
accurate to a few arcseconds throughout the historical period,
worsening to a few tenths of a degree at the end of the
+/- 200,000 year time span.
Called:
S2c spherical coordinates to unit vector
Ltecm J2000.0 to ecliptic rotation matrix, long term
Trxp product of transpose of r-matrix and p-vector
C2s unit vector to spherical coordinates
Anp normalize angle into range 0 to 2pi
Anpm normalize angle into range +/- pi
References:
Vondrak, J., Capitaine, N. and Wallace, P., 2011, New precession
expressions, valid for long time intervals, Astron.Astrophys. 534,
A22
Vondrak, J., Capitaine, N. and Wallace, P., 2012, New precession
expressions, valid for long time intervals (Corrigendum),
Astron.Astrophys. 541, C1
*/
func Lteceq(epj float64, dl, db float64, dr, dd *float64) {
var rm [3][3]float64
var v1, v2 [3]float64
var a, b float64
/* Spherical to Cartesian. */
S2c(dl, db, &v1)
/* Rotation matrix, ICRS equatorial to ecliptic. */
Ltecm(epj, &rm)
/* The transformation from ecliptic to ICRS. */
Trxp(rm, v1, &v2)
/* Cartesian to spherical. */
C2s(v2, &a, &b)
/* Express in conventional ranges. */
*dr = Anp(a)
*dd = Anpm(b)
}
/*
Eform a,f for a nominated Earth reference ellipsoid
Given:
n int ellipsoid identifier (Note 1)
Returned:
a float64 equatorial radius (meters, Note 2)
f float64 flattening (Note 2)
Returned (function value):
int status: 0 = OK
-1 = illegal identifier (Note 3)
Notes:
1) The identifier n is a number that specifies the choice of
reference ellipsoid. The following are supported:
n ellipsoid
1 WGS84
2 GRS80
3 WGS72
The n value has no significance outside the SOFA software. For
convenience, symbols WGS84 etc. are defined in sofam.h.
2) The ellipsoid parameters are returned in the form of equatorial
radius in meters (a) and flattening (f). The latter is a number
around 0.00335, i.e. around 1/298.
3) For the case where an unsupported n value is supplied, zero a and
f are returned, as well as error status.
References:
Department of Defense World Geodetic System 1984, National
Imagery and Mapping Agency Technical Report 8350.2, Third
Edition, p3-2.
Moritz, H., Bull. Geodesique 66-2, 187 (1992).
The Department of Defense World Geodetic System 1972, World
Geodetic System Committee, May 1974.
Explanatory Supplement to the Astronomical Almanac,
P. Kenneth Seidelmann (ed), University Science Books (1992),
p220.
*/
func Eform(n int, a, f *float64) int {
/* Look up a and f for the specified reference ellipsoid. */
switch n {
case WGS84:
*a = 6378137.0
*f = 1.0 / 298.257223563
break
case GRS80:
*a = 6378137.0
*f = 1.0 / 298.257222101
break
case WGS72:
*a = 6378135.0
*f = 1.0 / 298.26
break
default:
/* Invalid identifier. */
*a = 0.0
*f = 0.0
return -1
}
/* OK status. */
return 0
}
/*
Gc2gd Transform geocentric coordinates to geodetic using the specified
reference ellipsoid.
Given:
n int ellipsoid identifier (Note 1)
xyz [3]float64 geocentric vector (Note 2)
Returned:
elong float64 longitude (radians, east +ve, Note 3)
phi float64 latitude (geodetic, radians, Note 3)
height float64 height above ellipsoid (geodetic, Notes 2,3)
Returned (function value):
int status: 0 = OK
-1 = illegal identifier (Note 3)
-2 = internal error (Note 3)
Notes:
1) The identifier n is a number that specifies the choice of
reference ellipsoid. The following are supported:
n ellipsoid
1 WGS84
2 GRS80
3 WGS72
The n value has no significance outside the SOFA software. For
convenience, symbols WGS84 etc. are defined in sofam.h.
2) The geocentric vector (xyz, given) and height (height, returned)
are in meters.
3) An error status -1 means that the identifier n is illegal. An
error status -2 is theoretically impossible. In all error cases,
all three results are set to -1e9.
4) The inverse transformation is performed in the function iauGd2gc.
Called:
Eform Earth reference ellipsoids
Gc2gde geocentric to geodetic transformation, general
*/
func Gc2gd(n int, xyz [3]float64, elong, phi, height *float64) int {
var j int
var a, f float64
/* Obtain reference ellipsoid parameters. */
j = Eform(n, &a, &f)
/* If OK, transform x,y,z to longitude, geodetic latitude, height. */
if j == 0 {
j = Gc2gde(a, f, xyz, elong, phi, height)
if j < 0 {
j = -2
}
}
/* Deal with any errors. */
if j < 0 {
*elong = -1e9
*phi = -1e9
*height = -1e9
}
/* Return the status. */
return j
}
/*
Gc2gde Transform geocentric coordinates to geodetic for a reference
ellipsoid of specified form.
Given:
a float64 equatorial radius (Notes 2,4)
f float64 flattening (Note 3)
xyz [3]float64 geocentric vector (Note 4)
Returned:
elong float64 longitude (radians, east +ve)
phi float64 latitude (geodetic, radians)
height float64 height above ellipsoid (geodetic, Note 4)
Returned (function value):
int status: 0 = OK
-1 = illegal f
-2 = illegal a