<?xml version="1.0" encoding="UTF-8"?>
<!--
==============================================================================

Osmarender 6.0 Alpha 6 
    with - orig area generation 
         - one node way filtered out
         - filtered out missing multipolygon relation members from areas
         - filtered out missing node ref from ways

==============================================================================

Copyright (C) 2006-2007  Etienne Cherdlu, Jochen Topf

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA

==============================================================================
-->
<xsl:stylesheet
  xmlns="http://www.w3.org/2000/svg"
  xmlns:svg="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns:xi="http://www.w3.org/2001/XInclude"
  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  xmlns:cc="http://web.resource.org/cc/"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exslt="http://exslt.org/common"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  exclude-result-prefixes="exslt msxsl" 
  version="1.0">

  <xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="UTF-8"/>

  <!-- This msxsl script extension fools msxsl into interpreting exslt extensions as msxsl ones, so 
       we can write code using exslt extensions even though msxsl only recognises the msxsl extension 
       namespace.  Thanks to David Carlisle for this: http://dpcarlisle.blogspot.com/2007/05/exslt-node-set-function.html -->
  <msxsl:script language="JScript" implements-prefix="exslt">
    this['node-set'] =  function (x) {
    return x;
    }
  </msxsl:script>

  <xsl:param name="osmfile" select="/rules/@data"/>
  <xsl:param name="title" select="/rules/@title"/>

  <xsl:param name="scale" select="/rules/@scale"/>
  <xsl:param name="symbolScale" select="/rules/@symbolScale"/>
  <xsl:param name='textAttenuation' select='/rules/@textAttenuation'/>
  <xsl:param name="withOSMLayers" select="/rules/@withOSMLayers"/>
  <xsl:param name="svgBaseProfile" select="/rules/@svgBaseProfile"/>
  <xsl:param name="symbolsDir" select="/rules/@symbolsDir"/>

  <xsl:param name="showGrid" select="/rules/@showGrid"/>
  <xsl:param name="showBorder" select="/rules/@showBorder"/>
  <xsl:param name="showScale" select="/rules/@showScale"/>
  <xsl:param name="showLicense" select="/rules/@showLicense"/>

  <xsl:param name="showRelationRoute" select="/rules/@showRelationRoute"/>
  <xsl:param name="showRelationBoundary" select="/rules/@showRelationBoundary"/>

  <xsl:key name="nodeById" match="/osm/node" use="@id"/>
  <xsl:key name="wayById" match="/osm/way" use="@id"/>
  <xsl:key name="wayByNode" match="/osm/way" use="nd/@ref"/>
  <xsl:key name="relationByWay" match="/osm/relation" use="member/@ref"/>

  <xsl:variable name="data" select="document($osmfile)"/>

  <!-- Use a web-service (if available) to get the current date -->
  <xsl:variable name="now" select="document('http://xobjex.com/service/date.xsl')" />
  <xsl:variable name="date">
    <xsl:choose>
      <xsl:when test="$now">
        <xsl:value-of select="substring($now/date/utc/@stamp,1,10)" />
        <!-- Assumes 4 digit year -->
      </xsl:when>
      <xsl:otherwise>2007-01-01</xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:variable name="year">
    <xsl:choose>
      <xsl:when test="$now">
        <xsl:value-of select="$now/date/utc/year" />
      </xsl:when>
      <xsl:otherwise>2007</xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- extra height for marginalia at top -->
  <xsl:variable name="marginaliaTopHeight">
    <xsl:choose>
      <xsl:when test="$title != ''">40</xsl:when>
      <xsl:when test="($title = '') and ($showBorder = 'yes')">1.5</xsl:when>
      <xsl:otherwise>0</xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- extra height for marginalia at bottom -->
  <xsl:variable name="marginaliaBottomHeight">
    <xsl:choose>
      <xsl:when test="($showScale = 'yes') or ($showLicense = 'yes')">45</xsl:when>
      <xsl:when test="($showScale != 'yes') and ($showLicense != 'yes') and ($showBorder = 'yes')">1.5</xsl:when>
      <xsl:otherwise>0</xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- extra width for border -->
  <xsl:variable name="extraWidth">
    <xsl:choose>
      <xsl:when test="$showBorder = 'yes'">3</xsl:when>
      <xsl:otherwise>0</xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- extra height for border -->
  <xsl:variable name="extraHeight">
    <xsl:choose>
      <xsl:when test="($title = '') and ($showBorder = 'yes')">3</xsl:when>
      <xsl:otherwise>0</xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Calculate the size of the bounding box based on the file content -->
  <xsl:variable name="bllat">
    <xsl:for-each select="$data/osm/node/@lat">
      <xsl:sort data-type="number" order="ascending"/>
      <xsl:if test="position()=1">
        <xsl:value-of select="."/>
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>
  <xsl:variable name="bllon">
    <xsl:for-each select="$data/osm/node/@lon">
      <xsl:sort data-type="number" order="ascending"/>
      <xsl:if test="position()=1">
        <xsl:value-of select="."/>
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>
  <xsl:variable name="trlat">
    <xsl:for-each select="$data/osm/node/@lat">
      <xsl:sort data-type="number" order="descending"/>
      <xsl:if test="position()=1">
        <xsl:value-of select="."/>
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>
  <xsl:variable name="trlon">
    <xsl:for-each select="$data/osm/node/@lon">
      <xsl:sort data-type="number" order="descending"/>
      <xsl:if test="position()=1">
        <xsl:value-of select="."/>
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>
  <xsl:variable name="bottomLeftLatitude">
    <xsl:choose>
      <xsl:when test="/rules/bounds">
        <xsl:value-of select="/rules/bounds/@minlat"/>
      </xsl:when>
      <xsl:when test="$data/osm/bounds">
        <xsl:value-of select="$data/osm/bounds/@minlat"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$bllat"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:variable name="bottomLeftLongitude">
    <xsl:choose>
      <xsl:when test="/rules/bounds">
        <xsl:value-of select="/rules/bounds/@minlon"/>
      </xsl:when>
      <xsl:when test="$data/osm/bounds">
        <xsl:value-of select="$data/osm/bounds/@minlon"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$bllon"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:variable name="topRightLatitude">
    <xsl:choose>
      <xsl:when test="/rules/bounds">
        <xsl:value-of select="/rules/bounds/@maxlat"/>
      </xsl:when>
      <xsl:when test="$data/osm/bounds">
        <xsl:value-of select="$data/osm/bounds/@maxlat"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$trlat"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:variable name="topRightLongitude">
    <xsl:choose>
      <xsl:when test="/rules/bounds">
        <xsl:value-of select="/rules/bounds/@maxlon"/>
      </xsl:when>
      <xsl:when test="$data/osm/bounds">
        <xsl:value-of select="$data/osm/bounds/@maxlon"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$trlon"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Derive the latitude of the middle of the map -->
  <xsl:variable name="middleLatitude" select="($topRightLatitude + $bottomLeftLatitude) div 2.0"/>
  <!--woohoo lets do trigonometry in xslt -->
  <!--convert latitude to radians -->
  <xsl:variable name="latr" select="$middleLatitude * 3.1415926 div 180.0"/>
  <!--taylor series: two terms is 1% error at lat<68 and 10% error lat<83. we probably need polar projection by then -->
  <xsl:variable name="coslat" select="1 - ($latr * $latr) div 2 + ($latr * $latr * $latr * $latr) div 24"/>
  <xsl:variable name="projection" select="1 div $coslat"/>

  <xsl:variable name="dataWidth" select="(number($topRightLongitude)-number($bottomLeftLongitude))*10000*$scale"/>
  <xsl:variable name="dataHeight" select="(number($topRightLatitude)-number($bottomLeftLatitude))*10000*$scale*$projection"/>
  <xsl:variable name="km" select="(0.0089928*$scale*10000*$projection)"/>

  <xsl:variable name="documentWidth">
    <xsl:choose>
      <xsl:when test="$dataWidth &gt; (number(/rules/@minimumMapWidth) * $km)">
        <xsl:value-of select="$dataWidth"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="number(/rules/@minimumMapWidth) * $km"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="documentHeight">
    <xsl:choose>
      <xsl:when test="$dataHeight &gt; (number(/rules/@minimumMapHeight) * $km)">
        <xsl:value-of select="$dataHeight"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="number(/rules/@minimumMapHeight) * $km"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="width" select="($documentWidth div 2) + ($dataWidth div 2)"/>
  <xsl:variable name="height" select="($documentHeight div 2) + ($dataHeight div 2)"/>



  <!-- Main template -->
  <xsl:template match="/rules">

    <!-- Include an external css stylesheet if one was specified in the rules file -->
    <xsl:if test="@xml-stylesheet">
      <xsl:processing-instruction name="xml-stylesheet">
        href="<xsl:value-of select="@xml-stylesheet"/>" type="text/css"
      </xsl:processing-instruction>
    </xsl:if>

    <xsl:variable name="svgWidth" select="$documentWidth + $extraWidth"/>
    <xsl:variable name="svgHeight" select="$documentHeight + $marginaliaTopHeight + $marginaliaBottomHeight"/>

    <svg id="main"
  version="1.1"
  baseProfile="{$svgBaseProfile}"
  width="{$svgWidth}px"
  height="{$svgHeight}px"
  preserveAspectRatio="none"
  viewBox="{-$extraWidth div 2} {-$extraHeight div 2} {$svgWidth} {$svgHeight}">
      <xsl:if test="/rules/@interactive='yes'">
        <xsl:attribute name="onscroll">fnOnScroll(evt)</xsl:attribute>
        <xsl:attribute name="onzoom">fnOnZoom(evt)</xsl:attribute>
        <xsl:attribute name="onload">fnOnLoad(evt)</xsl:attribute>
        <xsl:attribute name="onmousedown">fnOnMouseDown(evt)</xsl:attribute>
        <xsl:attribute name="onmousemove">fnOnMouseMove(evt)</xsl:attribute>
        <xsl:attribute name="onmouseup">fnOnMouseUp(evt)</xsl:attribute>
      </xsl:if>

      <xsl:call-template name="metadata"/>

      <!-- Include javaScript functions for all the dynamic stuff -->
      <xsl:if test="/rules/@interactive='yes'">
        <xsl:call-template name="javaScript"/>
      </xsl:if>


      <defs id="defs-rulefile">
        <!-- Get any <defs> and styles from the rules file -->
        <xsl:copy-of select="defs/*"/>
      </defs>


      <xsl:if test="$symbolsDir != ''">
        <!-- Get all symbols mentioned in the rules file from the symbolsDir -->
        <defs id="defs-symbols">
          <xsl:for-each select="/rules//symbol/@ref">
            <xsl:copy-of select="document(concat($symbolsDir,'/', ., '.svg'))/svg:svg/svg:defs/svg:symbol"/>
          </xsl:for-each>
        </defs>
      </xsl:if>

      <!-- Pre-generate named path definitions for all ways -->
      <xsl:variable name="allWays" select="$data/osm/way"/>
      <defs id="defs-ways">
        <xsl:for-each select="$allWays">
          <xsl:call-template name="generateWayPaths"/>
        </xsl:for-each>
      </defs>

      <!-- Clipping rectangle for map -->
      <clipPath id="map-clipping">
        <rect id="map-clipping-rect" x="0px" y="0px" height="{$documentHeight}px" width="{$documentWidth}px"/>
      </clipPath>

      <g id="map" clip-path="url(#map-clipping)" inkscape:groupmode="layer" inkscape:label="Map" transform="translate(0,{$marginaliaTopHeight})">
        <!-- Draw a nice background layer -->
        <rect id="background" x="0px" y="0px" height="{$documentHeight}px" width="{$documentWidth}px" class="map-background"/>

        <!-- Process all the rules drawing all map features -->
        <xsl:call-template name="processRules"/>
      </g>

      <!-- Draw map decoration -->
      <g id="map-decoration" inkscape:groupmode="layer" inkscape:label="Map decoration" transform="translate(0,{$marginaliaTopHeight})">
        <!-- Draw a grid if required -->
        <xsl:if test="$showGrid='yes'">
          <xsl:call-template name="drawGrid"/>
        </xsl:if>

        <!-- Draw a border if required -->
        <xsl:if test="$showBorder='yes'">
          <xsl:call-template name="drawBorder"/>
        </xsl:if>
      </g>

      <!-- Draw map marginalia -->
      <xsl:if test="($title != '') or ($showScale = 'yes') or ($showLicense = 'yes')">
        <g id="marginalia" inkscape:groupmode="layer" inkscape:label="Marginalia">
          <!-- Draw the title -->
          <xsl:if test="$title!=''">
            <xsl:call-template name="drawTitle">
              <xsl:with-param name="title" select="$title"/>
            </xsl:call-template>
          </xsl:if>

          <xsl:if test="($showScale = 'yes') or ($showLicense = 'yes')">
            <g id="marginalia-bottom" inkscape:groupmode="layer" inkscape:label="Marginalia (Bottom)" transform="translate(0,{$marginaliaTopHeight})">
              <!-- Draw background for marginalia at bottom -->
              <rect id="marginalia-background" x="0px" y="{$documentHeight + 5}px" height="40px" width="{$documentWidth}px" class="map-marginalia-background"/>

              <!-- Draw the scale in the bottom left corner -->
              <xsl:if test="$showScale='yes'">
                <xsl:call-template name="drawScale"/>
              </xsl:if>

              <!-- Draw Creative commons license -->
              <xsl:if test="$showLicense='yes'">
                <xsl:call-template name="in-image-license">
                  <xsl:with-param name="dx" select="$documentWidth"/>
                  <xsl:with-param name="dy" select="$documentHeight"/>
                </xsl:call-template>
              </xsl:if>
            </g>
          </xsl:if>
        </g>
      </xsl:if>

      <!-- Draw labels and controls that are in a static position -->
      <g id="staticElements" transform="scale(1) translate(0,0)">
        <!-- Draw the +/- zoom controls -->
        <xsl:if test="/rules/@interactive='yes'">
          <xsl:call-template name="zoomControl"/>
        </xsl:if>
      </g>
    </svg>

  </xsl:template>

  <!-- Path Fragment Drawing -->
  <xsl:template name="drawPath">
    <xsl:param name='instruction' />
    <xsl:param name='pathId'/>
    <xsl:param name='extraClasses'/>

    <xsl:variable name="maskId" select="concat('mask_',$pathId)"/>

    <xsl:call-template name='generateMask'>
      <xsl:with-param name='instruction' select='$instruction'/>
      <xsl:with-param name='pathId' select='$pathId'/>
      <xsl:with-param name='maskId' select='$maskId'/>
    </xsl:call-template>

    <use xlink:href="#{$pathId}">
      <!-- Copy all attributes from instruction -->
      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes" />
      <!-- Add in any extra classes -->
      <xsl:attribute name="class">
        <xsl:value-of select='$instruction/@class'/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="$extraClasses"/>
      </xsl:attribute>
      <!-- If there is a mask class then include the mask attribute -->
      <xsl:if test='$instruction/@mask-class'>
        <xsl:attribute name="mask">url(#<xsl:value-of select="$maskId"/>)</xsl:attribute>
      </xsl:if>
      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
    </use>
  </xsl:template>


  <xsl:template name='generateMask'>
    <xsl:param name='instruction' />
    <xsl:param name='pathId'/>
    <xsl:param name='maskId'/>

    <!-- If the instruction has a mask class -->
    <xsl:if test='$instruction/@mask-class'>
      <mask id="{$maskId}" maskUnits="userSpaceOnUse">
        <use xlink:href="#{$pathId}" class="{$instruction/@mask-class} osmarender-stroke-linecap-round osmarender-mask-black" />
        <!-- Required for Inkscape bug -->
        <use xlink:href="#{$pathId}" class="{$instruction/@class} osmarender-mask-white" />
        <use xlink:href="#{$pathId}" class="{$instruction/@mask-class} osmarender-stroke-linecap-round osmarender-mask-black" />
      </mask>
    </xsl:if>
  </xsl:template>



  <!-- Draw a line for the current <way> element using the formatting of the current <line> instruction -->
  <xsl:template name="drawWay">
    <xsl:param name="instruction"/>
    <xsl:param name="way"/>
    <!-- The current way element if applicable -->
    <xsl:param name="layer"/>

    <xsl:variable name="extraClasses">
      <xsl:if test="$instruction/@suppress-markers-tag != ''">
        <xsl:variable name="suppressMarkersTag" select="$instruction/@suppress-markers-tag" />
        <xsl:variable name="firstNode" select="key('nodeById',$way/nd[1]/@ref)"/>
        <xsl:variable name="firstNodeMarkerGroupConnectionCount"
                      select="count(key('wayByNode',$firstNode/@id)/tag[@k=$suppressMarkersTag and ( @v = 'yes' or @v = 'true' )])" />
        <xsl:variable name="lastNode" select="key('nodeById',$way/nd[last()]/@ref)"/>
        <xsl:variable name="lastNodeMarkerGroupConnectionCount"
                      select="count(key('wayByNode',$lastNode/@id)/tag[@k=$suppressMarkersTag and ( @v = 'yes' or @v = 'true' )])" />
       
        <xsl:if test="$firstNodeMarkerGroupConnectionCount > 1">osmarender-no-marker-start</xsl:if>
        <xsl:if test="$lastNodeMarkerGroupConnectionCount > 1"> osmarender-no-marker-end</xsl:if>
      </xsl:if>
    </xsl:variable>

    <xsl:choose>
      <xsl:when test="$instruction/@smart-linecap='no'">
        <xsl:call-template name='drawPath'>
          <xsl:with-param name='pathId' select="concat('way_normal_',$way/@id)"/>
          <xsl:with-param name='instruction' select='$instruction'/>
          <xsl:with-param name="extraClasses" select='$extraClasses'/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="drawWayWithSmartLinecaps">
          <xsl:with-param name="instruction" select="$instruction"/>
          <xsl:with-param name="way" select="$way"/>
          <xsl:with-param name="layer" select="$layer"/>
          <xsl:with-param name="extraClasses" select='$extraClasses'/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <xsl:template name="drawWayWithSmartLinecaps">
    <xsl:param name="instruction"/>
    <xsl:param name="way"/>
    <!-- The current way element if applicable -->
    <xsl:param name="layer"/>
    <xsl:param name="extraClasses"/>

    <!-- The first half of the first segment and the last half of the last segment are treated differently from the main
			part of the way path.  The main part is always rendered with a butt line-cap.  Each end fragment is rendered with
			either a round line-cap, if it connects to some other path, or with its default line-cap if it is not connected
			to anything.  That way, cul-de-sacs etc are terminated with round, square or butt as specified in the style for the
			way. -->

    <!-- First draw the middle section of the way with round linejoins and butt linecaps -->
    <xsl:if test="count($way/nd) &gt; 1">
      <xsl:call-template name='drawPath'>
        <xsl:with-param name='pathId' select="concat('way_mid_',$way/@id)"/>
        <xsl:with-param name='instruction' select='$instruction'/>
        <xsl:with-param name='extraClasses'>osmarender-stroke-linecap-butt osmarender-no-marker-start osmarender-no-marker-end</xsl:with-param>
      </xsl:call-template>
    </xsl:if>


    <!-- For the first half segment in the way, count the number of segments that link to the from-node of this segment.
			Also count links where the layer tag is less than the layer of this way, if there are links on a lower layer then
			we can safely draw a butt line-cap because the lower layer will already have a round line-cap. -->
    <!-- Process the first segment in the way -->
    <xsl:variable name="firstNode" select="key('nodeById',$way/nd[1]/@ref)"/>

    <!-- Count the number of segments connecting to the from node. If there is only one (the current segment) then draw a default line.  -->
    <xsl:variable name="firstNodeConnectionCount" select="count(key('wayByNode',$firstNode/@id))" />

    <!-- Count the number of connectors at a layer lower than the current layer -->
    <xsl:variable name="firstNodeLowerLayerConnectionCount" select="
			count(key('wayByNode',$firstNode/@id)/tag[@k='layer' and @v &lt; $layer]) +
			count(key('wayByNode',$firstNode/@id)[count(tag[@k='layer'])=0 and $layer &gt; 0])
			" />
    <xsl:choose>
      <xsl:when test="$firstNodeConnectionCount=1">
        <xsl:call-template name='drawPath'>
          <xsl:with-param name='pathId' select="concat('way_start_',$way/@id)"/>
          <xsl:with-param name='instruction' select='$instruction'/>
          <xsl:with-param name="extraClasses"><xsl:value-of select="$extraClasses"/> osmarender-no-marker-end</xsl:with-param>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$firstNodeLowerLayerConnectionCount>0">
        <xsl:call-template name='drawPath'>
          <xsl:with-param name='pathId' select="concat('way_start_',$way/@id)"/>
          <xsl:with-param name='instruction' select='$instruction'/>
          <xsl:with-param name="extraClasses"><xsl:value-of select="$extraClasses"/> osmarender-stroke-linecap-butt osmarender-no-marker-end</xsl:with-param>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name='drawPath'>
          <xsl:with-param name='pathId' select="concat('way_start_',$way/@id)"/>
          <xsl:with-param name='instruction' select='$instruction'/>
          <xsl:with-param name="extraClasses"><xsl:value-of select="$extraClasses"/>  osmarender-stroke-linecap-round osmarender-no-marker-end</xsl:with-param>
        </xsl:call-template>
      </xsl:otherwise>

    </xsl:choose>


    <!-- Process the last segment in the way -->
    <xsl:variable name="lastNode" select="key('nodeById',$way/nd[last()]/@ref)"/>

    <!-- Count the number of segments connecting to the last node. If there is only one (the current segment) then draw
		     a default line.  -->
    <xsl:variable name="lastNodeConnectionCount" select="count(key('wayByNode',$lastNode/@id))" />

    <!-- Count the number of connectors at a layer lower than the current layer -->
    <xsl:variable name="lastNodeLowerLayerConnectionCount" select="
			count(key('wayByNode',$lastNode/@id)/tag[@k='layer' and @v &lt; $layer]) +
			count(key('wayByNode',$lastNode/@id)[count(tag[@k='layer'])=0 and $layer &gt; 0])
			" />


    <xsl:choose>
      <xsl:when test="$lastNodeConnectionCount=1">
        <xsl:call-template name='drawPath'>
          <xsl:with-param name='pathId' select="concat('way_end_',$way/@id)"/>
          <xsl:with-param name='instruction' select='$instruction'/>
          <xsl:with-param name="extraClasses"><xsl:value-of select="$extraClasses"/> osmarender-no-marker-start</xsl:with-param>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$lastNodeLowerLayerConnectionCount>0">
        <xsl:call-template name='drawPath'>
          <xsl:with-param name='pathId' select="concat('way_end_',$way/@id)"/>
          <xsl:with-param name='instruction' select='$instruction'/>
          <xsl:with-param name="extraClasses"><xsl:value-of select="$extraClasses"/> osmarender-stroke-linecap-butt osmarender-no-marker-start</xsl:with-param>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name='drawPath'>
          <xsl:with-param name='pathId' select="concat('way_end_',$way/@id)"/>
          <xsl:with-param name='instruction' select='$instruction'/>
          <xsl:with-param name="extraClasses"><xsl:value-of select="$extraClasses"/> osmarender-stroke-linecap-round osmarender-no-marker-start</xsl:with-param>
        </xsl:call-template>
      </xsl:otherwise>

    </xsl:choose>

  </xsl:template>


  <!-- Draw a circle for the current <node> element using the formatting of the current <circle> instruction -->
  <xsl:template name="drawCircle">
    <xsl:param name="instruction"/>

    <xsl:variable name="x" select="($width)-((($topRightLongitude)-(@lon))*10000*$scale)"/>
    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-(@lat))*10000*$scale*$projection)"/>

    <circle cx="{$x}" cy="{$y}">
      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
      <!-- Copy all the svg attributes from the <circle> instruction -->
    </circle>

  </xsl:template>


  <!-- Draw a symbol for the current <node> element using the formatting of the current <symbol> instruction -->
  <xsl:template name="drawSymbol">
    <xsl:param name="instruction"/>

    <xsl:variable name="x" select="($width)-((($topRightLongitude)-(@lon))*10000*$scale)"/>
    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-(@lat))*10000*$scale*$projection)"/>

    <g transform="translate({$x},{$y}) scale({$symbolScale})">
      <use>
        <xsl:if test="$instruction/@ref">
          <xsl:attribute name="xlink:href">
            <xsl:value-of select="concat('#symbol-', $instruction/@ref)"/>
          </xsl:attribute>
        </xsl:if>
        <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
	<!-- Copy all the attributes from the <symbol> instruction -->
      </use>
    </g>
  </xsl:template>


  <!-- Render the appropriate attribute of the current <node> element using the formatting of the current <text> instruction -->
  <xsl:template name="renderText">
    <xsl:param name="instruction"/>

    <xsl:variable name="x" select="($width)-((($topRightLongitude)-(@lon))*10000*$scale)"/>
    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-(@lat))*10000*$scale*$projection)"/>

    <text>
      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
      <xsl:attribute name="x">
        <xsl:value-of select="$x"/>
      </xsl:attribute>
      <xsl:attribute name="y">
        <xsl:value-of select="$y"/>
      </xsl:attribute>
      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
      <xsl:value-of select="tag[@k=$instruction/@k]/@v"/>
    </text>
  </xsl:template>


  <!-- Render the appropriate attribute of the current <segment> element using the formatting of the current <textPath> instruction -->
  <xsl:template name="renderTextPath">
    <xsl:param name="instruction"/>
    <xsl:param name="pathId"/>
    <xsl:param name="pathDirection"/>
    <xsl:param name='text'/>

    <xsl:variable name='pathLengthSquared'>
      <xsl:call-template name='getPathLength'>
        <xsl:with-param name='pathLengthMultiplier'>
          <!-- This factor is used to adjust the path-length for comparison with text along a path to determine whether it will fit. -->
          <xsl:choose>
            <xsl:when test='$instruction/@textAttenuation'>
              <xsl:value-of select='$instruction/@textAttenuation'/>
            </xsl:when>
            <xsl:when test='string($textAttenuation)'>
              <xsl:value-of select='$textAttenuation'/>
            </xsl:when>
            <xsl:otherwise>99999999</xsl:otherwise>
          </xsl:choose>
        </xsl:with-param>
        <xsl:with-param name='nodes' select='nd'/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:variable name='textLength' select='string-length($text)' />
    <xsl:variable name='textLengthSquared100' select='($textLength)*($textLength)' />
    <xsl:variable name='textLengthSquared90' select='($textLength *.9)*($textLength*.9)' />
    <xsl:variable name='textLengthSquared80' select='($textLength *.8)*($textLength*.8)' />
    <xsl:variable name='textLengthSquared70' select='($textLength *.7)*($textLength*.7)' />

    <xsl:choose>
      <xsl:when test='($pathLengthSquared) > $textLengthSquared100'>
        <text>
          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
          <textPath xlink:href="#{$pathId}">
            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
            <xsl:value-of select="$text"/>
          </textPath>
        </text>
      </xsl:when>
      <xsl:when test='($pathLengthSquared) > ($textLengthSquared90)'>
        <text>
          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
          <textPath xlink:href="#{$pathId}">
            <xsl:attribute name='font-size'>90%</xsl:attribute>
            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
            <xsl:value-of select="$text"/>
          </textPath>
        </text>
      </xsl:when>
      <xsl:when test='($pathLengthSquared) > ($textLengthSquared80)'>
        <text>
          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
          <textPath xlink:href="#{$pathId}">
            <xsl:attribute name='font-size'>80%</xsl:attribute>
            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
            <xsl:value-of select="$text"/>
          </textPath>
        </text>
      </xsl:when>
      <xsl:when test='($pathLengthSquared) > ($textLengthSquared70)'>
        <text>
          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
          <textPath xlink:href="#{$pathId}">
            <xsl:attribute name='font-size'>70%</xsl:attribute>
            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
            <xsl:value-of select="$text"/>
          </textPath>
        </text>
      </xsl:when>
      <xsl:otherwise />
      <!-- Otherwise don't render the text -->
    </xsl:choose>
  </xsl:template>


  <xsl:template name='getPathLength'>
    <xsl:param name='sumLon' select='number("0")' />
    <!-- initialise sum to zero -->
    <xsl:param name='sumLat' select='number("0")' />
    <!-- initialise sum to zero -->
    <xsl:param name='nodes'/>
    <xsl:param name='pathLengthMultiplier'/>
    <xsl:choose>
      <xsl:when test='$nodes[1] and $nodes[2]'>
        <xsl:variable name='fromNode' select='key("nodeById",$nodes[1]/@ref)'/>
        <xsl:variable name='toNode' select='key("nodeById",$nodes[2]/@ref)'/>
        <xsl:variable name='lengthLon' select='($fromNode/@lon)-($toNode/@lon)'/>
        <xsl:variable name='absLengthLon'>
          <xsl:choose>
            <xsl:when test='$lengthLon &lt; 0'>
              <xsl:value-of select='$lengthLon * -1'/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select='$lengthLon'/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>
        <xsl:variable name='lengthLat' select='($fromNode/@lat)-($toNode/@lat)'/>
        <xsl:variable name='absLengthLat'>
          <xsl:choose>
            <xsl:when test='$lengthLat &lt; 0'>
              <xsl:value-of select='$lengthLat * -1'/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select='$lengthLat'/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>
        <xsl:call-template name='getPathLength'>
          <xsl:with-param name='sumLon' select='$sumLon+$absLengthLon'/>
          <xsl:with-param name='sumLat' select='$sumLat+$absLengthLat'/>
          <xsl:with-param name='nodes' select='$nodes[position()!=1]'/>
          <xsl:with-param name='pathLengthMultiplier' select='$pathLengthMultiplier'/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <!-- Add the square of the total horizontal length to the square of the total vertical length to get the square of
				     the total way length.  We don't have a sqrt() function so leave it squared.
				     Multiply by 1,000 so that we are usually dealing with a values greater than 1.  Squares of values between 0 and 1
				     are smaller and so not very useful.
				     Multiply the latitude component by $projection to adjust for Mercator projection issues. 
				     -->
        <xsl:value-of select='(
					(($sumLon*1000*$pathLengthMultiplier)*($sumLon*1000*$pathLengthMultiplier))+
					(($sumLat*1000*$pathLengthMultiplier*$projection)*($sumLat*1000*$pathLengthMultiplier*$projection))
					)'/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <!-- Suppress the following attributes, allow everything else -->
  <xsl:template match="@startOffset|@method|@spacing|@lengthAdjust|@textLength|@k" mode="renderTextPath-text" />

  <xsl:template match="@*" mode="renderTextPath-text">
    <xsl:copy/>
  </xsl:template>


  <!-- Allow the following attributes, suppress everything else -->
  <xsl:template match="@startOffset|@method|@spacing|@lengthAdjust|@textLength" mode="renderTextPath-textPath">
    <xsl:copy/>
  </xsl:template>

  <xsl:template match="@*" mode="renderTextPath-textPath" />


  <!-- If there are any tags like <tag k="svg:font-size" v="5"/> then add these as attributes of the svg output -->
  <xsl:template name="getSvgAttributesFromOsmTags">
    <xsl:for-each select="tag[contains(@k,'svg:')]">
      <xsl:attribute name="{substring-after(@k,'svg:')}">
        <xsl:value-of select="@v"/>
      </xsl:attribute>
    </xsl:for-each>
  </xsl:template>


  <xsl:template name="renderArea">
    <xsl:param name="instruction"/>
    <xsl:param name="pathId"/>

    <use xlink:href="#{$pathId}">
      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
    </use>
  </xsl:template>


  <!-- Templates to process line, circle, text, etc. instructions -->
  <!-- Each template is passed a variable containing the set of elements that need to
         be processed.  The set of elements is already determined by the rules, so
         these templates don't need to know anything about the rules context they are in. -->

  <!-- Process a <line> instruction -->
  <xsl:template match="line">
    <xsl:param name="elements"/>
    <xsl:param name="layer"/>

    <!-- This is the instruction that is currently being processed -->
    <xsl:variable name="instruction" select="."/>

    <g>
      <xsl:apply-templates select="@*" mode="copyAttributes" />
      <!-- Add all the svg attributes of the <line> instruction to the <g> element -->

      <!-- For each way -->
      <xsl:apply-templates select="$elements" mode="line">
        <xsl:with-param name="instruction" select="$instruction"/>
        <xsl:with-param name="layer" select="$layer"/>
      </xsl:apply-templates>

    </g>
  </xsl:template>


  <!-- Suppress output of any unhandled elements -->
  <xsl:template match="*" mode="line"/>


  <!-- Draw lines for a way  -->
  <xsl:template match="way" mode="line">
    <xsl:param name="instruction"/>
    <xsl:param name="layer"/>

    <!-- The current <way> element -->
    <xsl:variable name="way" select="."/>

    <!-- DODI: !!!WORKAROUND!!! skip one node ways-->
    <xsl:if test="count($way/nd) &gt; 1">
      <xsl:call-template name="drawWay">
        <xsl:with-param name="instruction" select="$instruction"/>
        <xsl:with-param name="way" select="$way"/>
        <xsl:with-param name="layer" select="$layer"/>
      </xsl:call-template>
    </xsl:if >
  </xsl:template>


  <!-- Draw lines for a relation -->
  <xsl:template match="relation" mode="line">
    <xsl:param name="instruction"/>
    <xsl:param name="layer"/>

    <xsl:variable name="relation" select="@id"/>

    <xsl:message>Processing route relation.</xsl:message>

    <xsl:if test="(tag[@k='type']/@v='route') and ($showRelationRoute!='~|no')">
      <!-- Draw lines for a RelationRoute -->
      <xsl:for-each select="$data/osm/relation[@id=$relation]/member[@type='way']">
        <xsl:variable name="wayid" select="@ref"/>

        <xsl:for-each select="$data/osm/way[@id=$wayid]">
          <!-- The current <way> element -->
          <xsl:variable name="way" select="."/>

          <!-- DODI: !!!WORKAROUND!!! skip one node ways-->
          <xsl:if test="count($way/nd) &gt; 1">
            <xsl:call-template name="drawWay">
              <xsl:with-param name="instruction" select="$instruction"/>
              <xsl:with-param name="way" select="$way"/>
              <xsl:with-param name="layer" select="$layer"/>
            </xsl:call-template>
          </xsl:if>
        </xsl:for-each>
      </xsl:for-each>
    </xsl:if>

    <!-- Handle other types of Relations if necessary -->

  </xsl:template>

  <!-- Draw areas for a boundary relation -->
  <xsl:template match="relation" mode="area">
    <xsl:param name="instruction"/>
    <xsl:param name="layer"/>

    <xsl:variable name="relation" select="@id"/>

    <xsl:message>
        Processing boundary relation: <xsl:value-of select="tag[@k='name']/@v"/>
    </xsl:message>

    <xsl:if test="(tag[@k='type']/@v='boundary') and ($showRelationBoundary!='~|no')">
      <!-- Generate an area for a relation Boundary -->
      <xsl:variable name="boundaryWays" select="$data/osm/relation[@id=$relation]/member[@type='way'][key('wayById', @ref)]"/>
      <xsl:variable name="firstWay" select="key('wayById',$boundaryWays[1]/@ref)"/>
      <xsl:message>
        count(boundaryWays): <xsl:value-of select="count($boundaryWays)"/>
      </xsl:message>
      <xsl:variable name="pathArea">
        <xsl:call-template name="generateRelationBorderPath">
            <xsl:with-param name="way"          select="$firstWay"/>
            <xsl:with-param name="firstWay"     select="$firstWay"/>
            <xsl:with-param name="reverse"      select="0 != 0"/><!-- false -->
            <xsl:with-param name="recursions"   select="1"/>
            <xsl:with-param name="boundaryWays" select="$boundaryWays"/>
        </xsl:call-template>
      </xsl:variable>
      <xsl:if test ="$pathArea!=''">
        <path id="area_{@id}" d="{$pathArea}"/>
        <xsl:call-template name="renderArea">
          <xsl:with-param name="instruction" select="$instruction"/>
          <xsl:with-param name="pathId" select="concat('area_',@id)"/>
        </xsl:call-template>
      </xsl:if>
    </xsl:if>
  </xsl:template>

  <!-- a recursive template which actually does the 
       drawing for boundary relations -->
  <xsl:template name="generateRelationBorderPath">
      <xsl:param name="way"/>
      <xsl:param name="firstWay"/>
      <xsl:param name="boundaryWays"/>
      <xsl:param name="reverse"/>
      <xsl:param name="recursions"/>

      <xsl:variable name="first" select="$way/nd[1]/@ref"/>
      <xsl:variable name="last" select="$way/nd[last()]/@ref"/>
      <xsl:variable name="firstNodeWays" select="key('wayByNode',$first)"/>
      <xsl:variable name="lastNodeWays" select="key('wayByNode',$last)"/>

      <xsl:message>
              WayID: <xsl:value-of select="$way/@id"/>
         firstWayID: <xsl:value-of select="$firstWay/@id"/>
           position: <xsl:value-of select="position()"/>
          firstNode: <xsl:value-of select="$first"/>
           lastNode: <xsl:value-of select="$last"/>
           reversed: <xsl:choose><xsl:when test="$reverse">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose>
      </xsl:message>

      <xsl:for-each select="$way/tag">
          <xsl:message>
               tagName: <xsl:value-of select="@k"/>
              tagValue: <xsl:value-of select="@v"/>
          </xsl:message>
      </xsl:for-each>

      <xsl:choose>
        <xsl:when test="$reverse">
          <xsl:for-each select="$way/nd">
            <xsl:sort select="position()" data-type="number" order="descending"/>
            <xsl:choose>
              <xsl:when test="($firstWay/@id = $way/@id) and (position() = 1)">
                <xsl:call-template name="moveToNode">
                  <xsl:with-param name="node" select="key('nodeById',@ref)"/>
                </xsl:call-template>
              </xsl:when>
              <xsl:otherwise>
                <xsl:call-template name="lineToNode">
                  <xsl:with-param name="node" select="key('nodeById',@ref)"/>
                </xsl:call-template>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:for-each>
        </xsl:when>
        <xsl:otherwise>
          <xsl:for-each select="$way/nd">
            <xsl:choose>
              <xsl:when test="($firstWay/@id = $way/@id) and (position() = 1)">
                <xsl:call-template name="moveToNode">
                  <xsl:with-param name="node" select="key('nodeById',@ref)"/>
                </xsl:call-template>
              </xsl:when>
              <xsl:otherwise>
                <xsl:call-template name="lineToNode">
                  <xsl:with-param name="node" select="key('nodeById',@ref)"/>
                </xsl:call-template>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:for-each>
        </xsl:otherwise>
      </xsl:choose>

      <xsl:variable name="nextWayID">
          <xsl:choose>
              <xsl:when test="$reverse">
                  <xsl:call-template name="getNextWayID">
                      <xsl:with-param name="nodeWays" select="$firstNodeWays"/>
                      <xsl:with-param name="boundaryWays" select="$boundaryWays"/>
                      <xsl:with-param name="currentWay" select="$way"/>
                  </xsl:call-template>
              </xsl:when>
              <xsl:otherwise>
                  <xsl:call-template name="getNextWayID">
                      <xsl:with-param name="nodeWays" select="$lastNodeWays"/>
                      <xsl:with-param name="boundaryWays" select="$boundaryWays"/>
                      <xsl:with-param name="currentWay" select="$way"/>
                  </xsl:call-template>
              </xsl:otherwise>
          </xsl:choose>
      </xsl:variable>

      <xsl:variable 
            name="nextReverse" 
            select="($last = key('wayById',$nextWayID)/nd[last()]/@ref) or
                    ($first = key('wayById',$nextWayID)/nd[last()]/@ref)"/>

      <xsl:choose>
          <xsl:when test="$recursions >= count($boundaryWays)">
              <xsl:text>Z</xsl:text>
          </xsl:when>
          <xsl:otherwise>
              <xsl:call-template name="generateRelationBorderPath">
                  <xsl:with-param name="way" select="key('wayById',$nextWayID)"/>
                  <xsl:with-param name="firstWay" select="$firstWay"/>
                  <xsl:with-param name="reverse" select="$nextReverse"/>
                  <xsl:with-param name="boundaryWays" select="$boundaryWays"/>
                  <xsl:with-param name="recursions" select="$recursions + 1"/>
              </xsl:call-template>
          </xsl:otherwise>
      </xsl:choose>
  </xsl:template>

  <xsl:template name="getNextWayID">
      <xsl:param name="nodeWays"/>
      <xsl:param name="boundaryWays"/>
      <xsl:param name="currentWay"/>
      <xsl:for-each select="$nodeWays">
          <xsl:variable name="wayID" select="@id"/>
          <xsl:variable name="nextWayID" select="$boundaryWays[@ref=$wayID]/@ref"/>
          <xsl:if test="$nextWayID != $currentWay/@id">
              <xsl:value-of select="$nextWayID"/>
          </xsl:if>
      </xsl:for-each>
  </xsl:template>


  <!-- Process an <area> instruction -->
  <xsl:template match="area">
    <xsl:param name="elements"/>

    <xsl:message>Processing &lt;area&gt; for <xsl:value-of select="count($elements)"/> elements.</xsl:message>

    <!-- This is the instruction that is currently being processed -->
    <xsl:variable name="instruction" select="."/>

    <g>
      <xsl:apply-templates select="@*" mode="copyAttributes"/>
      <!-- Add all the svg attributes of the <line> instruction to the <g> element -->

      <!-- For each way -->
      <xsl:apply-templates select="$elements" mode="area">
        <xsl:with-param name="instruction" select="$instruction"/>
      </xsl:apply-templates>
    </g>
  </xsl:template>


  <!-- Discard anything that is not matched by a more specific template -->
  <xsl:template match="*" mode="area"/>


  <!-- Draw area for a <way> -->
  <xsl:template match="way" mode="area">
    <xsl:param name="instruction"/>

    <!-- DODI:  removed because duplicate definition generated if area referenced 2 or more times -->
    <!-- DODI:  reenabled because of "duplicate point detection in lines2curves.pl " -->
    <!-- <xsl:call-template name="generateAreaPath"/> -->

    <xsl:variable name="pathArea">
      <xsl:call-template name="generateAreaPath"/>
    </xsl:variable>

    <!-- DODI: do now draw empty ways/areas-->
    <xsl:if test ="$pathArea!=''">
      <path id="area_{@id}" d="{$pathArea}"/>
      <xsl:call-template name="renderArea">
        <xsl:with-param name="instruction" select="$instruction"/>
        <xsl:with-param name="pathId" select="concat('area_',@id)"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>


  <!-- Process <circle> instruction -->
  <xsl:template match="circle">
    <xsl:param name="elements"/>
    <xsl:param name="layer"/>

    <!-- This is the instruction that is currently being processed -->
    <xsl:variable name="instruction" select="."/>

    <!-- For each circle -->
    <xsl:apply-templates select="$elements" mode="circle">
      <xsl:with-param name="instruction" select="$instruction"/>
      <xsl:with-param name="layer" select="$layer"/>
      <xsl:with-param name="elements" select="$elements"/>
    </xsl:apply-templates>
  </xsl:template>


  <!-- Suppress output of any unhandled elements -->
  <xsl:template match="*" mode="circle"/>


  <!-- Draw circle for a node -->
  <xsl:template match="node" mode="circle">
    <xsl:param name="instruction"/>
    <xsl:param name="elements"/>

    <xsl:for-each select="$elements[name()='node']">
      <xsl:call-template name="drawCircle">
        <xsl:with-param name="instruction" select="$instruction"/>
      </xsl:call-template>
    </xsl:for-each>

  </xsl:template>


  <!-- Draw circle for a relation -->
  <xsl:template match="relation" mode="circle">
    <xsl:param name="instruction"/>
    <xsl:param name="layer"/>

    <xsl:variable name="relation" select="@id"/>

    <xsl:if test="(tag[@k='type']/@v='route') and ($showRelationRoute!='~|no')">
      <!-- Draw Circles for a RelationRoute Stop -->
      <xsl:for-each select="$data/osm/relation[@id=$relation]/member[@type='node']">
        <xsl:variable name="nodeid" select="@ref"/>

        <xsl:for-each select="$data/osm/node[@id=$nodeid]">
          <xsl:call-template name="drawCircle">
            <xsl:with-param name="instruction" select="$instruction"/>
            <xsl:with-param name="node" select="@id"/>
          </xsl:call-template>
        </xsl:for-each>
      </xsl:for-each>
    </xsl:if>

    <!-- Handle other types of Relations if necessary -->

  </xsl:template>


  <!-- Process a <symbol> instruction -->
  <xsl:template match="symbol">
    <xsl:param name="elements"/>

    <!-- This is the instruction that is currently being processed -->
    <xsl:variable name="instruction" select="."/>

    <xsl:for-each select="$elements[name()='node']">
      <xsl:call-template name="drawSymbol">
        <xsl:with-param name="instruction" select="$instruction"/>
      </xsl:call-template>
    </xsl:for-each>

  </xsl:template>

  <!-- wayMarker instruction.  Draws a marker on a node that is perpendicular to a way that passes through the node.
       If more than one way passes through the node then the result is a bit unspecified.  -->
  <xsl:template match="wayMarker">
    <xsl:param name="elements"/>
    
    <!-- This is the instruction that is currently being processed -->
    <xsl:variable name="instruction" select="."/>
    
    <g>
      <!-- Add all the svg attributes of the <wayMarker> instruction to the <g> element -->
      <xsl:apply-templates select="@*" mode="copyAttributes" />
      
      <!-- Process each matched node in turn -->
      <xsl:for-each select="$elements[name()='node']">
	<xsl:variable name='nodeId' select="@id" />
	
	<xsl:variable name='way' select="key('wayByNode', @id)" />
	<xsl:variable name='previousNode' select="key('nodeById', $way/nd[@ref=$nodeId]/preceding-sibling::nd[1]/@ref)" />
	<xsl:variable name='nextNode' select="key('nodeById', $way/nd[@ref=$nodeId]/following-sibling::nd[1]/@ref)" />
	
	<xsl:variable name='path'>
	  <xsl:choose>
	    <xsl:when test='$previousNode and $nextNode'>
	      <xsl:call-template name="moveToNode">
		<xsl:with-param name="node" select="$previousNode"/>
	      </xsl:call-template>
	      <xsl:call-template name="lineToNode">
		<xsl:with-param name="node" select="."/>
	      </xsl:call-template>
	      <xsl:call-template name="lineToNode">
		<xsl:with-param name="node" select="$nextNode"/>
	      </xsl:call-template>
	    </xsl:when>

	    <xsl:when test='$previousNode'>
	      <xsl:call-template name="moveToNode">
		<xsl:with-param name="node" select="$previousNode"/>
	      </xsl:call-template>
	      <xsl:call-template name="lineToNode">
		<xsl:with-param name="node" select="."/>
	      </xsl:call-template>
	      <xsl:call-template name="lineToNode">
		<xsl:with-param name="node" select="."/>
	      </xsl:call-template>
	    </xsl:when>

	    <xsl:when test='$nextNode'>
	      <xsl:call-template name="moveToNode">
		<xsl:with-param name="node" select="."/>
	      </xsl:call-template>
	      <xsl:call-template name="lineToNode">
		<xsl:with-param name="node" select="$nextNode"/>
	      </xsl:call-template>
	      <xsl:call-template name="lineToNode">
		<xsl:with-param name="node" select="$nextNode"/>
	      </xsl:call-template>
	    </xsl:when>
	  </xsl:choose>
	</xsl:variable>
	
	<path id="nodePath_{@id}" d="{$path}"/>
	
	<use xlink:href="#nodePath_{@id}">
	  <xsl:apply-templates select="$instruction/@*" mode="copyAttributes" />
	</use>
      </xsl:for-each>
    </g>
    
  </xsl:template>

  <!-- Process an <areaText> instruction -->
  <xsl:template match="areaText">
    <xsl:param name="elements"/>

    <!-- This is the instruction that is currently being processed -->
    <xsl:variable name="instruction" select="."/>

    <!-- Select all <way> elements that have a key that matches the k attribute of the text instruction -->
    <xsl:apply-templates select="$elements[name()='way'][tag[@k=$instruction/@k]]" mode="areaTextPath">
      <xsl:with-param name="instruction" select="$instruction"/>
    </xsl:apply-templates>
  </xsl:template>


  <xsl:template match="*" mode="areaTextPath"/>


  <xsl:template match="way" mode="areaTextPath">
    <xsl:param name="instruction"/>

    <!-- The current <way> element -->
    <xsl:variable name="way" select="."/>

    <xsl:call-template name="renderAreaText">
      <xsl:with-param name="instruction" select="$instruction"/>
      <xsl:with-param name="pathId" select="concat('way_normal_',@id)"/>
    </xsl:call-template>

  </xsl:template>


  <xsl:template name="renderAreaText">
    <xsl:param name="instruction"/>

    <xsl:variable name='center'>
      <xsl:call-template name="areaCenter">
	<xsl:with-param name="element" select="." />
      </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="centerLon" select="substring-before($center, ',')" />
    <xsl:variable name="centerLat" select="substring-after($center, ',')" />

    <xsl:variable name="x" select="($width)-((($topRightLongitude)-($centerLon))*10000*$scale)"/>
    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-($centerLat))*10000*$scale*$projection)"/>

    <text>
      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
      <xsl:attribute name="x">
        <xsl:value-of select="$x"/>
      </xsl:attribute>
      <xsl:attribute name="y">
        <xsl:value-of select="$y"/>
      </xsl:attribute>
      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
      <xsl:value-of select="tag[@k=$instruction/@k]/@v"/>
    </text>
  </xsl:template>

  <!-- Process an <areaSymbol> instruction -->
  <xsl:template match="areaSymbol">
    <xsl:param name="elements"/>

    <!-- This is the instruction that is currently being processed -->
    <xsl:variable name="instruction" select="."/>

    <!-- Select all <way> elements -->
    <xsl:apply-templates select="$elements[name()='way']" mode="areaSymbolPath">
      <xsl:with-param name="instruction" select="$instruction"/>
    </xsl:apply-templates>
  </xsl:template>


  <xsl:template match="*" mode="areaSymbolPath"/>


  <xsl:template match="way" mode="areaSymbolPath">
    <xsl:param name="instruction"/>

    <!-- The current <way> element -->
    <xsl:variable name="way" select="."/>

    <xsl:call-template name="renderAreaSymbol">
      <xsl:with-param name="instruction" select="$instruction"/>
      <xsl:with-param name="pathId" select="concat('way_normal_',@id)"/>
    </xsl:call-template>

  </xsl:template>


  <xsl:template name="renderAreaSymbol">
    <xsl:param name="instruction"/>

    <xsl:variable name='center'>
      <xsl:call-template name="areaCenter">
	<xsl:with-param name="element" select="." />
      </xsl:call-template>
    </xsl:variable>

    <xsl:message>
      areaCenter: <xsl:value-of select="$center" />
    </xsl:message>

    <xsl:variable name="centerLon" select="substring-before($center, ',')" />
    <xsl:variable name="centerLat" select="substring-after($center, ',')" />

    <xsl:variable name="x" select="($width)-((($topRightLongitude)-($centerLon))*10000*$scale)"/>
    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-($centerLat))*10000*$scale*$projection)"/>

    <g transform="translate({$x},{$y}) scale({$symbolScale})">
      <use>
        <xsl:if test="$instruction/@ref">
          <xsl:attribute name="xlink:href">
            <xsl:value-of select="concat('#symbol-', $instruction/@ref)"/>
          </xsl:attribute>
        </xsl:if>
        <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
        <!-- Copy all the attributes from the <symbol> instruction -->
      </use>
    </g>
  </xsl:template>

  <!--
      areaCenter: Find a good center point for label/icon placement inside of polygon.
      Algorithm is described at http://bob.cakebox.net/poly-center.php
  -->
  <xsl:template name="areaCenter">
    <xsl:param name="element" />

    <!-- Get multipolygon relation for areas with holes -->
    <xsl:variable name='holerelation' select="key('relationByWay',$element/@id)[tag[@k='type' and @v='multipolygon']]"/>

    <!-- A semicolon-separated list of x,y coordinate pairs of points lying halfway into the polygon at angles to the vertex -->
    <xsl:variable name="points">
      <xsl:call-template name="areacenterPointsInside">
	<xsl:with-param name="element" select="$element" />
	<xsl:with-param name="holerelation" select="$holerelation" />
      </xsl:call-template>
    </xsl:variable>

    <!-- x,y calculated by a simple average over all x/y's in points -->
    <xsl:variable name="mediumpoint">
      <xsl:call-template name="areacenterMediumOfPoints">
	<xsl:with-param name="points" select="$points" />
      </xsl:call-template>
    </xsl:variable>
    <xsl:variable name="mediumpoint_x" select="substring-before($mediumpoint, ',')" />
    <xsl:variable name="mediumpoint_y" select="substring-before(substring-after($mediumpoint, ','), ',')" />
    <xsl:variable name="medium_dist" select="substring-after(substring-after($mediumpoint, ','), ',')" />

    <!-- Find out if mediumpoint is inside or outside the polygon -->
    <xsl:variable name="intersection">
      <xsl:call-template name="areacenterNearestIntersectionInside">
	<xsl:with-param name="x" select="$mediumpoint_x" />
	<xsl:with-param name="y" select="$mediumpoint_y" />
	<xsl:with-param name="edgestart" select="$element/nd[1]" />
	<xsl:with-param name="linepoint_x" select="$mediumpoint_x" />
	<xsl:with-param name="linepoint_y" select="$mediumpoint_y + 1" />
	<xsl:with-param name="holerelation" select="$holerelation" />
      </xsl:call-template>
    </xsl:variable>
    <xsl:variable name="intersection_count" select="substring-before($intersection, ';')" />

    <xsl:variable name="nearestEdge">
      <xsl:call-template name="areacenterNearestEdge">
	<xsl:with-param name="x" select="$mediumpoint_x" />
	<xsl:with-param name="y" select="$mediumpoint_y" />
	<xsl:with-param name="edgestart" select="$element/nd[1]" />
	<xsl:with-param name="holerelation" select="$holerelation" />
      </xsl:call-template>
    </xsl:variable>

    <xsl:choose>
      <xsl:when test="$intersection_count mod 2 = 0 or $nearestEdge div 2 * 1.20 &gt; $medium_dist">
	<!-- Find the best point in $points to use -->
	<xsl:call-template name="areacenterBestPoint">
	  <xsl:with-param name="points" select="$points" />
	  <xsl:with-param name="x" select="$mediumpoint_x" />
	  <xsl:with-param name="y" select="$mediumpoint_y" />
	  <xsl:with-param name="medium_dist" select="$medium_dist" />
	</xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
	<xsl:value-of select="$mediumpoint_x"/>,<xsl:value-of select="$mediumpoint_y"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Returns a semicolon-separated list of x,y pairs -->
  <xsl:template name="areacenterPointsInside">
    <xsl:param name="element" />
    <xsl:param name="holerelation" />

    <!-- iterate over every vertex except the first one, which is also the last -->
    <xsl:for-each select="$element/nd[position() &gt; 1]">
      <xsl:variable name="vertex" select="." />
      <xsl:variable name="prev" select="$vertex/preceding-sibling::nd[1]" />
      <xsl:variable name="nextId">
	<xsl:choose>
	  <xsl:when test="position() &lt; last()">
	    <xsl:value-of select="$vertex/following-sibling::nd[1]/@ref" />
	  </xsl:when>
	  <xsl:otherwise>
	    <xsl:value-of select="$vertex/../nd[2]/@ref" />
	  </xsl:otherwise>
	</xsl:choose>
      </xsl:variable>
      <xsl:variable name="next" select="$vertex/../nd[@ref=$nextId]" />

      <!-- Angle at between $prev and $next in $vertex -->
      <xsl:variable name="angle">
	<xsl:call-template name="angleThroughPoints">
	  <xsl:with-param name="from" select="key('nodeById', $prev/@ref)" />
	  <xsl:with-param name="through" select="key('nodeById', $vertex/@ref)" />
	  <xsl:with-param name="to" select="key('nodeById', $next/@ref)" />
	</xsl:call-template>
      </xsl:variable>

      <!-- Calculate a point on the line going through $vertex at $angle -->
      <xsl:variable name="linepoint">
	<xsl:call-template name="areacenterLinepoint">
	  <xsl:with-param name="point" select="key('nodeById', $vertex/@ref)" />
	  <xsl:with-param name="angle" select="$angle" />
	</xsl:call-template>
      </xsl:variable>
      <xsl:variable name="linepoint_x" select="substring-before($linepoint, ',')" />
      <xsl:variable name="linepoint_y" select="substring-after($linepoint, ',')" />

      <!-- Find the nearest intersection between the line vertex-linepoint and the nearest edge inwards into the polygon -->
      <xsl:variable name="intersection">
	<xsl:call-template name="areacenterNearestIntersectionInside">
	  <xsl:with-param name="x" select="key('nodeById', $vertex/@ref)/@lon" />
	  <xsl:with-param name="y" select="key('nodeById', $vertex/@ref)/@lat" />
	  <xsl:with-param name="edgestart" select="../nd[1]" />
	  <xsl:with-param name="linepoint_x" select="$linepoint_x" />
	  <xsl:with-param name="linepoint_y" select="$linepoint_y" />
	  <xsl:with-param name="holerelation" select="$holerelation" />
	</xsl:call-template>
      </xsl:variable>
      <xsl:variable name="intersection_count" select="substring-before($intersection, ';')" />
      <xsl:variable name="intersection_data">
	<xsl:choose>
	  <xsl:when test="$intersection_count mod 2 != 0">
	    <xsl:value-of select="substring-before(substring-after($intersection, ';'), ';')" />
	  </xsl:when>
	  <xsl:otherwise>
	    <xsl:value-of select="substring-after(substring-after($intersection, ';'), ';')" />
	  </xsl:otherwise>
	</xsl:choose>
      </xsl:variable>
      <xsl:variable name="intersection_x" select="substring-before($intersection_data, ',')" />
      <xsl:variable name="intersection_y" select="substring-before(substring-after($intersection_data, ','), ',')" />
      <xsl:variable name="intersection_dist" select="substring-before(substring-after(substring-after($intersection_data, ','), ','), ',')" />

      <xsl:variable name="point_x" select="key('nodeById', $vertex/@ref)/@lon + ( $intersection_x - key('nodeById', $vertex/@ref)/@lon ) div 2" />
      <xsl:variable name="point_y" select="key('nodeById', $vertex/@ref)/@lat + ( $intersection_y - key('nodeById', $vertex/@ref)/@lat ) div 2" />
      
      <xsl:if test="($point_x &lt;= 0 or $point_x &gt; 0)  and ($point_y &lt;= 0 or $point_y &gt; 0)"> <!-- Only return anything if we actually have a result -->
	<!-- Note: this will produce trailing semicolon, which is nice as it simplifies looping over this later -->
	<xsl:value-of select="$point_x" />,<xsl:value-of select="$point_y" />,<xsl:value-of select="$intersection_dist" />;
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

  <!-- Calculate the angle between $from and $to in $through. Returns answer in radians -->
  <xsl:template name="angleThroughPoints">
    <xsl:param name="from" />
    <xsl:param name="through" />
    <xsl:param name="to" />

    <xsl:variable name="from_x" select="($from/@lon) - ($through/@lon)" />
    <xsl:variable name="from_y" select="$from/@lat - $through/@lat" />
    <xsl:variable name="to_x" select="$to/@lon - $through/@lon" />
    <xsl:variable name="to_y" select="$to/@lat - $through/@lat" />

    <xsl:variable name="from_angle_">
      <xsl:call-template name="atan2">
	<xsl:with-param name="x" select="$from_x" />
	<xsl:with-param name="y" select="$from_y" />
      </xsl:call-template>
    </xsl:variable>
    <xsl:variable name="from_angle" select="$from_angle_ + $pi" />
    <xsl:variable name="to_angle_">
      <xsl:call-template name="atan2">
	<xsl:with-param name="x" select="$to_x" />
	<xsl:with-param name="y" select="$to_y" />
      </xsl:call-template>
    </xsl:variable>
    <xsl:variable name="to_angle" select="$to_angle_ + $pi" />

    <xsl:variable name="min_angle">
      <xsl:choose>
	<xsl:when test="$from_angle &gt; $to_angle">
	  <xsl:value-of select="$to_angle" />
	</xsl:when>
	<xsl:otherwise>
	  <xsl:value-of select="$from_angle" />
	</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="max_angle">
      <xsl:choose>
	<xsl:when test="$from_angle &gt; $to_angle">
	  <xsl:value-of select="$from_angle" />
	</xsl:when>
	<xsl:otherwise>
	  <xsl:value-of select="$to_angle" />
	</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:value-of select="$min_angle + ($max_angle - $min_angle) div 2" />
  </xsl:template>

  <!-- atan2 implementation from http://lists.fourthought.com/pipermail/exslt/2007-March/001540.html -->
  <xsl:template name="atan2">
    <xsl:param name="y"/>
    <xsl:param name="x"/>
    <!-- http://lists.apple.com/archives/PerfOptimization-dev/2005/Jan/msg00051.html -->
    <xsl:variable name="PI"    select="number(3.1415926535897)"/>
    <xsl:variable name="PIBY2" select="$PI div 2.0"/>
    <xsl:choose>
      <xsl:when test="$x = 0.0">
        <xsl:choose>
          <xsl:when test="($y &gt; 0.0)">
            <xsl:value-of select="$PIBY2"/>
          </xsl:when>
          <xsl:when test="($y &lt; 0.0)">
            <xsl:value-of select="-$PIBY2"/>
          </xsl:when>
          <xsl:otherwise>
            <!-- Error: Degenerate x == y == 0.0 -->
            <xsl:value-of select="number(NaN)"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="z" select="$y div $x"/>
        <xsl:variable name="absZ">
          <!-- inline abs function -->
          <xsl:choose>
            <xsl:when test="$z &lt; 0.0">
              <xsl:value-of select="- number($z)"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="number($z)"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>
        <xsl:choose>
          <xsl:when test="($absZ &lt; 1.0)">
            <xsl:variable name="f1Z" select="$z div (1.0 + 0.28*$z*$z)"/>
            <xsl:choose>
              <xsl:when test="($x &lt; 0.0) and ($y &lt; 0.0)">
                <xsl:value-of select="$f1Z - $PI"/>
              </xsl:when>
              <xsl:when test="($x &lt; 0.0)">
                <xsl:value-of select="$f1Z + $PI"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="$f1Z"/>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:when>
          <xsl:otherwise>
            <xsl:variable name="f2Z" select="$PIBY2 - ($z div ($z*$z +
0.28))"/>
            <xsl:choose>
              <xsl:when test="($y &lt; 0.0)">
                <xsl:value-of select="$f2Z - $PI"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="$f2Z"/>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Find a point on the line going through $point at $angle that's guaranteed to be outside the polygon -->
  <xsl:template name="areacenterLinepoint">
    <xsl:param name="point" />
    <xsl:param name="angle" />

    <xsl:variable name="cos_angle">
      <xsl:call-template name="cos">
	<xsl:with-param name="angle" select="$angle"/>
      </xsl:call-template>
    </xsl:variable>
    
    <xsl:variable name="sin_angle">
      <xsl:call-template name="sin">
	<xsl:with-param name="angle" select="$angle"/>
      </xsl:call-template>
    </xsl:variable>
    
    <xsl:value-of select="$point/@lon + $cos_angle"/>, <xsl:value-of select="$point/@lat + $sin_angle"/>
  </xsl:template>
  
  <!-- Constants for trig templates -->
  <xsl:variable name="pi" select="3.1415926535897"/>
  <xsl:variable name="halfPi" select="$pi div 2"/>
  <xsl:variable name="twicePi" select="$pi*2"/>

  <xsl:template name="sin">
    <xsl:param name="angle" />
    <xsl:param name="precision" select="0.00000001"/>

    <xsl:variable name="y">
      <xsl:choose>
        <xsl:when test="not(0 &lt;= $angle and $twicePi > $angle)">
          <xsl:call-template name="cutIntervals">
            <xsl:with-param name="length" select="$twicePi"/>
            <xsl:with-param name="angle" select="$angle"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$angle"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:call-template name="sineIter">
      <xsl:with-param name="angle2" select="$y*$y"/>
      <xsl:with-param name="res" select="$y"/>
      <xsl:with-param name="elem" select="$y"/>
      <xsl:with-param name="n" select="1"/>
      <xsl:with-param name="precision" select="$precision" />
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="sineIter">
    <xsl:param name="angle2" />
    <xsl:param name="res" />
    <xsl:param name="elem" />
    <xsl:param name="n" />
    <xsl:param name="precision"/>

    <xsl:variable name="nextN" select="$n+2" />
    <xsl:variable name="newElem" select="-$elem*$angle2 div ($nextN*($nextN - 1))" />
    <xsl:variable name="newResult" select="$res + $newElem" />
    <xsl:variable name="diffResult" select="$newResult - $res" />

    <xsl:choose>
      <xsl:when test="$diffResult > $precision or $diffResult &lt; -$precision">
        <xsl:call-template name="sineIter">
          <xsl:with-param name="angle2" select="$angle2" />
          <xsl:with-param name="res" select="$newResult" />
          <xsl:with-param name="elem" select="$newElem" />
          <xsl:with-param name="n" select="$nextN" />
          <xsl:with-param name="precision" select="$precision" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$newResult"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="cutIntervals">
    <xsl:param name="length"/>
    <xsl:param name="angle"/>

    <xsl:variable name="vsign">
      <xsl:choose>
        <xsl:when test="$angle >= 0">1</xsl:when>
        <xsl:otherwise>-1</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="vdiff" select="$length*floor($angle div $length) -$angle"/> 
    <xsl:choose>
      <xsl:when test="$vdiff*$angle > 0">
        <xsl:value-of select="$vsign*$vdiff"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="-$vsign*$vdiff"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="cos">
    <xsl:param name="angle" />
    <xsl:param name="precision" select="0.00000001"/>

    <xsl:call-template name="sin">
      <xsl:with-param name="angle" select="$halfPi - $angle" />
      <xsl:with-param name="precision" select="$precision" />
    </xsl:call-template>
  </xsl:template>

  <!-- Find the nearest intersection into the polygon along the line ($x,$y)-$linepoint.
       Can also be used for ray-casting point-in-polygon checking -->
  <xsl:template name="areacenterNearestIntersectionInside">
    <xsl:param name="x" />
    <xsl:param name="y" />
    <xsl:param name="edgestart" />
    <xsl:param name="linepoint_x" />
    <xsl:param name="linepoint_y" />
    <xsl:param name="holerelation" />
    <xsl:param name="intersectioncount_on" select="0" /><!-- Number of intersections. Only counts those on segment (x,y)-linepoint -->
    <xsl:param name="nearest_on_x" />
    <xsl:param name="nearest_on_y" />
    <xsl:param name="nearest_on_dist" select="'NaN'" />
    <xsl:param name="nearest_off_x" />
    <xsl:param name="nearest_off_y" />
    <xsl:param name="nearest_off_dist" select="'NaN'" />

    <xsl:choose>
      <!-- If there are no more vertices we don't have a second point for the edge, and are finished -->
      <xsl:when test="$edgestart/following-sibling::nd[1]">
	<xsl:variable name="edgeend" select="$edgestart/following-sibling::nd[1]" />
	<!-- Get the intersection point between the line ($x,$y)-$linepoint and $edgestart-$edgeend -->
	<xsl:variable name="intersection">
	  <xsl:choose>
	    <xsl:when test="( $x = key('nodeById', $edgestart/@ref)/@lon and $y = key('nodeById', $edgestart/@ref)/@lat ) or
			    ( $x = key('nodeById', $edgeend/@ref)/@lon and $y = key('nodeById', $edgeend/@ref)/@lat )">
	      <!-- (x,y) is one of the points in edge, skip -->
	      NoIntersection
	    </xsl:when>
	    <xsl:otherwise>      
	      <xsl:call-template name="areacenterLinesIntersection">
		<xsl:with-param name="x1" select="$x" />
		<xsl:with-param name="y1" select="$y" />
		<xsl:with-param name="x2" select="$linepoint_x" />
		<xsl:with-param name="y2" select="$linepoint_y" />
		<xsl:with-param name="x3" select="key('nodeById', $edgestart/@ref)/@lon" />
		<xsl:with-param name="y3" select="key('nodeById', $edgestart/@ref)/@lat" />
		<xsl:with-param name="x4" select="key('nodeById', $edgeend/@ref)/@lon" />
		<xsl:with-param name="y4" select="key('nodeById', $edgeend/@ref)/@lat" />
	      </xsl:call-template>
	    </xsl:otherwise>
	  </xsl:choose>
	</xsl:variable>

	<!-- Haul ix, iy, ua and ub out of the csv -->
	<xsl:variable name="ix" select="substring-before($intersection, ',')" />
	<xsl:variable name="iy" select="substring-before(substring-after($intersection, ','), ',')" />
	<xsl:variable name="ua" select="substring-before(substring-after(substring-after($intersection, ','), ','), ',')" />
	<xsl:variable name="ub" select="substring-after(substring-after(substring-after($intersection, ','), ','), ',')" />

	<!-- A) Is there actually an intersection? B) Is it on edge? -->
	<xsl:choose>
	  <xsl:when test="$intersection != 'NoIntersection' and $ub &gt; 0 and $ub &lt;= 1">
	    <xsl:variable name="distance">
	      <xsl:call-template name="areacenterPointDistance">
		<xsl:with-param name="x1" select="$x" />
		<xsl:with-param name="y1" select="$y" />
		<xsl:with-param name="x2" select="$ix" />
		<xsl:with-param name="y2" select="$iy" />
	      </xsl:call-template>
	    </xsl:variable>

	    <!-- Is intersection on the segment ($x,$y)-$linepoint, or on the other side of ($x,$y)? -->
	    <xsl:variable name="isOnSegment">
	      <xsl:if test="$ua &gt;= 0">Yes</xsl:if>
	    </xsl:variable>
	    
	    <xsl:variable name="isNewNearestOn">
	      <xsl:if test="$isOnSegment = 'Yes' and ( $nearest_on_dist = 'NaN' or $distance &lt; $nearest_on_dist )">Yes</xsl:if>
	    </xsl:variable>
	    
	    <xsl:variable name="isNewNearestOff">
	      <xsl:if test="$isOnSegment != 'Yes' and ( $nearest_off_dist = 'NaN' or $distance &lt; $nearest_off_dist )">Yes</xsl:if>
	    </xsl:variable>

	    <xsl:call-template name="areacenterNearestIntersectionInside">
	      <xsl:with-param name="x" select="$x" />
	      <xsl:with-param name="y" select="$y" />
	      <xsl:with-param name="linepoint_x" select="$linepoint_x" />
	      <xsl:with-param name="linepoint_y" select="$linepoint_y" />
	      <xsl:with-param name="edgestart" select="$edgeend" />
	      <xsl:with-param name="holerelation" select="$holerelation" />
	      <xsl:with-param name="intersectioncount_on" select="$intersectioncount_on + number(boolean($isOnSegment = 'Yes'))" />
	      <xsl:with-param name="nearest_on_dist"> <xsl:choose>
		<xsl:when test="$isNewNearestOn = 'Yes'"> <xsl:value-of select="$distance" /> </xsl:when>
		<xsl:otherwise> <xsl:value-of select="$nearest_on_dist" /> </xsl:otherwise>
	      </xsl:choose> </xsl:with-param>
	      <xsl:with-param name="nearest_on_x"> <xsl:choose>
		<xsl:when test="$isNewNearestOn = 'Yes'"> <xsl:value-of select="$ix" /> </xsl:when>
		<xsl:otherwise> <xsl:value-of select="$nearest_on_x" /> </xsl:otherwise>
	      </xsl:choose> </xsl:with-param>
	      <xsl:with-param name="nearest_on_y"> <xsl:choose>
		<xsl:when test="$isNewNearestOn = 'Yes'"> <xsl:value-of select="$iy" /> </xsl:when>
		<xsl:otherwise> <xsl:value-of select="$nearest_on_y" /> </xsl:otherwise>
	      </xsl:choose> </xsl:with-param>
	      <xsl:with-param name="nearest_off_dist"> <xsl:choose>
		<xsl:when test="$isNewNearestOff = 'Yes'"> <xsl:value-of select="$distance" /> </xsl:when>
		<xsl:otherwise> <xsl:value-of select="$nearest_off_dist" /> </xsl:otherwise>
	      </xsl:choose> </xsl:with-param>
	      <xsl:with-param name="nearest_off_x"> <xsl:choose>
		<xsl:when test="$isNewNearestOff = 'Yes'"> <xsl:value-of select="$ix" /> </xsl:when>
		<xsl:otherwise> <xsl:value-of select="$nearest_off_x" /> </xsl:otherwise>
	      </xsl:choose> </xsl:with-param>
	      <xsl:with-param name="nearest_off_y"> <xsl:choose>
		<xsl:when test="$isNewNearestOff = 'Yes'"> <xsl:value-of select="$iy" /> </xsl:when>
		<xsl:otherwise> <xsl:value-of select="$nearest_off_y" /> </xsl:otherwise>
	      </xsl:choose> </xsl:with-param>
	    </xsl:call-template>
	  </xsl:when>
	  <!-- No intersection, just go on to next edge -->
	  <xsl:otherwise>
	    <xsl:call-template name="areacenterNearestIntersectionInside">
	      <xsl:with-param name="x" select="$x" />
	      <xsl:with-param name="y" select="$y" />
	      <xsl:with-param name="linepoint_x" select="$linepoint_x" />
	      <xsl:with-param name="linepoint_y" select="$linepoint_y" />
	      <xsl:with-param name="edgestart" select="$edgeend" />
	      <xsl:with-param name="holerelation" select="$holerelation" />
	      <xsl:with-param name="intersectioncount_on" select="$intersectioncount_on" />
	      <xsl:with-param name="nearest_on_dist" select="$nearest_on_dist" />
	      <xsl:with-param name="nearest_on_x" select="$nearest_on_x" />
	      <xsl:with-param name="nearest_on_y" select="$nearest_on_y" />
	      <xsl:with-param name="nearest_off_dist" select="$nearest_off_dist" />
	      <xsl:with-param name="nearest_off_x" select="$nearest_off_x" />
	      <xsl:with-param name="nearest_off_y" select="$nearest_off_y" />
	    </xsl:call-template>
	  </xsl:otherwise>
	</xsl:choose>
      </xsl:when>
      <!-- Is there a hole in the polygon, and were we working on the outer one? Then we start edge detection against the hole. -->
      <xsl:when test="$holerelation and
		      $holerelation/member[@ref = $edgestart/../@id][@role='outer']">
	<xsl:variable name="nextnode" select="key('wayById', $holerelation/member[@type='way'][@role='inner'][1]/@ref)/nd[1]"/>
	<xsl:call-template name="areacenterNearestIntersectionInside">
	  <xsl:with-param name="x" select="$x" />
	  <xsl:with-param name="y" select="$y" />
	  <xsl:with-param name="linepoint_x" select="$linepoint_x" />
	  <xsl:with-param name="linepoint_y" select="$linepoint_y" />
	  <xsl:with-param name="edgestart" select="$nextnode" />
	  <xsl:with-param name="holerelation" select="$holerelation" />
	  <xsl:with-param name="intersectioncount_on" select="$intersectioncount_on" />
	  <xsl:with-param name="nearest_on_dist" select="$nearest_on_dist" />
	  <xsl:with-param name="nearest_on_x" select="$nearest_on_x" />
	  <xsl:with-param name="nearest_on_y" select="$nearest_on_y" />
	  <xsl:with-param name="nearest_off_dist" select="$nearest_off_dist" />
	  <xsl:with-param name="nearest_off_x" select="$nearest_off_x" />
	  <xsl:with-param name="nearest_off_y" select="$nearest_off_y" />
	</xsl:call-template>
      </xsl:when>
      <!-- Is there a hole in the polygon, and were we working working on one of the inner ones? Then go to the next hole, if there is one -->
      <xsl:when test="$holerelation and
		      $holerelation/member[@ref = $edgestart/../@id][@type='way'][@role='inner']/following-sibling::member[@role='inner']">
	<xsl:variable name="nextnode" select="key('wayById', $holerelation/member[@ref = $edgestart/../@id][@type='way'][@role='inner']/following-sibling::member[@role='inner']/@ref)/nd[1]"/>
	<xsl:call-template name="areacenterNearestIntersectionInside">
	  <xsl:with-param name="x" select="$x" />
	  <xsl:with-param name="y" select="$y" />
	  <xsl:with-param name="linepoint_x" select="$linepoint_x" />
	  <xsl:with-param name="linepoint_y" select="$linepoint_y" />
	  <xsl:with-param name="edgestart" select="$nextnode" />
	  <xsl:with-param name="holerelation" select="$holerelation" />
	  <xsl:with-param name="intersectioncount_on" select="$intersectioncount_on" />
	  <xsl:with-param name="nearest_on_dist" select="$nearest_on_dist" />
	  <xsl:with-param name="nearest_on_x" select="$nearest_on_x" />
	  <xsl:with-param name="nearest_on_y" select="$nearest_on_y" />
	  <xsl:with-param name="nearest_off_dist" select="$nearest_off_dist" />
	  <xsl:with-param name="nearest_off_x" select="$nearest_off_x" />
	  <xsl:with-param name="nearest_off_y" select="$nearest_off_y" />
	</xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
	<!-- No more edges, return data -->
	<xsl:value-of select="$intersectioncount_on" />;
	<xsl:value-of select="$nearest_on_x"/>,<xsl:value-of select="$nearest_on_y"/>,<xsl:value-of select="$nearest_on_dist"/>;
	<xsl:value-of select="$nearest_off_x"/>,<xsl:value-of select="$nearest_off_y"/>,<xsl:value-of select="$nearest_off_dist"/>;
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Find the distance to the edge nearest (x,y) -->
  <xsl:template name="areacenterNearestEdge">
    <xsl:param name="x" />
    <xsl:param name="y" />
    <xsl:param name="edgestart" />
    <xsl:param name="holerelation" />
    <xsl:param name="nearest_dist" select="'NaN'" />

    <xsl:choose>
      <!-- If there are no more vertices we don't have a second point for the edge, and are finished -->
      <xsl:when test="$edgestart/following-sibling::nd[1]">
	<xsl:variable name="edgeend" select="$edgestart/following-sibling::nd[1]" />

	<xsl:variable name="distance">
	  <xsl:call-template name="areacenterDistancePointSegment">
	    <xsl:with-param name="x" select="$x" />
	    <xsl:with-param name="y" select="$y" />
	    <xsl:with-param name="x1" select="key('nodeById', $edgestart/@ref)/@lon" />
	    <xsl:with-param name="y1" select="key('nodeById', $edgestart/@ref)/@lat" />
	    <xsl:with-param name="x2" select="key('nodeById', $edgeend/@ref)/@lon" />
	    <xsl:with-param name="y2" select="key('nodeById', $edgeend/@ref)/@lat" />
	  </xsl:call-template>
	</xsl:variable>

	<!-- Did we get a valid distance?
	     There is some code in DistancePointSegment that can return NaN in some cases -->
	<xsl:choose>
	  <xsl:when test="string(number($distance)) != 'NaN'">
	    <xsl:call-template name="areacenterNearestEdge">
	      <xsl:with-param name="x" select="$x" />
	      <xsl:with-param name="y" select="$y" />
	      <xsl:with-param name="edgestart" select="$edgeend" />
	      <xsl:with-param name="holerelation" select="$holerelation" />
	      <xsl:with-param name="nearest_dist"> <xsl:choose>
		<xsl:when test="$nearest_dist = 'NaN' or $distance &lt; $nearest_dist"> <xsl:value-of select="$distance" /> </xsl:when>
		<xsl:otherwise> <xsl:value-of select="$nearest_dist" /> </xsl:otherwise>
	      </xsl:choose> </xsl:with-param>
	    </xsl:call-template>
	  </xsl:when>

	  <xsl:otherwise>
	    <xsl:call-template name="areacenterNearestEdge">
	      <xsl:with-param name="x" select="$x" />
	      <xsl:with-param name="y" select="$y" />
	      <xsl:with-param name="edgestart" select="$edgeend" />
	      <xsl:with-param name="holerelation" select="$holerelation" />
	      <xsl:with-param name="nearest_dist" select="$nearest_dist" />
	    </xsl:call-template>
	  </xsl:otherwise>
	</xsl:choose>
      </xsl:when>
      <!-- Is there a hole in the polygon, and were we working on the outer one? Then we start edge detection against the hole. -->
      <xsl:when test="$holerelation and
		      $holerelation/member[@ref = $edgestart/../@id][@role='outer']">
	<xsl:variable name="nextnode" select="key('wayById', $holerelation/member[@type='way'][@role='inner'][1]/@ref)/nd[1]"/>
	<xsl:call-template name="areacenterNearestEdge">
	  <xsl:with-param name="x" select="$x" />
	  <xsl:with-param name="y" select="$y" />
	  <xsl:with-param name="edgestart" select="$nextnode" />
	  <xsl:with-param name="holerelation" select="$holerelation" />
	  <xsl:with-param name="nearest_dist" select="$nearest_dist" />
	</xsl:call-template>
      </xsl:when>
      <!-- Is there a hole in the polygon, and were we working working on one of the inner ones? Then go to the next hole, if there is one -->
      <xsl:when test="$holerelation and
		      $holerelation/member[@ref = $edgestart/../@id][@type='way'][@role='inner']/following-sibling::member[@role='inner']">
	<xsl:variable name="nextnode" select="key('wayById', $holerelation/member[@ref = $edgestart/../@id][@type='way'][@role='inner']/following-sibling::member[@role='inner']/@ref)/nd[1]"/>
	<xsl:call-template name="areacenterNearestEdge">
	  <xsl:with-param name="x" select="$x" />
	  <xsl:with-param name="y" select="$y" />
	  <xsl:with-param name="edgestart" select="$nextnode" />
	  <xsl:with-param name="holerelation" select="$holerelation" />
	  <xsl:with-param name="nearest_dist" select="$nearest_dist" />
	</xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
	<!-- No more edges, return data -->
	<xsl:value-of select="$nearest_dist" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Find the distance between the point (x,y) and the segment x1,y1 -> x2,y2 -->
  <!-- Based on http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ and the
       Delphi example by Graham O'Brien -->
  <xsl:template name="areacenterDistancePointSegment">
    <xsl:param name="x" />
    <xsl:param name="y" />
    <xsl:param name="x1" />
    <xsl:param name="y1" />
    <xsl:param name="x2" />
    <xsl:param name="y2" />

    <!-- Constants -->
    <xsl:variable name="EPS" select="0.000001" />
    <xsl:variable name="EPSEPS" select="$EPS * $EPS" />

    <!-- The line magnitude, squared -->
    <xsl:variable name="sqLineMagnitude" select="($x2 - $x1) * ($x2 - $x1) + ($y2 - $y1) * ($y2 - $y1)" />

    <xsl:choose>
      <xsl:when test="sqLineMagnitude &lt; $EPSEPS">
	NaN
      </xsl:when>
      <xsl:otherwise>
	<xsl:variable name="u" select="( ($x - $x1)*($x2 - $x1) + ($y - $y1)*($y2 - $y1) ) div sqLineMagnitude" />

	<xsl:variable name="result">
	  <xsl:choose>
	    <xsl:when test="u &lt; $EPS or u &gt; 1">
	      <!-- Closest point in not on segment, return shortest distance to an endpoint -->
	      <xsl:variable name="dist1" select="($x1 - $x) * ($x1 - $x) + ($y1 - $y) * ($y1 - $y)" />
	      <xsl:variable name="dist2" select="($x2 - $x) * ($x2 - $x) + ($y2 - $y) * ($y2 - $y)" />
	      
	      <!-- min($dist1, $dist2) -->
	      <xsl:choose>
		<xsl:when test="$dist1 &lt; $dist2">
		  <xsl:value-of select="$dist1" />
		</xsl:when>
		<xsl:otherwise>
		  <xsl:value-of select="$dist2" />
		</xsl:otherwise>
	      </xsl:choose>
	      
	    </xsl:when>
	    <xsl:otherwise>
	      <xsl:variable name="ix" select="$x1 + $u * ($x2 - $x1)" />
	      <xsl:variable name="iy" select="$y1 + $u * ($y2 - $y1)" />
	      <xsl:value-of select="($ix - $x) * ($ix - $x) + ($iy - $y) * ($iy - $y)" />
	    </xsl:otherwise>
	  </xsl:choose>
	</xsl:variable>

	<!-- Finally return the square root of the result, as we were working with squared distances -->
	<xsl:call-template name="sqrt">
	  <xsl:with-param name="num" select="$result" />
	</xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>

  </xsl:template>

  <!--
      Finds intersection point between lines x1,y1 -> x2,y2 and x3,y3 -> x4,y4.
      Returns a comma-separated list of x,y,ua,ub or NoIntersection if the lines do not intersect
  -->
  <xsl:template name="areacenterLinesIntersection">
    <xsl:param name="x1" />
    <xsl:param name="y1" />
    <xsl:param name="x2" />
    <xsl:param name="y2" />
    <xsl:param name="x3" />
    <xsl:param name="y3" />
    <xsl:param name="x4" />
    <xsl:param name="y4" />

    <xsl:variable name="denom" select="(( $y4 - $y3 ) * ( $x2 - $x1 )) -
				       (( $x4 - $x3 ) * ( $y2 - $y1 ))" />
    <xsl:variable name="nume_a" select="(( $x4 - $x3 ) * ( $y1 - $y3 )) -
					(( $y4 - $y3 ) * ( $x1 - $x3 ))" />
    <xsl:variable name="nume_b" select="(( $x2 - $x1 ) * ( $y1 - $y3 )) -
					(( $y2 - $y1 ) * ( $x1 - $x3 ))" />

    <xsl:choose>
      <xsl:when test="$denom = 0">
	NoIntersection
      </xsl:when>
      <xsl:otherwise>
	<xsl:variable name="ua" select="$nume_a div $denom" />
	<xsl:variable name="ub" select="$nume_b div $denom" />

	<!-- x,y,ua,ub -->
	<xsl:value-of select="$x1 + $ua * ($x2 - $x1)" />,<xsl:value-of select="$y1 + $ua * ($y2 - $y1)" />,<xsl:value-of select="$ua" />,<xsl:value-of select="$ub" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Distance between two points -->
  <xsl:template name="areacenterPointDistance">
    <xsl:param name="x1" />
    <xsl:param name="y1" />
    <xsl:param name="x2" />
    <xsl:param name="y2" />

    <!-- sqrt( ($x2 - $x1)**2 + ($y2 - $y1)**2 ) -->
    <xsl:call-template name="sqrt">
      <xsl:with-param name="num" select="($x2*$x2 - $x2*$x1 - $x1*$x2 + $x1*$x1) + ($y2*$y2 - $y2*$y1 - $y1*$y2 + $y1*$y1)" />
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="sqrt">
    <xsl:param name="num" select="0"/>  <!-- The number you want to find the
					     square root of -->
    <xsl:param name="try" select="1"/>  <!-- The current 'try'.  This is used
					     internally. -->
    <xsl:param name="iter" select="1"/> <!-- The current iteration, checked
					     against maxiter to limit loop count -->
    <xsl:param name="maxiter" select="10"/>  <!-- Set this up to insure
against infinite loops -->
    
    <!-- This template was written by Nate Austin using Sir Isaac Newton's
	 method of finding roots -->
    
    <xsl:choose>
      <xsl:when test="$try * $try = $num or $iter &gt; $maxiter">
	<xsl:value-of select="$try"/>
      </xsl:when>
      <xsl:otherwise>
	<xsl:call-template name="sqrt">
          <xsl:with-param name="num" select="$num"/>
          <xsl:with-param name="try" select="$try - (($try * $try - $num) div
					     (2 * $try))"/>
          <xsl:with-param name="iter" select="$iter + 1"/>
          <xsl:with-param name="maxiter" select="$maxiter"/>
	</xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Returns the medium value of all the points -->
  <xsl:template name="areacenterMediumOfPoints">
    <xsl:param name="points" />
    <xsl:param name="total_x" select="0" />
    <xsl:param name="total_y" select="0" />
    <xsl:param name="total_dist" select="0" />
    <xsl:param name="count" select="0" />

    <xsl:variable name="point" select="substring-before($points, ';')" />

    <xsl:choose>
      <xsl:when test="string-length($point) &gt; 0">
	<xsl:variable name="x" select="substring-before($point, ',')" />
	<xsl:variable name="y" select="substring-before(substring-after($point, ','), ',')" />
	<xsl:variable name="dist" select="substring-after(substring-after($point, ','), ',')" />

	<xsl:call-template name="areacenterMediumOfPoints">
	  <xsl:with-param name="points" select="substring-after($points, ';')" />
	  <xsl:with-param name="total_x" select="$total_x + $x" />
	  <xsl:with-param name="total_y" select="$total_y + $y" />
	  <xsl:with-param name="total_dist" select="$total_dist + $dist" />
	  <xsl:with-param name="count" select="$count + 1" />
	</xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
	<xsl:value-of select="$total_x div $count" />,<xsl:value-of select="$total_y div $count" />,<xsl:value-of select="$total_dist div $count" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Returns the coordinates of the point that scores highest.
       The score is based on the distance to (x,y),
       the distance between the point and it's vertex,
       and the medium of that distance in all the points -->
  <xsl:template name="areacenterBestPoint">
    <xsl:param name="points" />
    <xsl:param name="x" />
    <xsl:param name="y" />
    <xsl:param name="nearest_x" />
    <xsl:param name="nearest_y" />
    <xsl:param name="medium_dist" />
    <xsl:param name="nearest_score" />
    <xsl:param name="nearest_dist" select="'NaN'" />

    <xsl:variable name="point" select="substring-before($points, ';')" />

    <xsl:choose>
      <xsl:when test="string-length($point) &gt; 0"> 
        <xsl:variable name="point_x" select="substring-before($point, ',')" />
	<xsl:variable name="point_y" select="substring-before(substring-after($point, ','), ',')" />
	<xsl:variable name="point_dist" select="substring-after(substring-after($point, ','), ',')" />
	
	<xsl:variable name="distance">
	  <xsl:call-template name="areacenterPointDistance">
	    <xsl:with-param name="x1" select="$x" />
	    <xsl:with-param name="y1" select="$y" />
	    <xsl:with-param name="x2" select="$point_x" />
	    <xsl:with-param name="y2" select="$point_y" />
	  </xsl:call-template>
	</xsl:variable>

	<xsl:variable name="score" select="0 - $distance + $point_dist + $point_dist - $medium_dist"/>
	<xsl:variable name="isNewNearest" select="$nearest_dist = 'NaN' or $score &gt; $nearest_score" />

	<xsl:call-template name="areacenterBestPoint">
	  <xsl:with-param name="points" select="substring-after($points, ';')" />
	  <xsl:with-param name="x" select="$x" />
	  <xsl:with-param name="y" select="$y" />
	  <xsl:with-param name="medium_dist" select="$medium_dist" />
	  <xsl:with-param name="nearest_dist"><xsl:choose>
	    <xsl:when test="$isNewNearest"><xsl:value-of select="$distance" /></xsl:when>
	    <xsl:otherwise><xsl:value-of select="$nearest_dist" /></xsl:otherwise>
	  </xsl:choose></xsl:with-param>
	  <xsl:with-param name="nearest_x"><xsl:choose>
	    <xsl:when test="$isNewNearest"><xsl:value-of select="$point_x" /></xsl:when>
	    <xsl:otherwise><xsl:value-of select="$nearest_x" /></xsl:otherwise>
	  </xsl:choose></xsl:with-param>
	  <xsl:with-param name="nearest_y"><xsl:choose>
	    <xsl:when test="$isNewNearest"><xsl:value-of select="$point_y" /></xsl:when>
	    <xsl:otherwise><xsl:value-of select="$nearest_y" /></xsl:otherwise>
	  </xsl:choose></xsl:with-param>
	  <xsl:with-param name="nearest_score"><xsl:choose>
	    <xsl:when test="$isNewNearest"><xsl:value-of select="$score" /></xsl:when>
	    <xsl:otherwise><xsl:value-of select="$nearest_score" /></xsl:otherwise>
	  </xsl:choose></xsl:with-param>
	</xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
	<xsl:value-of select="$nearest_x" />, <xsl:value-of select="$nearest_y" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Process a <text> instruction -->
  <xsl:template match="text">
    <xsl:param name="elements"/>

    <!-- This is the instruction that is currently being processed -->
    <xsl:variable name="instruction" select="."/>

    <!-- Select all <node> elements that have a key that matches the k attribute of the text instruction -->
    <xsl:for-each select="$elements[name()='node'][tag[@k=$instruction/@k]]">
      <xsl:call-template name="renderText">
        <xsl:with-param name="instruction" select="$instruction"/>
      </xsl:call-template>
    </xsl:for-each>

    <!-- Select all <way> elements -->
    <xsl:apply-templates select="$elements[name()='way']" mode="textPath">
      <xsl:with-param name="instruction" select="$instruction"/>
    </xsl:apply-templates>
  </xsl:template>


  <!-- Suppress output of any unhandled elements -->
  <xsl:template match="*" mode="textPath"/>


  <!-- Render textPaths for a way -->
  <xsl:template match="way" mode="textPath">
    <xsl:param name="instruction"/>

    <!-- The current <way> element -->
    <xsl:variable name="way" select="."/>

    <!-- DODI: !!!WORKAROUND!!! no text for one node ways-->
    <xsl:if test="count($way/nd) &gt; 1">
      <xsl:variable name='text'>
        <xsl:choose>
          <xsl:when test='$instruction/@k'>
            <xsl:value-of select='tag[@k=$instruction/@k]/@v'/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:apply-templates select='$instruction' mode='textFormat'>
              <xsl:with-param name='way' select='$way'/>
            </xsl:apply-templates>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>

      <xsl:if test='string($text)'>

        <xsl:variable name="pathDirection">
          <xsl:choose>
            <!-- Manual override, reverse direction -->
            <xsl:when test="tag[@k='name_direction']/@v='-1' or tag[@k='osmarender:nameDirection']/@v='-1'">reverse</xsl:when>
            <!-- Manual override, normal direction -->
            <xsl:when test="tag[@k='name_direction']/@v='1' or tag[@k='osmarender:nameDirection']/@v='1'">normal</xsl:when>
            <!-- Automatic, reverse direction -->
            <xsl:when test="(key('nodeById',$way/nd[1]/@ref)/@lon &gt; key('nodeById',$way/nd[last()]/@ref)/@lon)">reverse</xsl:when>
            <!-- Automatic, normal direction -->
            <xsl:otherwise>normal</xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <xsl:variable name="wayPath">
          <xsl:choose>
            <!-- Normal -->
            <xsl:when test='$pathDirection="normal"'>
              <xsl:value-of select="concat('way_normal_',@id)"/>
            </xsl:when>
            <!-- Reverse -->
            <xsl:otherwise>
              <xsl:value-of select="concat('way_reverse_',@id)"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <xsl:call-template name="renderTextPath">
          <xsl:with-param name="instruction" select="$instruction"/>
          <xsl:with-param name="pathId" select="$wayPath"/>
          <xsl:with-param name="pathDirection" select="$pathDirection"/>
          <xsl:with-param name="text" select="$text"/>
        </xsl:call-template>
      </xsl:if>
    </xsl:if>
  </xsl:template>

  <!-- Process extended form of text instruction -->
  <xsl:template match='text' mode='textFormat'>
    <xsl:param name='way'/>

    <xsl:apply-templates mode='textFormat'>
      <xsl:with-param name='way' select='$way'/>
    </xsl:apply-templates>
  </xsl:template>


  <!-- Substitute a tag in a text instruction -->
  <xsl:template match='text/tag' mode='textFormat'>
    <xsl:param name='way'/>

    <xsl:variable name='key' select='@k'/>
    <xsl:variable name='value'>
      <xsl:choose>
        <xsl:when test='$key="osm:user"'>
          <xsl:value-of select='$way/@user'/>
        </xsl:when>
        <xsl:when test='$key="osm:timestamp"'>
          <xsl:value-of select='$way/@timestamp'/>
        </xsl:when>
        <xsl:when test='$key="osm:id"'>
          <xsl:value-of select='$way/@id'/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select='$way/tag[@k=$key]/@v'/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test='string($value)'>
        <xsl:value-of select='$value'/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select='@default'/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>



  <!-- Generate a way path for the current way element -->
  <xsl:template name="generateWayPaths">
    <!-- DODI: !!!WORKAROUND!!! skip one node ways -->
    <xsl:if test="count(nd) &gt; 1">

      <!-- Generate a normal way path -->
      <xsl:variable name="pathWayNormal">
        <xsl:call-template name="generateWayPathNormal"/>
      </xsl:variable>
      <xsl:if test="$pathWayNormal!=''">
        <path id="way_normal_{@id}" d="{$pathWayNormal}"/>
      </xsl:if>

      <!-- Generate a normal way path as area -->
      <!-- DODI: !!!WORKAROUND!!! added to generate "area for all ways, yes it is very dirty... but -->
      <!-- DODI: removed because of line2curves.pl duplicate node detection problem -->
      <!-- <xsl:variable name="pathArea">
      <xsl:call-template name="generateAreaPath"/>
    </xsl:variable>
    <path id="area_{@id}" d="{$pathArea}"/> -->
      <!-- Generate a reverse way path (if needed) -->
      <xsl:variable name="pathWayReverse">
        <xsl:choose>
          <!-- Manual override, reverse direction -->
          <xsl:when test="tag[@k='name_direction']/@v='-1' or tag[@k='osmarender:nameDirection']/@v='-1'">
            <xsl:call-template name="generateWayPathReverse"/>
          </xsl:when>
          <!-- Manual override, normal direction -->
          <xsl:when test="tag[@k='name_direction']/@v='1' or tag[@k='osmarender:nameDirection']/@v='1'">
            <!-- Generate nothing -->
          </xsl:when>
          <!-- Automatic, reverse direction -->
          <xsl:when test="(key('nodeById',nd[1]/@ref)/@lon &gt; key('nodeById',nd[last()]/@ref)/@lon)">
            <xsl:call-template name="generateWayPathReverse"/>
          </xsl:when>
        </xsl:choose>
      </xsl:variable>
      <xsl:if test="$pathWayReverse!=''">
        <path id="way_reverse_{@id}" d="{$pathWayReverse}"/>
      </xsl:if>

      <!-- Generate the start, middle and end paths needed for smart-linecaps (TM). -->
      <xsl:variable name="pathWayStart">
        <xsl:call-template name="generatePathWayStart"/>
      </xsl:variable>
      <path id="way_start_{@id}" d="{$pathWayStart}"/>

      <xsl:if test="count(nd) &gt; 1">
        <xsl:variable name="pathWayMid">
          <xsl:call-template name="generatePathWayMid"/>
        </xsl:variable>
        <path id="way_mid_{@id}" d="{$pathWayMid}"/>
      </xsl:if>

      <xsl:variable name="pathWayEnd">
        <xsl:call-template name="generatePathWayEnd"/>
      </xsl:variable>
      <path id="way_end_{@id}" d="{$pathWayEnd}"/>
    </xsl:if >
  </xsl:template>


  <!-- Generate a normal way path -->
  <xsl:template name="generateWayPathNormal">
    <xsl:for-each select="nd[key('nodeById',@ref) ]">
      <xsl:choose>
        <xsl:when test="position()=1">
          <xsl:call-template name="moveToNode">
            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="lineToNode">
            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>


  <!-- Generate a reverse way path -->
  <xsl:template name="generateWayPathReverse">
    <xsl:for-each select="nd[key('nodeById',@ref)]">
      <xsl:sort select="position()" data-type="number" order="descending"/>
      <xsl:choose>
        <xsl:when test="position()=1">
          <xsl:call-template name="moveToNode">
            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="lineToNode">
            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>


  <!-- These template generates two paths, one for each end of a way.  The line to the first node is cut in two so that the join
         between the two paths is not at an angle.  -->
  <xsl:template name="generatePathWayStart">
    <xsl:call-template name="moveToNode">
      <xsl:with-param name="node" select="key('nodeById',nd[1]/@ref)"/>
    </xsl:call-template>
    <xsl:call-template name="lineToMidpointPlus">
      <xsl:with-param name="fromNode" select="key('nodeById',nd[1]/@ref)"/>
      <xsl:with-param name="toNode" select="key('nodeById',nd[2]/@ref)"/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="generatePathWayEnd">
    <xsl:call-template name="moveToMidpointPlus">
      <xsl:with-param name="fromNode" select="key('nodeById',nd[position()=(last())]/@ref)"/>
      <xsl:with-param name="toNode" select="key('nodeById',nd[position()=last()-1]/@ref)"/>
    </xsl:call-template>
    <xsl:call-template name="lineToNode">
      <xsl:with-param name="node" select="key('nodeById',nd[position()=last()]/@ref)"/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="generatePathWayMid">
    <xsl:for-each select="nd[key('nodeById',@ref)]">
      <xsl:choose>
        <xsl:when test="position()=1">
          <xsl:call-template name="moveToMidpointPlus">
            <xsl:with-param name="fromNode" select="key('nodeById',@ref)"/>
            <xsl:with-param name="toNode" select="key('nodeById',following-sibling::nd[1]/@ref)"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:when test="position()=last()">
          <xsl:call-template name="lineToMidpointMinus">
            <xsl:with-param name="fromNode" select="key('nodeById',preceding-sibling::nd[1]/@ref)"/>
            <xsl:with-param name="toNode" select="key('nodeById',@ref)"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="lineToNode">
            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>

  <!-- Generate an area path for the current way or area element -->
  <xsl:template name="generateAreaPath">
    <xsl:variable name='relation' select="key('relationByWay',@id)[tag[@k='type' and @v='multipolygon']]"/>
    <xsl:choose>
      <xsl:when test='$relation'>
        <!-- Handle multipolygons.
             Draw area only once, draw the outer one first if we know which is it, else just draw the first one -->
        <xsl:variable name='outerway' select="$relation/member[@type='way'][@role='outer']/@ref"/>
        <xsl:variable name='firsrelationmember' select="$relation/member[@type='way'][key('wayById', @ref)][1]/@ref"/> 
        <xsl:if test='( $outerway and $outerway=@id ) or ( not($outerway) and $firsrelationmember=@id )'>
          <xsl:message>
            <xsl:value-of select='$relation/@id'/>
          </xsl:message>
          <xsl:for-each select="$relation/member[@type='way'][key('wayById', @ref)]">
            <xsl:call-template name='generateAreaSubPath'>
              <xsl:with-param name='way' select="key('wayById',@ref)"/>
              <xsl:with-param name='position' select="position()"/>
            </xsl:call-template>
          </xsl:for-each>
          <xsl:text>Z</xsl:text>
        </xsl:if>

      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name='generateAreaSubPath'>
          <xsl:with-param name='way' select='.'/>
          <xsl:with-param name='position' select="'1'"/>
        </xsl:call-template>
        <xsl:text>Z</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <xsl:template name='generateAreaSubPath'>
    <xsl:param name='way'/>
    <xsl:param name='position'/>

    <xsl:variable name='loop' select='$way/nd[1]/@ref=$way/nd[last()]/@ref'/>
    <xsl:message>
      WayId: <xsl:value-of select='$way/@id'/>
      Loop: <xsl:value-of select='$loop'/>
      Loop: <xsl:value-of select='$way/nd[1]/@ref'/>
      Loop: <xsl:value-of select='$way/nd[last()]/@ref'/>
    </xsl:message>
    <xsl:for-each select="$way/nd[key('nodeById',@ref)]">
      <xsl:choose>
        <xsl:when test="position()=1 and $loop">
          <xsl:if test='not($position=1)'>
            <xsl:text>Z</xsl:text>
          </xsl:if>
          <xsl:call-template name="moveToNode">
            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:when test="$position=1 and position()=1 and not($loop=1)">
          <xsl:call-template name="moveToNode">
            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="lineToNode">
            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>


  </xsl:template>

  <!-- Generate a MoveTo command for a node -->
  <xsl:template name="moveToNode">
    <xsl:param name='node' />
    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($node/@lon))*10000*$scale)"/>
    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($node/@lat))*10000*$scale*$projection)"/>
    <xsl:text>M</xsl:text>
    <xsl:value-of select="$x1"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="$y1"/>
  </xsl:template>

  <!-- Generate a LineTo command for a nd -->
  <xsl:template name="lineToNode">
    <xsl:param name='node'/>

    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($node/@lon))*10000*$scale)"/>
    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($node/@lat))*10000*$scale*$projection)"/>
    <xsl:text>L</xsl:text>
    <xsl:value-of select="$x1"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="$y1"/>
  </xsl:template>

  <xsl:template name="lineToMidpointPlus">
    <xsl:param name='fromNode'/>
    <xsl:param name='toNode'/>

    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>

    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>

    <xsl:text>L</xsl:text>
    <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
  </xsl:template>

  <xsl:template name="lineToMidpointMinus">
    <xsl:param name='fromNode'/>
    <xsl:param name='toNode'/>

    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>

    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
    <xsl:text>L</xsl:text>
    <xsl:value-of select="$x1+(($x2 - $x1) div 2.1)"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="$y1+(($y2 - $y1) div 2.1)"/>
  </xsl:template>


  <xsl:template name="moveToMidpointPlus">
    <xsl:param name='fromNode'/>
    <xsl:param name='toNode'/>

    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>

    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
    <xsl:text>M</xsl:text>
    <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
  </xsl:template>

  <!-- Some attribute shouldn't be copied -->
  <xsl:template match="@type|@ref|@scale|@smart-linecap" mode="copyAttributes" />

  <!-- Copy all other attributes  -->
  <xsl:template match="@*" mode="copyAttributes">
    <xsl:copy/>
  </xsl:template>


  <!-- Rule processing engine -->

  <!-- 

		Calls all templates inside <rule> tags (including itself, if there are nested rules).

		If the global var withOSMLayers is 'no', we don't care about layers and draw everything
		in one go. This is faster and is sometimes useful. For normal maps you want withOSMLayers
		to be 'yes', which is the default.

	-->
  <xsl:template name="processRules">

    <!-- First select all elements - exclude those marked as deleted by JOSM -->
    <xsl:variable name='elements' select="$data/osm/*[not(@action) or not(@action='delete')]" />

    <xsl:choose>

      <!-- Process all the rules, one layer at a time -->
      <xsl:when test="$withOSMLayers='yes'">
        <xsl:call-template name="processLayer">
          <xsl:with-param name="layer" select="'-5'"/>
          <xsl:with-param name="elements" select="$elements"/>
        </xsl:call-template>
        <xsl:call-template name="processLayer">
          <xsl:with-param name="layer" select="'-4'"/>
          <xsl:with-param name="elements" select="$elements"/>
        </xsl:call-template>
        <xsl:call-template name="processLayer">
          <xsl:with-param name="layer" select="'-3'"/>
          <xsl:with-param name="elements" select="$elements"/>
        </xsl:call-template>
        <xsl:call-template name="processLayer">
          <xsl:with-param name="layer" select="'-2'"/>
          <xsl:with-param name="elements" select="$elements"/>
        </xsl:call-template>
        <xsl:call-template name="processLayer">
          <xsl:with-param name="layer" select="'-1'"/>
          <xsl:with-param name="elements" select="$elements"/>
        </xsl:call-template>
        <xsl:call-template name="processLayer">
          <xsl:with-param name="layer" select="'0'"/>
          <xsl:with-param name="elements" select="$elements"/>
        </xsl:call-template>
        <xsl:call-template name="processLayer">
          <xsl:with-param name="layer" select="'1'"/>
          <xsl:with-param name="elements" select="$elements"/>
        </xsl:call-template>
        <xsl:call-template name="processLayer">
          <xsl:with-param name="layer" select="'2'"/>
          <xsl:with-param name="elements" select="$elements"/>
        </xsl:call-template>
        <xsl:call-template name="processLayer">
          <xsl:with-param name="layer" select="'3'"/>
          <xsl:with-param name="elements" select="$elements"/>
        </xsl:call-template>
        <xsl:call-template name="processLayer">
          <xsl:with-param name="layer" select="'4'"/>
          <xsl:with-param name="elements" select="$elements"/>
        </xsl:call-template>
        <xsl:call-template name="processLayer">
          <xsl:with-param name="layer" select="'5'"/>
          <xsl:with-param name="elements" select="$elements"/>
        </xsl:call-template>
      </xsl:when>

      <!-- Process all the rules, without looking at the layers -->
      <xsl:otherwise>
        <xsl:apply-templates select="/rules/rule">
          <xsl:with-param name="elements" select="$elements"/>
          <xsl:with-param name="layer" select="'0'"/>
        </xsl:apply-templates>
      </xsl:otherwise>

    </xsl:choose>
  </xsl:template>


  <xsl:template name="processLayer">
    <xsl:param name="layer"/>
    <xsl:param name="elements"/>

    <g inkscape:groupmode="layer" id="layer{$layer}" inkscape:label="Layer {$layer}">
      <xsl:apply-templates select="/rules/rule">
        <xsl:with-param name="elements" select="$elements"/>
        <xsl:with-param name="layer" select="$layer"/>
      </xsl:apply-templates>
    </g>
  </xsl:template>


  <!-- Process a rule at a specific level -->
  <xsl:template match='rule'>
    <xsl:param name="elements"/>
    <xsl:param name="layer"/>

    <!-- If the rule is for a specific layer and we are processing that layer then pass *all* elements 
		     to the rule, otherwise just select the matching elements for this layer. -->
    <xsl:choose>
      <xsl:when test='$layer=@layer'>
        <xsl:call-template name="rule">
          <xsl:with-param name="elements" select="$elements"/>
          <xsl:with-param name="layer" select="$layer"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:if test='not(@layer)'>
          <xsl:call-template name="rule">
            <xsl:with-param name="elements" select="$elements[
							tag[@k='layer' and @v=$layer]
							or ($layer='0' and count(tag[@k='layer'])=0)
						]"/>
            <xsl:with-param name="layer" select="$layer"/>
          </xsl:call-template>
        </xsl:if>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <xsl:template name='rule'>
    <xsl:param name="elements"/>
    <xsl:param name="layer"/>

    <!-- This is the rule currently being processed -->
    <xsl:variable name="rule" select="."/>

    <!-- Make list of elements that this rule should be applied to -->
    <xsl:variable name="eBare">
      <xsl:choose>
        <xsl:when test="$rule/@e='*'">node|way</xsl:when>
        <xsl:when test="$rule/@e">
          <xsl:value-of select="$rule/@e"/>
        </xsl:when>
        <xsl:otherwise>node|way</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <!-- List of keys that this rule should be applied to -->
    <xsl:variable name="kBare" select="$rule/@k"/>

    <!-- List of values that this rule should be applied to -->
    <xsl:variable name="vBare" select="$rule/@v"/>
    <xsl:variable name="sBare" select="$rule/@s"/>

    <!-- Top'n'tail selectors with | for contains usage -->
    <xsl:variable name="e">
      |<xsl:value-of select="$eBare"/>|
    </xsl:variable>
    <xsl:variable name="k">
      |<xsl:value-of select="$kBare"/>|
    </xsl:variable>
    <xsl:variable name="v">
      |<xsl:value-of select="$vBare"/>|
    </xsl:variable>
    <xsl:variable name="s">
      |<xsl:value-of select="$sBare"/>|
    </xsl:variable>

    <xsl:variable
      name="selectedElements"
      select="$elements[contains($e,concat('|',name(),'|'))
            or 
            (contains($e,'|node|') and name()='way' and key('wayByNode',@id))
            ]"/>


    <!-- Patch $s -->
    <xsl:choose>
      <!-- way selector -->
      <xsl:when test="contains($s,'|way|')">
        <xsl:choose>
          <!-- every key -->
          <xsl:when test="contains($k,'|*|')">
            <xsl:choose>
              <!-- every key ,no value defined -->
              <xsl:when test="contains($v,'|~|')">
                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(key('wayByNode',@id)/tag)=0]"/>
                <xsl:call-template name="processElements">
                  <xsl:with-param name="eBare" select="$eBare"/>
                  <xsl:with-param name="kBare" select="$kBare"/>
                  <xsl:with-param name="vBare" select="$vBare"/>
                  <xsl:with-param name="layer" select="$layer"/>
                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
                  <xsl:with-param name="rule" select="$rule"/>
                </xsl:call-template>
              </xsl:when>
              <!-- every key ,every value -->
              <xsl:when test="contains($v,'|*|')">
                <xsl:variable name="allElements" select="$selectedElements"/>
                <xsl:call-template name="processElements">
                  <xsl:with-param name="eBare" select="$eBare"/>
                  <xsl:with-param name="kBare" select="$kBare"/>
                  <xsl:with-param name="vBare" select="$vBare"/>
                  <xsl:with-param name="layer" select="$layer"/>
                  <xsl:with-param name="elements" select="$allElements"/>
                  <xsl:with-param name="rule" select="$rule"/>
                </xsl:call-template>
              </xsl:when>
              <!-- every key , selected values -->
              <xsl:otherwise>
                <xsl:variable name="allElementsWithValue" select="$selectedElements[key('wayByNode',@id)/tag[contains($v,concat('|',@v,'|'))]]"/>
                <xsl:call-template name="processElements">
                  <xsl:with-param name="eBare" select="$eBare"/>
                  <xsl:with-param name="kBare" select="$kBare"/>
                  <xsl:with-param name="vBare" select="$vBare"/>
                  <xsl:with-param name="layer" select="$layer"/>
                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
                  <xsl:with-param name="rule" select="$rule"/>
                </xsl:call-template>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:when>
          <!-- no value  -->
          <xsl:when test="contains($v,'|~|')">
            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])=0]"/>
            <xsl:call-template name="processElements">
              <xsl:with-param name="eBare" select="$eBare"/>
              <xsl:with-param name="kBare" select="$kBare"/>
              <xsl:with-param name="vBare" select="$vBare"/>
              <xsl:with-param name="layer" select="$layer"/>
              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
              <xsl:with-param name="rule" select="$rule"/>
            </xsl:call-template>
          </xsl:when>
          <!-- every value  -->
          <xsl:when test="contains($v,'|*|')">
            <xsl:variable name="allElementsWithKey" select="$selectedElements[key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))]]"/>
            <xsl:call-template name="processElements">
              <xsl:with-param name="eBare" select="$eBare"/>
              <xsl:with-param name="kBare" select="$kBare"/>
              <xsl:with-param name="vBare" select="$vBare"/>
              <xsl:with-param name="layer" select="$layer"/>
              <xsl:with-param name="elements" select="$allElementsWithKey"/>
              <xsl:with-param name="rule" select="$rule"/>
            </xsl:call-template>
          </xsl:when>

          <!-- defined key and defined value -->
          <xsl:otherwise>
            <xsl:variable name="elementsWithKey" select="$selectedElements[
							key('wayByNode',@id)/tag[
								contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))
								]
							]"/>
            <xsl:call-template name="processElements">
              <xsl:with-param name="eBare" select="$eBare"/>
              <xsl:with-param name="kBare" select="$kBare"/>
              <xsl:with-param name="vBare" select="$vBare"/>
              <xsl:with-param name="layer" select="$layer"/>
              <xsl:with-param name="elements" select="$elementsWithKey"/>
              <xsl:with-param name="rule" select="$rule"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>

      <!-- other selector -->
      <xsl:otherwise>
        <xsl:choose>
          <xsl:when test="contains($k,'|*|')">
            <xsl:choose>
              <xsl:when test="contains($v,'|~|')">
                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(tag)=0]"/>
                <xsl:call-template name="processElements">
                  <xsl:with-param name="eBare" select="$eBare"/>
                  <xsl:with-param name="kBare" select="$kBare"/>
                  <xsl:with-param name="vBare" select="$vBare"/>
                  <xsl:with-param name="layer" select="$layer"/>
                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
                  <xsl:with-param name="rule" select="$rule"/>
                </xsl:call-template>
              </xsl:when>
              <xsl:when test="contains($v,'|*|')">
                <xsl:variable name="allElements" select="$selectedElements"/>
                <xsl:call-template name="processElements">
                  <xsl:with-param name="eBare" select="$eBare"/>
                  <xsl:with-param name="kBare" select="$kBare"/>
                  <xsl:with-param name="vBare" select="$vBare"/>
                  <xsl:with-param name="layer" select="$layer"/>
                  <xsl:with-param name="elements" select="$allElements"/>
                  <xsl:with-param name="rule" select="$rule"/>
                </xsl:call-template>
              </xsl:when>
              <xsl:otherwise>
                <xsl:variable name="allElementsWithValue" select="$selectedElements[tag[contains($v,concat('|',@v,'|'))]]"/>
                <xsl:call-template name="processElements">
                  <xsl:with-param name="eBare" select="$eBare"/>
                  <xsl:with-param name="kBare" select="$kBare"/>
                  <xsl:with-param name="vBare" select="$vBare"/>
                  <xsl:with-param name="layer" select="$layer"/>
                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
                  <xsl:with-param name="rule" select="$rule"/>
                </xsl:call-template>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:when>
          <xsl:when test="contains($v,'|~|')">
            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(tag[contains($k,concat('|',@k,'|'))])=0]"/>
            <xsl:call-template name="processElements">
              <xsl:with-param name="eBare" select="$eBare"/>
              <xsl:with-param name="kBare" select="$kBare"/>
              <xsl:with-param name="vBare" select="$vBare"/>
              <xsl:with-param name="layer" select="$layer"/>
              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
              <xsl:with-param name="rule" select="$rule"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:when test="contains($v,'|*|')">
            <xsl:variable name="allElementsWithKey" select="$selectedElements[tag[contains($k,concat('|',@k,'|'))]]"/>
            <xsl:call-template name="processElements">
              <xsl:with-param name="eBare" select="$eBare"/>
              <xsl:with-param name="kBare" select="$kBare"/>
              <xsl:with-param name="vBare" select="$vBare"/>
              <xsl:with-param name="layer" select="$layer"/>
              <xsl:with-param name="elements" select="$allElementsWithKey"/>
              <xsl:with-param name="rule" select="$rule"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <xsl:variable name="elementsWithKey" select="$selectedElements[tag[contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))]]"/>
            <xsl:call-template name="processElements">
              <xsl:with-param name="eBare" select="$eBare"/>
              <xsl:with-param name="kBare" select="$kBare"/>
              <xsl:with-param name="vBare" select="$vBare"/>
              <xsl:with-param name="layer" select="$layer"/>
              <xsl:with-param name="elements" select="$elementsWithKey"/>
              <xsl:with-param name="rule" select="$rule"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <xsl:template match="else">
    <xsl:param name="elements"/>
    <xsl:param name="layer"/>

    <!-- This is the previous rule that is being negated -->
    <!-- TODO: abort if no preceding rule element -->
    <xsl:variable name="rule" select="preceding-sibling::rule[1]"/>

    <!-- Make list of elements that this rule should be applied to -->
    <xsl:variable name="eBare">
      <xsl:choose>
        <xsl:when test="$rule/@e='*'">node|way</xsl:when>
        <xsl:when test="$rule/@e">
          <xsl:value-of select="$rule/@e"/>
        </xsl:when>
        <xsl:otherwise>node|way</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <!-- List of keys that this rule should be applied to -->
    <xsl:variable name="kBare" select="$rule/@k"/>

    <!-- List of values that this rule should be applied to -->
    <xsl:variable name="vBare" select="$rule/@v"/>
    <xsl:variable name="sBare" select="$rule/@s"/>


    <!-- Top'n'tail selectors with | for contains usage -->
    <xsl:variable name="e">
      |<xsl:value-of select="$eBare"/>|
    </xsl:variable>
    <xsl:variable name="k">
      |<xsl:value-of select="$kBare"/>|
    </xsl:variable>
    <xsl:variable name="v">
      |<xsl:value-of select="$vBare"/>|
    </xsl:variable>
    <xsl:variable name="s">
      |<xsl:value-of select="$sBare"/>|
    </xsl:variable>

    <xsl:variable
      name="selectedElements"
      select="$elements[contains($e,concat('|',name(),'|'))
              or 
              (contains($e,'|node|') and name()='way'and key('wayByNode',@id))
              ]"/>

    <!-- Patch $s -->
    <xsl:choose>
      <xsl:when test="contains($s,'|way|')">
        <xsl:choose>
          <xsl:when test="contains($k,'|*|')">
            <xsl:choose>
              <xsl:when test="contains($v,'|~|')">
                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(key('wayByNode',@id)/tag)!=0]"/>
                <xsl:call-template name="processElements">
                  <xsl:with-param name="eBare" select="$eBare"/>
                  <xsl:with-param name="kBare" select="$kBare"/>
                  <xsl:with-param name="vBare" select="$vBare"/>
                  <xsl:with-param name="layer" select="$layer"/>
                  <xsl:with-param name="elements" select="$elementsW