이 질문은 요청 된 전 이상 3 년 전에 조금. 주어진 대답이 있었지만 솔루션에서 결함을 발견했습니다.
아래 코드는 R에 있습니다. 다른 언어로 이식했지만 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))
}
내가 치는 문제는 그것이 반환하는 방위각이 잘못 보인다는 것입니다. 예를 들어, 0ºE 및 41ºS, 3ºS, 3ºN 및 41ºN 위치에 대해 12:00에 (남부)하지에서 함수를 실행하는 경우 :
> 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
이 숫자는 옳지 않은 것 같습니다. 내가 만족하는 고도-처음 두 개는 거의 같고 세 번째는 터치가 더 낮아야하며 네 번째는 훨씬 더 낮아야합니다. 그러나 첫 번째 방위각은 대략 정북이어야하며, 제공하는 숫자는 완전히 반대입니다. 나머지 3 개는 대략 남쪽을 가리켜 야하지만 마지막 하나만 그렇습니다. 중간에있는 두 개는 북쪽에서 약간 떨어져 다시 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
나는 주변을 훑어 보았고 C에서 비슷한 코드 덩어리를 발견했으며 방위각을 계산하는 데 사용하는 라인은 R로 변환되었습니다.
az <- atan(sin(ha) / (cos(ha) * sin(lat) - tan(dec) * cos(lat)))
여기의 출력은 올바른 방향으로 향하고있는 것 같지만 다시 각도로 변환 될 때 항상 올바른 답을 제공 할 수는 없습니다.
정확한 방위각을 계산하기 위해 코드를 수정하는 것은 환상적 일 것입니다.