var Lat,Lon,LatDir,LonDir
// Sun Outage Predictor
// Predicts sun outages for any satellite and ground station
// December 10, 1997
//
// Original Excel Macro developed by Hughes Communications Inc, Orbital Operations
// Orignal Concept and number crunching by Mark Shannon
// Orignal Excel Spreadsheet Macro design by Miro Svetinsky
// Conversion to JavaScript by Michael Shoffeitt for iXL, inc. mshoffeitt@ixl.com
//
// Note that most of these variables and formulas were named based upon the names they were given orginally in the
// Excel Macro - Hence some are named '
' as in 'F6' based upon the cell names from the Excel Macro...
// changes to calculator made by:
// schupp
// 031799
// with the help of Mark Shannon
//
// corrections for azimuth and elevation..
// corrections to Smartraound()
// display of year in 'yyyy' format where it appears
// extra comments..
//
// who ever works on this next, the current version of the .xls spreadsheet
// that this is taken from is: 'SunOutage Predicter 2.2.xls'
// you will want to get a copy of it.
//
// also, there seems to be a bug in atan2(x,y)
// the true implementation of it: atan2(y,x)
// (as of javascript 1.2)
//
// this may be the cause of erratic results in the future
// -s
var F3 = 0; // ground station altitude
var F6 = (1/298.26); // earth flattening factor
var F7 = 3441.7305; // radius of earth
var F8 = 22752.469; // synchronus orbit radius
//var F17 = Math.PI/180;
var GS_Lon = 0;
var GS_Lat = 0;
var Sat_Lon = 0;
var Out_Num = 0;
var Counter = 0;
var Epoch_Cons = 0;
var dayInMils = 60 * 60 * 24 * 1000;
var hrInMils = 60 * 60 * 1000;
var minInMils = 60 * 1000;
var Epoch_date;
function toRadians( degreeNum )
{
return ( degreeNum * ((Math.PI)/180));
}
function toDegrees( radianNum )
{
return ( radianNum / ((Math.PI)/180));
}
function makeArray(n)
{
this.length = n;
return this;
}
function SiteRecord(Name, NLat, WLon)
{
this.Name = Name;
this.NLat = NLat;
this.WLon = WLon;
}
function SatelliteRecord(Name, Lon)
{
this.Name = Name;
this.Lon = Lon;
}
function OutageRecord(OutDate, StartTime, EndTime, Duration, TZStartTime, TZEndTime)
{
this.OutDate = OutDate;
this.StartTime = StartTime;
this.EndTime = EndTime;
this.Duration = Duration;
this.TZStartTime = TZStartTime;
this.TZEndTime = TZEndTime;
}
function Find_Epoch()
{
Epoch_date = new Date();
Epoch_date.setYear(1904);
Epoch_date.setMonth(0);
Epoch_date.setDate(1);
Epoch_date.setHours(0);
Epoch_date.setMinutes(0);
Epoch_date.setSeconds(0);
var utcOffset = Epoch_date.getTimezoneOffset();
// Set Epoch date to include local daylight savings time.
Epoch_date.setTime(Epoch_date.getTime() - (utcOffset * minInMils));
Epoch = (eval("document.forms[0].Year.options[document.forms[0].Year.selectedIndex].value") - 1904) * 365.25;
if (document.forms[0].Season[0].checked)
Epoch = Epoch + 45;
else
Epoch = Epoch + 229;
Epoch = Math.floor(Epoch);
Epoch_Cons = Math.floor(Epoch);
}
function Find_Epoch2()
{
Epoch_date = new Date();
Epoch_date.setYear(1904);
Epoch_date.setMonth(0);
Epoch_date.setDate(1);
Epoch_date.setHours(0);
Epoch_date.setMinutes(0);
Epoch_date.setSeconds(0);
var utcOffset = Epoch_date.getTimezoneOffset();
// Set Epoch date to include local daylight savings time.
Epoch_date.setTime(Epoch_date.getTime() - (utcOffset * minInMils));
if (document.forms[0].Season[0].checked)
Epoch = (document.forms[0].Year.options[document.forms[0].Year.selectedIndex].value - 1904) * 365.25;
else
Epoch = (document.forms[0].Year.options[document.forms[0].Year.selectedIndex].value - 1903) * 365.25;
if (document.forms[0].Season[1].checked)
Epoch = Epoch + 45;
else
Epoch = Epoch + 229;
Epoch = Math.floor(Epoch);
Epoch_Cons = Math.floor(Epoch);
}
function Find_Outage_Angle()
{
// Calculate Outage Angle
// if (document.forms[0].Band[0].checked)
Outage_Angle = 11 / 3.95 / document.forms[0].meters.value + 0.25;
// else
// Outage_Angle = 11 / 11.95 / document.forms[0].meters.value + 0.25;
if (Outage_Angle < 0.27 || Outage_Angle > 4)
if (!confirm("Please check antenna size... (Continue?)"))
return;
}
function Find_Begin_Angle()
{
A26 = Begin_Outage;
D26 = A26 + 1460.5;
E26 = (D26)/36525;
F26 = (99.81355 + 0.9856474 * (A26 - 27759) + 360 * ((A26 - 27759) - Math.floor(A26 - 27759))) % 360;
G26 = 0.016751 - (0.000042 * E26);
H26 = 358.4759 + (35999.0498 * E26);
I26 = 279.6964 + (36000.769 * E26);
L26 = 23.4523 - (0.013 * E26);
J26 = (2 * G26 * Math.sin(H26 * Math.PI / 180) + 1.25 * G26 * G26 * Math.sin(H26 * Math.PI / 90)) * (180 / Math.PI);
K26 = I26 + J26;
O26 = 149504200 * (1 - G26 * Math.cos(H26 * Math.PI/180) - G26 * G26 / 2 * (Math.cos(H26 * Math.PI/90) - 1));
// This formula is broken up because of possible errors with atan2...
M26b = Math.cos(K26 * (Math.PI/180));
M26c = (Math.cos(L26 * Math.PI/180) * Math.sin(K26 * Math.PI/180));
M26a = Math.atan2(M26c, M26b);
M26 = (M26a * 180/Math.PI + 360) % 360;
N26 = Math.atan(Math.tan(L26 * Math.PI / 180) * Math.sin(M26 * Math.PI / 180)) * 180 / Math.PI;
Q26 = (F26 - GS_Lon + 360) % 360;
P26 = (F26 - Sat_Lon + 360) % 360;
S26 = Math.sin(M26 * (Math.PI / 180)) * Math.cos(N26 * Math.PI / 180) * O26 - Math.sin(Q26 * Math.PI / 180) * Math.cos(GS_Lat * Math.PI / 180) * 6380;
T26 = Math.sin(N26 * (Math.PI / 180)) * O26 - Math.sin(GS_Lat * Math.PI / 180) * 6380;
R26 = Math.cos(M26 * (Math.PI / 180)) * Math.cos(N26 * Math.PI / 180) * O26 - Math.cos(Q26 * Math.PI / 180) * Math.cos(GS_Lat * Math.PI / 180) * 6380;
X26 = (Math.sin(P26 * (Math.PI / 180)) * 42164) - (Math.sin(Q26 * (Math.PI / 180)) * Math.cos(GS_Lat * Math.PI / 180) * 6380);
W26 = Math.cos(P26 * Math.PI / 180) * 42165 - Math.cos(Q26 * Math.PI / 180) * Math.cos(GS_Lat * Math.PI / 180) * 6380;
Y26 = -Math.sin(GS_Lat * Math.PI / 180) * 6380;
U26 = (Math.atan2(S26,R26) * 180 / Math.PI + 360) % 360;
Z26 = (Math.atan2(X26,W26) * 180 / Math.PI + 360) % 360;
V26 = Math.atan(T26 / Math.sqrt(R26 * R26 + S26 * S26)) * 180 / Math.PI;
AA26 = Math.atan(Y26 / Math.sqrt(W26 * W26 + X26 * X26)) * (180 / Math.PI);
Sun_Dec = V26;
SC_Dec = AA26;
// Sun_Dec = Smartround(V26,3)
// SC_Dec = Smartround(AA26,3)
Begin_Angle = Math.acos(Math.sin(AA26 * Math.PI / 180) * Math.sin(V26 * Math.PI / 180) + Math.cos(AA26 * Math.PI / 180) * Math.cos(V26 * Math.PI / 180) * Math.cos((Z26 - U26) * Math.PI / 180)) * 180 / Math.PI;
}
function Find_End_Angle()
{
A27 = End_Outage;
D27 = A27 + 1460.5;
E27 = (D27)/36525;
F27 = (99.81355 + 0.9856474 * (A27 - 27759) + 360 * ((A27 - 27759) - Math.floor(A27 - 27759))) % 360;
G27 = 0.016751 - (0.000042 * E27);
H27 = 358.4759 + (35999.0498 * E27);
I27 = 279.6964 + (36000.769 * E27);
L27 = 23.4523 - (0.013 * E27);
J27 = (2 * G27 * Math.sin(H27 * Math.PI / 180) + 1.25 * G27 * G27 * Math.sin(H27 * Math.PI / 90)) * (180 / Math.PI);
K27 = I27 + J27;
O27 = 149504200 * (1 - G27 * Math.cos(H27 * Math.PI/180) - G27 * G27 / 2 * (Math.cos(H27 * Math.PI/90) - 1));
// This formula is broken up because of possible errors with atan2...
M27b = Math.cos(K27 * (Math.PI/180));
M27c = (Math.cos(L27 * Math.PI/180) * Math.sin(K27 * Math.PI/180));
M27a = Math.atan2(M27c, M27b);
M27 = (M27a * 180/Math.PI + 360) % 360;
N27 = Math.atan(Math.tan(L27 * Math.PI / 180) * Math.sin(M27 * Math.PI / 180)) * 180 / Math.PI;
Q27 = (F27 - GS_Lon + 360) % 360;
P27 = (F27 - Sat_Lon + 360) % 360;
S27 = Math.sin(M27 * (Math.PI / 180)) * Math.cos(N27 * Math.PI / 180) * O27 - Math.sin(Q27 * Math.PI / 180) * Math.cos(GS_Lat * Math.PI / 180) * 6380;
T27 = Math.sin(N27 * (Math.PI / 180)) * O27 - Math.sin(GS_Lat * Math.PI / 180) * 6380;
R27 = Math.cos(M27 * (Math.PI / 180)) * Math.cos(N27 * Math.PI / 180) * O27 - Math.cos(Q27 * Math.PI / 180) * Math.cos(GS_Lat * Math.PI / 180) * 6380;
X27 = (Math.sin(P27 * (Math.PI / 180)) * 42164) - (Math.sin(Q27 * (Math.PI / 180)) * Math.cos(GS_Lat * Math.PI / 180) * 6380);
W27 = Math.cos(P27 * Math.PI / 180) * 42165 - Math.cos(Q27 * Math.PI / 180) * Math.cos(GS_Lat * Math.PI / 180) * 6380;
Y27 = -Math.sin(GS_Lat * Math.PI / 180) * 6380;
U27 = (Math.atan2(S27,R27) * 180 / Math.PI + 360) % 360;
Z27 = (Math.atan2(X27,W27) * 180 / Math.PI + 360) % 360;
V27 = Math.atan(T27 / Math.sqrt(R27 * R27 + S27 * S27)) * 180 / Math.PI;
AA27 = Math.atan(Y27 / Math.sqrt(W27 * W27 + X27 * X27)) * 180 / Math.PI;
End_Angle = Math.acos(Math.sin(AA27 * Math.PI / 180) * Math.sin (V27 * Math.PI / 180) + Math.cos(AA27 * Math.PI / 180) * Math.cos(V27 * Math.PI / 180) * Math.cos((Z27 - U27) * Math.PI / 180)) * 180 / Math.PI;
}
function Smartround(n, sigdigit)
{
// May be used without permission as long as these 2 lines remain intact...
// Written by Michael Shoffeitt - 12/01/97
// modified by schupp 031899
//
// Usage: if i = 2.14532
// i = Smartround(i, 2) - i = 2.15
// i = Smartround(i, 3) - i = 2.145
neg = false;
if (n < 0)
{
neg = true;
n = Math.abs(n);
}
nString = "" + n + "00";
i = nString.indexOf(".", 0);
if (i>=0)
{
remainder = Math.round(eval(nString.substring(i+sigdigit, i+sigdigit+1) + "." + nString.substring(i+sigdigit+1, nString.length)));
addfactor = "" + remainder;
addlength = addfactor.length;
for (r=0; r< sigdigit - addlength; r++)
{
addfactor = "0" + addfactor;
}
addfactor = "." + addfactor;
nTemp = nString.substring(0,i + sigdigit);
n = eval(nTemp) + eval(addfactor);
nTemp = "" + n;
nTemp = nTemp.substring(0,i+sigdigit + 1);
if (neg)
{
nTemp = nTemp * -1;
}
return eval(nTemp);
}
else
{
if (neg)
{
n = n * -1;
}
return n;
}
}
function Calculate_Azimuth_Elevation()
{
// here are some of the values refered to by the formulas:
// they are defined for the javascript elsewhere, so dont uncomment these.
// -s
//
// F1 = GS_Lon = ground station longitude
// F2 = GS_Lat = Ground station latitude
// F3 = 0 = ground station altitude
// F4 = Sat_Lon = geosynchronous Satellite longitude
// F6 = (1/298.26) = earth flattening factor ( flattening constant or f_constant )
// F7 = 3441.7305 = radius of earth
// F8 = 22752.469 = synchronus orbit radius ( 42164.211 km )
F9 = toDegrees(Math.atan(Math.pow((1-F6),2)*Math.tan(toRadians(GS_Lat)))); // geocentric latitude
F11 = F7/Math.sqrt(1-F6*(2-F6)*Math.pow((Math.sin(toRadians(GS_Lat))),2)); // R
F12 = (F11+F3)*Math.cos(toRadians(GS_Lat)); // Ra
F13 = (F11*Math.pow((1-F6),2)+F3)*Math.sin(toRadians(GS_Lat)); // Rz
F14 = F8*Math.cos(toRadians(Sat_Lon-GS_Lon))-F12; // delta r(x)
F15 = F8*Math.sin(toRadians(Sat_Lon-GS_Lon)); // delta r(y)
F16 = -F13; // delta r(z)
F17 = -F14*Math.sin(toRadians(GS_Lat))+F16*Math.cos(toRadians(GS_Lat)); // delta r(north)
F18 = F14*Math.cos(toRadians(GS_Lat))+F16*Math.sin(toRadians(GS_Lat)); // delta r(zenith)
Azimuth = (720 - (toDegrees(Math.atan2(F15,F17))) )%360;
Elevation = toDegrees(Math.atan(F18/Math.sqrt(F17*F17+F15*F15)));
Elevation = Smartround(Elevation, 3);
document.forms[0].Elevation.value = Elevation;
Azimuth = Smartround(Azimuth, 3);
document.forms[0].Azimuth.value = Azimuth;
if (Elevation < 0.5)
{
alert("Satellite is not visible from ground station!");
}
}
function Check_Inputs()
{
if (eval("document.forms[0].meters.value") < 0.5 || eval("document.forms[0].meters.value") > 15)
{
if (!confirm("Please check antenna size... (Continue?)"))
{
return false;
}
}
if (eval("document.forms[0].Year.options[document.forms[0].Year.selectedIndex].value") < 2000 || eval("document.forms[0].Year.options[document.forms[0].Year.selectedIndex].value") > 2020)
{
if (!confirm("You are requesting suninterference data from the past ... (Continue?)"))
{
return false;
}
}
if (eval("Elevation") < 0.1)
{
if (!confirm("This satellite is not visible from the Ground Station!... (Continue?)"))
{
return false;
}
}
return true;
}
function getFullYear(d)
{
var y = d.getYear();
if (y < 1000)
y += 1900;
return y;
}
function formatDate(dateIn)
{
thisDate = new Date();
thisDate.setTime(dateIn.getTime() + (dateIn.getTimezoneOffset() * minInMils));
var currMonth = "" + (thisDate.getMonth() + 1);
var currDay = "" + thisDate.getDate();
monthOut = (currMonth.length == 1) ? "0" + currMonth + "/" : currMonth + "/";
dayOut = (currDay.length == 1) ? "0" + currDay + "/" : currDay + "/";
yrOut = getFullYear(thisDate);
return monthOut + dayOut + yrOut;
}
function formatTime(timeIn)
{
var thisTime = new Date();
thisTime.setTime(timeIn.getTime());
var currHrs = thisTime.getHours();
var currMins = thisTime.getMinutes();
var currSecs = "" + thisTime.getSeconds();
var isNeg = false;
var hrsFromUTC = 0;
var minsFromUTC = 0;
// Adjust for daylight savings time
minsFromUTC = thisTime.getTimezoneOffset();
if (minsFromUTC != 0)
{
hrsFromUTC = Math.floor(minsFromUTC / 60);
minsFromUTC %= 60;
}
currMins += minsFromUTC;
if (currMins >= 60)
{
currMins -= 60;
currHrs += 1;
}
if (currMins < 0)
{
currMins += 60;
currHrs -= 1;
}
currHrs += hrsFromUTC;
if (currHrs >= 24)
currHrs -= 24;
if (currHrs < 0)
currHrs += 24;
currHrs += "";
currMins += "";
hrOut = (currHrs.length == 1) ? "0" + currHrs + ":" : currHrs + ":";
minOut = (currMins.length == 1) ? "0" + currMins + ":" : currMins + ":";
secOut = (currSecs.length == 1) ? "0" + currSecs : currSecs;
return hrOut + minOut + secOut;
}
function formatDuration(startTime, endTime)
{
var startMins = startTime.getMinutes();
var startSecs = startTime.getSeconds();
var endMins = endTime.getMinutes();
var endSecs = endTime.getSeconds();
var minOffset = 0;
var durationSecs = endSecs - startSecs;
if (durationSecs < 0)
{
durationSecs += 60;
minOffset = 1;
}
var durationMins = endMins - startMins - minOffset;
if (durationMins < 0)
durationMins += 60;
durationMins += "";
durationSecs += "";
durationMins = (durationMins.length == 1) ? "0" + durationMins + ":" : durationMins + ":";
durationSecs = (durationSecs.length == 1) ? "0" + durationSecs : durationSecs;
return durationMins + durationSecs;
}
function Write_Out()
{
// this function is responsible for formating the results and
// wrting out the outage times in the display.
Begin_date = new Date();
Begin_date.setTime(Epoch_date.getTime() + (Begin_Outage * dayInMils));
End_date = new Date();
End_date.setTime(Epoch_date.getTime() + (End_Outage * dayInMils));
var Date_Text = formatDate(Begin_date);
var Begin_Time = formatTime(Begin_date);
var End_Time = formatTime(End_date);
var Duration_Time = formatDuration(Begin_date, End_date);
var TZBegin_date = new Date();
var TZEnd_date = new Date();
TZBegin_date.setTime(Begin_date.getTime() - (TZOffset * hrInMils));
TZEnd_date.setTime(End_date.getTime() - (TZOffset * hrInMils));
var TZBegin_Time = formatTime(TZBegin_date);
var TZEnd_Time = formatTime(TZEnd_date);
Outage[Out_Num - 1] = new OutageRecord(Date_Text, Begin_Time, End_Time, Duration_Time, TZBegin_Time, TZEnd_Time);
document.getElementById('Results').innerHTML=document.getElementById('Results').innerHTML+Date_Text+ " | " + Begin_Time + " | " + End_Time + " | " + Duration_Time + " | " + TZBegin_Time + " | " + TZEnd_Time + "
";
}
function Find_Start()
{
Begin_Outage = Epoch;
Find_Begin_Angle();
ref_Epoch = Epoch;
Found1 = false;
while (Begin_Angle > Outage_Angle && (Begin_Outage - ref_Epoch) < 1)
{
Y_Angle = Math.abs(SC_Dec - Sun_Dec);
if((Y_Angle)>(1 + Outage_Angle / 2))
{
Begin_Outage = Begin_Outage + (Y_Angle * 0.5);
Find_Begin_Angle();
}
if(Begin_Angle > (Outage_Angle * 4))
{
Begin_Outage = Begin_Outage + (Begin_Angle / 540);
Find_Begin_Angle();
}
Begin_Outage = Begin_Outage + 0.00005787;
Find_Begin_Angle();
}
Epoch = Begin_Outage;
if (Begin_Angle < Outage_Angle)
{
Found1 = true;
}
return
}
function Find_End()
{
End_Outage = Begin_Outage;
Find_End_Angle();
while (End_Angle < Outage_Angle)
{
End_Outage = End_Outage + 0.00005787;
Find_End_Angle();
}
End_Outage = End_Outage - 0.00005787;
Find_End_Angle();
}
function Find_Out()
{
Find_Start();
if (Found1)
{
Out_Num = Out_Num + 1;
Find_End();
Write_Out();
Epoch = End_Outage + 0.9;
Find_Begin_Angle();
}
if (Epoch-Epoch_Cons>15 && Out_Num==0)
{
//alert("Something may be wrong... No Outages Found...")
return;
}
return;
}
function Find_All()
{
Found1 = false;
while ((Out_Num == 0 || Found1 == true))
{
Find_Out();
}
}
function createTZ(TZIn, TZOffsetIn)
{
this.TZ = TZIn;
this.TZOffset = TZOffsetIn;
}
var timeZones = new makeArray(9);
var tmp_time = new Date();
timeZones[0] = new createTZ("PST", 8);
timeZones[1] = new createTZ("PDT", 7);
timeZones[2] = new createTZ("MST", 7);
timeZones[3] = new createTZ("MDT", 6);
timeZones[4] = new createTZ("CST", 6);
timeZones[5] = new createTZ("CDT", 5);
timeZones[6] = new createTZ("EST", 5);
timeZones[7] = new createTZ("EDT", 4);
timeZones[8] = new createTZ("Local Time", tmp_time.getTimezoneOffset()/60);
//alert(tmp_time.getTimezoneOffset()/60);
function Calculate()
{
//F3 = 0
//F6 = (1/298.26)
//F7 = 3441.7305
//F8 = 22752.469
//F17 = Math.PI/180
Out_Num = 0;
Counter = 0;
Epoch_Cons = 0;
TZ = "GMT";
TZOffset = 0;
for(var i=0; i";
document.getElementById('Results').innerHTML=document.getElementById('Results').innerHTML+"Date...... | Start... | End..... | Dur.. | Start... | End....." + "
";
document.getElementById('Results').innerHTML=document.getElementById('Results').innerHTML+"mm/dd/yyyy | hh:mm:ss | hh:mm:ss | mm:ss | hh:mm:ss | hh:mm:ss
";
document.getElementById('Results').innerHTML=document.getElementById('Results').innerHTML+"-----------|----------|----------|-------|----------|---------- " + "
";
if (!Check_Inputs())
{
return;
}
Find_Epoch();
Find_Outage_Angle();
Find_All();
document.getElementById('Results').innerHTML=document.getElementById('Results').innerHTML+"-----------|----------|----------|-------|----------|---------- " + "
";
Out_Num = 0;
Counter = 0;
Epoch_Cons = 0;
Find_Epoch2();
Find_Outage_Angle();
Find_All();
document.getElementById('Results').innerHTML=document.getElementById('Results').innerHTML+"-----------|----------|----------|-------|----------|---------- " + "
";
}
function Update_Station()
{
// change here
var MyVal
var ValArray=new Array();
var SubArray=new Array();
MyVal=document.forms[0].groundStation.options[document.forms[0].groundStation.selectedIndex].value;
if (MyVal !== null)
{
// Check position
ValArray=MyVal.split(",");
SubArray = ValArray[0].split(":") ; // The first subarray containing Lat:LatDir
Lat=SubArray[0];
LatDir=SubArray[1];
SubArray = ValArray[1].split(":"); // The second subarray containing Lon:LonDir
Lon=SubArray[0];
LonDir=SubArray[1];
}
if (LatDir=="South") document.forms[0].NLat.value = (-1)*Lat
else document.forms[0].NLat.value = 1*Lat;
if (LonDir=="East") document.forms[0].WLon.value = -1*Lon
else document.forms[0].WLon.value = 1*Lon;
GS_Lat=1*document.forms[0].NLat.value;
GS_Lon=1*document.forms[0].WLon.value;
}
function Update_Satellite()
{
var temp
temp=document.forms[0].Satellite.options[document.forms[0].Satellite.selectedIndex].value;
if (document.forms[0].Satellite.selectedIndex==0)
document.getElementById('OutputTitle').innerHTML="Solar interference with the CRC/AMB-OS Feeds on GE3 is expected at the following times:";
if (document.forms[0].Satellite.selectedIndex==1)
document.getElementById('OutputTitle').innerHTML="Solar interference with the ABC Radio Feeds on GE8 is expected at the following times:";
Sat_Lon = temp;
}
// This code prepared for up to 150 outages... Increase this array size to allow for more...
var Outage = new makeArray(1700)