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

Last change on this file since 7995 was 7995, checked in by deelkar, 11 years ago

patch by mungewell, fixes error about not defined

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