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

Last change on this file since 6380 was 6380, checked in by etienne, 12 years ago

Improvements to proximity algorithm.

File size: 135.8 KB
Line 
1<?xml version="1.0" encoding="UTF-8"?>
2<!--
3==============================================================================
4
5Osmarender 6.0 Alpha 6
6    with - orig area generation
7         - one node way filtered out
8         - filtered out missing multipolygon relation members from areas
9         - filtered out missing node ref from ways
10
11==============================================================================
12
13Copyright (C) 2006-2007  Etienne Cherdlu, Jochen Topf
14
15This program is free software; you can redistribute it and/or modify
16it under the terms of the GNU General Public License as published by
17the Free Software Foundation; either version 2 of the License, or
18(at your option) any later version.
19
20This program is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23GNU General Public License for more details.
24
25You should have received a copy of the GNU General Public License
26along with this program; if not, write to the Free Software
27Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
28
29==============================================================================
30-->
31<xsl:stylesheet
32  xmlns="http://www.w3.org/2000/svg"
33  xmlns:svg="http://www.w3.org/2000/svg"
34  xmlns:xlink="http://www.w3.org/1999/xlink"
35  xmlns:xi="http://www.w3.org/2001/XInclude"
36  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
37  xmlns:cc="http://web.resource.org/cc/"
38  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
39  xmlns:dc="http://purl.org/dc/elements/1.1/"
40  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
41  xmlns:exslt="http://exslt.org/common"
42  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
43  exclude-result-prefixes="exslt msxsl" 
44  version="1.0">
45
46  <xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="UTF-8"/>
47
48  <!-- This msxsl script extension fools msxsl into interpreting exslt extensions as msxsl ones, so
49       we can write code using exslt extensions even though msxsl only recognises the msxsl extension
50       namespace.  Thanks to David Carlisle for this: http://dpcarlisle.blogspot.com/2007/05/exslt-node-set-function.html -->
51  <msxsl:script language="JScript" implements-prefix="exslt">
52    this['node-set'] =  function (x) {
53    return x;
54    }
55  </msxsl:script>
56
57  <xsl:param name="osmfile" select="/rules/@data"/>
58  <xsl:param name="title" select="/rules/@title"/>
59
60  <xsl:param name="scale" select="/rules/@scale"/>
61  <xsl:param name="symbolScale" select="/rules/@symbolScale"/>
62  <xsl:param name='textAttenuation' select='/rules/@textAttenuation'/>
63  <xsl:param name="withOSMLayers" select="/rules/@withOSMLayers"/>
64  <xsl:param name="svgBaseProfile" select="/rules/@svgBaseProfile"/>
65  <xsl:param name="symbolsDir" select="/rules/@symbolsDir"/>
66
67  <xsl:param name="showGrid" select="/rules/@showGrid"/>
68  <xsl:param name="showBorder" select="/rules/@showBorder"/>
69  <xsl:param name="showScale" select="/rules/@showScale"/>
70  <xsl:param name="showLicense" select="/rules/@showLicense"/>
71
72  <xsl: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
924  <!-- Process an <areaText> instruction -->
925  <xsl:template match="areaText">
926    <xsl:param name="elements"/>
927
928    <!-- This is the instruction that is currently being processed -->
929    <xsl:variable name="instruction" select="."/>
930
931    <!-- Select all <way> elements that have a key that matches the k attribute of the text instruction -->
932    <xsl:apply-templates select="$elements[name()='way'][tag[@k=$instruction/@k]]" mode="areaTextPath">
933      <xsl:with-param name="instruction" select="$instruction"/>
934    </xsl:apply-templates>
935  </xsl:template>
936
937
938  <xsl:template match="*" mode="areaTextPath"/>
939
940
941  <xsl:template match="way" mode="areaTextPath">
942    <xsl:param name="instruction"/>
943
944    <!-- The current <way> element -->
945    <xsl:variable name="way" select="."/>
946
947    <xsl:call-template name="renderAreaText">
948      <xsl:with-param name="instruction" select="$instruction"/>
949      <xsl:with-param name="pathId" select="concat('way_normal_',@id)"/>
950    </xsl:call-template>
951
952  </xsl:template>
953
954
955  <xsl:template name="renderAreaText">
956    <xsl:param name="instruction"/>
957
958    <xsl:variable name='left'>
959      <xsl:call-template name='areaExtentLeft'>
960        <xsl:with-param name='nd' select='./nd[1]'/>
961        <!-- First node -->
962        <xsl:with-param name='left' select='key("nodeById",./nd[1]/@ref)/@lon'/>
963        <!-- Longitude of first node -->
964      </xsl:call-template>
965    </xsl:variable>
966
967    <xsl:variable name='right'>
968      <xsl:call-template name='areaExtentRight'>
969        <xsl:with-param name='nd' select='./nd[1]'/>
970        <!-- First node -->
971        <xsl:with-param name='right' select='key("nodeById",./nd[1]/@ref)/@lon'/>
972        <!-- Longitude of first node -->
973      </xsl:call-template>
974    </xsl:variable>
975
976    <xsl:variable name='top'>
977      <xsl:call-template name='areaExtentTop'>
978        <xsl:with-param name='nd' select='./nd[1]'/>
979        <!-- First node -->
980        <xsl:with-param name='top' select='key("nodeById",./nd[1]/@ref)/@lat'/>
981        <!-- Latitude of first node -->
982      </xsl:call-template>
983    </xsl:variable>
984
985    <xsl:variable name='bottom'>
986      <xsl:call-template name='areaExtentBottom'>
987        <xsl:with-param name='nd' select='./nd[1]'/>
988        <!-- First node -->
989        <xsl:with-param name='bottom' select='key("nodeById",./nd[1]/@ref)/@lat'/>
990        <!-- Latitude of first node -->
991      </xsl:call-template>
992    </xsl:variable>
993
994    <xsl:variable name='midLon'>
995      <xsl:value-of select='$left+(($right - $left) div 2)'/>
996    </xsl:variable>
997    <xsl:variable name='midLat'>
998      <xsl:value-of select='$bottom+(($top - $bottom) div 2)'/>
999    </xsl:variable>
1000
1001    <xsl:variable name="x" select="($width)-((($topRightLongitude)-($midLon))*10000*$scale)"/>
1002    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-($midLat))*10000*$scale*$projection)"/>
1003
1004    <text>
1005      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
1006      <xsl:attribute name="x">
1007        <xsl:value-of select="$x"/>
1008      </xsl:attribute>
1009      <xsl:attribute name="y">
1010        <xsl:value-of select="$y"/>
1011      </xsl:attribute>
1012      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
1013      <xsl:value-of select="tag[@k=$instruction/@k]/@v"/>
1014    </text>
1015  </xsl:template>
1016
1017  <!-- Process an <areaSymbol> instruction -->
1018  <xsl:template match="areaSymbol">
1019    <xsl:param name="elements"/>
1020
1021    <!-- This is the instruction that is currently being processed -->
1022    <xsl:variable name="instruction" select="."/>
1023
1024    <!-- Select all <way> elements -->
1025    <xsl:apply-templates select="$elements[name()='way']" mode="areaSymbolPath">
1026      <xsl:with-param name="instruction" select="$instruction"/>
1027    </xsl:apply-templates>
1028  </xsl:template>
1029
1030
1031  <xsl:template match="*" mode="areaSymbolPath"/>
1032
1033
1034  <xsl:template match="way" mode="areaSymbolPath">
1035    <xsl:param name="instruction"/>
1036
1037    <!-- The current <way> element -->
1038    <xsl:variable name="way" select="."/>
1039
1040    <xsl:call-template name="renderAreaSymbol">
1041      <xsl:with-param name="instruction" select="$instruction"/>
1042      <xsl:with-param name="pathId" select="concat('way_normal_',@id)"/>
1043    </xsl:call-template>
1044
1045  </xsl:template>
1046
1047
1048  <xsl:template name="renderAreaSymbol">
1049    <xsl:param name="instruction"/>
1050
1051    <xsl:variable name='left'>
1052      <xsl:call-template name='areaExtentLeft'>
1053        <xsl:with-param name='nd' select='./nd[1]'/>
1054        <!-- First node -->
1055        <xsl:with-param name='left' select='key("nodeById",./nd[1]/@ref)/@lon'/>
1056        <!-- Longitude of first node -->
1057      </xsl:call-template>
1058    </xsl:variable>
1059
1060    <xsl:variable name='right'>
1061      <xsl:call-template name='areaExtentRight'>
1062        <xsl:with-param name='nd' select='./nd[1]'/>
1063        <!-- First node -->
1064        <xsl:with-param name='right' select='key("nodeById",./nd[1]/@ref)/@lon'/>
1065        <!-- Longitude of first node -->
1066      </xsl:call-template>
1067    </xsl:variable>
1068
1069    <xsl:variable name='top'>
1070      <xsl:call-template name='areaExtentTop'>
1071        <xsl:with-param name='nd' select='./nd[1]'/>
1072        <!-- First node -->
1073        <xsl:with-param name='top' select='key("nodeById",./nd[1]/@ref)/@lat'/>
1074        <!-- Latitude of first node -->
1075      </xsl:call-template>
1076    </xsl:variable>
1077
1078    <xsl:variable name='bottom'>
1079      <xsl:call-template name='areaExtentBottom'>
1080        <xsl:with-param name='nd' select='./nd[1]'/>
1081        <!-- First node -->
1082        <xsl:with-param name='bottom' select='key("nodeById",./nd[1]/@ref)/@lat'/>
1083        <!-- Latitude of first node -->
1084      </xsl:call-template>
1085    </xsl:variable>
1086
1087    <xsl:variable name='midLon'>
1088      <xsl:value-of select='$left+(($right - $left) div 2)'/>
1089    </xsl:variable>
1090    <xsl:variable name='midLat'>
1091      <xsl:value-of select='$bottom+(($top - $bottom) div 2)'/>
1092    </xsl:variable>
1093
1094    <xsl:variable name="x" select="($width)-((($topRightLongitude)-($midLon))*10000*$scale)"/>
1095    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-($midLat))*10000*$scale*$projection)"/>
1096
1097    <g transform="translate({$x},{$y}) scale({$symbolScale})">
1098      <use>
1099        <xsl:if test="$instruction/@ref">
1100          <xsl:attribute name="xlink:href">
1101            <xsl:value-of select="concat('#symbol-', $instruction/@ref)"/>
1102          </xsl:attribute>
1103        </xsl:if>
1104        <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
1105        <!-- Copy all the attributes from the <symbol> instruction -->
1106      </use>
1107    </g>
1108  </xsl:template>
1109
1110  <xsl:template name='areaExtentLeft'>
1111    <xsl:param name='nd'/>
1112    <xsl:param name='left'/>
1113
1114    <xsl:variable name='leftmostLon' select='key("nodeById",$nd/@ref)/@lon'/>
1115    <xsl:variable name='newLeft'>
1116      <xsl:choose>
1117        <xsl:when test='$left>$leftmostLon'>
1118          <xsl:value-of select='$leftmostLon'/>
1119        </xsl:when>
1120        <xsl:otherwise>
1121          <xsl:value-of select='$left'/>
1122        </xsl:otherwise>
1123      </xsl:choose>
1124    </xsl:variable>
1125
1126    <xsl:choose>
1127      <xsl:when test="$nd/following-sibling::nd[1]">
1128        <xsl:call-template name='areaExtentLeft'>
1129          <xsl:with-param name='nd' select='$nd/following-sibling::nd[1]'/>
1130          <!-- next node -->
1131          <xsl:with-param name='left' select='$newLeft'/>
1132        </xsl:call-template>
1133      </xsl:when>
1134      <xsl:otherwise>
1135        <xsl:value-of select='$newLeft'/>
1136      </xsl:otherwise>
1137    </xsl:choose>
1138  </xsl:template>
1139
1140
1141  <xsl:template name='areaExtentRight'>
1142    <xsl:param name='nd'/>
1143    <xsl:param name='right'/>
1144
1145    <xsl:variable name='rightmostLon' select='key("nodeById",$nd/@ref)/@lon'/>
1146    <xsl:variable name='newRight'>
1147      <xsl:choose>
1148        <xsl:when test='$rightmostLon>$right'>
1149          <xsl:value-of select='$rightmostLon'/>
1150        </xsl:when>
1151        <xsl:otherwise>
1152          <xsl:value-of select='$right'/>
1153        </xsl:otherwise>
1154      </xsl:choose>
1155    </xsl:variable>
1156
1157    <xsl:choose>
1158      <xsl:when test="$nd/following-sibling::nd[1]">
1159        <xsl:call-template name='areaExtentRight'>
1160          <xsl:with-param name='nd' select='$nd/following-sibling::nd[1]'/>
1161          <!-- next node -->
1162          <xsl:with-param name='right' select='$newRight'/>
1163        </xsl:call-template>
1164      </xsl:when>
1165      <xsl:otherwise>
1166        <xsl:value-of select='$newRight'/>
1167      </xsl:otherwise>
1168    </xsl:choose>
1169  </xsl:template>
1170
1171
1172  <xsl:template name='areaExtentTop'>
1173    <xsl:param name='nd'/>
1174    <xsl:param name='top'/>
1175
1176    <xsl:variable name='topmostLat' select='key("nodeById",$nd/@ref)/@lat'/>
1177    <xsl:variable name='newTop'>
1178      <xsl:choose>
1179        <xsl:when test='$top>$topmostLat'>
1180          <xsl:value-of select='$top'/>
1181        </xsl:when>
1182        <xsl:otherwise>
1183          <xsl:value-of select='$topmostLat'/>
1184        </xsl:otherwise>
1185      </xsl:choose>
1186    </xsl:variable>
1187
1188    <xsl:choose>
1189      <xsl:when test="$nd/following-sibling::nd[1]">
1190        <xsl:call-template name='areaExtentTop'>
1191          <xsl:with-param name='nd' select='$nd/following-sibling::nd[1]'/>
1192          <!-- next node -->
1193          <xsl:with-param name='top' select='$newTop'/>
1194        </xsl:call-template>
1195      </xsl:when>
1196      <xsl:otherwise>
1197        <xsl:value-of select='$newTop'/>
1198      </xsl:otherwise>
1199    </xsl:choose>
1200  </xsl:template>
1201
1202
1203  <xsl:template name='areaExtentBottom'>
1204    <xsl:param name='nd'/>
1205    <xsl:param name='bottom'/>
1206
1207    <xsl:variable name='bottommostLat' select='key("nodeById",$nd/@ref)/@lat'/>
1208    <xsl:variable name='newBottom'>
1209      <xsl:choose>
1210        <xsl:when test='$bottommostLat>$bottom'>
1211          <xsl:value-of select='$bottom'/>
1212        </xsl:when>
1213        <xsl:otherwise>
1214          <xsl:value-of select='$bottommostLat'/>
1215        </xsl:otherwise>
1216      </xsl:choose>
1217    </xsl:variable>
1218
1219    <xsl:choose>
1220      <xsl:when test="$nd/following-sibling::nd[1]">
1221        <xsl:call-template name='areaExtentBottom'>
1222          <xsl:with-param name='nd' select='$nd/following-sibling::nd[1]'/>
1223          <!-- next node -->
1224          <xsl:with-param name='bottom' select='$newBottom'/>
1225        </xsl:call-template>
1226      </xsl:when>
1227      <xsl:otherwise>
1228        <xsl:value-of select='$newBottom'/>
1229      </xsl:otherwise>
1230    </xsl:choose>
1231  </xsl:template>
1232
1233  <!-- Process a <text> instruction -->
1234  <xsl:template match="text">
1235    <xsl:param name="elements"/>
1236
1237    <!-- This is the instruction that is currently being processed -->
1238    <xsl:variable name="instruction" select="."/>
1239
1240    <!-- Select all <node> elements that have a key that matches the k attribute of the text instruction -->
1241    <xsl:for-each select="$elements[name()='node'][tag[@k=$instruction/@k]]">
1242      <xsl:call-template name="renderText">
1243        <xsl:with-param name="instruction" select="$instruction"/>
1244      </xsl:call-template>
1245    </xsl:for-each>
1246
1247    <!-- Select all <way> elements -->
1248    <xsl:apply-templates select="$elements[name()='way']" mode="textPath">
1249      <xsl:with-param name="instruction" select="$instruction"/>
1250    </xsl:apply-templates>
1251  </xsl:template>
1252
1253
1254  <!-- Suppress output of any unhandled elements -->
1255  <xsl:template match="*" mode="textPath"/>
1256
1257
1258  <!-- Render textPaths for a way -->
1259  <xsl:template match="way" mode="textPath">
1260    <xsl:param name="instruction"/>
1261
1262    <!-- The current <way> element -->
1263    <xsl:variable name="way" select="."/>
1264
1265    <!-- DODI: !!!WORKAROUND!!! no text for one node ways-->
1266    <xsl:if test="count($way/nd) &gt; 1">
1267      <xsl:variable name='text'>
1268        <xsl:choose>
1269          <xsl:when test='$instruction/@k'>
1270            <xsl:value-of select='tag[@k=$instruction/@k]/@v'/>
1271          </xsl:when>
1272          <xsl:otherwise>
1273            <xsl:apply-templates select='$instruction' mode='textFormat'>
1274              <xsl:with-param name='way' select='$way'/>
1275            </xsl:apply-templates>
1276          </xsl:otherwise>
1277        </xsl:choose>
1278      </xsl:variable>
1279
1280      <xsl:if test='string($text)'>
1281
1282        <xsl:variable name="pathDirection">
1283          <xsl:choose>
1284            <!-- Manual override, reverse direction -->
1285            <xsl:when test="tag[@k='name_direction']/@v='-1' or tag[@k='osmarender:nameDirection']/@v='-1'">reverse</xsl:when>
1286            <!-- Manual override, normal direction -->
1287            <xsl:when test="tag[@k='name_direction']/@v='1' or tag[@k='osmarender:nameDirection']/@v='1'">normal</xsl:when>
1288            <!-- Automatic, reverse direction -->
1289            <xsl:when test="(key('nodeById',$way/nd[1]/@ref)/@lon &gt; key('nodeById',$way/nd[last()]/@ref)/@lon)">reverse</xsl:when>
1290            <!-- Automatic, normal direction -->
1291            <xsl:otherwise>normal</xsl:otherwise>
1292          </xsl:choose>
1293        </xsl:variable>
1294
1295        <xsl:variable name="wayPath">
1296          <xsl:choose>
1297            <!-- Normal -->
1298            <xsl:when test='$pathDirection="normal"'>
1299              <xsl:value-of select="concat('way_normal_',@id)"/>
1300            </xsl:when>
1301            <!-- Reverse -->
1302            <xsl:otherwise>
1303              <xsl:value-of select="concat('way_reverse_',@id)"/>
1304            </xsl:otherwise>
1305          </xsl:choose>
1306        </xsl:variable>
1307
1308        <xsl:call-template name="renderTextPath">
1309          <xsl:with-param name="instruction" select="$instruction"/>
1310          <xsl:with-param name="pathId" select="$wayPath"/>
1311          <xsl:with-param name="pathDirection" select="$pathDirection"/>
1312          <xsl:with-param name="text" select="$text"/>
1313        </xsl:call-template>
1314      </xsl:if>
1315    </xsl:if>
1316  </xsl:template>
1317
1318  <!-- Process extended form of text instruction -->
1319  <xsl:template match='text' mode='textFormat'>
1320    <xsl:param name='way'/>
1321
1322    <xsl:apply-templates mode='textFormat'>
1323      <xsl:with-param name='way' select='$way'/>
1324    </xsl:apply-templates>
1325  </xsl:template>
1326
1327
1328  <!-- Substitute a tag in a text instruction -->
1329  <xsl:template match='text/tag' mode='textFormat'>
1330    <xsl:param name='way'/>
1331
1332    <xsl:variable name='key' select='@k'/>
1333    <xsl:variable name='value'>
1334      <xsl:choose>
1335        <xsl:when test='$key="osm:user"'>
1336          <xsl:value-of select='$way/@user'/>
1337        </xsl:when>
1338        <xsl:when test='$key="osm:timestamp"'>
1339          <xsl:value-of select='$way/@timestamp'/>
1340        </xsl:when>
1341        <xsl:when test='$key="osm:id"'>
1342          <xsl:value-of select='$way/@id'/>
1343        </xsl:when>
1344        <xsl:otherwise>
1345          <xsl:value-of select='$way/tag[@k=$key]/@v'/>
1346        </xsl:otherwise>
1347      </xsl:choose>
1348    </xsl:variable>
1349    <xsl:choose>
1350      <xsl:when test='string($value)'>
1351        <xsl:value-of select='$value'/>
1352      </xsl:when>
1353      <xsl:otherwise>
1354        <xsl:value-of select='@default'/>
1355      </xsl:otherwise>
1356    </xsl:choose>
1357  </xsl:template>
1358
1359
1360
1361  <!-- Generate a way path for the current way element -->
1362  <xsl:template name="generateWayPaths">
1363    <!-- DODI: !!!WORKAROUND!!! skip one node ways -->
1364    <xsl:if test="count(nd) &gt; 1">
1365
1366      <!-- Generate a normal way path -->
1367      <xsl:variable name="pathWayNormal">
1368        <xsl:call-template name="generateWayPathNormal"/>
1369      </xsl:variable>
1370      <xsl:if test="$pathWayNormal!=''">
1371        <path id="way_normal_{@id}" d="{$pathWayNormal}"/>
1372      </xsl:if>
1373
1374      <!-- Generate a normal way path as area -->
1375      <!-- DODI: !!!WORKAROUND!!! added to generate "area for all ways, yes it is very dirty... but -->
1376      <!-- DODI: removed because of line2curves.pl duplicate node detection problem -->
1377      <!-- <xsl:variable name="pathArea">
1378      <xsl:call-template name="generateAreaPath"/>
1379    </xsl:variable>
1380    <path id="area_{@id}" d="{$pathArea}"/> -->
1381      <!-- Generate a reverse way path (if needed) -->
1382      <xsl:variable name="pathWayReverse">
1383        <xsl:choose>
1384          <!-- Manual override, reverse direction -->
1385          <xsl:when test="tag[@k='name_direction']/@v='-1' or tag[@k='osmarender:nameDirection']/@v='-1'">
1386            <xsl:call-template name="generateWayPathReverse"/>
1387          </xsl:when>
1388          <!-- Manual override, normal direction -->
1389          <xsl:when test="tag[@k='name_direction']/@v='1' or tag[@k='osmarender:nameDirection']/@v='1'">
1390            <!-- Generate nothing -->
1391          </xsl:when>
1392          <!-- Automatic, reverse direction -->
1393          <xsl:when test="(key('nodeById',nd[1]/@ref)/@lon &gt; key('nodeById',nd[last()]/@ref)/@lon)">
1394            <xsl:call-template name="generateWayPathReverse"/>
1395          </xsl:when>
1396        </xsl:choose>
1397      </xsl:variable>
1398      <xsl:if test="$pathWayReverse!=''">
1399        <path id="way_reverse_{@id}" d="{$pathWayReverse}"/>
1400      </xsl:if>
1401
1402      <!-- Generate the start, middle and end paths needed for smart-linecaps (TM). -->
1403      <xsl:variable name="pathWayStart">
1404        <xsl:call-template name="generatePathWayStart"/>
1405      </xsl:variable>
1406      <path id="way_start_{@id}" d="{$pathWayStart}"/>
1407
1408      <xsl:if test="count(nd) &gt; 1">
1409        <xsl:variable name="pathWayMid">
1410          <xsl:call-template name="generatePathWayMid"/>
1411        </xsl:variable>
1412        <path id="way_mid_{@id}" d="{$pathWayMid}"/>
1413      </xsl:if>
1414
1415      <xsl:variable name="pathWayEnd">
1416        <xsl:call-template name="generatePathWayEnd"/>
1417      </xsl:variable>
1418      <path id="way_end_{@id}" d="{$pathWayEnd}"/>
1419    </xsl:if >
1420  </xsl:template>
1421
1422
1423  <!-- Generate a normal way path -->
1424  <xsl:template name="generateWayPathNormal">
1425    <xsl:for-each select="nd[key('nodeById',@ref) ]">
1426      <xsl:choose>
1427        <xsl:when test="position()=1">
1428          <xsl:call-template name="moveToNode">
1429            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1430          </xsl:call-template>
1431        </xsl:when>
1432        <xsl:otherwise>
1433          <xsl:call-template name="lineToNode">
1434            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1435          </xsl:call-template>
1436        </xsl:otherwise>
1437      </xsl:choose>
1438    </xsl:for-each>
1439  </xsl:template>
1440
1441
1442  <!-- Generate a reverse way path -->
1443  <xsl:template name="generateWayPathReverse">
1444    <xsl:for-each select="nd[key('nodeById',@ref)]">
1445      <xsl:sort select="position()" data-type="number" order="descending"/>
1446      <xsl:choose>
1447        <xsl:when test="position()=1">
1448          <xsl:call-template name="moveToNode">
1449            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1450          </xsl:call-template>
1451        </xsl:when>
1452        <xsl:otherwise>
1453          <xsl:call-template name="lineToNode">
1454            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1455          </xsl:call-template>
1456        </xsl:otherwise>
1457      </xsl:choose>
1458    </xsl:for-each>
1459  </xsl:template>
1460
1461
1462  <!-- 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
1463         between the two paths is not at an angle.  -->
1464  <xsl:template name="generatePathWayStart">
1465    <xsl:call-template name="moveToNode">
1466      <xsl:with-param name="node" select="key('nodeById',nd[1]/@ref)"/>
1467    </xsl:call-template>
1468    <xsl:call-template name="lineToMidpointPlus">
1469      <xsl:with-param name="fromNode" select="key('nodeById',nd[1]/@ref)"/>
1470      <xsl:with-param name="toNode" select="key('nodeById',nd[2]/@ref)"/>
1471    </xsl:call-template>
1472  </xsl:template>
1473
1474
1475  <xsl:template name="generatePathWayEnd">
1476    <xsl:call-template name="moveToNode">
1477      <xsl:with-param name="node" select="key('nodeById',nd[position()=last()]/@ref)"/>
1478    </xsl:call-template>
1479    <xsl:call-template name="lineToMidpointMinus">
1480      <xsl:with-param name="fromNode" select="key('nodeById',nd[position()=(last()-1)]/@ref)"/>
1481      <xsl:with-param name="toNode" select="key('nodeById',nd[position()=last()]/@ref)"/>
1482    </xsl:call-template>
1483  </xsl:template>
1484
1485  <xsl:template name="generatePathWayMid">
1486    <xsl:for-each select="nd[key('nodeById',@ref)]">
1487      <xsl:choose>
1488        <xsl:when test="position()=1">
1489          <xsl:call-template name="moveToMidpointPlus">
1490            <xsl:with-param name="fromNode" select="key('nodeById',@ref)"/>
1491            <xsl:with-param name="toNode" select="key('nodeById',following-sibling::nd[1]/@ref)"/>
1492          </xsl:call-template>
1493        </xsl:when>
1494        <xsl:when test="position()=last()">
1495          <xsl:call-template name="lineToMidpointMinus">
1496            <xsl:with-param name="fromNode" select="key('nodeById',preceding-sibling::nd[1]/@ref)"/>
1497            <xsl:with-param name="toNode" select="key('nodeById',@ref)"/>
1498          </xsl:call-template>
1499        </xsl:when>
1500        <xsl:otherwise>
1501          <xsl:call-template name="lineToNode">
1502            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1503          </xsl:call-template>
1504        </xsl:otherwise>
1505      </xsl:choose>
1506    </xsl:for-each>
1507  </xsl:template>
1508
1509  <!-- Generate an area path for the current way or area element -->
1510  <xsl:template name="generateAreaPath">
1511    <xsl:variable name='relation' select="key('relationByWay',@id)[tag[@k='type' and @v='multipolygon']]"/>
1512    <xsl:choose>
1513      <xsl:when test='$relation'>
1514
1515        <!-- DODI: handling mulitpolygons: draw area only once
1516                   ways is a part of a multipolygon relation so we need process all members-->
1517        <xsl:variable name='firsrelationmember' select="$relation/member[@type='way'][key('wayById', @ref)][1]/@ref"/>
1518        <!-- DODI: if /me is a real first member, process all, otherwise skip it-->
1519        <xsl:if test='$firsrelationmember=@id'>
1520          <xsl:message>
1521            <xsl:value-of select='$relation/@id'/>
1522          </xsl:message>
1523          <xsl:for-each select="$relation/member[@type='way'][key('wayById', @ref)]">
1524            <xsl:call-template name='generateAreaSubPath'>
1525              <xsl:with-param name='way' select="key('wayById',@ref)"/>
1526              <xsl:with-param name='position' select="position()"/>
1527            </xsl:call-template>
1528          </xsl:for-each>
1529          <xsl:text>Z</xsl:text>
1530        </xsl:if>
1531
1532      </xsl:when>
1533      <xsl:otherwise>
1534        <xsl:call-template name='generateAreaSubPath'>
1535          <xsl:with-param name='way' select='.'/>
1536          <xsl:with-param name='position' select="'1'"/>
1537        </xsl:call-template>
1538        <xsl:text>Z</xsl:text>
1539      </xsl:otherwise>
1540    </xsl:choose>
1541  </xsl:template>
1542
1543
1544  <xsl:template name='generateAreaSubPath'>
1545    <xsl:param name='way'/>
1546    <xsl:param name='position'/>
1547
1548    <xsl:variable name='loop' select='$way/nd[1]/@ref=$way/nd[last()]/@ref'/>
1549    <xsl:message>
1550      WayId: <xsl:value-of select='$way/@id'/>
1551      Loop: <xsl:value-of select='$loop'/>
1552      Loop: <xsl:value-of select='$way/nd[1]/@ref'/>
1553      Loop: <xsl:value-of select='$way/nd[last()]/@ref'/>
1554    </xsl:message>
1555    <xsl:for-each select="$way/nd[key('nodeById',@ref)]">
1556      <xsl:choose>
1557        <xsl:when test="position()=1 and $loop">
1558          <xsl:if test='not($position=1)'>
1559            <xsl:text>Z</xsl:text>
1560          </xsl:if>
1561          <xsl:call-template name="moveToNode">
1562            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1563          </xsl:call-template>
1564        </xsl:when>
1565        <xsl:when test="$position=1 and position()=1 and not($loop=1)">
1566          <xsl:call-template name="moveToNode">
1567            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1568          </xsl:call-template>
1569        </xsl:when>
1570        <xsl:otherwise>
1571          <xsl:call-template name="lineToNode">
1572            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1573          </xsl:call-template>
1574        </xsl:otherwise>
1575      </xsl:choose>
1576    </xsl:for-each>
1577
1578
1579  </xsl:template>
1580
1581  <!-- Generate a MoveTo command for a node -->
1582  <xsl:template name="moveToNode">
1583    <xsl:param name='node' />
1584    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($node/@lon))*10000*$scale)"/>
1585    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($node/@lat))*10000*$scale*$projection)"/>
1586    <xsl:text>M</xsl:text>
1587    <xsl:value-of select="$x1"/>
1588    <xsl:text> </xsl:text>
1589    <xsl:value-of select="$y1"/>
1590  </xsl:template>
1591
1592  <!-- Generate a LineTo command for a nd -->
1593  <xsl:template name="lineToNode">
1594    <xsl:param name='node'/>
1595
1596    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($node/@lon))*10000*$scale)"/>
1597    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($node/@lat))*10000*$scale*$projection)"/>
1598    <xsl:text>L</xsl:text>
1599    <xsl:value-of select="$x1"/>
1600    <xsl:text> </xsl:text>
1601    <xsl:value-of select="$y1"/>
1602  </xsl:template>
1603
1604  <xsl:template name="lineToMidpointPlus">
1605    <xsl:param name='fromNode'/>
1606    <xsl:param name='toNode'/>
1607
1608    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1609    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1610
1611    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1612    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1613
1614    <xsl:text>L</xsl:text>
1615    <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
1616    <xsl:text> </xsl:text>
1617    <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
1618  </xsl:template>
1619
1620  <xsl:template name="lineToMidpointMinus">
1621    <xsl:param name='fromNode'/>
1622    <xsl:param name='toNode'/>
1623
1624    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1625    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1626
1627    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1628    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1629    <xsl:text>L</xsl:text>
1630    <xsl:value-of select="$x1+(($x2 - $x1) div 2.1)"/>
1631    <xsl:text> </xsl:text>
1632    <xsl:value-of select="$y1+(($y2 - $y1) div 2.1)"/>
1633  </xsl:template>
1634
1635
1636  <xsl:template name="moveToMidpointPlus">
1637    <xsl:param name='fromNode'/>
1638    <xsl:param name='toNode'/>
1639
1640    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1641    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1642
1643    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1644    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1645    <xsl:text>M</xsl:text>
1646    <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
1647    <xsl:text> </xsl:text>
1648    <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
1649  </xsl:template>
1650
1651  <!-- Some attribute shouldn't be copied -->
1652  <xsl:template match="@type|@ref|@scale|@smart-linecap" mode="copyAttributes" />
1653
1654  <!-- Copy all other attributes  -->
1655  <xsl:template match="@*" mode="copyAttributes">
1656    <xsl:copy/>
1657  </xsl:template>
1658
1659
1660  <!-- Rule processing engine -->
1661
1662  <!--
1663
1664                Calls all templates inside <rule> tags (including itself, if there are nested rules).
1665
1666                If the global var withOSMLayers is 'no', we don't care about layers and draw everything
1667                in one go. This is faster and is sometimes useful. For normal maps you want withOSMLayers
1668                to be 'yes', which is the default.
1669
1670        -->
1671  <xsl:template name="processRules">
1672
1673    <!-- First select all elements - exclude those marked as deleted by JOSM -->
1674    <xsl:variable name='elements' select="$data/osm/*[not(@action) or not(@action='delete')]" />
1675
1676    <xsl:choose>
1677
1678      <!-- Process all the rules, one layer at a time -->
1679      <xsl:when test="$withOSMLayers='yes'">
1680        <xsl:call-template name="processLayer">
1681          <xsl:with-param name="layer" select="'-5'"/>
1682          <xsl:with-param name="elements" select="$elements"/>
1683        </xsl:call-template>
1684        <xsl:call-template name="processLayer">
1685          <xsl:with-param name="layer" select="'-4'"/>
1686          <xsl:with-param name="elements" select="$elements"/>
1687        </xsl:call-template>
1688        <xsl:call-template name="processLayer">
1689          <xsl:with-param name="layer" select="'-3'"/>
1690          <xsl:with-param name="elements" select="$elements"/>
1691        </xsl:call-template>
1692        <xsl:call-template name="processLayer">
1693          <xsl:with-param name="layer" select="'-2'"/>
1694          <xsl:with-param name="elements" select="$elements"/>
1695        </xsl:call-template>
1696        <xsl:call-template name="processLayer">
1697          <xsl:with-param name="layer" select="'-1'"/>
1698          <xsl:with-param name="elements" select="$elements"/>
1699        </xsl:call-template>
1700        <xsl:call-template name="processLayer">
1701          <xsl:with-param name="layer" select="'0'"/>
1702          <xsl:with-param name="elements" select="$elements"/>
1703        </xsl:call-template>
1704        <xsl:call-template name="processLayer">
1705          <xsl:with-param name="layer" select="'1'"/>
1706          <xsl:with-param name="elements" select="$elements"/>
1707        </xsl:call-template>
1708        <xsl:call-template name="processLayer">
1709          <xsl:with-param name="layer" select="'2'"/>
1710          <xsl:with-param name="elements" select="$elements"/>
1711        </xsl:call-template>
1712        <xsl:call-template name="processLayer">
1713          <xsl:with-param name="layer" select="'3'"/>
1714          <xsl:with-param name="elements" select="$elements"/>
1715        </xsl:call-template>
1716        <xsl:call-template name="processLayer">
1717          <xsl:with-param name="layer" select="'4'"/>
1718          <xsl:with-param name="elements" select="$elements"/>
1719        </xsl:call-template>
1720        <xsl:call-template name="processLayer">
1721          <xsl:with-param name="layer" select="'5'"/>
1722          <xsl:with-param name="elements" select="$elements"/>
1723        </xsl:call-template>
1724      </xsl:when>
1725
1726      <!-- Process all the rules, without looking at the layers -->
1727      <xsl:otherwise>
1728        <xsl:apply-templates select="/rules/rule">
1729          <xsl:with-param name="elements" select="$elements"/>
1730          <xsl:with-param name="layer" select="'0'"/>
1731        </xsl:apply-templates>
1732      </xsl:otherwise>
1733
1734    </xsl:choose>
1735  </xsl:template>
1736
1737
1738  <xsl:template name="processLayer">
1739    <xsl:param name="layer"/>
1740    <xsl:param name="elements"/>
1741
1742    <g inkscape:groupmode="layer" id="layer{$layer}" inkscape:label="Layer {$layer}">
1743      <xsl:apply-templates select="/rules/rule">
1744        <xsl:with-param name="elements" select="$elements"/>
1745        <xsl:with-param name="layer" select="$layer"/>
1746      </xsl:apply-templates>
1747    </g>
1748  </xsl:template>
1749
1750
1751  <!-- Process a rule at a specific level -->
1752  <xsl:template match='rule'>
1753    <xsl:param name="elements"/>
1754    <xsl:param name="layer"/>
1755
1756    <!-- If the rule is for a specific layer and we are processing that layer then pass *all* elements
1757                     to the rule, otherwise just select the matching elements for this layer. -->
1758    <xsl:choose>
1759      <xsl:when test='$layer=@layer'>
1760        <xsl:call-template name="rule">
1761          <xsl:with-param name="elements" select="$elements"/>
1762          <xsl:with-param name="layer" select="$layer"/>
1763        </xsl:call-template>
1764      </xsl:when>
1765      <xsl:otherwise>
1766        <xsl:if test='not(@layer)'>
1767          <xsl:call-template name="rule">
1768            <xsl:with-param name="elements" select="$elements[
1769                                                        tag[@k='layer' and @v=$layer]
1770                                                        or ($layer='0' and count(tag[@k='layer'])=0)
1771                                                ]"/>
1772            <xsl:with-param name="layer" select="$layer"/>
1773          </xsl:call-template>
1774        </xsl:if>
1775      </xsl:otherwise>
1776    </xsl:choose>
1777  </xsl:template>
1778
1779
1780  <xsl:template name='rule'>
1781    <xsl:param name="elements"/>
1782    <xsl:param name="layer"/>
1783
1784    <!-- This is the rule currently being processed -->
1785    <xsl:variable name="rule" select="."/>
1786
1787    <!-- Make list of elements that this rule should be applied to -->
1788    <xsl:variable name="eBare">
1789      <xsl:choose>
1790        <xsl:when test="$rule/@e='*'">node|way</xsl:when>
1791        <xsl:when test="$rule/@e">
1792          <xsl:value-of select="$rule/@e"/>
1793        </xsl:when>
1794        <xsl:otherwise>node|way</xsl:otherwise>
1795      </xsl:choose>
1796    </xsl:variable>
1797
1798    <!-- List of keys that this rule should be applied to -->
1799    <xsl:variable name="kBare" select="$rule/@k"/>
1800
1801    <!-- List of values that this rule should be applied to -->
1802    <xsl:variable name="vBare" select="$rule/@v"/>
1803    <xsl:variable name="sBare" select="$rule/@s"/>
1804
1805    <!-- Top'n'tail selectors with | for contains usage -->
1806    <xsl:variable name="e">
1807      |<xsl:value-of select="$eBare"/>|
1808    </xsl:variable>
1809    <xsl:variable name="k">
1810      |<xsl:value-of select="$kBare"/>|
1811    </xsl:variable>
1812    <xsl:variable name="v">
1813      |<xsl:value-of select="$vBare"/>|
1814    </xsl:variable>
1815    <xsl:variable name="s">
1816      |<xsl:value-of select="$sBare"/>|
1817    </xsl:variable>
1818
1819    <xsl:variable
1820      name="selectedElements"
1821      select="$elements[contains($e,concat('|',name(),'|'))
1822            or
1823            (contains($e,'|node|') and name()='way' and key('wayByNode',@id))
1824            ]"/>
1825
1826
1827    <!-- Patch $s -->
1828    <xsl:choose>
1829      <!-- way selector -->
1830      <xsl:when test="contains($s,'|way|')">
1831        <xsl:choose>
1832          <!-- every key -->
1833          <xsl:when test="contains($k,'|*|')">
1834            <xsl:choose>
1835              <!-- every key ,no value defined -->
1836              <xsl:when test="contains($v,'|~|')">
1837                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(key('wayByNode',@id)/tag)=0]"/>
1838                <xsl:call-template name="processElements">
1839                  <xsl:with-param name="eBare" select="$eBare"/>
1840                  <xsl:with-param name="kBare" select="$kBare"/>
1841                  <xsl:with-param name="vBare" select="$vBare"/>
1842                  <xsl:with-param name="layer" select="$layer"/>
1843                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
1844                  <xsl:with-param name="rule" select="$rule"/>
1845                </xsl:call-template>
1846              </xsl:when>
1847              <!-- every key ,every value -->
1848              <xsl:when test="contains($v,'|*|')">
1849                <xsl:variable name="allElements" select="$selectedElements"/>
1850                <xsl:call-template name="processElements">
1851                  <xsl:with-param name="eBare" select="$eBare"/>
1852                  <xsl:with-param name="kBare" select="$kBare"/>
1853                  <xsl:with-param name="vBare" select="$vBare"/>
1854                  <xsl:with-param name="layer" select="$layer"/>
1855                  <xsl:with-param name="elements" select="$allElements"/>
1856                  <xsl:with-param name="rule" select="$rule"/>
1857                </xsl:call-template>
1858              </xsl:when>
1859              <!-- every key , selected values -->
1860              <xsl:otherwise>
1861                <xsl:variable name="allElementsWithValue" select="$selectedElements[key('wayByNode',@id)/tag[contains($v,concat('|',@v,'|'))]]"/>
1862                <xsl:call-template name="processElements">
1863                  <xsl:with-param name="eBare" select="$eBare"/>
1864                  <xsl:with-param name="kBare" select="$kBare"/>
1865                  <xsl:with-param name="vBare" select="$vBare"/>
1866                  <xsl:with-param name="layer" select="$layer"/>
1867                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
1868                  <xsl:with-param name="rule" select="$rule"/>
1869                </xsl:call-template>
1870              </xsl:otherwise>
1871            </xsl:choose>
1872          </xsl:when>
1873          <!-- no value  -->
1874          <xsl:when test="contains($v,'|~|')">
1875            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])=0]"/>
1876            <xsl:call-template name="processElements">
1877              <xsl:with-param name="eBare" select="$eBare"/>
1878              <xsl:with-param name="kBare" select="$kBare"/>
1879              <xsl:with-param name="vBare" select="$vBare"/>
1880              <xsl:with-param name="layer" select="$layer"/>
1881              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
1882              <xsl:with-param name="rule" select="$rule"/>
1883            </xsl:call-template>
1884          </xsl:when>
1885          <!-- every value  -->
1886          <xsl:when test="contains($v,'|*|')">
1887            <xsl:variable name="allElementsWithKey" select="$selectedElements[key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))]]"/>
1888            <xsl:call-template name="processElements">
1889              <xsl:with-param name="eBare" select="$eBare"/>
1890              <xsl:with-param name="kBare" select="$kBare"/>
1891              <xsl:with-param name="vBare" select="$vBare"/>
1892              <xsl:with-param name="layer" select="$layer"/>
1893              <xsl:with-param name="elements" select="$allElementsWithKey"/>
1894              <xsl:with-param name="rule" select="$rule"/>
1895            </xsl:call-template>
1896          </xsl:when>
1897
1898          <!-- defined key and defined value -->
1899          <xsl:otherwise>
1900            <xsl:variable name="elementsWithKey" select="$selectedElements[
1901                                                        key('wayByNode',@id)/tag[
1902                                                                contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))
1903                                                                ]
1904                                                        ]"/>
1905            <xsl:call-template name="processElements">
1906              <xsl:with-param name="eBare" select="$eBare"/>
1907              <xsl:with-param name="kBare" select="$kBare"/>
1908              <xsl:with-param name="vBare" select="$vBare"/>
1909              <xsl:with-param name="layer" select="$layer"/>
1910              <xsl:with-param name="elements" select="$elementsWithKey"/>
1911              <xsl:with-param name="rule" select="$rule"/>
1912            </xsl:call-template>
1913          </xsl:otherwise>
1914        </xsl:choose>
1915      </xsl:when>
1916
1917      <!-- other selector -->
1918      <xsl:otherwise>
1919        <xsl:choose>
1920          <xsl:when test="contains($k,'|*|')">
1921            <xsl:choose>
1922              <xsl:when test="contains($v,'|~|')">
1923                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(tag)=0]"/>
1924                <xsl:call-template name="processElements">
1925                  <xsl:with-param name="eBare" select="$eBare"/>
1926                  <xsl:with-param name="kBare" select="$kBare"/>
1927                  <xsl:with-param name="vBare" select="$vBare"/>
1928                  <xsl:with-param name="layer" select="$layer"/>
1929                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
1930                  <xsl:with-param name="rule" select="$rule"/>
1931                </xsl:call-template>
1932              </xsl:when>
1933              <xsl:when test="contains($v,'|*|')">
1934                <xsl:variable name="allElements" select="$selectedElements"/>
1935                <xsl:call-template name="processElements">
1936                  <xsl:with-param name="eBare" select="$eBare"/>
1937                  <xsl:with-param name="kBare" select="$kBare"/>
1938                  <xsl:with-param name="vBare" select="$vBare"/>
1939                  <xsl:with-param name="layer" select="$layer"/>
1940                  <xsl:with-param name="elements" select="$allElements"/>
1941                  <xsl:with-param name="rule" select="$rule"/>
1942                </xsl:call-template>
1943              </xsl:when>
1944              <xsl:otherwise>
1945                <xsl:variable name="allElementsWithValue" select="$selectedElements[tag[contains($v,concat('|',@v,'|'))]]"/>
1946                <xsl:call-template name="processElements">
1947                  <xsl:with-param name="eBare" select="$eBare"/>
1948                  <xsl:with-param name="kBare" select="$kBare"/>
1949                  <xsl:with-param name="vBare" select="$vBare"/>
1950                  <xsl:with-param name="layer" select="$layer"/>
1951                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
1952                  <xsl:with-param name="rule" select="$rule"/>
1953                </xsl:call-template>
1954              </xsl:otherwise>
1955            </xsl:choose>
1956          </xsl:when>
1957          <xsl:when test="contains($v,'|~|')">
1958            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(tag[contains($k,concat('|',@k,'|'))])=0]"/>
1959            <xsl:call-template name="processElements">
1960              <xsl:with-param name="eBare" select="$eBare"/>
1961              <xsl:with-param name="kBare" select="$kBare"/>
1962              <xsl:with-param name="vBare" select="$vBare"/>
1963              <xsl:with-param name="layer" select="$layer"/>
1964              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
1965              <xsl:with-param name="rule" select="$rule"/>
1966            </xsl:call-template>
1967          </xsl:when>
1968          <xsl:when test="contains($v,'|*|')">
1969            <xsl:variable name="allElementsWithKey" select="$selectedElements[tag[contains($k,concat('|',@k,'|'))]]"/>
1970            <xsl:call-template name="processElements">
1971              <xsl:with-param name="eBare" select="$eBare"/>
1972              <xsl:with-param name="kBare" select="$kBare"/>
1973              <xsl:with-param name="vBare" select="$vBare"/>
1974              <xsl:with-param name="layer" select="$layer"/>
1975              <xsl:with-param name="elements" select="$allElementsWithKey"/>
1976              <xsl:with-param name="rule" select="$rule"/>
1977            </xsl:call-template>
1978          </xsl:when>
1979          <xsl:otherwise>
1980            <xsl:variable name="elementsWithKey" select="$selectedElements[tag[contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))]]"/>
1981            <xsl:call-template name="processElements">
1982              <xsl:with-param name="eBare" select="$eBare"/>
1983              <xsl:with-param name="kBare" select="$kBare"/>
1984              <xsl:with-param name="vBare" select="$vBare"/>
1985              <xsl:with-param name="layer" select="$layer"/>
1986              <xsl:with-param name="elements" select="$elementsWithKey"/>
1987              <xsl:with-param name="rule" select="$rule"/>
1988            </xsl:call-template>
1989          </xsl:otherwise>
1990        </xsl:choose>
1991      </xsl:otherwise>
1992    </xsl:choose>
1993  </xsl:template>
1994
1995
1996  <xsl:template match="else">
1997    <xsl:param name="elements"/>
1998    <xsl:param name="layer"/>
1999
2000    <!-- This is the previous rule that is being negated -->
2001    <!-- TODO: abort if no preceding rule element -->
2002    <xsl:variable name="rule" select="preceding-sibling::rule[1]"/>
2003
2004    <!-- Make list of elements that this rule should be applied to -->
2005    <xsl:variable name="eBare">
2006      <xsl:choose>
2007        <xsl:when test="$rule/@e='*'">node|way</xsl:when>
2008        <xsl:when test="$rule/@e">
2009          <xsl:value-of select="$rule/@e"/>
2010        </xsl:when>
2011        <xsl:otherwise>node|way</xsl:otherwise>
2012      </xsl:choose>
2013    </xsl:variable>
2014
2015    <!-- List of keys that this rule should be applied to -->
2016    <xsl:variable name="kBare" select="$rule/@k"/>
2017
2018    <!-- List of values that this rule should be applied to -->
2019    <xsl:variable name="vBare" select="$rule/@v"/>
2020    <xsl:variable name="sBare" select="$rule/@s"/>
2021
2022
2023    <!-- Top'n'tail selectors with | for contains usage -->
2024    <xsl:variable name="e">
2025      |<xsl:value-of select="$eBare"/>|
2026    </xsl:variable>
2027    <xsl:variable name="k">
2028      |<xsl:value-of select="$kBare"/>|
2029    </xsl:variable>
2030    <xsl:variable name="v">
2031      |<xsl:value-of select="$vBare"/>|
2032    </xsl:variable>
2033    <xsl:variable name="s">
2034      |<xsl:value-of select="$sBare"/>|
2035    </xsl:variable>
2036
2037    <xsl:variable
2038      name="selectedElements"
2039      select="$elements[contains($e,concat('|',name(),'|'))
2040              or
2041              (contains($e,'|node|') and name()='way'and key('wayByNode',@id))
2042              ]"/>
2043
2044    <!-- Patch $s -->
2045    <xsl:choose>
2046      <xsl:when test="contains($s,'|way|')">
2047        <xsl:choose>
2048          <xsl:when test="contains($k,'|*|')">
2049            <xsl:choose>
2050              <xsl:when test="contains($v,'|~|')">
2051                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(key('wayByNode',@id)/tag)!=0]"/>
2052                <xsl:call-template name="processElements">
2053                  <xsl:with-param name="eBare" select="$eBare"/>
2054                  <xsl:with-param name="kBare" select="$kBare"/>
2055                  <xsl:with-param name="vBare" select="$vBare"/>
2056                  <xsl:with-param name="layer" select="$layer"/>
2057                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2058                  <xsl:with-param name="rule" select="$rule"/>
2059                </xsl:call-template>
2060              </xsl:when>
2061              <xsl:when test="contains($v,'|*|')">
2062                <!-- no-op! -->
2063              </xsl:when>
2064              <xsl:otherwise>
2065                <xsl:variable name="allElementsWithValue" select="$selectedElements[not(key('wayByNode',@id)/tag[contains($v,concat('|',@v,'|'))])]"/>
2066                <xsl:call-template name="processElements">
2067                  <xsl:with-param name="eBare" select="$eBare"/>
2068                  <xsl:with-param name="kBare" select="$kBare"/>
2069                  <xsl:with-param name="vBare" select="$vBare"/>
2070                  <xsl:with-param name="layer" select="$layer"/>
2071                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
2072                  <xsl:with-param name="rule" select="$rule"/>
2073                </xsl:call-template>
2074              </xsl:otherwise>
2075            </xsl:choose>
2076          </xsl:when>
2077          <xsl:when test="contains($v,'|~|')">
2078            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])!=0]"/>
2079            <xsl:call-template name="processElements">
2080              <xsl:with-param name="eBare" select="$eBare"/>
2081              <xsl:with-param name="kBare" select="$kBare"/>
2082              <xsl:with-param name="vBare" select="$vBare"/>
2083              <xsl:with-param name="layer" select="$layer"/>
2084              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2085              <xsl:with-param name="rule" select="$rule"/>
2086            </xsl:call-template>
2087          </xsl:when>
2088          <xsl:when test="contains($v,'|*|')">
2089            <xsl:variable name="allElementsWithKey" select="$selectedElements[not(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])]"/>
2090            <xsl:call-template name="processElements">
2091              <xsl:with-param name="eBare" select="$eBare"/>
2092              <xsl:with-param name="kBare" select="$kBare"/>
2093              <xsl:with-param name="vBare" select="$vBare"/>
2094              <xsl:with-param name="layer" select="$layer"/>
2095              <xsl:with-param name="elements" select="$allElementsWithKey"/>
2096              <xsl:with-param name="rule" select="$rule"/>
2097            </xsl:call-template>
2098          </xsl:when>
2099          <xsl:otherwise>
2100            <xsl:variable name="elementsWithKey" select="$selectedElements[not(
2101                         key('wayByNode',@id)/tag[
2102                            contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))
2103                            ]
2104                         )]"/>
2105            <xsl:call-template name="processElements">
2106              <xsl:with-param name="eBare" select="$eBare"/>
2107              <xsl:with-param name="kBare" select="$kBare"/>
2108              <xsl:with-param name="vBare" select="$vBare"/>
2109              <xsl:with-param name="layer" select="$layer"/>
2110              <xsl:with-param name="elements" select="$elementsWithKey"/>
2111              <xsl:with-param name="rule" select="$rule"/>
2112            </xsl:call-template>
2113          </xsl:otherwise>
2114        </xsl:choose>
2115      </xsl:when>
2116
2117      <xsl:otherwise>
2118        <!-- not contains $s -->
2119        <xsl:choose>
2120          <xsl:when test="contains($k,'|*|')">
2121            <xsl:choose>
2122              <xsl:when test="contains($v,'|~|')">
2123                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(tag)!=0]"/>
2124                <xsl:call-template name="processElements">
2125                  <xsl:with-param name="eBare" select="$eBare"/>
2126                  <xsl:with-param name="kBare" select="$kBare"/>
2127                  <xsl:with-param name="vBare" select="$vBare"/>
2128                  <xsl:with-param name="layer" select="$layer"/>
2129                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2130                  <xsl:with-param name="rule" select="$rule"/>
2131                </xsl:call-template>
2132              </xsl:when>
2133              <xsl:when test="contains($v,'|*|')">
2134                <!-- no-op! -->
2135              </xsl:when>
2136              <xsl:otherwise>
2137                <xsl:variable name="allElementsWithValue" select="$selectedElements[not(tag[contains($v,concat('|',@v,'|'))])]"/>
2138                <xsl:call-template name="processElements">
2139                  <xsl:with-param name="eBare" select="$eBare"/>
2140                  <xsl:with-param name="kBare" select="$kBare"/>
2141                  <xsl:with-param name="vBare" select="$vBare"/>
2142                  <xsl:with-param name="layer" select="$layer"/>
2143                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
2144                  <xsl:with-param name="rule" select="$rule"/>
2145                </xsl:call-template>
2146              </xsl:otherwise>
2147            </xsl:choose>
2148          </xsl:when>
2149          <xsl:when test="contains($v,'|~|')">
2150            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(tag[contains($k,concat('|',@k,'|'))])!=0]"/>
2151            <xsl:call-template name="processElements">
2152              <xsl:with-param name="eBare" select="$eBare"/>
2153              <xsl:with-param name="kBare" select="$kBare"/>
2154              <xsl:with-param name="vBare" select="$vBare"/>
2155              <xsl:with-param name="layer" select="$layer"/>
2156              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2157              <xsl:with-param name="rule" select="$rule"/>
2158            </xsl:call-template>
2159          </xsl:when>
2160          <xsl:when test="contains($v,'|*|')">
2161            <xsl:variable name="allElementsWithKey" select="$selectedElements[not(tag[contains($k,concat('|',@k,'|'))])]"/>
2162            <xsl:call-template name="processElements">
2163              <xsl:with-param name="eBare" select="$eBare"/>
2164              <xsl:with-param name="kBare" select="$kBare"/>
2165              <xsl:with-param name="vBare" select="$vBare"/>
2166              <xsl:with-param name="layer" select="$layer"/>
2167              <xsl:with-param name="elements" select="$allElementsWithKey"/>
2168              <xsl:with-param name="rule" select="$rule"/>
2169            </xsl:call-template>
2170          </xsl:when>
2171          <xsl:otherwise>
2172            <xsl:variable name="elementsWithKey" select="$selectedElements[not(tag[contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))])]"/>
2173            <xsl:call-template name="processElements">
2174              <xsl:with-param name="eBare" select="$eBare"/>
2175              <xsl:with-param name="kBare" select="$kBare"/>
2176              <xsl:with-param name="vBare" select="$vBare"/>
2177              <xsl:with-param name="layer" select="$layer"/>
2178              <xsl:with-param name="elements" select="$elementsWithKey"/>
2179              <xsl:with-param name="rule" select="$rule"/>
2180            </xsl:call-template>
2181          </xsl:otherwise>
2182        </xsl:choose>
2183      </xsl:otherwise>
2184    </xsl:choose>
2185  </xsl:template>
2186
2187
2188  <xsl:template name="processElements">
2189    <xsl:param name="eBare"/>
2190    <xsl:param name="kBare"/>
2191    <xsl:param name="vBare"/>
2192    <xsl:param name="layer"/>
2193    <xsl:param name="elements"/>
2194    <xsl:param name="rule"/>
2195
2196
2197    <xsl:if test="$elements">
2198 
2199      <!-- elementCount is the number of elements we started with (just used for the progress message) -->
2200      <xsl:variable name="elementCount" select="count($elements)"/>
2201      <!-- If there's a proximity attribute on the rule then filter elements based on proximity -->
2202      <xsl:choose>
2203        <xsl:when test='$rule/@verticalProximity'>
2204          <xsl:variable name='nearbyElements1'>
2205            <xsl:call-template name="proximityFilter">
2206              <xsl:with-param name="elements" select="$elements"/>
2207              <xsl:with-param name="horizontalProximity" select="$rule/@horizontalProximity div 32"/>
2208              <xsl:with-param name="verticalProximity" select="$rule/@verticalProximity div 32"/>
2209            </xsl:call-template>
2210          </xsl:variable>
2211          <xsl:variable name='nearbyElements2'>
2212            <xsl:call-template name="proximityFilter">
2213              <xsl:with-param name="elements" select="exslt:node-set($nearbyElements1)/*"/>
2214              <xsl:with-param name="horizontalProximity" select="$rule/@horizontalProximity div 16"/>
2215              <xsl:with-param name="verticalProximity" select="$rule/@verticalProximity div 16"/>
2216            </xsl:call-template>
2217          </xsl:variable>
2218          <xsl:variable name='nearbyElements3'>
2219            <xsl:call-template name="proximityFilter">
2220              <xsl:with-param name="elements" select="exslt:node-set($nearbyElements2)/*"/>
2221              <xsl:with-param name="horizontalProximity" select="$rule/@horizontalProximity div 8"/>
2222              <xsl:with-param name="verticalProximity" select="$rule/@verticalProximity div 8"/>
2223            </xsl:call-template>
2224          </xsl:variable>
2225          <xsl:variable name='nearbyElements4'>
2226            <xsl:call-template name="proximityFilter">
2227              <xsl:with-param name="elements" select="exslt:node-set($nearbyElements3)/*"/>
2228              <xsl:with-param name="horizontalProximity" select="$rule/@horizontalProximity div 4"/>
2229              <xsl:with-param name="verticalProximity" select="$rule/@verticalProximity div 4"/>
2230            </xsl:call-template>
2231          </xsl:variable>
2232          <xsl:variable name='nearbyElements5'>
2233            <xsl:call-template name="proximityFilter">
2234              <xsl:with-param name="elements" select="exslt:node-set($nearbyElements4)/*"/>
2235              <xsl:with-param name="horizontalProximity" select="$rule/@horizontalProximity div 2"/>
2236              <xsl:with-param name="verticalProximity" select="$rule/@verticalProximity div 2"/>
2237            </xsl:call-template>
2238          </xsl:variable>
2239          <xsl:variable name='nearbyElementsRtf'>
2240            <xsl:call-template name="proximityFilter">
2241              <xsl:with-param name="elements" select="exslt:node-set($nearbyElements5)/*"/>
2242              <xsl:with-param name="horizontalProximity" select="$rule/@horizontalProximity"/>
2243              <xsl:with-param name="verticalProximity" select="$rule/@verticalProximity"/>
2244            </xsl:call-template>
2245          </xsl:variable>
2246
2247          <!-- Convert nearbyElements rtf to a node-set -->
2248          <xsl:variable name="nearbyElements" select="exslt:node-set($nearbyElementsRtf)/*"/>
2249
2250          <xsl:message>
2251            Processing &lt;rule e="<xsl:value-of select="$eBare"/>" k="<xsl:value-of select="$kBare"/>" v="<xsl:value-of select="$vBare"/>"
2252                        horizontalProximity="<xsl:value-of select="$rule/@horizontalProximity"/>" verticalProximity="<xsl:value-of select="$rule/@verticalProximity"/>" &gt;
2253            Matched by <xsl:value-of select="count($nearbyElements)"/> out of <xsl:value-of select="count($elements)"/> elements for layer <xsl:value-of select="$layer"/>.
2254          </xsl:message>
2255
2256          <xsl:apply-templates select="*">
2257            <xsl:with-param name="layer" select="$layer"/>
2258            <xsl:with-param name="elements" select="$nearbyElements"/>
2259            <xsl:with-param name="rule" select="$rule"/>
2260          </xsl:apply-templates>
2261        </xsl:when>
2262        <xsl:otherwise>
2263
2264          <xsl:message>
2265            Processing &lt;rule e="<xsl:value-of select="$eBare"/>" k="<xsl:value-of select="$kBare"/>" v="<xsl:value-of select="$vBare"/>" &gt;
2266            Matched by <xsl:value-of select="count($elements)"/> elements for layer <xsl:value-of select="$layer"/>.
2267          </xsl:message>
2268
2269          <xsl:apply-templates select="*">
2270            <xsl:with-param name="layer" select="$layer"/>
2271            <xsl:with-param name="elements" select="$elements"/>
2272            <xsl:with-param name="rule" select="$rule"/>
2273          </xsl:apply-templates>
2274        </xsl:otherwise>
2275      </xsl:choose>
2276    </xsl:if>
2277  </xsl:template>
2278
2279
2280  <!-- Select elements that are not within the specified distance from any other element -->
2281  <xsl:template name="proximityFilter">
2282    <xsl:param name="elements"/>
2283    <xsl:param name="horizontalProximity"/>
2284    <xsl:param name="verticalProximity"/>
2285   
2286    <!-- Offsetting the rectangle to the right gives better results when there are a solitary pair of adjacent elements. 
2287         One will get selected but the other won't.  Without the offset neither will get selected.  -->
2288    <xsl:variable name="topOffset" select="90  + $verticalProximity"/>
2289    <xsl:variable name="bottomOffset" select="90  - $verticalProximity"/>
2290    <xsl:variable name="leftOffset" select="180 - ($horizontalProximity * 0.5)"/>
2291    <xsl:variable name="rightOffset" select="180 + ($horizontalProximity * 1.5)"/>
2292
2293    <!-- Test each element to see if it is near any other element -->
2294    <xsl:for-each select="$elements">
2295      <xsl:variable name="id" select="@id"/>
2296      <xsl:variable name="top"    select="@lat + $topOffset"/>
2297      <xsl:variable name="bottom" select="@lat + $bottomOffset"/>
2298      <xsl:variable name="left"   select="@lon + $leftOffset"/>
2299      <xsl:variable name="right"  select="@lon + $rightOffset"/>
2300      <!-- Iterate through all of the elements currently selected and if there are no elements other
2301           than the current element in the rectangle then select this element -->
2302      <xsl:if test="not($elements[not(@id=$id)
2303                                  and (@lon+180) &lt; $right
2304                                  and (@lon+180) &gt; $left
2305                                  and (@lat+90)  &lt; $top
2306                                  and (@lat+90)  &gt; $bottom
2307                                  ]
2308                        )">
2309        <xsl:copy-of select="."/>
2310      </xsl:if>
2311    </xsl:for-each>
2312  </xsl:template>
2313
2314
2315  <!-- Draw SVG layers -->
2316  <xsl:template match="layer">
2317    <xsl:param name="elements"/>
2318    <xsl:param name="layer"/>
2319    <xsl:param name="rule"/>
2320
2321    <xsl:message>
2322      Processing SVG layer: <xsl:value-of select="@name"/> (at OSM layer <xsl:value-of select="$layer"/>)
2323    </xsl:message>
2324
2325    <xsl:variable name="opacity">
2326      <xsl:if test="@opacity">
2327        <xsl:value-of select="concat('opacity:',@opacity,';')"/>
2328      </xsl:if>
2329    </xsl:variable>
2330
2331    <xsl:variable name="display">
2332      <xsl:if test="(@display='none') or (@display='off')">
2333        <xsl:text>display:none;</xsl:text>
2334      </xsl:if>
2335    </xsl:variable>
2336
2337    <g inkscape:groupmode="layer" id="{@name}-{$layer}" inkscape:label="{@name}">
2338      <xsl:if test="concat($opacity,$display)!=''">
2339        <xsl:attribute name="style">
2340          <xsl:value-of select="concat($opacity,$display)"/>
2341        </xsl:attribute>
2342      </xsl:if>
2343      <xsl:apply-templates select="*">
2344        <xsl:with-param name="layer" select="$layer"/>
2345        <xsl:with-param name="elements" select="$elements"/>
2346      </xsl:apply-templates>
2347    </g>
2348
2349  </xsl:template>
2350
2351
2352  <!-- Draw map border -->
2353  <xsl:template name="drawBorder">
2354    <!-- dasharray definitions here can be overridden in stylesheet -->
2355    <g id="border" inkscape:groupmode="layer" inkscape:label="Map Border">
2356      <line id="border-left-casing" x1="0" y1="0" x2="0" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2357      <line id="border-top-casing" x1="0" y1="0" x2="{$documentWidth}" y2="0" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2358      <line id="border-bottom-casing" x1="0" y1="{$documentHeight}" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2359      <line id="border-right-casing" x1="{$documentWidth}" y1="0" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2360
2361      <line id="border-left-core" x1="0" y1="0" x2="0" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2362      <line id="border-top-core" x1="0" y1="0" x2="{$documentWidth}" y2="0" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2363      <line id="border-bottom-core" x1="0" y1="{$documentHeight}" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2364      <line id="border-right-core" x1="{$documentWidth}" y1="0" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2365    </g>
2366  </xsl:template>
2367
2368
2369  <!-- Draw a grid over the map in 1km increments -->
2370  <xsl:template name="drawGrid">
2371    <g id="grid" inkscape:groupmode="layer" inkscape:label="Grid">
2372      <xsl:call-template name="drawGridHorizontals">
2373        <xsl:with-param name="line" select="'1'"/>
2374      </xsl:call-template>
2375      <xsl:call-template name="drawGridVerticals">
2376        <xsl:with-param name="line" select="'1'"/>
2377      </xsl:call-template>
2378    </g>
2379  </xsl:template>
2380
2381
2382  <xsl:template name="drawGridHorizontals">
2383    <xsl:param name="line"/>
2384    <xsl:if test="($line*$km) &lt; $documentHeight">
2385      <line id="grid-hori-{$line}" x1="0px" y1="{$line*$km}px" x2="{$documentWidth}px" y2="{$line*$km}px" class="map-grid-line"/>
2386      <xsl:call-template name="drawGridHorizontals">
2387        <xsl:with-param name="line" select="$line+1"/>
2388      </xsl:call-template>
2389    </xsl:if>
2390  </xsl:template>
2391
2392
2393  <xsl:template name="drawGridVerticals">
2394    <xsl:param name="line"/>
2395    <xsl:if test="($line*$km) &lt; $documentWidth">
2396      <line id="grid-vert-{$line}" x1="{$line*$km}px" y1="0px" x2="{$line*$km}px" y2="{$documentHeight}px" class="map-grid-line"/>
2397      <xsl:call-template name="drawGridVerticals">
2398        <xsl:with-param name="line" select="$line+1"/>
2399      </xsl:call-template>
2400    </xsl:if>
2401  </xsl:template>
2402
2403
2404  <!-- Draw map title -->
2405  <xsl:template name="drawTitle">
2406    <xsl:param name="title"/>
2407
2408    <xsl:variable name="x" select="$documentWidth div 2"/>
2409    <xsl:variable name="y" select="30"/>
2410
2411    <g id="marginalia-title" inkscape:groupmode="layer" inkscape:label="Title">
2412      <rect id="marginalia-title-background" x="0px" y="0px" height="{$marginaliaTopHeight - 5}px" width="{$documentWidth}px" class="map-title-background"/>
2413      <text id="marginalia-title-text" class="map-title" x="{$x}" y="{$y}">
2414        <xsl:value-of select="$title"/>
2415      </text>
2416    </g>
2417  </xsl:template>
2418
2419
2420  <!-- Draw an approximate scale in the bottom left corner of the map -->
2421  <xsl:template name="drawScale">
2422    <xsl:variable name="x1" select="14"/>
2423    <xsl:variable name="y1" select="round(($documentHeight)+((($bottomLeftLatitude)-(number($bottomLeftLatitude)))*10000*$scale*$projection))+28"/>
2424    <xsl:variable name="x2" select="$x1+$km"/>
2425    <xsl:variable name="y2" select="$y1"/>
2426
2427    <g id="marginalia-scale" inkscape:groupmode="layer" inkscape:label="Scale">
2428      <line id="marginalia-scale-casing" class="map-scale-casing" x1="{$x1}" y1="{$y1}" x2="{$x2}" y2="{$y2}"/>
2429
2430      <line id="marginalia-scale-core" class="map-scale-core" stroke-dasharray="{($km div 10)}" x1="{$x1}" y1="{$y1}" x2="{$x2}" y2="{$y2}"/>
2431
2432      <line id="marginalia-scale-bookend-from" class="map-scale-bookend" x1="{$x1}" y1="{$y1 + 2}" x2="{$x1}" y2="{$y1 - 10}"/>
2433
2434      <line id="marginalia-scale-bookend-to" class="map-scale-bookend" x1="{$x2}" y1="{$y2 + 2}" x2="{$x2}" y2="{$y2 - 10}"/>
2435
2436      <text id="marginalia-scale-text-from" class="map-scale-caption" x="{$x1}" y="{$y1 - 10}">0</text>
2437
2438      <text id="marginalia-scale-text-to" class="map-scale-caption" x="{$x2}" y="{$y2 - 10}">1km</text>
2439    </g>
2440  </xsl:template>
2441
2442
2443  <!-- Create a comment in SVG source code and RDF description of license -->
2444  <xsl:template name="metadata">
2445
2446    <xsl:comment>
2447
2448      Copyright (c) <xsl:value-of select="$year"/> OpenStreetMap
2449      www.openstreetmap.org
2450      This work is licensed under the
2451      Creative Commons Attribution-ShareAlike 2.0 License.
2452      http://creativecommons.org/licenses/by-sa/2.0/
2453
2454    </xsl:comment>
2455    <metadata id="metadata">
2456      <rdf:RDF xmlns="http://web.resource.org/cc/">
2457        <cc:Work rdf:about="">
2458          <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/"/>
2459          <dc:format>image/svg+xml</dc:format>
2460          <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
2461          <dc:title>
2462            <xsl:value-of select="$title"/>
2463          </dc:title>
2464          <dc:date>
2465            <xsl:value-of select="$date"/>
2466          </dc:date>
2467          <dc:source>http://www.openstreetmap.org/</dc:source>
2468        </cc:Work>
2469        <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
2470          <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
2471          <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
2472          <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
2473          <cc:requires rdf:resource="http://web.resource.org/cc/Notice"/>
2474          <cc:requires rdf:resource="http://web.resource.org/cc/Attribution"/>
2475          <cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/>
2476        </cc:License>
2477      </rdf:RDF>
2478    </metadata>
2479  </xsl:template>
2480
2481  <!-- Create a license logo and description in the image -->
2482  <xsl:template name="in-image-license">
2483    <xsl:param name="dx"/>
2484    <xsl:param name="dy"/>
2485
2486    <g id="license" inkscape:groupmode="layer" inkscape:label="Copyright" transform="translate({$dx},{$dy})">
2487      <style type="text/css">
2488        <![CDATA[
2489                .license-text {
2490                    text-anchor: left;
2491                    font-family: "DejaVu Sans",sans-serif;
2492                    font-size: 6px;
2493                    fill: black;
2494                }
2495            ]]>
2496      </style>
2497      <a id="license-cc-logo-link" xlink:href="http://creativecommons.org/licenses/by-sa/2.0/">
2498        <g id="license-cc-logo" transform="scale(0.5,0.5) translate(-604,-49)">
2499          <path id="path3817_2_" nodetypes="ccccccc" d="M
2500                    182.23532,75.39014 L 296.29928,75.59326 C
2501                    297.89303,75.59326 299.31686,75.35644 299.31686,78.77344 L
2502                    299.17721,116.34033 L 179.3569,116.34033 L
2503                    179.3569,78.63379 C 179.3569,76.94922 179.51999,75.39014
2504                    182.23532,75.39014 z " style="fill:#aab2ab"/>
2505          <g id="g5908_2_" transform="matrix(0.872921,0,0,0.872921,50.12536,143.2144)">
2506            <path id="path5906_2_" type="arc" cx="296.35416"
2507            cy="264.3577" ry="22.939548" rx="22.939548" d="M
2508                        187.20944,-55.6792 C 187.21502,-46.99896
2509                        180.18158,-39.95825 171.50134,-39.95212 C
2510                        162.82113,-39.94708 155.77929,-46.97998
2511                        155.77426,-55.66016 C 155.77426,-55.66687
2512                        155.77426,-55.67249 155.77426,-55.6792 C
2513                        155.76922,-64.36054 162.80209,-71.40125
2514                        171.48233,-71.40631 C 180.16367,-71.41193
2515                        187.20441,-64.37842 187.20944,-55.69824 C
2516                        187.20944,-55.69263 187.20944,-55.68591
2517                        187.20944,-55.6792 z " style="fill:white"/>
2518            <g id="g5706_2_" transform="translate(-289.6157,99.0653)">
2519              <path id="path5708_2_" d="M 473.88455,-167.54724 C
2520                            477.36996,-164.06128 479.11294,-159.79333
2521                            479.11294,-154.74451 C 479.11294,-149.69513
2522                            477.40014,-145.47303 473.9746,-142.07715 C
2523                            470.33929,-138.50055 466.04281,-136.71283
2524                            461.08513,-136.71283 C 456.18736,-136.71283
2525                            451.96526,-138.48544 448.42003,-142.03238 C
2526                            444.87419,-145.57819 443.10158,-149.81537
2527                            443.10158,-154.74451 C 443.10158,-159.6731
2528                            444.87419,-163.94049 448.42003,-167.54724 C
2529                            451.87523,-171.03375 456.09728,-172.77618
2530                            461.08513,-172.77618 C 466.13342,-172.77618
2531                            470.39914,-171.03375 473.88455,-167.54724 z M
2532                            450.76657,-165.20239 C 447.81982,-162.22601
2533                            446.34701,-158.7395 446.34701,-154.74005 C
2534                            446.34701,-150.7417 447.80529,-147.28485
2535                            450.72125,-144.36938 C 453.63778,-141.45288
2536                            457.10974,-139.99462 461.1383,-139.99462 C
2537                            465.16683,-139.99462 468.66848,-141.46743
2538                            471.64486,-144.41363 C 474.47076,-147.14947
2539                            475.88427,-150.59069 475.88427,-154.74005 C
2540                            475.88427,-158.85809 474.44781,-162.35297
2541                            471.57659,-165.22479 C 468.70595,-168.09546
2542                            465.22671,-169.53131 461.1383,-169.53131 C
2543                            457.04993,-169.53131 453.59192,-168.08813
2544                            450.76657,-165.20239 z M 458.52106,-156.49927 C
2545                            458.07074,-157.4809 457.39673,-157.9715
2546                            456.49781,-157.9715 C 454.90867,-157.9715
2547                            454.11439,-156.90198 454.11439,-154.763 C
2548                            454.11439,-152.62341 454.90867,-151.55389
2549                            456.49781,-151.55389 C 457.54719,-151.55389
2550                            458.29676,-152.07519 458.74647,-153.11901 L
2551                            460.94923,-151.94598 C 459.8993,-150.0805
2552                            458.32417,-149.14697 456.22374,-149.14697 C
2553                            454.60384,-149.14697 453.30611,-149.64367
2554                            452.33168,-150.63653 C 451.35561,-151.62994
2555                            450.86894,-152.99926 450.86894,-154.7445 C
2556                            450.86894,-156.46008 451.37123,-157.82159
2557                            452.37642,-158.83013 C 453.38161,-159.83806
2558                            454.63347,-160.34264 456.13423,-160.34264 C
2559                            458.35435,-160.34264 459.94407,-159.46776
2560                            460.90504,-157.71978 L 458.52106,-156.49927 z M
2561                            468.8844,-156.49927 C 468.43353,-157.4809
2562                            467.77292,-157.9715 466.90201,-157.9715 C
2563                            465.28095,-157.9715 464.46988,-156.90198
2564                            464.46988,-154.763 C 464.46988,-152.62341
2565                            465.28095,-151.55389 466.90201,-151.55389 C
2566                            467.95304,-151.55389 468.68918,-152.07519
2567                            469.10925,-153.11901 L 471.36126,-151.94598 C
2568                            470.31301,-150.0805 468.74007,-149.14697
2569                            466.64358,-149.14697 C 465.02587,-149.14697
2570                            463.73095,-149.64367 462.75711,-150.63653 C
2571                            461.78494,-151.62994 461.29773,-152.99926
2572                            461.29773,-154.7445 C 461.29773,-156.46008
2573                            461.79221,-157.82159 462.78061,-158.83013 C
2574                            463.76843,-159.83806 465.02588,-160.34264
2575                            466.55408,-160.34264 C 468.77027,-160.34264
2576                            470.35776,-159.46776 471.3154,-157.71978 L
2577                            468.8844,-156.49927 z "/>
2578            </g>
2579          </g>
2580          <path d="M 297.29639,74.91064 L 181.06688,74.91064 C
2581                    179.8203,74.91064 178.80614,75.92529 178.80614,77.17187 L
2582                    178.80614,116.66748 C 178.80614,116.94922
2583                    179.03466,117.17822 179.31639,117.17822 L
2584                    299.04639,117.17822 C 299.32813,117.17822
2585                    299.55713,116.94922 299.55713,116.66748 L
2586                    299.55713,77.17188 C 299.55713,75.92529 298.54297,74.91064
2587                    297.29639,74.91064 z M 181.06688,75.93213 L
2588                    297.29639,75.93213 C 297.97998,75.93213 298.53565,76.48828
2589                    298.53565,77.17188 C 298.53565,77.17188 298.53565,93.09131
2590                    298.53565,104.59034 L 215.4619,104.59034 C
2591                    212.41698,110.09571 206.55077,113.83399 199.81835,113.83399
2592                    C 193.083,113.83399 187.21825,110.09913 184.1748,104.59034
2593                    L 179.82666,104.59034 C 179.82666,93.09132
2594                    179.82666,77.17188 179.82666,77.17188 C 179.82664,76.48828
2595                    180.38329,75.93213 181.06688,75.93213 z " id="frame"/>
2596          <g enable-background="new" id="g2821">
2597            <path d="M 265.60986,112.8833 C 265.68994,113.03906
2598                        265.79736,113.16504 265.93115,113.26172 C
2599                        266.06494,113.35791 266.22119,113.42969
2600                        266.40088,113.47608 C 266.58154,113.52296
2601                        266.76807,113.54639 266.96045,113.54639 C
2602                        267.09033,113.54639 267.22998,113.53565
2603                        267.3794,113.51368 C 267.52784,113.4922
2604                        267.66749,113.44972 267.79835,113.3877 C
2605                        267.92823,113.32569 268.03761,113.23975
2606                        268.12355,113.13086 C 268.21144,113.02197
2607                        268.25441,112.88379 268.25441,112.71533 C
2608                        268.25441,112.53515 268.19679,112.38916
2609                        268.08156,112.27685 C 267.9673,112.16455
2610                        267.81594,112.07177 267.62941,111.99658 C
2611                        267.44386,111.92236 267.23195,111.85693
2612                        266.9966,111.80078 C 266.76027,111.74463
2613                        266.52101,111.68262 266.27883,111.61377 C
2614                        266.02981,111.55176 265.78762,111.47559
2615                        265.55129,111.38525 C 265.31594,111.29541
2616                        265.10402,111.17822 264.9175,111.03515 C
2617                        264.73098,110.89208 264.58059,110.71337
2618                        264.46535,110.49853 C 264.35109,110.28369
2619                        264.29347,110.02392 264.29347,109.71923 C
2620                        264.29347,109.37646 264.36671,109.07958
2621                        264.51222,108.82763 C 264.6587,108.57568
2622                        264.85011,108.36572 265.08644,108.19726 C
2623                        265.32179,108.02929 265.58937,107.90478
2624                        265.8882,107.82372 C 266.18605,107.74315
2625                        266.48488,107.70263 266.78273,107.70263 C
2626                        267.13136,107.70263 267.46535,107.74169
2627                        267.78566,107.81982 C 268.105,107.89746
2628                        268.39015,108.02392 268.6382,108.19824 C
2629                        268.88722,108.37256 269.08449,108.59521
2630                        269.23097,108.86621 C 269.37648,109.13721
2631                        269.44972,109.46582 269.44972,109.85156 L
2632                        268.02784,109.85156 C 268.01514,109.65234
2633                        267.97315,109.4873 267.90284,109.35693 C
2634                        267.83155,109.22607 267.73682,109.12353
2635                        267.61964,109.04834 C 267.50148,108.97412
2636                        267.36671,108.9209 267.21534,108.89014 C
2637                        267.063,108.85889 266.89796,108.84326
2638                        266.71827,108.84326 C 266.60108,108.84326
2639                        266.48292,108.85596 266.36573,108.88037 C
2640                        266.24757,108.90576 266.14112,108.94922
2641                        266.04542,109.01123 C 265.94874,109.07373
2642                        265.86964,109.15137 265.80812,109.24463 C
2643                        265.7466,109.33838 265.71535,109.45654
2644                        265.71535,109.59961 C 265.71535,109.73047
2645                        265.73976,109.83643 265.78957,109.91699 C
2646                        265.83937,109.99804 265.93801,110.07275
2647                        266.08352,110.14111 C 266.22903,110.20947
2648                        266.43118,110.27832 266.68899,110.34668 C
2649                        266.9468,110.41504 267.28372,110.50244
2650                        267.70071,110.60791 C 267.82473,110.63281
2651                        267.99661,110.67822 268.21731,110.74365 C
2652                        268.43801,110.80908 268.65676,110.91308
2653                        268.87454,111.05615 C 269.09231,111.1997
2654                        269.27981,111.39111 269.43899,111.63037 C
2655                        269.59719,111.87012 269.67629,112.17676
2656                        269.67629,112.55029 C 269.67629,112.85547
2657                        269.61672,113.13867 269.49856,113.3999 C
2658                        269.3804,113.66162 269.20461,113.8872
2659                        268.97122,114.07666 C 268.73782,114.26709
2660                        268.44876,114.41455 268.10403,114.52051 C
2661                        267.75833,114.62647 267.35794,114.6792
2662                        266.90481,114.6792 C 266.53762,114.6792
2663                        266.18118,114.63379 265.83547,114.54346 C
2664                        265.49074,114.45313 265.18508,114.31104
2665                        264.92043,114.11768 C 264.65676,113.92432
2666                        264.4468,113.67774 264.29055,113.37891 C
2667                        264.13528,113.07959 264.06106,112.7251
2668                        264.06692,112.31397 L 265.4888,112.31397 C
2669                        265.48877,112.53809 265.52881,112.72803
2670                        265.60986,112.8833 z " id="path2823"
2671            style="fill:white"/>
2672            <path d="M 273.8667,107.8667 L
2673                        276.35986,114.53076 L 274.8374,114.53076 L
2674                        274.33349,113.04638 L 271.84033,113.04638 L
2675                        271.31787,114.53076 L 269.84326,114.53076 L
2676                        272.36377,107.8667 L 273.8667,107.8667 z M
2677                        273.95068,111.95264 L 273.11084,109.50928 L
2678                        273.09229,109.50928 L 272.22315,111.95264 L
2679                        273.95068,111.95264 z " id="path2825"
2680            style="fill:white"/>
2681          </g>
2682          <g enable-background="new" id="g2827">
2683            <path d="M 239.17821,107.8667 C 239.49559,107.8667
2684                        239.78563,107.89502 240.04735,107.95068 C
2685                        240.30907,108.00683 240.53368,108.09863
2686                        240.72118,108.22607 C 240.9077,108.35351
2687                        241.05321,108.52295 241.15575,108.73437 C
2688                        241.25829,108.94579 241.31005,109.20703
2689                        241.31005,109.51806 C 241.31005,109.854
2690                        241.23388,110.13329 241.08056,110.35742 C
2691                        240.92822,110.58154 240.70165,110.76465
2692                        240.40283,110.90771 C 240.81494,111.02587
2693                        241.12256,111.23291 241.32568,111.5288 C
2694                        241.5288,111.82469 241.63037,112.18114
2695                        241.63037,112.59814 C 241.63037,112.93408
2696                        241.56494,113.22509 241.43408,113.47119 C
2697                        241.30322,113.7168 241.12646,113.91748
2698                        240.90576,114.07324 C 240.68408,114.229
2699                        240.43115,114.34424 240.14795,114.41845 C
2700                        239.86377,114.49365 239.57275,114.53075
2701                        239.27295,114.53075 L 236.03662,114.53075 L
2702                        236.03662,107.86669 L 239.17821,107.86669 L
2703                        239.17821,107.8667 z M 238.99071,110.56201 C
2704                        239.25243,110.56201 239.46727,110.5 239.63622,110.37597
2705                        C 239.80419,110.25146 239.88817,110.05029
2706                        239.88817,109.77099 C 239.88817,109.61572
2707                        239.85985,109.48828 239.80419,109.38915 C
2708                        239.74755,109.28954 239.67333,109.21239
2709                        239.57958,109.15624 C 239.48583,109.10058
2710                        239.37841,109.06151 239.25731,109.04003 C
2711                        239.13524,109.01806 239.00926,109.00732
2712                        238.8784,109.00732 L 237.50535,109.00732 L
2713                        237.50535,110.56201 L 238.99071,110.56201 z M
2714                        239.07664,113.39014 C 239.22019,113.39014
2715                        239.35691,113.37647 239.48777,113.34815 C
2716                        239.61863,113.32032 239.73484,113.27344
2717                        239.83445,113.2085 C 239.93406,113.14307
2718                        240.01316,113.0542 240.07273,112.94239 C
2719                        240.1323,112.83058 240.1616,112.68751
2720                        240.1616,112.51319 C 240.1616,112.17139
2721                        240.06492,111.92725 239.87156,111.78126 C
2722                        239.6782,111.63527 239.42234,111.56202
2723                        239.10496,111.56202 L 237.50535,111.56202 L
2724                        237.50535,113.39014 L 239.07664,113.39014 z "
2725            id="path2829" style="fill:white"/>
2726            <path d="M 241.88914,107.8667 L 243.53269,107.8667 L
2727                        245.09324,110.49854 L 246.64402,107.8667 L
2728                        248.27781,107.8667 L 245.80418,111.97315 L
2729                        245.80418,114.53077 L 244.33543,114.53077 L
2730                        244.33543,111.93604 L 241.88914,107.8667 z "
2731            id="path2831" style="fill:white"/>
2732          </g>
2733          <g id="g6316_1_" transform="matrix(0.624995,0,0,0.624995,391.2294,176.9332)">
2734            <path id="path6318_1_" type="arc" cx="475.97119"
2735            cy="252.08646" ry="29.209877" rx="29.209877" d="M
2736                        -175.0083,-139.1153 C -175.00204,-129.7035
2737                        -182.62555,-122.06751 -192.03812,-122.06049 C
2738                        -201.44913,-122.05341 -209.08512,-129.67774
2739                        -209.09293,-139.09028 C -209.09293,-139.09809
2740                        -209.09293,-139.10749 -209.09293,-139.1153 C
2741                        -209.09919,-148.52784 -201.47413,-156.1623
2742                        -192.06311,-156.17011 C -182.65054,-156.17713
2743                        -175.01456,-148.55207 -175.0083,-139.14026 C
2744                        -175.0083,-139.13092 -175.0083,-139.1239
2745                        -175.0083,-139.1153 z " style="fill:white"/>
2746            <g id="g6320_1_" transform="translate(-23.9521,-89.72962)">
2747              <path id="path6322_1_" d="M -168.2204,-68.05536 C
2748                            -173.39234,-68.05536 -177.76892,-66.25067
2749                            -181.35175,-62.64203 C -185.02836,-58.90759
2750                            -186.86588,-54.48883 -186.86588,-49.38568 C
2751                            -186.86588,-44.28253 -185.02836,-39.89416
2752                            -181.35175,-36.22308 C -177.67673,-32.55114
2753                            -173.29859,-30.71521 -168.2204,-30.71521 C
2754                            -163.07974,-30.71521 -158.62503,-32.56677
2755                            -154.85312,-36.26996 C -151.30307,-39.78558
2756                            -149.52652,-44.15827 -149.52652,-49.38568 C
2757                            -149.52652,-54.6123 -151.33432,-59.03265
2758                            -154.94843,-62.64203 C -158.5625,-66.25067
2759                            -162.98599,-68.05536 -168.2204,-68.05536 z M
2760                            -168.17352,-64.69519 C -163.936,-64.69519
2761                            -160.33752,-63.20221 -157.37655,-60.21466 C
2762                            -154.38748,-57.25836 -152.89214,-53.64899
2763                            -152.89214,-49.38568 C -152.89214,-45.09186
2764                            -154.35466,-41.52856 -157.28438,-38.69653 C
2765                            -160.36876,-35.64727 -163.99849,-34.12304
2766                            -168.17351,-34.12304 C -172.34856,-34.12304
2767                            -175.94701,-35.63244 -178.96892,-38.64965 C
2768                            -181.9908,-41.66918 -183.50176,-45.24657
2769                            -183.50176,-49.38567 C -183.50176,-53.52398
2770                            -181.97518,-57.13414 -178.92205,-60.21465 C
2771                            -175.9939,-63.20221 -172.41107,-64.69519
2772                            -168.17352,-64.69519 z "/>
2773              <path id="path6324_1_" d="M -176.49548,-52.02087 C
2774                            -175.75171,-56.71856 -172.44387,-59.22949
2775                            -168.30008,-59.22949 C -162.33911,-59.22949
2776                            -158.70783,-54.90448 -158.70783,-49.1372 C
2777                            -158.70783,-43.50982 -162.57194,-39.13793
2778                            -168.39383,-39.13793 C -172.39856,-39.13793
2779                            -175.98297,-41.60277 -176.63611,-46.43877 L
2780                            -171.93292,-46.43877 C -171.7923,-43.92778
2781                            -170.1626,-43.04418 -167.83447,-43.04418 C
2782                            -165.1813,-43.04418 -163.4563,-45.50908
2783                            -163.4563,-49.27709 C -163.4563,-53.22942
2784                            -164.94693,-55.32244 -167.74228,-55.32244 C
2785                            -169.79074,-55.32244 -171.55948,-54.57787
2786                            -171.93292,-52.02087 L -170.56418,-52.02789 L
2787                            -174.26734,-48.32629 L -177.96894,-52.02789 L
2788                            -176.49548,-52.02087 z "/>
2789            </g>
2790          </g>
2791          <g id="g2838">
2792            <circle cx="242.56226" cy="90.224609" r="10.8064" id="circle2840" style="fill:white"/>
2793            <g id="g2842">
2794              <path d="M 245.68994,87.09766 C 245.68994,86.68116
2795                            245.35205,86.34424 244.93603,86.34424 L
2796                            240.16357,86.34424 C 239.74755,86.34424
2797                            239.40966,86.68115 239.40966,87.09766 L
2798                            239.40966,91.87061 L 240.74071,91.87061 L
2799                            240.74071,97.52295 L 244.3579,97.52295 L
2800                            244.3579,91.87061 L 245.68993,91.87061 L
2801                            245.68993,87.09766 L 245.68994,87.09766 z "
2802              id="path2844"/>
2803              <circle cx="242.5498" cy="84.083008" r="1.63232" id="circle2846"/>
2804            </g>
2805            <path clip-rule="evenodd" d="M 242.53467,78.31836 C
2806                        239.30322,78.31836 236.56641,79.4458 234.32715,81.70215
2807                        C 232.0293,84.03516 230.88086,86.79736
2808                        230.88086,89.98633 C 230.88086,93.1753
2809                        232.0293,95.91846 234.32715,98.21338 C
2810                        236.625,100.50781 239.36133,101.65527
2811                        242.53467,101.65527 C 245.74756,101.65527
2812                        248.53272,100.49853 250.88819,98.18359 C
2813                        253.10889,95.98681 254.21827,93.2539 254.21827,89.98632
2814                        C 254.21827,86.71874 253.08936,83.95751
2815                        250.83057,81.70214 C 248.57178,79.4458
2816                        245.80615,78.31836 242.53467,78.31836 z M
2817                        242.56396,80.41797 C 245.2124,80.41797
2818                        247.46142,81.35156 249.31103,83.21875 C
2819                        251.18115,85.06592 252.11572,87.32227
2820                        252.11572,89.98633 C 252.11572,92.66992
2821                        251.20068,94.89746 249.36963,96.66699 C
2822                        247.4419,98.57275 245.17334,99.52539 242.56397,99.52539
2823                        C 239.9546,99.52539 237.70557,98.58252
2824                        235.81739,96.6958 C 233.92774,94.80957
2825                        232.98389,92.57324 232.98389,89.98633 C
2826                        232.98389,87.3999 233.93799,85.14404 235.84619,83.21875
2827                        C 237.67676,81.35156 239.9165,80.41797
2828                        242.56396,80.41797 z " id="path2848"
2829            style="fill-rule:evenodd"/>
2830          </g>
2831        </g>
2832      </a>
2833      <a id="license-osm-link" xlink:href="http://www.openstreetmap.org/">
2834        <g transform="translate(-210,10)" id="license-osm-text">
2835          <text class="license-text" dx="0" dy="0">
2836            Copyright © <xsl:value-of select="$year"/> OpenStreetMap (openstreetmap.org)
2837          </text>
2838        </g>
2839      </a>
2840      <a id="license-cc-text-link" xlink:href="http://creativecommons.org/licenses/by-sa/2.0/">
2841        <g transform="translate(-150,18)" id="license-cc-text">
2842          <text class="license-text" dx="0" dy="0">This work is licensed under the Creative</text>
2843          <text class="license-text" dx="0" dy="8">Commons Attribution-ShareAlike 2.0 License.</text>
2844          <text class="license-text" dx="0" dy="16">http://creativecommons.org/licenses/by-sa/2.0/</text>
2845        </g>
2846      </a>
2847    </g>
2848  </xsl:template>
2849
2850
2851  <!-- Draw zoom controls -->
2852  <xsl:template name="zoomControl">
2853    <defs>
2854
2855      <style type="text/css">
2856        .fancyButton {
2857        stroke: #8080ff;
2858        stroke-width: 2px;
2859        fill: #fefefe;
2860        }
2861        .fancyButton:hover {
2862        stroke: red;
2863        }
2864      </style>
2865
2866      <filter id="fancyButton" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="350">
2867        <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>
2868        <feOffset in="blur" dx="2" dy="2" result="offsetBlur"/>
2869        <feSpecularLighting in="blur" surfaceScale="5" specularConstant=".75" specularExponent="20" lighting-color="white" result="specOut">
2870          <fePointLight x="-5000" y="-10000" z="7000"/>
2871        </feSpecularLighting>
2872        <feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut"/>
2873        <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="litPaint"/>
2874        <feMerge>
2875          <feMergeNode in="offsetBlur"/>
2876          <feMergeNode in="litPaint"/>
2877        </feMerge>
2878      </filter>
2879      <symbol id="panDown" viewBox="0 0 19 19" class="fancyButton">
2880        <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"/>
2881        <path d="M 9.5,5 L 9.5,14"/>
2882      </symbol>
2883      <symbol id="panUp" viewBox="0 0 19 19" class="fancyButton">
2884        <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"/>
2885        <path d="M 9.5,5 L 9.5,14"/>
2886      </symbol>
2887      <symbol id="panLeft" viewBox="0 0 19 19" class="fancyButton">
2888        <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"/>
2889        <path d="M 5,9.5 L 14,9.5"/>
2890      </symbol>
2891      <symbol id="panRight" viewBox="0 0 19 19" class="fancyButton">
2892        <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"/>
2893        <path d="M 5,9.5 L 14,9.5"/>
2894      </symbol>
2895      <symbol id="zoomIn" viewBox="0 0 19 19" class="fancyButton">
2896        <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"/>
2897        <path d="M 5,9.5 L 14,9.5 M 9.5,5 L 9.5,14"/>
2898      </symbol>
2899      <symbol id="zoomOut" viewBox="0 0 19 19" class="fancyButton">
2900        <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"/>
2901        <path d="M 5,9.5 L 14,9.5"/>
2902      </symbol>
2903
2904    </defs>
2905
2906    <g id="gPanDown" filter="url(#fancyButton)" onclick="fnPan('down')">
2907      <use x="18px" y="60px" xlink:href="#panDown" width="14px" height="14px"/>
2908    </g>
2909    <g id="gPanRight" filter="url(#fancyButton)" onclick="fnPan('right')">
2910      <use x="8px" y="70px" xlink:href="#panRight" width="14px" height="14px"/>
2911    </g>
2912    <g id="gPanLeft" filter="url(#fancyButton)" onclick="fnPan('left')">
2913      <use x="28px" y="70px" xlink:href="#panLeft" width="14px" height="14px"/>
2914    </g>
2915    <g id="gPanUp" filter="url(#fancyButton)" onclick="fnPan('up')">
2916      <use x="18px" y="80px" xlink:href="#panUp" width="14px" height="14px"/>
2917    </g>
2918
2919    <xsl:variable name="x1" select="25"/>
2920    <xsl:variable name="y1" select="105"/>
2921    <xsl:variable name="x2" select="25"/>
2922    <xsl:variable name="y2" select="300"/>
2923
2924    <line style="stroke-width: 10; stroke-linecap: butt; stroke: #8080ff;">
2925      <xsl:attribute name="x1">
2926        <xsl:value-of select="$x1"/>
2927      </xsl:attribute>
2928      <xsl:attribute name="y1">
2929        <xsl:value-of select="$y1"/>
2930      </xsl:attribute>
2931      <xsl:attribute name="x2">
2932        <xsl:value-of select="$x2"/>
2933      </xsl:attribute>
2934      <xsl:attribute name="y2">
2935        <xsl:value-of select="$y2"/>
2936      </xsl:attribute>
2937    </line>
2938
2939    <line style="stroke-width: 8; stroke-linecap: butt; stroke: white; stroke-dasharray: 10,1;">
2940      <xsl:attribute name="x1">
2941        <xsl:value-of select="$x1"/>
2942      </xsl:attribute>
2943      <xsl:attribute name="y1">
2944        <xsl:value-of select="$y1"/>
2945      </xsl:attribute>
2946      <xsl:attribute name="x2">
2947        <xsl:value-of select="$x2"/>
2948      </xsl:attribute>
2949      <xsl:attribute name="y2">
2950        <xsl:value-of select="$y2"/>
2951      </xsl:attribute>
2952    </line>
2953
2954    <!-- Need to use onmousedown because onclick is interfered with by the onmousedown handler for panning -->
2955    <g id="gZoomIn" filter="url(#fancyButton)" onmousedown="fnZoom('in')">
2956      <use x="15.5px" y="100px" xlink:href="#zoomIn" width="19px" height="19px"/>
2957    </g>
2958
2959    <!-- Need to use onmousedown because onclick is interfered with by the onmousedown handler for panning -->
2960    <g id="gZoomOut" filter="url(#fancyButton)" onmousedown="fnZoom('out')">
2961      <use x="15.5px" y="288px" xlink:href="#zoomOut" width="19px" height="19px"/>
2962    </g>
2963  </xsl:template>
2964
2965  <xsl:template name="javaScript">
2966    <script>
2967      /*
2968
2969      Osmarender
2970
2971      interactive.js
2972
2973      */
2974
2975      function fnResize() {
2976      fnResizeElement("gAttribution")
2977      fnResizeElement("gLicense")
2978      fnResizeElement("gZoomIn")
2979      fnResizeElement("gZoomOut")
2980      }
2981
2982
2983      function fnResizeElement(e) {
2984      //
2985      var oSVG,scale,currentTranslateX,currentTranslateY,oe
2986      //
2987      oSVG=document.rootElement
2988      scale=1/oSVG.currentScale
2989      currentTranslateX=oSVG.currentTranslate.x
2990      currentTranslateY=oSVG.currentTranslate.y
2991      oe=document.getElementById(e)
2992      if (oe) oe.setAttributeNS(null,"transform","scale("+scale+","+scale+") translate("+(-currentTranslateX)+","+(-currentTranslateY)+")")
2993      }
2994
2995
2996      function fnToggleImage(osmImage) {
2997      var xlink = 'http://www.w3.org/1999/xlink';
2998      ogThumbnail=document.getElementById('gThumbnail')
2999      if (ogThumbnail.getAttributeNS(null,"visibility")=="visible") fnHideImage()
3000      else {
3001      ogThumbnail.setAttributeNS(null,"visibility","visible")
3002      oThumbnail=document.getElementById('thumbnail')
3003      oThumbnail.setAttributeNS(xlink,"href",osmImage)
3004      }
3005      }
3006
3007      function fnHideImage() {
3008      ogThumbnail=document.getElementById('gThumbnail')
3009      ogThumbnail.setAttributeNS(null,"visibility","hidden")
3010      }
3011
3012
3013      /* The following code originally written by Jonathan Watt (http://jwatt.org/), Aug. 2005 */
3014
3015      if (!window)
3016      window = this;
3017
3018
3019      function fnOnLoad(evt) {
3020      if (!document) window.document = evt.target.ownerDocument
3021      }
3022
3023
3024      /**
3025      * Event handlers to change the current user space for the zoom and pan
3026      * controls to make them appear to be scale invariant.
3027      */
3028
3029      function fnOnZoom(evt) {
3030      try {
3031      if (evt.newScale == undefined) throw 'bad interface'
3032      // update the transform list that adjusts for zoom and pan
3033      var tlist = document.getElementById('staticElements').transform.baseVal
3034      tlist.getItem(0).setScale(1/evt.newScale, 1/evt.newScale)
3035      tlist.getItem(1).setTranslate(-evt.newTranslate.x, -evt.newTranslate.y)
3036      }
3037      catch (e) {
3038      // work around difficiencies in non-moz implementations (some don't
3039      // implement the SVGZoomEvent or SVGAnimatedTransform interfaces)
3040      var de = document.documentElement
3041      var tform = 'scale(' + 1/de.currentScale + ') ' + 'translate(' + (-de.currentTranslate.x) + ', ' + (-de.currentTranslate.y) + ')'
3042      document.getElementById('staticElements').setAttributeNS(null, 'transform', tform)
3043      }
3044      }
3045
3046
3047      function fnOnScroll(evt) {
3048      var ct = document.documentElement.currentTranslate
3049      try {
3050      // update the transform list that adjusts for zoom and pan
3051      var tlist = document.getElementById('staticElements').transform.baseVal
3052      tlist.getItem(1).setTranslate(-ct.x, -ct.y)
3053      }
3054      catch (e) {
3055      // work around difficiencies in non-moz implementations (some don't
3056      // implement the SVGAnimatedTransform interface)
3057      var tform = 'scale(' + 1/document.documentElement.currentScale + ') ' + 'translate(' + (-ct.x) + ', ' + (-ct.y) + ')';
3058      document.getElementById('staticElements').setAttributeNS(null, 'transform', tform)
3059      }
3060      }
3061
3062
3063      function fnZoom(type) {
3064      var de = document.documentElement;
3065      var oldScale = de.currentScale;
3066      var oldTranslate = { x: de.currentTranslate.x, y: de.currentTranslate.y };
3067      var s = 2;
3068      if (type == 'in') {de.currentScale *= 1.5;}
3069      if (type == 'out') {de.currentScale /= 1.4;}
3070      // correct currentTranslate so zooming is to the center of the viewport:
3071
3072      var vp_width, vp_height;
3073      try {
3074      vp_width = de.viewport.width;
3075      vp_height = de.viewport.height;
3076      }
3077      catch (e) {
3078      // work around difficiency in moz ('viewport' property not implemented)
3079      vp_width = window.innerWidth;
3080      vp_height = window.innerHeight;
3081      }
3082      de.currentTranslate.x = vp_width/2 - ((de.currentScale/oldScale) * (vp_width/2 - oldTranslate.x));
3083      de.currentTranslate.y = vp_height/2 - ((de.currentScale/oldScale) * (vp_height/2 - oldTranslate.y));
3084
3085      }
3086
3087
3088      function fnPan(type) {
3089      var de = document.documentElement;
3090      var ct = de.currentTranslate;
3091      var t = 150;
3092      if (type == 'right') ct.x += t;
3093      if (type == 'down') ct.y += t;
3094      if (type == 'left') ct.x -= t;
3095      if (type == 'up') ct.y -= t;
3096      }
3097
3098
3099      var gCurrentX,gCurrentY
3100      var gDeltaX,gDeltaY
3101      var gMouseDown=false
3102      var gCurrentTranslate=document.documentElement.currentTranslate
3103
3104      function fnOnMouseDown(evt) {
3105      gCurrentX=gCurrentTranslate.x
3106      gCurrentY=gCurrentTranslate.y
3107      gDeltaX=evt.clientX
3108      gDeltaY=evt.clientY
3109      gMouseDown=true
3110      evt.target.ownerDocument.rootElement.setAttributeNS(null,"cursor","move")
3111      }
3112
3113
3114      function fnOnMouseUp(evt) {
3115      gMouseDown=false
3116      evt.target.ownerDocument.rootElement.setAttribute("cursor","default")
3117      }
3118
3119
3120      function fnOnMouseMove(evt) {
3121      var id
3122      if (gMouseDown) {
3123      gCurrentTranslate.x=gCurrentX+evt.clientX-gDeltaX
3124      gCurrentTranslate.y=gCurrentY+evt.clientY-gDeltaY
3125      }
3126      }
3127
3128
3129    </script>
3130  </xsl:template>
3131
3132</xsl:stylesheet>
Note: See TracBrowser for help on using the repository browser.