Compare commits
4 commits
28286df814
...
158bd8f62b
Author | SHA1 | Date | |
---|---|---|---|
158bd8f62b | |||
b5482b8962 | |||
7930e4dd0a | |||
1f1a3260c0 |
7 changed files with 94 additions and 26 deletions
|
@ -8,5 +8,5 @@
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="temurin-21" project-jdk-type="JavaSDK" />
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="graalvm-ce-17" project-jdk-type="JavaSDK" />
|
||||||
</project>
|
</project>
|
|
@ -3,7 +3,7 @@ package eu.m724.wtapi.provider;
|
||||||
import eu.m724.wtapi.provider.exception.NoSuchProviderException;
|
import eu.m724.wtapi.provider.exception.NoSuchProviderException;
|
||||||
import eu.m724.wtapi.provider.thunder.ThunderProvider;
|
import eu.m724.wtapi.provider.thunder.ThunderProvider;
|
||||||
import eu.m724.wtapi.provider.thunder.impl.blitzortung.BlitzortungProvider;
|
import eu.m724.wtapi.provider.thunder.impl.blitzortung.BlitzortungProvider;
|
||||||
import eu.m724.wtapi.provider.twilight.ApproximateTwilightTimeProvider;
|
import eu.m724.wtapi.provider.twilight.impl.approximate.ApproximateTwilightTimeProvider;
|
||||||
import eu.m724.wtapi.provider.twilight.TwilightTimeProvider;
|
import eu.m724.wtapi.provider.twilight.TwilightTimeProvider;
|
||||||
import eu.m724.wtapi.provider.weather.WeatherProvider;
|
import eu.m724.wtapi.provider.weather.WeatherProvider;
|
||||||
import eu.m724.wtapi.provider.weather.impl.openweathermap.OpenWeatherMapProvider;
|
import eu.m724.wtapi.provider.weather.impl.openweathermap.OpenWeatherMapProvider;
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package eu.m724.wtapi.provider.twilight;
|
||||||
|
|
||||||
|
import eu.m724.wtapi.object.Coordinates;
|
||||||
|
import eu.m724.wtapi.object.Twilight;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
// TODO reconsider if this is necessary and doesn't actually harm performance
|
||||||
|
/**
|
||||||
|
* A {@link TwilightTimeProvider} that can cache some calculations to be faster
|
||||||
|
*
|
||||||
|
* @param <T> An implementation of {@link TwilightTimeCache} where you store whatever you need
|
||||||
|
*/
|
||||||
|
public abstract class CacheableTwilightTimeProvider<T extends TwilightTimeCache> extends TwilightTimeProvider {
|
||||||
|
/**
|
||||||
|
* Calculates sunrise and sunset for provided coordinates
|
||||||
|
*
|
||||||
|
* @param cache {@link T}, implementation of {@link TwilightTimeCache}
|
||||||
|
* @param coordinates Coordinates of the observer
|
||||||
|
* @return {@link Twilight}
|
||||||
|
* @see #initializeCache(LocalDate)
|
||||||
|
*/
|
||||||
|
public abstract Twilight calculateTwilightTime(T cache, Coordinates coordinates);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes cache for provided date
|
||||||
|
*
|
||||||
|
* @param date The UTC date
|
||||||
|
* @return ready to use cache
|
||||||
|
*/
|
||||||
|
public abstract T initializeCache(LocalDate date);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Twilight calculateTwilightTime(LocalDate date, Coordinates coordinates) {
|
||||||
|
return calculateTwilightTime(
|
||||||
|
initializeCache(date),
|
||||||
|
coordinates
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
package eu.m724.wtapi.provider.twilight;
|
||||||
|
|
||||||
|
public interface TwilightTimeCache {
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package eu.m724.wtapi.provider.twilight.impl.approximate;
|
||||||
|
|
||||||
|
import eu.m724.wtapi.provider.twilight.TwilightTimeCache;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
public record ApproximateTwilightTimeCache(LocalDate date, double equationOfTime,
|
||||||
|
double declination) implements TwilightTimeCache {
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
package eu.m724.wtapi.provider.twilight;
|
package eu.m724.wtapi.provider.twilight.impl.approximate;
|
||||||
|
|
||||||
import eu.m724.wtapi.object.Coordinates;
|
import eu.m724.wtapi.object.Coordinates;
|
||||||
import eu.m724.wtapi.object.Twilight;
|
import eu.m724.wtapi.object.Twilight;
|
||||||
|
import eu.m724.wtapi.provider.twilight.CacheableTwilightTimeProvider;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
@ -9,13 +10,40 @@ import java.time.LocalDate;
|
||||||
import static java.lang.Math.*;
|
import static java.lang.Math.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates approximate sunrise and sunset times
|
* Calculates approximate sunrise and sunset times<br>
|
||||||
* Usually off by a few minutes, except the Poles which, during polar days, are up to few hours inaccurate
|
* Usually off by a few minutes, except the Poles which, during polar days, are up to few hours inaccurate<br>
|
||||||
* Adapted from: <a href="https://gml.noaa.gov/grad/solcalc/solareqns.PDF">https://gml.noaa.gov/grad/solcalc/solareqns.PDF</a>
|
* I don't know why, I just copied stuff and maybe transformed a bit, I don't actually understand the topic<br>
|
||||||
|
* Source: <a href="https://gml.noaa.gov/grad/solcalc/solareqns.PDF">https://gml.noaa.gov/grad/solcalc/solareqns.PDF</a>
|
||||||
*/
|
*/
|
||||||
public class ApproximateTwilightTimeProvider extends TwilightTimeProvider {
|
public class ApproximateTwilightTimeProvider extends CacheableTwilightTimeProvider<ApproximateTwilightTimeCache> {
|
||||||
@Override
|
@Override
|
||||||
public Twilight calculateTwilightTime(LocalDate date, Coordinates coordinates) {
|
public Twilight calculateTwilightTime(ApproximateTwilightTimeCache cache, Coordinates coordinates) {
|
||||||
|
double declination = cache.declination();
|
||||||
|
double equationOfTime = cache.equationOfTime();
|
||||||
|
|
||||||
|
double latRad = toRadians(coordinates.latitude);
|
||||||
|
// 90.833 deg = 1.5853349194640094 rad
|
||||||
|
double n1 = cos(1.5853349194640094) / (cos(latRad) * cos(declination));
|
||||||
|
double n2 = tan(latRad) * tan(declination);
|
||||||
|
double hourAngle = acos(n1 - n2);
|
||||||
|
|
||||||
|
double hourAngleDeg = 4 * toDegrees(hourAngle);
|
||||||
|
|
||||||
|
// sunrise = 720 - 4 * (coordinates.longitude + hourAngleDeg) - equationOfTime
|
||||||
|
// sunset = 720 - 4 * (coordinates.longitude - hourAngleDeg) - equationOfTime
|
||||||
|
double solarNoon = 720 - 4 * coordinates.longitude - equationOfTime;
|
||||||
|
double sunrise = solarNoon - hourAngleDeg;
|
||||||
|
double sunset = solarNoon + hourAngleDeg;
|
||||||
|
|
||||||
|
return new Twilight(
|
||||||
|
cache.date(),
|
||||||
|
Duration.ofMillis((long) (sunrise * 60000)),
|
||||||
|
Duration.ofMillis((long) (sunset * 60000))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApproximateTwilightTimeCache initializeCache(LocalDate date) {
|
||||||
int dayOfYear = date.getDayOfYear() - 1; // -1 because we have to start from zero
|
int dayOfYear = date.getDayOfYear() - 1; // -1 because we have to start from zero
|
||||||
// 2 * PI / 365 = 0.01721420632103996
|
// 2 * PI / 365 = 0.01721420632103996
|
||||||
double fractionalYear = 0.01721420632103996 * dayOfYear;
|
double fractionalYear = 0.01721420632103996 * dayOfYear;
|
||||||
|
@ -33,24 +61,10 @@ public class ApproximateTwilightTimeProvider extends TwilightTimeProvider {
|
||||||
- 0.002697 * cos(3 * fractionalYear)
|
- 0.002697 * cos(3 * fractionalYear)
|
||||||
+ 0.00148 * sin(3 * fractionalYear);
|
+ 0.00148 * sin(3 * fractionalYear);
|
||||||
|
|
||||||
double latRad = toRadians(coordinates.latitude);
|
return new ApproximateTwilightTimeCache(
|
||||||
// 90.833 deg = 1.5853349194640094 rad
|
|
||||||
double n1 = cos(1.5853349194640094) / (cos(latRad) * cos(declination));
|
|
||||||
double n2 = tan(latRad) * tan(declination);
|
|
||||||
double hourAngle = acos(n1 - n2);
|
|
||||||
|
|
||||||
double hourAngleDeg = 4 * toDegrees(hourAngle);
|
|
||||||
|
|
||||||
// sunrise = 720 - 4 * (coordinates.longitude + hourAngleDeg) - equationOfTime
|
|
||||||
// sunset = 720 - 4 * (coordinates.longitude - hourAngleDeg) - equationOfTime
|
|
||||||
double solarNoon = 720 - 4 * coordinates.longitude - equationOfTime;
|
|
||||||
double sunrise = solarNoon - hourAngleDeg;
|
|
||||||
double sunset = solarNoon + hourAngleDeg;
|
|
||||||
|
|
||||||
return new Twilight(
|
|
||||||
date,
|
date,
|
||||||
Duration.ofMillis((long) (sunrise * 60000)),
|
equationOfTime,
|
||||||
Duration.ofMillis((long) (sunset * 60000))
|
declination
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,12 +2,13 @@ package eu.m724.wtapi.twilight;
|
||||||
|
|
||||||
import eu.m724.wtapi.object.Coordinates;
|
import eu.m724.wtapi.object.Coordinates;
|
||||||
import eu.m724.wtapi.object.Twilight;
|
import eu.m724.wtapi.object.Twilight;
|
||||||
import eu.m724.wtapi.provider.twilight.ApproximateTwilightTimeProvider;
|
import eu.m724.wtapi.provider.twilight.impl.approximate.ApproximateTwilightTimeProvider;
|
||||||
import eu.m724.wtapi.provider.twilight.TwilightTimeProvider;
|
import eu.m724.wtapi.provider.twilight.TwilightTimeProvider;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
// TODO also test cached
|
||||||
public class ApproximateTwilightTimeTest {
|
public class ApproximateTwilightTimeTest {
|
||||||
/**
|
/**
|
||||||
* Acceptable discrepancy in minutes
|
* Acceptable discrepancy in minutes
|
||||||
|
|
Loading…
Reference in a new issue