太陽高度を計算する

地球は太陽の周りを回る。
地軸が特定の角度だけ傾いた状態を維持したまま、地球は太陽の周りを回る。
その地軸を回転軸として地球は回る。
一周回ると一日。
地上の点の天頂方向は、地球の中心を原点として、地軸ベクトルを回転軸として回転する。


太陽の仰角(夜間は地平線の下に隠れているが、負の仰角を持つ)は、この天頂方向ベクトルと、太陽-地球ベクトルとが成す角を90度から引いた角度になる。


これをRで計算してみる。

# 緯度 degree
ido <- 35
ido.pi <- 35 / 180 * pi
# date of year
date <- 1 # 元日
# date of year, fraction
date.y <- date / (365 + 0.25)
date.y.pi <- date.y * 2 * pi
# 地軸の傾き(太陽に向かって)
psi <- 23.4
psi.pi <- 23.4 / 180 * pi
# 時刻
t <- 0 # 0 ... 24 hours


# 地球の回転軸単位ベクトルは、季節・時刻によらず一定
v.earth <- c(-cos(psi.pi),0,sin(psi.pi))
# 太陽光が地球に向かう(平行)光線単位ベクトルは季節によって変動、時刻によらず一定
v.solar <- c(cos(date.y.pi),sin(date.y.pi),0)

# 着目地点の天の頂上方向単位ベクトルは季節によらず、時刻によって変動
# そのベクトルは、あるベクトルを、地球の回転軸に関して時刻に応じた角度だけ回転させたもの
# この計算は四元数を用いると便利
# v.pointをある地点の、計算しやすい、特定の方向ベクトルとする
v.point <- c(-cos(ido.pi - psi.pi),0,sin(ido.pi - psi.pi))
# 以下がその計算関数
library(onion)

my.tencho.time <- function(v.earth,v.point,time){
	time.pi <- time/24 * 2 * pi
	v.earth.q <- Hi * v.earth[1] + Hj * v.earth[2] + Hk * v.earth[3]
	rotation.q <- cos(time.pi/2) + sin(time.pi/2) * v.earth.q
	rotated <- rotate(matrix(v.point,ncol=3),rotation.q)
	return(rotated)
}

# 太陽の高度は、天の頂上方向ベクトルと太陽光線ベクトルとの成す角で決まる
my.angle.solar <- function(tencho.v,solar.v){
	ip <- sum(tencho.v * solar.v) / (sqrt(sum(tencho.v^2)) * sqrt(sum(solar.v^2)))
	ang <- acos(ip) / pi * 180
	return(ang)
}

# ある日のある時刻の太陽高度を計算する関数
my.sun.angle <- function(ido,date,time,psi=23.4){
	# 地軸の傾き(太陽に向かって)
	#psi <- 23.4
	psi.pi <- 23.4 / 180 * pi
	# ベクトルの成分を求めるときには、地軸の傾きそのものではなく
	# pi/2 - psi.pi を用いる
	v.earth <- c(-cos(pi/2-psi.pi),0,sin(pi/2-psi.pi))
	# date of year, fraction
	date.y <- date / (365 + 0.25)
	date.y.pi <- date.y * 2 * pi
	
	ido.pi <- ido / 180 * pi
	# v.pointをある地点の、計算しやすい、特定の方向ベクトルとする
	# その方向は、北半球では夏至のときの地球の位置と太陽の位置を
	# 結ぶ線の方向に「地点」があるときの地点方向ベクトルを計算しやすい方向とする
	
	dir <- psi.pi
	v.point <- c(-cos(ido.pi - psi.pi),0,sin(ido.pi - psi.pi))

	tencho.v <- my.tencho.time(v.earth, v.point, time)
	
	# 太陽光が地球に向かう(平行)光線単位ベクトルは季節によって変動、時刻によらず一定
	solar.v <- c(cos(date.y.pi),sin(date.y.pi),0)

	ang <- 90 - my.angle.solar(tencho.v,solar.v)
	
	return(ang)
}

ido <- 35
# おおよそ、夏至、秋分、冬至、春分
dates <- (0:3) / 4 * 365 + 1
# 1日。ただし、季節によって、このtimesの値のどこが「南中か」にはずれがあるので
# 太陽高度が一番高くなっているtimes 値を、南中時刻とみなすべき
times <- seq(from=0,to=24,length=200)
dates.times <- expand.grid(dates,times)

angs <- rep(0,length(dates.times[,1]))

for(i in 1:length(dates.times[,1])){
	date <- dates.times[i,1]
	time <- dates.times[i,2]
	angs[i] <- my.sun.angle(ido,date,time)
}

#plot(times,angs,type="l")

matplot(times,matrix(angs,ncol=length(dates),byrow=TRUE),type="l",xlab="時間",ylab="太陽高度")
abline(h=0) # 水平線

###############
# ある日の24時間の太陽高度を計算する関数

my.sun.angle.24 <- function(ido,date,n.times=24*10,psi=23.4){
	angs <- rep(0,n.times)
	times <- seq(from=0,to=24,length=n.times)
	for(i in 1:n.times){
		angs[i] <- my.sun.angle(ido,date,times[i],psi=psi)
	}
	idmin <- which.min(angs)
	ids <- c(idmin:n.times,1:(idmin-1))
	return(angs[ids])
}


ido <- 35
# おおよそ、夏至、秋分、冬至、春分
dates <- (0:3) / 4 * 365 + 1
# 1日。ただし、季節によって、このtimesの値のどこが「南中か」にはずれがあるので
# 太陽高度が一番高くなっているtimes 値を、南中時刻とみなすべき

n.times <- 240

angs <- matrix(0,ncol=length(dates),nrow=n.times)


for(i in 1:length(dates)){
	date <- dates[i]
	angs[,i] <- my.sun.angle.24(ido,date,n.times)
}

#plot(times,angs,type="l")
times <- seq(from=0,to=24,length=n.times)
matplot(times,angs,type="l",xlab="時間",ylab="太陽高度")
abline(h=0) # 水平線
abline(v=c(0,12,24))


この記事が気に入ったらサポートをしてみませんか?