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

Last change on this file since 7985 was 7985, checked in by mungewell, 11 years ago

Added the ability to render RelationRoutes?, disabled by default set
"showRelationRoutes='yes'" to enable.

Colours/Style? configurable in features file.

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