<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="2.0"
  xmlns:c="http://www.acooke.org/countries"
  xmlns:math="http://exslt.org/math"
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:param name="longZero" select="0"/>
 <xsl:param name="latZero" select="0"/>

 <xsl:output method="xml" version="1.0" encoding="iso-8859-1"
   omit-xml-declaration="no" indent="yes"/>

 <xsl:template match="c:country[./c:name][./c:coords][string(number(./c:dollar)) != 'NaN'][./c:gdp]">
  <xsl:variable name="long" select="(./c:coords/c:long - $longZero + 720 + 180) mod 360 - 180"/>
  <xsl:variable name="lat" select="(./c:coords/c:lat - $latZero + 720 + 180) mod 360 - 180"/>
  <xsl:variable name="cx">
   <xsl:call-template name="scale-long">
    <xsl:with-param name="long" select="$long"/>
    <xsl:with-param name="lat" select="$lat"/>
   </xsl:call-template>
  </xsl:variable>
  <xsl:variable name="cy">
   <xsl:call-template name="scale-lat">
    <xsl:with-param name="lat" select="$lat"/>
   </xsl:call-template>
  </xsl:variable>
  <xsl:variable name="theta" select="(180 * math:atan2($cx, $cy)) div 3.1415926"/>
  <xsl:variable name="r" select="math:sqrt($cx*$cx+$cy*$cy)"/>
  <xsl:variable name="id" select="./c:code"/>
  <xsl:variable name="scaled-dollar">
   <xsl:call-template name="norm-gamma">
    <xsl:with-param name="pX" select="./c:dollar"/>
    <xsl:with-param name="pMin" select="0"/>
    <xsl:with-param name="pMax" select="5e11"/>
    <xsl:with-param name="pScale" select="1.0"/>
    <xsl:with-param name="pPower" select="0.5"/>
   </xsl:call-template>
  </xsl:variable>
  <xsl:variable name="scaled-gdp">
   <xsl:call-template name="norm-gamma">
    <xsl:with-param name="pX" select="./c:gdp"/>
    <xsl:with-param name="pMin" select="0"/>
    <xsl:with-param name="pMax" select="10"/>
    <xsl:with-param name="pScale" select="1.0"/>
    <xsl:with-param name="pPower" select="1.0"/>
   </xsl:call-template>
  </xsl:variable>
  <xsl:variable name="colour">
   <xsl:call-template name="heat">
    <xsl:with-param name="pX" select="$scaled-gdp"/>
   </xsl:call-template>
  </xsl:variable>
  <xsl:choose>
   <xsl:when test="$long &gt;= -90  and $long &lt;= 90">
    <xsl:call-template name="gradient">
     <xsl:with-param name="pId" select="$id"/>
     <xsl:with-param name="pOpacity" select="0.5"/>
     <xsl:with-param name="pColour" select="$colour"/>
    </xsl:call-template>
    <xsl:if test="$r &lt; 0.8 and $scaled-dollar &gt; 0.017">
     <xsl:element name="text">
      <xsl:attribute name="x" select="$cx"/>
      <xsl:attribute name="y" select="$cy"/>
      <xsl:attribute name="text-anchor">middle</xsl:attribute>
      <xsl:attribute name="font-family">Verdana</xsl:attribute>
      <xsl:attribute name="font-size">0.03</xsl:attribute>
      <xsl:attribute name="fill">#ccc</xsl:attribute>
      <xsl:value-of select="./c:name"/>
     </xsl:element> 
    </xsl:if>
   </xsl:when>
   <xsl:otherwise>
    <xsl:call-template name="gradient">
     <xsl:with-param name="pId" select="$id"/>
     <xsl:with-param name="pOpacity" select="0.15"/>
     <xsl:with-param name="pColour" select="$colour"/>
    </xsl:call-template>
   </xsl:otherwise>
  </xsl:choose>
  <xsl:comment><xsl:value-of select="./c:name"/></xsl:comment>
  <xsl:element name="ellipse">
   <xsl:attribute name="transform" 
    select="concat('translate(', $cx, ',', $cy, ') ',
                   'rotate(', (90 - $theta), ')')"/>
   <xsl:attribute name="cy" select="0"/>
   <xsl:attribute name="cx" select="0"/>
   <xsl:choose>
    <xsl:when test="math:cos($r * 3.1415926 div 2) &gt; 0.1">
     <xsl:attribute name="rx" select="1 * $scaled-dollar * math:cos($r * 3.1415926 div 2)"/>
    </xsl:when>
    <xsl:otherwise>
     <xsl:attribute name="rx" select="1 * $scaled-dollar * 0.1"/>
    </xsl:otherwise>
   </xsl:choose>
   <xsl:attribute name="ry" select="1 * $scaled-dollar"/>
   <xsl:attribute name="fill">url(#<xsl:value-of select="$id"/>)</xsl:attribute>
  </xsl:element>
 </xsl:template>

 <xsl:template match="c:arms">
  <svg x="0" y="0" height="2" width="2">
   <desc>Map of Arms Spending</desc>
   <rect x="0" y="0" height="2" width="2" fill="black"/>
   <g transform="translate(1,1)">
    <xsl:apply-templates select="*">
     <xsl:sort select="./c:gdp"/>
    </xsl:apply-templates>
    <circle cx="0" cy="0" r="1.25" stroke="black" stroke-width="0.5" fill="none"/>
   </g>
  </svg>
 </xsl:template>

 <xsl:template match="*"/> 

 <xsl:template name="gradient">
  <xsl:param name="pId"/>
  <xsl:param name="pOpacity"/>
  <xsl:param name="pColour"/>
  <defs>
   <xsl:element name="radialGradient">
    <xsl:attribute name="gradientUnits">objectBoundingBox</xsl:attribute>
    <xsl:attribute name="id">
     <xsl:value-of select="$pId"/>
    </xsl:attribute>
    <xsl:element name="stop">
     <xsl:attribute name="offset">1%</xsl:attribute>
     <xsl:attribute name="stop-color">
      <xsl:value-of select="$pColour"/>
     </xsl:attribute>
     <xsl:attribute name="stop-opacity">
      <xsl:value-of select="$pOpacity"/>
     </xsl:attribute>
    </xsl:element>
    <xsl:element name="stop">
     <xsl:attribute name="offset">99%</xsl:attribute>
     <xsl:attribute name="stop-color">
      <xsl:value-of select="$pColour"/>
     </xsl:attribute>
     <xsl:attribute name="stop-opacity">
      <xsl:value-of select="0.25 * $pOpacity"/>
     </xsl:attribute>
    </xsl:element>
   </xsl:element>
  </defs>
 </xsl:template>

 <xsl:template name="heat">
  <xsl:param name="pX"/>
  <xsl:choose>
   <xsl:when test="$pX &lt; 0.5">
    <xsl:variable name="g-dot" select="string(510 * $pX)"/>
    <xsl:variable name="g">
     <xsl:choose>
      <xsl:when test="contains($g-dot, '.')">
       <xsl:value-of select="substring-before($g-dot, '.')"/>
      </xsl:when>
      <xsl:otherwise>
       <xsl:value-of select="$g-dot"/>
      </xsl:otherwise>
     </xsl:choose>
    </xsl:variable>rgb(255,<xsl:value-of select="$g"/>,0)</xsl:when>
   <xsl:otherwise>
    <xsl:variable name="b-dot" select="string(510 * ($pX - 0.5))"/>
    <xsl:variable name="b">
     <xsl:choose>
      <xsl:when test="contains($b-dot, '.')">
       <xsl:value-of select="substring-before($b-dot, '.')"/>
      </xsl:when>
      <xsl:otherwise>
       <xsl:value-of select="$b-dot"/>
      </xsl:otherwise>
     </xsl:choose>
    </xsl:variable>rgb(255,255,<xsl:value-of select="$b"/>)</xsl:otherwise>
  </xsl:choose>
 </xsl:template>

 <xsl:template name="norm-gamma">
  <xsl:param name="pX"/>
  <xsl:param name="pMin"/>
  <xsl:param name="pMax"/>
  <xsl:param name="pScale"/>
  <xsl:param name="pPower"/>
  <xsl:variable name="norm" select="($pX - $pMin) div ($pMax - $pMin)"/>
  <xsl:choose>
   <xsl:when test="$norm &gt; 0">
    <xsl:value-of select="$pScale * math:power($norm, $pPower)"/>
   </xsl:when>
   <xsl:otherwise>
    <xsl:value-of select="0"/>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

 <!-- spatial position
      place on a sphere, radius 1, centre (0,0) -->
 <xsl:template name="scale-long">
  <xsl:param name="lat"/>
  <xsl:param name="long"/>
  <xsl:value-of select="math:sin($long * 0.01745323) * math:cos($lat * 0.01745323)"/>
 </xsl:template>
 <xsl:template name="scale-lat">
  <xsl:param name="lat"/>
  <!-- invert because stupid coord system -->
  <xsl:value-of select="-1 * math:sin($lat * 0.01745323)"/>
 </xsl:template>

</xsl:stylesheet>
