Fabiz / MeeusJs

MeeusJs is an implementation of some algorithms of the Book 'Astronomical Algorithms of Jean Meeus' in Javascript.
MIT License
84 stars 16 forks source link

Calculating when the sun is at a specific angle? #13

Open mennyg opened 4 years ago

mennyg commented 4 years ago

Need this to calculate certain times even before sunrise. When is the sun X degrees below/above the horizon? Suncalc has a function called addtimes() that takes an angle as a parameter and returns a time, but suncalc is returning very inaccurate times, and I want to use MeeusJs

jumpjack commented 1 year ago

I am using this function to calculate sun position at given time:

function suncalcMeeus(myDateJS, lat, lon, height) {
// gets sun position and times 
  var jdo = new A.JulianDay(myDateJS); 
  var coord = A.EclCoord.fromWgs84(lat, lon, height);

  // gets the position of the sun
  var tp = A.Solar.topocentricPosition(jdo, coord, true);
  var altRad = tp.hz.alt;
  var altDeg = altRad * 180 / Math.PI;
  var azRad = tp.hz.az;
  var azDeg = azRad * 180 / Math.PI;
  var distKm =  tp.delta; // debug

  if (azRad < 0) {
     azRad = Math.PI + azRad;
     azDeg = 180.0 + azDeg;
  }
  // gets the rise, transit and set time of the sun
  var times = A.Solar.times(jdo, coord);

  return {
    sunAzimuthRad : azRad,
    sunAltitudeRad : altRad,
    sunAzimuthDegrees : azDeg,
    sunAltitudeDegrees : altDeg,
    rise : A.Coord.secondsToHMSStr(times.rise),
    riseJS : new Date(myDateJS.getFullYear() + "-" + (myDateJS.getMonth()+1) + "-" + myDateJS.getDate() + " "  + A.Coord.secondsToHMSStr(times.rise)),
    transit : A.Coord.secondsToHMSStr(times.transit) ,
    transitJS : new Date(myDateJS.getFullYear() + "-" + (myDateJS.getMonth()+1) + "-" + myDateJS.getDate() + " "  + A.Coord.secondsToHMSStr(times.transit)),
    set: A.Coord.secondsToHMSStr(times.set),
    setJS : new Date(myDateJS.getFullYear() + "-" + (myDateJS.getMonth()+1) + "-" + myDateJS.getDate() + " "  + A.Coord.secondsToHMSStr(times.set)),
  }
}

You can iterate throuogh myDateJS while monitoring for elevation value, for example:

function elevThreshold(THRESHOLD, d) { 
 var tempResults = []; 
 baseDateJS = new Date(d)
 for (var m=0; m < 1440; m++) { 
   myDateJS = new Date(baseDateJS.getTime() + m * 60000);
   res = suncalcMeeus(myDateJS, 42,12,0);
   if (res.sunAltitudeDegrees <= THRESHOLD) {
     tempResults.push("Time: "+ myDateJS.getHours() + ":" + myDateJS.getMinutes() + ", Elevation: "+ res.sunAltitudeDegrees)
   }
 }
 return { all: tempResults, first: tempResults[0], last: tempResults[tempResults.length-1]} 
}

Call:

elevThreshold(-10, "2023-03-01 12:00:00Z");

Result:

first: "Time: 18:55, Elevation: -10.119625318268696" ​ last: "Time: 5:53, Elevation: -10.105459335822681"