source: subversion/applications/rendering/osmarender6/osmarender.xsl @ 8792

Last change on this file since 8792 was 8792, checked in by bobkare, 11 years ago

Committing patch from nomis, fixes several issues with tunnel rendering

File size: 174.8 KB
Line 
1<?xml version="1.0" encoding="UTF-8"?>
2<!--
3==============================================================================
4
5Osmarender 6.0 Alpha 6
6    with - orig area generation
7         - one node way filtered out
8         - filtered out missing multipolygon relation members from areas
9         - filtered out missing node ref from ways
10
11==============================================================================
12
13Copyright (C) 2006-2007  Etienne Cherdlu, Jochen Topf
14
15This program is free software; you can redistribute it and/or modify
16it under the terms of the GNU General Public License as published by
17the Free Software Foundation; either version 2 of the License, or
18(at your option) any later version.
19
20This program is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23GNU General Public License for more details.
24
25You should have received a copy of the GNU General Public License
26along with this program; if not, write to the Free Software
27Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
28
29==============================================================================
30-->
31<xsl:stylesheet
32  xmlns="http://www.w3.org/2000/svg"
33  xmlns:svg="http://www.w3.org/2000/svg"
34  xmlns:xlink="http://www.w3.org/1999/xlink"
35  xmlns:xi="http://www.w3.org/2001/XInclude"
36  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
37  xmlns:cc="http://web.resource.org/cc/"
38  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
39  xmlns:dc="http://purl.org/dc/elements/1.1/"
40  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
41  xmlns:exslt="http://exslt.org/common"
42  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
43  exclude-result-prefixes="exslt msxsl" 
44  version="1.0">
45
46  <xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="UTF-8"/>
47
48  <!-- This msxsl script extension fools msxsl into interpreting exslt extensions as msxsl ones, so
49       we can write code using exslt extensions even though msxsl only recognises the msxsl extension
50       namespace.  Thanks to David Carlisle for this: http://dpcarlisle.blogspot.com/2007/05/exslt-node-set-function.html -->
51  <msxsl:script language="JScript" implements-prefix="exslt">
52    this['node-set'] =  function (x) {
53    return x;
54    }
55  </msxsl:script>
56
57  <xsl:param name="osmfile" select="/rules/@data"/>
58  <xsl:param name="title" select="/rules/@title"/>
59
60  <xsl:param name="scale" select="/rules/@scale"/>
61  <xsl:param name="symbolScale" select="/rules/@symbolScale"/>
62  <xsl:param name='textAttenuation' select='/rules/@textAttenuation'/>
63  <xsl:param name="withOSMLayers" select="/rules/@withOSMLayers"/>
64  <xsl:param name="svgBaseProfile" select="/rules/@svgBaseProfile"/>
65  <xsl:param name="symbolsDir" select="/rules/@symbolsDir"/>
66
67  <xsl:param name="showGrid" select="/rules/@showGrid"/>
68  <xsl:param name="showBorder" select="/rules/@showBorder"/>
69  <xsl:param name="showScale" select="/rules/@showScale"/>
70  <xsl:param name="showLicense" select="/rules/@showLicense"/>
71
72  <xsl:param name="showRelationRoute" select="/rules/@showRelationRoute"/>
73
74  <xsl:key name="nodeById" match="/osm/node" use="@id"/>
75  <xsl:key name="wayById" match="/osm/way" use="@id"/>
76  <xsl:key name="wayByNode" match="/osm/way" use="nd/@ref"/>
77  <xsl:key name="relationByWay" match="/osm/relation" use="member/@ref"/>
78
79  <xsl:variable name="data" select="document($osmfile)"/>
80
81  <!-- Use a web-service (if available) to get the current date -->
82  <xsl:variable name="now" select="document('http://xobjex.com/service/date.xsl')" />
83  <xsl:variable name="date">
84    <xsl:choose>
85      <xsl:when test="$now">
86        <xsl:value-of select="substring($now/date/utc/@stamp,1,10)" />
87        <!-- Assumes 4 digit year -->
88      </xsl:when>
89      <xsl:otherwise>2007-01-01</xsl:otherwise>
90    </xsl:choose>
91  </xsl:variable>
92  <xsl:variable name="year">
93    <xsl:choose>
94      <xsl:when test="$now">
95        <xsl:value-of select="$now/date/utc/year" />
96      </xsl:when>
97      <xsl:otherwise>2007</xsl:otherwise>
98    </xsl:choose>
99  </xsl:variable>
100
101  <!-- extra height for marginalia at top -->
102  <xsl:variable name="marginaliaTopHeight">
103    <xsl:choose>
104      <xsl:when test="$title != ''">40</xsl:when>
105      <xsl:when test="($title = '') and ($showBorder = 'yes')">1.5</xsl:when>
106      <xsl:otherwise>0</xsl:otherwise>
107    </xsl:choose>
108  </xsl:variable>
109
110  <!-- extra height for marginalia at bottom -->
111  <xsl:variable name="marginaliaBottomHeight">
112    <xsl:choose>
113      <xsl:when test="($showScale = 'yes') or ($showLicense = 'yes')">45</xsl:when>
114      <xsl:when test="($showScale != 'yes') and ($showLicense != 'yes') and ($showBorder = 'yes')">1.5</xsl:when>
115      <xsl:otherwise>0</xsl:otherwise>
116    </xsl:choose>
117  </xsl:variable>
118
119  <!-- extra width for border -->
120  <xsl:variable name="extraWidth">
121    <xsl:choose>
122      <xsl:when test="$showBorder = 'yes'">3</xsl:when>
123      <xsl:otherwise>0</xsl:otherwise>
124    </xsl:choose>
125  </xsl:variable>
126
127  <!-- extra height for border -->
128  <xsl:variable name="extraHeight">
129    <xsl:choose>
130      <xsl:when test="($title = '') and ($showBorder = 'yes')">3</xsl:when>
131      <xsl:otherwise>0</xsl:otherwise>
132    </xsl:choose>
133  </xsl:variable>
134
135  <!-- Calculate the size of the bounding box based on the file content -->
136  <xsl:variable name="bllat">
137    <xsl:for-each select="$data/osm/node/@lat">
138      <xsl:sort data-type="number" order="ascending"/>
139      <xsl:if test="position()=1">
140        <xsl:value-of select="."/>
141      </xsl:if>
142    </xsl:for-each>
143  </xsl:variable>
144  <xsl:variable name="bllon">
145    <xsl:for-each select="$data/osm/node/@lon">
146      <xsl:sort data-type="number" order="ascending"/>
147      <xsl:if test="position()=1">
148        <xsl:value-of select="."/>
149      </xsl:if>
150    </xsl:for-each>
151  </xsl:variable>
152  <xsl:variable name="trlat">
153    <xsl:for-each select="$data/osm/node/@lat">
154      <xsl:sort data-type="number" order="descending"/>
155      <xsl:if test="position()=1">
156        <xsl:value-of select="."/>
157      </xsl:if>
158    </xsl:for-each>
159  </xsl:variable>
160  <xsl:variable name="trlon">
161    <xsl:for-each select="$data/osm/node/@lon">
162      <xsl:sort data-type="number" order="descending"/>
163      <xsl:if test="position()=1">
164        <xsl:value-of select="."/>
165      </xsl:if>
166    </xsl:for-each>
167  </xsl:variable>
168  <xsl:variable name="bottomLeftLatitude">
169    <xsl:choose>
170      <xsl:when test="/rules/bounds">
171        <xsl:value-of select="/rules/bounds/@minlat"/>
172      </xsl:when>
173      <xsl:when test="$data/osm/bounds">
174        <xsl:value-of select="$data/osm/bounds/@request_minlat"/>
175      </xsl:when>
176      <xsl:otherwise>
177        <xsl:value-of select="$bllat"/>
178      </xsl:otherwise>
179    </xsl:choose>
180  </xsl:variable>
181  <xsl:variable name="bottomLeftLongitude">
182    <xsl:choose>
183      <xsl:when test="/rules/bounds">
184        <xsl:value-of select="/rules/bounds/@minlon"/>
185      </xsl:when>
186      <xsl:when test="$data/osm/bounds">
187        <xsl:value-of select="$data/osm/bounds/@request_minlon"/>
188      </xsl:when>
189      <xsl:otherwise>
190        <xsl:value-of select="$bllon"/>
191      </xsl:otherwise>
192    </xsl:choose>
193  </xsl:variable>
194  <xsl:variable name="topRightLatitude">
195    <xsl:choose>
196      <xsl:when test="/rules/bounds">
197        <xsl:value-of select="/rules/bounds/@maxlat"/>
198      </xsl:when>
199      <xsl:when test="$data/osm/bounds">
200        <xsl:value-of select="$data/osm/bounds/@request_maxlat"/>
201      </xsl:when>
202      <xsl:otherwise>
203        <xsl:value-of select="$trlat"/>
204      </xsl:otherwise>
205    </xsl:choose>
206  </xsl:variable>
207  <xsl:variable name="topRightLongitude">
208    <xsl:choose>
209      <xsl:when test="/rules/bounds">
210        <xsl:value-of select="/rules/bounds/@maxlon"/>
211      </xsl:when>
212      <xsl:when test="$data/osm/bounds">
213        <xsl:value-of select="$data/osm/bounds/@request_maxlon"/>
214      </xsl:when>
215      <xsl:otherwise>
216        <xsl:value-of select="$trlon"/>
217      </xsl:otherwise>
218    </xsl:choose>
219  </xsl:variable>
220
221  <!-- Derive the latitude of the middle of the map -->
222  <xsl:variable name="middleLatitude" select="($topRightLatitude + $bottomLeftLatitude) div 2.0"/>
223  <!--woohoo lets do trigonometry in xslt -->
224  <!--convert latitude to radians -->
225  <xsl:variable name="latr" select="$middleLatitude * 3.1415926 div 180.0"/>
226  <!--taylor series: two terms is 1% error at lat<68 and 10% error lat<83. we probably need polar projection by then -->
227  <xsl:variable name="coslat" select="1 - ($latr * $latr) div 2 + ($latr * $latr * $latr * $latr) div 24"/>
228  <xsl:variable name="projection" select="1 div $coslat"/>
229
230  <xsl:variable name="dataWidth" select="(number($topRightLongitude)-number($bottomLeftLongitude))*10000*$scale"/>
231  <xsl:variable name="dataHeight" select="(number($topRightLatitude)-number($bottomLeftLatitude))*10000*$scale*$projection"/>
232  <xsl:variable name="km" select="(0.0089928*$scale*10000*$projection)"/>
233
234  <xsl:variable name="documentWidth">
235    <xsl:choose>
236      <xsl:when test="$dataWidth &gt; (number(/rules/@minimumMapWidth) * $km)">
237        <xsl:value-of select="$dataWidth"/>
238      </xsl:when>
239      <xsl:otherwise>
240        <xsl:value-of select="number(/rules/@minimumMapWidth) * $km"/>
241      </xsl:otherwise>
242    </xsl:choose>
243  </xsl:variable>
244
245  <xsl:variable name="documentHeight">
246    <xsl:choose>
247      <xsl:when test="$dataHeight &gt; (number(/rules/@minimumMapHeight) * $km)">
248        <xsl:value-of select="$dataHeight"/>
249      </xsl:when>
250      <xsl:otherwise>
251        <xsl:value-of select="number(/rules/@minimumMapHeight) * $km"/>
252      </xsl:otherwise>
253    </xsl:choose>
254  </xsl:variable>
255
256  <xsl:variable name="width" select="($documentWidth div 2) + ($dataWidth div 2)"/>
257  <xsl:variable name="height" select="($documentHeight div 2) + ($dataHeight div 2)"/>
258
259
260
261  <!-- Main template -->
262  <xsl:template match="/rules">
263
264    <!-- Include an external css stylesheet if one was specified in the rules file -->
265    <xsl:if test="@xml-stylesheet">
266      <xsl:processing-instruction name="xml-stylesheet">
267        href="<xsl:value-of select="@xml-stylesheet"/>" type="text/css"
268      </xsl:processing-instruction>
269    </xsl:if>
270
271    <xsl:variable name="svgWidth" select="$documentWidth + $extraWidth"/>
272    <xsl:variable name="svgHeight" select="$documentHeight + $marginaliaTopHeight + $marginaliaBottomHeight"/>
273
274    <svg id="main"
275  version="1.1"
276  baseProfile="{$svgBaseProfile}"
277  width="{$svgWidth}px"
278  height="{$svgHeight}px"
279  preserveAspectRatio="none"
280  viewBox="{-$extraWidth div 2} {-$extraHeight div 2} {$svgWidth} {$svgHeight}">
281      <xsl:if test="/rules/@interactive='yes'">
282        <xsl:attribute name="onscroll">fnOnScroll(evt)</xsl:attribute>
283        <xsl:attribute name="onzoom">fnOnZoom(evt)</xsl:attribute>
284        <xsl:attribute name="onload">fnOnLoad(evt)</xsl:attribute>
285        <xsl:attribute name="onmousedown">fnOnMouseDown(evt)</xsl:attribute>
286        <xsl:attribute name="onmousemove">fnOnMouseMove(evt)</xsl:attribute>
287        <xsl:attribute name="onmouseup">fnOnMouseUp(evt)</xsl:attribute>
288      </xsl:if>
289
290      <xsl:call-template name="metadata"/>
291
292      <!-- Include javaScript functions for all the dynamic stuff -->
293      <xsl:if test="/rules/@interactive='yes'">
294        <xsl:call-template name="javaScript"/>
295      </xsl:if>
296
297
298      <defs id="defs-rulefile">
299        <!-- Get any <defs> and styles from the rules file -->
300        <xsl:copy-of select="defs/*"/>
301      </defs>
302
303
304      <xsl:if test="$symbolsDir != ''">
305        <!-- Get all symbols mentioned in the rules file from the symbolsDir -->
306        <defs id="defs-symbols">
307          <xsl:for-each select="/rules//symbol/@ref">
308            <xsl:copy-of select="document(concat($symbolsDir,'/', ., '.svg'))/svg:svg/svg:defs/svg:symbol"/>
309          </xsl:for-each>
310        </defs>
311      </xsl:if>
312
313      <!-- Pre-generate named path definitions for all ways -->
314      <xsl:variable name="allWays" select="$data/osm/way"/>
315      <defs id="defs-ways">
316        <xsl:for-each select="$allWays">
317          <xsl:call-template name="generateWayPaths"/>
318        </xsl:for-each>
319      </defs>
320
321      <!-- Clipping rectangle for map -->
322      <clipPath id="map-clipping">
323        <rect id="map-clipping-rect" x="0px" y="0px" height="{$documentHeight}px" width="{$documentWidth}px"/>
324      </clipPath>
325
326      <g id="map" clip-path="url(#map-clipping)" inkscape:groupmode="layer" inkscape:label="Map" transform="translate(0,{$marginaliaTopHeight})">
327        <!-- Draw a nice background layer -->
328        <rect id="background" x="0px" y="0px" height="{$documentHeight}px" width="{$documentWidth}px" class="map-background"/>
329
330        <!-- Process all the rules drawing all map features -->
331        <xsl:call-template name="processRules"/>
332      </g>
333
334      <!-- Draw map decoration -->
335      <g id="map-decoration" inkscape:groupmode="layer" inkscape:label="Map decoration" transform="translate(0,{$marginaliaTopHeight})">
336        <!-- Draw a grid if required -->
337        <xsl:if test="$showGrid='yes'">
338          <xsl:call-template name="drawGrid"/>
339        </xsl:if>
340
341        <!-- Draw a border if required -->
342        <xsl:if test="$showBorder='yes'">
343          <xsl:call-template name="drawBorder"/>
344        </xsl:if>
345      </g>
346
347      <!-- Draw map marginalia -->
348      <xsl:if test="($title != '') or ($showScale = 'yes') or ($showLicense = 'yes')">
349        <g id="marginalia" inkscape:groupmode="layer" inkscape:label="Marginalia">
350          <!-- Draw the title -->
351          <xsl:if test="$title!=''">
352            <xsl:call-template name="drawTitle">
353              <xsl:with-param name="title" select="$title"/>
354            </xsl:call-template>
355          </xsl:if>
356
357          <xsl:if test="($showScale = 'yes') or ($showLicense = 'yes')">
358            <g id="marginalia-bottom" inkscape:groupmode="layer" inkscape:label="Marginalia (Bottom)" transform="translate(0,{$marginaliaTopHeight})">
359              <!-- Draw background for marginalia at bottom -->
360              <rect id="marginalia-background" x="0px" y="{$documentHeight + 5}px" height="40px" width="{$documentWidth}px" class="map-marginalia-background"/>
361
362              <!-- Draw the scale in the bottom left corner -->
363              <xsl:if test="$showScale='yes'">
364                <xsl:call-template name="drawScale"/>
365              </xsl:if>
366
367              <!-- Draw Creative commons license -->
368              <xsl:if test="$showLicense='yes'">
369                <xsl:call-template name="in-image-license">
370                  <xsl:with-param name="dx" select="$documentWidth"/>
371                  <xsl:with-param name="dy" select="$documentHeight"/>
372                </xsl:call-template>
373              </xsl:if>
374            </g>
375          </xsl:if>
376        </g>
377      </xsl:if>
378
379      <!-- Draw labels and controls that are in a static position -->
380      <g id="staticElements" transform="scale(1) translate(0,0)">
381        <!-- Draw the +/- zoom controls -->
382        <xsl:if test="/rules/@interactive='yes'">
383          <xsl:call-template name="zoomControl"/>
384        </xsl:if>
385      </g>
386    </svg>
387
388  </xsl:template>
389
390  <!-- Path Fragment Drawing -->
391  <xsl:template name="drawPath">
392    <xsl:param name='instruction' />
393    <xsl:param name='pathId'/>
394    <xsl:param name='extraClasses'/>
395
396    <xsl:variable name="maskId" select="concat('mask_',$pathId)"/>
397
398    <xsl:call-template name='generateMask'>
399      <xsl:with-param name='instruction' select='$instruction'/>
400      <xsl:with-param name='pathId' select='$pathId'/>
401      <xsl:with-param name='maskId' select='$maskId'/>
402    </xsl:call-template>
403
404    <use xlink:href="#{$pathId}">
405      <!-- Copy all attributes from instruction -->
406      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes" />
407      <!-- Add in any extra classes -->
408      <xsl:attribute name="class">
409        <xsl:value-of select='$instruction/@class'/>
410        <xsl:text> </xsl:text>
411        <xsl:value-of select="$extraClasses"/>
412      </xsl:attribute>
413      <!-- If there is a mask class then include the mask attribute -->
414      <xsl:if test='$instruction/@mask-class'>
415        <xsl:attribute name="mask">url(#<xsl:value-of select="$maskId"/>)</xsl:attribute>
416      </xsl:if>
417      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
418    </use>
419  </xsl:template>
420
421
422  <xsl:template name='generateMask'>
423    <xsl:param name='instruction' />
424    <xsl:param name='pathId'/>
425    <xsl:param name='maskId'/>
426
427    <!-- If the instruction has a mask class -->
428    <xsl:if test='$instruction/@mask-class'>
429      <mask id="{$maskId}" maskUnits="userSpaceOnUse">
430        <use xlink:href="#{$pathId}" class="{$instruction/@mask-class} osmarender-mask-black" />
431        <!-- Required for Inkscape bug -->
432        <use xlink:href="#{$pathId}" class="{$instruction/@class} osmarender-mask-white" />
433        <use xlink:href="#{$pathId}" class="{$instruction/@mask-class} osmarender-mask-black" />
434      </mask>
435    </xsl:if>
436  </xsl:template>
437
438
439
440  <!-- Draw a line for the current <way> element using the formatting of the current <line> instruction -->
441  <xsl:template name="drawWay">
442    <xsl:param name="instruction"/>
443    <xsl:param name="way"/>
444    <!-- The current way element if applicable -->
445    <xsl:param name="layer"/>
446
447    <xsl:variable name="extraClasses">
448      <xsl:if test="$instruction/@suppress-markers-tag != ''">
449        <xsl:variable name="suppressMarkersTag" select="$instruction/@suppress-markers-tag" />
450        <xsl:variable name="firstNode" select="key('nodeById',$way/nd[1]/@ref)"/>
451        <xsl:variable name="firstNodeMarkerGroupConnectionCount"
452                      select="count(key('wayByNode',$firstNode/@id)/tag[@k=$suppressMarkersTag and ( @v = 'yes' or @v = 'true' )])" />
453        <xsl:variable name="lastNode" select="key('nodeById',$way/nd[last()]/@ref)"/>
454        <xsl:variable name="lastNodeMarkerGroupConnectionCount"
455                      select="count(key('wayByNode',$lastNode/@id)/tag[@k=$suppressMarkersTag and ( @v = 'yes' or @v = 'true' )])" />
456       
457        <xsl:if test="$firstNodeMarkerGroupConnectionCount > 1">osmarender-no-marker-start</xsl:if>
458        <xsl:if test="$lastNodeMarkerGroupConnectionCount > 1"> osmarender-no-marker-end</xsl:if>
459      </xsl:if>
460    </xsl:variable>
461
462    <xsl:choose>
463      <xsl:when test="$instruction/@smart-linecap='no'">
464        <xsl:call-template name='drawPath'>
465          <xsl:with-param name='pathId' select="concat('way_normal_',$way/@id)"/>
466          <xsl:with-param name='instruction' select='$instruction'/>
467          <xsl:with-param name="extraClasses" select='$extraClasses'/>
468        </xsl:call-template>
469      </xsl:when>
470      <xsl:otherwise>
471        <xsl:call-template name="drawWayWithSmartLinecaps">
472          <xsl:with-param name="instruction" select="$instruction"/>
473          <xsl:with-param name="way" select="$way"/>
474          <xsl:with-param name="layer" select="$layer"/>
475          <xsl:with-param name="extraClasses" select='$extraClasses'/>
476        </xsl:call-template>
477      </xsl:otherwise>
478    </xsl:choose>
479  </xsl:template>
480
481
482  <xsl:template name="drawWayWithSmartLinecaps">
483    <xsl:param name="instruction"/>
484    <xsl:param name="way"/>
485    <!-- The current way element if applicable -->
486    <xsl:param name="layer"/>
487    <xsl:param name="extraClasses"/>
488
489    <!-- The first half of the first segment and the last half of the last segment are treated differently from the main
490                        part of the way path.  The main part is always rendered with a butt line-cap.  Each end fragment is rendered with
491                        either a round line-cap, if it connects to some other path, or with its default line-cap if it is not connected
492                        to anything.  That way, cul-de-sacs etc are terminated with round, square or butt as specified in the style for the
493                        way. -->
494
495    <!-- First draw the middle section of the way with round linejoins and butt linecaps -->
496    <xsl:if test="count($way/nd) &gt; 1">
497      <xsl:call-template name='drawPath'>
498        <xsl:with-param name='pathId' select="concat('way_mid_',$way/@id)"/>
499        <xsl:with-param name='instruction' select='$instruction'/>
500        <xsl:with-param name='extraClasses'>osmarender-stroke-linecap-butt osmarender-no-marker-start osmarender-no-marker-end</xsl:with-param>
501      </xsl:call-template>
502    </xsl:if>
503
504
505    <!-- For the first half segment in the way, count the number of segments that link to the from-node of this segment.
506                        Also count links where the layer tag is less than the layer of this way, if there are links on a lower layer then
507                        we can safely draw a butt line-cap because the lower layer will already have a round line-cap. -->
508    <!-- Process the first segment in the way -->
509    <xsl:variable name="firstNode" select="key('nodeById',$way/nd[1]/@ref)"/>
510
511    <!-- Count the number of segments connecting to the from node. If there is only one (the current segment) then draw a default line.  -->
512    <xsl:variable name="firstNodeConnectionCount" select="count(key('wayByNode',$firstNode/@id))" />
513
514    <!-- Count the number of connectors at a layer lower than the current layer -->
515    <xsl:variable name="firstNodeLowerLayerConnectionCount" select="
516                        count(key('wayByNode',$firstNode/@id)/tag[@k='layer' and @v &lt; $layer]) +
517                        count(key('wayByNode',$firstNode/@id)[count(tag[@k='layer'])=0 and $layer &gt; 0])
518                        " />
519    <xsl:choose>
520      <xsl:when test="$firstNodeConnectionCount=1">
521        <xsl:call-template name='drawPath'>
522          <xsl:with-param name='pathId' select="concat('way_start_',$way/@id)"/>
523          <xsl:with-param name='instruction' select='$instruction'/>
524          <xsl:with-param name="extraClasses"><xsl:value-of select="$extraClasses"/> osmarender-no-marker-end</xsl:with-param>
525        </xsl:call-template>
526      </xsl:when>
527      <xsl:when test="$firstNodeLowerLayerConnectionCount>0">
528        <xsl:call-template name='drawPath'>
529          <xsl:with-param name='pathId' select="concat('way_start_',$way/@id)"/>
530          <xsl:with-param name='instruction' select='$instruction'/>
531          <xsl:with-param name="extraClasses"><xsl:value-of select="$extraClasses"/> osmarender-stroke-linecap-butt osmarender-no-marker-end</xsl:with-param>
532        </xsl:call-template>
533      </xsl:when>
534      <xsl:otherwise>
535        <xsl:call-template name='drawPath'>
536          <xsl:with-param name='pathId' select="concat('way_start_',$way/@id)"/>
537          <xsl:with-param name='instruction' select='$instruction'/>
538          <xsl:with-param name="extraClasses"><xsl:value-of select="$extraClasses"/>  osmarender-stroke-linecap-round osmarender-no-marker-end</xsl:with-param>
539        </xsl:call-template>
540      </xsl:otherwise>
541
542    </xsl:choose>
543
544
545    <!-- Process the last segment in the way -->
546    <xsl:variable name="lastNode" select="key('nodeById',$way/nd[last()]/@ref)"/>
547
548    <!-- Count the number of segments connecting to the last node. If there is only one (the current segment) then draw
549                     a default line.  -->
550    <xsl:variable name="lastNodeConnectionCount" select="count(key('wayByNode',$lastNode/@id))" />
551
552    <!-- Count the number of connectors at a layer lower than the current layer -->
553    <xsl:variable name="lastNodeLowerLayerConnectionCount" select="
554                        count(key('wayByNode',$lastNode/@id)/tag[@k='layer' and @v &lt; $layer]) +
555                        count(key('wayByNode',$lastNode/@id)[count(tag[@k='layer'])=0 and $layer &gt; 0])
556                        " />
557
558
559    <xsl:choose>
560      <xsl:when test="$lastNodeConnectionCount=1">
561        <xsl:call-template name='drawPath'>
562          <xsl:with-param name='pathId' select="concat('way_end_',$way/@id)"/>
563          <xsl:with-param name='instruction' select='$instruction'/>
564          <xsl:with-param name="extraClasses"><xsl:value-of select="$extraClasses"/> osmarender-no-marker-start</xsl:with-param>
565        </xsl:call-template>
566      </xsl:when>
567      <xsl:when test="$lastNodeLowerLayerConnectionCount>0">
568        <xsl:call-template name='drawPath'>
569          <xsl:with-param name='pathId' select="concat('way_end_',$way/@id)"/>
570          <xsl:with-param name='instruction' select='$instruction'/>
571          <xsl:with-param name="extraClasses"><xsl:value-of select="$extraClasses"/> osmarender-stroke-linecap-butt osmarender-no-marker-start</xsl:with-param>
572        </xsl:call-template>
573      </xsl:when>
574      <xsl:otherwise>
575        <xsl:call-template name='drawPath'>
576          <xsl:with-param name='pathId' select="concat('way_end_',$way/@id)"/>
577          <xsl:with-param name='instruction' select='$instruction'/>
578          <xsl:with-param name="extraClasses"><xsl:value-of select="$extraClasses"/> osmarender-stroke-linecap-round osmarender-no-marker-start</xsl:with-param>
579        </xsl:call-template>
580      </xsl:otherwise>
581
582    </xsl:choose>
583
584  </xsl:template>
585
586
587  <!-- Draw a circle for the current <node> element using the formatting of the current <circle> instruction -->
588  <xsl:template name="drawCircle">
589    <xsl:param name="instruction"/>
590
591    <xsl:variable name="x" select="($width)-((($topRightLongitude)-(@lon))*10000*$scale)"/>
592    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-(@lat))*10000*$scale*$projection)"/>
593
594    <circle cx="{$x}" cy="{$y}">
595      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
596      <!-- Copy all the svg attributes from the <circle> instruction -->
597    </circle>
598
599  </xsl:template>
600
601
602  <!-- Draw a symbol for the current <node> element using the formatting of the current <symbol> instruction -->
603  <xsl:template name="drawSymbol">
604    <xsl:param name="instruction"/>
605
606    <xsl:variable name="x" select="($width)-((($topRightLongitude)-(@lon))*10000*$scale)"/>
607    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-(@lat))*10000*$scale*$projection)"/>
608
609    <g transform="translate({$x},{$y}) scale({$symbolScale})">
610      <use>
611        <xsl:if test="$instruction/@ref">
612          <xsl:attribute name="xlink:href">
613            <xsl:value-of select="concat('#symbol-', $instruction/@ref)"/>
614          </xsl:attribute>
615        </xsl:if>
616        <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
617        <!-- Copy all the attributes from the <symbol> instruction -->
618      </use>
619    </g>
620  </xsl:template>
621
622
623  <!-- Render the appropriate attribute of the current <node> element using the formatting of the current <text> instruction -->
624  <xsl:template name="renderText">
625    <xsl:param name="instruction"/>
626
627    <xsl:variable name="x" select="($width)-((($topRightLongitude)-(@lon))*10000*$scale)"/>
628    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-(@lat))*10000*$scale*$projection)"/>
629
630    <text>
631      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
632      <xsl:attribute name="x">
633        <xsl:value-of select="$x"/>
634      </xsl:attribute>
635      <xsl:attribute name="y">
636        <xsl:value-of select="$y"/>
637      </xsl:attribute>
638      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
639      <xsl:value-of select="tag[@k=$instruction/@k]/@v"/>
640    </text>
641  </xsl:template>
642
643
644  <!-- Render the appropriate attribute of the current <segment> element using the formatting of the current <textPath> instruction -->
645  <xsl:template name="renderTextPath">
646    <xsl:param name="instruction"/>
647    <xsl:param name="pathId"/>
648    <xsl:param name="pathDirection"/>
649    <xsl:param name='text'/>
650
651    <xsl:variable name='pathLengthSquared'>
652      <xsl:call-template name='getPathLength'>
653        <xsl:with-param name='pathLengthMultiplier'>
654          <!-- This factor is used to adjust the path-length for comparison with text along a path to determine whether it will fit. -->
655          <xsl:choose>
656            <xsl:when test='$instruction/@textAttenuation'>
657              <xsl:value-of select='$instruction/@textAttenuation'/>
658            </xsl:when>
659            <xsl:when test='string($textAttenuation)'>
660              <xsl:value-of select='$textAttenuation'/>
661            </xsl:when>
662            <xsl:otherwise>99999999</xsl:otherwise>
663          </xsl:choose>
664        </xsl:with-param>
665        <xsl:with-param name='nodes' select='nd'/>
666      </xsl:call-template>
667    </xsl:variable>
668
669    <xsl:variable name='textLength' select='string-length($text)' />
670    <xsl:variable name='textLengthSquared100' select='($textLength)*($textLength)' />
671    <xsl:variable name='textLengthSquared90' select='($textLength *.9)*($textLength*.9)' />
672    <xsl:variable name='textLengthSquared80' select='($textLength *.8)*($textLength*.8)' />
673    <xsl:variable name='textLengthSquared70' select='($textLength *.7)*($textLength*.7)' />
674
675    <xsl:choose>
676      <xsl:when test='($pathLengthSquared) > $textLengthSquared100'>
677        <text>
678          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
679          <textPath xlink:href="#{$pathId}">
680            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
681            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
682            <xsl:value-of select="$text"/>
683          </textPath>
684        </text>
685      </xsl:when>
686      <xsl:when test='($pathLengthSquared) > ($textLengthSquared90)'>
687        <text>
688          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
689          <textPath xlink:href="#{$pathId}">
690            <xsl:attribute name='font-size'>90%</xsl:attribute>
691            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
692            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
693            <xsl:value-of select="$text"/>
694          </textPath>
695        </text>
696      </xsl:when>
697      <xsl:when test='($pathLengthSquared) > ($textLengthSquared80)'>
698        <text>
699          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
700          <textPath xlink:href="#{$pathId}">
701            <xsl:attribute name='font-size'>80%</xsl:attribute>
702            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
703            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
704            <xsl:value-of select="$text"/>
705          </textPath>
706        </text>
707      </xsl:when>
708      <xsl:when test='($pathLengthSquared) > ($textLengthSquared70)'>
709        <text>
710          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
711          <textPath xlink:href="#{$pathId}">
712            <xsl:attribute name='font-size'>70%</xsl:attribute>
713            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
714            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
715            <xsl:value-of select="$text"/>
716          </textPath>
717        </text>
718      </xsl:when>
719      <xsl:otherwise />
720      <!-- Otherwise don't render the text -->
721    </xsl:choose>
722  </xsl:template>
723
724
725  <xsl:template name='getPathLength'>
726    <xsl:param name='sumLon' select='number("0")' />
727    <!-- initialise sum to zero -->
728    <xsl:param name='sumLat' select='number("0")' />
729    <!-- initialise sum to zero -->
730    <xsl:param name='nodes'/>
731    <xsl:param name='pathLengthMultiplier'/>
732    <xsl:choose>
733      <xsl:when test='$nodes[1] and $nodes[2]'>
734        <xsl:variable name='fromNode' select='key("nodeById",$nodes[1]/@ref)'/>
735        <xsl:variable name='toNode' select='key("nodeById",$nodes[2]/@ref)'/>
736        <xsl:variable name='lengthLon' select='($fromNode/@lon)-($toNode/@lon)'/>
737        <xsl:variable name='absLengthLon'>
738          <xsl:choose>
739            <xsl:when test='$lengthLon &lt; 0'>
740              <xsl:value-of select='$lengthLon * -1'/>
741            </xsl:when>
742            <xsl:otherwise>
743              <xsl:value-of select='$lengthLon'/>
744            </xsl:otherwise>
745          </xsl:choose>
746        </xsl:variable>
747        <xsl:variable name='lengthLat' select='($fromNode/@lat)-($toNode/@lat)'/>
748        <xsl:variable name='absLengthLat'>
749          <xsl:choose>
750            <xsl:when test='$lengthLat &lt; 0'>
751              <xsl:value-of select='$lengthLat * -1'/>
752            </xsl:when>
753            <xsl:otherwise>
754              <xsl:value-of select='$lengthLat'/>
755            </xsl:otherwise>
756          </xsl:choose>
757        </xsl:variable>
758        <xsl:call-template name='getPathLength'>
759          <xsl:with-param name='sumLon' select='$sumLon+$absLengthLon'/>
760          <xsl:with-param name='sumLat' select='$sumLat+$absLengthLat'/>
761          <xsl:with-param name='nodes' select='$nodes[position()!=1]'/>
762          <xsl:with-param name='pathLengthMultiplier' select='$pathLengthMultiplier'/>
763        </xsl:call-template>
764      </xsl:when>
765      <xsl:otherwise>
766        <!-- Add the square of the total horizontal length to the square of the total vertical length to get the square of
767                                     the total way length.  We don't have a sqrt() function so leave it squared.
768                                     Multiply by 1,000 so that we are usually dealing with a values greater than 1.  Squares of values between 0 and 1
769                                     are smaller and so not very useful.
770                                     Multiply the latitude component by $projection to adjust for Mercator projection issues.
771                                     -->
772        <xsl:value-of select='(
773                                        (($sumLon*1000*$pathLengthMultiplier)*($sumLon*1000*$pathLengthMultiplier))+
774                                        (($sumLat*1000*$pathLengthMultiplier*$projection)*($sumLat*1000*$pathLengthMultiplier*$projection))
775                                        )'/>
776      </xsl:otherwise>
777    </xsl:choose>
778  </xsl:template>
779
780
781  <!-- Suppress the following attributes, allow everything else -->
782  <xsl:template match="@startOffset|@method|@spacing|@lengthAdjust|@textLength|@k" mode="renderTextPath-text" />
783
784  <xsl:template match="@*" mode="renderTextPath-text">
785    <xsl:copy/>
786  </xsl:template>
787
788
789  <!-- Allow the following attributes, suppress everything else -->
790  <xsl:template match="@startOffset|@method|@spacing|@lengthAdjust|@textLength" mode="renderTextPath-textPath">
791    <xsl:copy/>
792  </xsl:template>
793
794  <xsl:template match="@*" mode="renderTextPath-textPath" />
795
796
797  <!-- If there are any tags like <tag k="svg:font-size" v="5"/> then add these as attributes of the svg output -->
798  <xsl:template name="getSvgAttributesFromOsmTags">
799    <xsl:for-each select="tag[contains(@k,'svg:')]">
800      <xsl:attribute name="{substring-after(@k,'svg:')}">
801        <xsl:value-of select="@v"/>
802      </xsl:attribute>
803    </xsl:for-each>
804  </xsl:template>
805
806
807  <xsl:template name="renderArea">
808    <xsl:param name="instruction"/>
809    <xsl:param name="pathId"/>
810
811    <use xlink:href="#{$pathId}">
812      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
813    </use>
814  </xsl:template>
815
816
817  <!-- Templates to process line, circle, text, etc. instructions -->
818  <!-- Each template is passed a variable containing the set of elements that need to
819         be processed.  The set of elements is already determined by the rules, so
820         these templates don't need to know anything about the rules context they are in. -->
821
822  <!-- Process a <line> instruction -->
823  <xsl:template match="line">
824    <xsl:param name="elements"/>
825    <xsl:param name="layer"/>
826
827    <!-- This is the instruction that is currently being processed -->
828    <xsl:variable name="instruction" select="."/>
829
830    <g>
831      <xsl:apply-templates select="@*" mode="copyAttributes" />
832      <!-- Add all the svg attributes of the <line> instruction to the <g> element -->
833
834      <!-- For each way -->
835      <xsl:apply-templates select="$elements" mode="line">
836        <xsl:with-param name="instruction" select="$instruction"/>
837        <xsl:with-param name="layer" select="$layer"/>
838      </xsl:apply-templates>
839
840    </g>
841  </xsl:template>
842
843
844  <!-- Suppress output of any unhandled elements -->
845  <xsl:template match="*" mode="line"/>
846
847
848  <!-- Draw lines for a way  -->
849  <xsl:template match="way" mode="line">
850    <xsl:param name="instruction"/>
851    <xsl:param name="layer"/>
852
853    <!-- The current <way> element -->
854    <xsl:variable name="way" select="."/>
855
856    <!-- DODI: !!!WORKAROUND!!! skip one node ways-->
857    <xsl:if test="count($way/nd) &gt; 1">
858      <xsl:call-template name="drawWay">
859        <xsl:with-param name="instruction" select="$instruction"/>
860        <xsl:with-param name="way" select="$way"/>
861        <xsl:with-param name="layer" select="$layer"/>
862      </xsl:call-template>
863    </xsl:if >
864  </xsl:template>
865
866
867  <!-- Draw lines for a relation -->
868  <xsl:template match="relation" mode="line">
869    <xsl:param name="instruction"/>
870    <xsl:param name="layer"/>
871
872    <xsl:variable name="relation" select="@id"/>
873
874    <xsl:if test="(tag[@k='type']/@v='route') and ($showRelationRoute!='~|no')">
875      <!-- Draw lines for a RelationRoute -->
876      <xsl:for-each select="$data/osm/relation[@id=$relation]/member[@type='way']">
877        <xsl:variable name="wayid" select="@ref"/>
878
879        <xsl:for-each select="$data/osm/way[@id=$wayid]">
880          <!-- The current <way> element -->
881          <xsl:variable name="way" select="."/>
882
883          <!-- DODI: !!!WORKAROUND!!! skip one node ways-->
884          <xsl:if test="count($way/nd) &gt; 1">
885            <xsl:call-template name="drawWay">
886              <xsl:with-param name="instruction" select="$instruction"/>
887              <xsl:with-param name="way" select="$way"/>
888              <xsl:with-param name="layer" select="$layer"/>
889            </xsl:call-template>
890          </xsl:if >
891        </xsl:for-each >
892      </xsl:for-each >
893    </xsl:if>
894
895    <!-- Handle other types of Relations if necessary -->
896
897  </xsl:template>
898
899
900  <!-- Process an <area> instruction -->
901  <xsl:template match="area">
902    <xsl:param name="elements"/>
903
904    <!-- This is the instruction that is currently being processed -->
905    <xsl:variable name="instruction" select="."/>
906
907    <g>
908      <xsl:apply-templates select="@*" mode="copyAttributes"/>
909      <!-- Add all the svg attributes of the <line> instruction to the <g> element -->
910
911      <!-- For each way -->
912      <xsl:apply-templates select="$elements" mode="area">
913        <xsl:with-param name="instruction" select="$instruction"/>
914      </xsl:apply-templates>
915    </g>
916  </xsl:template>
917
918
919  <!-- Discard anything that is not matched by a more specific template -->
920  <xsl:template match="*" mode="area"/>
921
922
923  <!-- Draw area for a <way> -->
924  <xsl:template match="way" mode="area">
925    <xsl:param name="instruction"/>
926
927    <!-- DODI:  removed because duplicate definition generated if area referenced 2 or more times -->
928    <!-- DODI:  reenabled because of "duplicate point detection in lines2curves.pl " -->
929    <!-- <xsl:call-template name="generateAreaPath"/> -->
930
931    <xsl:variable name="pathArea">
932      <xsl:call-template name="generateAreaPath"/>
933    </xsl:variable>
934
935    <!-- DODI: do now draw empty ways/areas-->
936    <xsl:if test ="$pathArea!=''">
937      <path id="area_{@id}" d="{$pathArea}"/>
938      <xsl:call-template name="renderArea">
939        <xsl:with-param name="instruction" select="$instruction"/>
940        <xsl:with-param name="pathId" select="concat('area_',@id)"/>
941      </xsl:call-template>
942    </xsl:if>
943  </xsl:template>
944
945
946  <!-- Process <circle> instruction -->
947  <xsl:template match="circle">
948    <xsl:param name="elements"/>
949    <xsl:param name="layer"/>
950
951    <!-- This is the instruction that is currently being processed -->
952    <xsl:variable name="instruction" select="."/>
953
954    <!-- For each circle -->
955    <xsl:apply-templates select="$elements" mode="circle">
956      <xsl:with-param name="instruction" select="$instruction"/>
957      <xsl:with-param name="layer" select="$layer"/>
958      <xsl:with-param name="elements" select="$elements"/>
959    </xsl:apply-templates>
960  </xsl:template>
961
962
963  <!-- Suppress output of any unhandled elements -->
964  <xsl:template match="*" mode="circle"/>
965
966
967  <!-- Draw circle for a node -->
968  <xsl:template match="node" mode="circle">
969    <xsl:param name="instruction"/>
970    <xsl:param name="elements"/>
971
972    <xsl:for-each select="$elements[name()='node']">
973      <xsl:call-template name="drawCircle">
974        <xsl:with-param name="instruction" select="$instruction"/>
975      </xsl:call-template>
976    </xsl:for-each>
977
978  </xsl:template>
979
980
981  <!-- Draw circle for a relation -->
982  <xsl:template match="relation" mode="circle">
983    <xsl:param name="instruction"/>
984    <xsl:param name="layer"/>
985
986    <xsl:variable name="relation" select="@id"/>
987
988    <xsl:if test="(tag[@k='type']/@v='route') and ($showRelationRoute!='~|no')">
989      <!-- Draw Circles for a RelationRoute Stop -->
990      <xsl:for-each select="$data/osm/relation[@id=$relation]/member[@type='node']">
991        <xsl:variable name="nodeid" select="@ref"/>
992
993        <xsl:for-each select="$data/osm/node[@id=$nodeid]">
994          <xsl:call-template name="drawCircle">
995            <xsl:with-param name="instruction" select="$instruction"/>
996            <xsl:with-param name="node" select="@id"/>
997          </xsl:call-template>
998        </xsl:for-each>
999      </xsl:for-each>
1000    </xsl:if>
1001
1002    <!-- Handle other types of Relations if necessary -->
1003
1004  </xsl:template>
1005
1006
1007  <!-- Process a <symbol> instruction -->
1008  <xsl:template match="symbol">
1009    <xsl:param name="elements"/>
1010
1011    <!-- This is the instruction that is currently being processed -->
1012    <xsl:variable name="instruction" select="."/>
1013
1014    <xsl:for-each select="$elements[name()='node']">
1015      <xsl:call-template name="drawSymbol">
1016        <xsl:with-param name="instruction" select="$instruction"/>
1017      </xsl:call-template>
1018    </xsl:for-each>
1019
1020  </xsl:template>
1021
1022  <!-- wayMarker instruction.  Draws a marker on a node that is perpendicular to a way that passes through the node.
1023       If more than one way passes through the node then the result is a bit unspecified.  -->
1024  <xsl:template match="wayMarker">
1025    <xsl:param name="elements"/>
1026   
1027    <!-- This is the instruction that is currently being processed -->
1028    <xsl:variable name="instruction" select="."/>
1029   
1030    <g>
1031      <!-- Add all the svg attributes of the <wayMarker> instruction to the <g> element -->
1032      <xsl:apply-templates select="@*" mode="copyAttributes" />
1033     
1034      <!-- Process each matched node in turn -->
1035      <xsl:for-each select="$elements[name()='node']">
1036        <xsl:variable name='nodeId' select="@id" />
1037       
1038        <xsl:variable name='way' select="key('wayByNode', @id)" />
1039        <xsl:variable name='previousNode' select="key('nodeById', $way/nd[@ref=$nodeId]/preceding-sibling::nd[1]/@ref)" />
1040        <xsl:variable name='nextNode' select="key('nodeById', $way/nd[@ref=$nodeId]/following-sibling::nd[1]/@ref)" />
1041       
1042        <xsl:variable name='path'>
1043          <xsl:choose>
1044            <xsl:when test='$previousNode and $nextNode'>
1045              <xsl:call-template name="moveToNode">
1046                <xsl:with-param name="node" select="$previousNode"/>
1047              </xsl:call-template>
1048              <xsl:call-template name="lineToNode">
1049                <xsl:with-param name="node" select="."/>
1050              </xsl:call-template>
1051              <xsl:call-template name="lineToNode">
1052                <xsl:with-param name="node" select="$nextNode"/>
1053              </xsl:call-template>
1054            </xsl:when>
1055
1056            <xsl:when test='$previousNode'>
1057              <xsl:call-template name="moveToNode">
1058                <xsl:with-param name="node" select="$previousNode"/>
1059              </xsl:call-template>
1060              <xsl:call-template name="lineToNode">
1061                <xsl:with-param name="node" select="."/>
1062              </xsl:call-template>
1063              <xsl:call-template name="lineToNode">
1064                <xsl:with-param name="node" select="."/>
1065              </xsl:call-template>
1066            </xsl:when>
1067
1068            <xsl:when test='$nextNode'>
1069              <xsl:call-template name="moveToNode">
1070                <xsl:with-param name="node" select="."/>
1071              </xsl:call-template>
1072              <xsl:call-template name="lineToNode">
1073                <xsl:with-param name="node" select="$nextNode"/>
1074              </xsl:call-template>
1075              <xsl:call-template name="lineToNode">
1076                <xsl:with-param name="node" select="$nextNode"/>
1077              </xsl:call-template>
1078            </xsl:when>
1079          </xsl:choose>
1080        </xsl:variable>
1081       
1082        <path id="nodePath_{@id}" d="{$path}"/>
1083       
1084        <use xlink:href="#nodePath_{@id}">
1085          <xsl:apply-templates select="$instruction/@*" mode="copyAttributes" />
1086        </use>
1087      </xsl:for-each>
1088    </g>
1089   
1090  </xsl:template>
1091
1092  <!-- Process an <areaText> instruction -->
1093  <xsl:template match="areaText">
1094    <xsl:param name="elements"/>
1095
1096    <!-- This is the instruction that is currently being processed -->
1097    <xsl:variable name="instruction" select="."/>
1098
1099    <!-- Select all <way> elements that have a key that matches the k attribute of the text instruction -->
1100    <xsl:apply-templates select="$elements[name()='way'][tag[@k=$instruction/@k]]" mode="areaTextPath">
1101      <xsl:with-param name="instruction" select="$instruction"/>
1102    </xsl:apply-templates>
1103  </xsl:template>
1104
1105
1106  <xsl:template match="*" mode="areaTextPath"/>
1107
1108
1109  <xsl:template match="way" mode="areaTextPath">
1110    <xsl:param name="instruction"/>
1111
1112    <!-- The current <way> element -->
1113    <xsl:variable name="way" select="."/>
1114
1115    <xsl:call-template name="renderAreaText">
1116      <xsl:with-param name="instruction" select="$instruction"/>
1117      <xsl:with-param name="pathId" select="concat('way_normal_',@id)"/>
1118    </xsl:call-template>
1119
1120  </xsl:template>
1121
1122
1123  <xsl:template name="renderAreaText">
1124    <xsl:param name="instruction"/>
1125
1126    <xsl:variable name='center'>
1127      <xsl:call-template name="areaCenter">
1128        <xsl:with-param name="element" select="." />
1129      </xsl:call-template>
1130    </xsl:variable>
1131
1132    <xsl:variable name="centerLon" select="substring-before($center, ',')" />
1133    <xsl:variable name="centerLat" select="substring-after($center, ',')" />
1134
1135    <xsl:variable name="x" select="($width)-((($topRightLongitude)-($centerLon))*10000*$scale)"/>
1136    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-($centerLat))*10000*$scale*$projection)"/>
1137
1138    <text>
1139      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
1140      <xsl:attribute name="x">
1141        <xsl:value-of select="$x"/>
1142      </xsl:attribute>
1143      <xsl:attribute name="y">
1144        <xsl:value-of select="$y"/>
1145      </xsl:attribute>
1146      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
1147      <xsl:value-of select="tag[@k=$instruction/@k]/@v"/>
1148    </text>
1149  </xsl:template>
1150
1151  <!-- Process an <areaSymbol> instruction -->
1152  <xsl:template match="areaSymbol">
1153    <xsl:param name="elements"/>
1154
1155    <!-- This is the instruction that is currently being processed -->
1156    <xsl:variable name="instruction" select="."/>
1157
1158    <!-- Select all <way> elements -->
1159    <xsl:apply-templates select="$elements[name()='way']" mode="areaSymbolPath">
1160      <xsl:with-param name="instruction" select="$instruction"/>
1161    </xsl:apply-templates>
1162  </xsl:template>
1163
1164
1165  <xsl:template match="*" mode="areaSymbolPath"/>
1166
1167
1168  <xsl:template match="way" mode="areaSymbolPath">
1169    <xsl:param name="instruction"/>
1170
1171    <!-- The current <way> element -->
1172    <xsl:variable name="way" select="."/>
1173
1174    <xsl:call-template name="renderAreaSymbol">
1175      <xsl:with-param name="instruction" select="$instruction"/>
1176      <xsl:with-param name="pathId" select="concat('way_normal_',@id)"/>
1177    </xsl:call-template>
1178
1179  </xsl:template>
1180
1181
1182  <xsl:template name="renderAreaSymbol">
1183    <xsl:param name="instruction"/>
1184
1185    <xsl:variable name='center'>
1186      <xsl:call-template name="areaCenter">
1187        <xsl:with-param name="element" select="." />
1188      </xsl:call-template>
1189    </xsl:variable>
1190
1191    <xsl:message>
1192      areaCenter: <xsl:value-of select="$center" />
1193    </xsl:message>
1194
1195    <xsl:variable name="centerLon" select="substring-before($center, ',')" />
1196    <xsl:variable name="centerLat" select="substring-after($center, ',')" />
1197
1198    <xsl:variable name="x" select="($width)-((($topRightLongitude)-($centerLon))*10000*$scale)"/>
1199    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-($centerLat))*10000*$scale*$projection)"/>
1200
1201    <g transform="translate({$x},{$y}) scale({$symbolScale})">
1202      <use>
1203        <xsl:if test="$instruction/@ref">
1204          <xsl:attribute name="xlink:href">
1205            <xsl:value-of select="concat('#symbol-', $instruction/@ref)"/>
1206          </xsl:attribute>
1207        </xsl:if>
1208        <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
1209        <!-- Copy all the attributes from the <symbol> instruction -->
1210      </use>
1211    </g>
1212  </xsl:template>
1213
1214  <!--
1215      areaCenter: Find a good center point for label/icon placement inside of polygon.
1216      Algorithm is described at http://bob.cakebox.net/poly-center.php
1217  -->
1218  <xsl:template name="areaCenter">
1219    <xsl:param name="element" />
1220
1221    <!-- Get multipolygon relation for areas with holes -->
1222    <xsl:variable name='holerelation' select="key('relationByWay',$element/@id)[tag[@k='type' and @v='multipolygon']]"/>
1223
1224    <!-- A semicolon-separated list of x,y coordinate pairs of points lying halfway into the polygon at angles to the vertex -->
1225    <xsl:variable name="points">
1226      <xsl:call-template name="areacenterPointsInside">
1227        <xsl:with-param name="element" select="$element" />
1228        <xsl:with-param name="holerelation" select="$holerelation" />
1229      </xsl:call-template>
1230    </xsl:variable>
1231
1232    <!-- x,y calculated by a simple average over all x/y's in points -->
1233    <xsl:variable name="mediumpoint">
1234      <xsl:call-template name="areacenterMediumOfPoints">
1235        <xsl:with-param name="points" select="$points" />
1236      </xsl:call-template>
1237    </xsl:variable>
1238    <xsl:variable name="mediumpoint_x" select="substring-before($mediumpoint, ',')" />
1239    <xsl:variable name="mediumpoint_y" select="substring-before(substring-after($mediumpoint, ','), ',')" />
1240    <xsl:variable name="medium_dist" select="substring-after(substring-after($mediumpoint, ','), ',')" />
1241
1242    <!-- Find out if mediumpoint is inside or outside the polygon -->
1243    <xsl:variable name="intersection">
1244      <xsl:call-template name="areacenterNearestIntersectionInside">
1245        <xsl:with-param name="x" select="$mediumpoint_x" />
1246        <xsl:with-param name="y" select="$mediumpoint_y" />
1247        <xsl:with-param name="edgestart" select="$element/nd[1]" />
1248        <xsl:with-param name="linepoint_x" select="$mediumpoint_x" />
1249        <xsl:with-param name="linepoint_y" select="$mediumpoint_y + 1" />
1250        <xsl:with-param name="holerelation" select="$holerelation" />
1251      </xsl:call-template>
1252    </xsl:variable>
1253    <xsl:variable name="intersection_count" select="substring-before($intersection, ';')" />
1254
1255    <xsl:variable name="nearestEdge">
1256      <xsl:call-template name="areacenterNearestEdge">
1257        <xsl:with-param name="x" select="$mediumpoint_x" />
1258        <xsl:with-param name="y" select="$mediumpoint_y" />
1259        <xsl:with-param name="edgestart" select="$element/nd[1]" />
1260        <xsl:with-param name="holerelation" select="$holerelation" />
1261      </xsl:call-template>
1262    </xsl:variable>
1263
1264    <xsl:choose>
1265      <xsl:when test="$intersection_count mod 2 = 0 or $nearestEdge div 2 * 1.20 &gt; $medium_dist">
1266        <!-- Find the best point in $points to use -->
1267        <xsl:call-template name="areacenterBestPoint">
1268          <xsl:with-param name="points" select="$points" />
1269          <xsl:with-param name="x" select="$mediumpoint_x" />
1270          <xsl:with-param name="y" select="$mediumpoint_y" />
1271          <xsl:with-param name="medium_dist" select="$medium_dist" />
1272        </xsl:call-template>
1273      </xsl:when>
1274      <xsl:otherwise>
1275        <xsl:value-of select="$mediumpoint_x"/>,<xsl:value-of select="$mediumpoint_y"/>
1276      </xsl:otherwise>
1277    </xsl:choose>
1278  </xsl:template>
1279
1280  <!-- Returns a semicolon-separated list of x,y pairs -->
1281  <xsl:template name="areacenterPointsInside">
1282    <xsl:param name="element" />
1283    <xsl:param name="holerelation" />
1284
1285    <!-- iterate over every vertex except the first one, which is also the last -->
1286    <xsl:for-each select="$element/nd[position() &gt; 1]">
1287      <xsl:variable name="vertex" select="." />
1288      <xsl:variable name="prev" select="$vertex/preceding-sibling::nd[1]" />
1289      <xsl:variable name="nextId">
1290        <xsl:choose>
1291          <xsl:when test="position() &lt; last()">
1292            <xsl:value-of select="$vertex/following-sibling::nd[1]/@ref" />
1293          </xsl:when>
1294          <xsl:otherwise>
1295            <xsl:value-of select="$vertex/../nd[2]/@ref" />
1296          </xsl:otherwise>
1297        </xsl:choose>
1298      </xsl:variable>
1299      <xsl:variable name="next" select="$vertex/../nd[@ref=$nextId]" />
1300
1301      <!-- Angle at between $prev and $next in $vertex -->
1302      <xsl:variable name="angle">
1303        <xsl:call-template name="angleThroughPoints">
1304          <xsl:with-param name="from" select="key('nodeById', $prev/@ref)" />
1305          <xsl:with-param name="through" select="key('nodeById', $vertex/@ref)" />
1306          <xsl:with-param name="to" select="key('nodeById', $next/@ref)" />
1307        </xsl:call-template>
1308      </xsl:variable>
1309
1310      <!-- Calculate a point on the line going through $vertex at $angle -->
1311      <xsl:variable name="linepoint">
1312        <xsl:call-template name="areacenterLinepoint">
1313          <xsl:with-param name="point" select="key('nodeById', $vertex/@ref)" />
1314          <xsl:with-param name="angle" select="$angle" />
1315        </xsl:call-template>
1316      </xsl:variable>
1317      <xsl:variable name="linepoint_x" select="substring-before($linepoint, ',')" />
1318      <xsl:variable name="linepoint_y" select="substring-after($linepoint, ',')" />
1319
1320      <!-- Find the nearest intersection between the line vertex-linepoint and the nearest edge inwards into the polygon -->
1321      <xsl:variable name="intersection">
1322        <xsl:call-template name="areacenterNearestIntersectionInside">
1323          <xsl:with-param name="x" select="key('nodeById', $vertex/@ref)/@lon" />
1324          <xsl:with-param name="y" select="key('nodeById', $vertex/@ref)/@lat" />
1325          <xsl:with-param name="edgestart" select="../nd[1]" />
1326          <xsl:with-param name="linepoint_x" select="$linepoint_x" />
1327          <xsl:with-param name="linepoint_y" select="$linepoint_y" />
1328          <xsl:with-param name="holerelation" select="$holerelation" />
1329        </xsl:call-template>
1330      </xsl:variable>
1331      <xsl:variable name="intersection_count" select="substring-before($intersection, ';')" />
1332      <xsl:variable name="intersection_data">
1333        <xsl:choose>
1334          <xsl:when test="$intersection_count mod 2 != 0">
1335            <xsl:value-of select="substring-before(substring-after($intersection, ';'), ';')" />
1336          </xsl:when>
1337          <xsl:otherwise>
1338            <xsl:value-of select="substring-after(substring-after($intersection, ';'), ';')" />
1339          </xsl:otherwise>
1340        </xsl:choose>
1341      </xsl:variable>
1342      <xsl:variable name="intersection_x" select="substring-before($intersection_data, ',')" />
1343      <xsl:variable name="intersection_y" select="substring-before(substring-after($intersection_data, ','), ',')" />
1344      <xsl:variable name="intersection_dist" select="substring-before(substring-after(substring-after($intersection_data, ','), ','), ',')" />
1345
1346      <xsl:variable name="point_x" select="key('nodeById', $vertex/@ref)/@lon + ( $intersection_x - key('nodeById', $vertex/@ref)/@lon ) div 2" />
1347      <xsl:variable name="point_y" select="key('nodeById', $vertex/@ref)/@lat + ( $intersection_y - key('nodeById', $vertex/@ref)/@lat ) div 2" />
1348     
1349      <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 -->
1350        <!-- Note: this will produce trailing semicolon, which is nice as it simplifies looping over this later -->
1351        <xsl:value-of select="$point_x" />,<xsl:value-of select="$point_y" />,<xsl:value-of select="$intersection_dist" />;
1352      </xsl:if>
1353    </xsl:for-each>
1354  </xsl:template>
1355
1356  <!-- Calculate the angle between $from and $to in $through. Returns answer in radians -->
1357  <xsl:template name="angleThroughPoints">
1358    <xsl:param name="from" />
1359    <xsl:param name="through" />
1360    <xsl:param name="to" />
1361
1362    <xsl:variable name="from_x" select="($from/@lon) - ($through/@lon)" />
1363    <xsl:variable name="from_y" select="$from/@lat - $through/@lat" />
1364    <xsl:variable name="to_x" select="$to/@lon - $through/@lon" />
1365    <xsl:variable name="to_y" select="$to/@lat - $through/@lat" />
1366
1367    <xsl:variable name="from_angle_">
1368      <xsl:call-template name="atan2">
1369        <xsl:with-param name="x" select="$from_x" />
1370        <xsl:with-param name="y" select="$from_y" />
1371      </xsl:call-template>
1372    </xsl:variable>
1373    <xsl:variable name="from_angle" select="$from_angle_ + $pi" />
1374    <xsl:variable name="to_angle_">
1375      <xsl:call-template name="atan2">
1376        <xsl:with-param name="x" select="$to_x" />
1377        <xsl:with-param name="y" select="$to_y" />
1378      </xsl:call-template>
1379    </xsl:variable>
1380    <xsl:variable name="to_angle" select="$to_angle_ + $pi" />
1381
1382    <xsl:variable name="min_angle">
1383      <xsl:choose>
1384        <xsl:when test="$from_angle &gt; $to_angle">
1385          <xsl:value-of select="$to_angle" />
1386        </xsl:when>
1387        <xsl:otherwise>
1388          <xsl:value-of select="$from_angle" />
1389        </xsl:otherwise>
1390      </xsl:choose>
1391    </xsl:variable>
1392    <xsl:variable name="max_angle">
1393      <xsl:choose>
1394        <xsl:when test="$from_angle &gt; $to_angle">
1395          <xsl:value-of select="$from_angle" />
1396        </xsl:when>
1397        <xsl:otherwise>
1398          <xsl:value-of select="$to_angle" />
1399        </xsl:otherwise>
1400      </xsl:choose>
1401    </xsl:variable>
1402
1403    <xsl:value-of select="$min_angle + ($max_angle - $min_angle) div 2" />
1404  </xsl:template>
1405
1406  <!-- atan2 implementation from http://lists.fourthought.com/pipermail/exslt/2007-March/001540.html -->
1407  <xsl:template name="atan2">
1408    <xsl:param name="y"/>
1409    <xsl:param name="x"/>
1410    <!-- http://lists.apple.com/archives/PerfOptimization-dev/2005/Jan/msg00051.html -->
1411    <xsl:variable name="PI"    select="number(3.1415926535897)"/>
1412    <xsl:variable name="PIBY2" select="$PI div 2.0"/>
1413    <xsl:choose>
1414      <xsl:when test="$x = 0.0">
1415        <xsl:choose>
1416          <xsl:when test="($y &gt; 0.0)">
1417            <xsl:value-of select="$PIBY2"/>
1418          </xsl:when>
1419          <xsl:when test="($y &lt; 0.0)">
1420            <xsl:value-of select="-$PIBY2"/>
1421          </xsl:when>
1422          <xsl:otherwise>
1423            <!-- Error: Degenerate x == y == 0.0 -->
1424            <xsl:value-of select="number(NaN)"/>
1425          </xsl:otherwise>
1426        </xsl:choose>
1427      </xsl:when>
1428      <xsl:otherwise>
1429        <xsl:variable name="z" select="$y div $x"/>
1430        <xsl:variable name="absZ">
1431          <!-- inline abs function -->
1432          <xsl:choose>
1433            <xsl:when test="$z &lt; 0.0">
1434              <xsl:value-of select="- number($z)"/>
1435            </xsl:when>
1436            <xsl:otherwise>
1437              <xsl:value-of select="number($z)"/>
1438            </xsl:otherwise>
1439          </xsl:choose>
1440        </xsl:variable>
1441        <xsl:choose>
1442          <xsl:when test="($absZ &lt; 1.0)">
1443            <xsl:variable name="f1Z" select="$z div (1.0 + 0.28*$z*$z)"/>
1444            <xsl:choose>
1445              <xsl:when test="($x &lt; 0.0) and ($y &lt; 0.0)">
1446                <xsl:value-of select="$f1Z - $PI"/>
1447              </xsl:when>
1448              <xsl:when test="($x &lt; 0.0)">
1449                <xsl:value-of select="$f1Z + $PI"/>
1450              </xsl:when>
1451              <xsl:otherwise>
1452                <xsl:value-of select="$f1Z"/>
1453              </xsl:otherwise>
1454            </xsl:choose>
1455          </xsl:when>
1456          <xsl:otherwise>
1457            <xsl:variable name="f2Z" select="$PIBY2 - ($z div ($z*$z +
14580.28))"/>
1459            <xsl:choose>
1460              <xsl:when test="($y &lt; 0.0)">
1461                <xsl:value-of select="$f2Z - $PI"/>
1462              </xsl:when>
1463              <xsl:otherwise>
1464                <xsl:value-of select="$f2Z"/>
1465              </xsl:otherwise>
1466            </xsl:choose>
1467          </xsl:otherwise>
1468        </xsl:choose>
1469      </xsl:otherwise>
1470    </xsl:choose>
1471  </xsl:template>
1472
1473  <!-- Find a point on the line going through $point at $angle that's guaranteed to be outside the polygon -->
1474  <xsl:template name="areacenterLinepoint">
1475    <xsl:param name="point" />
1476    <xsl:param name="angle" />
1477
1478    <xsl:variable name="cos_angle">
1479      <xsl:call-template name="cos">
1480        <xsl:with-param name="angle" select="$angle"/>
1481      </xsl:call-template>
1482    </xsl:variable>
1483   
1484    <xsl:variable name="sin_angle">
1485      <xsl:call-template name="sin">
1486        <xsl:with-param name="angle" select="$angle"/>
1487      </xsl:call-template>
1488    </xsl:variable>
1489   
1490    <xsl:value-of select="$point/@lon + $cos_angle"/>, <xsl:value-of select="$point/@lat + $sin_angle"/>
1491  </xsl:template>
1492 
1493  <!-- Constants for trig templates -->
1494  <xsl:variable name="pi" select="3.1415926535897"/>
1495  <xsl:variable name="halfPi" select="$pi div 2"/>
1496  <xsl:variable name="twicePi" select="$pi*2"/>
1497
1498  <xsl:template name="sin">
1499    <xsl:param name="angle" />
1500    <xsl:param name="precision" select="0.00000001"/>
1501
1502    <xsl:variable name="y">
1503      <xsl:choose>
1504        <xsl:when test="not(0 &lt;= $angle and $twicePi > $angle)">
1505          <xsl:call-template name="cutIntervals">
1506            <xsl:with-param name="length" select="$twicePi"/>
1507            <xsl:with-param name="angle" select="$angle"/>
1508          </xsl:call-template>
1509        </xsl:when>
1510        <xsl:otherwise>
1511          <xsl:value-of select="$angle"/>
1512        </xsl:otherwise>
1513      </xsl:choose>
1514    </xsl:variable>
1515
1516    <xsl:call-template name="sineIter">
1517      <xsl:with-param name="angle2" select="$y*$y"/>
1518      <xsl:with-param name="res" select="$y"/>
1519      <xsl:with-param name="elem" select="$y"/>
1520      <xsl:with-param name="n" select="1"/>
1521      <xsl:with-param name="precision" select="$precision" />
1522    </xsl:call-template>
1523  </xsl:template>
1524
1525  <xsl:template name="sineIter">
1526    <xsl:param name="angle2" />
1527    <xsl:param name="res" />
1528    <xsl:param name="elem" />
1529    <xsl:param name="n" />
1530    <xsl:param name="precision"/>
1531
1532    <xsl:variable name="nextN" select="$n+2" />
1533    <xsl:variable name="newElem" select="-$elem*$angle2 div ($nextN*($nextN - 1))" />
1534    <xsl:variable name="newResult" select="$res + $newElem" />
1535    <xsl:variable name="diffResult" select="$newResult - $res" />
1536
1537    <xsl:choose>
1538      <xsl:when test="$diffResult > $precision or $diffResult &lt; -$precision">
1539        <xsl:call-template name="sineIter">
1540          <xsl:with-param name="angle2" select="$angle2" />
1541          <xsl:with-param name="res" select="$newResult" />
1542          <xsl:with-param name="elem" select="$newElem" />
1543          <xsl:with-param name="n" select="$nextN" />
1544          <xsl:with-param name="precision" select="$precision" />
1545        </xsl:call-template>
1546      </xsl:when>
1547      <xsl:otherwise>
1548        <xsl:value-of select="$newResult"/>
1549      </xsl:otherwise>
1550    </xsl:choose>
1551  </xsl:template>
1552
1553  <xsl:template name="cutIntervals">
1554    <xsl:param name="length"/>
1555    <xsl:param name="angle"/>
1556
1557    <xsl:variable name="vsign">
1558      <xsl:choose>
1559        <xsl:when test="$angle >= 0">1</xsl:when>
1560        <xsl:otherwise>-1</xsl:otherwise>
1561      </xsl:choose>
1562    </xsl:variable>
1563    <xsl:variable name="vdiff" select="$length*floor($angle div $length) -$angle"/> 
1564    <xsl:choose>
1565      <xsl:when test="$vdiff*$angle > 0">
1566        <xsl:value-of select="$vsign*$vdiff"/>
1567      </xsl:when>
1568      <xsl:otherwise>
1569        <xsl:value-of select="-$vsign*$vdiff"/>
1570      </xsl:otherwise>
1571    </xsl:choose>
1572  </xsl:template>
1573
1574  <xsl:template name="cos">
1575    <xsl:param name="angle" />
1576    <xsl:param name="precision" select="0.00000001"/>
1577
1578    <xsl:call-template name="sin">
1579      <xsl:with-param name="angle" select="$halfPi - $angle" />
1580      <xsl:with-param name="precision" select="$precision" />
1581    </xsl:call-template>
1582  </xsl:template>
1583
1584  <!-- Find the nearest intersection into the polygon along the line ($x,$y)-$linepoint.
1585       Can also be used for ray-casting point-in-polygon checking -->
1586  <xsl:template name="areacenterNearestIntersectionInside">
1587    <xsl:param name="x" />
1588    <xsl:param name="y" />
1589    <xsl:param name="edgestart" />
1590    <xsl:param name="linepoint_x" />
1591    <xsl:param name="linepoint_y" />
1592    <xsl:param name="holerelation" />
1593    <xsl:param name="intersectioncount_on" select="0" /><!-- Number of intersections. Only counts those on segment (x,y)-linepoint -->
1594    <xsl:param name="nearest_on_x" />
1595    <xsl:param name="nearest_on_y" />
1596    <xsl:param name="nearest_on_dist" select="'NaN'" />
1597    <xsl:param name="nearest_off_x" />
1598    <xsl:param name="nearest_off_y" />
1599    <xsl:param name="nearest_off_dist" select="'NaN'" />
1600
1601    <xsl:choose>
1602      <!-- If there are no more vertices we don't have a second point for the edge, and are finished -->
1603      <xsl:when test="$edgestart/following-sibling::nd[1]">
1604        <xsl:variable name="edgeend" select="$edgestart/following-sibling::nd[1]" />
1605        <!-- Get the intersection point between the line ($x,$y)-$linepoint and $edgestart-$edgeend -->
1606        <xsl:variable name="intersection">
1607          <xsl:choose>
1608            <xsl:when test="( $x = key('nodeById', $edgestart/@ref)/@lon and $y = key('nodeById', $edgestart/@ref)/@lat ) or
1609                            ( $x = key('nodeById', $edgeend/@ref)/@lon and $y = key('nodeById', $edgeend/@ref)/@lat )">
1610              <!-- (x,y) is one of the points in edge, skip -->
1611              NoIntersection
1612            </xsl:when>
1613            <xsl:otherwise>     
1614              <xsl:call-template name="areacenterLinesIntersection">
1615                <xsl:with-param name="x1" select="$x" />
1616                <xsl:with-param name="y1" select="$y" />
1617                <xsl:with-param name="x2" select="$linepoint_x" />
1618                <xsl:with-param name="y2" select="$linepoint_y" />
1619                <xsl:with-param name="x3" select="key('nodeById', $edgestart/@ref)/@lon" />
1620                <xsl:with-param name="y3" select="key('nodeById', $edgestart/@ref)/@lat" />
1621                <xsl:with-param name="x4" select="key('nodeById', $edgeend/@ref)/@lon" />
1622                <xsl:with-param name="y4" select="key('nodeById', $edgeend/@ref)/@lat" />
1623              </xsl:call-template>
1624            </xsl:otherwise>
1625          </xsl:choose>
1626        </xsl:variable>
1627
1628        <!-- Haul ix, iy, ua and ub out of the csv -->
1629        <xsl:variable name="ix" select="substring-before($intersection, ',')" />
1630        <xsl:variable name="iy" select="substring-before(substring-after($intersection, ','), ',')" />
1631        <xsl:variable name="ua" select="substring-before(substring-after(substring-after($intersection, ','), ','), ',')" />
1632        <xsl:variable name="ub" select="substring-after(substring-after(substring-after($intersection, ','), ','), ',')" />
1633
1634        <!-- A) Is there actually an intersection? B) Is it on edge? -->
1635        <xsl:choose>
1636          <xsl:when test="$intersection != 'NoIntersection' and $ub &gt; 0 and $ub &lt;= 1">
1637            <xsl:variable name="distance">
1638              <xsl:call-template name="areacenterPointDistance">
1639                <xsl:with-param name="x1" select="$x" />
1640                <xsl:with-param name="y1" select="$y" />
1641                <xsl:with-param name="x2" select="$ix" />
1642                <xsl:with-param name="y2" select="$iy" />
1643              </xsl:call-template>
1644            </xsl:variable>
1645
1646            <!-- Is intersection on the segment ($x,$y)-$linepoint, or on the other side of ($x,$y)? -->
1647            <xsl:variable name="isOnSegment">
1648              <xsl:if test="$ua &gt;= 0">Yes</xsl:if>
1649            </xsl:variable>
1650           
1651            <xsl:variable name="isNewNearestOn">
1652              <xsl:if test="$isOnSegment = 'Yes' and ( $nearest_on_dist = 'NaN' or $distance &lt; $nearest_on_dist )">Yes</xsl:if>
1653            </xsl:variable>
1654           
1655            <xsl:variable name="isNewNearestOff">
1656              <xsl:if test="$isOnSegment != 'Yes' and ( $nearest_off_dist = 'NaN' or $distance &lt; $nearest_off_dist )">Yes</xsl:if>
1657            </xsl:variable>
1658
1659            <xsl:call-template name="areacenterNearestIntersectionInside">
1660              <xsl:with-param name="x" select="$x" />
1661              <xsl:with-param name="y" select="$y" />
1662              <xsl:with-param name="linepoint_x" select="$linepoint_x" />
1663              <xsl:with-param name="linepoint_y" select="$linepoint_y" />
1664              <xsl:with-param name="edgestart" select="$edgeend" />
1665              <xsl:with-param name="holerelation" select="$holerelation" />
1666              <xsl:with-param name="intersectioncount_on" select="$intersectioncount_on + number(boolean($isOnSegment = 'Yes'))" />
1667              <xsl:with-param name="nearest_on_dist"> <xsl:choose>
1668                <xsl:when test="$isNewNearestOn = 'Yes'"> <xsl:value-of select="$distance" /> </xsl:when>
1669                <xsl:otherwise> <xsl:value-of select="$nearest_on_dist" /> </xsl:otherwise>
1670              </xsl:choose> </xsl:with-param>
1671              <xsl:with-param name="nearest_on_x"> <xsl:choose>
1672                <xsl:when test="$isNewNearestOn = 'Yes'"> <xsl:value-of select="$ix" /> </xsl:when>
1673                <xsl:otherwise> <xsl:value-of select="$nearest_on_x" /> </xsl:otherwise>
1674              </xsl:choose> </xsl:with-param>
1675              <xsl:with-param name="nearest_on_y"> <xsl:choose>
1676                <xsl:when test="$isNewNearestOn = 'Yes'"> <xsl:value-of select="$iy" /> </xsl:when>
1677                <xsl:otherwise> <xsl:value-of select="$nearest_on_y" /> </xsl:otherwise>
1678              </xsl:choose> </xsl:with-param>
1679              <xsl:with-param name="nearest_off_dist"> <xsl:choose>
1680                <xsl:when test="$isNewNearestOff = 'Yes'"> <xsl:value-of select="$distance" /> </xsl:when>
1681                <xsl:otherwise> <xsl:value-of select="$nearest_off_dist" /> </xsl:otherwise>
1682              </xsl:choose> </xsl:with-param>
1683              <xsl:with-param name="nearest_off_x"> <xsl:choose>
1684                <xsl:when test="$isNewNearestOff = 'Yes'"> <xsl:value-of select="$ix" /> </xsl:when>
1685                <xsl:otherwise> <xsl:value-of select="$nearest_off_x" /> </xsl:otherwise>
1686              </xsl:choose> </xsl:with-param>
1687              <xsl:with-param name="nearest_off_y"> <xsl:choose>
1688                <xsl:when test="$isNewNearestOff = 'Yes'"> <xsl:value-of select="$iy" /> </xsl:when>
1689                <xsl:otherwise> <xsl:value-of select="$nearest_off_y" /> </xsl:otherwise>
1690              </xsl:choose> </xsl:with-param>
1691            </xsl:call-template>
1692          </xsl:when>
1693          <!-- No intersection, just go on to next edge -->
1694          <xsl:otherwise>
1695            <xsl:call-template name="areacenterNearestIntersectionInside">
1696              <xsl:with-param name="x" select="$x" />
1697              <xsl:with-param name="y" select="$y" />
1698              <xsl:with-param name="linepoint_x" select="$linepoint_x" />
1699              <xsl:with-param name="linepoint_y" select="$linepoint_y" />
1700              <xsl:with-param name="edgestart" select="$edgeend" />
1701              <xsl:with-param name="holerelation" select="$holerelation" />
1702              <xsl:with-param name="intersectioncount_on" select="$intersectioncount_on" />
1703              <xsl:with-param name="nearest_on_dist" select="$nearest_on_dist" />
1704              <xsl:with-param name="nearest_on_x" select="$nearest_on_x" />
1705              <xsl:with-param name="nearest_on_y" select="$nearest_on_y" />
1706              <xsl:with-param name="nearest_off_dist" select="$nearest_off_dist" />
1707              <xsl:with-param name="nearest_off_x" select="$nearest_off_x" />
1708              <xsl:with-param name="nearest_off_y" select="$nearest_off_y" />
1709            </xsl:call-template>
1710          </xsl:otherwise>
1711        </xsl:choose>
1712      </xsl:when>
1713      <!-- Is there a hole in the polygon, and were we working on the outer one? Then we start edge detection against the hole. -->
1714      <xsl:when test="$holerelation and
1715                      $holerelation/member[@ref = $edgestart/../@id][@role='outer']">
1716        <xsl:variable name="nextnode" select="key('wayById', $holerelation/member[@type='way'][@role='inner'][1]/@ref)/nd[1]"/>
1717        <xsl:call-template name="areacenterNearestIntersectionInside">
1718          <xsl:with-param name="x" select="$x" />
1719          <xsl:with-param name="y" select="$y" />
1720          <xsl:with-param name="linepoint_x" select="$linepoint_x" />
1721          <xsl:with-param name="linepoint_y" select="$linepoint_y" />
1722          <xsl:with-param name="edgestart" select="$nextnode" />
1723          <xsl:with-param name="holerelation" select="$holerelation" />
1724          <xsl:with-param name="intersectioncount_on" select="$intersectioncount_on" />
1725          <xsl:with-param name="nearest_on_dist" select="$nearest_on_dist" />
1726          <xsl:with-param name="nearest_on_x" select="$nearest_on_x" />
1727          <xsl:with-param name="nearest_on_y" select="$nearest_on_y" />
1728          <xsl:with-param name="nearest_off_dist" select="$nearest_off_dist" />
1729          <xsl:with-param name="nearest_off_x" select="$nearest_off_x" />
1730          <xsl:with-param name="nearest_off_y" select="$nearest_off_y" />
1731        </xsl:call-template>
1732      </xsl:when>
1733      <!-- 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 -->
1734      <xsl:when test="$holerelation and
1735                      $holerelation/member[@ref = $edgestart/../@id][@type='way'][@role='inner']/following-sibling::member[@role='inner']">
1736        <xsl:variable name="nextnode" select="key('wayById', $holerelation/member[@ref = $edgestart/../@id][@type='way'][@role='inner']/following-sibling::member[@role='inner']/@ref)/nd[1]"/>
1737        <xsl:call-template name="areacenterNearestIntersectionInside">
1738          <xsl:with-param name="x" select="$x" />
1739          <xsl:with-param name="y" select="$y" />
1740          <xsl:with-param name="linepoint_x" select="$linepoint_x" />
1741          <xsl:with-param name="linepoint_y" select="$linepoint_y" />
1742          <xsl:with-param name="edgestart" select="$nextnode" />
1743          <xsl:with-param name="holerelation" select="$holerelation" />
1744          <xsl:with-param name="intersectioncount_on" select="$intersectioncount_on" />
1745          <xsl:with-param name="nearest_on_dist" select="$nearest_on_dist" />
1746          <xsl:with-param name="nearest_on_x" select="$nearest_on_x" />
1747          <xsl:with-param name="nearest_on_y" select="$nearest_on_y" />
1748          <xsl:with-param name="nearest_off_dist" select="$nearest_off_dist" />
1749          <xsl:with-param name="nearest_off_x" select="$nearest_off_x" />
1750          <xsl:with-param name="nearest_off_y" select="$nearest_off_y" />
1751        </xsl:call-template>
1752      </xsl:when>
1753      <xsl:otherwise>
1754        <!-- No more edges, return data -->
1755        <xsl:value-of select="$intersectioncount_on" />;
1756        <xsl:value-of select="$nearest_on_x"/>,<xsl:value-of select="$nearest_on_y"/>,<xsl:value-of select="$nearest_on_dist"/>;
1757        <xsl:value-of select="$nearest_off_x"/>,<xsl:value-of select="$nearest_off_y"/>,<xsl:value-of select="$nearest_off_dist"/>;
1758      </xsl:otherwise>
1759    </xsl:choose>
1760  </xsl:template>
1761
1762  <!-- Find the distance to the edge nearest (x,y) -->
1763  <xsl:template name="areacenterNearestEdge">
1764    <xsl:param name="x" />
1765    <xsl:param name="y" />
1766    <xsl:param name="edgestart" />
1767    <xsl:param name="holerelation" />
1768    <xsl:param name="nearest_dist" select="'NaN'" />
1769
1770    <xsl:choose>
1771      <!-- If there are no more vertices we don't have a second point for the edge, and are finished -->
1772      <xsl:when test="$edgestart/following-sibling::nd[1]">
1773        <xsl:variable name="edgeend" select="$edgestart/following-sibling::nd[1]" />
1774
1775        <xsl:variable name="distance">
1776          <xsl:call-template name="areacenterDistancePointSegment">
1777            <xsl:with-param name="x" select="$x" />
1778            <xsl:with-param name="y" select="$y" />
1779            <xsl:with-param name="x1" select="key('nodeById', $edgestart/@ref)/@lon" />
1780            <xsl:with-param name="y1" select="key('nodeById', $edgestart/@ref)/@lat" />
1781            <xsl:with-param name="x2" select="key('nodeById', $edgeend/@ref)/@lon" />
1782            <xsl:with-param name="y2" select="key('nodeById', $edgeend/@ref)/@lat" />
1783          </xsl:call-template>
1784        </xsl:variable>
1785
1786        <!-- Did we get a valid distance?
1787             There is some code in DistancePointSegment that can return NaN in some cases -->
1788        <xsl:choose>
1789          <xsl:when test="string(number($distance)) != 'NaN'">
1790            <xsl:call-template name="areacenterNearestEdge">
1791              <xsl:with-param name="x" select="$x" />
1792              <xsl:with-param name="y" select="$y" />
1793              <xsl:with-param name="edgestart" select="$edgeend" />
1794              <xsl:with-param name="holerelation" select="$holerelation" />
1795              <xsl:with-param name="nearest_dist"> <xsl:choose>
1796                <xsl:when test="$nearest_dist = 'NaN' or $distance &lt; $nearest_dist"> <xsl:value-of select="$distance" /> </xsl:when>
1797                <xsl:otherwise> <xsl:value-of select="$nearest_dist" /> </xsl:otherwise>
1798              </xsl:choose> </xsl:with-param>
1799            </xsl:call-template>
1800          </xsl:when>
1801
1802          <xsl:otherwise>
1803            <xsl:call-template name="areacenterNearestEdge">
1804              <xsl:with-param name="x" select="$x" />
1805              <xsl:with-param name="y" select="$y" />
1806              <xsl:with-param name="edgestart" select="$edgeend" />
1807              <xsl:with-param name="holerelation" select="$holerelation" />
1808              <xsl:with-param name="nearest_dist" select="$nearest_dist" />
1809            </xsl:call-template>
1810          </xsl:otherwise>
1811        </xsl:choose>
1812      </xsl:when>
1813      <!-- Is there a hole in the polygon, and were we working on the outer one? Then we start edge detection against the hole. -->
1814      <xsl:when test="$holerelation and
1815                      $holerelation/member[@ref = $edgestart/../@id][@role='outer']">
1816        <xsl:variable name="nextnode" select="key('wayById', $holerelation/member[@type='way'][@role='inner'][1]/@ref)/nd[1]"/>
1817        <xsl:call-template name="areacenterNearestEdge">
1818          <xsl:with-param name="x" select="$x" />
1819          <xsl:with-param name="y" select="$y" />
1820          <xsl:with-param name="edgestart" select="$nextnode" />
1821          <xsl:with-param name="holerelation" select="$holerelation" />
1822          <xsl:with-param name="nearest_dist" select="$nearest_dist" />
1823        </xsl:call-template>
1824      </xsl:when>
1825      <!-- 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 -->
1826      <xsl:when test="$holerelation and
1827                      $holerelation/member[@ref = $edgestart/../@id][@type='way'][@role='inner']/following-sibling::member[@role='inner']">
1828        <xsl:variable name="nextnode" select="key('wayById', $holerelation/member[@ref = $edgestart/../@id][@type='way'][@role='inner']/following-sibling::member[@role='inner']/@ref)/nd[1]"/>
1829        <xsl:call-template name="areacenterNearestEdge">
1830          <xsl:with-param name="x" select="$x" />
1831          <xsl:with-param name="y" select="$y" />
1832          <xsl:with-param name="edgestart" select="$nextnode" />
1833          <xsl:with-param name="holerelation" select="$holerelation" />
1834          <xsl:with-param name="nearest_dist" select="$nearest_dist" />
1835        </xsl:call-template>
1836      </xsl:when>
1837      <xsl:otherwise>
1838        <!-- No more edges, return data -->
1839        <xsl:value-of select="$nearest_dist" />
1840      </xsl:otherwise>
1841    </xsl:choose>
1842  </xsl:template>
1843
1844  <!-- Find the distance between the point (x,y) and the segment x1,y1 -> x2,y2 -->
1845  <!-- Based on http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ and the
1846       Delphi example by Graham O'Brien -->
1847  <xsl:template name="areacenterDistancePointSegment">
1848    <xsl:param name="x" />
1849    <xsl:param name="y" />
1850    <xsl:param name="x1" />
1851    <xsl:param name="y1" />
1852    <xsl:param name="x2" />
1853    <xsl:param name="y2" />
1854
1855    <!-- Constants -->
1856    <xsl:variable name="EPS" select="0.000001" />
1857    <xsl:variable name="EPSEPS" select="$EPS * $EPS" />
1858
1859    <!-- The line magnitude, squared -->
1860    <xsl:variable name="sqLineMagnitude" select="($x2 - $x1) * ($x2 - $x1) + ($y2 - $y1) * ($y2 - $y1)" />
1861
1862    <xsl:choose>
1863      <xsl:when test="sqLineMagnitude &lt; $EPSEPS">
1864        NaN
1865      </xsl:when>
1866      <xsl:otherwise>
1867        <xsl:variable name="u" select="( ($x - $x1)*($x2 - $x1) + ($y - $y1)*($y2 - $y1) ) div sqLineMagnitude" />
1868
1869        <xsl:variable name="result">
1870          <xsl:choose>
1871            <xsl:when test="u &lt; $EPS or u &gt; 1">
1872              <!-- Closest point in not on segment, return shortest distance to an endpoint -->
1873              <xsl:variable name="dist1" select="($x1 - $x) * ($x1 - $x) + ($y1 - $y) * ($y1 - $y)" />
1874              <xsl:variable name="dist2" select="($x2 - $x) * ($x2 - $x) + ($y2 - $y) * ($y2 - $y)" />
1875             
1876              <!-- min($dist1, $dist2) -->
1877              <xsl:choose>
1878                <xsl:when test="$dist1 &lt; $dist2">
1879                  <xsl:value-of select="$dist1" />
1880                </xsl:when>
1881                <xsl:otherwise>
1882                  <xsl:value-of select="$dist2" />
1883                </xsl:otherwise>
1884              </xsl:choose>
1885             
1886            </xsl:when>
1887            <xsl:otherwise>
1888              <xsl:variable name="ix" select="$x1 + $u * ($x2 - $x1)" />
1889              <xsl:variable name="iy" select="$y1 + $u * ($y2 - $y1)" />
1890              <xsl:value-of select="($ix - $x) * ($ix - $x) + ($iy - $y) * ($iy - $y)" />
1891            </xsl:otherwise>
1892          </xsl:choose>
1893        </xsl:variable>
1894
1895        <!-- Finally return the square root of the result, as we were working with squared distances -->
1896        <xsl:call-template name="sqrt">
1897          <xsl:with-param name="num" select="$result" />
1898        </xsl:call-template>
1899      </xsl:otherwise>
1900    </xsl:choose>
1901
1902  </xsl:template>
1903
1904  <!--
1905      Finds intersection point between lines x1,y1 -> x2,y2 and x3,y3 -> x4,y4.
1906      Returns a comma-separated list of x,y,ua,ub or NoIntersection if the lines do not intersect
1907  -->
1908  <xsl:template name="areacenterLinesIntersection">
1909    <xsl:param name="x1" />
1910    <xsl:param name="y1" />
1911    <xsl:param name="x2" />
1912    <xsl:param name="y2" />
1913    <xsl:param name="x3" />
1914    <xsl:param name="y3" />
1915    <xsl:param name="x4" />
1916    <xsl:param name="y4" />
1917
1918    <xsl:variable name="denom" select="(( $y4 - $y3 ) * ( $x2 - $x1 )) -
1919                                       (( $x4 - $x3 ) * ( $y2 - $y1 ))" />
1920    <xsl:variable name="nume_a" select="(( $x4 - $x3 ) * ( $y1 - $y3 )) -
1921                                        (( $y4 - $y3 ) * ( $x1 - $x3 ))" />
1922    <xsl:variable name="nume_b" select="(( $x2 - $x1 ) * ( $y1 - $y3 )) -
1923                                        (( $y2 - $y1 ) * ( $x1 - $x3 ))" />
1924
1925    <xsl:choose>
1926      <xsl:when test="$denom = 0">
1927        NoIntersection
1928      </xsl:when>
1929      <xsl:otherwise>
1930        <xsl:variable name="ua" select="$nume_a div $denom" />
1931        <xsl:variable name="ub" select="$nume_b div $denom" />
1932
1933        <!-- x,y,ua,ub -->
1934        <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" />
1935      </xsl:otherwise>
1936    </xsl:choose>
1937  </xsl:template>
1938
1939  <!-- Distance between two points -->
1940  <xsl:template name="areacenterPointDistance">
1941    <xsl:param name="x1" />
1942    <xsl:param name="y1" />
1943    <xsl:param name="x2" />
1944    <xsl:param name="y2" />
1945
1946    <!-- sqrt( ($x2 - $x1)**2 + ($y2 - $y1)**2 ) -->
1947    <xsl:call-template name="sqrt">
1948      <xsl:with-param name="num" select="($x2*$x2 - $x2*$x1 - $x1*$x2 + $x1*$x1) + ($y2*$y2 - $y2*$y1 - $y1*$y2 + $y1*$y1)" />
1949    </xsl:call-template>
1950  </xsl:template>
1951
1952  <xsl:template name="sqrt">
1953    <xsl:param name="num" select="0"/>  <!-- The number you want to find the
1954                                             square root of -->
1955    <xsl:param name="try" select="1"/>  <!-- The current 'try'.  This is used
1956                                             internally. -->
1957    <xsl:param name="iter" select="1"/> <!-- The current iteration, checked
1958                                             against maxiter to limit loop count -->
1959    <xsl:param name="maxiter" select="10"/>  <!-- Set this up to insure
1960against infinite loops -->
1961   
1962    <!-- This template was written by Nate Austin using Sir Isaac Newton's
1963         method of finding roots -->
1964   
1965    <xsl:choose>
1966      <xsl:when test="$try * $try = $num or $iter &gt; $maxiter">
1967        <xsl:value-of select="$try"/>
1968      </xsl:when>
1969      <xsl:otherwise>
1970        <xsl:call-template name="sqrt">
1971          <xsl:with-param name="num" select="$num"/>
1972          <xsl:with-param name="try" select="$try - (($try * $try - $num) div
1973                                             (2 * $try))"/>
1974          <xsl:with-param name="iter" select="$iter + 1"/>
1975          <xsl:with-param name="maxiter" select="$maxiter"/>
1976        </xsl:call-template>
1977      </xsl:otherwise>
1978    </xsl:choose>
1979  </xsl:template>
1980
1981  <!-- Returns the medium value of all the points -->
1982  <xsl:template name="areacenterMediumOfPoints">
1983    <xsl:param name="points" />
1984    <xsl:param name="total_x" select="0" />
1985    <xsl:param name="total_y" select="0" />
1986    <xsl:param name="total_dist" select="0" />
1987    <xsl:param name="count" select="0" />
1988
1989    <xsl:variable name="point" select="substring-before($points, ';')" />
1990
1991    <xsl:choose>
1992      <xsl:when test="string-length($point) &gt; 0">
1993        <xsl:variable name="x" select="substring-before($point, ',')" />
1994        <xsl:variable name="y" select="substring-before(substring-after($point, ','), ',')" />
1995        <xsl:variable name="dist" select="substring-after(substring-after($point, ','), ',')" />
1996
1997        <xsl:call-template name="areacenterMediumOfPoints">
1998          <xsl:with-param name="points" select="substring-after($points, ';')" />
1999          <xsl:with-param name="total_x" select="$total_x + $x" />
2000          <xsl:with-param name="total_y" select="$total_y + $y" />
2001          <xsl:with-param name="total_dist" select="$total_dist + $dist" />
2002          <xsl:with-param name="count" select="$count + 1" />
2003        </xsl:call-template>
2004      </xsl:when>
2005      <xsl:otherwise>
2006        <xsl:value-of select="$total_x div $count" />,<xsl:value-of select="$total_y div $count" />,<xsl:value-of select="$total_dist div $count" />
2007      </xsl:otherwise>
2008    </xsl:choose>
2009  </xsl:template>
2010
2011  <!-- Returns the coordinates of the point that scores highest.
2012       The score is based on the distance to (x,y),
2013       the distance between the point and it's vertex,
2014       and the medium of that distance in all the points -->
2015  <xsl:template name="areacenterBestPoint">
2016    <xsl:param name="points" />
2017    <xsl:param name="x" />
2018    <xsl:param name="y" />
2019    <xsl:param name="nearest_x" />
2020    <xsl:param name="nearest_y" />
2021    <xsl:param name="medium_dist" />
2022    <xsl:param name="nearest_score" />
2023    <xsl:param name="nearest_dist" select="'NaN'" />
2024
2025    <xsl:variable name="point" select="substring-before($points, ';')" />
2026
2027    <xsl:choose>
2028      <xsl:when test="string-length($point) &gt; 0"> 
2029        <xsl:variable name="point_x" select="substring-before($point, ',')" />
2030        <xsl:variable name="point_y" select="substring-before(substring-after($point, ','), ',')" />
2031        <xsl:variable name="point_dist" select="substring-after(substring-after($point, ','), ',')" />
2032       
2033        <xsl:variable name="distance">
2034          <xsl:call-template name="areacenterPointDistance">
2035            <xsl:with-param name="x1" select="$x" />
2036            <xsl:with-param name="y1" select="$y" />
2037            <xsl:with-param name="x2" select="$point_x" />
2038            <xsl:with-param name="y2" select="$point_y" />
2039          </xsl:call-template>
2040        </xsl:variable>
2041
2042        <xsl:variable name="score" select="0 - $distance + $point_dist + $point_dist - $medium_dist"/>
2043        <xsl:variable name="isNewNearest" select="$nearest_dist = 'NaN' or $score &gt; $nearest_score" />
2044
2045        <xsl:call-template name="areacenterBestPoint">
2046          <xsl:with-param name="points" select="substring-after($points, ';')" />
2047          <xsl:with-param name="x" select="$x" />
2048          <xsl:with-param name="y" select="$y" />
2049          <xsl:with-param name="medium_dist" select="$medium_dist" />
2050          <xsl:with-param name="nearest_dist"><xsl:choose>
2051            <xsl:when test="$isNewNearest"><xsl:value-of select="$distance" /></xsl:when>
2052            <xsl:otherwise><xsl:value-of select="$nearest_dist" /></xsl:otherwise>
2053          </xsl:choose></xsl:with-param>
2054          <xsl:with-param name="nearest_x"><xsl:choose>
2055            <xsl:when test="$isNewNearest"><xsl:value-of select="$point_x" /></xsl:when>
2056            <xsl:otherwise><xsl:value-of select="$nearest_x" /></xsl:otherwise>
2057          </xsl:choose></xsl:with-param>
2058          <xsl:with-param name="nearest_y"><xsl:choose>
2059            <xsl:when test="$isNewNearest"><xsl:value-of select="$point_y" /></xsl:when>
2060            <xsl:otherwise><xsl:value-of select="$nearest_y" /></xsl:otherwise>
2061          </xsl:choose></xsl:with-param>
2062          <xsl:with-param name="nearest_score"><xsl:choose>
2063            <xsl:when test="$isNewNearest"><xsl:value-of select="$score" /></xsl:when>
2064            <xsl:otherwise><xsl:value-of select="$nearest_score" /></xsl:otherwise>
2065          </xsl:choose></xsl:with-param>
2066        </xsl:call-template>
2067      </xsl:when>
2068      <xsl:otherwise>
2069        <xsl:value-of select="$nearest_x" />, <xsl:value-of select="$nearest_y" />
2070      </xsl:otherwise>
2071    </xsl:choose>
2072  </xsl:template>
2073
2074  <!-- Process a <text> instruction -->
2075  <xsl:template match="text">
2076    <xsl:param name="elements"/>
2077
2078    <!-- This is the instruction that is currently being processed -->
2079    <xsl:variable name="instruction" select="."/>
2080
2081    <!-- Select all <node> elements that have a key that matches the k attribute of the text instruction -->
2082    <xsl:for-each select="$elements[name()='node'][tag[@k=$instruction/@k]]">
2083      <xsl:call-template name="renderText">
2084        <xsl:with-param name="instruction" select="$instruction"/>
2085      </xsl:call-template>
2086    </xsl:for-each>
2087
2088    <!-- Select all <way> elements -->
2089    <xsl:apply-templates select="$elements[name()='way']" mode="textPath">
2090      <xsl:with-param name="instruction" select="$instruction"/>
2091    </xsl:apply-templates>
2092  </xsl:template>
2093
2094
2095  <!-- Suppress output of any unhandled elements -->
2096  <xsl:template match="*" mode="textPath"/>
2097
2098
2099  <!-- Render textPaths for a way -->
2100  <xsl:template match="way" mode="textPath">
2101    <xsl:param name="instruction"/>
2102
2103    <!-- The current <way> element -->
2104    <xsl:variable name="way" select="."/>
2105
2106    <!-- DODI: !!!WORKAROUND!!! no text for one node ways-->
2107    <xsl:if test="count($way/nd) &gt; 1">
2108      <xsl:variable name='text'>
2109        <xsl:choose>
2110          <xsl:when test='$instruction/@k'>
2111            <xsl:value-of select='tag[@k=$instruction/@k]/@v'/>
2112          </xsl:when>
2113          <xsl:otherwise>
2114            <xsl:apply-templates select='$instruction' mode='textFormat'>
2115              <xsl:with-param name='way' select='$way'/>
2116            </xsl:apply-templates>
2117          </xsl:otherwise>
2118        </xsl:choose>
2119      </xsl:variable>
2120
2121      <xsl:if test='string($text)'>
2122
2123        <xsl:variable name="pathDirection">
2124          <xsl:choose>
2125            <!-- Manual override, reverse direction -->
2126            <xsl:when test="tag[@k='name_direction']/@v='-1' or tag[@k='osmarender:nameDirection']/@v='-1'">reverse</xsl:when>
2127            <!-- Manual override, normal direction -->
2128            <xsl:when test="tag[@k='name_direction']/@v='1' or tag[@k='osmarender:nameDirection']/@v='1'">normal</xsl:when>
2129            <!-- Automatic, reverse direction -->
2130            <xsl:when test="(key('nodeById',$way/nd[1]/@ref)/@lon &gt; key('nodeById',$way/nd[last()]/@ref)/@lon)">reverse</xsl:when>
2131            <!-- Automatic, normal direction -->
2132            <xsl:otherwise>normal</xsl:otherwise>
2133          </xsl:choose>
2134        </xsl:variable>
2135
2136        <xsl:variable name="wayPath">
2137          <xsl:choose>
2138            <!-- Normal -->
2139            <xsl:when test='$pathDirection="normal"'>
2140              <xsl:value-of select="concat('way_normal_',@id)"/>
2141            </xsl:when>
2142            <!-- Reverse -->
2143            <xsl:otherwise>
2144              <xsl:value-of select="concat('way_reverse_',@id)"/>
2145            </xsl:otherwise>
2146          </xsl:choose>
2147        </xsl:variable>
2148
2149        <xsl:call-template name="renderTextPath">
2150          <xsl:with-param name="instruction" select="$instruction"/>
2151          <xsl:with-param name="pathId" select="$wayPath"/>
2152          <xsl:with-param name="pathDirection" select="$pathDirection"/>
2153          <xsl:with-param name="text" select="$text"/>
2154        </xsl:call-template>
2155      </xsl:if>
2156    </xsl:if>
2157  </xsl:template>
2158
2159  <!-- Process extended form of text instruction -->
2160  <xsl:template match='text' mode='textFormat'>
2161    <xsl:param name='way'/>
2162
2163    <xsl:apply-templates mode='textFormat'>
2164      <xsl:with-param name='way' select='$way'/>
2165    </xsl:apply-templates>
2166  </xsl:template>
2167
2168
2169  <!-- Substitute a tag in a text instruction -->
2170  <xsl:template match='text/tag' mode='textFormat'>
2171    <xsl:param name='way'/>
2172
2173    <xsl:variable name='key' select='@k'/>
2174    <xsl:variable name='value'>
2175      <xsl:choose>
2176        <xsl:when test='$key="osm:user"'>
2177          <xsl:value-of select='$way/@user'/>
2178        </xsl:when>
2179        <xsl:when test='$key="osm:timestamp"'>
2180          <xsl:value-of select='$way/@timestamp'/>
2181        </xsl:when>
2182        <xsl:when test='$key="osm:id"'>
2183          <xsl:value-of select='$way/@id'/>
2184        </xsl:when>
2185        <xsl:otherwise>
2186          <xsl:value-of select='$way/tag[@k=$key]/@v'/>
2187        </xsl:otherwise>
2188      </xsl:choose>
2189    </xsl:variable>
2190    <xsl:choose>
2191      <xsl:when test='string($value)'>
2192        <xsl:value-of select='$value'/>
2193      </xsl:when>
2194      <xsl:otherwise>
2195        <xsl:value-of select='@default'/>
2196      </xsl:otherwise>
2197    </xsl:choose>
2198  </xsl:template>
2199
2200
2201
2202  <!-- Generate a way path for the current way element -->
2203  <xsl:template name="generateWayPaths">
2204    <!-- DODI: !!!WORKAROUND!!! skip one node ways -->
2205    <xsl:if test="count(nd) &gt; 1">
2206
2207      <!-- Generate a normal way path -->
2208      <xsl:variable name="pathWayNormal">
2209        <xsl:call-template name="generateWayPathNormal"/>
2210      </xsl:variable>
2211      <xsl:if test="$pathWayNormal!=''">
2212        <path id="way_normal_{@id}" d="{$pathWayNormal}"/>
2213      </xsl:if>
2214
2215      <!-- Generate a normal way path as area -->
2216      <!-- DODI: !!!WORKAROUND!!! added to generate "area for all ways, yes it is very dirty... but -->
2217      <!-- DODI: removed because of line2curves.pl duplicate node detection problem -->
2218      <!-- <xsl:variable name="pathArea">
2219      <xsl:call-template name="generateAreaPath"/>
2220    </xsl:variable>
2221    <path id="area_{@id}" d="{$pathArea}"/> -->
2222      <!-- Generate a reverse way path (if needed) -->
2223      <xsl:variable name="pathWayReverse">
2224        <xsl:choose>
2225          <!-- Manual override, reverse direction -->
2226          <xsl:when test="tag[@k='name_direction']/@v='-1' or tag[@k='osmarender:nameDirection']/@v='-1'">
2227            <xsl:call-template name="generateWayPathReverse"/>
2228          </xsl:when>
2229          <!-- Manual override, normal direction -->
2230          <xsl:when test="tag[@k='name_direction']/@v='1' or tag[@k='osmarender:nameDirection']/@v='1'">
2231            <!-- Generate nothing -->
2232          </xsl:when>
2233          <!-- Automatic, reverse direction -->
2234          <xsl:when test="(key('nodeById',nd[1]/@ref)/@lon &gt; key('nodeById',nd[last()]/@ref)/@lon)">
2235            <xsl:call-template name="generateWayPathReverse"/>
2236          </xsl:when>
2237        </xsl:choose>
2238      </xsl:variable>
2239      <xsl:if test="$pathWayReverse!=''">
2240        <path id="way_reverse_{@id}" d="{$pathWayReverse}"/>
2241      </xsl:if>
2242
2243      <!-- Generate the start, middle and end paths needed for smart-linecaps (TM). -->
2244      <xsl:variable name="pathWayStart">
2245        <xsl:call-template name="generatePathWayStart"/>
2246      </xsl:variable>
2247      <path id="way_start_{@id}" d="{$pathWayStart}"/>
2248
2249      <xsl:if test="count(nd) &gt; 1">
2250        <xsl:variable name="pathWayMid">
2251          <xsl:call-template name="generatePathWayMid"/>
2252        </xsl:variable>
2253        <path id="way_mid_{@id}" d="{$pathWayMid}"/>
2254      </xsl:if>
2255
2256      <xsl:variable name="pathWayEnd">
2257        <xsl:call-template name="generatePathWayEnd"/>
2258      </xsl:variable>
2259      <path id="way_end_{@id}" d="{$pathWayEnd}"/>
2260    </xsl:if >
2261  </xsl:template>
2262
2263
2264  <!-- Generate a normal way path -->
2265  <xsl:template name="generateWayPathNormal">
2266    <xsl:for-each select="nd[key('nodeById',@ref) ]">
2267      <xsl:choose>
2268        <xsl:when test="position()=1">
2269          <xsl:call-template name="moveToNode">
2270            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
2271          </xsl:call-template>
2272        </xsl:when>
2273        <xsl:otherwise>
2274          <xsl:call-template name="lineToNode">
2275            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
2276          </xsl:call-template>
2277        </xsl:otherwise>
2278      </xsl:choose>
2279    </xsl:for-each>
2280  </xsl:template>
2281
2282
2283  <!-- Generate a reverse way path -->
2284  <xsl:template name="generateWayPathReverse">
2285    <xsl:for-each select="nd[key('nodeById',@ref)]">
2286      <xsl:sort select="position()" data-type="number" order="descending"/>
2287      <xsl:choose>
2288        <xsl:when test="position()=1">
2289          <xsl:call-template name="moveToNode">
2290            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
2291          </xsl:call-template>
2292        </xsl:when>
2293        <xsl:otherwise>
2294          <xsl:call-template name="lineToNode">
2295            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
2296          </xsl:call-template>
2297        </xsl:otherwise>
2298      </xsl:choose>
2299    </xsl:for-each>
2300  </xsl:template>
2301
2302
2303  <!-- 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
2304         between the two paths is not at an angle.  -->
2305  <xsl:template name="generatePathWayStart">
2306    <xsl:call-template name="moveToNode">
2307      <xsl:with-param name="node" select="key('nodeById',nd[1]/@ref)"/>
2308    </xsl:call-template>
2309    <xsl:call-template name="lineToMidpointPlus">
2310      <xsl:with-param name="fromNode" select="key('nodeById',nd[1]/@ref)"/>
2311      <xsl:with-param name="toNode" select="key('nodeById',nd[2]/@ref)"/>
2312    </xsl:call-template>
2313  </xsl:template>
2314
2315  <xsl:template name="generatePathWayEnd">
2316    <xsl:call-template name="moveToMidpointPlus">
2317      <xsl:with-param name="fromNode" select="key('nodeById',nd[position()=(last())]/@ref)"/>
2318      <xsl:with-param name="toNode" select="key('nodeById',nd[position()=last()-1]/@ref)"/>
2319    </xsl:call-template>
2320    <xsl:call-template name="lineToNode">
2321      <xsl:with-param name="node" select="key('nodeById',nd[position()=last()]/@ref)"/>
2322    </xsl:call-template>
2323  </xsl:template>
2324
2325  <xsl:template name="generatePathWayMid">
2326    <xsl:for-each select="nd[key('nodeById',@ref)]">
2327      <xsl:choose>
2328        <xsl:when test="position()=1">
2329          <xsl:call-template name="moveToMidpointPlus">
2330            <xsl:with-param name="fromNode" select="key('nodeById',@ref)"/>
2331            <xsl:with-param name="toNode" select="key('nodeById',following-sibling::nd[1]/@ref)"/>
2332          </xsl:call-template>
2333        </xsl:when>
2334        <xsl:when test="position()=last()">
2335          <xsl:call-template name="lineToMidpointMinus">
2336            <xsl:with-param name="fromNode" select="key('nodeById',preceding-sibling::nd[1]/@ref)"/>
2337            <xsl:with-param name="toNode" select="key('nodeById',@ref)"/>
2338          </xsl:call-template>
2339        </xsl:when>
2340        <xsl:otherwise>
2341          <xsl:call-template name="lineToNode">
2342            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
2343          </xsl:call-template>
2344        </xsl:otherwise>
2345      </xsl:choose>
2346    </xsl:for-each>
2347  </xsl:template>
2348
2349  <!-- Generate an area path for the current way or area element -->
2350  <xsl:template name="generateAreaPath">
2351    <xsl:variable name='relation' select="key('relationByWay',@id)[tag[@k='type' and @v='multipolygon']]"/>
2352    <xsl:choose>
2353      <xsl:when test='$relation'>
2354        <!-- Handle multipolygons.
2355             Draw area only once, draw the outer one first if we know which is it, else just draw the first one -->
2356        <xsl:variable name='outerway' select="$relation/member[@type='way'][@role='outer']/@ref"/>
2357        <xsl:variable name='firsrelationmember' select="$relation/member[@type='way'][key('wayById', @ref)][1]/@ref"/> 
2358        <xsl:if test='( $outerway and $outerway=@id ) or ( not($outerway) and $firsrelationmember=@id )'>
2359          <xsl:message>
2360            <xsl:value-of select='$relation/@id'/>
2361          </xsl:message>
2362          <xsl:for-each select="$relation/member[@type='way'][key('wayById', @ref)]">
2363            <xsl:call-template name='generateAreaSubPath'>
2364              <xsl:with-param name='way' select="key('wayById',@ref)"/>
2365              <xsl:with-param name='position' select="position()"/>
2366            </xsl:call-template>
2367          </xsl:for-each>
2368          <xsl:text>Z</xsl:text>
2369        </xsl:if>
2370
2371      </xsl:when>
2372      <xsl:otherwise>
2373        <xsl:call-template name='generateAreaSubPath'>
2374          <xsl:with-param name='way' select='.'/>
2375          <xsl:with-param name='position' select="'1'"/>
2376        </xsl:call-template>
2377        <xsl:text>Z</xsl:text>
2378      </xsl:otherwise>
2379    </xsl:choose>
2380  </xsl:template>
2381
2382
2383  <xsl:template name='generateAreaSubPath'>
2384    <xsl:param name='way'/>
2385    <xsl:param name='position'/>
2386
2387    <xsl:variable name='loop' select='$way/nd[1]/@ref=$way/nd[last()]/@ref'/>
2388    <xsl:message>
2389      WayId: <xsl:value-of select='$way/@id'/>
2390      Loop: <xsl:value-of select='$loop'/>
2391      Loop: <xsl:value-of select='$way/nd[1]/@ref'/>
2392      Loop: <xsl:value-of select='$way/nd[last()]/@ref'/>
2393    </xsl:message>
2394    <xsl:for-each select="$way/nd[key('nodeById',@ref)]">
2395      <xsl:choose>
2396        <xsl:when test="position()=1 and $loop">
2397          <xsl:if test='not($position=1)'>
2398            <xsl:text>Z</xsl:text>
2399          </xsl:if>
2400          <xsl:call-template name="moveToNode">
2401            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
2402          </xsl:call-template>
2403        </xsl:when>
2404        <xsl:when test="$position=1 and position()=1 and not($loop=1)">
2405          <xsl:call-template name="moveToNode">
2406            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
2407          </xsl:call-template>
2408        </xsl:when>
2409        <xsl:otherwise>
2410          <xsl:call-template name="lineToNode">
2411            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
2412          </xsl:call-template>
2413        </xsl:otherwise>
2414      </xsl:choose>
2415    </xsl:for-each>
2416
2417
2418  </xsl:template>
2419
2420  <!-- Generate a MoveTo command for a node -->
2421  <xsl:template name="moveToNode">
2422    <xsl:param name='node' />
2423    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($node/@lon))*10000*$scale)"/>
2424    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($node/@lat))*10000*$scale*$projection)"/>
2425    <xsl:text>M</xsl:text>
2426    <xsl:value-of select="$x1"/>
2427    <xsl:text> </xsl:text>
2428    <xsl:value-of select="$y1"/>
2429  </xsl:template>
2430
2431  <!-- Generate a LineTo command for a nd -->
2432  <xsl:template name="lineToNode">
2433    <xsl:param name='node'/>
2434
2435    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($node/@lon))*10000*$scale)"/>
2436    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($node/@lat))*10000*$scale*$projection)"/>
2437    <xsl:text>L</xsl:text>
2438    <xsl:value-of select="$x1"/>
2439    <xsl:text> </xsl:text>
2440    <xsl:value-of select="$y1"/>
2441  </xsl:template>
2442
2443  <xsl:template name="lineToMidpointPlus">
2444    <xsl:param name='fromNode'/>
2445    <xsl:param name='toNode'/>
2446
2447    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
2448    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
2449
2450    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
2451    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
2452
2453    <xsl:text>L</xsl:text>
2454    <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
2455    <xsl:text> </xsl:text>
2456    <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
2457  </xsl:template>
2458
2459  <xsl:template name="lineToMidpointMinus">
2460    <xsl:param name='fromNode'/>
2461    <xsl:param name='toNode'/>
2462
2463    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
2464    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
2465
2466    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
2467    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
2468    <xsl:text>L</xsl:text>
2469    <xsl:value-of select="$x1+(($x2 - $x1) div 2.1)"/>
2470    <xsl:text> </xsl:text>
2471    <xsl:value-of select="$y1+(($y2 - $y1) div 2.1)"/>
2472  </xsl:template>
2473
2474
2475  <xsl:template name="moveToMidpointPlus">
2476    <xsl:param name='fromNode'/>
2477    <xsl:param name='toNode'/>
2478
2479    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
2480    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
2481
2482    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
2483    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
2484    <xsl:text>M</xsl:text>
2485    <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
2486    <xsl:text> </xsl:text>
2487    <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
2488  </xsl:template>
2489
2490  <!-- Some attribute shouldn't be copied -->
2491  <xsl:template match="@type|@ref|@scale|@smart-linecap" mode="copyAttributes" />
2492
2493  <!-- Copy all other attributes  -->
2494  <xsl:template match="@*" mode="copyAttributes">
2495    <xsl:copy/>
2496  </xsl:template>
2497
2498
2499  <!-- Rule processing engine -->
2500
2501  <!--
2502
2503                Calls all templates inside <rule> tags (including itself, if there are nested rules).
2504
2505                If the global var withOSMLayers is 'no', we don't care about layers and draw everything
2506                in one go. This is faster and is sometimes useful. For normal maps you want withOSMLayers
2507                to be 'yes', which is the default.
2508
2509        -->
2510  <xsl:template name="processRules">
2511
2512    <!-- First select all elements - exclude those marked as deleted by JOSM -->
2513    <xsl:variable name='elements' select="$data/osm/*[not(@action) or not(@action='delete')]" />
2514
2515    <xsl:choose>
2516
2517      <!-- Process all the rules, one layer at a time -->
2518      <xsl:when test="$withOSMLayers='yes'">
2519        <xsl:call-template name="processLayer">
2520          <xsl:with-param name="layer" select="'-5'"/>
2521          <xsl:with-param name="elements" select="$elements"/>
2522        </xsl:call-template>
2523        <xsl:call-template name="processLayer">
2524          <xsl:with-param name="layer" select="'-4'"/>
2525          <xsl:with-param name="elements" select="$elements"/>
2526        </xsl:call-template>
2527        <xsl:call-template name="processLayer">
2528          <xsl:with-param name="layer" select="'-3'"/>
2529          <xsl:with-param name="elements" select="$elements"/>
2530        </xsl:call-template>
2531        <xsl:call-template name="processLayer">
2532          <xsl:with-param name="layer" select="'-2'"/>
2533          <xsl:with-param name="elements" select="$elements"/>
2534        </xsl:call-template>
2535        <xsl:call-template name="processLayer">
2536          <xsl:with-param name="layer" select="'-1'"/>
2537          <xsl:with-param name="elements" select="$elements"/>
2538        </xsl:call-template>
2539        <xsl:call-template name="processLayer">
2540          <xsl:with-param name="layer" select="'0'"/>
2541          <xsl:with-param name="elements" select="$elements"/>
2542        </xsl:call-template>
2543        <xsl:call-template name="processLayer">
2544          <xsl:with-param name="layer" select="'1'"/>
2545          <xsl:with-param name="elements" select="$elements"/>
2546        </xsl:call-template>
2547        <xsl:call-template name="processLayer">
2548          <xsl:with-param name="layer" select="'2'"/>
2549          <xsl:with-param name="elements" select="$elements"/>
2550        </xsl:call-template>
2551        <xsl:call-template name="processLayer">
2552          <xsl:with-param name="layer" select="'3'"/>
2553          <xsl:with-param name="elements" select="$elements"/>
2554        </xsl:call-template>
2555        <xsl:call-template name="processLayer">
2556          <xsl:with-param name="layer" select="'4'"/>
2557          <xsl:with-param name="elements" select="$elements"/>
2558        </xsl:call-template>
2559        <xsl:call-template name="processLayer">
2560          <xsl:with-param name="layer" select="'5'"/>
2561          <xsl:with-param name="elements" select="$elements"/>
2562        </xsl:call-template>
2563      </xsl:when>
2564
2565      <!-- Process all the rules, without looking at the layers -->
2566      <xsl:otherwise>
2567        <xsl:apply-templates select="/rules/rule">
2568          <xsl:with-param name="elements" select="$elements"/>
2569          <xsl:with-param name="layer" select="'0'"/>
2570        </xsl:apply-templates>
2571      </xsl:otherwise>
2572
2573    </xsl:choose>
2574  </xsl:template>
2575
2576
2577  <xsl:template name="processLayer">
2578    <xsl:param name="layer"/>
2579    <xsl:param name="elements"/>
2580
2581    <g inkscape:groupmode="layer" id="layer{$layer}" inkscape:label="Layer {$layer}">
2582      <xsl:apply-templates select="/rules/rule">
2583        <xsl:with-param name="elements" select="$elements"/>
2584        <xsl:with-param name="layer" select="$layer"/>
2585      </xsl:apply-templates>
2586    </g>
2587  </xsl:template>
2588
2589
2590  <!-- Process a rule at a specific level -->
2591  <xsl:template match='rule'>
2592    <xsl:param name="elements"/>
2593    <xsl:param name="layer"/>
2594
2595    <!-- If the rule is for a specific layer and we are processing that layer then pass *all* elements
2596                     to the rule, otherwise just select the matching elements for this layer. -->
2597    <xsl:choose>
2598      <xsl:when test='$layer=@layer'>
2599        <xsl:call-template name="rule">
2600          <xsl:with-param name="elements" select="$elements"/>
2601          <xsl:with-param name="layer" select="$layer"/>
2602        </xsl:call-template>
2603      </xsl:when>
2604      <xsl:otherwise>
2605        <xsl:if test='not(@layer)'>
2606          <xsl:call-template name="rule">
2607            <xsl:with-param name="elements" select="$elements[
2608                                                        tag[@k='layer' and @v=$layer]
2609                                                        or ($layer='0' and count(tag[@k='layer'])=0)
2610                                                ]"/>
2611            <xsl:with-param name="layer" select="$layer"/>
2612          </xsl:call-template>
2613        </xsl:if>
2614      </xsl:otherwise>
2615    </xsl:choose>
2616  </xsl:template>
2617
2618
2619  <xsl:template name='rule'>
2620    <xsl:param name="elements"/>
2621    <xsl:param name="layer"/>
2622
2623    <!-- This is the rule currently being processed -->
2624    <xsl:variable name="rule" select="."/>
2625
2626    <!-- Make list of elements that this rule should be applied to -->
2627    <xsl:variable name="eBare">
2628      <xsl:choose>
2629        <xsl:when test="$rule/@e='*'">node|way</xsl:when>
2630        <xsl:when test="$rule/@e">
2631          <xsl:value-of select="$rule/@e"/>
2632        </xsl:when>
2633        <xsl:otherwise>node|way</xsl:otherwise>
2634      </xsl:choose>
2635    </xsl:variable>
2636
2637    <!-- List of keys that this rule should be applied to -->
2638    <xsl:variable name="kBare" select="$rule/@k"/>
2639
2640    <!-- List of values that this rule should be applied to -->
2641    <xsl:variable name="vBare" select="$rule/@v"/>
2642    <xsl:variable name="sBare" select="$rule/@s"/>
2643
2644    <!-- Top'n'tail selectors with | for contains usage -->
2645    <xsl:variable name="e">
2646      |<xsl:value-of select="$eBare"/>|
2647    </xsl:variable>
2648    <xsl:variable name="k">
2649      |<xsl:value-of select="$kBare"/>|
2650    </xsl:variable>
2651    <xsl:variable name="v">
2652      |<xsl:value-of select="$vBare"/>|
2653    </xsl:variable>
2654    <xsl:variable name="s">
2655      |<xsl:value-of select="$sBare"/>|
2656    </xsl:variable>
2657
2658    <xsl:variable
2659      name="selectedElements"
2660      select="$elements[contains($e,concat('|',name(),'|'))
2661            or
2662            (contains($e,'|node|') and name()='way' and key('wayByNode',@id))
2663            ]"/>
2664
2665
2666    <!-- Patch $s -->
2667    <xsl:choose>
2668      <!-- way selector -->
2669      <xsl:when test="contains($s,'|way|')">
2670        <xsl:choose>
2671          <!-- every key -->
2672          <xsl:when test="contains($k,'|*|')">
2673            <xsl:choose>
2674              <!-- every key ,no value defined -->
2675              <xsl:when test="contains($v,'|~|')">
2676                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(key('wayByNode',@id)/tag)=0]"/>
2677                <xsl:call-template name="processElements">
2678                  <xsl:with-param name="eBare" select="$eBare"/>
2679                  <xsl:with-param name="kBare" select="$kBare"/>
2680                  <xsl:with-param name="vBare" select="$vBare"/>
2681                  <xsl:with-param name="layer" select="$layer"/>
2682                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2683                  <xsl:with-param name="rule" select="$rule"/>
2684                </xsl:call-template>
2685              </xsl:when>
2686              <!-- every key ,every value -->
2687              <xsl:when test="contains($v,'|*|')">
2688                <xsl:variable name="allElements" select="$selectedElements"/>
2689                <xsl:call-template name="processElements">
2690                  <xsl:with-param name="eBare" select="$eBare"/>
2691                  <xsl:with-param name="kBare" select="$kBare"/>
2692                  <xsl:with-param name="vBare" select="$vBare"/>
2693                  <xsl:with-param name="layer" select="$layer"/>
2694                  <xsl:with-param name="elements" select="$allElements"/>
2695                  <xsl:with-param name="rule" select="$rule"/>
2696                </xsl:call-template>
2697              </xsl:when>
2698              <!-- every key , selected values -->
2699              <xsl:otherwise>
2700                <xsl:variable name="allElementsWithValue" select="$selectedElements[key('wayByNode',@id)/tag[contains($v,concat('|',@v,'|'))]]"/>
2701                <xsl:call-template name="processElements">
2702                  <xsl:with-param name="eBare" select="$eBare"/>
2703                  <xsl:with-param name="kBare" select="$kBare"/>
2704                  <xsl:with-param name="vBare" select="$vBare"/>
2705                  <xsl:with-param name="layer" select="$layer"/>
2706                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
2707                  <xsl:with-param name="rule" select="$rule"/>
2708                </xsl:call-template>
2709              </xsl:otherwise>
2710            </xsl:choose>
2711          </xsl:when>
2712          <!-- no value  -->
2713          <xsl:when test="contains($v,'|~|')">
2714            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])=0]"/>
2715            <xsl:call-template name="processElements">
2716              <xsl:with-param name="eBare" select="$eBare"/>
2717              <xsl:with-param name="kBare" select="$kBare"/>
2718              <xsl:with-param name="vBare" select="$vBare"/>
2719              <xsl:with-param name="layer" select="$layer"/>
2720              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2721              <xsl:with-param name="rule" select="$rule"/>
2722            </xsl:call-template>
2723          </xsl:when>
2724          <!-- every value  -->
2725          <xsl:when test="contains($v,'|*|')">
2726            <xsl:variable name="allElementsWithKey" select="$selectedElements[key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))]]"/>
2727            <xsl:call-template name="processElements">
2728              <xsl:with-param name="eBare" select="$eBare"/>
2729              <xsl:with-param name="kBare" select="$kBare"/>
2730              <xsl:with-param name="vBare" select="$vBare"/>
2731              <xsl:with-param name="layer" select="$layer"/>
2732              <xsl:with-param name="elements" select="$allElementsWithKey"/>
2733              <xsl:with-param name="rule" select="$rule"/>
2734            </xsl:call-template>
2735          </xsl:when>
2736
2737          <!-- defined key and defined value -->
2738          <xsl:otherwise>
2739            <xsl:variable name="elementsWithKey" select="$selectedElements[
2740                                                        key('wayByNode',@id)/tag[
2741                                                                contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))
2742                                                                ]
2743                                                        ]"/>
2744            <xsl:call-template name="processElements">
2745              <xsl:with-param name="eBare" select="$eBare"/>
2746              <xsl:with-param name="kBare" select="$kBare"/>
2747              <xsl:with-param name="vBare" select="$vBare"/>
2748              <xsl:with-param name="layer" select="$layer"/>
2749              <xsl:with-param name="elements" select="$elementsWithKey"/>
2750              <xsl:with-param name="rule" select="$rule"/>
2751            </xsl:call-template>
2752          </xsl:otherwise>
2753        </xsl:choose>
2754      </xsl:when>
2755
2756      <!-- other selector -->
2757      <xsl:otherwise>
2758        <xsl:choose>
2759          <xsl:when test="contains($k,'|*|')">
2760            <xsl:choose>
2761              <xsl:when test="contains($v,'|~|')">
2762                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(tag)=0]"/>
2763                <xsl:call-template name="processElements">
2764                  <xsl:with-param name="eBare" select="$eBare"/>
2765                  <xsl:with-param name="kBare" select="$kBare"/>
2766                  <xsl:with-param name="vBare" select="$vBare"/>
2767                  <xsl:with-param name="layer" select="$layer"/>
2768                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2769                  <xsl:with-param name="rule" select="$rule"/>
2770                </xsl:call-template>
2771              </xsl:when>
2772              <xsl:when test="contains($v,'|*|')">
2773                <xsl:variable name="allElements" select="$selectedElements"/>
2774                <xsl:call-template name="processElements">
2775                  <xsl:with-param name="eBare" select="$eBare"/>
2776                  <xsl:with-param name="kBare" select="$kBare"/>
2777                  <xsl:with-param name="vBare" select="$vBare"/>
2778                  <xsl:with-param name="layer" select="$layer"/>
2779                  <xsl:with-param name="elements" select="$allElements"/>
2780                  <xsl:with-param name="rule" select="$rule"/>
2781                </xsl:call-template>
2782              </xsl:when>
2783              <xsl:otherwise>
2784                <xsl:variable name="allElementsWithValue" select="$selectedElements[tag[contains($v,concat('|',@v,'|'))]]"/>
2785                <xsl:call-template name="processElements">
2786                  <xsl:with-param name="eBare" select="$eBare"/>
2787                  <xsl:with-param name="kBare" select="$kBare"/>
2788                  <xsl:with-param name="vBare" select="$vBare"/>
2789                  <xsl:with-param name="layer" select="$layer"/>
2790                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
2791                  <xsl:with-param name="rule" select="$rule"/>
2792                </xsl:call-template>
2793              </xsl:otherwise>
2794            </xsl:choose>
2795          </xsl:when>
2796          <xsl:when test="contains($v,'|~|')">
2797            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(tag[contains($k,concat('|',@k,'|'))])=0]"/>
2798            <xsl:call-template name="processElements">
2799              <xsl:with-param name="eBare" select="$eBare"/>
2800              <xsl:with-param name="kBare" select="$kBare"/>
2801              <xsl:with-param name="vBare" select="$vBare"/>
2802              <xsl:with-param name="layer" select="$layer"/>
2803              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2804              <xsl:with-param name="rule" select="$rule"/>
2805            </xsl:call-template>
2806          </xsl:when>
2807          <xsl:when test="contains($v,'|*|')">
2808            <xsl:variable name="allElementsWithKey" select="$selectedElements[tag[contains($k,concat('|',@k,'|'))]]"/>
2809            <xsl:call-template name="processElements">
2810              <xsl:with-param name="eBare" select="$eBare"/>
2811              <xsl:with-param name="kBare" select="$kBare"/>
2812              <xsl:with-param name="vBare" select="$vBare"/>
2813              <xsl:with-param name="layer" select="$layer"/>
2814              <xsl:with-param name="elements" select="$allElementsWithKey"/>
2815              <xsl:with-param name="rule" select="$rule"/>
2816            </xsl:call-template>
2817          </xsl:when>
2818          <xsl:otherwise>
2819            <xsl:variable name="elementsWithKey" select="$selectedElements[tag[contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))]]"/>
2820            <xsl:call-template name="processElements">
2821              <xsl:with-param name="eBare" select="$eBare"/>
2822              <xsl:with-param name="kBare" select="$kBare"/>
2823              <xsl:with-param name="vBare" select="$vBare"/>
2824              <xsl:with-param name="layer" select="$layer"/>
2825              <xsl:with-param name="elements" select="$elementsWithKey"/>
2826              <xsl:with-param name="rule" select="$rule"/>
2827            </xsl:call-template>
2828          </xsl:otherwise>
2829        </xsl:choose>
2830      </xsl:otherwise>
2831    </xsl:choose>
2832  </xsl:template>
2833
2834
2835  <xsl:template match="else">
2836    <xsl:param name="elements"/>
2837    <xsl:param name="layer"/>
2838
2839    <!-- This is the previous rule that is being negated -->
2840    <!-- TODO: abort if no preceding rule element -->
2841    <xsl:variable name="rule" select="preceding-sibling::rule[1]"/>
2842
2843    <!-- Make list of elements that this rule should be applied to -->
2844    <xsl:variable name="eBare">
2845      <xsl:choose>
2846        <xsl:when test="$rule/@e='*'">node|way</xsl:when>
2847        <xsl:when test="$rule/@e">
2848          <xsl:value-of select="$rule/@e"/>
2849        </xsl:when>
2850        <xsl:otherwise>node|way</xsl:otherwise>
2851      </xsl:choose>
2852    </xsl:variable>
2853
2854    <!-- List of keys that this rule should be applied to -->
2855    <xsl:variable name="kBare" select="$rule/@k"/>
2856
2857    <!-- List of values that this rule should be applied to -->
2858    <xsl:variable name="vBare" select="$rule/@v"/>
2859    <xsl:variable name="sBare" select="$rule/@s"/>
2860
2861
2862    <!-- Top'n'tail selectors with | for contains usage -->
2863    <xsl:variable name="e">
2864      |<xsl:value-of select="$eBare"/>|
2865    </xsl:variable>
2866    <xsl:variable name="k">
2867      |<xsl:value-of select="$kBare"/>|
2868    </xsl:variable>
2869    <xsl:variable name="v">
2870      |<xsl:value-of select="$vBare"/>|
2871    </xsl:variable>
2872    <xsl:variable name="s">
2873      |<xsl:value-of select="$sBare"/>|
2874    </xsl:variable>
2875
2876    <xsl:variable
2877      name="selectedElements"
2878      select="$elements[contains($e,concat('|',name(),'|'))
2879              or
2880              (contains($e,'|node|') and name()='way'and key('wayByNode',@id))
2881              ]"/>
2882
2883    <!-- Patch $s -->
2884    <xsl:choose>
2885      <xsl:when test="contains($s,'|way|')">
2886        <xsl:choose>
2887          <xsl:when test="contains($k,'|*|')">
2888            <xsl:choose>
2889              <xsl:when test="contains($v,'|~|')">
2890                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(key('wayByNode',@id)/tag)!=0]"/>
2891                <xsl:call-template name="processElements">
2892                  <xsl:with-param name="eBare" select="$eBare"/>
2893                  <xsl:with-param name="kBare" select="$kBare"/>
2894                  <xsl:with-param name="vBare" select="$vBare"/>
2895                  <xsl:with-param name="layer" select="$layer"/>
2896                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2897                  <xsl:with-param name="rule" select="$rule"/>
2898                </xsl:call-template>
2899              </xsl:when>
2900              <xsl:when test="contains($v,'|*|')">
2901                <!-- no-op! -->
2902              </xsl:when>
2903              <xsl:otherwise>
2904                <xsl:variable name="allElementsWithValue" select="$selectedElements[not(key('wayByNode',@id)/tag[contains($v,concat('|',@v,'|'))])]"/>
2905                <xsl:call-template name="processElements">
2906                  <xsl:with-param name="eBare" select="$eBare"/>
2907                  <xsl:with-param name="kBare" select="$kBare"/>
2908                  <xsl:with-param name="vBare" select="$vBare"/>
2909                  <xsl:with-param name="layer" select="$layer"/>
2910                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
2911                  <xsl:with-param name="rule" select="$rule"/>
2912                </xsl:call-template>
2913              </xsl:otherwise>
2914            </xsl:choose>
2915          </xsl:when>
2916          <xsl:when test="contains($v,'|~|')">
2917            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])!=0]"/>
2918            <xsl:call-template name="processElements">
2919              <xsl:with-param name="eBare" select="$eBare"/>
2920              <xsl:with-param name="kBare" select="$kBare"/>
2921              <xsl:with-param name="vBare" select="$vBare"/>
2922              <xsl:with-param name="layer" select="$layer"/>
2923              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2924              <xsl:with-param name="rule" select="$rule"/>
2925            </xsl:call-template>
2926          </xsl:when>
2927          <xsl:when test="contains($v,'|*|')">
2928            <xsl:variable name="allElementsWithKey" select="$selectedElements[not(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])]"/>
2929            <xsl:call-template name="processElements">
2930              <xsl:with-param name="eBare" select="$eBare"/>
2931              <xsl:with-param name="kBare" select="$kBare"/>
2932              <xsl:with-param name="vBare" select="$vBare"/>
2933              <xsl:with-param name="layer" select="$layer"/>
2934              <xsl:with-param name="elements" select="$allElementsWithKey"/>
2935              <xsl:with-param name="rule" select="$rule"/>
2936            </xsl:call-template>
2937          </xsl:when>
2938          <xsl:otherwise>
2939            <xsl:variable name="elementsWithKey" select="$selectedElements[not(
2940                         key('wayByNode',@id)/tag[
2941                            contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))
2942                            ]
2943                         )]"/>
2944            <xsl:call-template name="processElements">
2945              <xsl:with-param name="eBare" select="$eBare"/>
2946              <xsl:with-param name="kBare" select="$kBare"/>
2947              <xsl:with-param name="vBare" select="$vBare"/>
2948              <xsl:with-param name="layer" select="$layer"/>
2949              <xsl:with-param name="elements" select="$elementsWithKey"/>
2950              <xsl:with-param name="rule" select="$rule"/>
2951            </xsl:call-template>
2952          </xsl:otherwise>
2953        </xsl:choose>
2954      </xsl:when>
2955
2956      <xsl:otherwise>
2957        <!-- not contains $s -->
2958        <xsl:choose>
2959          <xsl:when test="contains($k,'|*|')">
2960            <xsl:choose>
2961              <xsl:when test="contains($v,'|~|')">
2962                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(tag)!=0]"/>
2963                <xsl:call-template name="processElements">
2964                  <xsl:with-param name="eBare" select="$eBare"/>
2965                  <xsl:with-param name="kBare" select="$kBare"/>
2966                  <xsl:with-param name="vBare" select="$vBare"/>
2967                  <xsl:with-param name="layer" select="$layer"/>
2968                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2969                  <xsl:with-param name="rule" select="$rule"/>
2970                </xsl:call-template>
2971              </xsl:when>
2972              <xsl:when test="contains($v,'|*|')">
2973                <!-- no-op! -->
2974              </xsl:when>
2975              <xsl:otherwise>
2976                <xsl:variable name="allElementsWithValue" select="$selectedElements[not(tag[contains($v,concat('|',@v,'|'))])]"/>
2977                <xsl:call-template name="processElements">
2978                  <xsl:with-param name="eBare" select="$eBare"/>
2979                  <xsl:with-param name="kBare" select="$kBare"/>
2980                  <xsl:with-param name="vBare" select="$vBare"/>
2981                  <xsl:with-param name="layer" select="$layer"/>
2982                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
2983                  <xsl:with-param name="rule" select="$rule"/>
2984                </xsl:call-template>
2985              </xsl:otherwise>
2986            </xsl:choose>
2987          </xsl:when>
2988          <xsl:when test="contains($v,'|~|')">
2989            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(tag[contains($k,concat('|',@k,'|'))])!=0]"/>
2990            <xsl:call-template name="processElements">
2991              <xsl:with-param name="eBare" select="$eBare"/>
2992              <xsl:with-param name="kBare" select="$kBare"/>
2993              <xsl:with-param name="vBare" select="$vBare"/>
2994              <xsl:with-param name="layer" select="$layer"/>
2995              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2996              <xsl:with-param name="rule" select="$rule"/>
2997            </xsl:call-template>
2998          </xsl:when>
2999          <xsl:when test="contains($v,'|*|')">
3000            <xsl:variable name="allElementsWithKey" select="$selectedElements[not(tag[contains($k,concat('|',@k,'|'))])]"/>
3001            <xsl:call-template name="processElements">
3002              <xsl:with-param name="eBare" select="$eBare"/>
3003              <xsl:with-param name="kBare" select="$kBare"/>
3004              <xsl:with-param name="vBare" select="$vBare"/>
3005              <xsl:with-param name="layer" select="$layer"/>
3006              <xsl:with-param name="elements" select="$allElementsWithKey"/>
3007              <xsl:with-param name="rule" select="$rule"/>
3008            </xsl:call-template>
3009          </xsl:when>
3010          <xsl:otherwise>
3011            <xsl:variable name="elementsWithKey" select="$selectedElements[not(tag[contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))])]"/>
3012            <xsl:call-template name="processElements">
3013              <xsl:with-param name="eBare" select="$eBare"/>
3014              <xsl:with-param name="kBare" select="$kBare"/>
3015              <xsl:with-param name="vBare" select="$vBare"/>
3016              <xsl:with-param name="layer" select="$layer"/>
3017              <xsl:with-param name="elements" select="$elementsWithKey"/>
3018              <xsl:with-param name="rule" select="$rule"/>
3019            </xsl:call-template>
3020          </xsl:otherwise>
3021        </xsl:choose>
3022      </xsl:otherwise>
3023    </xsl:choose>
3024  </xsl:template>
3025
3026
3027  <xsl:template name="processElements">
3028    <xsl:param name="eBare"/>
3029    <xsl:param name="kBare"/>
3030    <xsl:param name="vBare"/>
3031    <xsl:param name="layer"/>
3032    <xsl:param name="elements"/>
3033    <xsl:param name="rule"/>
3034
3035
3036    <xsl:if test="$elements">
3037 
3038      <!-- elementCount is the number of elements we started with (just used for the progress message) -->
3039      <xsl:variable name="elementCount" select="count($elements)"/>
3040      <!-- If there's a proximity attribute on the rule then filter elements based on proximity -->
3041      <xsl:choose>
3042        <xsl:when test='$rule/@verticalProximity'>
3043          <xsl:variable name='nearbyElements1'>
3044            <xsl:call-template name="proximityFilter">
3045              <xsl:with-param name="elements" select="$elements"/>
3046              <xsl:with-param name="horizontalProximity" select="$rule/@horizontalProximity div 32"/>
3047              <xsl:with-param name="verticalProximity" select="$rule/@verticalProximity div 32"/>
3048            </xsl:call-template>
3049          </xsl:variable>
3050          <xsl:variable name='nearbyElements2'>
3051            <xsl:call-template name="proximityFilter">
3052              <xsl:with-param name="elements" select="exslt:node-set($nearbyElements1)/*"/>
3053              <xsl:with-param name="horizontalProximity" select="$rule/@horizontalProximity div 16"/>
3054              <xsl:with-param name="verticalProximity" select="$rule/@verticalProximity div 16"/>
3055            </xsl:call-template>
3056          </xsl:variable>
3057          <xsl:variable name='nearbyElements3'>
3058            <xsl:call-template name="proximityFilter">
3059              <xsl:with-param name="elements" select="exslt:node-set($nearbyElements2)/*"/>
3060              <xsl:with-param name="horizontalProximity" select="$rule/@horizontalProximity div 8"/>
3061              <xsl:with-param name="verticalProximity" select="$rule/@verticalProximity div 8"/>
3062            </xsl:call-template>
3063          </xsl:variable>
3064          <xsl:variable name='nearbyElements4'>
3065            <xsl:call-template name="proximityFilter">
3066              <xsl:with-param name="elements" select="exslt:node-set($nearbyElements3)/*"/>
3067              <xsl:with-param name="horizontalProximity" select="$rule/@horizontalProximity div 4"/>
3068              <xsl:with-param name="verticalProximity" select="$rule/@verticalProximity div 4"/>
3069            </xsl:call-template>
3070          </xsl:variable>
3071          <xsl:variable name='nearbyElements5'>
3072            <xsl:call-template name="proximityFilter">
3073              <xsl:with-param name="elements" select="exslt:node-set($nearbyElements4)/*"/>
3074              <xsl:with-param name="horizontalProximity" select="$rule/@horizontalProximity div 2"/>
3075              <xsl:with-param name="verticalProximity" select="$rule/@verticalProximity div 2"/>
3076            </xsl:call-template>
3077          </xsl:variable>
3078          <xsl:variable name='nearbyElementsRtf'>
3079            <xsl:call-template name="proximityFilter">
3080              <xsl:with-param name="elements" select="exslt:node-set($nearbyElements5)/*"/>
3081              <xsl:with-param name="horizontalProximity" select="$rule/@horizontalProximity"/>
3082              <xsl:with-param name="verticalProximity" select="$rule/@verticalProximity"/>
3083            </xsl:call-template>
3084          </xsl:variable>
3085
3086          <!-- Convert nearbyElements rtf to a node-set -->
3087          <xsl:variable name="nearbyElements" select="exslt:node-set($nearbyElementsRtf)/*"/>
3088
3089          <xsl:message>
3090            Processing &lt;rule e="<xsl:value-of select="$eBare"/>" k="<xsl:value-of select="$kBare"/>" v="<xsl:value-of select="$vBare"/>"
3091                        horizontalProximity="<xsl:value-of select="$rule/@horizontalProximity"/>" verticalProximity="<xsl:value-of select="$rule/@verticalProximity"/>" &gt;
3092            Matched by <xsl:value-of select="count($nearbyElements)"/> out of <xsl:value-of select="count($elements)"/> elements for layer <xsl:value-of select="$layer"/>.
3093          </xsl:message>
3094
3095          <xsl:apply-templates select="*">
3096            <xsl:with-param name="layer" select="$layer"/>
3097            <xsl:with-param name="elements" select="$nearbyElements"/>
3098            <xsl:with-param name="rule" select="$rule"/>
3099          </xsl:apply-templates>
3100        </xsl:when>
3101        <xsl:otherwise>
3102
3103          <xsl:message>
3104            Processing &lt;rule e="<xsl:value-of select="$eBare"/>" k="<xsl:value-of select="$kBare"/>" v="<xsl:value-of select="$vBare"/>" &gt;
3105            Matched by <xsl:value-of select="count($elements)"/> elements for layer <xsl:value-of select="$layer"/>.
3106          </xsl:message>
3107
3108          <xsl:apply-templates select="*">
3109            <xsl:with-param name="layer" select="$layer"/>
3110            <xsl:with-param name="elements" select="$elements"/>
3111            <xsl:with-param name="rule" select="$rule"/>
3112          </xsl:apply-templates>
3113        </xsl:otherwise>
3114      </xsl:choose>
3115    </xsl:if>
3116  </xsl:template>
3117
3118
3119  <!-- Select elements that are not within the specified distance from any other element -->
3120  <xsl:template name="proximityFilter">
3121    <xsl:param name="elements"/>
3122    <xsl:param name="horizontalProximity"/>
3123    <xsl:param name="verticalProximity"/>
3124   
3125    <!-- Offsetting the rectangle to the right gives better results when there are a solitary pair of adjacent elements. 
3126         One will get selected but the other won't.  Without the offset neither will get selected.  -->
3127    <xsl:variable name="topOffset" select="90  + $verticalProximity"/>
3128    <xsl:variable name="bottomOffset" select="90  - $verticalProximity"/>
3129    <xsl:variable name="leftOffset" select="180 - ($horizontalProximity * 0.5)"/>
3130    <xsl:variable name="rightOffset" select="180 + ($horizontalProximity * 1.5)"/>
3131
3132    <!-- Test each element to see if it is near any other element -->
3133    <xsl:for-each select="$elements">
3134      <xsl:variable name="id" select="@id"/>
3135      <xsl:variable name="top"    select="@lat + $topOffset"/>
3136      <xsl:variable name="bottom" select="@lat + $bottomOffset"/>
3137      <xsl:variable name="left"   select="@lon + $leftOffset"/>
3138      <xsl:variable name="right"  select="@lon + $rightOffset"/>
3139      <!-- Iterate through all of the elements currently selected and if there are no elements other
3140           than the current element in the rectangle then select this element -->
3141      <xsl:if test="not($elements[not(@id=$id)
3142                                  and (@lon+180) &lt; $right
3143                                  and (@lon+180) &gt; $left
3144                                  and (@lat+90)  &lt; $top
3145                                  and (@lat+90)  &gt; $bottom
3146                                  ]
3147                        )">
3148        <xsl:copy-of select="."/>
3149      </xsl:if>
3150    </xsl:for-each>
3151  </xsl:template>
3152
3153
3154  <!-- Draw SVG layers -->
3155  <xsl:template match="layer">
3156    <xsl:param name="elements"/>
3157    <xsl:param name="layer"/>
3158    <xsl:param name="rule"/>
3159
3160    <xsl:message>
3161      Processing SVG layer: <xsl:value-of select="@name"/> (at OSM layer <xsl:value-of select="$layer"/>)
3162    </xsl:message>
3163
3164    <xsl:variable name="opacity">
3165      <xsl:if test="@opacity">
3166        <xsl:value-of select="concat('opacity:',@opacity,';')"/>
3167      </xsl:if>
3168    </xsl:variable>
3169
3170    <xsl:variable name="display">
3171      <xsl:if test="(@display='none') or (@display='off')">
3172        <xsl:text>display:none;</xsl:text>
3173      </xsl:if>
3174    </xsl:variable>
3175
3176    <g inkscape:groupmode="layer" id="{@name}-{$layer}" inkscape:label="{@name}">
3177      <xsl:if test="concat($opacity,$display)!=''">
3178        <xsl:attribute name="style">
3179          <xsl:value-of select="concat($opacity,$display)"/>
3180        </xsl:attribute>
3181      </xsl:if>
3182      <xsl:apply-templates select="*">
3183        <xsl:with-param name="layer" select="$layer"/>
3184        <xsl:with-param name="elements" select="$elements"/>
3185      </xsl:apply-templates>
3186    </g>
3187
3188  </xsl:template>
3189
3190
3191  <!-- Draw map border -->
3192  <xsl:template name="drawBorder">
3193    <!-- dasharray definitions here can be overridden in stylesheet -->
3194    <g id="border" inkscape:groupmode="layer" inkscape:label="Map Border">
3195      <line id="border-left-casing" x1="0" y1="0" x2="0" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
3196      <line id="border-top-casing" x1="0" y1="0" x2="{$documentWidth}" y2="0" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
3197      <line id="border-bottom-casing" x1="0" y1="{$documentHeight}" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
3198      <line id="border-right-casing" x1="{$documentWidth}" y1="0" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
3199
3200      <line id="border-left-core" x1="0" y1="0" x2="0" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
3201      <line id="border-top-core" x1="0" y1="0" x2="{$documentWidth}" y2="0" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
3202      <line id="border-bottom-core" x1="0" y1="{$documentHeight}" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
3203      <line id="border-right-core" x1="{$documentWidth}" y1="0" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
3204    </g>
3205  </xsl:template>
3206
3207
3208  <!-- Draw a grid over the map in 1km increments -->
3209  <xsl:template name="drawGrid">
3210    <g id="grid" inkscape:groupmode="layer" inkscape:label="Grid">
3211      <xsl:call-template name="drawGridHorizontals">
3212        <xsl:with-param name="line" select="'1'"/>
3213      </xsl:call-template>
3214      <xsl:call-template name="drawGridVerticals">
3215        <xsl:with-param name="line" select="'1'"/>
3216      </xsl:call-template>
3217    </g>
3218  </xsl:template>
3219
3220
3221  <xsl:template name="drawGridHorizontals">
3222    <xsl:param name="line"/>
3223    <xsl:if test="($line*$km) &lt; $documentHeight">
3224      <line id="grid-hori-{$line}" x1="0px" y1="{$line*$km}px" x2="{$documentWidth}px" y2="{$line*$km}px" class="map-grid-line"/>
3225      <xsl:call-template name="drawGridHorizontals">
3226        <xsl:with-param name="line" select="$line+1"/>
3227      </xsl:call-template>
3228    </xsl:if>
3229  </xsl:template>
3230
3231
3232  <xsl:template name="drawGridVerticals">
3233    <xsl:param name="line"/>
3234    <xsl:if test="($line*$km) &lt; $documentWidth">
3235      <line id="grid-vert-{$line}" x1="{$line*$km}px" y1="0px" x2="{$line*$km}px" y2="{$documentHeight}px" class="map-grid-line"/>
3236      <xsl:call-template name="drawGridVerticals">
3237        <xsl:with-param name="line" select="$line+1"/>
3238      </xsl:call-template>
3239    </xsl:if>
3240  </xsl:template>
3241
3242
3243  <!-- Draw map title -->
3244  <xsl:template name="drawTitle">
3245    <xsl:param name="title"/>
3246
3247    <xsl:variable name="x" select="$documentWidth div 2"/>
3248    <xsl:variable name="y" select="30"/>
3249
3250    <g id="marginalia-title" inkscape:groupmode="layer" inkscape:label="Title">
3251      <rect id="marginalia-title-background" x="0px" y="0px" height="{$marginaliaTopHeight - 5}px" width="{$documentWidth}px" class="map-title-background"/>
3252      <text id="marginalia-title-text" class="map-title" x="{$x}" y="{$y}">
3253        <xsl:value-of select="$title"/>
3254      </text>
3255    </g>
3256  </xsl:template>
3257
3258
3259  <!-- Draw an approximate scale in the bottom left corner of the map -->
3260  <xsl:template name="drawScale">
3261    <xsl:variable name="x1" select="14"/>
3262    <xsl:variable name="y1" select="round(($documentHeight)+((($bottomLeftLatitude)-(number($bottomLeftLatitude)))*10000*$scale*$projection))+28"/>
3263    <xsl:variable name="x2" select="$x1+$km"/>
3264    <xsl:variable name="y2" select="$y1"/>
3265
3266    <g id="marginalia-scale" inkscape:groupmode="layer" inkscape:label="Scale">
3267      <line id="marginalia-scale-casing" class="map-scale-casing" x1="{$x1}" y1="{$y1}" x2="{$x2}" y2="{$y2}"/>
3268
3269      <line id="marginalia-scale-core" class="map-scale-core" stroke-dasharray="{($km div 10)}" x1="{$x1}" y1="{$y1}" x2="{$x2}" y2="{$y2}"/>
3270
3271      <line id="marginalia-scale-bookend-from" class="map-scale-bookend" x1="{$x1}" y1="{$y1 + 2}" x2="{$x1}" y2="{$y1 - 10}"/>
3272
3273      <line id="marginalia-scale-bookend-to" class="map-scale-bookend" x1="{$x2}" y1="{$y2 + 2}" x2="{$x2}" y2="{$y2 - 10}"/>
3274
3275      <text id="marginalia-scale-text-from" class="map-scale-caption" x="{$x1}" y="{$y1 - 10}">0</text>
3276
3277      <text id="marginalia-scale-text-to" class="map-scale-caption" x="{$x2}" y="{$y2 - 10}">1km</text>
3278    </g>
3279  </xsl:template>
3280
3281
3282  <!-- Create a comment in SVG source code and RDF description of license -->
3283  <xsl:template name="metadata">
3284
3285    <xsl:comment>
3286
3287      Copyright (c) <xsl:value-of select="$year"/> OpenStreetMap
3288      www.openstreetmap.org
3289      This work is licensed under the
3290      Creative Commons Attribution-ShareAlike 2.0 License.
3291      http://creativecommons.org/licenses/by-sa/2.0/
3292
3293    </xsl:comment>
3294    <metadata id="metadata">
3295      <rdf:RDF xmlns="http://web.resource.org/cc/">
3296        <cc:Work rdf:about="">
3297          <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/"/>
3298          <dc:format>image/svg+xml</dc:format>
3299          <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
3300          <dc:title>
3301            <xsl:value-of select="$title"/>
3302          </dc:title>
3303          <dc:date>
3304            <xsl:value-of select="$date"/>
3305          </dc:date>
3306          <dc:source>http://www.openstreetmap.org/</dc:source>
3307        </cc:Work>
3308        <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
3309          <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
3310          <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
3311          <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
3312          <cc:requires rdf:resource="http://web.resource.org/cc/Notice"/>
3313          <cc:requires rdf:resource="http://web.resource.org/cc/Attribution"/>
3314          <cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/>
3315        </cc:License>
3316      </rdf:RDF>
3317    </metadata>
3318  </xsl:template>
3319
3320  <!-- Create a license logo and description in the image -->
3321  <xsl:template name="in-image-license">
3322    <xsl:param name="dx"/>
3323    <xsl:param name="dy"/>
3324
3325    <g id="license" inkscape:groupmode="layer" inkscape:label="Copyright" transform="translate({$dx},{$dy})">
3326      <style type="text/css">
3327        <![CDATA[
3328                .license-text {
3329                    text-anchor: start;
3330                    font-family: "DejaVu Sans",sans-serif;
3331                    font-size: 6px;
3332                    fill: black;
3333                }
3334            ]]>
3335      </style>
3336      <a id="license-cc-logo-link" xlink:href="http://creativecommons.org/licenses/by-sa/2.0/">
3337        <g id="license-cc-logo" transform="scale(0.5,0.5) translate(-604,-49)">
3338          <path id="path3817_2_" nodetypes="ccccccc" d="M
3339                    182.23532,75.39014 L 296.29928,75.59326 C
3340                    297.89303,75.59326 299.31686,75.35644 299.31686,78.77344 L
3341                    299.17721,116.34033 L 179.3569,116.34033 L
3342                    179.3569,78.63379 C 179.3569,76.94922 179.51999,75.39014
3343                    182.23532,75.39014 z " style="fill:#aab2ab"/>
3344          <g id="g5908_2_" transform="matrix(0.872921,0,0,0.872921,50.12536,143.2144)">
3345            <path id="path5906_2_" type="arc" cx="296.35416"
3346            cy="264.3577" ry="22.939548" rx="22.939548" d="M
3347                        187.20944,-55.6792 C 187.21502,-46.99896
3348                        180.18158,-39.95825 171.50134,-39.95212 C
3349                        162.82113,-39.94708 155.77929,-46.97998
3350                        155.77426,-55.66016 C 155.77426,-55.66687
3351                        155.77426,-55.67249 155.77426,-55.6792 C
3352                        155.76922,-64.36054 162.80209,-71.40125
3353                        171.48233,-71.40631 C 180.16367,-71.41193
3354                        187.20441,-64.37842 187.20944,-55.69824 C
3355                        187.20944,-55.69263 187.20944,-55.68591
3356                        187.20944,-55.6792 z " style="fill:white"/>
3357            <g id="g5706_2_" transform="translate(-289.6157,99.0653)">
3358              <path id="path5708_2_" d="M 473.88455,-167.54724 C
3359                            477.36996,-164.06128 479.11294,-159.79333
3360                            479.11294,-154.74451 C 479.11294,-149.69513
3361                            477.40014,-145.47303 473.9746,-142.07715 C
3362                            470.33929,-138.50055 466.04281,-136.71283
3363                            461.08513,-136.71283 C 456.18736,-136.71283
3364                            451.96526,-138.48544 448.42003,-142.03238 C
3365                            444.87419,-145.57819 443.10158,-149.81537
3366                            443.10158,-154.74451 C 443.10158,-159.6731
3367                            444.87419,-163.94049 448.42003,-167.54724 C
3368                            451.87523,-171.03375 456.09728,-172.77618
3369                            461.08513,-172.77618 C 466.13342,-172.77618
3370                            470.39914,-171.03375 473.88455,-167.54724 z M
3371                            450.76657,-165.20239 C 447.81982,-162.22601
3372                            446.34701,-158.7395 446.34701,-154.74005 C
3373                            446.34701,-150.7417 447.80529,-147.28485
3374                            450.72125,-144.36938 C 453.63778,-141.45288
3375                            457.10974,-139.99462 461.1383,-139.99462 C
3376                            465.16683,-139.99462 468.66848,-141.46743
3377                            471.64486,-144.41363 C 474.47076,-147.14947
3378                            475.88427,-150.59069 475.88427,-154.74005 C
3379                            475.88427,-158.85809 474.44781,-162.35297
3380                            471.57659,-165.22479 C 468.70595,-168.09546
3381                            465.22671,-169.53131 461.1383,-169.53131 C
3382                            457.04993,-169.53131 453.59192,-168.08813
3383                            450.76657,-165.20239 z M 458.52106,-156.49927 C
3384                            458.07074,-157.4809 457.39673,-157.9715
3385                            456.49781,-157.9715 C 454.90867,-157.9715
3386                            454.11439,-156.90198 454.11439,-154.763 C
3387                            454.11439,-152.62341 454.90867,-151.55389
3388                            456.49781,-151.55389 C 457.54719,-151.55389
3389                            458.29676,-152.07519 458.74647,-153.11901 L
3390                            460.94923,-151.94598 C 459.8993,-150.0805
3391                            458.32417,-149.14697 456.22374,-149.14697 C
3392                            454.60384,-149.14697 453.30611,-149.64367
3393                            452.33168,-150.63653 C 451.35561,-151.62994
3394                            450.86894,-152.99926 450.86894,-154.7445 C
3395                            450.86894,-156.46008 451.37123,-157.82159
3396                            452.37642,-158.83013 C 453.38161,-159.83806
3397                            454.63347,-160.34264 456.13423,-160.34264 C
3398                            458.35435,-160.34264 459.94407,-159.46776
3399                            460.90504,-157.71978 L 458.52106,-156.49927 z M
3400                            468.8844,-156.49927 C 468.43353,-157.4809
3401                            467.77292,-157.9715 466.90201,-157.9715 C
3402                            465.28095,-157.9715 464.46988,-156.90198
3403                            464.46988,-154.763 C 464.46988,-152.62341
3404                            465.28095,-151.55389 466.90201,-151.55389 C
3405                            467.95304,-151.55389 468.68918,-152.07519
3406                            469.10925,-153.11901 L 471.36126,-151.94598 C
3407                            470.31301,-150.0805 468.74007,-149.14697
3408                            466.64358,-149.14697 C 465.02587,-149.14697
3409                            463.73095,-149.64367 462.75711,-150.63653 C
3410                            461.78494,-151.62994 461.29773,-152.99926
3411                            461.29773,-154.7445 C 461.29773,-156.46008
3412                            461.79221,-157.82159 462.78061,-158.83013 C
3413                            463.76843,-159.83806 465.02588,-160.34264
3414                            466.55408,-160.34264 C 468.77027,-160.34264
3415                            470.35776,-159.46776 471.3154,-157.71978 L
3416                            468.8844,-156.49927 z "/>
3417            </g>
3418          </g>
3419          <path d="M 297.29639,74.91064 L 181.06688,74.91064 C
3420                    179.8203,74.91064 178.80614,75.92529 178.80614,77.17187 L
3421                    178.80614,116.66748 C 178.80614,116.94922
3422                    179.03466,117.17822 179.31639,117.17822 L
3423                    299.04639,117.17822 C 299.32813,117.17822
3424                    299.55713,116.94922 299.55713,116.66748 L
3425                    299.55713,77.17188 C 299.55713,75.92529 298.54297,74.91064
3426                    297.29639,74.91064 z M 181.06688,75.93213 L
3427                    297.29639,75.93213 C 297.97998,75.93213 298.53565,76.48828
3428                    298.53565,77.17188 C 298.53565,77.17188 298.53565,93.09131
3429                    298.53565,104.59034 L 215.4619,104.59034 C
3430                    212.41698,110.09571 206.55077,113.83399 199.81835,113.83399
3431                    C 193.083,113.83399 187.21825,110.09913 184.1748,104.59034
3432                    L 179.82666,104.59034 C 179.82666,93.09132
3433                    179.82666,77.17188 179.82666,77.17188 C 179.82664,76.48828
3434                    180.38329,75.93213 181.06688,75.93213 z " id="frame"/>
3435          <g enable-background="new" id="g2821">
3436            <path d="M 265.60986,112.8833 C 265.68994,113.03906
3437                        265.79736,113.16504 265.93115,113.26172 C
3438                        266.06494,113.35791 266.22119,113.42969
3439                        266.40088,113.47608 C 266.58154,113.52296
3440                        266.76807,113.54639 266.96045,113.54639 C
3441                        267.09033,113.54639 267.22998,113.53565
3442                        267.3794,113.51368 C 267.52784,113.4922
3443                        267.66749,113.44972 267.79835,113.3877 C
3444                        267.92823,113.32569 268.03761,113.23975
3445                        268.12355,113.13086 C 268.21144,113.02197
3446                        268.25441,112.88379 268.25441,112.71533 C
3447                        268.25441,112.53515 268.19679,112.38916
3448                        268.08156,112.27685 C 267.9673,112.16455
3449                        267.81594,112.07177 267.62941,111.99658 C
3450                        267.44386,111.92236 267.23195,111.85693
3451                        266.9966,111.80078 C 266.76027,111.74463
3452                        266.52101,111.68262 266.27883,111.61377 C
3453                        266.02981,111.55176 265.78762,111.47559
3454                        265.55129,111.38525 C 265.31594,111.29541
3455                        265.10402,111.17822 264.9175,111.03515 C
3456                        264.73098,110.89208 264.58059,110.71337
3457                        264.46535,110.49853 C 264.35109,110.28369
3458                        264.29347,110.02392 264.29347,109.71923 C
3459                        264.29347,109.37646 264.36671,109.07958
3460                        264.51222,108.82763 C 264.6587,108.57568
3461                        264.85011,108.36572 265.08644,108.19726 C
3462                        265.32179,108.02929 265.58937,107.90478
3463                        265.8882,107.82372 C 266.18605,107.74315
3464                        266.48488,107.70263 266.78273,107.70263 C
3465                        267.13136,107.70263 267.46535,107.74169
3466                        267.78566,107.81982 C 268.105,107.89746
3467                        268.39015,108.02392 268.6382,108.19824 C
3468                        268.88722,108.37256 269.08449,108.59521
3469                        269.23097,108.86621 C 269.37648,109.13721
3470                        269.44972,109.46582 269.44972,109.85156 L
3471                        268.02784,109.85156 C 268.01514,109.65234
3472                        267.97315,109.4873 267.90284,109.35693 C
3473                        267.83155,109.22607 267.73682,109.12353
3474                        267.61964,109.04834 C 267.50148,108.97412
3475                        267.36671,108.9209 267.21534,108.89014 C
3476                        267.063,108.85889 266.89796,108.84326
3477                        266.71827,108.84326 C 266.60108,108.84326
3478                        266.48292,108.85596 266.36573,108.88037 C
3479                        266.24757,108.90576 266.14112,108.94922
3480                        266.04542,109.01123 C 265.94874,109.07373
3481                        265.86964,109.15137 265.80812,109.24463 C
3482                        265.7466,109.33838 265.71535,109.45654
3483                        265.71535,109.59961 C 265.71535,109.73047
3484                        265.73976,109.83643 265.78957,109.91699 C
3485                        265.83937,109.99804 265.93801,110.07275
3486                        266.08352,110.14111 C 266.22903,110.20947
3487                        266.43118,110.27832 266.68899,110.34668 C
3488                        266.9468,110.41504 267.28372,110.50244
3489                        267.70071,110.60791 C 267.82473,110.63281
3490                        267.99661,110.67822 268.21731,110.74365 C
3491                        268.43801,110.80908 268.65676,110.91308
3492                        268.87454,111.05615 C 269.09231,111.1997
3493                        269.27981,111.39111 269.43899,111.63037 C
3494                        269.59719,111.87012 269.67629,112.17676
3495                        269.67629,112.55029 C 269.67629,112.85547
3496                        269.61672,113.13867 269.49856,113.3999 C
3497                        269.3804,113.66162 269.20461,113.8872
3498                        268.97122,114.07666 C 268.73782,114.26709
3499                        268.44876,114.41455 268.10403,114.52051 C
3500                        267.75833,114.62647 267.35794,114.6792
3501                        266.90481,114.6792 C 266.53762,114.6792
3502                        266.18118,114.63379 265.83547,114.54346 C
3503                        265.49074,114.45313 265.18508,114.31104
3504                        264.92043,114.11768 C 264.65676,113.92432
3505                        264.4468,113.67774 264.29055,113.37891 C
3506                        264.13528,113.07959 264.06106,112.7251
3507                        264.06692,112.31397 L 265.4888,112.31397 C
3508                        265.48877,112.53809 265.52881,112.72803
3509                        265.60986,112.8833 z " id="path2823"
3510            style="fill:white"/>
3511            <path d="M 273.8667,107.8667 L
3512                        276.35986,114.53076 L 274.8374,114.53076 L
3513                        274.33349,113.04638 L 271.84033,113.04638 L
3514                        271.31787,114.53076 L 269.84326,114.53076 L
3515                        272.36377,107.8667 L 273.8667,107.8667 z M
3516                        273.95068,111.95264 L 273.11084,109.50928 L
3517                        273.09229,109.50928 L 272.22315,111.95264 L
3518                        273.95068,111.95264 z " id="path2825"
3519            style="fill:white"/>
3520          </g>
3521          <g enable-background="new" id="g2827">
3522            <path d="M 239.17821,107.8667 C 239.49559,107.8667
3523                        239.78563,107.89502 240.04735,107.95068 C
3524                        240.30907,108.00683 240.53368,108.09863
3525                        240.72118,108.22607 C 240.9077,108.35351
3526                        241.05321,108.52295 241.15575,108.73437 C
3527                        241.25829,108.94579 241.31005,109.20703
3528                        241.31005,109.51806 C 241.31005,109.854
3529                        241.23388,110.13329 241.08056,110.35742 C
3530                        240.92822,110.58154 240.70165,110.76465
3531                        240.40283,110.90771 C 240.81494,111.02587
3532                        241.12256,111.23291 241.32568,111.5288 C
3533                        241.5288,111.82469 241.63037,112.18114
3534                        241.63037,112.59814 C 241.63037,112.93408
3535                        241.56494,113.22509 241.43408,113.47119 C
3536                        241.30322,113.7168 241.12646,113.91748
3537                        240.90576,114.07324 C 240.68408,114.229
3538                        240.43115,114.34424 240.14795,114.41845 C
3539                        239.86377,114.49365 239.57275,114.53075
3540                        239.27295,114.53075 L 236.03662,114.53075 L
3541                        236.03662,107.86669 L 239.17821,107.86669 L
3542                        239.17821,107.8667 z M 238.99071,110.56201 C
3543                        239.25243,110.56201 239.46727,110.5 239.63622,110.37597
3544                        C 239.80419,110.25146 239.88817,110.05029
3545                        239.88817,109.77099 C 239.88817,109.61572
3546                        239.85985,109.48828 239.80419,109.38915 C
3547                        239.74755,109.28954 239.67333,109.21239
3548                        239.57958,109.15624 C 239.48583,109.10058
3549                        239.37841,109.06151 239.25731,109.04003 C
3550                        239.13524,109.01806 239.00926,109.00732
3551                        238.8784,109.00732 L 237.50535,109.00732 L
3552                        237.50535,110.56201 L 238.99071,110.56201 z M
3553                        239.07664,113.39014 C 239.22019,113.39014
3554                        239.35691,113.37647 239.48777,113.34815 C
3555                        239.61863,113.32032 239.73484,113.27344
3556                        239.83445,113.2085 C 239.93406,113.14307
3557                        240.01316,113.0542 240.07273,112.94239 C
3558                        240.1323,112.83058 240.1616,112.68751
3559                        240.1616,112.51319 C 240.1616,112.17139
3560                        240.06492,111.92725 239.87156,111.78126 C
3561                        239.6782,111.63527 239.42234,111.56202
3562                        239.10496,111.56202 L 237.50535,111.56202 L
3563                        237.50535,113.39014 L 239.07664,113.39014 z "
3564            id="path2829" style="fill:white"/>
3565            <path d="M 241.88914,107.8667 L 243.53269,107.8667 L
3566                        245.09324,110.49854 L 246.64402,107.8667 L
3567                        248.27781,107.8667 L 245.80418,111.97315 L
3568                        245.80418,114.53077 L 244.33543,114.53077 L
3569                        244.33543,111.93604 L 241.88914,107.8667 z "
3570            id="path2831" style="fill:white"/>
3571          </g>
3572          <g id="g6316_1_" transform="matrix(0.624995,0,0,0.624995,391.2294,176.9332)">
3573            <path id="path6318_1_" type="arc" cx="475.97119"
3574            cy="252.08646" ry="29.209877" rx="29.209877" d="M
3575                        -175.0083,-139.1153 C -175.00204,-129.7035
3576                        -182.62555,-122.06751 -192.03812,-122.06049 C
3577                        -201.44913,-122.05341 -209.08512,-129.67774
3578                        -209.09293,-139.09028 C -209.09293,-139.09809
3579                        -209.09293,-139.10749 -209.09293,-139.1153 C
3580                        -209.09919,-148.52784 -201.47413,-156.1623
3581                        -192.06311,-156.17011 C -182.65054,-156.17713
3582                        -175.01456,-148.55207 -175.0083,-139.14026 C
3583                        -175.0083,-139.13092 -175.0083,-139.1239
3584                        -175.0083,-139.1153 z " style="fill:white"/>
3585            <g id="g6320_1_" transform="translate(-23.9521,-89.72962)">
3586              <path id="path6322_1_" d="M -168.2204,-68.05536 C
3587                            -173.39234,-68.05536 -177.76892,-66.25067
3588                            -181.35175,-62.64203 C -185.02836,-58.90759
3589                            -186.86588,-54.48883 -186.86588,-49.38568 C
3590                            -186.86588,-44.28253 -185.02836,-39.89416
3591                            -181.35175,-36.22308 C -177.67673,-32.55114
3592                            -173.29859,-30.71521 -168.2204,-30.71521 C
3593                            -163.07974,-30.71521 -158.62503,-32.56677
3594                            -154.85312,-36.26996 C -151.30307,-39.78558
3595                            -149.52652,-44.15827 -149.52652,-49.38568 C
3596                            -149.52652,-54.6123 -151.33432,-59.03265
3597                            -154.94843,-62.64203 C -158.5625,-66.25067
3598                            -162.98599,-68.05536 -168.2204,-68.05536 z M
3599                            -168.17352,-64.69519 C -163.936,-64.69519
3600                            -160.33752,-63.20221 -157.37655,-60.21466 C
3601                            -154.38748,-57.25836 -152.89214,-53.64899
3602                            -152.89214,-49.38568 C -152.89214,-45.09186
3603                            -154.35466,-41.52856 -157.28438,-38.69653 C
3604                            -160.36876,-35.64727 -163.99849,-34.12304
3605                            -168.17351,-34.12304 C -172.34856,-34.12304
3606                            -175.94701,-35.63244 -178.96892,-38.64965 C
3607                            -181.9908,-41.66918 -183.50176,-45.24657
3608                            -183.50176,-49.38567 C -183.50176,-53.52398
3609                            -181.97518,-57.13414 -178.92205,-60.21465 C
3610                            -175.9939,-63.20221 -172.41107,-64.69519
3611                            -168.17352,-64.69519 z "/>
3612              <path id="path6324_1_" d="M -176.49548,-52.02087 C
3613                            -175.75171,-56.71856 -172.44387,-59.22949
3614                            -168.30008,-59.22949 C -162.33911,-59.22949
3615                            -158.70783,-54.90448 -158.70783,-49.1372 C
3616                            -158.70783,-43.50982 -162.57194,-39.13793
3617                            -168.39383,-39.13793 C -172.39856,-39.13793
3618                            -175.98297,-41.60277 -176.63611,-46.43877 L
3619                            -171.93292,-46.43877 C -171.7923,-43.92778
3620                            -170.1626,-43.04418 -167.83447,-43.04418 C
3621                            -165.1813,-43.04418 -163.4563,-45.50908
3622                            -163.4563,-49.27709 C -163.4563,-53.22942
3623                            -164.94693,-55.32244 -167.74228,-55.32244 C
3624                            -169.79074,-55.32244 -171.55948,-54.57787
3625                            -171.93292,-52.02087 L -170.56418,-52.02789 L
3626                            -174.26734,-48.32629 L -177.96894,-52.02789 L
3627                            -176.49548,-52.02087 z "/>
3628            </g>
3629          </g>
3630          <g id="g2838">
3631            <circle cx="242.56226" cy="90.224609" r="10.8064" id="circle2840" style="fill:white"/>
3632            <g id="g2842">
3633              <path d="M 245.68994,87.09766 C 245.68994,86.68116
3634                            245.35205,86.34424 244.93603,86.34424 L
3635                            240.16357,86.34424 C 239.74755,86.34424
3636                            239.40966,86.68115 239.40966,87.09766 L
3637                            239.40966,91.87061 L 240.74071,91.87061 L
3638                            240.74071,97.52295 L 244.3579,97.52295 L
3639                            244.3579,91.87061 L 245.68993,91.87061 L
3640                            245.68993,87.09766 L 245.68994,87.09766 z "
3641              id="path2844"/>
3642              <circle cx="242.5498" cy="84.083008" r="1.63232" id="circle2846"/>
3643            </g>
3644            <path clip-rule="evenodd" d="M 242.53467,78.31836 C
3645                        239.30322,78.31836 236.56641,79.4458 234.32715,81.70215
3646                        C 232.0293,84.03516 230.88086,86.79736
3647                        230.88086,89.98633 C 230.88086,93.1753
3648                        232.0293,95.91846 234.32715,98.21338 C
3649                        236.625,100.50781 239.36133,101.65527
3650                        242.53467,101.65527 C 245.74756,101.65527
3651                        248.53272,100.49853 250.88819,98.18359 C
3652                        253.10889,95.98681 254.21827,93.2539 254.21827,89.98632
3653                        C 254.21827,86.71874 253.08936,83.95751
3654                        250.83057,81.70214 C 248.57178,79.4458
3655                        245.80615,78.31836 242.53467,78.31836 z M
3656                        242.56396,80.41797 C 245.2124,80.41797
3657                        247.46142,81.35156 249.31103,83.21875 C
3658                        251.18115,85.06592 252.11572,87.32227
3659                        252.11572,89.98633 C 252.11572,92.66992
3660                        251.20068,94.89746 249.36963,96.66699 C
3661                        247.4419,98.57275 245.17334,99.52539 242.56397,99.52539
3662                        C 239.9546,99.52539 237.70557,98.58252
3663                        235.81739,96.6958 C 233.92774,94.80957
3664                        232.98389,92.57324 232.98389,89.98633 C
3665                        232.98389,87.3999 233.93799,85.14404 235.84619,83.21875
3666                        C 237.67676,81.35156 239.9165,80.41797
3667                        242.56396,80.41797 z " id="path2848"
3668            style="fill-rule:evenodd"/>
3669          </g>
3670        </g>
3671      </a>
3672      <a id="license-osm-link" xlink:href="http://www.openstreetmap.org/">
3673        <g transform="translate(-210,10)" id="license-osm-text">
3674          <text class="license-text" dx="0" dy="0">
3675            Copyright © <xsl:value-of select="$year"/> OpenStreetMap (openstreetmap.org)
3676          </text>
3677        </g>
3678      </a>
3679      <a id="license-cc-text-link" xlink:href="http://creativecommons.org/licenses/by-sa/2.0/">
3680        <g transform="translate(-150,18)" id="license-cc-text">
3681          <text class="license-text" dx="0" dy="0">This work is licensed under the Creative</text>
3682          <text class="license-text" dx="0" dy="8">Commons Attribution-ShareAlike 2.0 License.</text>
3683          <text class="license-text" dx="0" dy="16">http://creativecommons.org/licenses/by-sa/2.0/</text>
3684        </g>
3685      </a>
3686    </g>
3687  </xsl:template>
3688
3689
3690  <!-- Draw zoom controls -->
3691  <xsl:template name="zoomControl">
3692    <defs>
3693
3694      <style type="text/css">
3695        .fancyButton {
3696        stroke: #8080ff;
3697        stroke-width: 2px;
3698        fill: #fefefe;
3699        }
3700        .fancyButton:hover {
3701        stroke: red;
3702        }
3703      </style>
3704
3705      <filter id="fancyButton" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="350">
3706        <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>
3707        <feOffset in="blur" dx="2" dy="2" result="offsetBlur"/>
3708        <feSpecularLighting in="blur" surfaceScale="5" specularConstant=".75" specularExponent="20" lighting-color="white" result="specOut">
3709          <fePointLight x="-5000" y="-10000" z="7000"/>
3710        </feSpecularLighting>
3711        <feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut"/>
3712        <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="litPaint"/>
3713        <feMerge>
3714          <feMergeNode in="offsetBlur"/>
3715          <feMergeNode in="litPaint"/>
3716        </feMerge>
3717      </filter>
3718      <symbol id="panDown" viewBox="0 0 19 19" class="fancyButton">
3719        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
3720        <path d="M 9.5,5 L 9.5,14"/>
3721      </symbol>
3722      <symbol id="panUp" viewBox="0 0 19 19" class="fancyButton">
3723        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
3724        <path d="M 9.5,5 L 9.5,14"/>
3725      </symbol>
3726      <symbol id="panLeft" viewBox="0 0 19 19" class="fancyButton">
3727        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
3728        <path d="M 5,9.5 L 14,9.5"/>
3729      </symbol>
3730      <symbol id="panRight" viewBox="0 0 19 19" class="fancyButton">
3731        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
3732        <path d="M 5,9.5 L 14,9.5"/>
3733      </symbol>
3734      <symbol id="zoomIn" viewBox="0 0 19 19" class="fancyButton">
3735        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
3736        <path d="M 5,9.5 L 14,9.5 M 9.5,5 L 9.5,14"/>
3737      </symbol>
3738      <symbol id="zoomOut" viewBox="0 0 19 19" class="fancyButton">
3739        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
3740        <path d="M 5,9.5 L 14,9.5"/>
3741      </symbol>
3742
3743    </defs>
3744
3745    <g id="gPanDown" filter="url(#fancyButton)" onclick="fnPan('down')">
3746      <use x="18px" y="60px" xlink:href="#panDown" width="14px" height="14px"/>
3747    </g>
3748    <g id="gPanRight" filter="url(#fancyButton)" onclick="fnPan('right')">
3749      <use x="8px" y="70px" xlink:href="#panRight" width="14px" height="14px"/>
3750    </g>
3751    <g id="gPanLeft" filter="url(#fancyButton)" onclick="fnPan('left')">
3752      <use x="28px" y="70px" xlink:href="#panLeft" width="14px" height="14px"/>
3753    </g>
3754    <g id="gPanUp" filter="url(#fancyButton)" onclick="fnPan('up')">
3755      <use x="18px" y="80px" xlink:href="#panUp" width="14px" height="14px"/>
3756    </g>
3757
3758    <xsl:variable name="x1" select="25"/>
3759    <xsl:variable name="y1" select="105"/>
3760    <xsl:variable name="x2" select="25"/>
3761    <xsl:variable name="y2" select="300"/>
3762
3763    <line style="stroke-width: 10; stroke-linecap: butt; stroke: #8080ff;">
3764      <xsl:attribute name="x1">
3765        <xsl:value-of select="$x1"/>
3766      </xsl:attribute>
3767      <xsl:attribute name="y1">
3768        <xsl:value-of select="$y1"/>
3769      </xsl:attribute>
3770      <xsl:attribute name="x2">
3771        <xsl:value-of select="$x2"/>
3772      </xsl:attribute>
3773      <xsl:attribute name="y2">
3774        <xsl:value-of select="$y2"/>
3775      </xsl:attribute>
3776    </line>
3777
3778    <line style="stroke-width: 8; stroke-linecap: butt; stroke: white; stroke-dasharray: 10,1;">
3779      <xsl:attribute name="x1">
3780        <xsl:value-of select="$x1"/>
3781      </xsl:attribute>
3782      <xsl:attribute name="y1">
3783        <xsl:value-of select="$y1"/>
3784      </xsl:attribute>
3785      <xsl:attribute name="x2">
3786        <xsl:value-of select="$x2"/>
3787      </xsl:attribute>
3788      <xsl:attribute name="y2">
3789        <xsl:value-of select="$y2"/>
3790      </xsl:attribute>
3791    </line>
3792
3793    <!-- Need to use onmousedown because onclick is interfered with by the onmousedown handler for panning -->
3794    <g id="gZoomIn" filter="url(#fancyButton)" onmousedown="fnZoom('in')">
3795      <use x="15.5px" y="100px" xlink:href="#zoomIn" width="19px" height="19px"/>
3796    </g>
3797
3798    <!-- Need to use onmousedown because onclick is interfered with by the onmousedown handler for panning -->
3799    <g id="gZoomOut" filter="url(#fancyButton)" onmousedown="fnZoom('out')">
3800      <use x="15.5px" y="288px" xlink:href="#zoomOut" width="19px" height="19px"/>
3801    </g>
3802  </xsl:template>
3803
3804  <xsl:template name="javaScript">
3805    <script>
3806      /*
3807
3808      Osmarender
3809
3810      interactive.js
3811
3812      */
3813
3814      function fnResize() {
3815      fnResizeElement("gAttribution")
3816      fnResizeElement("gLicense")
3817      fnResizeElement("gZoomIn")
3818      fnResizeElement("gZoomOut")
3819      }
3820
3821
3822      function fnResizeElement(e) {
3823      //
3824      var oSVG,scale,currentTranslateX,currentTranslateY,oe
3825      //
3826      oSVG=document.rootElement
3827      scale=1/oSVG.currentScale
3828      currentTranslateX=oSVG.currentTranslate.x
3829      currentTranslateY=oSVG.currentTranslate.y
3830      oe=document.getElementById(e)
3831      if (oe) oe.setAttributeNS(null,"transform","scale("+scale+","+scale+") translate("+(-currentTranslateX)+","+(-currentTranslateY)+")")
3832      }
3833
3834
3835      function fnToggleImage(osmImage) {
3836      var xlink = 'http://www.w3.org/1999/xlink';
3837      ogThumbnail=document.getElementById('gThumbnail')
3838      if (ogThumbnail.getAttributeNS(null,"visibility")=="visible") fnHideImage()
3839      else {
3840      ogThumbnail.setAttributeNS(null,"visibility","visible")
3841      oThumbnail=document.getElementById('thumbnail')
3842      oThumbnail.setAttributeNS(xlink,"href",osmImage)
3843      }
3844      }
3845
3846      function fnHideImage() {
3847      ogThumbnail=document.getElementById('gThumbnail')
3848      ogThumbnail.setAttributeNS(null,"visibility","hidden")
3849      }
3850
3851
3852      /* The following code originally written by Jonathan Watt (http://jwatt.org/), Aug. 2005 */
3853
3854      if (!window)
3855      window = this;
3856
3857
3858      function fnOnLoad(evt) {
3859      if (!document) window.document = evt.target.ownerDocument
3860      }
3861
3862
3863      /**
3864      * Event handlers to change the current user space for the zoom and pan
3865      * controls to make them appear to be scale invariant.
3866      */
3867
3868      function fnOnZoom(evt) {
3869      try {
3870      if (evt.newScale == undefined) throw 'bad interface'
3871      // update the transform list that adjusts for zoom and pan
3872      var tlist = document.getElementById('staticElements').transform.baseVal
3873      tlist.getItem(0).setScale(1/evt.newScale, 1/evt.newScale)
3874      tlist.getItem(1).setTranslate(-evt.newTranslate.x, -evt.newTranslate.y)
3875      }
3876      catch (e) {
3877      // work around difficiencies in non-moz implementations (some don't
3878      // implement the SVGZoomEvent or SVGAnimatedTransform interfaces)
3879      var de = document.documentElement
3880      var tform = 'scale(' + 1/de.currentScale + ') ' + 'translate(' + (-de.currentTranslate.x) + ', ' + (-de.currentTranslate.y) + ')'
3881      document.getElementById('staticElements').setAttributeNS(null, 'transform', tform)
3882      }
3883      }
3884
3885
3886      function fnOnScroll(evt) {
3887      var ct = document.documentElement.currentTranslate
3888      try {
3889      // update the transform list that adjusts for zoom and pan
3890      var tlist = document.getElementById('staticElements').transform.baseVal
3891      tlist.getItem(1).setTranslate(-ct.x, -ct.y)
3892      }
3893      catch (e) {
3894      // work around difficiencies in non-moz implementations (some don't
3895      // implement the SVGAnimatedTransform interface)
3896      var tform = 'scale(' + 1/document.documentElement.currentScale + ') ' + 'translate(' + (-ct.x) + ', ' + (-ct.y) + ')';
3897      document.getElementById('staticElements').setAttributeNS(null, 'transform', tform)
3898      }
3899      }
3900
3901
3902      function fnZoom(type) {
3903      var de = document.documentElement;
3904      var oldScale = de.currentScale;
3905      var oldTranslate = { x: de.currentTranslate.x, y: de.currentTranslate.y };
3906      var s = 2;
3907      if (type == 'in') {de.currentScale *= 1.5;}
3908      if (type == 'out') {de.currentScale /= 1.4;}
3909      // correct currentTranslate so zooming is to the center of the viewport:
3910
3911      var vp_width, vp_height;
3912      try {
3913      vp_width = de.viewport.width;
3914      vp_height = de.viewport.height;
3915      }
3916      catch (e) {
3917      // work around difficiency in moz ('viewport' property not implemented)
3918      vp_width = window.innerWidth;
3919      vp_height = window.innerHeight;
3920      }
3921      de.currentTranslate.x = vp_width/2 - ((de.currentScale/oldScale) * (vp_width/2 - oldTranslate.x));
3922      de.currentTranslate.y = vp_height/2 - ((de.currentScale/oldScale) * (vp_height/2 - oldTranslate.y));
3923
3924      }
3925
3926
3927      function fnPan(type) {
3928      var de = document.documentElement;
3929      var ct = de.currentTranslate;
3930      var t = 150;
3931      if (type == 'right') ct.x += t;
3932      if (type == 'down') ct.y += t;
3933      if (type == 'left') ct.x -= t;
3934      if (type == 'up') ct.y -= t;
3935      }
3936
3937
3938      var gCurrentX,gCurrentY
3939      var gDeltaX,gDeltaY
3940      var gMouseDown=false
3941      var gCurrentTranslate=document.documentElement.currentTranslate
3942
3943      function fnOnMouseDown(evt) {
3944      gCurrentX=gCurrentTranslate.x
3945      gCurrentY=gCurrentTranslate.y
3946      gDeltaX=evt.clientX
3947      gDeltaY=evt.clientY
3948      gMouseDown=true
3949      evt.target.ownerDocument.rootElement.setAttributeNS(null,"cursor","move")
3950      }
3951
3952
3953      function fnOnMouseUp(evt) {
3954      gMouseDown=false
3955      evt.target.ownerDocument.rootElement.setAttribute("cursor","default")
3956      }
3957
3958
3959      function fnOnMouseMove(evt) {
3960      var id
3961      if (gMouseDown) {
3962      gCurrentTranslate.x=gCurrentX+evt.clientX-gDeltaX
3963      gCurrentTranslate.y=gCurrentY+evt.clientY-gDeltaY
3964      }
3965      }
3966
3967
3968    </script>
3969  </xsl:template>
3970
3971</xsl:stylesheet>
Note: See TracBrowser for help on using the repository browser.