【问题标题】:Position of the Sun (azimuth) in Lua太阳在 Lua 中的位置(方位角)
【发布时间】:2016-02-17 20:42:23
【问题描述】:

在 LUA 中我只能在网上找到一个函数,但它给出了错误的值(使用专业的在线工具测量)。

似乎从日出到中午之后的某个时间,数学是有效的,但是之后,太阳的角度又回到了日出位置。应该是从 106° 到 253°,目前是从 106° 到 ~180° 到 106°。

我正在使用的功能:

-- solar altitude, azimuth (degrees)
function sunposition(latitude, longitude, time)
    time = time or os.time()
    if type(time) == 'table' then time = os.time(time) end

    local date = os.date('*t', time)
    local timezone = (os.time(date) - os.time(os.date('!*t', time))) / 3600
    if date.isdst then timezone = timezone + 1 end

    local utcdate = os.date('*t', time - timezone * 3600)
    local latrad = math.rad(latitude)
    local fd = (utcdate.hour + utcdate.min / 60 + utcdate.sec / 3600) / 24
    local g = (2 * math.pi / 365.25) * (utcdate.yday + fd)
    local d = math.rad(0.396372 - 22.91327 * math.cos(g) + 4.02543 * math.sin(g) - 0.387205 * math.cos(2 * g)
      + 0.051967 * math.sin(2 * g) - 0.154527 * math.cos(3 * g) + 0.084798 * math.sin(3 * g))
    local t = math.rad(0.004297 + 0.107029 * math.cos(g) - 1.837877 * math.sin(g)
      - 0.837378 * math.cos(2 * g) - 2.340475 * math.sin(2 * g))
    local sha = 2 * math.pi * (fd - 0.5) + t + math.rad(longitude)

    local sza = math.acos(math.sin(latrad) * math.sin(d) + math.cos(latrad) * math.cos(d) * math.cos(sha))
    local saa = math.acos((math.sin(d) - math.sin(latrad) * math.cos(sza)) / (math.cos(latrad) * math.sin(sza)))

    return 90 - math.deg(sza), math.deg(saa)
end

示例请求:

lat, long = 45.327063, 14.442176 -- Rijeka, Croatia
time = {year=2016, month=2, day=17, hour=17, min=30} -- end of the day
altitude, azimuth = sunposition(lat, long, time)

结果是:

  • -0.1 度高度
  • 106 度方位角。

结果应该是:

  • -0.1 度高度
  • 253 度方位角。

我在其他编程语言中找到了多种解决方案,甚至尝试用 Lua 重写但没有任何成功。解决方案背后的数学太复杂了。

我将它用于我的 Corona SDK 应用程序,该应用程序将显示太阳相对于设备的位置。目前唯一可行的解​​决方案是我的应用程序可以通过 Internet 上的 API 调用询问的 PHP 或 Javascript 脚本,但我真的很想避免这种情况。

我非常感谢社区提供的任何帮助。谢谢你们,爱你们! :)

【问题讨论】:

    标签: lua sdk coronasdk sun azimuth


    【解决方案1】:

    我找到了解决此问题的方法/hack。

    功能还是一样的:

    -- solar altitude, azimuth (degrees)
    function sunposition(latitude, longitude, time)
        time = time or os.time()
        if type(time) == 'table' then time = os.time(time) end
    
        local date = os.date('*t', time)
        local timezone = (os.time(date) - os.time(os.date('!*t', time))) / 3600
        if date.isdst then timezone = timezone + 1 end
    
        local utcdate = os.date('*t', time - timezone * 3600)
        local latrad = math.rad(latitude)
        local fd = (utcdate.hour + utcdate.min / 60 + utcdate.sec / 3600) / 24
        local g = (2 * math.pi / 365.25) * (utcdate.yday + fd)
        local d = math.rad(0.396372 - 22.91327 * math.cos(g) + 4.02543 * math.sin(g) - 0.387205 * math.cos(2 * g)
          + 0.051967 * math.sin(2 * g) - 0.154527 * math.cos(3 * g) + 0.084798 * math.sin(3 * g))
        local t = math.rad(0.004297 + 0.107029 * math.cos(g) - 1.837877 * math.sin(g)
          - 0.837378 * math.cos(2 * g) - 2.340475 * math.sin(2 * g))
        local sha = 2 * math.pi * (fd - 0.5) + t + math.rad(longitude)
    
        local sza = math.acos(math.sin(latrad) * math.sin(d) + math.cos(latrad) * math.cos(d) * math.cos(sha))
        local saa = math.acos((math.sin(d) - math.sin(latrad) * math.cos(sza)) / (math.cos(latrad) * math.sin(sza)))
    
        return 90 - math.deg(sza), math.deg(saa)
    end
    

    解决问题的添加代码:

    function getSunPos(lat, long, time)
        findTime = {}
        findTime.hour, findTime.min = time.hour, time.min
        fixedAzimuthLast, fixedAzimuth = 0, 0
        for i=0,23 do
            for j=0,59 do
                time.hour, time.min = i, j
                local altitude, azimuth = sunposition(lat, long, time)
                -- fix azimuth
                if fixedAzimuthLast < azimuth then 
                    fixedAzimuthLast = azimuth
                    fixedAzimuth = fixedAzimuthLast
                else
                    fixedAzimuth = fixedAzimuthLast + (180 - azimuth)
                end
                -- find azimuth at target time
                if findTime.hour == i and findTime.min == j then
                    -- final result
                    return altitude, fixedAzimuth
                end
            end
        end
    end
    

    最后得到正确的结果:

    lat, long = 45.327063, 14.442176
    altitude, azimuth = getSunPos(lat, long, os.date('*t', os.time()))
    

    就是这样。 我会对正确进行数学运算的完整函数感到满意,但这就足够了。它可以工作并在全球 3 个地点进行了测试。

    【讨论】:

      【解决方案2】:

      角度的 Arccos 等于 360 度角,因为它们的余弦值相等。您可以简单地返回 360 度。

      【讨论】:

      • 这仅适用于通过查看太阳高度手动找到日落位置的算法,并且由于高度工作正常,它帮助我在提交的答案中找到了解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-08
      • 1970-01-01
      • 2013-02-09
      • 2012-12-22
      • 1970-01-01
      • 1970-01-01
      • 2019-04-22
      相关资源
      最近更新 更多