<?xml version="1.0" encoding="UTF-8" ?> 
<Module>
<ModulePrefs title="NOAA Weather Satellites Tracking" directory_title="NOAA Weather Satellites Tracking" category="technology" category2="tools" author="Ciprian Sufitchi" author_email="csufitchi@gmail.com" author_affiliation="None" author_location="Fairfax, VA" screenshot="http://www.n2yo.com/img/gadgets/noaa.png" thumbnail="http://www.n2yo.com/img/gadgets/noaa-thumb.png" description="NOAA Weather Satellites Tracking on your Personalized Google Homepage." scaling="false" scrolling="false" singleton="false" title_url="http://www.n2yo.com" author_link="http://www.n2yo.com"> 
<Require feature="com.google.gadgets.analytics" /> 
</ModulePrefs>
<Content type="html">
<![CDATA[
<style type="text/css">
#satmap
{ width:100%; height:100%;text-align: center}
.style1 
{background-color:#ffffff;font-weight:bold;border:2px #006699 solid;}
#infocornertop
{position:absolute;left:0px;top:0px;font: 10px Arial} 
#infocornerbottom
{position:absolute;font: 10px Arial}
#infocenter
{position:absolute;font: 10px Arial}
#home {position:absolute; color:#6A0000;font: 10px Arial}
#btn {   
color:#050;   
font: 10px 'trebuchet ms',helvetica,sans-serif;   
background-color:#fed;   
border:1px solid;   
border-color: #696 #363 #363 #696;
position:absolute;
top:0px;
right:0px;
}
#hdr {font: 10px 'trebuchet ms',helvetica,sans-serif;padding:1px;}
#satselect {font: 10px 84% 'trebuchet ms',helvetica,sans-serif;}
</style>
<div id="hdr">
<SELECT id="satselect" onChange='javascript:SATID=this.value;startSatModule()'>
<OPTION value='33591'>NOAA 19</OPTION>
<OPTION value='28654'>NOAA 18</OPTION>
<OPTION value='27453'>NOAA 17</OPTION>
<OPTION value='26536'>NOAA 16</OPTION>
<OPTION value='25338'>NOAA 15</OPTION>
<OPTION value='23455'>NOAA 14</OPTION>
<OPTION value='21263'>NOAA 12</OPTION>
<OPTION value='19531'>NOAA 11</OPTION>
<OPTION value='16969'>NOAA 10</OPTION>
<OPTION value='15427'>NOAA 9</OPTION>
<OPTION value='11416'>NOAA 6</OPTION>
<OPTION value='28654'>TIROS N</OPTION>
</SELECT>
<span style='position:absolute;top:0px;right:0px;'><input type="radio" name="maptype" onClick='setTrackingType(1)'>Zoom/Center <input type="radio" name="maptype" onClick='setTrackingType(0)' CHECKED>World view</span></div>
<div id="insert"></div>

<div id="satmap" style="height: 250px; border: 1px solid #999999;background:#FFFFFF"></div>
<div id="infocornertop"></div>
<div id="infocornerbottom"></div>
<div id="infocenter"></div>
<div id="home" style="display:none;">You are here</div>

<script src="http://maps.google.com/maps?file=api&v=3" type="text/javascript"></script>
<script src="http://www.n2yo.com/js/jquery.js" type="text/javascript"></script>
<script src="http://www.n2yo.com/js/polylineencoder.js" type="text/javascript"></script>
<!--<script src="http://www.n2yo.com/js/gadget.js" type="text/javascript"></script>-->
<script type="text/javascript">
//SATID = getQuerystring('satid','25544');
SATID = 33591;
ZOOM=0;
function getQuerystring(key, default_)
{
  if (default_==null) default_=""; 
  key = key.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regex = new RegExp("[\\?&]"+key+"=([^&#]*)");
  var qs = regex.exec(window.location.href);
  if(qs == null)
    return default_;
  else
    return qs[1];
} 
//********//
var SATID;
var satmap;
var setIntervalId;
var footOverlay;
var STEP;
var ZOOM=0;
var counter=0;
var dArray = new Array(); // array for tracking
var gArray = new Array(); // array for drawing
var dayNightOverlay; // overaly for drawing the terminator
var sunOverlay; // overaly for drawing the Sun
var sMarker;
var altitude;
var TRACKING_STYLE=0; // 0 is World View, 1 is Zoom and Center
function ObjectPosition(a,b,c,d)
{
	this.id=a;
	this.latlng=b;
	this.alt=c; // km
	this.sp=d; // m/s
}
function startSatModule()
{
	dArray = new Array(); // reset tracking
	gArray = new Array(); // reset drawing
	counter=0;
	clearInterval (setIntervalId);
	satmap = new GMap2($("#satmap").get(0));
	satmap.setMapType(G_PHYSICAL_MAP);
	var centerWorld = new GLatLng(0,0);
    var icon = new GIcon();
    icon.image = "http://www.n2yo.com/inc/saticon.php?t=0&s="+SATID;
    icon.shadow = "http://www.n2yo.com/inc/saticon.php?t=1&s="+SATID;
    icon.iconSize = new GSize(16.0, 16.0);
    icon.shadowSize = new GSize(25.0, 16.0);
    icon.iconAnchor = new GPoint(8.0, 8.0);
    icon.infoWindowAnchor = new GPoint(8.0, 8.0);
	sMarker = new GMarker(centerWorld, icon);
	dayNightOverlay = getDayNightOverlay();
	sunOverlay = getSunOverlay();
	satmap.addOverlay(sunOverlay);	
	satmap.addOverlay(dayNightOverlay);	
	if (TRACKING_STYLE == 0)
		satmap.setCenter(centerWorld, ZOOM);
	if (TRACKING_STYLE == 1)
		satmap.setCenter(centerWorld, 7);
	var hc = satmap.getSize().height;
	var wc = satmap.getSize().width;
	var top = $("#satmap").get(0).offsetTop;
	$("#infocornertop").css("top",top); 
	$("#infocenter").css("top", top+hc/2-30); 
	$("#infocenter").css("left", wc/2-30); 
	$("#infocenter").html("Please wait"); 
	$("#infocornerbottom").css("top", top); 
	$("#infocornerbottom").css("left", wc-115); 
	$("#infocornerbottom").html("Powered by <A HREF=\"http://www.n2yo.com?rid=g"+SATID+"\">N2YO.com</A>"); 
	getLocation();
	if (SATID==9999999)
	{
		$("#infocenter").css("top", top+hc/2-30); 
		$("#infocenter").css("left", wc/2-60); 
		$("#infocenter").html("Tracking data not available"); 
	}
	callN2YO(SATID, STEP);
	setIntervalId = setInterval("animateSat()", 1000);
}
function callN2YO(sid, step)
{
	var r = Math.random() * Date.parse(new Date());
	var url = 'http://www.n2yo.com/sat/gg.php?s='+sid+'&d='+step+'&RandomKey='+r;
	_IG_FetchContent(url, getOrbit);
}
function getOrbit(txt)
{
	//alert(txt);
	var txtArray = txt.split("\n");
	var miscInfo = txtArray[0].split("|");
	var startPoint = parseInt(miscInfo[0])+1;
	STEP = parseInt(miscInfo[1]);
	var startPosition;
	var currentTime = new Date()
	var dd=currentTime.toGMTString();
	var cUTCTime=Date.parse(dd)/1000;
	for (var i=startPoint;i<txtArray.length;i++)
	{
		var coord = txtArray[i].split("|");
		if (Math.abs(cUTCTime-parseInt(coord[3]))<STEP)
		{
			startPosition=i;
			break;
		}
	}


	for (var i=startPosition;i<txtArray.length;i++)
	{
		var coord = txtArray[i].split("|");
		dArray[i-startPosition] = new ObjectPosition(SATID,new GLatLng(coord[0],coord[1]),parseFloat(coord[2]),parseFloat(coord[4]));
	}
	for (var i=1;i<txtArray.length;i++)
	{
		var coord = txtArray[i].split("|");
		gArray[i-1] = new GLatLng(coord[0],coord[1]);
	}
	//GLog.write(dArray[0].sp + '  ');
	/*
	var drawingOverlay = new GPolyline(gArray, "#ff0000", 1);
	satmap.addOverlay(drawingOverlay);

	*/

	var polylineEncoder = new PolylineEncoder();   
  	var drawingOverlay = polylineEncoder.dpEncodeToGPolyline(gArray, '#ff0000', 1, 0.5); 
	satmap.addOverlay(drawingOverlay);

	satmap.addOverlay(sMarker);	
	sMarker.hide();
}
function animateSat()
{
	//var disp = dArray[counter].lat();
	var currPos = getInterpolatedData();
	if (currPos != null)
	{
		var clat = (currPos.latlng).lat();
		var clng = (currPos.latlng).lng();
		var calt = currPos.alt;
		var dir = "";
		if (calt>altitude) dir = "&uarr;";
		else dir = "&darr;";
		altitude = calt;
		var csp = currPos.sp;
		$("#infocenter").html("");
		$("#infocornertop").html("LAT: "+round(clat)+"<br>LNG: "+round(clng)+"<br>ALT: "+round(calt)+" "+dir+"<br>SPD: "+round(csp));
		sMarker.show();
		sMarker.setLatLng(currPos.latlng);
		if (TRACKING_STYLE == 1)
		{
			satmap.panTo(currPos.latlng);
		}

	/*
		if (counter%10 == 0)  // every 10 seconds, redraw the terminator
		{
			if(footOverlay != null)
				satmap.removeOverlay(footOverlay);
			var polylineEncoder = new PolylineEncoder();   
			footOverlay = polylineEncoder.dpEncodeToGPolyline(footPrintArray(calt, clat, clng, 60), '#3300CC', 1, 0.7); 
			satmap.addOverlay(footOverlay);
		}
	*/
		if ((counter%300 == 0) && (counter>0))  // every 5 minutes, redraw the terminator
		{
			satmap.removeOverlay(dayNightOverlay);
			dayNightOverlay = getDayNightOverlay();
			satmap.addOverlay(dayNightOverlay);
			satmap.removeOverlay(sunOverlay);
			sunOverlay = getSunOverlay();
			satmap.addOverlay(sunOverlay);
		}
		counter++;
	}
}
function getInterpolatedData()
{
	// Find the interval where the position should be calculated
	var interval = Math.floor(counter/STEP);
	if ((dArray.length !=0)&&(dArray.length-2>interval))
	{
		// The calculation will be executed on the range interval...interval+1
		if(Math.abs((dArray[interval+1].latlng).lng()  -   (dArray[interval].latlng).lng())>300)
		{
			// the limit of the map has been reached
			if ((dArray[interval+1].latlng).lng() < 0) 
			{
				var dlng = ((dArray[interval+1].latlng).lng() + 360 - (dArray[interval].latlng).lng())/STEP;
			}
			else
			{
				var dlng = ((dArray[interval+1].latlng).lng() - 360 - (dArray[interval].latlng).lng())/STEP;
			}
		}
		else
		{
			var dlng = ((dArray[interval+1].latlng).lng() - (dArray[interval].latlng).lng())/STEP;
		}
		var dlat = ((dArray[interval+1].latlng).lat() - (dArray[interval].latlng).lat())/STEP;
		var dalt = (dArray[interval+1].alt - dArray[interval].alt)/STEP;
		var dsp = (dArray[interval+1].sp - dArray[interval].sp)/STEP;
		var plat = dlat*(counter%STEP)+(dArray[interval].latlng).lat();
		var plng = dlng*(counter%STEP)+(dArray[interval].latlng).lng();
		var palt = dalt*(counter%STEP)+dArray[interval].alt;
		//var psp = dsp*(counter%STEP)+dArray[interval].sp;
		var psp = getSpeed(plat, dlat, dlng, palt);

		var iObject = new ObjectPosition(SATID,new GLatLng(plat,plng),palt,psp);
		return iObject;
	}
	else if (dArray.length-2>interval)
	{
		clearInterval (setIntervalId);
		callN2YO(SATID, STEP);
		counter=0;
		setIntervalId = setInterval ("animateSat()", 1000);		
	}
}

function getSpeed(x1, dx, dy, h)
{
		// calculate speed, as it is not computed correctly on the server
		var dlat=dx*Math.PI/180;
		var dlon=dy*Math.PI/180;
		var lat1=x1*Math.PI/180;
		var lat2=(x1+dx)*Math.PI/180;
		var a = Math.sin(dlat/2) * Math.sin(dlat/2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dlon/2) * Math.sin(dlon/2); 
		var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
		var speed = (h + 6378.135) * c;
		return speed;
}
function setTrackingType(type)
{
	if (type==1)
	{
		TRACKING_STYLE = 1;
		satmap.removeOverlay(dayNightOverlay);
		dayNightOverlay = getDayNightOverlay();
		satmap.addOverlay(dayNightOverlay);
		satmap.setZoom(7);
		return true;
	}

	if (type==0)
	{
		TRACKING_STYLE = 0;
		satmap.setZoom(ZOOM);
		satmap.removeOverlay(dayNightOverlay);
		dayNightOverlay = getDayNightOverlay();
		satmap.addOverlay(dayNightOverlay);
		satmap.panTo(new GLatLng(0,0))

		return true;
	}
}
function round(num) 
{ 
	var prefix = ""; 
	var suffix = ""; 
	if ( num < 0 ) 
	{ 
		prefix = "-"; 
		suffix = ""; 
		num = - num; 
	} 
	var temp = Math.round( num * 100.0 ); // convert to pennies! 
	if ( temp < 10 ) return prefix + "0.0" + temp + suffix; 
	if ( temp < 100 ) return prefix + "0." + temp + suffix; 
	temp = prefix + temp; // convert to string! 
	return temp.substring(0,temp.length-2) + "." + temp.substring(temp.length-2) + suffix; 
} 
function getDayNightOverlay()
{
	var cnt = 0;
	var dayNightArray = new Array();
	var lngStart = satmap.getBounds().getSouthWest().lng();
	var latStart = satmap.getBounds().getSouthWest().lat();
	var latEnd = latStart;
	var lngEnd = satmap.getBounds().getNorthEast().lng();
	var j = jd();
	latStart=-90;
	lngStart=-180;
	latEnd=-90;
	lngEnd=180;
	for (var i=lngStart; i<=lngEnd; i++) 
	{
		var dt = new Date();
		var LT = dt.getUTCHours() + dt.getUTCMinutes()/60;
		var tau = 15*(LT-12);
		var dec = sunDecRA(1,j);
		var K = Math.PI/180.0;
		var longitude=i+tau;
		var tanLat = - Math.cos(longitude*K)/Math.tan(dec*K);						
		var arctanLat = Math.atan(tanLat)/K;
		dayNightArray[cnt]=new GLatLng(arctanLat,i);
		cnt++;
	}

	dayNightArray[0]=new GLatLng(latStart,lngStart);
	dayNightArray[dayNightArray.length-1]=new GLatLng(latEnd,lngEnd);
	//var dayNightOverlay = new GPolygon(dayNightArray, "#7171FF", 1, 0.5,"#7171FF",0.5);
	var polylineEncoder = new PolylineEncoder();
	var dumbArray = new Array();
	dumbArray[0] = dayNightArray;
	var dayNightOverlay = polylineEncoder.dpEncodeToGPolygon(dumbArray, "#FFFF33", 1, 0.1,"#FFFF33",0.2); 
	//GLog.write(lngStart + '  ' + lngEnd + '  ' + latEnd);
	return dayNightOverlay;
}

function getSunOverlay()
{
	var j = jd();
	var dec = sunDecRA(1,j);
	var dt = new Date();
	var LT = dt.getUTCHours() + dt.getUTCMinutes()/60;
	var tau = 15*(LT-12);
    var icon = new GIcon();
    icon.image = "http://www.n2yo.com/img/sun.gif";
    icon.shadow = "http://www.n2yo.com/img/shadow-sun.png";
    icon.iconSize = new GSize(16.0, 16.0);
    icon.shadowSize = new GSize(25.0, 16.0);
    icon.iconAnchor = new GPoint(8.0, 8.0);
    icon.infoWindowAnchor = new GPoint(8.0, 8.0);
	var sunMarker = new GMarker(new GLatLng(dec,-tau), icon);
	return sunMarker;
	//GLog.write(tau + '  ' + dec);
}
function jd() {
	var dt = new Date();
    MM=dt.getMonth() + 1;
    DD=dt.getDate();
    YY=dt.getFullYear();
    HR=dt.getUTCHours();
    MN= dt.getUTCMinutes();
    SC=0;
    with (Math) {  
      HR = HR + (MN / 60) + (SC/3600);
      GGG = 1;
      if (YY <= 1585) GGG = 0;
      JD = -1 * floor(7 * (floor((MM + 9) / 12) + YY) / 4);
      S = 1;
      if ((MM - 9)<0) S=-1;
      A = abs(MM - 9);
      J1 = floor(YY + S * floor(A / 7));
      J1 = -1 * floor((floor(J1 / 100) + 1) * 3 / 4);
      JD = JD + floor(275 * MM / 9) + DD + (GGG * J1);
      JD = JD + 1721027 + 2 * GGG + 367 * YY - 0.5;
      JD = JD + (HR / 24);
    }
    return JD;
}
function sunDecRA (what, jd) {
		var PI2 = 2.0*Math.PI;
		var cos_eps = 0.917482;
		var sin_eps = 0.397778;				
		var M, DL, L, SL, X, Y, Z, R;
		var T, dec, ra;		
		T = (jd - 2451545.0) / 36525.0;	// number of Julian centuries since Jan 1, 2000, 0 GMT								
		M = PI2*frac(0.993133 + 99.997361*T);
		DL = 6893.0*Math.sin(M) + 72.0*Math.sin(2.0*M);
		L = PI2*frac(0.7859453 + M/PI2 + (6191.2*T+DL)/1296000);
		SL = Math.sin(L);
		X = Math.cos(L);
		Y = cos_eps*SL;
		Z = sin_eps*SL;
		R = Math.sqrt(1.0-Z*Z);
		dec = (360.0/PI2)*Math.atan(Z/R);
		ra = (48.0/PI2)*Math.atan(Y/(X+R));
		if (ra<0) ra = ra + 24.0;
		if (what==1) return dec; else return ra;			
}
function frac(X) {
 X = X - Math.floor(X);
 if (X<0) X = X + 1.0;
 return X;		
}
function getLocation()
{
	script = document.createElement('script');
	script.src = 'http://www.n2yo.com/sat/json.php?callback=initialize';
	document.body.appendChild(script);
}
function initialize(obj){
    var icon = new GIcon();
    icon.image = "http://www.n2yo.com/img/dot.gif";
    icon.iconSize = new GSize(7.0, 7.0);
    icon.iconAnchor = new GPoint(3.0, 3.0);
    icon.infoWindowAnchor = new GPoint(3.0, 3.0);
	var home = new GLatLng(obj['lat'],obj['lng']);
	var hMarker = new GMarker(home,icon);
	satmap.addOverlay(hMarker);
	//var markerOffset = satmap.fromLatLngToDivPixel(hMarker.getPoint());
	//$("#home").show().css({ top:markerOffset.y, left:markerOffset.x-20 });

}
/////////////////////////
	function footPrintArray(salt, lat1, lon1, points)
	{

		var parr = new Array();
		re=6375;
		k = re/(re+salt);

		max=Math.acos(k) - (0.1 * 3.141)/180;	// protection 0.01 degrees to avoid an exception
		var dg = max/points;
		//K I
		for (i=0; i<points; i++)
		{
			lat2 = (lat1 * 3.141)/180 - max + i*dg;
			gamma = (lon1 * 3.141)/180;
			var alfa = Math.sin((lat1 * 3.141)/180);
			var beta = Math.cos((lat1 * 3.141)/180);
			lon2 = gamma - Math.acos((k-alfa*Math.sin (lat2))/(beta*Math.cos(lat2)));
			//alert((lon2*180)/3.14);
			parr[i] = new GLatLng((lat2*180)/3.14, (lon2*180)/3.14);
		}
		//K II
		for (i=0; i<points; i++)
		{
			lat2 = (lat1 * 3.141)/180 + i*dg;
			gamma = (lon1 * 3.141)/180;
			var alfa = Math.sin((lat1 * 3.141)/180);
			var beta = Math.cos((lat1 * 3.141)/180);
			lon2 = gamma - Math.acos((k-alfa*Math.sin (lat2))/(beta*Math.cos(lat2)));
			//alert((lon2*180)/3.14);
			parr[points+i] = new GLatLng((lat2*180)/3.14, (lon2*180)/3.14);
		}
		//K III
		for (i=0; i<points; i++)
		{
			lat2 = (lat1 * 3.141)/180 + max-i*dg;
			gamma = (lon1 * 3.141)/180;
			var alfa = Math.sin((lat1 * 3.141)/180);
			var beta = Math.cos((lat1 * 3.141)/180);
			lon2 = gamma + Math.acos((k-alfa*Math.sin (lat2))/(beta*Math.cos(lat2)));
			//alert((lon2*180)/3.14);
			parr[2*points+i] = new GLatLng((lat2*180)/3.14, (lon2*180)/3.14);
		}
		//K IV
		for (i=0; i<points; i++)
		{
			lat2 = (lat1 * 3.141)/180 -i*dg;
			gamma = (lon1 * 3.141)/180;
			var alfa = Math.sin((lat1 * 3.141)/180);
			var beta = Math.cos((lat1 * 3.141)/180);
			lon2 = gamma + Math.acos((k-alfa*Math.sin (lat2))/(beta*Math.cos(lat2)));
			//alert((lon2*180)/3.14);
			parr[3*points+i] = new GLatLng((lat2*180)/3.14, (lon2*180)/3.14);
		}
		parr[4*points] = parr[0];

		return parr;
	}
_IG_RegisterOnloadHandler(function() {
    new startSatModule();
});
//********//
</script>
  ]]>
   </Content> 
</Module>