This is strange or I’m missing something. The code is working, the calculations are right (about sun position using current date/time and latitude and longitude values) the relevant variables are updating quickly (hopefully every few milliseconds) in the functions (I can see this using the console) but in the draw() loop the final calculation (and even the initial timer) is just stalled.
Any ideas? This is driving me nuts.
Edit: This should behave like another script I just did in javascript at https://bit.ly/2YQS33z --just two numbers updating every few milliseconds. Same calculation. JS source available with view source, using an old js library -suncalc.js --the calculations are somewhat equivalent, the main problem is the values won’t change quickly in the draw loop, something related to the double/float conversion of some values, as @William3954 pointed out. The problem here is that floats lost floating point precision (something crucial here) but in some cases I can’t pass double values to functions. Thanks a lot for any help!
import java.util.*;
double dayMs = 1000 * 60 * 60 * 24;
float J1970 = 2440588;
float J2000 = 2451545;
float lat = 4.596674;
float lng = -74.06525;
DoubleDict sp = new DoubleDict();
void setup() {
frameRate(300);
size(400,300);
fill(250); color (250);
}
void draw(){
background(0);
sp = sunPosition (lat, lng);
float alt = degrees((float) sp.get("altitude"));
float azt = degrees((float) sp.get("azimuth")+3.141516);
// println("alt", alt);
// println("azt", azt);
text(nf((float) toDays(),2,10),10,20);
text(nf(alt,2,10),10,50);
text(nf(azt,3,10),10,80);
}
// shortcuts for easier to read formulas
// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas
double toJulian() { return System.currentTimeMillis() / dayMs - 0.5 + J1970; }
// float fromJulian(float j) { return new Date((j + 0.5 - J1970) * dayMs); }
double toDays() { return toJulian() - J2000; }
// general calculations for position
float rad = PI / 180;
float e = rad * 23.4397; // obliquity of the Earth
float rightAscension(float l, float b) { return atan2(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); }
float declination(float l, float b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); }
float azimuth(float H, float phi, float dec) { return atan2(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); }
float altitude(float H, float phi, float dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); }
float siderealTime(double d, float lw) { return rad * (280.16 + 360.9856235 * (float) d) - lw; }
float astroRefraction(float h) {
if (h < 0) // the following formula works for positive altitudes only.
h = 0; // if h = -0.08901179 a div/0 would occur.
// formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998.
// 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad:
return 0.0002967 / tan(h + 0.00312536 / (h + 0.08901179));
}
// general sun calculations
float solarMeanAnomaly(double d) { return rad * (357.5291 + 0.98560028 * (float) d); }
float eclipticLongitude(float M) {
float C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)); // equation of center
float P = rad * 102.9372; // perihelion of the Earth
return M + C + P + PI;
}
FloatDict sunCoords(double d) {
FloatDict suncoords = new FloatDict();
float M = solarMeanAnomaly(d);
float L = eclipticLongitude(M);
suncoords.add("dec", declination(L, 0));
suncoords.add("ra", rightAscension(L, 0));
return suncoords;
}
// calculates sun position for a given date and latitude/longitude
DoubleDict sunPosition (float lat, float lng) {
DoubleDict sunpos = new DoubleDict();
float lw = rad * -lng;
float phi = rad * lat;
double d = toDays();
println(d);
FloatDict c = sunCoords(d);
float H = siderealTime(d, lw) - c.get("ra");
sunpos.set("azimuth", azimuth(H, phi, c.get("dec")));
sunpos.set("altitude", altitude(H, phi, c.get("dec")));
// conversion error
println("double: " + (double) toDays());
println("float: " + (float) toDays());
println("float to double" + nf((float) toDays(), 2, 10));
return sunpos;
}