Вычислить длину тени с помощью PyEphem - PullRequest
8 голосов
/ 19 апреля 2011

Я использую PyEphem и хочу рассчитать длину тени (предположим, что в землю посажена палка единичной длины). Длина будет дана в койке (фи), где фи - угол места Солнца (пожалуйста, поправьте меня, если я ошибаюсь). Я не уверен , какое поле использовать на Солнце ? В приведенном ниже примере я использую угол alt:

import ephem, math
o = ephem.Observer()
o.lat, o.long = '37.0625', '-95.677068'
sun = ephem.Sun()
sunrise = o.previous_rising(sun, start=ephem.now())
noon = o.next_transit(sun, start=sunrise)
shadow = 1 / math.tan(sun.alt)

Пожалуйста, проверьте мою интерпретацию ниже:

  1. Если касательная бесконечна, это означает, что солнце находится прямо над головой и тени нет.
  2. Если касательная равна нулю, это означает, что солнце находится на горизонте, а тень бесконечно длинна.
  3. Я не знаю, как интерпретировать отрицательные результаты от кроватки (фи). Может ли кто-нибудь мне помочь?

Наконец, я запутался в том, как использовать PyEphem для работы в обратном направлении от длины тени до следующего раза, когда солнце будет отбрасывать тень такой длины, учитывая ephem.Observer ().

Буду признателен за помощь.

1 Ответ

9 голосов
/ 20 апреля 2011

какое поле использовать на Солнце?

sun.alt правильно. alt - высота над горизонтом; вместе с азимутом к востоку от севера они определяют видимое положение относительно горизонта.

Ваши расчеты почти верны. Вы забыли предоставить наблюдателя: sun = ephem.Sun(o).

  1. Я не знаю, как интерпретировать отрицательные результаты от кроватки (фи). Можно кто-нибудь поможет мне?

В этом случае Солнце находится ниже горизонта.

Наконец, я запутался в том, как использовать PyEphem работать в обратном направлении от Длина тени до следующего раза, когда солнце отбрасывает тень этого длина, заданная в ephem.Observer ().

Вот скрипт, который дал функцию: g(date) -> altitude вычисляет в следующий раз, когда Солнце будет отбрасывать тень такой же длины, как сейчас (азимут - направление тени не учитывается):

#!/usr/bin/env python
import math
import ephem    
import matplotlib.pyplot as plt
import numpy as np
import scipy.optimize as opt

def main():
    # find a shadow length for a unit-length stick
    o = ephem.Observer()
    o.lat, o.long = '37.0625', '-95.677068'
    now = o.date
    sun = ephem.Sun(o) #NOTE: use observer; it provides coordinates and time
    A = sun.alt
    shadow_len = 1 / math.tan(A)

    # find the next time when the sun will cast a shadow of the same length
    t = ephem.Date(find_next_time(shadow_len, o, sun))
    print "current time:", now, "next time:", t # UTC time
    ####print ephem.localtime(t) # print "next time" in a local timezone

def update(time, sun, observer):
    """Update Sun and observer using given `time`."""
    observer.date = time
    sun.compute(observer) # computes `sun.alt` implicitly.
    # return nothing to remember that it modifies objects inplace

def find_next_time(shadow_len, observer, sun, dt=1e-3):
    """Solve `sun_altitude(time) = known_altitude` equation w.r.t. time."""
    def f(t):
        """Convert the equation to `f(t) = 0` form for the Brent's method.

        where f(t) = sun_altitude(t) - known_altitude
        """
        A = math.atan(1./shadow_len) # len -> altitude
        update(t, sun, observer)
        return sun.alt - A

    # find a, b such as f(a), f(b) have opposite signs
    now = observer.date # time in days
    x = np.arange(now, now + 1, dt) # consider 1 day
    plt.plot(x, map(f, x))
    plt.grid(True)
    ####plt.show()
    # use a, b from the plot (uncomment previous line to see it)
    a, b = now+0.2, now+0.8

    return opt.brentq(f, a, b) # solve f(t) = 0 equation using Brent's method


if __name__=="__main__":
    main()

выход

current time: 2011/4/19 23:22:52 next time: 2011/4/20 13:20:01
...