Skip to content

Instantly share code, notes, and snippets.

@keiya
Created March 16, 2013 05:04
Show Gist options
  • Select an option

  • Save keiya/5175072 to your computer and use it in GitHub Desktop.

Select an option

Save keiya/5175072 to your computer and use it in GitHub Desktop.
日の出・日の入りの計算アルゴリズム
<html><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<style>
div#map_canvas {
width: 640px;
height: 320px;
}
</style>
<title>SOLAR</title>
</head>
<body>
<form>
<h2>地点選択</h2>
<input type='button' id='ui_curr' value='現在地' />
<div id="map_canvas" style="border-left:1px solid #555555;"></div>
緯度(lat.)<input name="lat" size="10" value="35.65" type="TEXT">N
経度(lng.)<input name="lon" size="10" value="139.7333" type="TEXT">E
標高(alt.)<input name="alt" size="10" value="0.0" type="TEXT">m<br>
<h2>日付</h2>
<input value="今日" id='ui_today' type="button">
西暦<input name="year" size="5" value="2013" type="TEXT">年
<input name="month" size="5" value="3" type="TEXT">月
<input name="dayn" size="5" value="16" type="TEXT">日 <br>
グリニッジ標準時との時差<input name="def" size="5" value="9" type="TEXT">時間<br><br>
<h2>結果</h2>
<input value="計算開始" id='ui_calc' type="button"><br>
</form>
<div id='result'></div>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script src='jquery-1.9.1.min.js'></script>
<script src='solar.js'></script>
<script src='ui.js'></script>
</body></html>
/*
* thanks to
* http://www.hoshi-lab.info/env/solar-j.html
*/
if (!jp) var jp = {};
if (!jp.co) jp.co = {};
if (!jp.co.missinglink) jp.co.missinglink = {};
if (!jp.co.missinglink.aerograce) jp.co.missinglink.aerograce = {};
jp.co.missinglink.aerograce.solar = function() {};
(function(){
// sin function using degree
function sind(d) {
return Math.sin(d*Math.PI/180) ;}
// cos function using degree
function cosd(d) {
return Math.cos(d*Math.PI/180) ; }
// tan function using degree
function tand(d) {
return Math.tan(d*Math.PI/180) ; }
// calculate Julius year (year from 2000/1/1, for variable "t")
function jy(yy,mm,dd,h,m,s,i) { // yy/mm/dd h:m:s, i: time difference
yy -= 2000 ;
if(mm <= 2) {
mm += 12 ;
yy-- ; }
var k = 365 * yy + 30 * mm + dd - 33.5 - i / 24 + Math.floor(3 * (mm + 1) / 5)
+ Math.floor(yy / 4) - Math.floor(yy / 100) + Math.floor(yy / 400);
k += ((s / 60 + m) / 60 + h) / 24 ; // plus time
k += (65 + yy) / 86400 ; // plus delta T
return k / 365.25 ;
}
// solar position1 (celestial longitude, degree)
function spls(t) { // t: Julius year
var l = 280.4603 + 360.00769 * t
+ (1.9146 - 0.00005 * t) * sind(357.538 + 359.991 * t)
+ 0.0200 * sind(355.05 + 719.981 * t)
+ 0.0048 * sind(234.95 + 19.341 * t)
+ 0.0020 * sind(247.1 + 329.640 * t)
+ 0.0018 * sind(297.8 + 4452.67 * t)
+ 0.0018 * sind(251.3 + 0.20 * t)
+ 0.0015 * sind(343.2 + 450.37 * t)
+ 0.0013 * sind( 81.4 + 225.18 * t)
+ 0.0008 * sind(132.5 + 659.29 * t)
+ 0.0007 * sind(153.3 + 90.38 * t)
+ 0.0007 * sind(206.8 + 30.35 * t)
+ 0.0006 * sind( 29.8 + 337.18 * t)
+ 0.0005 * sind(207.4 + 1.50 * t)
+ 0.0005 * sind(291.2 + 22.81 * t)
+ 0.0004 * sind(234.9 + 315.56 * t)
+ 0.0004 * sind(157.3 + 299.30 * t)
+ 0.0004 * sind( 21.1 + 720.02 * t)
+ 0.0003 * sind(352.5 + 1079.97 * t)
+ 0.0003 * sind(329.7 + 44.43 * t) ;
while(l >= 360) { l -= 360 ; }
while(l < 0) { l += 360 ; }
return l ;
}
// solar position2 (distance, AU)
function spds(t) { // t: Julius year
var r = (0.007256 - 0.0000002 * t) * sind(267.54 + 359.991 * t)
+ 0.000091 * sind(265.1 + 719.98 * t)
+ 0.000030 * sind( 90.0)
+ 0.000013 * sind( 27.8 + 4452.67 * t)
+ 0.000007 * sind(254 + 450.4 * t)
+ 0.000007 * sind(156 + 329.6 * t)
r = Math.pow(10,r) ;
return r ;
}
// solar position3 (declination, degree)
function spal(t) { // t: Julius year
var ls = spls(t) ;
var ep = 23.439291 - 0.000130042 * t ;
var al = Math.atan(tand(ls) * cosd(ep)) * 180 / Math.PI ;
if((ls >= 0)&&(ls < 180)) {
while(al < 0) { al += 180 ; }
while(al >= 180) { al -= 180 ; } }
else {
while(al < 180) { al += 180 ; }
while(al >= 360) { al -= 180 ; } }
return al ;
}
// solar position4 (the right ascension, degree)
function spdl(t) { // t: Julius year
var ls = spls(t) ;
var ep = 23.439291 - 0.000130042 * t ;
var dl = Math.asin(sind(ls) * sind(ep)) * 180 / Math.PI ;
return dl ;
}
// Calculate sidereal hour (degree)
function sh(t,h,m,s,l,i) { // t: julius year, h: hour, m: minute, s: second,
// l: longitude, i: time difference
var d = ((s / 60 + m) / 60 + h) / 24 ; // elapsed hour (from 0:00 a.m.)
var th = 100.4606 + 360.007700536 * t + 0.00000003879 * t * t - 15 * i ;
th += l + 360 * d ;
while(th >= 360) { th -= 360 ; }
while(th < 0) { th += 360 ; }
return th ;
}
// Calculating the seeming horizon altitude "sa"(degree)
function eandp(alt,ds) { // subfunction for altitude and parallax
var e = 0.035333333 * Math.sqrt(alt) ;
var p = 0.002442818 / ds ;
return p - e ;
}
function sa(alt,ds) { // alt: altitude (m), ds: solar distance (AU)
var s = 0.266994444 / ds ;
var r = 0.585555555 ;
var k = eandp(alt,ds) - s - r ;
return k ;
}
// Calculating solar alititude (degree)
function soal(la,th,al,dl) { // la: latitude, th: sidereal hour,
// al: solar declination, dl: right ascension
var h = sind(dl) * sind(la) + cosd(dl) * cosd(la) * cosd(th - al) ;
h = Math.asin(h) * 180 / Math.PI ;
return h;
}
// Calculating solar direction (degree)
function sodr(la,th,al,dl) { // la: latitude, th: sidereal hour,
// al: solar declination, dl: right ascension
var t = th - al ;
var dc = - cosd(dl) * sind(t) ;
var dm = sind(dl) * sind(la) - cosd(dl) * cosd(la) * cosd(t) ;
if(dm == 0) {
st = sind(t) ;
if(st > 0) dr = -90 ;
if(st == 0) dr = 9999 ;
if(st < 0) dr = 90 ;
}
else {
var dr = Math.atan(dc / dm) * 180 / Math.PI ;
if(dm <0) dr += 180 ;
}
if(dr < 0) dr += 360 ;
return dr ;
}
jp.co.missinglink.aerograce.solar.prototype.calc = function (yy,mm,dd,i,alt,lat,lng) {
var t = jy(yy,mm,dd-1,23,59,0,i) ;
var th = sh(t,23,59,0,lng,i) ;
var ds = spds(t) ;
var ls = spls(t) ;
var alp = spal(t) ;
var dlt = spdl(t) ;
var pht = soal(lat,th,alp,dlt) ;
var pdr = sodr(lat,th,alp,dlt) ;
var res = {
'sast':{},'snt':{},'sciv':{},'sciv':{},'mer':{},'sr':{},'ss':{},'east':{},'ent':{},'eciv':{}
};
for(hh=0; hh<24; ++hh) {
for(m=0; m<60; ++m) {
t = jy(yy,mm,dd,hh,m,0,i) ;
th = sh(t,hh,m,0,lng,i) ;
ds = spds(t) ;
ls = spls(t) ;
alp = spal(t) ;
dlt = spdl(t) ;
var ht = soal(lat,th,alp,dlt) ;
var dr = sodr(lat,th,alp,dlt) ;
var tt = eandp(alt,ds) ;
var t1 = tt - 18 ;
var t2 = tt - 12 ;
var t3 = tt - 6 ;
var t4 = sa(alt,ds) ;
// Solar check
// 0: non, 1: astronomical twilight start , 2: voyage twilight start,
// 3: citizen twilight start, 4: sun rise, 5: meridian, 6: sun set,
// 7: citizen twilight end, 8: voyage twilight end,
// 9: astronomical twilight end
if((pht<t1)&&(ht>t1)) {
res.sast.h = hh
res.sast.m = m;
}
else if((pht<t2)&&(ht>t2)) {
res.snt.h = hh
res.snt.m = m;
}
else if((pht<t3)&&(ht>t3)) {
res.sciv.h = hh
res.sciv.m = m;
}
else if((pht<t4)&&(ht>t4)) {
res.sr.h = hh
res.sr.m = m;
res.sr.or = Math.floor(dr);
}
else if((pdr<180)&&(dr>180)) {
res.mer.h = hh;
res.mer.m = m;
res.mer.ang = Math.floor(ht);
}
else if((pht>t4)&&(ht<t4)) {
res.ss.h = hh;
res.ss.m = m;
res.ss.or = Math.floor(dr);
}
else if((pht>t3)&&(ht<t3)) {
res.eciv.h = hh;
res.eciv.m = m;
}
else if((pht>t2)&&(ht<t2)) {
res.ent.h = hh;
res.ent.m = m;
}
else if((pht>t1)&&(ht<t1)) {
res.east.h = hh;
res.east.m = m;
}
pht = ht ;
pdr = dr ;
}
}
return res;
}
}());
$('document').ready(function(){
$('#ui_calc').click(
_calc
);
$('#ui_curr').click(function(){
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(pos) {
$lat.val(pos.coords.latitude);
$lng.val(pos.coords.longitude);
_calc();
}, function() {
});
} else {
// Browser doesn't support Geolocation
}
});
var $year = $('input[name="year"]');
var $month = $('input[name="month"]');
var $day = $('input[name="dayn"]');
var $td = $('input[name="def"]');
var $alt = $('input[name="alt"]');
var $lat = $('input[name="lat"]');
var $lng = $('input[name="lon"]');
var $result = $('#result');
var marker;
function today() { // get doday
Td = new Date() ;
$year.val(Td.getFullYear());
$month.val(Td.getMonth() + 1);
$day.val(Td.getDate());
}
today();
$('#ui_today').click(function(){
today();
_calc();
});
$year.change(_calc);
$month.change(_calc);
$day.change(_calc);
$td.change(_calc);
$alt.change(_calc);
function _calc() {
var r = map.getCenter();
var lat = parseFloat($lat.val());
var lng = parseFloat($lng.val());
var yy = $year.val();
var mm = $month.val();
var dd = $day.val();
var i = $td.val();
var alt = $alt.val();//標高
var ans = "<h3>" + yy + "/" + mm + "/" + dd + "</h3><table>";
var solar = new jp.co.missinglink.aerograce.solar;
var res = solar.calc($year.val(),$month.val(),$day.val(),$td.val(),$alt.val(),lat,lng);
ans += "<tr class='res_sa'><td class='res_clock'>" + res.sast.h + ":" + res.sast.m + "</td><td class='res_desc'>start of Astronomical twilight</td></tr>\n" ;
ans += "<tr class='res_sn'><td class='res_clock'>" + res.snt.h + ":" + res.snt.m + "</td><td class='res_desc'>start of Nautical twilight</td></tr>\n" ;
ans += "<tr class='res_sc'><td class='res_clock'>" + res.sciv.h + ":" + res.sciv.m + "</td><td class='res_desc'>start of Civil twilight</td></tr>\n" ;
ans += "<tr class='res_sr'><td class='res_clock'>" + res.sr.h + ":" + res.sr.m + "</td><td class='res_desc'>Sunrise 日出</td><td ='res_add'>orientation:" + res.sr.or +"deg</td></tr>\n";
ans += "<tr class='res_m'> <td class='res_clock'>" + res.mer.h + ":" + res.mer.m + "</td><td class='res_desc'>Meridian 南中</td><td class='res_add'>altitude:" +res.mer.ang+"deg</td></tr>\n";
ans += "<tr class='res_ss'><td class='res_clock'>" + res.ss.h + ":" + res.ss.m + "</td><td class='res_desc'>Sunset 日没</td><td class='res_add'>orientation:" + res.ss.or +"deg</td></tr>\n";
ans += "<tr class='res_ec'><td class='res_clock'>" + res.eciv.h + ":" + res.eciv.m + "</td><td class='res_desc'>end of Civil twilight</td></tr>\n" ;
ans += "<tr class='res_en'><td class='res_clock'>" + res.ent.h + ":" + res.ent.m + "</td><td class='res_desc'>end of Nautical twilight</td></tr>\n" ;
ans += "<tr class='res_ea'><td class='res_clock'>" + res.east.h + ":" + res.east.m + "</td><td class='res_desc'>end of Astronomical twilight</td></tr>\n" ;
ans += "</table>";
$result.html(ans);
}
var target = new google.maps.LatLng(35.668143,139.733294);
var crosshairShape = {coords:[0,0,0,0],type:'rect'};
var myOptions = {
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl:false,
center: target,
overviewMapControl : true,
scaleControl : true,
panControl : true,
zoomControl : true,
streetViewControl: false,
}
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
marker = new google.maps.Marker({
map: map,
icon: 'http://www.daftlogic.com/images/cross-hairs.gif',
shape: crosshairShape
});
marker.bindTo('position', map, 'center');
map.setOptions(
{
styles:[
{
featureType: "all",
stylers: [
{
hue: '#38a5ee'
},
{invert_lightness:true},
{gamma:1.2}
]
}
]
}
);
google.maps.event.addListener(map,'center_changed',function(){
var r = map.getCenter();
$lat.val(r.lat());
$lng.val(r.lng());
marker.setVisible(false);
});
google.maps.event.addListener(map,'idle',function(){
var r = map.getCenter();
$lat.val(r.lat());
$lng.val(r.lng());
_calc();
marker.setVisible(true);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment