使用PyEphem计算阴影长度
我正在使用PyEphem这个工具,想要计算一个影子的长度(假设有一根单位长度的棍子插在地上)。影子的长度可以通过cot(phi)来计算,其中phi是太阳的高度角(如果我说错了,请纠正我)。我不太确定在太阳的相关数据中应该用哪个字段?在下面的例子中,我使用的是角度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)
请看看我下面的理解:
- 如果切线是无限大,说明太阳正好在头顶上,这时候没有影子。
- 如果切线是零,说明太阳在地平线上,这时候影子会无限长。
- 我不太明白cot(phi)的负值该怎么理解。有人能帮我吗?
最后,我对如何使用PyEphem从影子的长度反推下一个时间点,太阳会投下那个长度的影子,感到困惑,前提是我已经有一个ephem.Observer()。
我会很感激能得到帮助。
1 个回答
10
在计算太阳的位置时,应该用哪个字段呢?
sun.alt
是正确的。alt
表示的是太阳离地平线的高度;再加上一个朝北的方位角,它们一起定义了太阳在地平线上的可见位置。
你的计算几乎是对的。不过你忘了提供观察者的信息:sun = ephem.Sun(o)
。
- 我不知道如何理解从cot(phi)得到的负值。有人能帮我吗?
在这种情况下,太阳是在地平线以下的。
最后,我对如何使用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