<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Kerbal Orbits</title>
<script type="text/javascript">
// http://www.nihilogic.dk/labs/canvas2image/
// https://developer.mozilla.org/en/Drawing_Graphics_with_Canvas
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-2d-context
// http://www.w3schools.com/jsref/default.asp

var mainCanvasCtx, mainCanvas;

var mouseIsDown = false;
var mouseIsDragging = false;
var cursorClickX = 0, cursorClickY = 0;
var cursorLastX = 0, cursorLastY = 0;
var pi = Math.PI;
var phi = (1 + Math.sqrt(5))/2;
var debugDiv = null;

function writedbg(msg) {if(debugDiv) debugDiv.value += msg + "\n";}

function frgba(r, g, b, a) {return ["rgba(", r, ",", g, ",", b, ",", a, ")"].join("");}
function frgb(r, g, b) {return ["rgb(", r, ",", g, ",", b, ")"].join("");}


// get a URL parameter by name
function getURL_Param(paramName, defVal)
{
	paramName = paramName.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
	var regexS = "[\\?&]"+paramName+"=([^&#]*)";
	var regex = new RegExp(regexS);
	var results = regex.exec(window.location.href);
	if(results == null)
		return defVal;
	else
		return results[1];
}

//************************************************************************************************

var KERBIN_R = 600e3
var KERBIN_GM = (9.80665*KERBIN_R*KERBIN_R);// A = M*G/r^2, M*G = A*r^2, A = 9.8665 m/s^2, r = KERBIN_R m
var infinity = 1.7976931348623157E+10308;

var periapsis = 0, apoapsis = 0;
var periapsisVel = 0, apoapsisVel = 0;// these are calculated from the above for elliptical orbits
var elliptical = true;

var lenScale = 1;
var velScale = 1;

var zooming = false;
var savedScale = 0;

var safety = false;

//************************************************************************************************

var scale = 2000e3;
var canvasMinX = -scale, canvasMinY = -scale;
var canvasSizeX = 3*scale, canvasSizeY = 2*scale;
var width = 0, height = 0;
var scaleX, scaleY;

// Screen/world coordinate transforms
function s2w_x(x) {return (x/scaleX) + canvasMinX;}
function s2w_y(y) {return ((height - y)/scaleY) + canvasMinY;}
function w2s_x(x) {return (x - canvasMinX)*scaleX;}
function w2s_y(y) {return height - (y - canvasMinY)*scaleY;}

function Circle(ctx, x, y, r) {
	ctx.beginPath();
	ctx.arc((x - canvasMinX)*scaleX, (y - canvasMinY)*scaleY, r, 0, 2*pi, false);
	ctx.stroke();
}

function Line(ctx, x, y, x2, y2) {
	ctx.beginPath();
	ctx.moveTo((x - canvasMinX)*scaleX, (y - canvasMinY)*scaleY);
	ctx.lineTo((x2 - canvasMinX)*scaleX, (y2 - canvasMinY)*scaleY);
	ctx.stroke();
}


function DrawMainCanvas()
{
	var ctx = mainCanvasCtx;
	ctx.fillStyle = "#EEEEEE";
	ctx.fillRect(0, 0, mainCanvas.width, mainCanvas.height);
	var width = ctx.canvas.width;
	var height = ctx.canvas.height;
	var scale = canvasSizeX/(ctx.canvas.width + 1);
	var aspect = ctx.canvas.width/ctx.canvas.height;
	
	ctx.save();
	ctx.translate(0, ctx.canvas.height);
	ctx.scale(1.0, -1.0);
	ctx.lineWidth = 1;
	
	ctx.fillStyle = "#000088";
	ctx.strokeStyle = "#000000";
	ctx.beginPath();
	ctx.arc(w2s_x(0), w2s_y(0), KERBIN_R/scale, 0, 2*pi, false);
	ctx.fill();
	
	ctx.strokeStyle = "#6666AA";
	ctx.beginPath();
	ctx.arc(w2s_x(0), w2s_y(0), (KERBIN_R + 35e3)/scale, 0, 2*pi, false);
	ctx.stroke();
	
	semimaj = (apoapsis + periapsis)/2;
	semimin = Math.sqrt(apoapsis*periapsis);
	
	ctx.strokeStyle = "#000000";
	ctx.beginPath();
	ctx.moveTo(w2s_x(apoapsis), w2s_y(0));
	n = 720
	for(j = 0; j <= n; ++j) {
		th = Math.PI*2.0*j/n;
		x = w2s_x(Math.cos(th)*semimaj + semimaj - periapsis);
		y = w2s_y(Math.sin(th)*semimin);
		ctx.lineTo(Math.min(2*width, Math.max(-width, x)), Math.min(2*height, Math.max(-height, y)));
	}
	ctx.stroke();
	
	ctx.restore();
}

function SetFromApoapsisPeriapsisEll(peri, apo)
{
	apoapsis = apo;
	periapsis = peri;
	// Can not make an elliptical trajectory parabolic/hyperbolic by setting apsides
	if(apoapsis < periapsis) {
		tmp = apoapsis;
		apoapsis = periapsis;
		periapsis = tmp;
	}
	periapsisVel = Math.sqrt(KERBIN_GM*(2.0/periapsis - 2.0/(periapsis + apoapsis)));
	apoapsisVel = Math.sqrt(KERBIN_GM*(2.0/apoapsis - 2.0/(periapsis + apoapsis)));
}

function SetFromApoapsis(apo)
{
	if(elliptical)
		SetFromApoapsisPeriapsisEll(periapsis, apo);
	else // Parabolic/hyperbolic
		SetFromApoapsisApovel();
}

function SetFromPeriapsis(peri)
{
	if(elliptical)
		SetFromApoapsisPeriapsisEll(peri, apoapsis);
	else // Parabolic/hyperbolic
		SetFromPeriapsisPerivel();
}

function SetFromApovelPerivel(apovel, perivel)
{
	// v = sqrt(mu*(2.0/r - 1/a));
	// 
	// So:
	// r1 = 2.0/(2.0/r0 - v0*v0/mu) - r0;
	// v1 = sqrt(mu*(2.0/r1 - 2.0/(r0 + r1)));
	// 
	// Wolfram Alpha to the rescue...
	// If v0*v0 != v0*v1: (v0 != v1, false for circular orbits)
	// 	r0 = 2*mu/(v0*v0 - v0*v1)
	// If v0*(v0 + v1) != 0: (v0 > 0 and v0 + v1 > 0, which is always true for sane numbers)
	// 	r0 = 2*mu/(v0*(v0 + v1))
	if(apovel > perivel) {
		tmp = apovel;
		apovel = periapsisVel;
		perivel = tmp;
	}
	periapsisVel = perivel;
	apoapsisVel = apovel;
	periapsis = 2*KERBIN_GM/(perivel*(perivel + apovel));
	apoapsis = 2.0/(2.0/periapsis - perivel*perivel/KERBIN_GM) - periapsis;
//	apoapsisVelCheck = Math.sqrt(KERBIN_GM*(2.0/apoapsis - 2.0/(periapsis + apoapsis)));
}

function SetFromPeriapsisPerivel(peri, perivel)
{
	periapsis = peri;
	periapsisVel = perivel;
	// Can make an elliptical trajectory parabolic/hyperbolic
	periEscVel = Math.sqrt(2.0*KERBIN_GM/periapsis);
	if(periapsisVel > periEscVel)
	{
		elliptical = false;
		apoapsis = infinity;
		// Excess velocity
		apoapsisVel = Math.sqrt(2.0*((periapsisVel*periapsisVel)/2.0 - KERBIN_GM/periapsis));
	}
	else
	{
		elliptical = true;
		apoapsis = 2.0/(2.0/periapsis - periapsisVel*periapsisVel/KERBIN_GM) - periapsis;
		apoapsisVel = Math.sqrt(KERBIN_GM*(2.0/apoapsis - 2.0/(periapsis + apoapsis)));
	}
}

function SetFromApoapsisApovel(apo, apovel)
{
	apoapsis = apo;
	apoapsisVel = apovel;
	// Can make an elliptical trajectory parabolic/hyperbolic, and if so, swaps periapsis/apoapsis
	// V = sqrt(KERBIN_GM*(2.0/r - 2.0/(peri + apo)))
	// 2.0/(2.0/apo - V^2/KERBIN_GM) - apo = peri
	apoEscVel = Math.sqrt(2.0*KERBIN_GM/apoapsis);
	if(apoapsisVel > apoEscVel)
	{
		elliptical = false;
		periapsis = apoapsis;
		apoapsis = infinity;
		// apoapsisVel is excess velocity
		periapsisVel = apoapsisVel;
		apoapsisVel = Math.sqrt(2.0*((periapsisVel*periapsisVel)/2.0 - KERBIN_GM/periapsis));
	}
	else
	{
		elliptical = true;
		periapsis = 2.0/(2.0/apoapsis - apoapsisVel*apoapsisVel/KERBIN_GM) - apoapsis;
		periapsisVel = Math.sqrt(KERBIN_GM*(2.0/periapsis - 2.0/(periapsis + apoapsis)));
	}
}

// Taylor series approximation of inverse of Kepler's equation
function InvKep(M, e)
{
	// 3! = 6, 5! = 120, 7! = 540, 9! = 362880
	me = 1 - e
	me2 = me*me
	me3 = me2*me
	me4 = me2*me2
	me7 = me4*me3
	me10 = me7*me3
	me13 = me10*me3
	
	e2 = e*e
	e3 = e2*e
	e4 = e3*e
	
	E = M*(1.0/me -
			M*M*(e/(me4*6) +
				M*M*((9*e2 + e)/(me7*120) -
					M*M*((225*e3 + 54*e2 + e)/(me10*540) +
						M*M*(11025*e4 + 4131*e3 + 243*e2 + e)/(me13*362880)))));
	return E;
}

function SetFromDataPoints(data)
{
	// We only have velocity, altitude, 
	// v = sqrt(mu*(2/r - 1/a))
	
	// Given mu, v0, r0, v1, r1:
	// v0 = sqrt(mu*(2/r0 - 1/a))
	// v1 = sqrt(mu*(2/r1 - 1/a))
	// r0 = 2/(v0^2/mu + 1/a)
	// r1 = 2/(v1^2/mu + 1/a)
	// a = 1/(2/r0 - v0^2/mu)
	// a = 1/(2/r1 - v1^2/mu)
	// a = (apo + peri)/2
	
	// E = ((v*v)/2.0 - (G*m)/r)
	
	// Period:
	// P = 2*pi*sqrt(a**3/mu)
	// Mean anomaly:
	// M = 2*pi*t/P = t/sqrt(a**3/mu)
	// M = E - e*sin(E)
	// t/sqrt(a**3/mu) = E - e*sin(E)
	// E = InvKep(t/sqrt(a**3/mu), e)
	// tan(halftheta) = sqrt((1 + e)/(1 - e))*tan(E/2)
	// r = a*(1 - e*e)/(1 + e*cos(theta))
}

// Set up ellipse from altitude, velocity, and angle
function SetFromRVA(r, v, ang)
{
	// angle is of velocity vector, tangent to ellipse, to a ray from the planet
	cosa = Math.cos(ang)
	sina = Math.sin(ang)
	//a = 1/(2/r - v^2/mu)
	a = 1.0/(2.0/r - v*v/KERBIN_GM);// semimajor axis
	
	// Only known with e:
	// b = a*sqrt(1 - e*e)
	// e = (apo - peri)/(apo + peri) = (apo - peri)/(2*a)
	// peri = a - e*a
	// apo = 2*a - peri
	
	b = a*Math.sqrt(1 - e*e);// semiminor axis
	
	
	// point and tangent on ellipse by angle from center of corresponding circle:
	// ex = cos(th), ey = sin(th)*b/a
	// tx = -sin(th), ty = cos(th)*b/a
	// atan(-tan(ang)*b/a) = th
}

function UpdateStats()
{
	debugDiv.value = ""
	
	peri = periapsis;
	apo = apoapsis;
	
	lenprec = (lenScale <= 1)? 1 : 4;
	velprec = (velScale <= 1)? 1 : 4;
	document.getElementById("periInput").value = ((periapsis - KERBIN_R)/lenScale).toFixed(lenprec);
	document.getElementById("apoInput").value = ((apoapsis - KERBIN_R)/lenScale).toFixed(lenprec);
	document.getElementById("perivelInput").value = (periapsisVel/velScale).toFixed(velprec);
	document.getElementById("apovelInput").value = (apoapsisVel/velScale).toFixed(velprec);
	if(elliptical)
	{
		vperi = periapsisVel;
		vapo = apoapsisVel;
		semimaj = (apo + peri)/2;
		semimin = Math.sqrt(apo*peri);
		ecc = (1 - 2.0/(apo/peri + 1));
		period = 2.0*Math.PI*Math.sqrt(Math.pow((peri + apo)/2.0, 3)/KERBIN_GM)
		periEscVel = Math.sqrt(2.0*KERBIN_GM/periapsis)
		apoEscVel = Math.sqrt(2.0*KERBIN_GM/apoapsis)
		periHohDV = Math.abs(vperi - Math.sqrt(KERBIN_GM/periapsis))
		apoHohDV = Math.abs(vapo - Math.sqrt(KERBIN_GM/apoapsis))
	
		writedbg("periapsis: " + (periapsis/1e3).toFixed(4) + " km, apoapsis: " + (apoapsis/1e3).toFixed(4) + " km");
		writedbg("periapsis: " + ((periapsis - KERBIN_R)/1e3).toFixed(4) + " km AMSL, " +
			"apoapsis: " + ((apoapsis - KERBIN_R)/1e3).toFixed(4) + " km AMSL");
		writedbg("\nvelocity at periapsis: " + vperi.toFixed(1) + " m/s, " + 
			"at apoapsis: " + vapo.toFixed(1) + " m/s");
		writedbg("Hohmann delta-v at periapsis: " + periHohDV.toFixed(1) + " m/s, " + 
			"at apoapsis: " + apoHohDV.toFixed(1) + " m/s");
		writedbg("Vesc at periapsis: " + periEscVel.toFixed(1) + " m/s, " + 
			"at apoapsis: " + apoEscVel.toFixed(1) + " m/s");
	
		writedbg("\nperiod: " + (period/60).toFixed(1) + " minutes");
		writedbg("semimajor axis: " + (semimaj/1e3).toFixed(4) + " km");
		writedbg("semiminor axis: " + (semimin/1e3).toFixed(4) + " km");
		writedbg("eccentricity: " + ecc.toFixed(1));
	}
	else
	{
		writedbg("periapsis: " + (periapsis/1e3).toFixed(4) + " km");
		writedbg("periapsis: " + ((periapsis - KERBIN_R)/1e3).toFixed(4) + " km AMSL");
		writedbg("velocity at periapsis: " + periapsisVel.toFixed(1) +
		 	" m/s, excess velocity: " + apoapsisVel.toFixed(1) + " m/s");
	}
	
	
	var plotLink = document.getElementById("plotLink");
	plotLink.href = "http://files.arklyffe.com/orbcalc.html?" +
		"a=" + (""+apoapsis) +
		"&p=" + (""+periapsis) +
		"&av=" + (""+apoapsisVel) +
		"&pv=" + (""+periapsisVel);
}

function PeriapsisChanged() {
	paramLock = document.getElementById("paramLockSelect").value;
	peri = (+document.getElementById("periInput").value + KERBIN_R)*lenScale;
	if(paramLock == "apo-peri")
		SetFromPeriapsis(peri);
	else
		SetFromPeriapsisPerivel(peri, periapsisVel);
	UpdateStats();
	DrawMainCanvas();
}
function ApsoapsisChanged() {
	paramLock = document.getElementById("paramLockSelect").value;
	apo = (+document.getElementById("apoInput").value + KERBIN_R)*lenScale;
	if(paramLock == "apo-peri")
		SetFromApoapsis(apo);
	else
		SetFromApoapsisApovel(apo, apoapsisVel);
	UpdateStats();
	DrawMainCanvas();
}

// Set velocity at apoapsis, recompute periapsis
function ApoVelChanged() {
	paramLock = document.getElementById("paramLockSelect").value;
	apovel = +document.getElementById("apovelInput").value*velScale;
	if(paramLock == "apo-peri")
		SetFromApovelPerivel(apovel, periapsisVel);
	else
		SetFromApoapsisApovel(apoapsis, apovel);
	UpdateStats();
	DrawMainCanvas();
}

// Set velocity at periapsis, recompute apoapsis
function PeriVelChanged() {
	paramLock = document.getElementById("paramLockSelect").value;
	perivel = +document.getElementById("perivelInput").value*velScale;
	if(paramLock == "apo-peri")
		SetFromApovelPerivel(apoapsisVel, perivel);
	else
		SetFromPeriapsisPerivel(periapsis, perivel);
	UpdateStats();
	DrawMainCanvas();
}

function ZoomIn()
{
	scale /= 2;
	canvasMinX = -scale;
	canvasMinY = -scale;
	canvasSizeX = 3*scale;
	canvasSizeY = canvasSizeX*height/width;// square aspect ratio
	scaleX = width/canvasSizeX;
	scaleY = height/canvasSizeY;
	DrawMainCanvas();
}
function ZoomOut()
{
	scale *= 2;
	canvasMinX = -scale;
	canvasMinY = -scale;
	canvasSizeX = 3*scale;
	canvasSizeY = canvasSizeX*height/width;// square aspect ratio
	scaleX = width/canvasSizeX;
	scaleY = height/canvasSizeY;
	DrawMainCanvas();
}

function MouseMoved(evt, x, y) {}
function MouseDown(evt, x, y) {
	if(safety) return;
	if(event.shiftKey)
	{
		zooming = true;
		savedScale = scale;
	}
	else
	{
		zooming = false;
		MouseDragging(evt, x, y, x, y);
	}
}

function MouseClicked(evt, x, y) {}
function MouseDragged(evt, x, y, prevX, prevY) {}

function MouseDragging(evt, x, y, prevX, prevY) {
	if(safety) return;
	if(zooming)
	{
		width = mainCanvasCtx.canvas.width;
		height = mainCanvasCtx.canvas.height;
		// Zoom
		scale = savedScale + (savedScale*(y - cursorClickY))/height;
		canvasMinX = -scale;
		canvasMinY = -scale;
		canvasSizeX = 3*scale;
		canvasSizeY = canvasSizeX*height/width;// square aspect ratio
		scaleX = width/canvasSizeX;
		scaleY = height/canvasSizeY;
		DrawMainCanvas();
	}
	else
	{
		MouseDragAltitude(evt, x, y, prevX, prevY)
	}
}
function MouseDragAltitude(evt, x, y, prevX, prevY) {
	if(safety) return;
	paramLock = document.getElementById("paramLockSelect").value;
	click_wx = s2w_x(cursorClickX)
	wx = s2w_x(x)
	if(click_wx > 0)
	{
		if(wx > 0)
		{
			elliptical = true;
			if(paramLock == "apo-peri")
			{
				if(wx < periapsis)
					wx = periapsis;
				SetFromApoapsis(wx);
			}
			else
			{
				apoapsis = savedApoapsis;
				periapsis = savedPeriapsis;
				apoapsisVel = savedApovel;
				periapsisVel = savedPerivel;
				SetFromApoapsisApovel(wx, apoapsisVel);
			}
		}
	}
	else
	{
		wx = -wx;
		if(wx > 0)
		{
			if(paramLock == "apo-peri")
			{
				if(wx > apoapsis)
					wx = apoapsis;
				
				SetFromPeriapsis(wx);
			}
			else
			{
				apoapsis = savedApoapsis;
				periapsis = savedPeriapsis;
				apoapsisVel = savedApovel;
				periapsisVel = savedPerivel;
				SetFromPeriapsisPerivel(wx, periapsisVel);
			}
		}
	}
	
	UpdateStats();
	DrawMainCanvas();
}

function UnitsChanged(self)
{
	units = document.getElementById("unitsSelect").value;
	if(units == "m_ms") {
		lenScale = 1;
		velScale = 1;
	}
	else if(units == "km_ms") {
		lenScale = 1000;
		velScale = 1;
	}
	else if(units == "m_kms") {
		lenScale = 1;
		velScale = 1000;
	}
	else if(units == "km_kms") {
		lenScale = 1000;
		velScale = 1000;
	}
	else {
		lenScale = 1;
		velScale = 1;
	}
	UpdateStats();
}

function SafetyBtnChanged(self)
{
	safety = document.getElementById("safetyBtn").checked;
}

//************************************************************************************************

window.onload = function() {
	apo = +getURL_Param("a", 0)
	peri = +getURL_Param("p", 0)
	apoV = +getURL_Param("av", 0)
	periV = +getURL_Param("pv", 0)
	
	if(apo > 0 && peri > 0)
		SetFromApoapsisPeriapsisEll(apo, peri);
	else if(apo > 0 && apoV > 0)
		SetFromApoapsisApovel(apo, apoV);
	else if(peri > 0 && periV > 0)
		SetFromPeriapsisPerivel(peri, periV);
	else
		SetFromApoapsisPeriapsisEll(50e3 + KERBIN_R, 200e3 + KERBIN_R)
	
	debugDiv = document.getElementById("debugDiv");
	mainCanvas = document.getElementById("mainCanvas");
	mainCanvasCtx = mainCanvas.getContext("2d");
	
	width = mainCanvasCtx.canvas.width;
	height = mainCanvasCtx.canvas.height;
	canvasSizeY = canvasSizeX*height/width;//square the initial aspect
	scaleX = width/canvasSizeX;
	scaleY = height/canvasSizeY;
	
	//Mouse events
	mainCanvas.onmouseover = function(evt) {document.body.style.cursor = "crosshair"; return false;}
	mainCanvas.onmouseout = function(evt) {document.body.style.cursor = "default"; return false;}
	
	mainCanvas.onmousedown = function(evt) {
		mouseIsDown = true;
		cursorLastX = evt.clientX - mainCanvas.offsetLeft +
					(window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft);
		cursorLastY = evt.clientY - mainCanvas.offsetTop +
					(window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop);
		cursorClickX = cursorLastX;
		cursorClickY = cursorLastY;
		MouseDown(evt, cursorClickX, cursorClickY);
		return false;
	}
	//if mouse is down, get mouseup events from window, not just canvas. Otherwise ignore.
	onmouseup = function(evt) {
		if(mouseIsDown) {
			var x = evt.clientX - mainCanvas.offsetLeft +
					(window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft);
			var y = evt.clientY - mainCanvas.offsetTop +
					(window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop);
			mouseIsDown = false;
			if(mouseIsDragging) {
				//mouse dragged
				mouseIsDragging = false;
				MouseDragged(evt, x, y, cursorLastX, cursorLastY);
			}
			else {
				//mouse clicked
				MouseClicked(evt, x, y);
			}
		}
		return false;
	}
	onmousemove = function(evt) {
		var x = evt.clientX - mainCanvas.offsetLeft +
					(window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft);
		var y = evt.clientY - mainCanvas.offsetTop +
					(window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop);
		if(mouseIsDown) {
			mouseIsDragging = true;
			MouseDragging(evt, x, y, cursorLastX, cursorLastY);
			cursorLastX = x;
			cursorLastY = y;
		}
		MouseMoved(evt, x, y);
		return false;
	}
	writedbg("Init done");
	
	UpdateStats();
	DrawMainCanvas();
}

//************************************************************************************************

</script>
</head>
<body>
	<a id="plotLink" href="http://files.arklyffe.com/orbcalc.html">This Orbit</a><br>
	<canvas id="mainCanvas" width="800" height="600"></canvas><br>
	<table>
		<tr>
	<td>Periapsis AMSL: <input type="text" id="periInput" size="8" onchange="PeriapsisChanged()"></td>
	<td>Velocity: <input type="text" id="perivelInput" size="8" onchange="PeriVelChanged()"></td>
	<td>Parameters: <select id="paramLockSelect">
		<option value="apo-peri" selected>Apoapsis-Periapsis</option>
		<option value="aps-vel">Apside-Velocity</option>
	</select></td>
	<td><input type="button" value="Zoom -" onclick="ZoomOut()">
		<input type="button" value="Zoom +" onclick="ZoomIn()"></td>
		</tr>
		<tr>
	<td>Apoapsis AMSL: <input type="text" id="apoInput" size="8" onchange="ApsoapsisChanged()"></td>
	<td>Velocity: <input type="text" id="apovelInput" size="8" onchange="ApoVelChanged()"></td>
	<td>Units: <select id="unitsSelect" onchange="UnitsChanged()">
		<option value="m_ms" selected>m, m/s</option>
		<option value="km_ms">km, m/s</option>
		<option value="m_kms">m, km/s</option>
		<option value="km_kms">km, km/s</option>
	</select></td>
	<td><input type="checkbox" id="safetyBtn" size="8" onchange="SafetyBtnChanged()">Ignore Mouse</td>
		</tr>
	</table>
	<div><textarea id="debugDiv" rows="20" cols="60" wrap="virtual" style="width:640px; height:250px"></textarea></div><br>
</body>
</html>