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

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