From 94fced4af0782ad36b8ea948004549081039f97a Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 22 May 2020 23:58:42 +0200 Subject: [PATCH] Sunrise and set --- Moose Development/Moose/Core/Point.lua | 8 ++ Moose Development/Moose/Utilities/Utils.lua | 147 +++++++++++++++++++- 2 files changed, 154 insertions(+), 1 deletion(-) diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index 5139d50a2..bc5018a7b 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -2036,6 +2036,14 @@ do -- COORDINATE return "" end + --- Get Latitude and Longitude in Degree Minute Second. + -- @param #COORDINATE self + -- @return #number Latitude. + -- @return #number Lontitude. + function COORDINATE:GetLLDMS() + return coord.LOtoLL( self:GetVec3() ) + end + --- Provides a Lat Lon string in Degree Minute Second format. -- @param #COORDINATE self -- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object. diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index 5bba94cc1..3fc5b3f27 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -1004,11 +1004,14 @@ end --- Returns the mission date. This is the date the mission started. -- @return #string Mission date in yyyy/mm/dd format. +-- @return #number The year anno domini. +-- @return #number The month. +-- @return #number The day. function UTILS.GetDCSMissionDate() local year=tostring(env.mission.date.Year) local month=tostring(env.mission.date.Month) local day=tostring(env.mission.date.Day) - return string.format("%s/%s/%s", year, month, day) + return string.format("%s/%s/%s", year, month, day), year, month, day end @@ -1144,3 +1147,145 @@ function UTILS.GetCallsignName(Callsign) return "Ghostrider" end + + +--- Get sunrise or sun set of a specific day of the year at a specific location. +-- @param #number Day Day of the year. +-- @param #number Month Month of the year. +-- @param #number Year Year. +-- @param #number Latitude Latitude. +-- @param #number Longitude Longitude. +-- @param #boolean Rising If true, calc sun rise, or sun set otherwise. +-- @return #number Sun rise/set in seconds of the day. +function UTILS.GetSunRiseAndSet(Day, Month, Year, Latitude, Longitude, Rising) + + local date={} + date.day=Day + date.month=Month + date.year=Year + + local zenith=90.83 + local latitude=Latitude + local longitude=Longitude + local rising=Rising + + + local current_time = nil + local srs_args + local rad = math.rad + local deg = math.deg + local floor = math.floor + local frac = function(n) return n - floor(n) end + local cos = function(d) return math.cos(rad(d)) end + local acos = function(d) return deg(math.acos(d)) end + local sin = function(d) return math.sin(rad(d)) end + local asin = function(d) return deg(math.asin(d)) end + local tan = function(d) return math.tan(rad(d)) end + local atan = function(d) return deg(math.atan(d)) end + + local function fit_into_range(val, min, max) + local range = max - min + local count + if val < min then + count = floor((min - val) / range) + 1 + return val + count * range + elseif val >= max then + count = floor((val - max) / range) + 1 + return val - count * range + else + return val + end + end + + local function day_of_year(date) + local n1 = floor(275 * date.month / 9) + local n2 = floor((date.month + 9) / 12) + local n3 = (1 + floor((date.year - 4 * floor(date.year / 4) + 2) / 3)) + return n1 - (n2 * n3) + date.day - 30 + end + + local n = day_of_year(date) + + -- Convert the longitude to hour value and calculate an approximate time + local lng_hour = longitude / 15 + + local t + if rising then -- Rising time is desired + t = n + ((6 - lng_hour) / 24) + else -- Setting time is desired + t = n + ((18 - lng_hour) / 24) + end + + -- Calculate the Sun's mean anomaly + local M = (0.9856 * t) - 3.289 + + -- Calculate the Sun's true longitude + local L = fit_into_range(M + (1.916 * sin(M)) + (0.020 * sin(2 * M)) + 282.634, 0, 360) + + -- Calculate the Sun's right ascension + local RA = fit_into_range(atan(0.91764 * tan(L)), 0, 360) + + -- Right ascension value needs to be in the same quadrant as L + local Lquadrant = floor(L / 90) * 90 + local RAquadrant = floor(RA / 90) * 90 + RA = RA + Lquadrant - RAquadrant + + -- Right ascension value needs to be converted into hours + RA = RA / 15 + + -- Calculate the Sun's declination + local sinDec = 0.39782 * sin(L) + local cosDec = cos(asin(sinDec)) + + -- Calculate the Sun's local hour angle + local cosH = (cos(zenith) - (sinDec * sin(latitude))) / (cosDec * cos(latitude)) + + if rising and cosH > 1 then + return "N/R" -- The sun never rises on this location on the specified date + elseif cosH < -1 then + return "N/S" -- The sun never sets on this location on the specified date + end + + -- Finish calculating H and convert into hours + local H + if rising then + H = 360 - acos(cosH) + else + H = acos(cosH) + end + H = H / 15 + + -- Calculate local mean time of rising/setting + local T = H + RA - (0.06571 * t) - 6.622 + + print(T) + + -- Adjust back to UTC + local UT = fit_into_range(T - lng_hour, 0, 24) + + return floor(UT)*60*60+frac(UT)*60*60 + end + +--- Get sun rise of a specific day of the year at a specific location. +-- @param #number Day Day of the year. +-- @param #number Month Month of the year. +-- @param #number Year Year. +-- @param #number Latitude Latitude. +-- @param #number Longitude Longitude. +-- @param #boolean Rising If true, calc sun rise, or sun set otherwise. +-- @return #number Sun rise in seconds of the day. +function UTILS.GetSunrise(Day, Month, Year, Latitude, Longitude) + return UTILS.GetSunRiseAndSet(Day, Month, Year, Latitude, Longitude, true) +end + +--- Get sun set of a specific day of the year at a specific location. +-- @param #number Day Day of the year. +-- @param #number Month Month of the year. +-- @param #number Year Year. +-- @param #number Latitude Latitude. +-- @param #number Longitude Longitude. +-- @param #boolean Rising If true, calc sun rise, or sun set otherwise. +-- @return #number Sun rise in seconds of the day. +function UTILS.GetSunset(Day, Month, Year, Latitude, Longitude) + return UTILS.GetSunRiseAndSet(Day, Month, Year, Latitude, Longitude, false) +end \ No newline at end of file