From 696dbbaa5dce693a9459e4e3e4ad4c4ad5eff984 Mon Sep 17 00:00:00 2001 From: Don Cross Date: Tue, 10 Dec 2019 20:20:31 -0500 Subject: [PATCH] C: Implemented Astronomy_InverseRefraction. --- generate/ctest.c | 12 ++++++--- generate/template/astronomy.c | 47 ++++++++++++++++++++++++++++++++--- hydrogen/hydrogen.js | 20 +++++++-------- source/c/README.md | 22 +++++++++++++++- source/c/astronomy.c | 47 ++++++++++++++++++++++++++++++++--- source/c/astronomy.h | 2 +- 6 files changed, 128 insertions(+), 22 deletions(-) diff --git a/generate/ctest.c b/generate/ctest.c index 34358894..244503e4 100644 --- a/generate/ctest.c +++ b/generate/ctest.c @@ -2525,19 +2525,23 @@ static int VectorDiff(astro_vector_t a, astro_vector_t b, double *diff) static int RefractionTest(void) { - int alt; - double corrected, refr, inv_refr, check_alt, diff; + double alt, corrected, refr, inv_refr, check_alt, diff; - for (alt = -90; alt <= +90; ++alt) + for (alt = -90.1; alt <= +90.1; alt += 0.001) { refr = Astronomy_Refraction(REFRACTION_NORMAL, (double)alt); corrected = alt + refr; inv_refr = Astronomy_InverseRefraction(REFRACTION_NORMAL, corrected); check_alt = corrected + inv_refr; diff = fabs(check_alt - alt); - printf("RefractionTest: alt=%3d, refr=%10.6lf, diff=%lg\n", alt, refr, diff); + if (diff > 1.0e+14) + { + printf("ERROR(RefractionTest): alt=%8.3lf, refr=%10.6lf, diff=%lg\n", alt, refr, diff); + return 1; + } } + printf("RefractionTest: PASS\n"); return 0; } diff --git a/generate/template/astronomy.c b/generate/template/astronomy.c index 049b298b..45f37d61 100644 --- a/generate/template/astronomy.c +++ b/generate/template/astronomy.c @@ -4277,6 +4277,11 @@ astro_spherical_t Astronomy_HorizonFromVector(astro_vector_t vector, astro_refra * @brief * Calculates the amount of "lift" to an altitude angle caused by atmospheric refraction. * + * Given an altitude angle and a refraction option, calculates + * the amount of "lift" caused by atmospheric refraction. + * This is the number of degrees higher in the sky an object appears + * due to the lensing of the Earth's atmosphere. + * * @param refraction * The option selecting which refraction correction to use. * If `REFRACTION_NORMAL`, uses a well-behaved refraction model that works well for @@ -4332,10 +4337,46 @@ double Astronomy_Refraction(astro_refraction_t refraction, double altitude) } -double Astronomy_InverseRefraction(astro_refraction_t refraction, double altitude) +/** + * @brief + * Calculates the amount of "lift" to an altitude angle caused by atmospheric refraction. + * + * Given an observed altitude angle that includes atmospheric refraction, + * calculate the negative angular correction to obtain the unrefracted + * altitude. This is useful for cases where observed horizontal + * coordinates are to be converted to another orientation system, + * but refraction first must be removed from the observed position. + * + * @param refraction + * The option selecting which refraction correction to use. + * See #Astronomy_Refraction. + * + * @param bent_altitude + * The apparent altitude that includes atmospheric refraction. + * + * @return + * The angular adjustment in degrees to be added to the + * altitude angle to correct for atmospheric lensing. + * This will be less than or equal to zero. + */ +double Astronomy_InverseRefraction(astro_refraction_t refraction, double bent_altitude) { - /* Find the pre-adjusted altitude whose refarction correction leads to 'altitude'. */ - return 0.0; + double altitude, diff; + + if (bent_altitude < -90.0 || bent_altitude > +90.0) + return 0.0; /* no attempt to correct an invalid altitude */ + + /* Find the pre-adjusted altitude whose refraction correction leads to 'altitude'. */ + altitude = bent_altitude - Astronomy_Refraction(refraction, bent_altitude); + for(;;) + { + /* See how close we got. */ + diff = (altitude + Astronomy_Refraction(refraction, altitude)) - bent_altitude; + if (fabs(diff) < 1.0e-14) + return altitude - bent_altitude; + + altitude -= diff; + } } /** diff --git a/hydrogen/hydrogen.js b/hydrogen/hydrogen.js index 576e4e7f..502cf487 100644 --- a/hydrogen/hydrogen.js +++ b/hydrogen/hydrogen.js @@ -63,29 +63,29 @@ class Item { static Flat(x) { if (typeof x === 'string') { return x; - } - + } + if (x instanceof Array) { let s = ''; for (let e of x) { s += Item.Flat(e); } return s; - } - + } + if (typeof x === 'object') { if (x.$$) { return Item.Flat(x.$$); } - + if (x._) { return Item.Flat(x._); } return ''; } - - throw `Item.Flat: don't know how to convert: ${x}`; + + throw `Item.Flat: don't know how to convert: ${x}`; } static Search(x, key, kind) { @@ -95,7 +95,7 @@ class Item { if (e['#name'] === key) { if (!kind || e.$.kind === kind) { return e; - } + } } if (e.$$ instanceof Array) { @@ -104,7 +104,7 @@ class Item { } } } - return null; + return null; } static Clean(s) { @@ -345,7 +345,7 @@ class FuncInfo extends Item { md += '| ' + type + ' | `' + name + '` | ' + desc + ' | \n'; } } - md += '\n\n'; + md += '\n\n'; } return md; diff --git a/source/c/README.md b/source/c/README.md index b6678d4d..65f4a560 100644 --- a/source/c/README.md +++ b/source/c/README.md @@ -542,7 +542,25 @@ When the body is Saturn, the returned structure contains a field `ring_tilt` tha --- -### Astronomy_InverseRefraction(refraction, altitude) ⇒ `double` +### Astronomy_InverseRefraction(refraction, bent_altitude) ⇒ `double` + +**Calculates the amount of "lift" to an altitude angle caused by atmospheric refraction.** + + + +Given an observed altitude angle that includes atmospheric refraction, calculate the negative angular correction to obtain the unrefracted altitude. This is useful for cases where observed horizontal coordinates are to be converted to another orientation system, but refraction first must be removed from the observed position. + + + +**Returns:** The angular adjustment in degrees to be added to the altitude angle to correct for atmospheric lensing. This will be less than or equal to zero. + + + +| Type | Parameter | Description | +| --- | --- | --- | +| [`astro_refraction_t`](#astro_refraction_t) | `refraction` | The option selecting which refraction correction to use. See [`Astronomy_Refraction`](#Astronomy_Refraction). | +| `double` | `bent_altitude` | The apparent altitude that includes atmospheric refraction. | + @@ -751,6 +769,8 @@ After calling [`Astronomy_SearchMoonQuarter`](#Astronomy_SearchMoonQuarter), thi +Given an altitude angle and a refraction option, calculates the amount of "lift" caused by atmospheric refraction. This is the number of degrees higher in the sky an object appears due to the lensing of the Earth's atmosphere. + **Returns:** The angular adjustment in degrees to be added to the altitude angle to correct for atmospheric lensing. diff --git a/source/c/astronomy.c b/source/c/astronomy.c index 0c403266..f8e07a95 100644 --- a/source/c/astronomy.c +++ b/source/c/astronomy.c @@ -5516,6 +5516,11 @@ astro_spherical_t Astronomy_HorizonFromVector(astro_vector_t vector, astro_refra * @brief * Calculates the amount of "lift" to an altitude angle caused by atmospheric refraction. * + * Given an altitude angle and a refraction option, calculates + * the amount of "lift" caused by atmospheric refraction. + * This is the number of degrees higher in the sky an object appears + * due to the lensing of the Earth's atmosphere. + * * @param refraction * The option selecting which refraction correction to use. * If `REFRACTION_NORMAL`, uses a well-behaved refraction model that works well for @@ -5571,10 +5576,46 @@ double Astronomy_Refraction(astro_refraction_t refraction, double altitude) } -double Astronomy_InverseRefraction(astro_refraction_t refraction, double altitude) +/** + * @brief + * Calculates the amount of "lift" to an altitude angle caused by atmospheric refraction. + * + * Given an observed altitude angle that includes atmospheric refraction, + * calculate the negative angular correction to obtain the unrefracted + * altitude. This is useful for cases where observed horizontal + * coordinates are to be converted to another orientation system, + * but refraction first must be removed from the observed position. + * + * @param refraction + * The option selecting which refraction correction to use. + * See #Astronomy_Refraction. + * + * @param bent_altitude + * The apparent altitude that includes atmospheric refraction. + * + * @return + * The angular adjustment in degrees to be added to the + * altitude angle to correct for atmospheric lensing. + * This will be less than or equal to zero. + */ +double Astronomy_InverseRefraction(astro_refraction_t refraction, double bent_altitude) { - /* Find the pre-adjusted altitude whose refarction correction leads to 'altitude'. */ - return 0.0; + double altitude, diff; + + if (bent_altitude < -90.0 || bent_altitude > +90.0) + return 0.0; /* no attempt to correct an invalid altitude */ + + /* Find the pre-adjusted altitude whose refraction correction leads to 'altitude'. */ + altitude = bent_altitude - Astronomy_Refraction(refraction, bent_altitude); + for(;;) + { + /* See how close we got. */ + diff = (altitude + Astronomy_Refraction(refraction, altitude)) - bent_altitude; + if (fabs(diff) < 1.0e-14) + return altitude - bent_altitude; + + altitude -= diff; + } } /** diff --git a/source/c/astronomy.h b/source/c/astronomy.h index 758a3382..74541dac 100644 --- a/source/c/astronomy.h +++ b/source/c/astronomy.h @@ -634,7 +634,7 @@ astro_rotation_t Astronomy_Rotation_HOR_EQJ(astro_time_t time, astro_observer_t astro_rotation_t Astronomy_Rotation_HOR_ECL(astro_time_t time, astro_observer_t observer); double Astronomy_Refraction(astro_refraction_t refraction, double altitude); -double Astronomy_InverseRefraction(astro_refraction_t refraction, double altitude); +double Astronomy_InverseRefraction(astro_refraction_t refraction, double bent_altitude); #ifdef __cplusplus }