cosinekitty / astronomy

Astronomy Engine: multi-language calculation of Sun, Moon, and planet positions. Predicts lunar phases, eclipses, transits, oppositions, conjunctions, equinoxes, solstices, rise/set times, and other events. Provides vector and angular coordinate transforms among equatorial, ecliptic, horizontal, and galactic orientations.
MIT License
489 stars 63 forks source link

Where an eclipse and crescent can be seen on a map? #150

Closed ebraminio closed 2 years ago

ebraminio commented 2 years ago

Hi! Wondering if is possible to see where an eclipse and/or crescent will be visible?

See for example https://www.moonsighting.com/visibility.html and https://svs.gsfc.nasa.gov/4906

Initially my first question was how to draw day and night map which the question led me to http://thenewkinetic.blogspot.com/2011/05/how-to-draw-daynight-world-map_7282.html

Thus I have the following very initial result on my foss app :)

image
cosinekitty commented 2 years ago

This is an interesting problem. Reading your link to "The New Kinetic", I would use a similar idea. You need some way to calculate the latitude and longitude for every pixel on your map. It looks like you are using a Mercator projection. But this would work for any projection, so long as you have a way of calculating the geographic coordinates for a given pixel.

First of all, there are solar eclipses and lunar eclipses. Both will require different approaches. A lunar eclipse and a crescent moon observation will both be very similar, because they are asking "can you see the Moon from this place?" The solar eclipse is asking, "is the Moon blocking sunlight from reaching this place?"

I will have to think more about the solar eclipse case. The closest thing I have right now is SearchLocalSolarEclipse, which will tell you the beginning, middle, and end of a solar eclipse at a given location on the Earth. The problem is you would have to call it for every single pixel on your map, which would be extremely slow. Maybe I can think about this to find a better answer.

Lunar eclipses and crescent moons are more feasible with the existing Astronomy Engine code. You will want to find the moment in time you are interested in for observing the Moon. For example, perhaps you call SearchLunarEclipse to find a lunar eclipse. This will tell you when the lunar eclipse starts, peaks, and ends. Let's assume we want to make a map for a single moment in time, such as the peak of a lunar eclipse.

Calculating the Moon's position is expensive (the formulas are very complicated). So you will want to calculate its position just once for your entire map. The best way would be to call GeoMoon to obtain the Moon's geocentric position vector at whatever moment in time you are interested in.

Then, for each pixel on your map, calculate the geographic coordinates (latitude, longitude). Use those coordinates to create an Observer object that you can pass into a call to ObserverVector to calculate a geocentric vector of that point on the Earth's surface. Subtract the observer vector from the moon vector to obtain a vector from the observer toward the moon.

Then call Rotation_EQJ_HOR to calculate a rotation matrix that converts equatorial J2000 vectors into local horizon vectors, for that same observer location. (This part could use some optimization to avoid redundantly calculating the Earth's axis and rotation for every single pixel on your map. I will have to come back and think about that some more.)

Pass your vector from the observer toward the moon, and the rotation matrix, into a call to RotateVector. The result will be a horizon-based vector for the given location on the Earth. The x component points north, the y component points west, and the z component points up. If z is a positive number, it means the object is above the observer's horizon, and is thus visible.

This might be enough to get you started. Again, this is very interesting! I may consider adding some new code to Astronomy Engine to make map calculations like this more efficient, because I can see how the approach I outlined above will waste time by repeating a lot of calculations for every pixel on the map.

ebraminio commented 2 years ago

Thank you so much! Just to note the map is from here https://commons.wikimedia.org/wiki/File:World_map_blank_without_borders.svg and is equirectangular projection AFAIK, and using https://jakearchibald.github.io/svgomg/ and Zopfli for compression it only takes 36,498 bytes of gzip, I wished it had the zero longitude on its center which apparently isn't and I don't know where exactly it starts from, am playing with QGIS right now to see if I can generate another map maybe also, just said as you may want to do the same here or not :)

cosinekitty commented 2 years ago

@ebraminio Which programming language would you want to use to generate your maps? I was assuming JavaScript, but I thought I would ask, so that I can prototype something in that language first. I want to focus on eliminating the redundant Earth axis calculations for every pixel.

ebraminio commented 2 years ago

Oh, thanks a lot for asking, feel free to use any of the supported languages you feel will be easier for it :)

ebraminio commented 2 years ago

Guess drawing day night also would be great for example I applied one simple change on my codes https://github.com/persian-calendar/DroidPersianCalendar/commit/f3667ff72077d32388d04a52d627c6d5dbccfd18 which made day night calculations much faster

cosinekitty commented 2 years ago

That is interesting also, because it turns out to be the same problem as the lunar eclipse case, only for the Sun instead of the Moon. In a way, it will be easier because, unlike for the Moon, there is no need for parallax correction for the Sun, because it is so much farther away. I will keep this in mind as I design the new feature.

ebraminio commented 2 years ago

Just to update, this is the result of my work about day night map till now (does't share any code with astronomy engine but guess still is interesting)

https://user-images.githubusercontent.com/833473/150416008-c2e84284-c633-499c-b1d2-b21f90d73bf1.mov

It uses a equirectangular projection map I crafted https://commons.wikimedia.org/wiki/File:Equirectangular_projection_world_map_without_borders.svg using QGIS which only takes 50kb of gzip.

am letting you know so possibly you can reuse some of the ideas of it 😊

Update:

Now features moon also!

image
ebraminio commented 2 years ago

Sorry for repeated spam again :) day night map probably can be done faster also using https://astronomy.stackexchange.com/a/43818 but as I've only have spotted this haven't yet studied it yet in detail, I will try to implement it in my code base to see what experiences I can share, maybe something similar can be done for other maps in question.

cosinekitty commented 2 years ago

No, it's not spam at all; it's helpful! That is a good point, that at the resolution of a world map, it may not make any visible difference to treat the Earth as a perfect sphere by ignoring its oblateness. I'm still planning on adding a feature for enabling more efficient repeated calculations that could be used for many different applications, not just drawing maps, so I don't want to assume a spherical Earth in what I'm doing. However, it's great to point out other reference materials here for anybody else who is reading this, so they can make the best choice for their own project.

cosinekitty commented 2 years ago

I just pushed this commit: 90a9839d1817b8b0dc6fcf5f90b11e6acc5c29d6. It improves performance for making maps like we have been discussing. I realized the main source of wasted calculation was the internal calculations for the Earth's rotation at a given moment in time, also known as sidereal time. The optimization is to cache the sidereal time and recycle it as much as possible. I did this for all 4 supported programming languages.

In the C version, for example, a simulated map-making program runs about 2.3 times faster with the sidereal time caching optimization.

I was very happy that the changes were simpler than I thought, and they do not require any changes in the exported interface. The changes are hidden entirely inside Astronomy Engine without breaking any outside code.

I'm going to convert this issue into a discussion, so we can keep it around for future reference, but without considering it an open issue.