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

Last change on this file since 5112 was 5112, checked in by frederik, 12 years ago

attempt at fixing the bug that would break all reverse direction street names

File size: 154.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                <xsl:variable name="way" select="."/>
1382
1383                <!-- Generate a reverse way path (if needed) -->
1384        <xsl:variable name="pathWayReverse">
1385            <xsl:choose>
1386                                <!-- Manual override, reverse direction -->
1387                <xsl:when test="tag[@k='name_direction']/@v='-1' or tag[@k='osmarender:nameDirection']/@v='-1'">
1388                                        <xsl:call-template name="generateWayPathReverse"/>
1389                </xsl:when>
1390                                <!-- Manual override, normal direction -->
1391                <xsl:when test="tag[@k='name_direction']/@v='1' or tag[@k='osmarender:nameDirection']/@v='1'">
1392                                        <!-- Generate nothing -->
1393                </xsl:when>
1394                                <!-- Automatic, reverse direction -->
1395                            <xsl:when test="(key('nodeById',$way/nd[1]/@ref)/@lon &gt; key('nodeById',$way/nd[last()]/@ref)/@lon)">
1396                                        <xsl:call-template name="generateWayPathReverse"/>
1397                </xsl:when>
1398            </xsl:choose>
1399        </xsl:variable>
1400                <xsl:if test="$pathWayReverse!=''">
1401                <path id="way_reverse_{@id}" d="{$pathWayReverse}"/>   
1402                </xsl:if>
1403
1404        <!-- Generate the start, middle and end paths needed for smart-linecaps (TM). -->
1405        <xsl:variable name="pathWayStart">
1406                        <xsl:call-template name="generatePathWayStart"/>
1407        </xsl:variable>
1408        <path id="way_start_{@id}" d="{$pathWayStart}"/>
1409
1410                <xsl:if test="count(nd) &gt; 1">
1411                        <xsl:variable name="pathWayMid">
1412                                <xsl:call-template name="generatePathWayMid"/>
1413                        </xsl:variable>
1414                        <path id="way_mid_{@id}" d="{$pathWayMid}"/>
1415                </xsl:if>
1416       
1417        <xsl:variable name="pathWayEnd">
1418                        <xsl:call-template name="generatePathWayEnd"/>
1419        </xsl:variable>
1420        <path id="way_end_{@id}" d="{$pathWayEnd}"/>
1421
1422    </xsl:template>
1423
1424   
1425    <!-- Generate a normal way path -->
1426    <xsl:template name="generateWayPathNormal">
1427                <xsl:for-each select="nd">
1428                        <xsl:choose>
1429                        <xsl:when test="position()=1">
1430                                <xsl:call-template name="moveToNode">
1431                                <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1432                                </xsl:call-template>
1433                        </xsl:when>
1434                        <xsl:otherwise>
1435                                <xsl:call-template name="lineToNode">
1436                                <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1437                                </xsl:call-template>
1438                        </xsl:otherwise>
1439                        </xsl:choose>
1440                </xsl:for-each>
1441    </xsl:template>
1442   
1443   
1444    <!-- Generate a normal way path -->
1445    <xsl:template name="generateWayPathReverse">
1446                <xsl:for-each select="nd">
1447                        <xsl:sort select="position()" data-type="number" order="descending"/>
1448                        <xsl:choose>
1449                        <xsl:when test="position()=1">
1450                                <xsl:call-template name="moveToNode">
1451                                <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1452                                </xsl:call-template>
1453                        </xsl:when>
1454                        <xsl:otherwise>
1455                                <xsl:call-template name="lineToNode">
1456                                <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1457                                </xsl:call-template>
1458                        </xsl:otherwise>
1459                        </xsl:choose>
1460                </xsl:for-each>
1461    </xsl:template>
1462
1463
1464    <!-- 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
1465         between the two paths is not at an angle.  -->
1466    <xsl:template name="generatePathWayStart">
1467                <xsl:call-template name="moveToNode">
1468                        <xsl:with-param name="node" select="key('nodeById',nd[1]/@ref)"/>
1469                </xsl:call-template>
1470                <xsl:call-template name="lineToMidpointPlus">
1471                        <xsl:with-param name="fromNode" select="key('nodeById',nd[1]/@ref)"/>
1472                        <xsl:with-param name="toNode" select="key('nodeById',nd[2]/@ref)"/>
1473                </xsl:call-template>
1474    </xsl:template>
1475
1476
1477    <xsl:template name="generatePathWayEnd">
1478                <xsl:call-template name="moveToNode">
1479                        <xsl:with-param name="node" select="key('nodeById',nd[position()=last()]/@ref)"/>
1480                </xsl:call-template>
1481                <xsl:call-template name="lineToMidpointMinus">
1482                        <xsl:with-param name="fromNode" select="key('nodeById',nd[position()=(last()-1)]/@ref)"/>
1483                        <xsl:with-param name="toNode" select="key('nodeById',nd[position()=last()]/@ref)"/>
1484                </xsl:call-template>
1485    </xsl:template>
1486
1487    <xsl:template name="generatePathWayMid">
1488                <xsl:for-each select="nd">
1489                        <xsl:choose>
1490                        <xsl:when test="position()=1">
1491                                <xsl:call-template name="moveToMidpointPlus">
1492                                <xsl:with-param name="fromNode" select="key('nodeById',@ref)"/>
1493                                <xsl:with-param name="toNode" select="key('nodeById',following-sibling::nd[1]/@ref)"/>
1494                                </xsl:call-template>
1495                        </xsl:when>
1496                        <xsl:when test="position()=last()">
1497                                <xsl:call-template name="lineToMidpointMinus">
1498                                <xsl:with-param name="fromNode" select="key('nodeById',preceding-sibling::nd[1]/@ref)"/>
1499                                <xsl:with-param name="toNode" select="key('nodeById',@ref)"/>
1500                                </xsl:call-template>
1501                        </xsl:when>
1502                        <xsl:otherwise>
1503                                <xsl:call-template name="lineToNode">
1504                                <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1505                                </xsl:call-template>
1506                        </xsl:otherwise>
1507                        </xsl:choose>
1508                </xsl:for-each>
1509    </xsl:template>
1510
1511
1512    <!--<xsl:template name="generatePathWayStart">
1513                <xsl:choose>
1514                        <xsl:when test="$bFrollo">
1515                                <xsl:for-each select="seg[key('segmentById',@id)][1]">
1516                                    <xsl:variable name="segmentId" select="@id"/>
1517                                        <xsl:variable name="bReverseSeg" select="@osma:reverse='1'"/>
1518                                        <xsl:variable name="bSubPath" select="(position()=1) or (@osma:sub-path='1')"/>
1519                                    <xsl:for-each select="key('segmentById',$segmentId)">
1520                                                <xsl:choose>
1521                                                        <xsl:when test="$bReverseSeg">
1522                                                                <xsl:if test="$bSubPath">
1523                                                                    <xsl:call-template name="segmentMoveToEnd"/>
1524                                                                </xsl:if>
1525                                                                <xsl:call-template name="segmentLineToMidpointMinus"/>
1526                                                        </xsl:when>
1527                                                        <xsl:otherwise>
1528                                                                <xsl:if test="$bSubPath">
1529                                                                    <xsl:call-template name="segmentMoveToStart"/>
1530                                                                </xsl:if>
1531                                                                <xsl:call-template name="segmentLineToMidpointPlus"/>
1532                                                        </xsl:otherwise>                               
1533                                                </xsl:choose>
1534                                    </xsl:for-each>
1535                                </xsl:for-each>
1536                        </xsl:when>
1537                        <xsl:otherwise>
1538                            <xsl:for-each select="seg[key('segmentById',@id)][1]">
1539                                        <xsl:variable name="segmentId" select="@id"/>
1540                                        <xsl:variable name="linkedSegment" select="key('segmentById',@id)/@from=key('segmentById',preceding-sibling::seg[1]/@id)/@to"/>
1541                                        <xsl:for-each select="key('segmentById',$segmentId)">
1542                                                <xsl:if test="not($linkedSegment)">
1543                                                        <xsl:call-template name="segmentMoveToStart"/>
1544                                                </xsl:if>
1545                                                <xsl:call-template name="segmentLineToMidpointPlus"/>
1546                                        </xsl:for-each>
1547                                </xsl:for-each>
1548                        </xsl:otherwise>               
1549                </xsl:choose>
1550    </xsl:template> -->
1551
1552
1553    <!--<xsl:template name="generatePathWayEnd">
1554                <xsl:choose>
1555                        <xsl:when test="$bFrollo">
1556                                <xsl:for-each select="seg[key('segmentById',@id)][position()=last()]">
1557                                    <xsl:variable name="segmentId" select="@id"/>
1558                                        <xsl:variable name="bReverseSeg" select="@osma:reverse='1'"/>
1559                                        <xsl:variable name="bSubPath" select="(position()=1) or (@osma:sub-path='1')"/>
1560                                    <xsl:for-each select="key('segmentById',$segmentId)">
1561                                                <xsl:choose>
1562                                                        <xsl:when test="$bReverseSeg">
1563                                                                <xsl:if test="$bSubPath">
1564                                                                    <xsl:call-template name="segmentMoveToEnd"/>
1565                                                                </xsl:if>
1566                                                                <xsl:call-template name="segmentLineToMidpointPlus"/>
1567                                                        </xsl:when>
1568                                                        <xsl:otherwise>
1569                                                                <xsl:if test="$bSubPath">
1570                                                                    <xsl:call-template name="segmentMoveToMidpointMinus"/>
1571                                                                </xsl:if>
1572                                                                <xsl:call-template name="segmentLineToEnd"/>
1573                                                        </xsl:otherwise>                               
1574                                                </xsl:choose>
1575                                    </xsl:for-each>
1576                                </xsl:for-each>
1577                        </xsl:when>
1578                        <xsl:otherwise>
1579                            <xsl:for-each select="seg[key('segmentById',@id)][position()=last()]">
1580                                        <xsl:variable name="segmentId" select="@id"/>
1581                                        <xsl:for-each select="key('segmentById',$segmentId)">
1582                                                <xsl:call-template name="segmentMoveToMidpointMinus"/>
1583                                                <xsl:call-template name="segmentLineToEnd"/>
1584                                        </xsl:for-each>
1585                                </xsl:for-each>
1586                        </xsl:otherwise>               
1587                </xsl:choose>
1588    </xsl:template>-->
1589
1590
1591    <!--<xsl:template name="generatePathWayMid">
1592                <xsl:choose>
1593                        <xsl:when test="$bFrollo">
1594                                <xsl:for-each select="seg[key('segmentById',@id)]">
1595                                    <xsl:variable name="segmentId" select="@id"/>
1596                                        <xsl:variable name="bReverseSeg" select="@osma:reverse='1'"/>
1597                                        <xsl:variable name="bSubPath" select="(position()=1) or (@osma:sub-path='1')"/>
1598                                        <xsl:variable name="bFirstSeg" select="position()=1"/>
1599                                        <xsl:variable name="bLastSeg" select="position()=last()"/>
1600                                       
1601                                    <xsl:for-each select="key('segmentById',$segmentId)">
1602                                                <xsl:choose>
1603                                                        <xsl:when test="$bReverseSeg">
1604                                                                <xsl:if test="$bSubPath">
1605                                                                        <xsl:choose>
1606                                                                                <xsl:when test='$bLastSeg'><xsl:call-template name="segmentMoveToMidpointMinus"/></xsl:when>
1607                                                                                <xsl:otherwise><xsl:call-template name="segmentMoveToEnd"/></xsl:otherwise>
1608                                                                        </xsl:choose>                                                               
1609                                                                </xsl:if>
1610                                                                <xsl:choose>
1611                                                                        <xsl:when test='$bFirstSeg'><xsl:call-template name="segmentLineToMidpointPlus"/></xsl:when>
1612                                                                        <xsl:otherwise><xsl:call-template name="segmentLineToStart"/></xsl:otherwise>
1613                                                                </xsl:choose>                                                               
1614                                                        </xsl:when>
1615                                                        <xsl:otherwise>
1616                                                                <xsl:if test="$bSubPath">
1617                                                                        <xsl:choose>
1618                                                                                <xsl:when test='$bFirstSeg'><xsl:call-template name="segmentMoveToMidpointPlus"/></xsl:when>
1619                                                                                <xsl:otherwise><xsl:call-template name="segmentMoveToStart"/></xsl:otherwise>
1620                                                                        </xsl:choose>                                                               
1621                                                                </xsl:if>
1622                                                                <xsl:choose>
1623                                                                        <xsl:when test='$bLastSeg'><xsl:call-template name="segmentLineToMidpointMinus"/></xsl:when>
1624                                                                        <xsl:otherwise><xsl:call-template name="segmentLineToEnd"/></xsl:otherwise>
1625                                                                </xsl:choose>                                                               
1626                                                        </xsl:otherwise>
1627                                                </xsl:choose>
1628                                    </xsl:for-each>
1629                                </xsl:for-each>
1630                        </xsl:when>
1631                        <xsl:otherwise> <!- Not pre-processed by frollo -
1632                            <xsl:for-each select="seg[key('segmentById',@id)]">
1633                                        <xsl:variable name="segmentId" select="@id"/>
1634                                        <xsl:variable name="linkedSegment" select="key('segmentById',@id)/@from=key('segmentById',preceding-sibling::seg[1]/@id)/@to"/>
1635                                        <xsl:variable name="bFirstSeg" select="position()=1"/>
1636                                        <xsl:variable name="bLastSeg" select="position()=last()"/>
1637
1638                                        <xsl:for-each select="key('segmentById',$segmentId)">
1639                                                <xsl:if test="not($linkedSegment)">
1640                                                        <xsl:choose>
1641                                                                <xsl:when test='$bFirstSeg'><xsl:call-template name="segmentMoveToMidpointPlus"/></xsl:when>
1642                                                                <xsl:otherwise><xsl:call-template name="segmentMoveToStart"/></xsl:otherwise>
1643                                                        </xsl:choose>                                                               
1644                                                </xsl:if>
1645                                                <xsl:choose>
1646                                                        <xsl:when test='$bLastSeg'><xsl:call-template name="segmentLineToMidpointMinus"/></xsl:when>
1647                                                        <xsl:otherwise><xsl:call-template name="segmentLineToEnd"/></xsl:otherwise>
1648                                                </xsl:choose>                                                               
1649                                        </xsl:for-each>
1650                                </xsl:for-each>
1651                        </xsl:otherwise>               
1652                </xsl:choose>
1653    </xsl:template>-->
1654
1655        <!-- Generate an area path for the current way or area element -->
1656    <xsl:template name="generateAreaPath">
1657                <xsl:variable name='relation' select="key('relationByWay',@id)[tag[@k='type' and @v='multipolygon']]"/>
1658
1659                <xsl:variable name="pathData">         
1660                        <xsl:choose>
1661                                <xsl:when test='$relation'>
1662                                        <xsl:message><xsl:value-of select='$relation/@id'/></xsl:message>
1663                                        <xsl:for-each select="$relation/member[@type='way']">
1664                                                <xsl:call-template name='generateAreaSubPath'>
1665                                                        <xsl:with-param name='way' select="key('wayById',@ref)"/>
1666                                                        <xsl:with-param name='position' select="position()"/>
1667                                                </xsl:call-template>
1668                                        </xsl:for-each>
1669                                        <xsl:text>Z</xsl:text>                 
1670                                </xsl:when>
1671                                <xsl:otherwise>
1672                                        <xsl:call-template name='generateAreaSubPath'>
1673                                                <xsl:with-param name='way' select='.'/>
1674                                                <xsl:with-param name='position' select="'1'"/>
1675                                        </xsl:call-template>
1676                                        <xsl:text>Z</xsl:text>         
1677                                </xsl:otherwise>               
1678                        </xsl:choose>
1679                </xsl:variable>
1680               
1681                <path id="area_{@id}" d="{$pathData}"/>
1682    </xsl:template>
1683
1684
1685        <xsl:template name='generateAreaSubPath'>
1686                <xsl:param name='way'/>
1687                <xsl:param name='position'/>
1688               
1689                <xsl:variable name='loop' select='$way/nd[1]/@ref=$way/nd[last()]/@ref'/>
1690                <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>
1691                <xsl:for-each select="$way/nd">
1692                        <xsl:choose>
1693                                <xsl:when test="position()=1 and $loop">
1694                                        <xsl:if test='not($position=1)'>
1695                                                <xsl:text>Z</xsl:text>
1696                                        </xsl:if>               
1697                                        <xsl:call-template name="moveToNode">
1698                                                <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1699                                        </xsl:call-template>
1700                                </xsl:when>
1701                                <xsl:otherwise>
1702                                        <xsl:call-template name="lineToNode">
1703                                                <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1704                                        </xsl:call-template>
1705                                </xsl:otherwise>
1706                        </xsl:choose>
1707                </xsl:for-each>
1708
1709       
1710        </xsl:template>
1711
1712
1713        <!-- Generate an area path for the current way or area element -->
1714    <xsl:template name="xgenerateAreaPath">
1715
1716                <!-- Generate the path for the area -->
1717                <xsl:variable name="pathData">
1718                        <xsl:choose>
1719                                <xsl:when test="$bFrollo">                     
1720                                        <xsl:for-each select="seg[key('segmentById',@id)]">
1721                                                <xsl:variable name="segmentId" select="@id"/>
1722                                                <xsl:variable name="bReverseSeg" select="@osma:reverse='1'"/>
1723                                                <xsl:variable name="bSubPath" select="@osma:sub-path='1'"/>                                             
1724                                                <xsl:variable name="fromCount" select="@osma:fromCount"/>                                               
1725                                                <xsl:variable name="segmentSequence" select="position()"/>
1726                                                <xsl:for-each select="key('segmentById',$segmentId)">
1727                                                        <xsl:choose>
1728                                                                <xsl:when test="not($bReverseSeg)">
1729                                                                        <xsl:choose>
1730                                                                                <!-- If this is the start of the way then we always have to move to the start of the segment. -->
1731                                                                                <xsl:when test="$segmentSequence=1">
1732                                                                                        <xsl:call-template name="segmentMoveToStart"/>                         
1733                                                                                </xsl:when>
1734                                                                               
1735                                                                                <!-- If the segment is connected to another segment (at the from end) and is the start of a new
1736                                                                                         sub-path then start a new sub-path -->
1737                                                                                <xsl:when test="$fromCount&gt;0 and $bSubPath">
1738                                                                                        <xsl:text>Z</xsl:text>
1739                                                                                        <xsl:call-template name="segmentMoveToStart"/>                         
1740                                                                                </xsl:when>
1741                                                                               
1742                                                                                <!-- If the segment is the start of a new sub-path, but is not connected to any previous
1743                                                                                     segment then draw an artificial line.  Typically this happens when a tile boundary chops
1744                                                                                     through the middle of an area or a river is segmented into manageable chunks. -->
1745                                                                                <xsl:otherwise>
1746                                                                                        <xsl:call-template name="segmentLineToStart"/>
1747                                                                                </xsl:otherwise>
1748                                                                        </xsl:choose>
1749                                                                        <xsl:call-template name="segmentLineToEnd"/>                                                           
1750                                                                </xsl:when>
1751                                                                <xsl:otherwise>
1752                                                                        <xsl:choose>
1753                                                                                <!-- If this is the start of the way then we always have to move to the start of the segment. -->
1754                                                                                <xsl:when test="$segmentSequence=1">
1755                                                                                        <xsl:call-template name="segmentMoveToEnd"/>                           
1756                                                                                </xsl:when>
1757                                                                               
1758                                                                                <!-- If the segment is connected to another segment (at the from end) and is the start of a new
1759                                                                                         sub-path then start a new sub-path -->
1760                                                                                <xsl:when test="$fromCount&gt;0 and $bSubPath">
1761                                                                                        <xsl:text>Z</xsl:text>
1762                                                                                        <xsl:call-template name="segmentMoveToEnd"/>                           
1763                                                                                </xsl:when>
1764                                                                               
1765                                                                                <!-- If the segment is the start of a new sub-path, but is not connected to any previous
1766                                                                                     segment then draw an artificial line.  Typically this happens when a tile boundary chops
1767                                                                                     through the middle of an area or a river is segmented into manageable chunks. -->
1768                                                                                <xsl:otherwise>
1769                                                                                        <xsl:call-template name="segmentLineToEnd"/>
1770                                                                                </xsl:otherwise>
1771                                                                        </xsl:choose>
1772                                                                        <xsl:call-template name="segmentLineToStart"/>
1773                                                                </xsl:otherwise>
1774                                                        </xsl:choose>
1775                                                </xsl:for-each>
1776                                        </xsl:for-each>
1777                                        <xsl:text>Z</xsl:text>
1778                                </xsl:when>
1779                                <xsl:otherwise> <!-- Not pre-processed by frollo -->
1780                                        <xsl:for-each select="seg[key('segmentById',@id)]">
1781                                                <xsl:variable name="segmentId" select="@id"/>
1782                                                <xsl:variable name="currentSegmentToNodeId" select="key('segmentById',@id)/@to"/>
1783                                                <xsl:variable name="currentSegmentFromNodeId" select="key('segmentById',@id)/@from"/>
1784                                                <xsl:variable name="previousSegmentToNodeId" select="key('segmentById',preceding-sibling::seg[1]/@id)/@to"/>
1785                                               
1786                                                <!-- The linkedSegment flag indicates whether the previous segment is connected to the current segment.  If it isn't
1787                                                     then we will need to draw an additional line (segmentLineToStart) from the end of the previous segment to the
1788                                                     start of the current segment.
1789                                                -->
1790                                                <xsl:variable name="linkedSegment" select="key('segmentById',@id)/@from=$previousSegmentToNodeId"/>
1791               
1792                                                <!--  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.
1793                                                      We do this to find out if the current segment is connected from some other segment in the way.  If it is, and it
1794                                                      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
1795                                                      draw an additional line between the end of the previous segment and the start of the current segment.
1796                                                -->
1797                                                <xsl:variable name="connectedSegmentCount" select="count(../*[key('segmentById',@id)/@to=$currentSegmentFromNodeId])"/>
1798                                               
1799                                                <xsl:variable name="segmentSequence" select="position()"/>
1800                                                <xsl:for-each select="key('segmentById',$segmentId)">
1801                                                        <xsl:choose>
1802                                                                <!-- If this is the start of the way then we always have to move to the start of the segment. -->
1803                                                                <xsl:when test="$segmentSequence=1">
1804                                                                        <xsl:call-template name="segmentMoveToStart"/>                         
1805                                                                </xsl:when>
1806                                                                <!-- If the segment is "connected" to another segment (at the from end) but is not linked to the
1807                                                                         previous segment, then start a new sub-path -->
1808                                                                <xsl:when test="$connectedSegmentCount&gt;0 and not($linkedSegment)">
1809                                                                        <xsl:text>Z</xsl:text>
1810                                                                        <xsl:call-template name="segmentMoveToStart"/>                         
1811                                                                </xsl:when>
1812                                                                <!-- If the previous segment is not linked to this one we need to draw an artificial line -->
1813                                                                <xsl:when test="not($linkedSegment)">
1814                                                                        <xsl:call-template name="segmentLineToStart"/>                         
1815                                                                </xsl:when>
1816                                                        </xsl:choose>
1817                                                        <xsl:call-template name="segmentLineToEnd"/>
1818                                                </xsl:for-each>
1819                                        </xsl:for-each>
1820                                        <xsl:text>Z</xsl:text> 
1821                                </xsl:otherwise>
1822                        </xsl:choose>
1823                </xsl:variable>
1824
1825                <path id="area_{@id}" d="{$pathData}"/>
1826
1827        </xsl:template>
1828       
1829
1830    <!-- Generate a MoveTo command for a segment start -->
1831        <xsl:template name="segmentMoveToStart">
1832        <xsl:variable name="from" select="@from"/>
1833        <xsl:variable name="fromNode" select="key('nodeById',$from)"/>
1834
1835        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1836        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1837        <xsl:text>M</xsl:text>
1838        <xsl:value-of select="$x1"/>
1839        <xsl:text> </xsl:text>
1840        <xsl:value-of select="$y1"/>
1841    </xsl:template>
1842   
1843   
1844    <!-- Generate a MoveTo command for a node -->
1845        <xsl:template name="moveToNode">
1846                <xsl:param name='node' />
1847
1848        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($node/@lon))*10000*$scale)"/>
1849        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($node/@lat))*10000*$scale*$projection)"/>
1850        <xsl:text>M</xsl:text>
1851        <xsl:value-of select="$x1"/>
1852        <xsl:text> </xsl:text>
1853        <xsl:value-of select="$y1"/>
1854    </xsl:template>
1855
1856    <!-- Generate a LineTo command for a segment start -->
1857    <xsl:template name="segmentLineToStart">
1858        <xsl:variable name="from" select="@from"/>
1859        <xsl:variable name="fromNode" select="key('nodeById',$from)"/>
1860
1861        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1862        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1863        <xsl:text>L</xsl:text>
1864        <xsl:value-of select="$x1"/>
1865        <xsl:text> </xsl:text>
1866        <xsl:value-of select="$y1"/>
1867    </xsl:template>
1868   
1869    <!-- Generate a LineTo command for a nd -->
1870    <xsl:template name="lineToNode">
1871                <xsl:param name='node'/>
1872
1873        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($node/@lon))*10000*$scale)"/>
1874        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($node/@lat))*10000*$scale*$projection)"/>
1875        <xsl:text>L</xsl:text>
1876        <xsl:value-of select="$x1"/>
1877        <xsl:text> </xsl:text>
1878        <xsl:value-of select="$y1"/>
1879    </xsl:template>
1880   
1881    <!-- Generate a MoveTo command for a segment end -->
1882    <xsl:template name="segmentMoveToEnd">
1883        <xsl:variable name="to" select="@to"/>
1884        <xsl:variable name="toNode" select="key('nodeById',$to)"/>
1885
1886        <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1887        <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1888        <xsl:text>M</xsl:text>
1889        <xsl:value-of select="$x2"/>
1890        <xsl:text> </xsl:text>
1891        <xsl:value-of select="$y2"/>
1892    </xsl:template>
1893   
1894   
1895    <!-- Generate a LineTo command for a segment end -->
1896    <xsl:template name="segmentLineToEnd">
1897        <xsl:variable name="to" select="@to"/>
1898        <xsl:variable name="toNode" select="key('nodeById',$to)"/>
1899
1900        <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1901        <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1902        <xsl:text>L</xsl:text>
1903        <xsl:value-of select="$x2"/>
1904        <xsl:text> </xsl:text>
1905        <xsl:value-of select="$y2"/>
1906    </xsl:template>
1907   
1908   
1909    <xsl:template name="segmentLineToMidpoint">
1910        <xsl:variable name="from" select="@from"/>
1911        <xsl:variable name="fromNode" select="key('nodeById',$from)"/>
1912
1913        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1914        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1915
1916        <xsl:variable name="to" select="@to"/>
1917        <xsl:variable name="toNode" select="key('nodeById',$to)"/>
1918
1919        <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1920        <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1921        <xsl:text>L</xsl:text>
1922        <xsl:value-of select="$x1+(($x2 - $x1) div 2)"/>
1923        <xsl:text> </xsl:text>
1924        <xsl:value-of select="$y1+(($y2 - $y1) div 2)"/>
1925    </xsl:template>
1926
1927    <xsl:template name="segmentLineToMidpointPlus">
1928        <xsl:variable name="from" select="@from"/>
1929        <xsl:variable name="fromNode" select="key('nodeById',$from)"/>
1930
1931        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1932        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1933
1934        <xsl:variable name="to" select="@to"/>
1935        <xsl:variable name="toNode" select="key('nodeById',$to)"/>
1936
1937        <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1938        <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1939        <xsl:text>L</xsl:text>
1940        <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
1941        <xsl:text> </xsl:text>
1942        <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
1943    </xsl:template>
1944
1945
1946    <xsl:template name="lineToMidpointPlus">
1947                <xsl:param name='fromNode'/>
1948                <xsl:param name='toNode'/>
1949
1950        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1951        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1952
1953        <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1954        <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1955
1956        <xsl:text>L</xsl:text>
1957        <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
1958        <xsl:text> </xsl:text>
1959        <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
1960    </xsl:template>
1961
1962    <xsl:template name="lineToMidpointMinus">
1963                <xsl:param name='fromNode'/>
1964                <xsl:param name='toNode'/>
1965
1966        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1967        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1968
1969        <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1970        <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1971        <xsl:text>L</xsl:text>
1972        <xsl:value-of select="$x1+(($x2 - $x1) div 2.1)"/>
1973        <xsl:text> </xsl:text>
1974        <xsl:value-of select="$y1+(($y2 - $y1) div 2.1)"/>
1975    </xsl:template>
1976
1977
1978    <xsl:template name="moveToMidpointPlus">
1979                <xsl:param name='fromNode'/>
1980                <xsl:param name='toNode'/>
1981
1982        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1983        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1984
1985        <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1986        <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1987        <xsl:text>M</xsl:text>
1988        <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
1989        <xsl:text> </xsl:text>
1990        <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
1991    </xsl:template>
1992
1993
1994    <xsl:template name="segmentLineToMidpointMinus">
1995        <xsl:variable name="from" select="@from"/>
1996        <xsl:variable name="fromNode" select="key('nodeById',$from)"/>
1997
1998        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1999        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
2000
2001        <xsl:variable name="to" select="@to"/>
2002        <xsl:variable name="toNode" select="key('nodeById',$to)"/>
2003
2004        <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
2005        <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
2006        <xsl:text>L</xsl:text>
2007        <xsl:value-of select="$x1+(($x2 - $x1) div 2.1)"/>
2008        <xsl:text> </xsl:text>
2009        <xsl:value-of select="$y1+(($y2 - $y1) div 2.1)"/>
2010    </xsl:template>
2011
2012
2013    <xsl:template name="segmentMoveToMidpoint">
2014        <xsl:variable name="from" select="@from"/>
2015        <xsl:variable name="fromNode" select="key('nodeById',$from)"/>
2016
2017        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
2018        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
2019
2020        <xsl:variable name="to" select="@to"/>
2021        <xsl:variable name="toNode" select="key('nodeById',$to)"/>
2022
2023        <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
2024        <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
2025        <xsl:text>M</xsl:text>
2026        <xsl:value-of select="$x1+(($x2 - $x1) div 2)"/>
2027        <xsl:text> </xsl:text>
2028        <xsl:value-of select="$y1+(($y2 - $y1) div 2)"/>
2029    </xsl:template>
2030
2031
2032    <xsl:template name="segmentMoveToMidpointPlus">
2033        <xsl:variable name="from" select="@from"/>
2034        <xsl:variable name="fromNode" select="key('nodeById',$from)"/>
2035
2036        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
2037        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
2038
2039        <xsl:variable name="to" select="@to"/>
2040        <xsl:variable name="toNode" select="key('nodeById',$to)"/>
2041
2042        <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
2043        <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
2044        <xsl:text>M</xsl:text>
2045        <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
2046        <xsl:text> </xsl:text>
2047        <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
2048    </xsl:template>
2049
2050    <xsl:template name="segmentMoveToMidpointMinus">
2051        <xsl:variable name="from" select="@from"/>
2052        <xsl:variable name="fromNode" select="key('nodeById',$from)"/>
2053
2054        <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
2055        <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
2056
2057        <xsl:variable name="to" select="@to"/>
2058        <xsl:variable name="toNode" select="key('nodeById',$to)"/>
2059
2060        <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
2061        <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
2062        <xsl:text>M</xsl:text>
2063        <xsl:value-of select="$x1+(($x2 - $x1) div 2.1)"/>
2064        <xsl:text> </xsl:text>
2065        <xsl:value-of select="$y1+(($y2 - $y1) div 2.1)"/>
2066    </xsl:template>
2067
2068   
2069   
2070    <!-- Some attribute shouldn't be copied -->
2071    <xsl:template match="@type|@ref|@scale" mode="copyAttributes" />
2072   
2073   
2074    <!-- Copy all other attributes  -->
2075    <xsl:template match="@*" mode="copyAttributes">
2076        <xsl:copy/>
2077    </xsl:template>
2078
2079
2080        <!-- Rule processing engine -->
2081
2082        <!--
2083
2084                Calls all templates inside <rule> tags (including itself, if there are nested rules).
2085
2086                If the global var withOSMLayers is 'no', we don't care about layers and draw everything
2087                in one go. This is faster and is sometimes useful. For normal maps you want withOSMLayers
2088                to be 'yes', which is the default.
2089
2090        -->
2091    <xsl:template name="processRules">
2092
2093                <!-- First select all elements - exclude those marked as deleted by JOSM -->
2094                <xsl:variable name='elements' select="$data/osm/*[not(@action) or not(@action='delete')]" />
2095
2096        <xsl:choose>
2097
2098            <!-- Process all the rules, one layer at a time -->
2099            <xsl:when test="$withOSMLayers='yes'">
2100                <xsl:call-template name="processLayer">
2101                                        <xsl:with-param name="layer" select="'-5'"/>
2102                                        <xsl:with-param name="elements" select="$elements"/>
2103                                </xsl:call-template>
2104                <xsl:call-template name="processLayer">
2105                                        <xsl:with-param name="layer" select="'-4'"/>
2106                                        <xsl:with-param name="elements" select="$elements"/>
2107                </xsl:call-template>
2108                <xsl:call-template name="processLayer">
2109                                        <xsl:with-param name="layer" select="'-3'"/>
2110                                        <xsl:with-param name="elements" select="$elements"/>
2111                </xsl:call-template>
2112                <xsl:call-template name="processLayer">
2113                                        <xsl:with-param name="layer" select="'-2'"/>
2114                                        <xsl:with-param name="elements" select="$elements"/>
2115                </xsl:call-template>
2116                <xsl:call-template name="processLayer">
2117                                        <xsl:with-param name="layer" select="'-1'"/>
2118                                        <xsl:with-param name="elements" select="$elements"/>
2119                </xsl:call-template>
2120                <xsl:call-template name="processLayer">
2121                                        <xsl:with-param name="layer" select="'0'"/>
2122                                        <xsl:with-param name="elements" select="$elements"/>
2123                </xsl:call-template>
2124                <xsl:call-template name="processLayer">
2125                                        <xsl:with-param name="layer" select="'1'"/>
2126                                        <xsl:with-param name="elements" select="$elements"/>
2127                </xsl:call-template>
2128                <xsl:call-template name="processLayer">
2129                                        <xsl:with-param name="layer" select="'2'"/>
2130                                        <xsl:with-param name="elements" select="$elements"/>
2131                </xsl:call-template>
2132                <xsl:call-template name="processLayer">
2133                                        <xsl:with-param name="layer" select="'3'"/>
2134                                        <xsl:with-param name="elements" select="$elements"/>
2135                </xsl:call-template>
2136                <xsl:call-template name="processLayer">
2137                                        <xsl:with-param name="layer" select="'4'"/>
2138                                        <xsl:with-param name="elements" select="$elements"/>
2139                </xsl:call-template>
2140                <xsl:call-template name="processLayer">
2141                                        <xsl:with-param name="layer" select="'5'"/>
2142                                        <xsl:with-param name="elements" select="$elements"/>
2143                </xsl:call-template>
2144            </xsl:when>
2145
2146            <!-- Process all the rules, without looking at the layers -->
2147            <xsl:otherwise>
2148                <xsl:apply-templates select="/rules/rule">
2149                    <xsl:with-param name="elements" select="$elements"/>
2150                    <xsl:with-param name="layer" select="'0'"/>
2151                </xsl:apply-templates>
2152            </xsl:otherwise>
2153
2154        </xsl:choose>
2155        </xsl:template>
2156       
2157       
2158        <xsl:template name="processLayer">
2159        <xsl:param name="layer"/>
2160        <xsl:param name="elements"/>
2161
2162        <g inkscape:groupmode="layer" id="layer{$layer}" inkscape:label="Layer {$layer}">
2163            <xsl:apply-templates select="/rules/rule">
2164                <xsl:with-param name="elements" select="$elements"/>
2165                <xsl:with-param name="layer" select="$layer"/>
2166            </xsl:apply-templates>
2167        </g>
2168    </xsl:template>
2169
2170
2171        <!-- Process a rule at a specific level -->
2172        <xsl:template match='rule'>
2173        <xsl:param name="elements"/>
2174        <xsl:param name="layer"/>
2175
2176                <!-- If the rule is for a specific layer and we are processing that layer then pass *all* elements
2177                     to the rule, otherwise just select the matching elements for this layer. -->
2178                <xsl:choose>
2179                        <xsl:when test='$layer=@layer'>
2180                                <xsl:call-template name="rule">
2181                                    <xsl:with-param name="elements" select="$elements"/>
2182                                    <xsl:with-param name="layer" select="$layer"/>
2183                                </xsl:call-template>           
2184                        </xsl:when>
2185                        <xsl:otherwise>
2186                                <xsl:if test='not(@layer)'>
2187                                        <xsl:call-template name="rule">
2188                                                <xsl:with-param name="elements" select="$elements[
2189                                                        tag[@k='layer' and @v=$layer]
2190                                                        or ($layer='0' and count(tag[@k='layer'])=0)
2191                                                ]"/>
2192                                                <xsl:with-param name="layer" select="$layer"/>
2193                                        </xsl:call-template>
2194                                </xsl:if>               
2195                        </xsl:otherwise>
2196                </xsl:choose>
2197        </xsl:template>
2198
2199
2200    <xsl:template name='rule'>
2201        <xsl:param name="elements"/>
2202        <xsl:param name="layer"/>
2203
2204        <!-- This is the rule currently being processed -->
2205        <xsl:variable name="rule" select="."/>
2206
2207        <!-- Make list of elements that this rule should be applied to -->
2208        <xsl:variable name="eBare">
2209            <xsl:choose>
2210                <xsl:when test="$rule/@e='*'">node|segment|way</xsl:when>
2211                <xsl:when test="$rule/@e"><xsl:value-of select="$rule/@e"/></xsl:when>
2212                <xsl:otherwise>node|segment|way</xsl:otherwise>
2213            </xsl:choose>
2214        </xsl:variable>
2215
2216        <!-- List of keys that this rule should be applied to -->
2217        <xsl:variable name="kBare" select="$rule/@k"/>
2218
2219        <!-- List of values that this rule should be applied to -->
2220        <xsl:variable name="vBare" select="$rule/@v"/>
2221        <xsl:variable name="sBare" select="$rule/@s"/>
2222
2223        <!-- Top'n'tail selectors with | for contains usage -->
2224        <xsl:variable name="e">|<xsl:value-of select="$eBare"/>|</xsl:variable>
2225        <xsl:variable name="k">|<xsl:value-of select="$kBare"/>|</xsl:variable>
2226        <xsl:variable name="v">|<xsl:value-of select="$vBare"/>|</xsl:variable>
2227        <xsl:variable name="s">|<xsl:value-of select="$sBare"/>|</xsl:variable>
2228
2229        <xsl:variable 
2230          name="selectedElements"
2231          select="$elements[
2232            contains($e,concat('|',name(),'|')) or
2233            (contains($e,'|waysegment|') and name()='segment' and key('wayBySegment',@id))
2234            ]"/>
2235
2236
2237                <!-- Patch $s -->
2238        <xsl:choose>
2239            <xsl:when test="contains($s,'|way|')">
2240                                <xsl:choose>
2241                                    <xsl:when test="contains($k,'|*|')">
2242                                        <xsl:choose>
2243                                            <xsl:when test="contains($v,'|~|')">
2244                                                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(key('wayBySegment',(key('segmentByFromNode',@id) | key('segmentByToNode',@id))/@id)/tag)=0]"/>
2245                                                <xsl:call-template name="processElements">
2246                                                    <xsl:with-param name="eBare" select="$eBare"/>
2247                                                    <xsl:with-param name="kBare" select="$kBare"/>
2248                                                    <xsl:with-param name="vBare" select="$vBare"/>
2249                                                    <xsl:with-param name="layer" select="$layer"/>
2250                                                    <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2251                                                    <xsl:with-param name="rule" select="$rule"/>
2252                                                </xsl:call-template>
2253                                            </xsl:when>
2254                                            <xsl:when test="contains($v,'|*|')">
2255                                                <xsl:variable name="allElements" select="$selectedElements"/>
2256                                                <xsl:call-template name="processElements">
2257                                                    <xsl:with-param name="eBare" select="$eBare"/>
2258                                                    <xsl:with-param name="kBare" select="$kBare"/>
2259                                                    <xsl:with-param name="vBare" select="$vBare"/>
2260                                                    <xsl:with-param name="layer" select="$layer"/>
2261                                                    <xsl:with-param name="elements" select="$allElements"/>
2262                                                    <xsl:with-param name="rule" select="$rule"/>
2263                                                </xsl:call-template>
2264                                            </xsl:when>
2265                                            <xsl:otherwise>
2266                                                <xsl:variable name="allElementsWithValue" select="$selectedElements[key('wayBySegment',(key('segmentByFromNode',@id) | key('segmentByToNode',@id))/@id)/tag[contains($v,concat('|',@v,'|'))]]"/>
2267                                                <xsl:call-template name="processElements">
2268                                                    <xsl:with-param name="eBare" select="$eBare"/>
2269                                                    <xsl:with-param name="kBare" select="$kBare"/>
2270                                                    <xsl:with-param name="vBare" select="$vBare"/>
2271                                                    <xsl:with-param name="layer" select="$layer"/>
2272                                                    <xsl:with-param name="elements" select="$allElementsWithValue"/>
2273                                                    <xsl:with-param name="rule" select="$rule"/>
2274                                                </xsl:call-template>
2275                                            </xsl:otherwise>
2276                                        </xsl:choose>
2277                                    </xsl:when>
2278                                    <xsl:when test="contains($v,'|~|')">
2279                                        <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(key('wayBySegment',(key('segmentByFromNode',@id) | key('segmentByToNode',@id))/@id)/tag[contains($k,concat('|',@k,'|'))])=0]"/>
2280                                        <xsl:call-template name="processElements">
2281                                            <xsl:with-param name="eBare" select="$eBare"/>
2282                                            <xsl:with-param name="kBare" select="$kBare"/>
2283                                            <xsl:with-param name="vBare" select="$vBare"/>
2284                                            <xsl:with-param name="layer" select="$layer"/>
2285                                            <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2286                                            <xsl:with-param name="rule" select="$rule"/>
2287                                        </xsl:call-template>
2288                                    </xsl:when>
2289                                    <xsl:when test="contains($v,'|*|')">
2290                                        <xsl:variable name="allElementsWithKey" select="$selectedElements[key('wayBySegment',(key('segmentByFromNode',@id) | key('segmentByToNode',@id))/@id)/tag[contains($k,concat('|',@k,'|'))]]"/>
2291                                        <xsl:call-template name="processElements">
2292                                            <xsl:with-param name="eBare" select="$eBare"/>
2293                                            <xsl:with-param name="kBare" select="$kBare"/>
2294                                            <xsl:with-param name="vBare" select="$vBare"/>
2295                                            <xsl:with-param name="layer" select="$layer"/>
2296                                            <xsl:with-param name="elements" select="$allElementsWithKey"/>
2297                                            <xsl:with-param name="rule" select="$rule"/>
2298                                        </xsl:call-template>
2299                                    </xsl:when>
2300                                    <xsl:otherwise>
2301                                        <xsl:variable name="elementsWithKey" select="$selectedElements[
2302                                                        key('wayBySegment',(key('segmentByFromNode',@id) | key('segmentByToNode',@id))/@id)/tag[
2303                                                                contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))
2304                                                                ]
2305                                                        ]"/>
2306                                        <xsl:call-template name="processElements">
2307                                            <xsl:with-param name="eBare" select="$eBare"/>
2308                                            <xsl:with-param name="kBare" select="$kBare"/>
2309                                            <xsl:with-param name="vBare" select="$vBare"/>
2310                                            <xsl:with-param name="layer" select="$layer"/>
2311                                            <xsl:with-param name="elements" select="$elementsWithKey"/>
2312                                            <xsl:with-param name="rule" select="$rule"/>
2313                                        </xsl:call-template>
2314                                    </xsl:otherwise>
2315                                </xsl:choose>
2316                        </xsl:when>
2317
2318                        <xsl:otherwise>
2319                                <xsl:choose>
2320                                    <xsl:when test="contains($k,'|*|')">
2321                                        <xsl:choose>
2322                                            <xsl:when test="contains($v,'|~|')">
2323                                                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(tag)=0]"/>
2324                                                <xsl:call-template name="processElements">
2325                                                    <xsl:with-param name="eBare" select="$eBare"/>
2326                                                    <xsl:with-param name="kBare" select="$kBare"/>
2327                                                    <xsl:with-param name="vBare" select="$vBare"/>
2328                                                    <xsl:with-param name="layer" select="$layer"/>
2329                                                    <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2330                                                    <xsl:with-param name="rule" select="$rule"/>
2331                                                </xsl:call-template>
2332                                            </xsl:when>
2333                                            <xsl:when test="contains($v,'|*|')">
2334                                                <xsl:variable name="allElements" select="$selectedElements"/>
2335                                                <xsl:call-template name="processElements">
2336                                                    <xsl:with-param name="eBare" select="$eBare"/>
2337                                                    <xsl:with-param name="kBare" select="$kBare"/>
2338                                                    <xsl:with-param name="vBare" select="$vBare"/>
2339                                                    <xsl:with-param name="layer" select="$layer"/>
2340                                                    <xsl:with-param name="elements" select="$allElements"/>
2341                                                    <xsl:with-param name="rule" select="$rule"/>
2342                                                </xsl:call-template>
2343                                            </xsl:when>
2344                                            <xsl:otherwise>
2345                                                <xsl:variable name="allElementsWithValue" select="$selectedElements[tag[contains($v,concat('|',@v,'|'))]]"/>
2346                                                <xsl:call-template name="processElements">
2347                                                    <xsl:with-param name="eBare" select="$eBare"/>
2348                                                    <xsl:with-param name="kBare" select="$kBare"/>
2349                                                    <xsl:with-param name="vBare" select="$vBare"/>
2350                                                    <xsl:with-param name="layer" select="$layer"/>
2351                                                    <xsl:with-param name="elements" select="$allElementsWithValue"/>
2352                                                    <xsl:with-param name="rule" select="$rule"/>
2353                                                </xsl:call-template>
2354                                            </xsl:otherwise>
2355                                        </xsl:choose>
2356                                    </xsl:when>
2357                                    <xsl:when test="contains($v,'|~|')">
2358                                        <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(tag[contains($k,concat('|',@k,'|'))])=0]"/>
2359                                        <xsl:call-template name="processElements">
2360                                            <xsl:with-param name="eBare" select="$eBare"/>
2361                                            <xsl:with-param name="kBare" select="$kBare"/>
2362                                            <xsl:with-param name="vBare" select="$vBare"/>
2363                                            <xsl:with-param name="layer" select="$layer"/>
2364                                            <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2365                                            <xsl:with-param name="rule" select="$rule"/>
2366                                        </xsl:call-template>
2367                                    </xsl:when>
2368                                    <xsl:when test="contains($v,'|*|')">
2369                                        <xsl:variable name="allElementsWithKey" select="$selectedElements[tag[contains($k,concat('|',@k,'|'))]]"/>
2370                                        <xsl:call-template name="processElements">
2371                                            <xsl:with-param name="eBare" select="$eBare"/>
2372                                            <xsl:with-param name="kBare" select="$kBare"/>
2373                                            <xsl:with-param name="vBare" select="$vBare"/>
2374                                            <xsl:with-param name="layer" select="$layer"/>
2375                                            <xsl:with-param name="elements" select="$allElementsWithKey"/>
2376                                            <xsl:with-param name="rule" select="$rule"/>
2377                                        </xsl:call-template>
2378                                    </xsl:when>
2379                                    <xsl:otherwise>
2380                                        <xsl:variable name="elementsWithKey" select="$selectedElements[tag[contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))]]"/>
2381                                        <xsl:call-template name="processElements">
2382                                            <xsl:with-param name="eBare" select="$eBare"/>
2383                                            <xsl:with-param name="kBare" select="$kBare"/>
2384                                            <xsl:with-param name="vBare" select="$vBare"/>
2385                                            <xsl:with-param name="layer" select="$layer"/>
2386                                            <xsl:with-param name="elements" select="$elementsWithKey"/>
2387                                            <xsl:with-param name="rule" select="$rule"/>
2388                                        </xsl:call-template>
2389                                    </xsl:otherwise>
2390                                </xsl:choose>
2391                        </xsl:otherwise>
2392                </xsl:choose>
2393    </xsl:template>
2394   
2395   
2396
2397
2398    <xsl:template match="else">
2399        <xsl:param name="elements"/>
2400        <xsl:param name="layer"/>
2401
2402        <!-- This is the previous rule that is being negated -->
2403                <!-- TODO: abort if no preceding rule element -->
2404        <xsl:variable name="rule" select="preceding-sibling::rule[1]"/>
2405
2406        <!-- Make list of elements that this rule should be applied to -->
2407        <xsl:variable name="eBare">
2408            <xsl:choose>
2409                <xsl:when test="$rule/@e='*'">node|segment|way</xsl:when>
2410                <xsl:when test="$rule/@e"><xsl:value-of select="$rule/@e"/></xsl:when>
2411                <xsl:otherwise>node|segment|way</xsl:otherwise>
2412            </xsl:choose>
2413        </xsl:variable>
2414
2415        <!-- List of keys that this rule should be applied to -->
2416        <xsl:variable name="kBare" select="$rule/@k"/>
2417
2418        <!-- List of values that this rule should be applied to -->
2419        <xsl:variable name="vBare" select="$rule/@v"/>
2420        <xsl:variable name="sBare" select="$rule/@s"/>  <!-- Patch $s -->
2421
2422        <!-- Top'n'tail selectors with | for contains usage -->
2423        <xsl:variable name="e">|<xsl:value-of select="$eBare"/>|</xsl:variable>
2424        <xsl:variable name="k">|<xsl:value-of select="$kBare"/>|</xsl:variable>
2425        <xsl:variable name="v">|<xsl:value-of select="$vBare"/>|</xsl:variable>
2426        <xsl:variable name="s">|<xsl:value-of select="$sBare"/>|</xsl:variable>
2427
2428        <xsl:variable 
2429          name="selectedElements"
2430          select="$elements[
2431            contains($e,concat('|',name(),'|')) or
2432            (contains($e,'|waysegment|') and name()='segment' and key('wayBySegment',@id))
2433            ]"/>
2434
2435        <xsl:choose>
2436            <xsl:when test="contains($s,'|way|')">
2437                                <xsl:choose>
2438                                    <xsl:when test="contains($k,'|*|')">
2439                                        <xsl:choose>
2440                                            <xsl:when test="contains($v,'|~|')">
2441                                                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(key('wayBySegment',(key('segmentByFromNode',@id) | key('segmentByToNode',@id))/@id)/tag)!=0]"/>
2442                                                <xsl:call-template name="processElements">
2443                                                    <xsl:with-param name="eBare" select="$eBare"/>
2444                                                    <xsl:with-param name="kBare" select="$kBare"/>
2445                                                    <xsl:with-param name="vBare" select="$vBare"/>
2446                                                    <xsl:with-param name="layer" select="$layer"/>
2447                                                    <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2448                                                    <xsl:with-param name="rule" select="$rule"/>
2449                                                </xsl:call-template>
2450                                            </xsl:when>
2451                                            <xsl:when test="contains($v,'|*|')">
2452                                                <!-- no-op! -->
2453                                            </xsl:when>
2454                                            <xsl:otherwise>
2455                                                <xsl:variable name="allElementsWithValue" select="$selectedElements[not(key('wayBySegment',(key('segmentByFromNode',@id) | key('segmentByToNode',@id))/@id)/tag[contains($v,concat('|',@v,'|'))])]"/>
2456                                                <xsl:call-template name="processElements">
2457                                                    <xsl:with-param name="eBare" select="$eBare"/>
2458                                                    <xsl:with-param name="kBare" select="$kBare"/>
2459                                                    <xsl:with-param name="vBare" select="$vBare"/>
2460                                                    <xsl:with-param name="layer" select="$layer"/>
2461                                                    <xsl:with-param name="elements" select="$allElementsWithValue"/>
2462                                                    <xsl:with-param name="rule" select="$rule"/>
2463                                                </xsl:call-template>
2464                                            </xsl:otherwise>
2465                                        </xsl:choose>
2466                                    </xsl:when>
2467                                    <xsl:when test="contains($v,'|~|')">
2468                                        <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(key('wayBySegment',(key('segmentByFromNode',@id) | key('segmentByToNode',@id))/@id)/tag[contains($k,concat('|',@k,'|'))])!=0]"/>
2469                                        <xsl:call-template name="processElements">
2470                                            <xsl:with-param name="eBare" select="$eBare"/>
2471                                            <xsl:with-param name="kBare" select="$kBare"/>
2472                                            <xsl:with-param name="vBare" select="$vBare"/>
2473                                            <xsl:with-param name="layer" select="$layer"/>
2474                                            <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2475                                            <xsl:with-param name="rule" select="$rule"/>
2476                                        </xsl:call-template>
2477                                    </xsl:when>
2478                                    <xsl:when test="contains($v,'|*|')">
2479                                        <xsl:variable name="allElementsWithKey" select="$selectedElements[not(key('wayBySegment',(key('segmentByFromNode',@id) | key('segmentByToNode',@id))/@id)/tag[contains($k,concat('|',@k,'|'))])]"/>
2480                                        <xsl:call-template name="processElements">
2481                                            <xsl:with-param name="eBare" select="$eBare"/>
2482                                            <xsl:with-param name="kBare" select="$kBare"/>
2483                                            <xsl:with-param name="vBare" select="$vBare"/>
2484                                            <xsl:with-param name="layer" select="$layer"/>
2485                                            <xsl:with-param name="elements" select="$allElementsWithKey"/>
2486                                            <xsl:with-param name="rule" select="$rule"/>
2487                                        </xsl:call-template>
2488                                    </xsl:when>
2489                                    <xsl:otherwise>
2490                                        <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,'|'))])]"/>
2491                                        <xsl:call-template name="processElements">
2492                                            <xsl:with-param name="eBare" select="$eBare"/>
2493                                            <xsl:with-param name="kBare" select="$kBare"/>
2494                                            <xsl:with-param name="vBare" select="$vBare"/>
2495                                            <xsl:with-param name="layer" select="$layer"/>
2496                                            <xsl:with-param name="elements" select="$elementsWithKey"/>
2497                                            <xsl:with-param name="rule" select="$rule"/>
2498                                        </xsl:call-template>
2499                                    </xsl:otherwise>
2500                                </xsl:choose>
2501                        </xsl:when>
2502                       
2503                        <xsl:otherwise> <!-- not contains $s -->
2504                                <xsl:choose>
2505                                    <xsl:when test="contains($k,'|*|')">
2506                                        <xsl:choose>
2507                                            <xsl:when test="contains($v,'|~|')">
2508                                                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(tag)!=0]"/>
2509                                                <xsl:call-template name="processElements">
2510                                                    <xsl:with-param name="eBare" select="$eBare"/>
2511                                                    <xsl:with-param name="kBare" select="$kBare"/>
2512                                                    <xsl:with-param name="vBare" select="$vBare"/>
2513                                                    <xsl:with-param name="layer" select="$layer"/>
2514                                                    <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2515                                                    <xsl:with-param name="rule" select="$rule"/>
2516                                                </xsl:call-template>
2517                                            </xsl:when>
2518                                            <xsl:when test="contains($v,'|*|')">
2519                                                <!-- no-op! -->
2520                                            </xsl:when>
2521                                            <xsl:otherwise>
2522                                                <xsl:variable name="allElementsWithValue" select="$selectedElements[not(tag[contains($v,concat('|',@v,'|'))])]"/>
2523                                                <xsl:call-template name="processElements">
2524                                                    <xsl:with-param name="eBare" select="$eBare"/>
2525                                                    <xsl:with-param name="kBare" select="$kBare"/>
2526                                                    <xsl:with-param name="vBare" select="$vBare"/>
2527                                                    <xsl:with-param name="layer" select="$layer"/>
2528                                                    <xsl:with-param name="elements" select="$allElementsWithValue"/>
2529                                                    <xsl:with-param name="rule" select="$rule"/>
2530                                                </xsl:call-template>
2531                                            </xsl:otherwise>
2532                                        </xsl:choose>
2533                                    </xsl:when>
2534                                    <xsl:when test="contains($v,'|~|')">
2535                                        <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(tag[contains($k,concat('|',@k,'|'))])!=0]"/>
2536                                        <xsl:call-template name="processElements">
2537                                            <xsl:with-param name="eBare" select="$eBare"/>
2538                                            <xsl:with-param name="kBare" select="$kBare"/>
2539                                            <xsl:with-param name="vBare" select="$vBare"/>
2540                                            <xsl:with-param name="layer" select="$layer"/>
2541                                            <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2542                                            <xsl:with-param name="rule" select="$rule"/>
2543                                        </xsl:call-template>
2544                                    </xsl:when>
2545                                    <xsl:when test="contains($v,'|*|')">
2546                                        <xsl:variable name="allElementsWithKey" select="$selectedElements[not(tag[contains($k,concat('|',@k,'|'))])]"/>
2547                                        <xsl:call-template name="processElements">
2548                                            <xsl:with-param name="eBare" select="$eBare"/>
2549                                            <xsl:with-param name="kBare" select="$kBare"/>
2550                                            <xsl:with-param name="vBare" select="$vBare"/>
2551                                            <xsl:with-param name="layer" select="$layer"/>
2552                                            <xsl:with-param name="elements" select="$allElementsWithKey"/>
2553                                            <xsl:with-param name="rule" select="$rule"/>
2554                                        </xsl:call-template>
2555                                    </xsl:when>
2556                                    <xsl:otherwise>
2557                                        <xsl:variable name="elementsWithKey" select="$selectedElements[not(tag[contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))])]"/>
2558                                        <xsl:call-template name="processElements">
2559                                            <xsl:with-param name="eBare" select="$eBare"/>
2560                                            <xsl:with-param name="kBare" select="$kBare"/>
2561                                            <xsl:with-param name="vBare" select="$vBare"/>
2562                                            <xsl:with-param name="layer" select="$layer"/>
2563                                            <xsl:with-param name="elements" select="$elementsWithKey"/>
2564                                            <xsl:with-param name="rule" select="$rule"/>
2565                                        </xsl:call-template>
2566                                    </xsl:otherwise>
2567                                </xsl:choose>
2568                        </xsl:otherwise>
2569                </xsl:choose>
2570    </xsl:template>
2571
2572   
2573    <xsl:template name="processElements">
2574        <xsl:param name="eBare"/>
2575        <xsl:param name="kBare"/>
2576        <xsl:param name="vBare"/>
2577        <xsl:param name="layer"/>
2578        <xsl:param name="elements"/>
2579        <xsl:param name="rule"/>
2580       
2581        <xsl:if test="$elements">
2582            <xsl:message>
2583Processing &lt;rule e="<xsl:value-of select="$eBare"/>" k="<xsl:value-of select="$kBare"/>" v="<xsl:value-of select="$vBare"/>" &gt; 
2584Matched by <xsl:value-of select="count($elements)"/> elements for layer <xsl:value-of select="$layer"/>.
2585            </xsl:message>
2586
2587            <xsl:apply-templates select="*">
2588                <xsl:with-param name="layer" select="$layer"/>
2589                <xsl:with-param name="elements" select="$elements"/>
2590                <xsl:with-param name="rule" select="$rule"/>
2591            </xsl:apply-templates>
2592        </xsl:if>
2593    </xsl:template>
2594   
2595   
2596   
2597   
2598        <!-- Draw SVG layers -->
2599    <xsl:template match="layer">
2600        <xsl:param name="elements"/>
2601        <xsl:param name="layer"/>
2602        <xsl:param name="rule"/>
2603
2604        <xsl:message>Processing SVG layer: <xsl:value-of select="@name"/> (at OSM layer <xsl:value-of select="$layer"/>)
2605</xsl:message>
2606
2607        <xsl:variable name="opacity">
2608            <xsl:if test="@opacity">
2609                <xsl:value-of select="concat('opacity:',@opacity,';')"/>
2610            </xsl:if>
2611        </xsl:variable>
2612
2613        <xsl:variable name="display">
2614            <xsl:if test="(@display='none') or (@display='off')">
2615                <xsl:text>display:none;</xsl:text>
2616            </xsl:if>
2617        </xsl:variable>
2618
2619        <g inkscape:groupmode="layer" id="{@name}-{$layer}" inkscape:label="{@name}">
2620            <xsl:if test="concat($opacity,$display)!=''">
2621                <xsl:attribute name="style">
2622                    <xsl:value-of select="concat($opacity,$display)"/>
2623                </xsl:attribute>
2624            </xsl:if>
2625            <xsl:apply-templates select="*">
2626                <xsl:with-param name="layer" select="$layer"/>
2627                <xsl:with-param name="elements" select="$elements"/>
2628            </xsl:apply-templates>
2629        </g>
2630
2631    </xsl:template>
2632   
2633
2634    <!-- Draw map border -->
2635    <xsl:template name="drawBorder">
2636        <!-- dasharray definitions here can be overridden in stylesheet -->
2637        <g id="border" inkscape:groupmode="layer" inkscape:label="Map Border">
2638            <line id="border-left-casing" x1="0" y1="0" x2="0" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2639            <line id="border-top-casing" x1="0" y1="0" x2="{$documentWidth}" y2="0" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2640            <line id="border-bottom-casing" x1="0" y1="{$documentHeight}" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2641            <line id="border-right-casing" x1="{$documentWidth}" y1="0" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2642
2643            <line id="border-left-core" x1="0" y1="0" x2="0" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2644            <line id="border-top-core" x1="0" y1="0" x2="{$documentWidth}" y2="0" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2645            <line id="border-bottom-core" x1="0" y1="{$documentHeight}" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2646            <line id="border-right-core" x1="{$documentWidth}" y1="0" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2647        </g>
2648    </xsl:template>
2649   
2650
2651        <!-- Draw a grid over the map in 1km increments -->
2652    <xsl:template name="drawGrid">
2653        <g id="grid" inkscape:groupmode="layer" inkscape:label="Grid">
2654            <xsl:call-template name="drawGridHorizontals">
2655                <xsl:with-param name="line" select="'1'"/>
2656            </xsl:call-template>
2657            <xsl:call-template name="drawGridVerticals">
2658                <xsl:with-param name="line" select="'1'"/>
2659            </xsl:call-template>
2660        </g>
2661    </xsl:template>
2662   
2663   
2664    <xsl:template name="drawGridHorizontals">
2665        <xsl:param name="line"/>
2666        <xsl:if test="($line*$km) &lt; $documentHeight">
2667            <line id="grid-hori-{$line}" x1="0px" y1="{$line*$km}px" x2="{$documentWidth}px" y2="{$line*$km}px" class="map-grid-line"/>
2668            <xsl:call-template name="drawGridHorizontals">
2669                <xsl:with-param name="line" select="$line+1"/>
2670            </xsl:call-template>
2671        </xsl:if>
2672    </xsl:template>
2673   
2674   
2675    <xsl:template name="drawGridVerticals">
2676        <xsl:param name="line"/>
2677        <xsl:if test="($line*$km) &lt; $documentWidth">
2678            <line id="grid-vert-{$line}" x1="{$line*$km}px" y1="0px" x2="{$line*$km}px" y2="{$documentHeight}px" class="map-grid-line"/>
2679            <xsl:call-template name="drawGridVerticals">
2680                <xsl:with-param name="line" select="$line+1"/>
2681            </xsl:call-template>
2682        </xsl:if>
2683    </xsl:template>
2684
2685
2686        <!-- Draw map title -->
2687    <xsl:template name="drawTitle">
2688        <xsl:param name="title"/>
2689
2690        <xsl:variable name="x" select="$documentWidth div 2"/>
2691        <xsl:variable name="y" select="30"/>
2692
2693        <g id="marginalia-title" inkscape:groupmode="layer" inkscape:label="Title">
2694            <rect id="marginalia-title-background" x="0px" y="0px" height="{$marginaliaTopHeight - 5}px" width="{$documentWidth}px" class="map-title-background"/>
2695            <text id="marginalia-title-text" class="map-title" x="{$x}" y="{$y}"><xsl:value-of select="$title"/></text>
2696        </g>
2697    </xsl:template>
2698   
2699   
2700        <!-- Draw an approximate scale in the bottom left corner of the map -->
2701    <xsl:template name="drawScale">
2702        <xsl:variable name="x1" select="14"/>
2703        <xsl:variable name="y1" select="round(($documentHeight)+((($bottomLeftLatitude)-(number($bottomLeftLatitude)))*10000*$scale*$projection))+28"/>
2704        <xsl:variable name="x2" select="$x1+$km"/>
2705        <xsl:variable name="y2" select="$y1"/>
2706
2707        <g id="marginalia-scale" inkscape:groupmode="layer" inkscape:label="Scale">
2708            <line id="marginalia-scale-casing" class="map-scale-casing" x1="{$x1}" y1="{$y1}" x2="{$x2}" y2="{$y2}"/>
2709
2710            <line id="marginalia-scale-core" class="map-scale-core" stroke-dasharray="{($km div 10)}" x1="{$x1}" y1="{$y1}" x2="{$x2}" y2="{$y2}"/>
2711
2712            <line id="marginalia-scale-bookend-from" class="map-scale-bookend" x1="{$x1}" y1="{$y1 + 2}" x2="{$x1}" y2="{$y1 - 10}"/>
2713
2714            <line id="marginalia-scale-bookend-to" class="map-scale-bookend" x1="{$x2}" y1="{$y2 + 2}" x2="{$x2}" y2="{$y2 - 10}"/>
2715
2716            <text id="marginalia-scale-text-from" class="map-scale-caption" x="{$x1}" y="{$y1 - 10}">0</text>
2717
2718            <text id="marginalia-scale-text-to" class="map-scale-caption" x="{$x2}" y="{$y2 - 10}">1km</text>
2719        </g>
2720    </xsl:template>
2721   
2722
2723    <!-- Create a comment in SVG source code and RDF description of license -->
2724    <xsl:template name="metadata">
2725   
2726        <xsl:comment>
2727
2728    Copyright (c) <xsl:value-of select="$year"/> OpenStreetMap
2729    www.openstreetmap.org
2730    This work is licensed under the
2731    Creative Commons Attribution-ShareAlike 2.0 License.
2732    http://creativecommons.org/licenses/by-sa/2.0/
2733
2734</xsl:comment>
2735        <metadata id="metadata">
2736            <rdf:RDF xmlns="http://web.resource.org/cc/">
2737                <cc:Work rdf:about="">
2738                    <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/"/>
2739                    <dc:format>image/svg+xml</dc:format>
2740                    <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
2741                    <dc:title><xsl:value-of select="$title"/></dc:title>
2742                    <dc:date><xsl:value-of select="$date"/></dc:date>
2743                    <dc:source>http://www.openstreetmap.org/</dc:source>
2744                </cc:Work>
2745                <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
2746                    <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
2747                    <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
2748                    <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
2749                    <cc:requires rdf:resource="http://web.resource.org/cc/Notice"/>
2750                    <cc:requires rdf:resource="http://web.resource.org/cc/Attribution"/>
2751                    <cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/>
2752                </cc:License>
2753            </rdf:RDF>
2754        </metadata>
2755    </xsl:template>
2756   
2757    <!-- Create a license logo and description in the image -->
2758    <xsl:template name="in-image-license">
2759        <xsl:param name="dx"/>
2760        <xsl:param name="dy"/>
2761
2762        <g id="license" inkscape:groupmode="layer" inkscape:label="Copyright" transform="translate({$dx},{$dy})">
2763            <style type="text/css"><![CDATA[
2764                .license-text {
2765                    text-anchor: left;
2766                    font-family: "DejaVu Sans",sans-serif;
2767                    font-size: 6px;
2768                    fill: black;
2769                }
2770            ]]></style>
2771            <a id="license-cc-logo-link" xlink:href="http://creativecommons.org/licenses/by-sa/2.0/">
2772                <g id="license-cc-logo" transform="scale(0.5,0.5) translate(-604,-49)">
2773                    <path id="path3817_2_" nodetypes="ccccccc" d="M
2774                    182.23532,75.39014 L 296.29928,75.59326 C
2775                    297.89303,75.59326 299.31686,75.35644 299.31686,78.77344 L
2776                    299.17721,116.34033 L 179.3569,116.34033 L
2777                    179.3569,78.63379 C 179.3569,76.94922 179.51999,75.39014
2778                    182.23532,75.39014 z " style="fill:#aab2ab"/>
2779                    <g id="g5908_2_" transform="matrix(0.872921,0,0,0.872921,50.12536,143.2144)">
2780                        <path id="path5906_2_" type="arc" cx="296.35416"
2781                        cy="264.3577" ry="22.939548" rx="22.939548" d="M
2782                        187.20944,-55.6792 C 187.21502,-46.99896
2783                        180.18158,-39.95825 171.50134,-39.95212 C
2784                        162.82113,-39.94708 155.77929,-46.97998
2785                        155.77426,-55.66016 C 155.77426,-55.66687
2786                        155.77426,-55.67249 155.77426,-55.6792 C
2787                        155.76922,-64.36054 162.80209,-71.40125
2788                        171.48233,-71.40631 C 180.16367,-71.41193
2789                        187.20441,-64.37842 187.20944,-55.69824 C
2790                        187.20944,-55.69263 187.20944,-55.68591
2791                        187.20944,-55.6792 z " style="fill:white"/>
2792                        <g id="g5706_2_" transform="translate(-289.6157,99.0653)">
2793                            <path id="path5708_2_" d="M 473.88455,-167.54724 C
2794                            477.36996,-164.06128 479.11294,-159.79333
2795                            479.11294,-154.74451 C 479.11294,-149.69513
2796                            477.40014,-145.47303 473.9746,-142.07715 C
2797                            470.33929,-138.50055 466.04281,-136.71283
2798                            461.08513,-136.71283 C 456.18736,-136.71283
2799                            451.96526,-138.48544 448.42003,-142.03238 C
2800                            444.87419,-145.57819 443.10158,-149.81537
2801                            443.10158,-154.74451 C 443.10158,-159.6731
2802                            444.87419,-163.94049 448.42003,-167.54724 C
2803                            451.87523,-171.03375 456.09728,-172.77618
2804                            461.08513,-172.77618 C 466.13342,-172.77618
2805                            470.39914,-171.03375 473.88455,-167.54724 z M
2806                            450.76657,-165.20239 C 447.81982,-162.22601
2807                            446.34701,-158.7395 446.34701,-154.74005 C
2808                            446.34701,-150.7417 447.80529,-147.28485
2809                            450.72125,-144.36938 C 453.63778,-141.45288
2810                            457.10974,-139.99462 461.1383,-139.99462 C
2811                            465.16683,-139.99462 468.66848,-141.46743
2812                            471.64486,-144.41363 C 474.47076,-147.14947
2813                            475.88427,-150.59069 475.88427,-154.74005 C
2814                            475.88427,-158.85809 474.44781,-162.35297
2815                            471.57659,-165.22479 C 468.70595,-168.09546
2816                            465.22671,-169.53131 461.1383,-169.53131 C
2817                            457.04993,-169.53131 453.59192,-168.08813
2818                            450.76657,-165.20239 z M 458.52106,-156.49927 C
2819                            458.07074,-157.4809 457.39673,-157.9715
2820                            456.49781,-157.9715 C 454.90867,-157.9715
2821                            454.11439,-156.90198 454.11439,-154.763 C
2822                            454.11439,-152.62341 454.90867,-151.55389
2823                            456.49781,-151.55389 C 457.54719,-151.55389
2824                            458.29676,-152.07519 458.74647,-153.11901 L
2825                            460.94923,-151.94598 C 459.8993,-150.0805
2826                            458.32417,-149.14697 456.22374,-149.14697 C
2827                            454.60384,-149.14697 453.30611,-149.64367
2828                            452.33168,-150.63653 C 451.35561,-151.62994
2829                            450.86894,-152.99926 450.86894,-154.7445 C
2830                            450.86894,-156.46008 451.37123,-157.82159
2831                            452.37642,-158.83013 C 453.38161,-159.83806
2832                            454.63347,-160.34264 456.13423,-160.34264 C
2833                            458.35435,-160.34264 459.94407,-159.46776
2834                            460.90504,-157.71978 L 458.52106,-156.49927 z M
2835                            468.8844,-156.49927 C 468.43353,-157.4809
2836                            467.77292,-157.9715 466.90201,-157.9715 C
2837                            465.28095,-157.9715 464.46988,-156.90198
2838                            464.46988,-154.763 C 464.46988,-152.62341
2839                            465.28095,-151.55389 466.90201,-151.55389 C
2840                            467.95304,-151.55389 468.68918,-152.07519
2841                            469.10925,-153.11901 L 471.36126,-151.94598 C
2842                            470.31301,-150.0805 468.74007,-149.14697
2843                            466.64358,-149.14697 C 465.02587,-149.14697
2844                            463.73095,-149.64367 462.75711,-150.63653 C
2845                            461.78494,-151.62994 461.29773,-152.99926
2846                            461.29773,-154.7445 C 461.29773,-156.46008
2847                            461.79221,-157.82159 462.78061,-158.83013 C
2848                            463.76843,-159.83806 465.02588,-160.34264
2849                            466.55408,-160.34264 C 468.77027,-160.34264
2850                            470.35776,-159.46776 471.3154,-157.71978 L
2851                            468.8844,-156.49927 z "/>
2852                        </g>
2853                    </g>
2854                    <path d="M 297.29639,74.91064 L 181.06688,74.91064 C
2855                    179.8203,74.91064 178.80614,75.92529 178.80614,77.17187 L
2856                    178.80614,116.66748 C 178.80614,116.94922
2857                    179.03466,117.17822 179.31639,117.17822 L
2858                    299.04639,117.17822 C 299.32813,117.17822
2859                    299.55713,116.94922 299.55713,116.66748 L
2860                    299.55713,77.17188 C 299.55713,75.92529 298.54297,74.91064
2861                    297.29639,74.91064 z M 181.06688,75.93213 L
2862                    297.29639,75.93213 C 297.97998,75.93213 298.53565,76.48828
2863                    298.53565,77.17188 C 298.53565,77.17188 298.53565,93.09131
2864                    298.53565,104.59034 L 215.4619,104.59034 C
2865                    212.41698,110.09571 206.55077,113.83399 199.81835,113.83399
2866                    C 193.083,113.83399 187.21825,110.09913 184.1748,104.59034
2867                    L 179.82666,104.59034 C 179.82666,93.09132
2868                    179.82666,77.17188 179.82666,77.17188 C 179.82664,76.48828
2869                    180.38329,75.93213 181.06688,75.93213 z " id="frame"/>
2870                    <g enable-background="new" id="g2821">
2871                        <path d="M 265.60986,112.8833 C 265.68994,113.03906
2872                        265.79736,113.16504 265.93115,113.26172 C
2873                        266.06494,113.35791 266.22119,113.42969
2874                        266.40088,113.47608 C 266.58154,113.52296
2875                        266.76807,113.54639 266.96045,113.54639 C
2876                        267.09033,113.54639 267.22998,113.53565
2877                        267.3794,113.51368 C 267.52784,113.4922
2878                        267.66749,113.44972 267.79835,113.3877 C
2879                        267.92823,113.32569 268.03761,113.23975
2880                        268.12355,113.13086 C 268.21144,113.02197
2881                        268.25441,112.88379 268.25441,112.71533 C
2882                        268.25441,112.53515 268.19679,112.38916
2883                        268.08156,112.27685 C 267.9673,112.16455
2884                        267.81594,112.07177 267.62941,111.99658 C
2885                        267.44386,111.92236 267.23195,111.85693
2886                        266.9966,111.80078 C 266.76027,111.74463
2887                        266.52101,111.68262 266.27883,111.61377 C
2888                        266.02981,111.55176 265.78762,111.47559
2889                        265.55129,111.38525 C 265.31594,111.29541
2890                        265.10402,111.17822 264.9175,111.03515 C
2891                        264.73098,110.89208 264.58059,110.71337
2892                        264.46535,110.49853 C 264.35109,110.28369
2893                        264.29347,110.02392 264.29347,109.71923 C
2894                        264.29347,109.37646 264.36671,109.07958
2895                        264.51222,108.82763 C 264.6587,108.57568
2896                        264.85011,108.36572 265.08644,108.19726 C
2897                        265.32179,108.02929 265.58937,107.90478
2898                        265.8882,107.82372 C 266.18605,107.74315
2899                        266.48488,107.70263 266.78273,107.70263 C
2900                        267.13136,107.70263 267.46535,107.74169
2901                        267.78566,107.81982 C 268.105,107.89746
2902                        268.39015,108.02392 268.6382,108.19824 C
2903                        268.88722,108.37256 269.08449,108.59521
2904                        269.23097,108.86621 C 269.37648,109.13721
2905                        269.44972,109.46582 269.44972,109.85156 L
2906                        268.02784,109.85156 C 268.01514,109.65234
2907                        267.97315,109.4873 267.90284,109.35693 C
2908                        267.83155,109.22607 267.73682,109.12353
2909                        267.61964,109.04834 C 267.50148,108.97412
2910                        267.36671,108.9209 267.21534,108.89014 C
2911                        267.063,108.85889 266.89796,108.84326
2912                        266.71827,108.84326 C 266.60108,108.84326
2913                        266.48292,108.85596 266.36573,108.88037 C
2914                        266.24757,108.90576 266.14112,108.94922
2915                        266.04542,109.01123 C 265.94874,109.07373
2916                        265.86964,109.15137 265.80812,109.24463 C
2917                        265.7466,109.33838 265.71535,109.45654
2918                        265.71535,109.59961 C 265.71535,109.73047
2919                        265.73976,109.83643 265.78957,109.91699 C
2920                        265.83937,109.99804 265.93801,110.07275
2921                        266.08352,110.14111 C 266.22903,110.20947
2922                        266.43118,110.27832 266.68899,110.34668 C
2923                        266.9468,110.41504 267.28372,110.50244
2924                        267.70071,110.60791 C 267.82473,110.63281
2925                        267.99661,110.67822 268.21731,110.74365 C
2926                        268.43801,110.80908 268.65676,110.91308
2927                        268.87454,111.05615 C 269.09231,111.1997
2928                        269.27981,111.39111 269.43899,111.63037 C
2929                        269.59719,111.87012 269.67629,112.17676
2930                        269.67629,112.55029 C 269.67629,112.85547
2931                        269.61672,113.13867 269.49856,113.3999 C
2932                        269.3804,113.66162 269.20461,113.8872
2933                        268.97122,114.07666 C 268.73782,114.26709
2934                        268.44876,114.41455 268.10403,114.52051 C
2935                        267.75833,114.62647 267.35794,114.6792
2936                        266.90481,114.6792 C 266.53762,114.6792
2937                        266.18118,114.63379 265.83547,114.54346 C
2938                        265.49074,114.45313 265.18508,114.31104
2939                        264.92043,114.11768 C 264.65676,113.92432
2940                        264.4468,113.67774 264.29055,113.37891 C
2941                        264.13528,113.07959 264.06106,112.7251
2942                        264.06692,112.31397 L 265.4888,112.31397 C
2943                        265.48877,112.53809 265.52881,112.72803
2944                        265.60986,112.8833 z " id="path2823"
2945                        style="fill:white"/>
2946                        <path d="M 273.8667,107.8667 L
2947                        276.35986,114.53076 L 274.8374,114.53076 L
2948                        274.33349,113.04638 L 271.84033,113.04638 L
2949                        271.31787,114.53076 L 269.84326,114.53076 L
2950                        272.36377,107.8667 L 273.8667,107.8667 z M
2951                        273.95068,111.95264 L 273.11084,109.50928 L
2952                        273.09229,109.50928 L 272.22315,111.95264 L
2953                        273.95068,111.95264 z " id="path2825"
2954                        style="fill:white"/>
2955                    </g>
2956                    <g enable-background="new" id="g2827">
2957                        <path d="M 239.17821,107.8667 C 239.49559,107.8667
2958                        239.78563,107.89502 240.04735,107.95068 C
2959                        240.30907,108.00683 240.53368,108.09863
2960                        240.72118,108.22607 C 240.9077,108.35351
2961                        241.05321,108.52295 241.15575,108.73437 C
2962                        241.25829,108.94579 241.31005,109.20703
2963                        241.31005,109.51806 C 241.31005,109.854
2964                        241.23388,110.13329 241.08056,110.35742 C
2965                        240.92822,110.58154 240.70165,110.76465
2966                        240.40283,110.90771 C 240.81494,111.02587
2967                        241.12256,111.23291 241.32568,111.5288 C
2968                        241.5288,111.82469 241.63037,112.18114
2969                        241.63037,112.59814 C 241.63037,112.93408
2970                        241.56494,113.22509 241.43408,113.47119 C
2971                        241.30322,113.7168 241.12646,113.91748
2972                        240.90576,114.07324 C 240.68408,114.229
2973                        240.43115,114.34424 240.14795,114.41845 C
2974                        239.86377,114.49365 239.57275,114.53075
2975                        239.27295,114.53075 L 236.03662,114.53075 L
2976                        236.03662,107.86669 L 239.17821,107.86669 L
2977                        239.17821,107.8667 z M 238.99071,110.56201 C
2978                        239.25243,110.56201 239.46727,110.5 239.63622,110.37597
2979                        C 239.80419,110.25146 239.88817,110.05029
2980                        239.88817,109.77099 C 239.88817,109.61572
2981                        239.85985,109.48828 239.80419,109.38915 C
2982                        239.74755,109.28954 239.67333,109.21239
2983                        239.57958,109.15624 C 239.48583,109.10058
2984                        239.37841,109.06151 239.25731,109.04003 C
2985                        239.13524,109.01806 239.00926,109.00732
2986                        238.8784,109.00732 L 237.50535,109.00732 L
2987                        237.50535,110.56201 L 238.99071,110.56201 z M
2988                        239.07664,113.39014 C 239.22019,113.39014
2989                        239.35691,113.37647 239.48777,113.34815 C
2990                        239.61863,113.32032 239.73484,113.27344
2991                        239.83445,113.2085 C 239.93406,113.14307
2992                        240.01316,113.0542 240.07273,112.94239 C
2993                        240.1323,112.83058 240.1616,112.68751
2994                        240.1616,112.51319 C 240.1616,112.17139
2995                        240.06492,111.92725 239.87156,111.78126 C
2996                        239.6782,111.63527 239.42234,111.56202
2997                        239.10496,111.56202 L 237.50535,111.56202 L
2998                        237.50535,113.39014 L 239.07664,113.39014 z "
2999                        id="path2829" style="fill:white"/>
3000                        <path d="M 241.88914,107.8667 L 243.53269,107.8667 L
3001                        245.09324,110.49854 L 246.64402,107.8667 L
3002                        248.27781,107.8667 L 245.80418,111.97315 L
3003                        245.80418,114.53077 L 244.33543,114.53077 L
3004                        244.33543,111.93604 L 241.88914,107.8667 z "
3005                        id="path2831" style="fill:white"/>
3006                    </g>
3007                    <g id="g6316_1_" transform="matrix(0.624995,0,0,0.624995,391.2294,176.9332)">
3008                        <path id="path6318_1_" type="arc" cx="475.97119"
3009                        cy="252.08646" ry="29.209877" rx="29.209877" d="M
3010                        -175.0083,-139.1153 C -175.00204,-129.7035
3011                        -182.62555,-122.06751 -192.03812,-122.06049 C
3012                        -201.44913,-122.05341 -209.08512,-129.67774
3013                        -209.09293,-139.09028 C -209.09293,-139.09809
3014                        -209.09293,-139.10749 -209.09293,-139.1153 C
3015                        -209.09919,-148.52784 -201.47413,-156.1623
3016                        -192.06311,-156.17011 C -182.65054,-156.17713
3017                        -175.01456,-148.55207 -175.0083,-139.14026 C
3018                        -175.0083,-139.13092 -175.0083,-139.1239
3019                        -175.0083,-139.1153 z " style="fill:white"/>
3020                        <g id="g6320_1_" transform="translate(-23.9521,-89.72962)">
3021                            <path id="path6322_1_" d="M -168.2204,-68.05536 C
3022                            -173.39234,-68.05536 -177.76892,-66.25067
3023                            -181.35175,-62.64203 C -185.02836,-58.90759
3024                            -186.86588,-54.48883 -186.86588,-49.38568 C
3025                            -186.86588,-44.28253 -185.02836,-39.89416
3026                            -181.35175,-36.22308 C -177.67673,-32.55114
3027                            -173.29859,-30.71521 -168.2204,-30.71521 C
3028                            -163.07974,-30.71521 -158.62503,-32.56677
3029                            -154.85312,-36.26996 C -151.30307,-39.78558
3030                            -149.52652,-44.15827 -149.52652,-49.38568 C
3031                            -149.52652,-54.6123 -151.33432,-59.03265
3032                            -154.94843,-62.64203 C -158.5625,-66.25067
3033                            -162.98599,-68.05536 -168.2204,-68.05536 z M
3034                            -168.17352,-64.69519 C -163.936,-64.69519
3035                            -160.33752,-63.20221 -157.37655,-60.21466 C
3036                            -154.38748,-57.25836 -152.89214,-53.64899
3037                            -152.89214,-49.38568 C -152.89214,-45.09186
3038                            -154.35466,-41.52856 -157.28438,-38.69653 C
3039                            -160.36876,-35.64727 -163.99849,-34.12304
3040                            -168.17351,-34.12304 C -172.34856,-34.12304
3041                            -175.94701,-35.63244 -178.96892,-38.64965 C
3042                            -181.9908,-41.66918 -183.50176,-45.24657
3043                            -183.50176,-49.38567 C -183.50176,-53.52398
3044                            -181.97518,-57.13414 -178.92205,-60.21465 C
3045                            -175.9939,-63.20221 -172.41107,-64.69519
3046                            -168.17352,-64.69519 z "/>
3047                            <path id="path6324_1_" d="M -176.49548,-52.02087 C
3048                            -175.75171,-56.71856 -172.44387,-59.22949
3049                            -168.30008,-59.22949 C -162.33911,-59.22949
3050                            -158.70783,-54.90448 -158.70783,-49.1372 C
3051                            -158.70783,-43.50982 -162.57194,-39.13793
3052                            -168.39383,-39.13793 C -172.39856,-39.13793
3053                            -175.98297,-41.60277 -176.63611,-46.43877 L
3054                            -171.93292,-46.43877 C -171.7923,-43.92778
3055                            -170.1626,-43.04418 -167.83447,-43.04418 C
3056                            -165.1813,-43.04418 -163.4563,-45.50908
3057                            -163.4563,-49.27709 C -163.4563,-53.22942
3058                            -164.94693,-55.32244 -167.74228,-55.32244 C
3059                            -169.79074,-55.32244 -171.55948,-54.57787
3060                            -171.93292,-52.02087 L -170.56418,-52.02789 L
3061                            -174.26734,-48.32629 L -177.96894,-52.02789 L
3062                            -176.49548,-52.02087 z "/>
3063                        </g>
3064                    </g>
3065                    <g id="g2838">
3066                        <circle cx="242.56226" cy="90.224609" r="10.8064" id="circle2840" style="fill:white"/>
3067                        <g id="g2842">
3068                            <path d="M 245.68994,87.09766 C 245.68994,86.68116
3069                            245.35205,86.34424 244.93603,86.34424 L
3070                            240.16357,86.34424 C 239.74755,86.34424
3071                            239.40966,86.68115 239.40966,87.09766 L
3072                            239.40966,91.87061 L 240.74071,91.87061 L
3073                            240.74071,97.52295 L 244.3579,97.52295 L
3074                            244.3579,91.87061 L 245.68993,91.87061 L
3075                            245.68993,87.09766 L 245.68994,87.09766 z "
3076                            id="path2844"/>
3077                            <circle cx="242.5498" cy="84.083008" r="1.63232" id="circle2846"/>
3078                        </g>
3079                        <path clip-rule="evenodd" d="M 242.53467,78.31836 C
3080                        239.30322,78.31836 236.56641,79.4458 234.32715,81.70215
3081                        C 232.0293,84.03516 230.88086,86.79736
3082                        230.88086,89.98633 C 230.88086,93.1753
3083                        232.0293,95.91846 234.32715,98.21338 C
3084                        236.625,100.50781 239.36133,101.65527
3085                        242.53467,101.65527 C 245.74756,101.65527
3086                        248.53272,100.49853 250.88819,98.18359 C
3087                        253.10889,95.98681 254.21827,93.2539 254.21827,89.98632
3088                        C 254.21827,86.71874 253.08936,83.95751
3089                        250.83057,81.70214 C 248.57178,79.4458
3090                        245.80615,78.31836 242.53467,78.31836 z M
3091                        242.56396,80.41797 C 245.2124,80.41797
3092                        247.46142,81.35156 249.31103,83.21875 C
3093                        251.18115,85.06592 252.11572,87.32227
3094                        252.11572,89.98633 C 252.11572,92.66992
3095                        251.20068,94.89746 249.36963,96.66699 C
3096                        247.4419,98.57275 245.17334,99.52539 242.56397,99.52539
3097                        C 239.9546,99.52539 237.70557,98.58252
3098                        235.81739,96.6958 C 233.92774,94.80957
3099                        232.98389,92.57324 232.98389,89.98633 C
3100                        232.98389,87.3999 233.93799,85.14404 235.84619,83.21875
3101                        C 237.67676,81.35156 239.9165,80.41797
3102                        242.56396,80.41797 z " id="path2848"
3103                        style="fill-rule:evenodd"/>
3104                    </g>
3105                </g>
3106            </a>
3107            <a id="license-osm-link" xlink:href="http://www.openstreetmap.org/">
3108                <g transform="translate(-210,10)" id="license-osm-text">
3109                    <text class="license-text" dx="0" dy="0">Copyright © <xsl:value-of select="$year"/> OpenStreetMap (openstreetmap.org)</text>
3110                </g>
3111            </a>
3112            <a id="license-cc-text-link" xlink:href="http://creativecommons.org/licenses/by-sa/2.0/">
3113                <g transform="translate(-150,18)" id="license-cc-text">
3114                    <text class="license-text" dx="0" dy="0">This work is licensed under the Creative</text>
3115                    <text class="license-text" dx="0" dy="8">Commons Attribution-ShareAlike 2.0 License.</text>
3116                    <text class="license-text" dx="0" dy="16">http://creativecommons.org/licenses/by-sa/2.0/</text>
3117                </g>
3118            </a>
3119        </g>
3120    </xsl:template>
3121
3122
3123        <!-- Draw zoom controls -->
3124    <xsl:template name="zoomControl">
3125        <defs>
3126
3127            <style type="text/css">
3128              .fancyButton {
3129                stroke: #8080ff;
3130                stroke-width: 2px;
3131                fill: #fefefe;
3132                }
3133              .fancyButton:hover {
3134                stroke: red;
3135                }
3136            </style>
3137
3138            <filter id="fancyButton" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="350">
3139                <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>
3140                <feOffset in="blur" dx="2" dy="2" result="offsetBlur"/>
3141                <feSpecularLighting in="blur" surfaceScale="5" specularConstant=".75" specularExponent="20" lighting-color="white" result="specOut">
3142                    <fePointLight x="-5000" y="-10000" z="7000"/>
3143                </feSpecularLighting>
3144                <feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut"/>
3145                <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="litPaint"/>
3146                <feMerge>
3147                    <feMergeNode in="offsetBlur"/>
3148                    <feMergeNode in="litPaint"/>
3149                </feMerge>
3150            </filter>
3151            <symbol id="panDown" viewBox="0 0 19 19" class="fancyButton">
3152                <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"/>
3153                <path d="M 9.5,5 L 9.5,14"/>
3154            </symbol>
3155            <symbol id="panUp" viewBox="0 0 19 19" class="fancyButton">
3156                <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"/>
3157                <path d="M 9.5,5 L 9.5,14"/>
3158            </symbol>
3159            <symbol id="panLeft" viewBox="0 0 19 19" class="fancyButton">
3160                <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"/>
3161                <path d="M 5,9.5 L 14,9.5"/>
3162            </symbol>
3163            <symbol id="panRight" viewBox="0 0 19 19" class="fancyButton">
3164                <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"/>
3165                <path d="M 5,9.5 L 14,9.5"/>
3166            </symbol>
3167            <symbol id="zoomIn" viewBox="0 0 19 19" class="fancyButton">
3168                <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"/>
3169                <path d="M 5,9.5 L 14,9.5 M 9.5,5 L 9.5,14"/>
3170            </symbol>
3171            <symbol id="zoomOut" viewBox="0 0 19 19" class="fancyButton">
3172                <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"/>
3173                <path d="M 5,9.5 L 14,9.5"/>
3174            </symbol>
3175
3176        </defs>
3177
3178        <g id="gPanDown" filter="url(#fancyButton)" onclick="fnPan('down')">
3179            <use x="18px" y="60px" xlink:href="#panDown" width="14px" height="14px"/>
3180        </g>
3181        <g id="gPanRight" filter="url(#fancyButton)" onclick="fnPan('right')">
3182            <use x="8px" y="70px" xlink:href="#panRight" width="14px" height="14px"/>
3183        </g>
3184        <g id="gPanLeft" filter="url(#fancyButton)" onclick="fnPan('left')">
3185            <use x="28px" y="70px" xlink:href="#panLeft" width="14px" height="14px"/>
3186        </g>
3187        <g id="gPanUp" filter="url(#fancyButton)" onclick="fnPan('up')">
3188            <use x="18px" y="80px" xlink:href="#panUp" width="14px" height="14px"/>
3189        </g>
3190
3191        <xsl:variable name="x1" select="25"/>
3192        <xsl:variable name="y1" select="105"/>
3193        <xsl:variable name="x2" select="25"/>
3194        <xsl:variable name="y2" select="300"/>
3195
3196        <line style="stroke-width: 10; stroke-linecap: butt; stroke: #8080ff;">
3197            <xsl:attribute name="x1"><xsl:value-of select="$x1"/></xsl:attribute>
3198            <xsl:attribute name="y1"><xsl:value-of select="$y1"/></xsl:attribute>
3199            <xsl:attribute name="x2"><xsl:value-of select="$x2"/></xsl:attribute>
3200            <xsl:attribute name="y2"><xsl:value-of select="$y2"/></xsl:attribute>
3201        </line>
3202
3203        <line style="stroke-width: 8; stroke-linecap: butt; stroke: white; stroke-dasharray: 10,1;">
3204            <xsl:attribute name="x1"><xsl:value-of select="$x1"/></xsl:attribute>
3205            <xsl:attribute name="y1"><xsl:value-of select="$y1"/></xsl:attribute>
3206            <xsl:attribute name="x2"><xsl:value-of select="$x2"/></xsl:attribute>
3207            <xsl:attribute name="y2"><xsl:value-of select="$y2"/></xsl:attribute>
3208        </line>
3209
3210        <!-- Need to use onmousedown because onclick is interfered with by the onmousedown handler for panning -->
3211        <g id="gZoomIn" filter="url(#fancyButton)" onmousedown="fnZoom('in')">
3212            <use x="15.5px" y="100px" xlink:href="#zoomIn" width="19px" height="19px"/>
3213        </g>
3214
3215        <!-- Need to use onmousedown because onclick is interfered with by the onmousedown handler for panning -->
3216        <g id="gZoomOut" filter="url(#fancyButton)" onmousedown="fnZoom('out')">
3217            <use x="15.5px" y="288px" xlink:href="#zoomOut" width="19px" height="19px"/>
3218        </g>
3219    </xsl:template>
3220   
3221    <xsl:template name="javaScript">
3222        <script>
3223            /*
3224
3225Osmarender
3226
3227interactive.js
3228
3229*/
3230
3231function fnResize() {
3232    fnResizeElement("gAttribution")
3233    fnResizeElement("gLicense")
3234    fnResizeElement("gZoomIn")
3235    fnResizeElement("gZoomOut")
3236}
3237
3238
3239function fnResizeElement(e) {
3240    //
3241    var oSVG,scale,currentTranslateX,currentTranslateY,oe
3242    //
3243    oSVG=document.rootElement
3244    scale=1/oSVG.currentScale
3245    currentTranslateX=oSVG.currentTranslate.x
3246    currentTranslateY=oSVG.currentTranslate.y
3247    oe=document.getElementById(e)
3248    if (oe) oe.setAttributeNS(null,"transform","scale("+scale+","+scale+") translate("+(-currentTranslateX)+","+(-currentTranslateY)+")")
3249}
3250
3251
3252function fnToggleImage(osmImage) {
3253    var xlink = 'http://www.w3.org/1999/xlink';
3254    ogThumbnail=document.getElementById('gThumbnail')
3255    if (ogThumbnail.getAttributeNS(null,"visibility")=="visible") fnHideImage()
3256    else {
3257        ogThumbnail.setAttributeNS(null,"visibility","visible")
3258        oThumbnail=document.getElementById('thumbnail')
3259        oThumbnail.setAttributeNS(xlink,"href",osmImage)
3260    }
3261}
3262
3263function fnHideImage() {
3264    ogThumbnail=document.getElementById('gThumbnail')
3265    ogThumbnail.setAttributeNS(null,"visibility","hidden")
3266}
3267
3268
3269/* The following code originally written by Jonathan Watt (http://jwatt.org/), Aug. 2005 */
3270
3271if (!window)
3272window = this;
3273
3274
3275function fnOnLoad(evt) {
3276    if (!document) window.document = evt.target.ownerDocument
3277}
3278
3279
3280/**
3281  * Event handlers to change the current user space for the zoom and pan
3282  * controls to make them appear to be scale invariant.
3283  */
3284
3285function fnOnZoom(evt) {
3286    try {
3287        if (evt.newScale === undefined) throw 'bad interface'
3288        // update the transform list that adjusts for zoom and pan
3289        var tlist = document.getElementById('staticElements').transform.baseVal
3290        tlist.getItem(0).setScale(1/evt.newScale, 1/evt.newScale)
3291        tlist.getItem(1).setTranslate(-evt.newTranslate.x, -evt.newTranslate.y)
3292        }
3293    catch (e) {
3294        // work around difficiencies in non-moz implementations (some don't
3295        // implement the SVGZoomEvent or SVGAnimatedTransform interfaces)
3296        var de = document.documentElement
3297        var tform = 'scale(' + 1/de.currentScale + ') ' + 'translate(' + (-de.currentTranslate.x) + ', ' + (-de.currentTranslate.y) + ')'
3298        document.getElementById('staticElements').setAttributeNS(null, 'transform', tform)
3299        }
3300    }
3301
3302
3303function fnOnScroll(evt) {
3304    var ct = document.documentElement.currentTranslate
3305    try {
3306        // update the transform list that adjusts for zoom and pan
3307        var tlist = document.getElementById('staticElements').transform.baseVal
3308        tlist.getItem(1).setTranslate(-ct.x, -ct.y)
3309        }
3310    catch (e) {
3311        // work around difficiencies in non-moz implementations (some don't
3312        // implement the SVGAnimatedTransform interface)
3313        var tform = 'scale(' + 1/document.documentElement.currentScale + ') ' + 'translate(' + (-ct.x) + ', ' + (-ct.y) + ')';
3314        document.getElementById('staticElements').setAttributeNS(null, 'transform', tform)
3315        }
3316    }
3317
3318
3319function fnZoom(type) {
3320    var de = document.documentElement;
3321    var oldScale = de.currentScale;
3322    var oldTranslate = { x: de.currentTranslate.x, y: de.currentTranslate.y };
3323    var s = 2;
3324    if (type == 'in') {de.currentScale *= 1.5;}
3325    if (type == 'out') {de.currentScale /= 1.4;}
3326    // correct currentTranslate so zooming is to the center of the viewport:
3327
3328    var vp_width, vp_height;
3329    try {
3330        vp_width = de.viewport.width;
3331        vp_height = de.viewport.height;
3332    }
3333    catch (e) {
3334        // work around difficiency in moz ('viewport' property not implemented)
3335        vp_width = window.innerWidth;
3336        vp_height = window.innerHeight;
3337    }
3338    de.currentTranslate.x = vp_width/2 - ((de.currentScale/oldScale) * (vp_width/2 - oldTranslate.x));
3339    de.currentTranslate.y = vp_height/2 - ((de.currentScale/oldScale) * (vp_height/2 - oldTranslate.y));
3340
3341}
3342
3343
3344function fnPan(type) {
3345    var de = document.documentElement;
3346    var ct = de.currentTranslate;
3347    var t = 150;
3348    if (type == 'right') ct.x += t;
3349    if (type == 'down') ct.y += t;
3350    if (type == 'left') ct.x -= t;
3351    if (type == 'up') ct.y -= t;
3352}
3353
3354
3355var gCurrentX,gCurrentY
3356var gDeltaX,gDeltaY
3357var gMouseDown=false
3358var gCurrentTranslate=document.documentElement.currentTranslate
3359
3360function fnOnMouseDown(evt) {
3361    gCurrentX=gCurrentTranslate.x
3362    gCurrentY=gCurrentTranslate.y
3363    gDeltaX=evt.clientX
3364    gDeltaY=evt.clientY
3365    gMouseDown=true
3366    evt.target.ownerDocument.rootElement.setAttributeNS(null,"cursor","move")
3367}
3368
3369
3370function fnOnMouseUp(evt) {
3371    gMouseDown=false
3372    evt.target.ownerDocument.rootElement.setAttribute("cursor","default")
3373}
3374
3375
3376function fnOnMouseMove(evt) {
3377    var id
3378    if (gMouseDown) {
3379        gCurrentTranslate.x=gCurrentX+evt.clientX-gDeltaX
3380        gCurrentTranslate.y=gCurrentY+evt.clientY-gDeltaY
3381    }
3382}
3383
3384
3385        </script>
3386    </xsl:template>
3387
3388</xsl:stylesheet>
Note: See TracBrowser for help on using the repository browser.