Compare commits
No commits in common. "6d38604507edf512924706454c52b0563fc75cb6" and "9ecaefc708a5a41c244c08c5ef9f2fef0109f4a5" have entirely different histories.
6d38604507
...
9ecaefc708
4 changed files with 26 additions and 59 deletions
|
@ -8,20 +8,9 @@ import java.time.LocalDateTime;
|
||||||
* @param date The date this object contains times for
|
* @param date The date this object contains times for
|
||||||
* @param sunrise Time of sunrise
|
* @param sunrise Time of sunrise
|
||||||
* @param sunset Time of sunset
|
* @param sunset Time of sunset
|
||||||
* @param solarNoon Time of solar noon in the current day.<br>
|
|
||||||
* If polar night, the solar noon still applies, because the sun still exists, but doesn't rise above the horizon.
|
|
||||||
* @param polar Is polar cycle
|
|
||||||
*/
|
*/
|
||||||
public record Twilight(LocalDate date, LocalDateTime sunrise, LocalDateTime sunset, LocalDateTime solarNoon, boolean polar) {
|
public record Twilight(LocalDate date, LocalDateTime sunrise, LocalDateTime sunset) {
|
||||||
public Duration getDayLength() {
|
public Duration getDayLength() {
|
||||||
return Duration.between(sunrise, sunset);
|
return Duration.between(sunrise, sunset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPolarNight() {
|
|
||||||
return polar && Duration.between(sunrise, sunset).isNegative();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isPolarDay() {
|
|
||||||
return polar && !isPolarNight();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import eu.m724.wtapi.object.Twilight;
|
||||||
import eu.m724.wtapi.provider.twilight.CacheableTwilightTimeProvider;
|
import eu.m724.wtapi.provider.twilight.CacheableTwilightTimeProvider;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
import static java.lang.Math.*;
|
import static java.lang.Math.*;
|
||||||
|
|
||||||
|
@ -22,14 +21,10 @@ public class ApproximateTwilightTimeProvider extends CacheableTwilightTimeProvid
|
||||||
double equationOfTime = cache.equationOfTime();
|
double equationOfTime = cache.equationOfTime();
|
||||||
|
|
||||||
double latRad = toRadians(coordinates.latitude);
|
double latRad = toRadians(coordinates.latitude);
|
||||||
double solarNoon = 720 - 4 * coordinates.longitude - equationOfTime;
|
double hourAngle = hourAngle(latRad, declination);
|
||||||
LocalDateTime solarNoonDateTime = cache.date().atStartOfDay().plusSeconds((long) (solarNoon * 60));
|
System.out.println(hourAngle);
|
||||||
|
|
||||||
// 90.833 deg = 1.5853349194640094 rad
|
if (Double.isNaN(hourAngle)) {
|
||||||
double n1 = cos(1.5853349194640094) / (cos(latRad) * cos(declination));
|
|
||||||
n1 -= tan(latRad) * tan(declination);
|
|
||||||
|
|
||||||
if (n1 < -1) { // polar day
|
|
||||||
LocalDate sunriseDate = step(cache.date().minusDays(1), latRad, -1);
|
LocalDate sunriseDate = step(cache.date().minusDays(1), latRad, -1);
|
||||||
LocalDate sunsetDate = step(cache.date().plusDays(1), latRad, 1);
|
LocalDate sunsetDate = step(cache.date().plusDays(1), latRad, 1);
|
||||||
|
|
||||||
|
@ -39,57 +34,46 @@ public class ApproximateTwilightTimeProvider extends CacheableTwilightTimeProvid
|
||||||
return new Twilight(
|
return new Twilight(
|
||||||
cache.date(),
|
cache.date(),
|
||||||
backwardTwilight.sunrise(),
|
backwardTwilight.sunrise(),
|
||||||
forwardTwilight.sunset(),
|
forwardTwilight.sunset()
|
||||||
solarNoonDateTime,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
} else if (n1 > 1) { // polar night
|
|
||||||
LocalDate sunriseDate = step(cache.date().plusDays(1), latRad, 1);
|
|
||||||
LocalDate sunsetDate = step(cache.date().minusDays(1), latRad, -1);
|
|
||||||
|
|
||||||
Twilight backwardTwilight = calculateTwilightTime(sunriseDate, coordinates);
|
|
||||||
Twilight forwardTwilight = calculateTwilightTime(sunsetDate, coordinates);
|
|
||||||
|
|
||||||
return new Twilight(
|
|
||||||
cache.date(),
|
|
||||||
backwardTwilight.sunrise(),
|
|
||||||
forwardTwilight.sunset(),
|
|
||||||
solarNoonDateTime,
|
|
||||||
true
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double hourAngle = acos(n1);
|
|
||||||
double longitudeEffect = 4 * toDegrees(hourAngle);
|
double longitudeEffect = 4 * toDegrees(hourAngle);
|
||||||
|
|
||||||
// sunrise = 720 - 4 * (coordinates.longitude + hourAngleDeg) - equationOfTime
|
// sunrise = 720 - 4 * (coordinates.longitude + hourAngleDeg) - equationOfTime
|
||||||
// sunset = 720 - 4 * (coordinates.longitude - hourAngleDeg) - equationOfTime
|
// sunset = 720 - 4 * (coordinates.longitude - hourAngleDeg) - equationOfTime
|
||||||
|
double solarNoon = 720 - 4 * coordinates.longitude - equationOfTime;
|
||||||
double sunrise = solarNoon - longitudeEffect;
|
double sunrise = solarNoon - longitudeEffect;
|
||||||
double sunset = solarNoon + longitudeEffect;
|
double sunset = solarNoon + longitudeEffect;
|
||||||
|
|
||||||
return new Twilight(
|
return new Twilight(
|
||||||
cache.date(),
|
cache.date(),
|
||||||
cache.date().atStartOfDay().plusMinutes((long) sunrise),
|
cache.date().atStartOfDay().plusMinutes((long) sunrise),
|
||||||
cache.date().atStartOfDay().plusMinutes((long) sunset),
|
cache.date().atStartOfDay().plusMinutes((long) sunset)
|
||||||
solarNoonDateTime,
|
|
||||||
false
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalDate step(LocalDate date, double latRad, int direction) {
|
private LocalDate step(LocalDate date, double latRad, int direction) {
|
||||||
double declination = getDeclination(getFractionalYear(date));
|
double declination = getDeclination(getFractionalYear(date));
|
||||||
|
|
||||||
//System.out.println("Step date: " + date);
|
System.out.println("Step date: " + date);
|
||||||
double n1 = cos(1.5853349194640094) / (cos(latRad) * cos(declination));
|
double hourAngle = hourAngle(latRad, declination);
|
||||||
n1 -= tan(latRad) * tan(declination);
|
if (Double.isNaN(hourAngle)) {
|
||||||
if (n1 < -1 || n1 > 1) {
|
|
||||||
return step(date.plusDays(direction), latRad, direction);
|
return step(date.plusDays(direction), latRad, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
//System.out.println("this the one");
|
System.out.println("this the one");
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double hourAngle(double latRad, double declination) {
|
||||||
|
// 90.833 deg = 1.5853349194640094 rad
|
||||||
|
double n1 = cos(1.5853349194640094) / (cos(latRad) * cos(declination));
|
||||||
|
double n2 = tan(latRad) * tan(declination);
|
||||||
|
System.out.println(n1 - n2);
|
||||||
|
return acos(n1 - n2);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApproximateTwilightTimeCache initializeCache(LocalDate date) {
|
public ApproximateTwilightTimeCache initializeCache(LocalDate date) {
|
||||||
double fractionalYear = getFractionalYear(date);
|
double fractionalYear = getFractionalYear(date);
|
||||||
|
|
|
@ -23,24 +23,22 @@ public class ApproximateTwilightTimeTest {
|
||||||
TwilightTimeProvider provider = new ApproximateTwilightTimeProvider();
|
TwilightTimeProvider provider = new ApproximateTwilightTimeProvider();
|
||||||
|
|
||||||
// used https://gml.noaa.gov/grad/solcalc/index.html for reference values
|
// used https://gml.noaa.gov/grad/solcalc/index.html for reference values
|
||||||
testLocation(provider, 26, 6, 2023, 53.123394, 23.0864867, LocalDateTime.of(2023, 6, 26, 2, 2), LocalDateTime.of(2023, 6, 26, 18, 59), 0);
|
testLocation(provider, 26, 6, 2023, 53.123394, 23.0864867, LocalDateTime.of(2023, 6, 26, 2, 2), LocalDateTime.of(2023, 6, 26, 18, 59));
|
||||||
testLocation(provider, 13, 11, 2040, 45.432427, -122.3899276, LocalDateTime.of(2040, 11, 13, 15, 7), LocalDateTime.of(2040, 11, 14, 0, 41), 0);
|
testLocation(provider, 13, 11, 2040, 45.432427, -122.3899276, LocalDateTime.of(2040, 11, 13, 15, 7), LocalDateTime.of(2040, 11, 14, 0, 41));
|
||||||
testLocation(provider, 23, 3, 2021, 55.5024161, 9.6801853, LocalDateTime.of(2021, 3, 23, 5, 15), LocalDateTime.of(2021, 3, 23, 17, 41), 0);
|
testLocation(provider, 23, 3, 2021, 55.5024161, 9.6801853, LocalDateTime.of(2021, 3, 23, 5, 15), LocalDateTime.of(2021, 3, 23, 17, 41));
|
||||||
testLocation(provider, 6, 8,1990, -72.012117, 2.5240873, LocalDateTime.of(1990, 8, 6, 10, 0), LocalDateTime.of(1990, 8, 6, 13, 52),0);
|
testLocation(provider, 6, 8,1990, -72.012117, 2.5240873, LocalDateTime.of(1990, 8, 6, 10, 0), LocalDateTime.of(1990, 8, 6, 13, 52));
|
||||||
// TODO this is broken (very inaccurate) so fix
|
// TODO this is broken (very inaccurate) so fix
|
||||||
ACCEPTABLE_DIFFERENCE = 172800; // 2 days
|
ACCEPTABLE_DIFFERENCE = 172800; // 2 days
|
||||||
testLocation(provider, 5, 9,2021, 82.498665, -62.3458366, LocalDateTime.of(2021, 4, 5, 20, 55), LocalDateTime.of(2021, 9, 6, 18, 22), 1); // the reference values might be incorrect
|
testLocation(provider, 5, 9,2021, 82.498665, -62.3458366, LocalDateTime.of(2021, 4, 5, 20, 55), LocalDateTime.of(2021, 9, 6, 18, 22)); // the reference values might be incorrect
|
||||||
testLocation(provider, 3, 2,2021, 82.498665, -62.3458366, LocalDateTime.of(2021, 2, 27, 7, 24), LocalDateTime.of(2020, 10, 13, 8, 46), -1); // the reference values might be incorrect
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testLocation(TwilightTimeProvider provider, int day, int month, int year, double latitude, double longitude, LocalDateTime actualSunrise, LocalDateTime actualSunset, int polar) {
|
private void testLocation(TwilightTimeProvider provider, int day, int month, int year, double latitude, double longitude, LocalDateTime actualSunrise, LocalDateTime actualSunset) {
|
||||||
LocalDate date = LocalDate.of(year, month, day);
|
LocalDate date = LocalDate.of(year, month, day);
|
||||||
Coordinates coordinates = new Coordinates(latitude, longitude);
|
Coordinates coordinates = new Coordinates(latitude, longitude);
|
||||||
|
|
||||||
Twilight twilight = provider.calculateTwilightTime(date, coordinates);
|
Twilight twilight = provider.calculateTwilightTime(date, coordinates);
|
||||||
System.out.println(date);
|
System.out.println(date);
|
||||||
System.out.println(coordinates.latitude + " " + coordinates.longitude);
|
System.out.println(coordinates.latitude + " " + coordinates.longitude);
|
||||||
System.out.println("Solar noon: " + twilight.solarNoon());
|
|
||||||
|
|
||||||
System.out.println("Calculated sunrise: " + twilight.sunrise());
|
System.out.println("Calculated sunrise: " + twilight.sunrise());
|
||||||
System.out.println("Actual sunrise: " + actualSunrise);
|
System.out.println("Actual sunrise: " + actualSunrise);
|
||||||
|
@ -50,8 +48,6 @@ public class ApproximateTwilightTimeTest {
|
||||||
System.out.println("Actual sunset: " + actualSunset);
|
System.out.println("Actual sunset: " + actualSunset);
|
||||||
assert Duration.between(twilight.sunset(), actualSunset).abs().getSeconds() < ACCEPTABLE_DIFFERENCE;
|
assert Duration.between(twilight.sunset(), actualSunset).abs().getSeconds() < ACCEPTABLE_DIFFERENCE;
|
||||||
|
|
||||||
assert polar == (twilight.isPolarDay() ? 1 : twilight.isPolarNight() ? -1 : 0);
|
|
||||||
|
|
||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,7 @@ public class MockTwilightTimeProvider extends TwilightTimeProvider {
|
||||||
return new Twilight(
|
return new Twilight(
|
||||||
date,
|
date,
|
||||||
date.atStartOfDay().plusSeconds(-time),
|
date.atStartOfDay().plusSeconds(-time),
|
||||||
date.atStartOfDay().plusSeconds(time),
|
date.atStartOfDay().plusSeconds(time)
|
||||||
date.atStartOfDay().plusMinutes(62),
|
|
||||||
false
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue