python:SunMoonTimeCalculator

news2024/11/15 15:40:31
# encoding: utf-8
# 版权所有 2024 ©涂聚文有限公司
# 许可信息查看:
# 描述: https://github.com/Broham/suncalcPy
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# Datetime  : 2024/5/14 21:59
# User      : geovindu
# Product   : PyCharm
# Project   : EssentialAlgorithms
# File      : sunCalc.py
# explain   : 学习

import math
from datetime import datetime, timedelta
import time
import calendar

class SunMoonTimeCalculator(object):
    """
    日出日落,月升月落计算类

    """


    def __init__(self):
        """

        """
        self.PI = 3.141592653589793  # math.pi
        """
        派
        """
        self.sin = math.sin
        """
        sin 函数
        """
        self.cos = math.cos
        """
        函数
        """
        self.tan = math.tan
        """
        函数
        """
        self.asin = math.asin
        """
        函数
        """
        self.atan = math.atan2
        """
        函数
        """
        self.acos = math.acos
        """
        函数
        """
        self.rad = self.PI / 180.0
        self.e = self.rad * 23.4397  # obliquity of the Earth

        self.dayMs = 1000 * 60 * 60 * 24
        self.J1970 = 2440588
        self.J2000 = 2451545
        self.J0 = 0.0009

        self.times = [
            [-0.833, 'sunrise', 'sunset'],
            [-0.3, 'sunriseEnd', 'sunsetStart'],
            [-6, 'dawn', 'dusk'],
            [-12, 'nauticalDawn', 'nauticalDusk'],
            [-18, 'nightEnd', 'night'],
            [6, 'goldenHourEnd', 'goldenHour']
        ]


    def rightAscension(self,l, b):
        """

        :param l:
        :param b:
        :return:
        """
        return self.atan(self.sin(l) * self.cos(self.e) - self.tan(b) * self.sin(self.e), self.cos(l))


    def declination(self,l, b):
        """

        :param l:
        :param b:
        :return:
        """
        return self.asin(self.sin(b) * self.cos(self.e) + self.cos(b) * self.sin(self.e) * self.sin(l))


    def azimuth(self,H, phi, dec):
        """

        :param H:
        :param phi:
        :param dec:
        :return:
        """
        return self.atan(self.sin(H), self.cos(H) * self.sin(phi) - self.tan(dec) * self.cos(phi))


    def altitude(self,H, phi, dec):
        """

        :param H:
        :param phi:
        :param dec:
        :return:
        """
        return self.asin(self.sin(phi) * self.sin(dec) + self.cos(phi) * self.cos(dec) * self.cos(H))


    def siderealTime(self,d, lw):
        """

        :param d:
        :param lw:
        :return:
        """
        return self.rad * (280.16 + 360.9856235 * d) - lw


    def toJulian(self,date):
        """

        :param date:
        :return:
        """
        return (time.mktime(date.timetuple()) * 1000) / self.dayMs - 0.5 + self.J1970


    def fromJulian(self,j):
        """

        :param j:
        :return:
        """
        return datetime.fromtimestamp(((j + 0.5 - self.J1970) * self.dayMs) / 1000.0)


    def toDays(self,date):
        """

        :param date:
        :return:
        """
        return self.toJulian(date) - self.J2000


    def julianCycle(self,d, lw):
        """

        :param d:
        :param lw:
        :return:
        """
        return round(d - self.J0 - lw / (2 * self.PI))


    def approxTransit(self,Ht, lw, n):
        """

        :param Ht:
        :param lw:
        :param n:
        :return:
        """
        return self.J0 + (Ht + lw) / (2 * self.PI) + n


    def solarTransitJ(self,ds, M, L):
        """

        :param ds:
        :param M:
        :param L:
        :return:
        """
        return self.J2000 + ds + 0.0053 * self.sin(M) - 0.0069 * self.sin(2 * L)


    def hourAngle(self,h, phi, d):
        """

        :param h:
        :param phi:
        :param d:
        :return:
        """
        try:
            ret = self.acos((self.sin(h) - self.sin(phi) * self.sin(d)) / (self.cos(phi) * self.cos(d)))
            return ret
        except ValueError as e:
            print(h, phi, d, "=>", e)


    def observerAngle(self,height):
        """

        :param height:
        :return:
        """
        return -2.076 * math.sqrt(height) / 60


    def solarMeanAnomaly(self,d):
        """

        :param d:
        :return:
        """
        return self.rad * (357.5291 + 0.98560028 * d)


    def eclipticLongitude(self,M):
        """

        :param M:
        :return:
        """
        C = self.rad * (1.9148 * self.sin(M) + 0.02 * self.sin(2 * M) + 0.0003 * self.sin(3 * M))  # equation of center
        P = self.rad * 102.9372  # perihelion of the Earth
        return M + C + P + self.PI


    def sunCoords(self,d):
        """

        :param d:
        :return:
        """
        M = self.solarMeanAnomaly(d)
        L = self.eclipticLongitude(M)
        return dict(
            dec=self.declination(L, 0),
            ra=self.rightAscension(L, 0)
        )


    def getSetJ(self,h, lw, phi, dec, n, M, L):
        """

        :param h:
        :param lw:
        :param phi:
        :param dec:
        :param n:
        :param M:
        :param L:
        :return:
        """
        w = self.hourAngle(h, phi, dec)
        a = self.approxTransit(w, lw, n)
        return self.solarTransitJ(a, M, L)



    def moonCoords(self,d):
        """
        geocentric ecliptic coordinates of the moon
        :param d:
        :return:
        """
        L = self.rad * (218.316 + 13.176396 * d)
        M = self.rad * (134.963 + 13.064993 * d)
        F = self.rad * (93.272 + 13.229350 * d)

        l = L + self.rad * 6.289 * self.sin(M)
        b = self.rad * 5.128 * self.sin(F)
        dt = 385001 - 20905 * self.cos(M)

        return dict(
            ra=self.rightAscension(l, b),
            dec=self.declination(l, b),
            dist=dt
        )


    def getMoonIllumination(self,date):
        """
        Gets illumination properties of the moon for the given time.
        :param date:
        :return:
        """
        d = self.toDays(date)
        s = self.sunCoords(d)
        m = self.moonCoords(d)

        # distance from Earth to Sun in km
        sdist = 149598000
        phi = self.acos(self.sin(s["dec"]) * self.sin(m["dec"]) + self.cos(s["dec"]) * self.cos(m["dec"]) * self.cos(s["ra"] - m["ra"]))
        inc = self.atan(sdist * self.sin(phi), m["dist"] - sdist * self.cos(phi))
        angle = self.atan(self.cos(s["dec"]) * self.sin(s["ra"] - m["ra"]),
                     self.sin(s["dec"]) * self.cos(m["dec"]) - self.cos(s["dec"]) * self.sin(m["dec"]) * self.cos(s["ra"] - m["ra"]))

        return dict(
            fraction=(1 + self.cos(inc)) / 2,
            phase=0.5 + 0.5 * inc * (-1 if angle < 0 else 1) / self.PI,
            angle=angle
        )


    def getSunrise(self,date, lat, lng):
        """

        :param lat:
        :param lng:
        :return:
        """
        ret = self.getTimes(date, lat, lng)
        return ret["sunrise"]


    def getTimes(self,date, lat, lng, height=0):
        """
        Gets sun rise/set properties for the given time, location and height.
        :param date:
        :param lat:
        :param lng:
        :param height:
        :return:
        """
        lw = self.rad * -lng
        phi = self.rad * lat

        dh = self.observerAngle(height)

        d = self.toDays(date)
        n = self.julianCycle(d, lw)
        ds = self.approxTransit(0, lw, n)

        M = self.solarMeanAnomaly(ds)
        L = self.eclipticLongitude(M)
        dec = self.declination(L, 0)

        Jnoon = self.solarTransitJ(ds, M, L)

        result = dict(
            solarNoon=self.fromJulian(Jnoon).strftime('%Y-%m-%d %H:%M:%S'),
            nadir=self.fromJulian(Jnoon - 0.5).strftime('%Y-%m-%d %H:%M:%S')
        )

        for i in range(0, len(self.times)):
            time = self.times[i]
            h0 = (time[0] + dh) * self.rad

            Jset = self.getSetJ(h0, lw, phi, dec, n, M, L)
            Jrise = Jnoon - (Jset - Jnoon)
            result[time[1]] = self.fromJulian(Jrise).strftime('%Y-%m-%d %H:%M:%S')
            result[time[2]] = self.fromJulian(Jset).strftime('%Y-%m-%d %H:%M:%S')

        return result


    def hoursLater(self,date, h):
        """

        :param date:
        :param h:
        :return:
        """
        return date + timedelta(hours=h)


    def getMoonTimes(self,date, lat, lng):
        """

        :param date:
        :param lat:
        :param lng:
        :return:
        """
        """Gets moon rise/set properties for the given time and location."""

        t = date.replace(hour=0, minute=0, second=0)

        hc = 0.133 * self.rad
        h0 = self.getMoonPosition(t, lat, lng)["altitude"] - hc
        rise = 0
        sett = 0

        # go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set)
        for i in range(1, 25, 2):
            h1 = self.getMoonPosition(self.hoursLater(t, i), lat, lng)["altitude"] - hc
            h2 = self.getMoonPosition(self.hoursLater(t, i + 1), lat, lng)["altitude"] - hc

            a = (h0 + h2) / 2 - h1
            b = (h2 - h0) / 2
            xe = -b / (2 * a)
            ye = (a * xe + b) * xe + h1
            d = b * b - 4 * a * h1
            roots = 0

            if d >= 0:
                dx = math.sqrt(d) / (abs(a) * 2)
                x1 = xe - dx
                x2 = xe + dx
                if abs(x1) <= 1:
                    roots += 1
                if abs(x2) <= 1:
                    roots += 1
                if x1 < -1:
                    x1 = x2

            if roots == 1:
                if h0 < 0:
                    rise = i + x1
                else:
                    sett = i + x1

            elif roots == 2:
                rise = i + (x2 if ye < 0 else x1)
                sett = i + (x1 if ye < 0 else x2)

            if (rise and sett):
                break

            h0 = h2

        result = dict()

        if (rise):
            result["rise"] = self.hoursLater(t, rise)
        if (sett):
            result["set"] = self.hoursLater(t, sett)

        if (not rise and not sett):
            value = 'alwaysUp' if ye > 0 else 'alwaysDown'
            result[value] = True

        return result


    def getMoonPosition(self,date, lat, lng):
        """
        Gets positional attributes of the moon for the given time and location.
        :param date:
        :param lat:
        :param lng:
        :return:
        """

        lw = self.rad * -lng
        phi = self.rad * lat
        d = self.toDays(date)

        c = self.moonCoords(d)
        H = self.siderealTime(d, lw) - c["ra"]
        h = self.altitude(H, phi, c["dec"])

        # altitude correction for refraction
        h = h + self.rad * 0.017 / self.tan(h + self.rad * 10.26 / (h + self.rad * 5.10))
        pa = self.atan(self.sin(H), self.tan(phi) * self.cos(c["dec"]) - self.sin(c["dec"]) * self.cos(H))

        return dict(
            azimuth=self.azimuth(H, phi, c["dec"]),
            altitude=h,
            distance=c["dist"],
            parallacticAngle=pa
        )


    def getPosition(self,date, lat, lng):
        """
        Returns positional attributes of the sun for the given time and location.
        :param date:
        :param lat:
        :param lng:
        :return:
        """
        lw = self.rad * -lng
        phi = self.rad * lat
        d = self.toDays(date)

        c = self.sunCoords(d)
        H = self.siderealTime(d, lw) - c["ra"]
        # print("d", d, "c",c,"H",H,"phi", phi)
        return dict(
            azimuth=self.azimuth(H, phi, c["dec"]),
            altitude=self.altitude(H, phi, c["dec"])
        )

调用:

#日出日落 深圳
sun=Common.sunCalc.SunMoonTimeCalculator()
lat= 22.5445741
lng= 114.0545429
print(sun.getTimes(datetime.now(),  lat, lng))
print(sun.getMoonIllumination(datetime.now()))
#月升月落
print(sun.getMoonTimes(datetime.now(), lat, lng))

输出:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1679922.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在抖音做电商,没有货源,不懂直播怎么办?分享一种解决方案!

大家好&#xff0c;我是电商糖果 糖果做电商的时间也挺久了&#xff0c;天猫&#xff0c;京东&#xff0c;闲鱼都搞过。 从学校进入社会工作&#xff0c;创业&#xff0c;一直都是围绕电商打转。 做的时间久了&#xff0c;好像只会做这一件事儿了。 2020年开始专攻抖音小店&…

大模型日报2024-05-15

大模型日报 2024-05-15 大模型资讯 OpenAI推出全新AI模型GPT-4o&#xff0c;具备文本、图像和音频处理能力 摘要: OpenAI公司继ChatGPT后&#xff0c;最新推出了名为GPT-4o的AI模型。这一模型不仅能够理解和生成文本&#xff0c;还新增了图像和音频的解释及生成功能。GPT-4o作为…

思科模拟器--2.静态路由和默认路由配置24.5.15

首先&#xff0c;创建三个路由器和两个个人电脑。 接着&#xff0c;配置两台电脑的IP&#xff0c;子网掩码和默认网关 对Router 0&#xff0c;进行以下命令&#xff1a; 对Router进行以下命令&#xff1a; 对Router2进行以下命令&#xff1a; 本实验完成。 验证&#xff1a;PC…

代码随想录训练营Day 29|力扣39. 组合总和、40.组合总和II、131.分割回文串

1.组合总和 题目链接/文章讲解&#xff1a; 代码随想录 视频讲解&#xff1a;带你学透回溯算法-组合总和&#xff08;对应「leetcode」力扣题目&#xff1a;39.组合总和&#xff09;| 回溯法精讲&#xff01;_哔哩哔哩_bilibili 代码&#xff1a;&#xff08;未剪枝版 &#xf…

React Native 之 原生组件和核心组件(二)

原生组件 在 Android 开发中是使用 Kotlin 或 Java 来编写视图&#xff1b;在 iOS 开发中是使用 Swift 或 Objective-C 来编写视图。在 React Native 中&#xff0c;则使用 React 组件通过 JavaScript 来调用这些视图。在运行时&#xff0c;React Native 为这些组件创建相应的 …

19个测试⽤例⽣成的AI⼯具!卷起来!

在不断发展的软件开发领域中&#xff0c;确保应⽤程序的可靠性和功能性⾄关重要。 随着软件系统复杂性的增加&#xff0c;有效测试⽅法的需求也在上升。 传统的测试⽤例⽣成⽅法通常⽆法满⾜快速开发周期和复杂代码库的需求。 随着进⼊⼈⼯智能&#xff08;AI&#xff09;时…

ROS学习笔记(15)小车巡墙驾驶

0.前提 前一章我讲解了拉氏变换和PID&#xff0c;这一章我来讲解一下小车巡墙驾驶的理论和部分代码。 1.前情回顾 1.拉氏变换 拉普拉斯变换是要将时域问题转换成频域问题来处理。 2.PID控制器 转向角&#xff1a; 误差牺牲&#xff1a; 3.具体参看上一篇文章 2.巡墙驾驶…

机器学习入门介绍

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 目录 三大方向机器学习产生的原因机器如何学习…

Vue3学习笔记 - 禹神YYDS

1. 教程介绍 https://www.bilibili.com/video/BV1Za4y1r7KE?p1 本篇vue3&#xff0c;内容比较新&#xff0c;比如有setup语法糖用法&#xff1b;只是他使用TS&#xff0c;并不是JS&#xff1b;不过JS也比较熟悉了&#xff0c;也可以学习下TS的语法&#xff0c;课程使用 TypeSc…

【利用数组处理批量数据-谭浩强配套】(适合专升本、考研)

无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 完整资料如下&#xff1a;纯干货、纯干货、纯干货&#xff01;&#xff01;…

再谈毕业论文设计投机取巧之IVR自动语音服务系统设计(信息与通信工程专业A+其实不难)

目录 举个IVR例子格局打开&#xff0c;万物皆能IVR - 把《民法典》搬上IVR IVR系统其实可盐可甜。还能可圈可点。 戎马一生&#xff0c;归来依然IVR。 举个IVR例子 以下是IVR系统的一个例子。 当您拨打电话进入IVR系统。 首先检验是否为工作时间。 如是&#xff0c;您将被送入…

STM32F407 2个高级定时器生成2路无刷电机波形以及相电流采集程序(寄存器版)

stm32f407 高级定时1、定时8 生成20k 中心PWM 波形 并分别用其通道4 触发ADC1 ADC2 采样 用于分别两无刷电机foc 电流环控制&#xff0c;ADC1产生50us的电流采集完成中断&#xff0c;用于foc算法周期运算 主要参考高级定时器的寄存器和ADC寄存器 首先&#xff0c;要使用STM32F…

OSG编程指南<二十三>:基于OSG+ImGui制作模型编辑器,实现三轴方向的实时平移、旋转和缩放变化

1、概述 在OSG的开发应用过程中&#xff0c;我们有时候总会纠结于使用MFC还是Qt来嵌入OSG窗口以便于后续的功能开发&#xff0c;毕竟选择一个合适的UI框架&#xff0c;对于后续的开发还是省去很多麻烦的。但对于初学者来说&#xff0c;可能对框架消息机制的不熟悉&#xff0c;尤…

每日复盘-20240515

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 一支股票 10%的时候可以操作&#xff0c; 90%的时间适合空仓等待 国联证券 (1)|[9:25]|[133765万]|31.12 一…

selenium发展史

Selenium Core 2004 年&#xff0c;Thoughtworks 的工程师 Jason Huggins 正在负责一个 Web 应用的测试工作&#xff0c;由于这个项目需要频繁回归&#xff0c;这导致他不得不每天做着重复且低效的工作。为了解决这个困境&#xff0c;Jason 开发了一个运行在 JavaScript 沙箱中…

表白成功率百分百的向女朋友表白网页源代码,向女友表白HTML源代码

表白成功率百分百的向女朋友表白网页源代码&#xff0c;向女友表白HTML源代码 效果&#xff1a; 完整代码下载地址&#xff1a;向女友表白HTML源代码 <!DOCTYPE html> <!--STATUS OK--> <html><head><meta http-equiv"Content-Type" c…

Linux|基础环境开发工具使用(1)

目录 Linux 软件包管理器 yum 什么是软件包 关于 rzsz 注意事项 查看软件包 如何安装软件 如何卸载软件 Linux编辑器-vim介绍 vi与vim的相同点 vi与vim区别 Linux 软件包管理器 yum 什么是软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译…

【Windows】回忆Win98

回忆Win98&#xff0c;又看到了这个Excel界面&#xff0c;上次还是十多年前的计算机课上 1、安装环境 Win11家庭版,23H2,VMware Workstation Pro 16 , 2、安装步骤及参考 虚拟机里的硬盘设置成SATA&#xff08;否则各种错误&#xff09;&#xff0c;安装MSDOS7.1&#xff…

VP Codeforces Round 944 (Div 4)

感受&#xff1a; A~G 其实都不难&#xff0c;都可以试着补起来。 H看到矩阵就放弃了。 A题&#xff1a; 思路&#xff1a; 打开编译器 代码&#xff1a; #include <iostream> #include <vector> #include <algorithm> #define int long long using na…

基于Springboot的学生心理压力咨询评判(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的学生心理压力咨询评判&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系…