Skip to content

Instantly share code, notes, and snippets.

@leebyron
Last active August 23, 2017 20:09
Show Gist options
  • Save leebyron/5678b01db7b28322f937 to your computer and use it in GitHub Desktop.
Save leebyron/5678b01db7b28322f937 to your computer and use it in GitHub Desktop.
Solar relative position math from Solar Calendar.
class Gradient2D{
PImage source;
Gradient2D(String src){
source = loadImage(src);
}
color get(float g1, float g2){
int x = constrain( floor( g1*source.width ), 0, source.width-1);
int y = constrain( floor( g2*source.height ), 0, source.height-1);
int p = x + y*source.width;
return source.pixels[p];
}
}
/**
* Does some crazy math and figures out all kinds of things about the sun
* Lee Byron - Dec 2006
*/
public class Sun{
final double K = PI/180;
double latitude, longitude;
Calendar calendar;
double hour;
double eqtime, time_offset, tst, ha;
double declin, Phi, Phi1, Theta, hars;
double sun_rise, sun_set, snoon;
Sun(double latitude, double longitude, Calendar calendar){
this.latitude = latitude;
this.longitude = longitude;
this.calendar = calendar;
}
void calculate(double hour){
this.hour = hour;
equationTime();
declination();
tzo();
solarTime();
hourAngle();
zenithAngle();
azimuthAngle();
hourAngleRiseSet();
RiseSet();
noon();
}
double getZenith(){
return Phi1;
}
// equation of time (in minutes)
private void equationTime(){
double x = calendar.get(Calendar.DAY_OF_YEAR)*TWO_PI/365;
eqtime = 229.18*(0.000075+0.001868*Math.cos(x)-0.032077*Math.sin(x)-0.014615*Math.cos(2*x)-0.040849*Math.sin(2*x));
}
// declination (in degrees)
private void declination(){
double x = calendar.get(Calendar.DAY_OF_YEAR)*TWO_PI/365; // fractional year in radians
declin = ( 0.006918 - 0.399912*Math.cos(x) + 0.070257*Math.sin(x) - 0.006758*Math.cos(2*x) + 0.000907*Math.sin(2*x) - 0.002697*Math.cos(3*x) + 0.00148*Math.sin(3*x) )*180/Math.PI;
}
// time offset (in minutes)
private void tzo(){
// we're using timezone offset minutes here
double offsetMinutes = (calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET))/60000;
time_offset = eqtime - 4*longitude + offsetMinutes;
}
// true solar time (in hours) // looks like minutes to me?
private void solarTime() {
tst = hour*60 - time_offset;
}
// solar hour angle (in degrees)
private void hourAngle() {
ha = tst/4 - 180;
}
// solar zenith angle (in degrees)
private void zenithAngle() {
Phi = Math.sin(K*latitude)*Math.sin(K*declin)+Math.cos(K*latitude)*Math.cos(K*declin)*Math.cos(K*ha);
Phi = Math.acos(Phi)/K;
Phi1 = 90-Phi; // altitude
}
// solar azimuth angle (in degrees, clockwise from north)
private void azimuthAngle() {
Theta = -(Math.sin(K*latitude)*Math.cos(K*Phi)-Math.sin(K*declin))/(Math.cos(K*latitude)*Math.sin(K*Phi));
Theta = Math.acos(Theta)/K;
if (ha<0) Theta=Theta;
else Theta=360-Theta;
}
// solar azimuth angle for sunrise and sunset corrected for atmospheric refraction (in degrees),
private void hourAngleRiseSet() {
hars = Math.cos(K*90.833)/(Math.cos(K*latitude)*Math.cos(K*declin)) - Math.tan(K*latitude)*Math.tan(K*declin);
hars = Math.acos(hars)/K;
}
// sunrise and sunset (local time)
private void RiseSet() {
// we're using timezone offset hours here
double offsetHours = (calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET))/3600000;
sun_rise = 720 + 4*(longitude-hars) - eqtime;
sun_rise = sun_rise/60 - offsetHours;
sun_set = 720 + 4*(longitude+hars) - eqtime;
sun_set = sun_set/60 - offsetHours;
}
// solar noon (local time)
private void noon() {
// we're using timezone offset hours here
double offsetHours = (calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET))/3600000;
snoon = 720 + 4*longitude - eqtime;
snoon = snoon/60 - offsetHours;
}
}
@jpmg90
Copy link

jpmg90 commented Aug 23, 2017

With this code I'm unable to properly get the Sun_rise/Sun_Set using your RiseSet() function. Based on calculations here you seem to be mixing up the +'s and -'s during the calculations

I use the following and I'm able to get within 1.5 minutes of the sun rise/set:

sun_rise = 720 - 4 * (longitude + hars) - eqtime;
sun_rise = sun_rise / 60 + offsetHours;
sun_set = 720 - 4 * (longitude - hars) - eqtime;
sun_set = sun_set / 60 + offsetHours;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment