From 7a7a3d1dbe9aa0e14d2502cbfb13f2165bd6e7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Hannequin?= Date: Fri, 22 Nov 2024 17:55:47 +0100 Subject: [PATCH] Fix `ObservationEvents` infinite loop (#110) In some cases new iterations of rise-transit-set calculations are not more precise than the previous ones. Quite the opposite, it is apparently possible to loop indefinitely over some values without ever crossing the targeted precision. This introduces a limit of 5 iterations. Passed this limit, it is admitted that the program in its current form will not achieve a better precision. Fixes #109 --- lib/astronoby/events/observation_events.rb | 5 ++++- spec/astronoby/bodies/moon_spec.rb | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/astronoby/events/observation_events.rb b/lib/astronoby/events/observation_events.rb index 600199f..5ea932f 100644 --- a/lib/astronoby/events/observation_events.rb +++ b/lib/astronoby/events/observation_events.rb @@ -7,6 +7,7 @@ class ObservationEvents RISING_SETTING_HOUR_ANGLE_RATIO_RANGE = (-1..1) EARTH_SIDEREAL_ROTATION_RATE = 360.98564736629 ITERATION_PRECISION = 0.0001 + ITERATION_LIMIT = 5 attr_reader :rising_time, :rising_azimuth, @@ -89,10 +90,11 @@ def compute def iterate(initial_rising, initial_transit, initial_setting) delta = 1 + iteration = 1 corrected_rising = initial_rising corrected_transit = initial_transit corrected_setting = initial_setting - until delta < ITERATION_PRECISION + until delta < ITERATION_PRECISION || iteration > ITERATION_LIMIT iterate = RiseTransitSetIteration.new( observer: @observer, date: @date, @@ -108,6 +110,7 @@ def iterate(initial_rising, initial_transit, initial_setting) corrected_rising = rationalize_decimal_time corrected_rising + iterate[0] corrected_transit = rationalize_decimal_time corrected_transit + iterate[1] corrected_setting = rationalize_decimal_time corrected_setting + iterate[2] + iteration += 1 end [corrected_rising, corrected_transit, corrected_setting] end diff --git a/spec/astronoby/bodies/moon_spec.rb b/spec/astronoby/bodies/moon_spec.rb index deb54fd..3116b6f 100644 --- a/spec/astronoby/bodies/moon_spec.rb +++ b/spec/astronoby/bodies/moon_spec.rb @@ -416,7 +416,7 @@ end end - it "returns the sunrise time on 1991-03-14" do + it "returns the moonrise time on 1991-03-14" do time = Time.utc(1991, 3, 14) observer = Astronoby::Observer.new( latitude: Astronoby::Angle.from_degrees(48.8566), @@ -431,6 +431,20 @@ # Time from IMCCE: 1991-03-14T05:08:08 end + it "returns moonrise time on 2024-11-10" do + time = Time.utc(2024, 11, 10) + observer = Astronoby::Observer.new( + latitude: Astronoby::Angle.from_degrees(41.02054), + longitude: Astronoby::Angle.from_degrees(-72.15608) + ) + moon = described_class.new(time: time) + observation_events = moon.observation_events(observer: observer) + + rising_time = observation_events.rising_time + + expect(rising_time).to eq Time.utc(2024, 11, 10, 18, 49, 45) + end + describe "#rising_azimuth" do it "returns the moonrise azimuth on 2024-05-31" do time = Time.utc(2024, 5, 31)