Skip to content

Commit 15d363e

Browse files
committed
novas_geom_to_app(), and tests
1 parent d711a1f commit 15d363e

File tree

4 files changed

+150
-35
lines changed

4 files changed

+150
-35
lines changed

include/novas.h

+2
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,8 @@ int novas_change_observer(const novas_frame *orig, const observer *obs, novas_fr
11181118

11191119
int novas_geom_posvel(const object *source, const novas_frame *frame, enum novas_reference_system sys, double *pos, double *vel);
11201120

1121+
int novas_geom_to_app(const novas_frame *frame, const double *pos, enum novas_reference_system sys, sky_pos *out);
1122+
11211123
int novas_sky_pos(const object *object, const novas_frame *frame, enum novas_reference_system sys, sky_pos *output);
11221124

11231125
int novas_app_to_hor(const novas_frame *frame, enum novas_reference_system sys, double ra, double dec, RefractionModel ref_model,

src/frames.c

+55-21
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ static int icrs_to_sys(const novas_frame *frame, double *pos, enum novas_referen
435435
* 50--70 error is 50 + error from light_time2().
436436
*
437437
* @sa novas_make_frame()
438+
* @sa novas_geom_to_app()
438439
* @sa novas_sky_pos()
439440
* @sa novas_transform_vector()
440441
* @sa place()
@@ -453,7 +454,7 @@ int novas_geom_posvel(const object *source, const novas_frame *frame, enum novas
453454
return novas_error(-1, EINVAL, fn, "NULL argument: source=%p, frame=%p", source, frame);
454455

455456
if(!pos && !vel)
456-
return novas_error(-1, EINVAL, fn, "Both output vectors (pos, vel) are NULL");
457+
return novas_error(-1, EINVAL, fn, "Both output vectors (pos, vel) are NULL");
457458

458459
obs = (observer*) &frame->observer;
459460

@@ -533,7 +534,7 @@ int novas_geom_posvel(const object *source, const novas_frame *frame, enum novas
533534
* @param sys The coordinate system in which to return the apparent sky location
534535
* @param[out] out Pointer to the data structure which is populated with the calculated
535536
* apparent location in the designated coordinate system.
536-
* @return 0 if successful, or an error from grav_def(),
537+
* @return 0 if successful,
537538
* 3 if Earth is the observed object, and the observer is either at the
538539
* geocenter or on the Earth's surface,
539540
* 50--70 error is 50 + error from light_time2(),
@@ -549,11 +550,10 @@ int novas_geom_posvel(const object *source, const novas_frame *frame, enum novas
549550
* @author Attila Kovacs
550551
*/
551552
int novas_sky_pos(const object *object, const novas_frame *frame, enum novas_reference_system sys, sky_pos *out) {
552-
static const char *fn = "novas_calc_apparent";
553-
enum novas_observer_place loc;
554-
double jd_tdb, id, d_sb;
553+
static const char *fn = "novas_sky_pos";
554+
555555
double pos[3], vel[3];
556-
int i;
556+
double d_sb;
557557

558558
if(!object || !frame || !out)
559559
return novas_error(-1, EINVAL, "NULL argument: object=%p, frame=%p, out=%p", (void *) object, frame, out);
@@ -566,8 +566,6 @@ int novas_sky_pos(const object *object, const novas_frame *frame, enum novas_ref
566566

567567
prop_error(fn, novas_geom_posvel(object, frame, NOVAS_ICRS, pos, vel), 0);
568568

569-
jd_tdb = novas_get_time(&frame->time, NOVAS_TDB);
570-
571569
if(object->type == NOVAS_CATALOG_OBJECT) {
572570
out->dis = 0.0;
573571
d_sb = novas_vlen(pos);
@@ -592,6 +590,45 @@ int novas_sky_pos(const object *object, const novas_frame *frame, enum novas_ref
592590
rad_vel(object, pos, vel, frame->obs_vel, novas_vdist(frame->obs_pos, &frame->pos[NOVAS_EARTH][0]),
593591
novas_vdist(frame->obs_pos, &frame->pos[NOVAS_SUN][0]), d_sb, &out->rv);
594592

593+
prop_error(fn, novas_geom_to_app(frame, pos, sys, out), 70);
594+
595+
return 0;
596+
}
597+
598+
/**
599+
* Converts an geometric position in ICRS to an apparent position on sky, by applying appropriate
600+
* corrections for aberration and gravitational deflection for the observer's frame.
601+
*
602+
* @param frame The observer frame, defining the location and time of observation
603+
* @param pos [AU] Geometric position of source in ICRS coordinates
604+
* @param sys The coordinate system in which to return the apparent sky location
605+
* @param[out] out Pointer to the data structure which is populated with the calculated
606+
* apparent location in the designated coordinate system.
607+
* @return 0 if successful, or an error from grav_def(),
608+
* or else -1 (errno will indicate the type of error).
609+
*
610+
* @sa novas_app_to_geom()
611+
* @sa novas_geom_posvel()
612+
* @sa novas_sky_pos()
613+
*/
614+
int novas_geom_to_app(const novas_frame *frame, const double *pos, enum novas_reference_system sys, sky_pos *out) {
615+
static const char *fn = "novas_geom_to_app";
616+
617+
double jd_tdb, id, pos1[3];
618+
enum novas_observer_place loc;
619+
int i;
620+
621+
if(!pos || !frame || !out)
622+
return novas_error(-1, EINVAL, "NULL argument: pos=%p, frame=%p, out=%p", (void *) pos, frame, out);
623+
624+
if(!is_frame_initialized(frame))
625+
return novas_error(-1, EINVAL, fn, "frame at %p not initialized", frame);
626+
627+
if(frame->accuracy != NOVAS_FULL_ACCURACY && frame->accuracy != NOVAS_REDUCED_ACCURACY)
628+
return novas_error(-1, EINVAL, fn, "invalid accuracy: %d", frame->accuracy);
629+
630+
jd_tdb = novas_get_time(&frame->time, NOVAS_TDB);
631+
595632
// ---------------------------------------------------------------------
596633
// Apply gravitational deflection of light and aberration.
597634
// ---------------------------------------------------------------------
@@ -605,22 +642,19 @@ int novas_sky_pos(const object *object, const novas_frame *frame, enum novas_ref
605642
}
606643

607644
// Compute gravitational deflection and aberration.
608-
prop_error(fn, grav_def(jd_tdb, loc, frame->accuracy, pos, frame->obs_pos, pos), 70);
645+
prop_error(fn, grav_def(jd_tdb, loc, frame->accuracy, pos, frame->obs_pos, pos1), 0);
609646

610647
// Aberration correction
611-
frame_aberration(frame, GEOM_TO_APP, pos);
648+
frame_aberration(frame, GEOM_TO_APP, pos1);
612649

613650
// Transform position to output system
614-
prop_error(fn, icrs_to_sys(frame, pos, sys), 0);
651+
prop_error(fn, icrs_to_sys(frame, pos1, sys), 0);
615652

616-
// ---------------------------------------------------------------------
617-
// Finish up.
618-
// ---------------------------------------------------------------------
619-
vector2radec(pos, &out->ra, &out->dec);
653+
vector2radec(pos1, &out->ra, &out->dec);
620654

621-
id = 1.0 / novas_vlen(pos);
655+
id = 1.0 / novas_vlen(pos1);
622656
for(i = 3; --i >= 0;)
623-
out->r_hat[i] = pos[i] * id;
657+
out->r_hat[i] = pos1[i] * id;
624658

625659
return 0;
626660
}
@@ -761,7 +795,7 @@ int novas_hor_to_app(const novas_frame *frame, double az, double el, RefractionM
761795
}
762796

763797
if(sys < 0 || sys >= NOVAS_REFERENCE_SYSTEMS)
764-
return novas_error(-1, EINVAL, fn, "invalid reference system", sys);
798+
return novas_error(-1, EINVAL, fn, "invalid reference system: %d", sys);
765799

766800
time = (novas_timespec *) &frame->time;
767801

@@ -826,7 +860,7 @@ int novas_hor_to_app(const novas_frame *frame, double az, double el, RefractionM
826860
* @return 0 if successful, or else an error from grav_undef(), or -1 (errno will
827861
* indicate the type of error).
828862
*
829-
* @sa novas_transform_skypos()
863+
* @sa novas_geom_to_app()
830864
*
831865
* @since 1.1
832866
* @author Attila Kovacs
@@ -837,13 +871,13 @@ int novas_app_to_geom(const novas_frame *frame, enum novas_reference_system sys,
837871
double jd_tdb, app_pos[3];
838872

839873
if(!frame || !geom_icrs)
840-
return novas_error(-1, EINVAL, fn, "NULL argument: frame=%p, nom_pos=%p", frame, geom_icrs);
874+
return novas_error(-1, EINVAL, fn, "NULL argument: frame=%p, geom_icrs=%p", frame, geom_icrs);
841875

842876
if(!is_frame_initialized(frame))
843877
return novas_error(-1, EINVAL, fn, "frame at %p not initialized", frame);
844878

845879
if(sys < 0 || sys >= NOVAS_REFERENCE_SYSTEMS)
846-
return novas_error(-1, EINVAL, fn, "invaliud reference system", sys);
880+
return novas_error(-1, EINVAL, fn, "invalid reference system: %d", sys);
847881

848882
jd_tdb = novas_get_time(&frame->time, NOVAS_TDB);
849883

test/src/test-errors.c

+26-1
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,30 @@ static int test_app_to_geom() {
10881088
return n;
10891089
}
10901090

1091+
static int test_geom_to_app() {
1092+
novas_timespec ts = {};
1093+
observer obs = {};
1094+
novas_frame frame = {};
1095+
sky_pos out = {};
1096+
double pos[3] = {};
1097+
int n = 0;
1098+
1099+
make_observer_at_geocenter(&obs);
1100+
novas_set_time(NOVAS_TT, NOVAS_JD_J2000, 32, 0.0, &ts);
1101+
1102+
if(check("geom_to_app:frame", -1, novas_geom_to_app(NULL, pos, NOVAS_ICRS, &out))) n++;
1103+
if(check("geom_to_app:frame:init", -1, novas_geom_to_app(&frame, pos, NOVAS_ICRS, &out))) n++;
1104+
1105+
novas_make_frame(NOVAS_REDUCED_ACCURACY, &obs, &ts, 0.0, 0.0, &frame);
1106+
if(check("geom_to_app:frame:ok", 0, novas_geom_to_app(&frame, pos, NOVAS_ICRS, &out))) n++;
1107+
1108+
if(check("geom_to_app:pos", -1, novas_geom_to_app(&frame, NULL, NOVAS_ICRS, &out))) n++;
1109+
if(check("geom_to_app:sys:-1", -1, novas_geom_to_app(&frame, pos, -1, &out))) n++;
1110+
if(check("geom_to_app:sys:hi", -1, novas_geom_to_app(&frame, pos, NOVAS_REFERENCE_SYSTEMS, &out))) n++;
1111+
1112+
return n;
1113+
}
1114+
10911115
static int test_app_to_hor() {
10921116
novas_timespec ts = {};
10931117
observer obs = {};
@@ -1296,10 +1320,11 @@ int main() {
12961320
if(test_change_observer()) n++;
12971321
if(test_make_transform()) n++;
12981322
if(test_geom_posvel()) n++;
1299-
if(test_sky_pos()) n++;
1323+
if(test_geom_to_app()) n++;
13001324
if(test_app_to_geom()) n++;
13011325
if(test_app_to_hor()) n++;
13021326
if(test_hor_to_app()) n++;
1327+
if(test_sky_pos()) n++;
13031328
if(test_transform_vector()) n++;
13041329
if(test_transform_sky_pos()) n++;
13051330
if(test_inv_transform()) n++;

test/src/test-super.c

+67-13
Original file line numberDiff line numberDiff line change
@@ -438,35 +438,87 @@ static int test_radec_star() {
438438

439439

440440
static int test_app_hor(enum novas_reference_system sys) {
441+
char label[50];
441442
novas_timespec ts = {};
442443
observer obs = {};
443444
novas_frame frame = {};
444445
cat_entry c = {};
445446

446447
double ra = source.star.ra, dec = source.star.dec, az, el, ra1, dec1;
447448

448-
if(!is_ok("app_hor:set_time", novas_set_time(NOVAS_TT, tdb, 32, 0.0, &ts))) return 1;
449-
if(!is_ok("app_hor:make_observer", make_observer_on_surface(1.0, 2.0, 3.0, 4.0, 1001.0, &obs))) return 1;
450-
if(!is_ok("app_hop:make_frame", novas_make_frame(NOVAS_REDUCED_ACCURACY, &obs, &ts, 0.0, 0.0, &frame))) return 1;
449+
sprintf(label, "app_hor:sys=%d:set_time", sys);
450+
if(!is_ok(label, novas_set_time(NOVAS_TT, tdb, 32, 0.0, &ts))) return 1;
451451

452-
if(!is_ok("app_hor:app_to_hor", novas_app_to_hor(&frame, sys, ra, dec, NULL, &az, &el))) return 1;
453-
if(!is_ok("app_hor:hor_to_app", novas_hor_to_app(&frame, az, el, NULL, sys, &ra1, &dec1))) return 1;
452+
sprintf(label, "app_hor:sys=%d:make_observer", sys);
453+
if(!is_ok(label, make_observer_on_surface(1.0, 2.0, 3.0, 4.0, 1001.0, &obs))) return 1;
454454

455-
if(!is_equal("app_hor:trip:ra", ra1, ra, 1e-7)) return 1;
456-
if(!is_equal("app_hor:trip:dec", dec1, dec, 1e-6)) return 1;
455+
sprintf(label, "app_hor:sys=%d:make_frame", sys);
456+
if(!is_ok(label, novas_make_frame(NOVAS_REDUCED_ACCURACY, &obs, &ts, 0.0, 0.0, &frame))) return 1;
457457

458-
if(!is_ok("app_hor:app_to_hor:refract", novas_app_to_hor(&frame, sys, ra, dec, novas_standard_refraction, &az, &el))) return 1;
459-
if(!is_ok("app_hor:hor_to_app:refract", novas_hor_to_app(&frame, az, el, novas_standard_refraction, sys, &ra1, &dec1))) return 1;
458+
459+
sprintf(label, "app_hor:sys=%d:app_to_hor", sys);
460+
if(!is_ok(label, novas_app_to_hor(&frame, sys, ra, dec, NULL, &az, &el))) return 1;
461+
462+
sprintf(label, "app_hor:sys=%d:hor_to_app", sys);
463+
if(!is_ok(label, novas_hor_to_app(&frame, az, el, NULL, sys, &ra1, &dec1))) return 1;
464+
465+
sprintf(label, "app_hor:sys=%d:trip:ra", sys);
466+
if(!is_equal(label, ra1, ra, 1e-7)) return 1;
467+
468+
sprintf(label, "app_hor:sys=%d:trip:dec", sys);
469+
if(!is_equal(label, dec1, dec, 1e-6)) return 1;
470+
471+
sprintf(label, "app_hor:sys=%d:app_to_hor:refract", sys);
472+
if(!is_ok(label, novas_app_to_hor(&frame, sys, ra, dec, novas_standard_refraction, &az, &el))) return 1;
473+
474+
sprintf(label, "app_hor:sys=%d:hor_to_app:refract", sys);
475+
if(!is_ok(label, novas_hor_to_app(&frame, az, el, novas_standard_refraction, sys, &ra1, &dec1))) return 1;
460476

461477
// TODO check against cel2ter...
462478

463-
if(!is_equal("app_hor:refract:trip:ra", ra1, ra, 1e-7)) return 1;
464-
if(!is_equal("app_hor:refract:trip:dec", dec1, dec, 1e-6)) return 1;
479+
sprintf(label, "app_hor:sys=%d:refract:ra", sys);
480+
if(!is_equal(label, ra1, ra, 1e-7)) return 1;
481+
482+
sprintf(label, "app_hor:sys=%d:refract:dec", sys);
483+
if(!is_equal(label, dec1, dec, 1e-6)) return 1;
465484

466485

467486
return 0;
468487
}
469488

489+
static int test_app_geom(enum novas_reference_system sys) {
490+
char label[50];
491+
novas_timespec ts = {};
492+
observer obs = {};
493+
novas_frame frame = {};
494+
cat_entry c = {};
495+
double pos0[3] = {}, pos1[3] = {};
496+
sky_pos app = {};
497+
498+
sprintf(label, "app_hor:sys=%d:set_time", sys);
499+
if(!is_ok(label, novas_set_time(NOVAS_TT, tdb, 32, 0.0, &ts))) return 1;
500+
501+
sprintf(label, "app_hor:sys=%d:make_observer", sys);
502+
if(!is_ok(label, make_observer_at_geocenter(&obs))) return 1;
503+
504+
sprintf(label, "app_hor:sys=%d:make_frame", sys);
505+
if(!is_ok(label, novas_make_frame(NOVAS_REDUCED_ACCURACY, &obs, &ts, 0.0, 0.0, &frame))) return 1;
506+
507+
starvectors(&source.star, pos0, NULL);
508+
509+
sprintf(label, "app_hor:sys=%d:geom_to_app", sys);
510+
if(!is_ok(label, novas_geom_to_app(&frame, pos0, sys, &app))) return 1;
511+
512+
sprintf(label, "app_hor:sys=%d:app_to_geom", sys);
513+
514+
if(!is_ok(label, novas_app_to_geom(&frame, sys, app.ra, app.dec, vlen(pos0), pos1))) return 1;
515+
516+
sprintf(label, "app_hor:sys=%d:check", sys);
517+
if(!is_ok(label, check_equal_pos(pos1, pos0, 1e-8 * vlen(pos0)))) return 1;
518+
519+
return 0;
520+
}
521+
470522

471523
static int test_source() {
472524
int k, n = 0;
@@ -496,9 +548,11 @@ static int test_source() {
496548

497549
if(test_geo_posvel()) n++;
498550

499-
if(test_app_hor(1)) n++;
551+
for(k = 0; k < NOVAS_REFERENCE_SYSTEMS; k++) if(test_app_hor(k)) n++;
500552

501-
for(k = 0; k < NOVAS_REFERENCE_SYSTEMS; k++) if(test_app_hor(k)) n++;
553+
novas_debug(NOVAS_DEBUG_ON);
554+
for(k = 0; k < NOVAS_REFERENCE_SYSTEMS; k++) if(test_app_geom(k)) n++;
555+
novas_debug(NOVAS_DEBUG_OFF);
502556

503557
return n;
504558
}

0 commit comments

Comments
 (0)