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

Last change on this file since 10959 was 10959, checked in by jttt, 6 years ago

Remove unused layer parameters

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