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

Last change on this file since 6455 was 6455, checked in by bobkare, 12 years ago

One more change to multipolygon handling to handle multipolygons output by close-areas which have role=

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