यह सवाल तीन साल पहले के एक छोटे से पहले पूछा गया है। वहाँ एक जवाब दिया गया था, हालांकि मैंने समाधान में एक गड़बड़ पाया है।
नीचे दिया गया कोड R में है। मैंने इसे दूसरी भाषा में पोर्ट कर लिया है, हालाँकि इस मुद्दे को मेरे पोर्टिंग के साथ न रखने के लिए आर में सीधे मूल कोड का परीक्षण किया है।
sunPosition <- function(year, month, day, hour=12, min=0, sec=0,
lat=46.5, long=6.5) {
twopi <- 2 * pi
deg2rad <- pi / 180
# Get day of the year, e.g. Feb 1 = 32, Mar 1 = 61 on leap years
month.days <- c(0,31,28,31,30,31,30,31,31,30,31,30)
day <- day + cumsum(month.days)[month]
leapdays <- year %% 4 == 0 & (year %% 400 == 0 | year %% 100 != 0) & day >= 60
day[leapdays] <- day[leapdays] + 1
# Get Julian date - 2400000
hour <- hour + min / 60 + sec / 3600 # hour plus fraction
delta <- year - 1949
leap <- trunc(delta / 4) # former leapyears
jd <- 32916.5 + delta * 365 + leap + day + hour / 24
# The input to the Atronomer's almanach is the difference between
# the Julian date and JD 2451545.0 (noon, 1 January 2000)
time <- jd - 51545.
# Ecliptic coordinates
# Mean longitude
mnlong <- 280.460 + .9856474 * time
mnlong <- mnlong %% 360
mnlong[mnlong < 0] <- mnlong[mnlong < 0] + 360
# Mean anomaly
mnanom <- 357.528 + .9856003 * time
mnanom <- mnanom %% 360
mnanom[mnanom < 0] <- mnanom[mnanom < 0] + 360
mnanom <- mnanom * deg2rad
# Ecliptic longitude and obliquity of ecliptic
eclong <- mnlong + 1.915 * sin(mnanom) + 0.020 * sin(2 * mnanom)
eclong <- eclong %% 360
eclong[eclong < 0] <- eclong[eclong < 0] + 360
oblqec <- 23.429 - 0.0000004 * time
eclong <- eclong * deg2rad
oblqec <- oblqec * deg2rad
# Celestial coordinates
# Right ascension and declination
num <- cos(oblqec) * sin(eclong)
den <- cos(eclong)
ra <- atan(num / den)
ra[den < 0] <- ra[den < 0] + pi
ra[den >= 0 & num < 0] <- ra[den >= 0 & num < 0] + twopi
dec <- asin(sin(oblqec) * sin(eclong))
# Local coordinates
# Greenwich mean sidereal time
gmst <- 6.697375 + .0657098242 * time + hour
gmst <- gmst %% 24
gmst[gmst < 0] <- gmst[gmst < 0] + 24.
# Local mean sidereal time
lmst <- gmst + long / 15.
lmst <- lmst %% 24.
lmst[lmst < 0] <- lmst[lmst < 0] + 24.
lmst <- lmst * 15. * deg2rad
# Hour angle
ha <- lmst - ra
ha[ha < -pi] <- ha[ha < -pi] + twopi
ha[ha > pi] <- ha[ha > pi] - twopi
# Latitude to radians
lat <- lat * deg2rad
# Azimuth and elevation
el <- asin(sin(dec) * sin(lat) + cos(dec) * cos(lat) * cos(ha))
az <- asin(-cos(dec) * sin(ha) / cos(el))
elc <- asin(sin(dec) / sin(lat))
az[el >= elc] <- pi - az[el >= elc]
az[el <= elc & ha > 0] <- az[el <= elc & ha > 0] + twopi
el <- el / deg2rad
az <- az / deg2rad
lat <- lat / deg2rad
return(list(elevation=el, azimuth=az))
}
जो समस्या मैं मार रहा हूं, वह यह है कि अजिमुथ यह रिटर्न गलत लगता है। उदाहरण के लिए, अगर मैं 12:00 बजे (दक्षिणी) गर्मियों में संक्रांति पर ifºE और 41ºS, 3ºS, 3ºN और 41ºN स्थानों पर फ़ंक्शन चलाता हूं:
> sunPosition(2012,12,22,12,0,0,-41,0)
$elevation
[1] 72.42113
$azimuth
[1] 180.9211
> sunPosition(2012,12,22,12,0,0,-3,0)
$elevation
[1] 69.57493
$azimuth
[1] -0.79713
Warning message:
In asin(sin(dec)/sin(lat)) : NaNs produced
> sunPosition(2012,12,22,12,0,0,3,0)
$elevation
[1] 63.57538
$azimuth
[1] -0.6250971
Warning message:
In asin(sin(dec)/sin(lat)) : NaNs produced
> sunPosition(2012,12,22,12,0,0,41,0)
$elevation
[1] 25.57642
$azimuth
[1] 180.3084
ये संख्या सिर्फ सही नहीं लगती है। मैं जिस ऊंचाई से खुश हूं - पहले दो मोटे तौर पर एक ही होना चाहिए, तीसरा एक स्पर्श कम, और चौथा बहुत कम। हालाँकि उत्तर की ओर पहला अज़ीमुथ लगभग होना चाहिए, जबकि यह जो संख्या देता है वह पूर्ण विपरीत है। शेष तीनों को मोटे तौर पर दक्षिण की ओर इशारा करना चाहिए, हालांकि केवल अंतिम एक ही करता है। बीच के दो बिंदु उत्तर की ओर, फिर 180। बाहर।
जैसा कि आप देख सकते हैं कि निम्न अक्षांशों (भूमध्य रेखा के करीब) के साथ ट्रिगर होने वाली कुछ त्रुटियां भी हैं
मेरा मानना है कि गलती इस खंड में है, तीसरी पंक्ति में त्रुटि शुरू होने के साथ (शुरुआत के साथ elc
)।
# Azimuth and elevation
el <- asin(sin(dec) * sin(lat) + cos(dec) * cos(lat) * cos(ha))
az <- asin(-cos(dec) * sin(ha) / cos(el))
elc <- asin(sin(dec) / sin(lat))
az[el >= elc] <- pi - az[el >= elc]
az[el <= elc & ha > 0] <- az[el <= elc & ha > 0] + twopi
मैंने चारों ओर गुगली की और सी में कोड का एक समान हिस्सा पाया, आर की गणना करने के लिए आर का उपयोग करने वाली रेखा में परिवर्तित हो गया, जो कुछ इस तरह होगा
az <- atan(sin(ha) / (cos(ha) * sin(lat) - tan(dec) * cos(lat)))
यहाँ आउटपुट सही दिशा में जा रहा है, लेकिन मैं इसे हर समय सही जवाब देने के लिए नहीं पा सकता हूँ जब इसे डिग्री में परिवर्तित किया जाता है।
कोड का एक सुधार (संदेह है कि यह ऊपर कुछ पंक्तियाँ हैं) यह सही azimuth की गणना करने के लिए शानदार होगा।