<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:v="urn:schemas-microsoft-com:vml" version="1.0">
	<xsl:output method="xml" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" indent="yes"/>
  <xsl:template match="/">
		<html>
			<head>
				<title>XSLorenz</title>
				<!-- 	For VML. IE8 will barf on the older star notation for VML style, but all the IEs work
							okay with the import instruction, it seems. -->
				<xsl:processing-instruction name="import">namespace="v" implementation="#default#VML"</xsl:processing-instruction>
        <style> v\:shape { display:inline-block } </style>
			</head>
			<body>
				<h1>XSLorenz</h1>
				<div>
					<xsl:apply-templates />
				</div>
			</body>
		</html>
  </xsl:template>
  
	<xsl:template match="lorenz">
		<!-- SVG -->
		<svg:svg width="500px" height="500px" viewBox="0 0 1000 1000">
			<svg:g transform="translate(500,500)">
				<xsl:call-template name="recurse">
					<xsl:with-param name="style" select="'svg'" />
					<xsl:with-param name="i" select="practice/iterations" />
					<xsl:with-param name="beta" select="theory/beta" />
					<xsl:with-param name="rho" select="theory/rho" />
					<xsl:with-param name="sigma" select="theory/sigma" />
					<xsl:with-param name="x" select="practice/initialvalues/x" />
					<xsl:with-param name="y" select="practice/initialvalues/y" />
					<xsl:with-param name="z" select="practice/initialvalues/z" />
					<xsl:with-param name="t" select="practice/initialvalues/t" />
					<xsl:with-param name="dt" select="practice/dt" />
				</xsl:call-template>
			</svg:g>
		</svg:svg>
		<!-- VML -->
		<v:group xmlns="urn:schemas-microsoft-com:vml" style='position: absolute; width: 500px; height: 500px' coordsize="1000,1000" coordorigin="-500,-500" >
			<xsl:call-template name="recurse">
				<xsl:with-param name="style" select="'vml'" />
				<xsl:with-param name="i" select="practice/iterations" />
				<xsl:with-param name="beta" select="theory/beta" />
				<xsl:with-param name="rho" select="theory/rho" />
				<xsl:with-param name="sigma" select="theory/sigma" />
				<xsl:with-param name="x" select="practice/initialvalues/x" />
				<xsl:with-param name="y" select="practice/initialvalues/y" />
				<xsl:with-param name="z" select="practice/initialvalues/z" />
				<xsl:with-param name="t" select="practice/initialvalues/t" />
				<xsl:with-param name="dt" select="practice/dt" />
			</xsl:call-template>	
		</v:group>
  </xsl:template>

	<!-- We recurse rather than iterating. We're a declarative language, so it's what we do :) -->
  <xsl:template name="recurse">
		<xsl:param name="style" />
		<xsl:param name="i" />
		<xsl:param name="beta" />
		<xsl:param name="rho" />
		<xsl:param name="sigma" />
		<xsl:param name="x" />
		<xsl:param name="y" />
		<xsl:param name="z" />
		<xsl:param name="t" />
		<xsl:param name="dt" />

		<xsl:variable name="scale">15</xsl:variable>
    <xsl:if test="$i &gt; 0">
		
			<xsl:variable name="x1" select="$x + (( -$sigma*$x + $sigma*$y ) * $dt)" />
			<xsl:variable name="y1" select="$y + ((( $rho*$x - $x*$z) - $y) * $dt)" />
			<xsl:variable name="z1" select="$z + (( ($x)*($y) - ($beta)*($z)) * $dt)" />
			<xsl:variable name="t1" select="$t + $dt" />

			<!-- 
				We can output either SVG or VML. Typically we'll do both; SVG will be displayed by Firefox, Safari,
				and other modern browsers. The VML should work in IE. Luckily the formats for SVG and VML for the 
				"draw a line" functionality we want to use can be virtually identical.
			-->
			<xsl:choose>
				<xsl:when test="$style='svg'" >
					<xsl:element xmlns="http://www.w3.org/2000/svg" name="svg:line">
						<xsl:attribute name="x1"><xsl:value-of select="($x)*($scale)" /></xsl:attribute>
						<xsl:attribute name="y1"><xsl:value-of select="($y)*($scale)" /></xsl:attribute>
						<xsl:attribute name="x2"><xsl:value-of select="($x1)*($scale)" /></xsl:attribute>
						<xsl:attribute name="y2"><xsl:value-of select="($y1)*($scale)" /></xsl:attribute>
						<xsl:attribute name="style"><xsl:text>stroke:rgb(99,99,99);stroke-width:2</xsl:text></xsl:attribute>
					</xsl:element>
				</xsl:when>
				<xsl:when test="$style='vml'" >
					<xsl:element xmlns="urn:schemas-microsoft-com:vml" name="v:line" >
						<xsl:attribute name="style">position: absolute;</xsl:attribute>
						<xsl:attribute name="strokecolor">rgb(99,99,99)</xsl:attribute>
						<xsl:attribute name="strokeweight">1pt</xsl:attribute>
						<xsl:attribute name="from"><xsl:value-of select="($x)*($scale)" />,<xsl:value-of select="($y)*($scale)" /></xsl:attribute>
						<xsl:attribute name="to"><xsl:value-of select="($x1)*($scale)" />,<xsl:value-of select="($y1)*($scale)" /></xsl:attribute>
					</xsl:element>
				</xsl:when>
			</xsl:choose>

			<!-- 
				Now just call ourselves. This is tail-recursion, but unfortunately most XSL parsers won't take
				advantage of that, so we'll generally overrun their stack-size. Firefox's XSL parser seems to 
				handle it fine, though; I guess it's turning the recursion into iteration, as you'd hope.
			-->
			<xsl:call-template name="recurse">
        <xsl:with-param name="i" select="($i)-1" />
        <xsl:with-param name="beta" select="$beta" />
				<xsl:with-param name="rho" select="$rho" />
				<xsl:with-param name="sigma"  select="$sigma" />
				<xsl:with-param name="dt" select="$dt" />
        <xsl:with-param name="x" select="$x1" />
				<xsl:with-param name="y" select="$y1" />
				<xsl:with-param name="z" select="$z1" />
				<xsl:with-param name="t" select="$t1" />
				<xsl:with-param name="style" select="$style" />
			</xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>
