/* Saturn Return Calcualtor in Javascript
V1.00	10/02/08	First draft
V1.01	12/02/08 	Tidy up calculation, date at month/year, CSS changes
V1.02	15/02/08	Tidy up text, remove table borders. Remove 'calculate %"

/* Miscellaneous functions */
/* looks for aspect 0,90,180,270 If aspect is in orb
returns "angular" as 1*/
function FNaspect(a,b)
{
	angular=false
	asp=Math.abs(a-b)
	if (Math.abs(asp-0)<orb)
		{angular=true}
	if (Math.abs(asp-90)<orb)
		{angular=true}
	if (Math.abs(asp-180)<orb)
		{angular=true}
	if (Math.abs(asp-270)<orb)
		{angular=true}
	return dummy
}

/* Calculates day month year from Jd, returns the date as month year string
in "newday"*/
function FNrevjd(jd)
{
	L=Math.floor(jd+0.5)+68569
	N=Math.floor(4*L/146097)
	L=L-Math.floor((146097*N+3)/4)
	IT=Math.floor(4000*(L+1)/1461001)
	L=L-Math.floor(1461*IT/4)+31
	JT=Math.floor(80*L/2447)
	/*K=L-Math.floor(2447*JT/80)*/
	L=Math.floor(JT/11)
	JT=JT+2-12*L
	IK=100*(N-49)+IT+L
	switch (JT)
	{
	case 1:
		month="January"
		break
	case 2:
		month="February"
		break
	case 3:
		month="March"
		break
	case 4:
		month="April"
		break
	case 5:
		month="May"
		break
	case 6:
		month="June"
		break
	case 7:
		month="July"
		break
	case 8:
		month="August"
		break
	case 9:
		month="September"
		break
	case 10:
		month="October"
		break
	case 11:
		month="November"
		break
	case 12:
		month="December"
		break
	}
	newday="   "+month+" "+IK.toString()
	return newday
}

/* Degree Decimal to Degree.minutes rounded */
function FNoutdeg(d)
{
  whole = Math.floor(d)
  dummy= whole+(Math.round((d-whole)*60))/100
  return dummy
}

/* Calculates jd, T and ob at date ye, mo, da*/
function FNjday(ye,mo,da)
{
	im = 12 * (ye + 4800) + mo - 3
	j = (2 * (im - Math.floor(im / 12) * 12) + 7 + 365 * im) / 12
	j = Math.floor(j) + da + Math.floor(im / 48) - 32083
	jd = j + Math.floor(im / 4800) - Math.floor(im / 1200) + 38
	T = (jd - 2415020) / 36525
	ob = FNr(23.452294 - .0130125 * T) 
	return
}

/*Calculate Sun at time T*/
function FNsun(T)
{
	i=1
  	s = (358.4758 + 35999.0498 * T +  -.0002 * T * T)
	M = FNr(FNu(s))
	s = (.01675 + -.4E-4 * T + 0 * T * T)
	e = s
	ea = M
		for (ii=1; ii <= 4; ii++)
	{
		ea = M + e * Math.sin(ea)
	}
	au=1
	rv = FNr(au) * (1 - e * Math.cos(ea))
	x = au * (Math.cos(ea) - e)
	y = au * Math.sin(ea) * Math.sqrt(1 - e * e)
	dummy=FNtransp(x,y)
	s = (101.2208 + 1.7192 * T +  -.00045 * T * T)
	a = FNd(a) + s
	s = (0 + 0 * T +  0 * T * T)
	v = FNu(a + s)
	M = FNr(s)
	b = FNr(v)
	s = (0 + 0 * T +  0 * T * T)
	inn=FNr(s)
	a = Math.atan(Math.cos(inn) * Math.tan(b - M))
	if (a<0)
	{
		a=a+Math.PI
	}
	a = FNd(a + M)
	if (Math.abs(v-a)>10)
	{
		a=a-180
	}
	c = FNr(FNu(a))
	d = Math.atan(Math.sin(c - M) * Math.tan(inn))
	x = rv * Math.cos(d) * Math.cos(c)
	y = rv * Math.cos(d) * Math.sin(c)
 	z = rv * Math.sin(d)
	 
	x1 = x
	y1 = y
	z1 = z

	c = FNu(FNd(c) + 180)
	return
}

/*Calculate Saturn at time T */
function FNsaturn(T)
{
	i=2
	s = (174.2153 + 1223.50796 * T +  0 * T * T)
	M = FNr(FNu(s))
	s = (.05423 + -.0002 * T + 0 * T * T)
	e = s
	ea = M
	for (ii=1; ii <= 4; ii++)
	{
		ea = M + e * Math.sin(ea)
	}
	au=9.5525
	rv = FNr(au) * (1 - e * Math.cos(ea))
	x = au * (Math.cos(ea) - e)
	y = au * Math.sin(ea) * Math.sqrt(1 - e * e)
	dummy=FNtransp(x,y)
	s = (338.9117 + -.31167 * T +  0 * T * T)
	a = FNd(a) + s
	s = (112.8261 + .82590 * T +  0 * T * T)
	v = FNu(a + s)
	M = FNr(s)
	b = FNr(v)
	s = (2.4908 + -.0047 * T +  0 * T * T)
	inn=FNr(s)
	a = Math.atan(Math.cos(inn) * Math.tan(b - M))
	if (a<0)
	{
		a=a+Math.PI
	}
	a = FNd(a + M)
	if (Math.abs(v-a)>10)
	{
		 a=a-180
	}
	c = FNr(FNu(a))
	d = Math.atan(Math.sin(c - M) * Math.tan(inn))
	x = rv * Math.cos(d) * Math.cos(c)
	y = rv * Math.cos(d) * Math.sin(c)
 	z = rv * Math.sin(d)
	 
	x = x - x1
	y = y - y1
	z = z - z1
	FNtransp (x,y)
		 
	g = a
	y = z
	x = r
	FNtransp (x,y)
	c = FNd(g)
	if (a > .35)
	{
	   a = a - 2 * Math.PI
	}
	return
}

function FNtransp (x,y)
{
	if (y == 0)
	{
		y = 1.7453E-09
	}
	r = Math.sqrt(x * x + y * y)
	a = Math.atan(y/x)
	if (a < 0)
	{
		a = a + Math.PI
	}
	if (y < 0)
	{
		a = a + Math.PI
	}
	return
}

function FNp (x)
{
	if (x < 0)
	{
		sgn=-1
	}
	else
	{
		sgn=1
	}
	return sgn * ((Math.abs(x) / M) / 360 - Math.floor((Math.abs(x) / M) / 360)) * 360
	
}

function FNu (x)
{
	return x - (Math.floor(x / 360) * 360)
}
function FNd (x)
{
	return 180 / Math.PI * x
}

function FNr(x)
{
	return Math.PI / 180 * x
}

function  FNs(x)
{
	return  Math.sin(Math.PI / 180 * x)
}

/* Main calculation here! 
These are based on the public domain utilites published by
Michael Erlwine in Manual of Computer Programming for Astrologers,1980
*/

function calculate()
/* Get the local variables from the form, and check bounds
and make sure they are valid numbers. If theres a problem, reset
to the default vaulue
*/
{
	da=Number(document.getElementById("inputform").selectday.value)
	if (da<1 || da>31 || isNaN(da) )
	{
		da=1
		document.getElementById("inputform").selectday.value=1
	}

	mo=Number(document.getElementById("inputform").selectmonth.value)
	if (mo<1 || mo>12 || isNaN(mo) )
	{
		mo=1
		document.getElementById("inputform").selectmonth.value=1
	}
	
	ye=Number(document.getElementById("inputform").selectyear.value)
	if (ye<1900 || ye>2020 || isNaN(ye) )
	{
		ye=2000
		document.getElementById("inputform").selectyear.value=2000
	}
/* Clear out the display area */

	document.getElementById("inputform").textfield11.value= ""
	document.getElementById("inputform").textfield12.value= ""
	document.getElementById("inputform").textfield13.value= ""
	document.getElementById("inputform").textfield14.value= ""
	document.getElementById("inputform").textfield15.value= ""
	document.getElementById("inputform").textfield16.value= ""
	document.getElementById("inputform").textfield17.value= ""
	document.getElementById("inputform").textfield18.value= ""
	document.getElementById("inputform").textfield19.value= ""
	document.getElementById("inputform").textfield20.value= ""
	document.getElementById("inputform").textfield21.value= ""
	document.getElementById("inputform").textfield22.value= ""
	document.getElementById("inputform").textfield23.value= ""
	document.getElementById("inputform").textfield24.value= ""
	document.getElementById("inputform").textfield25.value= ""
	document.getElementById("inputform").textfield26.value= ""
	document.getElementById("inputform").textfield27.value= ""
	document.getElementById("inputform").textfield28.value= ""
	document.getElementById("inputform").textfield29.value= ""
	document.getElementById("inputform").textfield30.value= ""
	document.getElementById("inputform").textfield31.value= ""
	document.getElementById("inputform").textfield32.value= ""
	document.getElementById("inputform").textfield33.value= ""
	document.getElementById("inputform").textfield34.value= ""
	
	var date=Array()
	retcomplete=0
	angular=0
	inc=5
  	x1=0
  	y1=0
	z1=0

/* Calculate the natal saturn ("natalsat") at birth date ("nataljd") */

	dummy=FNjday(ye,mo,da) 
	dummy=FNsun(T)
	dummy=FNsaturn(T)
  	natalsat=c
  	nataljd=jd
	
/* Start to search from natal+1 year to miss birth conjunction */
/* orb set to 0.5 degree
returnevent =0 to catch retrograde motion
set birth time at 4 year to avoid time wasting
oldjd is the start time of the search
*/

	orb=0.5
	returnevent=0
	ret=11
	nataljd=nataljd+1460
	oldjd=nataljd
	
  	for (jd=nataljd; jd <= nataljd+33000; jd=jd+inc)
  	{
		T = (jd - 2415020) / 36525
		ob = FNr(23.452294 - .0130125 * T)		
		dummy=FNsun(T)
		dummy=FNsaturn(T)
		aspect=Math.abs(natalsat-c)	
	
/*	not in a return yet, so update the start of return event date */

		if (retcomplete==0)
		{
			date[ret]=FNrevjd(jd)
		}

/* check for natal to present position aspect. If present (angular=1) then enter the search */

		dummy=FNaspect(natalsat,c)
		while (angular==1)
		{

/* must be a return, so start logging the date. Keep in this loop until out of orb */

			oldjd=jd
			retcomplete=1
			date[ret+1]=FNrevjd(jd)
			T = (jd - 2415020) / 36525
			ob = FNr(23.452294 - .0130125 * T)		
			dummy=FNsun(T)
			dummy=FNsaturn(T)
			dummy=FNaspect(natalsat,c)
			jd=jd+inc
		}
		if (retcomplete==1 && jd-oldjd>=360)
		{

/* Finished one return. If its complete (retcomplete=1) AND more than a year after the return, reset for the next return */

			ret=ret+2	
			retcomplete=0
			oldjd=jd
		}
		
  	}
	
/* We have fille the date[] array with data, now dump it out */

	document.getElementById("inputform").textfield11.value= date[11]
	document.getElementById("inputform").textfield12.value= date[12]
	document.getElementById("inputform").textfield13.value= date[13]
	document.getElementById("inputform").textfield14.value= date[14]
	document.getElementById("inputform").textfield15.value= date[15]
	document.getElementById("inputform").textfield16.value= date[16]
	document.getElementById("inputform").textfield17.value= date[17]
	document.getElementById("inputform").textfield18.value= date[18]
	document.getElementById("inputform").textfield19.value= date[19]
	document.getElementById("inputform").textfield20.value= date[20]
	document.getElementById("inputform").textfield21.value= date[21]
	document.getElementById("inputform").textfield22.value= date[22]
	document.getElementById("inputform").textfield23.value= date[23]
	document.getElementById("inputform").textfield24.value= date[24]
	document.getElementById("inputform").textfield25.value= date[25]
	document.getElementById("inputform").textfield26.value= date[26]
	document.getElementById("inputform").textfield27.value= date[27]
	document.getElementById("inputform").textfield28.value= date[28]
	document.getElementById("inputform").textfield29.value= date[29]
	document.getElementById("inputform").textfield30.value= date[30]
	document.getElementById("inputform").textfield31.value= date[31]
	document.getElementById("inputform").textfield32.value= date[32]
	document.getElementById("inputform").textfield33.value= date[33]
	document.getElementById("inputform").textfield34.value= date[34]

}
