The calendar enumerator demo now includes inferior and superior
conjunctions of the inner planets (Mercury and Venus), along
with the conjunctions and oppositions of the outer planets
(Mars ... Pluto).
Once a collator has been created, and a caller starts
enumerating events, it does not make sense to be able to add
another enumerator to the collator. So I removed EventCollator.Append().
It was just opening up the possibility of bugs for no good reason.
Client code should decide up front what kind of events it wants
to enumerate and provide a complete list of enumerators.
Then it may use FindFirst/FindNext as many times as it wants
and everything will just work.
Added MoonQuarterEnumerator, which finds new moon, first quarter,
full moon, and third quarter events.
Changed the calendar start date to May 2021, so it is
more relevant to the time I'm testing it.
This is an example of how multiple enumerators can be combined
into an EventCollator. The collator does the minimum amount
of work to keep searching for one event at a time, while always
emitting them in chronological order.
Decreased the minified browser code from 94918 bytes to 94221 bytes.
Did this by using a more efficient encoding of the IAU2000B nutation model:
instead of making {nals:[_], cls:[_]} objects, make lists of lists [[_], [_]].
Finished the script demos/python/lunar_angles.py
that shows how to search for times when the Moon and other
solar system bodies reach apparent ecliptic longitude separations
as seen from the Earth.
This is also a good demo of how to perform a custom search
for events using Astronomy Engine. This is the same technique
used internally by Astronomy Engine to search for lunar phases,
eclipses, solstices, etc.
Started work on a Python demo for finding when the moon
reaches relative longitudes with other solar system bodies
that are multiples of 30 degrees. It is not finished yet,
but getting close.
Added operator overloads for the Python Time class so
that times can be compared against each other.
This makes it easier to sort a list of times, for example.
This script will help me figure out how to tune the search algorithm
I'm about to write for searching for times that a pair of bodies
reach a given relative apparent ecliptic longitude.
Before making these changes, I had the following discrepancies
between the calculations made by the different programming
language implementations of Astronomy Engine:
C vs C#: 5.55112e-17, worst line number = 6
C vs JS: 2.78533e-12, worst line number = 196936
C vs PY: 1.52767e-12, worst line number = 159834
Now the results are:
Diffing calculations: C vs C#
ctest(Diff): Maximum numeric difference = 5.55112e-17, worst line number = 5
Diffing calculations: C vs JS
ctest(Diff): Maximum numeric difference = 1.02318e-12, worst line number = 133677
Diffing calculations: C vs PY
ctest(Diff): Maximum numeric difference = 5.68434e-14, worst line number = 49066
Diffing calculations: JS vs PY
ctest(Diff): Maximum numeric difference = 1.02318e-12, worst line number = 133677
Here is how I did this:
1. Use new constants HOUR2RAD, RAD2HOUR that directly convert between radians and sidereal hours.
This reduces tiny roundoff errors in the conversions.
2. In VSOP longitude calculations, keep clamping the angular sum to
the range [-2pi, +2pi], to prevent it from accumulating thousands
of radians. This reduces the accumulated error in the final result
before it is fed into trig functions.
The remaining discrepancies are largely because of an "azimuth amplification" effect:
When converting equatorial coordinates to horizontal coordinates, an object near
the zenith (or nadir) has an azimuth that is highly sensitive to the input
equatorial coordinates. A tiny change in right ascension (RA) can cause a much
larger change in azimuth.
I tracked down the RA discrepancy, and it is due to a different behavior
of the atan2 function in C and JavaScript. There are cases where the least
significant decimal digit is off by 1, as if due to a difference of opinion
about rounding policy.
My best thought is to go back and have a more nuanced diffcalc that
applies less strict tests for azimuth values than the other calculated values.
It seems like every other computed quantity is less sensitive, because solar
system bodies tend to stay away from "poles" of other angular coordinate
systems: their ecliptic latitudes and equatorial declinations are usually
reasonably close to zero. Therefore, right ascensions and ecliptic longitudes
are usually insensitive to changes in the cartesian coordinates they
are calculated from.
This change has no effect on client-facing behavior.
It just makes the internal data tables for the array of
constellation appear more compact in C, C#, and Python.
This is what the TypeScript/JavaScript code was already doing.
The demo shows how to correct for light travel
time to render Jupiter's moons as they appear
from the Earth.
Created an addition operator for the Vector
class in the Python code, because it is handy.
Corrected a bug in the string representation
of the Python StateVector class.
Now there are constants for the mean radii of Jupiter's
four major moons available in the C, C#, Python, and JavaScript
versions of Astronomy Engine.
Clarified that these are all mean radii.
Fixed some lingering "//" comments in the C code
(I want to keep ANSI C code as portable as possible.)
To assist software that wants to depict Jupiter and its 4 major moons
as they would appear in a telescope, it is important to know their
physical sizes. I already had constants for Jupiter's equatorial
and polar radii. Here I add constants for the radii of the moons
Io, Europa, Ganymede, and Callisto. They are all nearly spherical,
so a single mean radius value is sufficient.
Now callers can create time objects from either UT (UT1/UTC civil time)
or ephemeris/dynamical Terrestrial Time (TT). The new TT functions
numerically solve to find the UT that produces the given TT based
on the Delta-T value at that UT. This is always a very fast
numerical convergence, because TT and UT are almost perfectly
linear over brief time windows.
I increased the error tolerance slightly for the Jupiter moons model.
This shrank the model tables significantly, giving me some more
breathing room to stay under 100K download size.
I don't like how close I am to my 100K target size, now
that I'm calculating Jupiter's moons.
Simplified the spin() function so its minified code is smaller.
I will look for other things I can shrink too.
I am starting the process of implementing calculation
of Jupiter's four largest moons: Io, Europa, Ganymede, Callisto.
This commit just contains constant declarations for the
equatorial, polar, and volumetric mean radii of Jupiter.
The positions of the moons will be related to the center
of Jupiter and be expressed in Jupiter equatorial radius units,
so I felt it would be good to give users a way to convert to
kilometers, which can in turn be converted to AU.
Python docstrings don't work for variables, so I hacked
a special comment format for helping pydown generate Markdown
text for the README.md for the exported constant KM_PER_AU,
or any other constants I may want to expose in the future.
Also made time parameters to rotation matrix functions be of
type FlexibleDateTime, and internally convert them to AstroTime.
This should be the policy of all exposed functions in the
JavaScript version of Astronomy Engine.
Exposed KM_PER_AU to outside callers.
Use a private enumerated type to select which direction
the precession and nutation is to be done:
- from date to J2000
- from J2000 to date
Normalize the order of parameters to be consistent
between precession() and nutation(), and across languages.
Pass in AstroTime instead of a pair of floating point TT
values (one of which had to be 0).
Added TypeScript version of ObserverVector(),
but it has not yet been documented or tested.
Moved the following constant definitions from astronomy.c
to astronomy.h, so external code can use them:
DEG2RAD
RAD2DEG
KM_PER_AU
My custom doxygen-to-markdown translator (hydrogen.js)
now emits markdown for the above constants.
Eliminated the obsolete constants MIN_YEAR and MAX_YEAR.
Astronomy Engine is no longer limited to calculating planets
within that range of years.
Fixed a couple of minor documentation issues in the C code.
Started work on a new function Astronomy_ObserverVector,
but it is just a stub for now.