source: osm/applications/editors/josm/oldplugins/osmarender/xslt/osmarender.xsl@ 36369

Last change on this file since 36369 was 35743, checked in by stoecker, 4 years ago

readd files directly

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