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

Last change on this file since 8789 was 8789, checked in by bobkare, 11 years ago

Applying patch from nomis, fixes #604

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