BangleApps/apps/planetarium/planetarium.app.js

209 lines
6.4 KiB
JavaScript

/*
* Degrees to radians
*/
function toRadians(degrees)
{
return Math.PI * degrees / 180;
}
/*
* Julian day number
* Assumes a proleptic gregorian calendar where the year 1 is preceded by the
* year 0.
*/
function toJulianDay(year, month, day, hours, minutes, seconds)
{
day += hours / 24 + minutes / 1440 + seconds / 86400;
if(month <= 2)
{
year -= 1;
month += 12;
}
var A = Math.floor(year / 100);
var B = 2 - A + Math.floor(A / 4);
return Math.floor(365.25 * (year + 4716)) + Math.floor(30.6001 * (month + 1)) + day + B - 1524.5;
}
/*
* Sidereal time in Greenwich
*/
function siderealTime(julianDay)
{
var T = (julianDay - 2451545.0) / 36525;
return toRadians(280.46061837 + 360.98564736629 * (julianDay - 2451545.0) + 0.000387933 * T * T - T * T * T / 38710000);
}
/*
* Draws a single star in the sky.
* starPositions is a dictionary that gets modified and it is used later for ploting the constelations
*/
function drawStar(zeta,theta,z,julianDay,latitude,longitude,starInfo,starNumber,starPositions){
let starRA = parseFloat(starInfo[0]);
let starDE = parseFloat(starInfo[1]);
let starMag = parseFloat(starInfo[2]);
var dec = Math.asin(Math.sin(theta) * Math.cos(starDE) * Math.cos(starRA + zeta) + Math.cos(theta) * Math.sin(starDE));
var ascen = Math.atan2(Math.cos(starDE) * Math.sin(starRA + zeta), Math.cos(theta) * Math.cos(starDE) * Math.cos(starRA + zeta) - Math.sin(theta) * Math.sin(starDE)) + z;
var H = siderealTime(julianDay) - longitude - ascen;
//Compute altitude
var alt = Math.asin(Math.sin(latitude) * Math.sin(dec) + Math.cos(latitude) * Math.cos(dec) * Math.cos(H));
if(alt >= 0)
{
//Compute azimuth
var azi = Math.atan2(Math.sin(H), Math.cos(H) * Math.sin(latitude) - Math.tan(dec) * Math.cos(latitude));
var x = size / 2 + size / 2 * Math.cos(alt) * Math.sin(azi);
var y = size / 2 + size / 2 * Math.cos(alt) * Math.cos(azi);
starPositions[starNumber] = [x,y];
var magnitude = starMag<1?2:1;
//Stars between 1.5 and 4 magnitude should get a different colour
var col=1;
if (starMag<=1.5)
col=1;
else if (starMag>1.5 && starMag<2)
col=0.9;
else if (starMag>=2 && starMag<3)
col=0.7;
else if (starMag>=3 && starMag<3.5)
col=0.5;
else
col=0.3;
g.setColor(col,col,col);
g.fillCircle(x, y, magnitude);
if (starMag<1 && settings.starnames)
g.drawString(starInfo[3],x,y+2);
g.flip();
}
}
function plotSky(lat,lon,date){
var longitude = toRadians(-lon);
var latitude = toRadians(lat);
var julianDay = toJulianDay(date.getFullYear(), date.getMonth()+1,date.getDate(),
date.getHours() + date.getTimezoneOffset() / 60,
date.getMinutes(), date.getSeconds());
storage = require('Storage');
f=storage.read("planetarium.data.csv","r");
g.clear();
//Common calculations based only on time
var t = (julianDay - 2451545.0) / 36525;
var zeta = toRadians((2306.2181 * t + 0.30188 * t * t + 0.017998 * t * t * t) / 3600);
var theta = toRadians((2004.3109 * t - 0.42665 * t * t - 0.041833 * t * t * t) / 3600);
var z = toRadians((2306.2181 * t + 1.09468 * t * t + 0.018203 * t * t * t) / 3600);
let starNumber = 0;
var starPositions = {};
var line,linestart = 0;
lineend = f.indexOf("\n");
while (lineend>=0) {
line = f.substring(linestart,lineend);
starNumber++;
//Process the star
starInfo = line.split(',');
drawStar(zeta,theta,z,julianDay,latitude,longitude,starInfo,starNumber,starPositions);
linestart = lineend+1;
lineend = f.indexOf("\n",linestart);
}
if (settings.constellations){
//First plot the extra stars for the constellations
fe=storage.read("planetarium.extra.csv","r");
linenum=linestart = 0;
lineend = fe.indexOf("\n");
let starNumber = 0;
while (lineend>=0) {
line = fe.substring(linestart,lineend);
starNumber++;
starInfo = line.split(',');
drawStar(zeta,theta,z,julianDay,latitude,longitude,starInfo,"e_"+starNumber,starPositions);
linestart = lineend+1;
lineend = fe.indexOf("\n",linestart);
}
//End of ploting extra stars
linenum=linestart = 0;
fc=storage.read("planetarium.const.csv","r");
lineend = fc.indexOf("\n");
while (lineend>=0) {
linenum++;
//In this file, each constelation are two lines. The first one the name, the second the lines joining stars
var name = fc.substring(linestart,lineend);
linestart = lineend+1;
lineend = fc.indexOf("\n",linestart);
var lines = fc.substring(linestart,lineend).split(',');
linestart = lineend+1;
lineend = fc.indexOf("\n",linestart);
g.setColor(0,255,0);
constelationShowing=false;
for (j=0;j<lines.length;j++){
positions = lines[j].split(' ');
positionStar1=starPositions[positions[0]];
positionStar2=starPositions[positions[1]];
//Both stars need to be visible
if (positionStar1 && positionStar2)
{
g.drawLine(positionStar1[0],positionStar1[1],positionStar2[0],positionStar2[1]);
constelationShowing=true;
}
else
constelationShowing=false;
g.flip();
}
//Write the name
if (constelationShowing && settings.consnames)
g.drawString(name,positionStar2[0]+10,positionStar2[1]);
}
}
}
const size = 240; //Bangle size screen
Bangle.setGPSPower(1);
//var gps = { fix : 0};
var prevSats = 0;
g.clear();
var settings = require('Storage').readJSON('planetarium.json',1)||
{ starnames:false,constellations:true,consnames:false};
g.setFontAlign(0,0);
Bangle.on('GPS',function(gp) {
date = new Date();
//gps = gp;
if (gp.fix) {
lat = gp.lat;
lon = gp.lon;
Bangle.setGPSPower(0);
setTimeout(function() {
plotSky(lat,lon,new Date());},0);
} else {
g.setFont("Vector",20);
g.drawString("Waiting for position",120,120);
g.setFont("Vector",15);
if (gp.satellites>prevSats || prevSats===0){
prevSats = gp.satellites;
g.clearRect(0,150,240,180);
g.drawString("Got "+gp.satellites+" satellites",120,160);
}
g.clearRect(0,180,240,220);
g.drawString("GMT:"+(date.getHours()+date.getTimezoneOffset() / 60)+":"+date.getMinutes()+":"+date.getSeconds(),120,200);
g.drawString(date.getDate()+'/'+date.getMonth()+1+"/"+date.getFullYear(),120,215);
g.flip();
}
});