source: subversion/applications/utils/gary68/mwMap.pm @ 26199

Last change on this file since 26199 was 26199, checked in by gary68, 8 years ago

mw version 0.08

File size: 21.5 KB
Line 
1#
2# PERL mapweaver module by gary68
3#
4#
5#
6#
7# Copyright (C) 2011, Gerhard Schwanz
8#
9# This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the
10# Free Software Foundation; either version 3 of the License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>
16#
17
18
19package mwMap ; 
20
21use strict ;
22use warnings ;
23
24use mwConfig ;
25# use mwFile ;
26# use mwLabel ;
27
28use OSM::osm ;
29
30use Geo::Proj4 ;
31
32
33use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
34
35require Exporter ;
36
37@ISA = qw ( Exporter AutoLoader ) ;
38
39@EXPORT = qw (  initGraph
40                        drawCircle
41                        drawSquare
42                        drawTriangle
43                        drawDiamond
44                        drawRect
45                        writeMap
46                        drawWay
47                        drawArea
48                        fitsPaper
49                        getScale
50                        createPath
51                        pathText
52                        placeIcon
53                        convert
54                        gridSquare
55                        getDimensions
56                 ) ;
57
58
59my @belowWays = ("background", "base", "area", "multi") ;
60
61my @aboveWays = ( "wayLabels", "shields", "routes", "routeStops", "nodes", "icons", "text", "additional") ;
62
63my @elements = ("scale", "ruler", "legend", "header", "footer", "title") ;
64
65my %svgLayer = () ;
66my %wayLayer = () ;
67
68my $proj ;
69
70my ($bottom, $left, $right, $top) ;
71my ($sizeX, $sizeY) ;
72my ($projLeft, $projBottom, $projRight, $projTop) ;
73my ($projSizeX, $projSizeY) ;
74
75my %areaDef ; # TODO replace by function call
76
77sub initGraph {
78
79        # function initializes the picture and projection
80
81        my ($x, $l, $b, $r, $t) = @_ ; 
82
83        # my $l0 = int($l) - 1 ;
84        my $l0 = int(($r+$l) / 2 ) ;
85
86        $proj = Geo::Proj4->new(
87                proj => cv('projection'), 
88                ellps => cv('ellipsoid'), 
89                lon_0 => $l0 
90                ) or die "parameter error: ".Geo::Proj4->error. "\n"; 
91
92
93        ($projLeft, $projBottom) = $proj->forward($b, $l) ; # lat/lon!!!
94        ($projRight, $projTop) = $proj->forward($t, $r) ; # lat/lon!!!
95
96        $projSizeX = $projRight - $projLeft ;
97        $projSizeY = $projTop - $projBottom ;
98
99        my $factor = $projSizeY / $projSizeX ;
100
101        $sizeX = int ($x) ;
102        $sizeY = int ($x * $factor) ;
103
104        mwLabel::initQuadTrees ($sizeX, $sizeY) ;
105
106        $top = $t ;
107        $left = $l ;
108        $right = $r ;
109        $bottom = $b ;
110
111        if ( cv('ruler') ne "0" ) {
112                drawRuler() ;
113        }
114
115        if ( cv('scale') ne "0" ) {
116                drawScale() ;
117        }
118
119        if ( cv('grid') != 0) {
120                drawGrid() ;
121        }
122        if ( cv('coords') eq "1") {
123                drawCoords() ;
124        }
125        if ( length cv('foot') > 0 ) {
126                drawFoot() ;
127        }
128        if ( length cv('head') > 0 ) {
129                drawHead() ;
130        }
131
132}
133
134sub addToLayer {
135        my ($layer, $text) = @_ ;
136        push @{$svgLayer{$layer}}, $text ;
137}
138
139sub drawWay {
140
141        # accepts list of nodes (plus convert=1)  or list of x,y,x,y (convert=0) and draws way/polygon to layerNr if defined or to layerName
142
143        my ($nodesRef, $convert, $svgString, $layerName, $layerNumber) = @_ ;
144        my @points = () ;
145
146        # convert? and expand.
147        if ($convert) {
148                my ($lonRef, $latRef, $tagRef) = mwFile::getNodePointers() ;
149                foreach my $node (@$nodesRef) {
150                        my ($x, $y) = convert ( $$lonRef{$node}, $$latRef{$node}) ;
151                        push @points, $x, $y ;
152                }
153        }
154        else {
155                @points = @$nodesRef ;
156        }
157
158        my $refp = simplifyPoints (\@points) ;
159        @points = @$refp ;
160
161
162        my $svg = "<polyline points=\"" ;
163        for (my$i=0; $i<scalar(@points)-1; $i+=2) {
164                $svg = $svg . $points[$i] . "," . $points[$i+1] . " " ;
165        }
166
167        $svg = $svg . "\" $svgString />" ;
168
169        if (defined $layerNumber) {
170                push @{ $wayLayer{ $layerNumber } }, $svg ;
171        }
172        else {
173                push @{ $svgLayer { $layerName } }, $svg ;
174        }
175}
176
177
178
179sub drawText {
180
181        my ($x, $y, $convert, $text, $svgString, $layerName) = @_ ;
182
183        if ($convert) {
184                ($x, $y) = convert ($x, $y) ;
185        }
186
187        my $svg = "<text x=\"$x\" y=\"$y\" $svgString>" . $text . "</text>" ;
188
189        push @{ $svgLayer { $layerName } }, $svg ;
190
191}
192
193
194
195
196sub drawCircle {
197
198        # draws circle element to svgLayer given; if convertCoords then lon / lat is converted to x / y
199        # circleradius either in pixel or in meters (convert=1)
200
201        my ($x, $y, $convertCoords, $radius, $convertRadius, $format, $layerName) = @_ ;
202
203        if ($convertCoords) {
204                ($x, $y) = convert ($x, $y) ;
205        }
206        if ($convertRadius) {
207                $radius = $radius / (1000 * distance ($left, $bottom, $right, $bottom) ) * $sizeX ;
208        }
209        my $svg = "<circle cx=\"$x\" cy=\"$y\" r=\"$radius\" " ;
210        $svg .= $format . " />" ;
211
212        push @{ $svgLayer { $layerName } }, $svg ;
213}
214
215sub drawSquare {
216
217        # draws square element to svgLayer given; if convertCoords then lon / lat is converted to x / y
218        # square size either in pixel or in meters (convert=1)
219
220        my ($x, $y, $convertCoords, $size, $convertSize, $format, $layerName) = @_ ;
221
222        if ($convertCoords) {
223                ($x, $y) = convert ($x, $y) ;
224        }
225        if ($convertSize) {
226                $size = $size / (1000 * distance ($left, $bottom, $right, $bottom) ) * $sizeX ;
227        }
228
229        my $x1 = $x - $size ;
230        my $y1 = $y - $size ;
231        my $dSize = 2 * $size ;
232
233        my $svg = "<rect x=\"$x1\" y=\"$y1\" width=\"$dSize\" height=\"$dSize\" " ;
234        $svg .= $format . " />" ;
235
236        push @{ $svgLayer { $layerName } }, $svg ;
237}
238
239sub drawTriangle {
240
241        # draws triangle element to svgLayer given; if convertCoords then lon / lat is converted to x / y
242        # square size either in pixel or in meters (convert=1)
243
244        my ($x, $y, $convertCoords, $size, $convertSize, $format, $layerName) = @_ ;
245
246        if ($convertCoords) {
247                ($x, $y) = convert ($x, $y) ;
248        }
249        if ($convertSize) {
250                $size = $size / (1000 * distance ($left, $bottom, $right, $bottom) ) * $sizeX ;
251        }
252
253        my $h = int ( sqrt ($size * $size / 2) ) ;
254
255        my $x1 = $x ;
256        my $y1 = $y - $size ;
257        my $x2 = $x - $h ;
258        my $y2 = $y + $h ;
259        my $x3 = $x + $h ;
260        my $y3 = $y + $h ;
261
262        my $svg = "<polyline points=\"$x1,$y1 $x2,$y2 $x3,$y3 $x1,$y1\" " ;
263        $svg .= $format . " />" ;
264
265        push @{ $svgLayer { $layerName } }, $svg ;
266}
267
268sub drawDiamond {
269
270        # draws diamond element to svgLayer given; if convertCoords then lon / lat is converted to x / y
271        # square size either in pixel or in meters (convert=1)
272
273        my ($x, $y, $convertCoords, $size, $convertSize, $format, $layerName) = @_ ;
274
275        if ($convertCoords) {
276                ($x, $y) = convert ($x, $y) ;
277        }
278        if ($convertSize) {
279                $size = $size / (1000 * distance ($left, $bottom, $right, $bottom) ) * $sizeX ;
280        }
281
282        my $x1 = $x - $size ; # left
283        my $y1 = $y ;
284        my $x2 = $x ; # top
285        my $y2 = $y - $size ;
286        my $x3 = $x + $size ; #right
287        my $y3 = $y ;
288        my $x4 = $x ; # bottom
289        my $y4 = $y + $size ;
290
291        my $svg = "<polyline points=\"$x1,$y1 $x2,$y2 $x3,$y3 $x4,$y4 $x1,$y1\" " ;
292        $svg .= $format . " />" ;
293
294        push @{ $svgLayer { $layerName } }, $svg ;
295}
296
297sub drawRect {
298
299        # draws square element to svgLayer given; if convertCoords then lon / lat is converted to x / y
300        # square size either in pixel or in meters (convert=1)
301
302        my ($x1, $y1, $x2, $y2, $convertCoords, $format, $layerName) = @_ ;
303
304        if ($convertCoords) {
305                ($x1, $y1) = convert ($x1, $y1) ;
306                ($x2, $y2) = convert ($x2, $y2) ;
307        }
308
309        my $sizeX = $x2 - $x1 ;
310        my $sizeY = $y2 - $y1 ;
311
312        my $svg = "<rect x=\"$x1\" y=\"$y1\" width=\"$sizeX\" height=\"$sizeY\" " ;
313        $svg .= $format . " />" ;
314
315        push @{ $svgLayer { $layerName } }, $svg ;
316}
317
318
319sub createPath {
320#
321# creates path element for later use with textPath
322#
323        my ($pathName, $refp, $layer) = @_ ;
324
325        my $refp2 = simplifyPoints ($refp) ;
326        my @points = @$refp2 ;
327
328        my $svg = "<path id=\"" . $pathName . "\" d=\"M " ;
329        my $i ;
330        my $first = 1 ;
331        for ($i=0; $i<scalar(@points); $i+=2) {
332                if ($first) {
333                        $svg = $svg . $points[$i] . "," . $points[$i+1] . " " ;
334                        $first = 0 ;
335                }
336                else {
337                        $svg = $svg . "L " . $points[$i] . "," . $points[$i+1] . " " ;
338                }
339        }
340        $svg = $svg . "\" />\n" ;
341
342        push @{ $svgLayer{ $layer } }, $svg ;
343}
344
345
346sub pathText {
347#
348# draws text to path element; alignment: start, middle, end
349#
350        my ($svgText, $text, $pathName, $tSpan, $alignment, $offset, $layer) = @_ ;
351
352        my $svg = "<text $svgText >\n" ;
353        $svg = $svg . "<textPath xlink:href=\"#" . $pathName . "\" text-anchor=\"" . $alignment . "\" startOffset=\"" . $offset . "%\" >\n" ;
354        $svg = $svg . "<tspan dy=\"" . $tSpan . "\" >" . $text . " </tspan>\n" ;
355        $svg = $svg . "</textPath>\n</text>\n" ;
356
357        push @{ $svgLayer{ $layer } }, $svg ;
358}
359
360
361sub placeIcon {
362#
363# create SVG text for icons
364#
365        my ($x, $y, $icon, $sizeX, $sizeY, $layer) = @_ ;
366        my ($out) = "<image x=\"" . $x . "\"" ;
367        $out .= " y=\"" . $y . "\"" ;
368        if ($sizeX > 0) { $out .= " width=\"" . $sizeX . "\"" ; }
369        if ($sizeY > 0) { $out .= " height=\"" . $sizeY . "\"" ; }
370        $out .= " xlink:href=\"" . $icon . "\" />" ;
371
372        push @{ $svgLayer{ $layer } }, $out ;
373}
374
375
376sub drawArea {
377#
378# draws mp in svg ARRAY of ARRAY of nodes/coordinates
379#
380        my ($svgText, $icon, $ref, $convert, $layer) = @_ ;
381        my @ways = @$ref ;
382        my $i ;
383        my $svg ;
384
385        if ($convert) {
386                my ($lonRef, $latRef, $tagRef) = mwFile::getNodePointers () ;
387                foreach my $aRef (@ways) {
388                        my @way = @$aRef ;
389                        my @newCoords = () ;
390                        foreach my $n (@way) {
391                                my ($x, $y) = convert ($$lonRef{$n}, $$latRef{$n}) ;
392                                push @newCoords, $x, $y ;
393                        }
394                        @$aRef = @newCoords ;
395                }
396        }
397
398        if (defined $areaDef{$icon}) {
399                $svg = "<path $svgText fill-rule=\"evenodd\" style=\"fill:url(" . $areaDef{$icon} . ")\" d=\"" ;
400        }
401        else {
402                $svg = "<path $svgText fill-rule=\"evenodd\" d=\"" ;
403        }
404       
405        foreach my $way (@ways) {
406                my @actual = @$way ;
407                for ($i=0; $i<scalar(@actual); $i+=2) {
408                        if ($i == 0) { $svg .= " M " ; } else { $svg .= " L " ; }
409                        $svg = $svg . $actual[$i] . " " . $actual[$i+1] ;
410                }
411                $svg .= " z" ;
412        }
413
414        $svg = $svg . "\" />" ;
415
416        push @{ $svgLayer{ $layer } }, $svg ;
417}
418
419
420
421# ---------------------------------------------------------------------
422
423sub writeMap {
424
425        my $fileName = cv ('out')  ;
426
427        open (my $file, ">", $fileName) || die "can't open svg output file $fileName\n";
428
429        print $file "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n" ;
430        print $file "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\" >\n" ;
431
432        my $w = $sizeX / 300 * 2.54 ; # cm
433        my $h = $sizeY / 300 * 2.54 ;
434
435        my ($svg) = "<svg version=\"1.1\" baseProfile=\"full\" xmlns=\"http://www.w3.org/2000/svg\" " ;
436        $svg .= "xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:ev=\"http://www.w3.org/2001/xml-events\" " ;
437        $svg .= "width=\"$w" . "cm\" height=\"$h" . "cm\" viewBox=\"0 0 $sizeX $sizeY\">\n" ;
438        print $file $svg ;
439
440        # definitions
441        if ( defined @{$svgLayer{'definitions'}} ) {
442                print $file "<defs>\n" ;
443                foreach ( @{$svgLayer{'definitions'}} ) { print $file $_, "\n" ; }
444                print $file "</defs>\n" ;
445        }
446
447        # below ways
448        foreach my $layer (@belowWays) {
449                if ( defined @{$svgLayer{$layer}} ) {
450                        print $file "<g id=\"$layer\">\n" ;
451                        foreach ( @{$svgLayer{$layer}} ) { print $file $_, "\n" ; }
452                        print $file "</g>\n" ;
453                }
454        }
455
456        # ways
457        foreach my $layer (sort {$a <=> $b} keys %wayLayer) {
458                if ( defined @{$wayLayer{$layer}} ) {
459                        print $file "<g id=\"way$layer\">\n" ;
460                        foreach ( @{$wayLayer{$layer}} ) { print $file $_, "\n" ; }
461                        print $file "</g>\n" ;
462                }
463        }
464
465
466        # above of ways
467        foreach my $layer (@aboveWays) {
468                if ( defined @{$svgLayer{$layer}} ) {
469                        print $file "<g id=\"$layer\">\n" ;
470                        foreach ( @{$svgLayer{$layer}} ) { print $file $_, "\n" ; }
471                        print $file "</g>\n" ;
472                }
473        }
474
475
476        # TODO use groups
477
478        foreach my $layer (@elements) {
479                if (defined @{$svgLayer{$layer}}) {
480                        print $file "<g id=\"$layer\">\n" ;
481                        foreach ( @{$svgLayer{$layer}} ) { print $file $_, "\n" ; }
482                        print $file "</g>\n" ;
483                }
484        }
485
486
487        print $file "</svg>\n" ;
488
489        close ($file) ;
490
491        if (cv('pdf') eq "1") {
492                my ($pdfName) = $fileName ;
493                $pdfName =~ s/\.svg/\.pdf/ ;
494                print "creating pdf file $pdfName ...\n" ;
495                `inkscape -A $pdfName $fileName` ;
496        }
497
498        if (cv('png') eq "1") {
499                my ($pngName) = $fileName ;
500                $pngName =~ s/\.svg/\.png/ ;
501                print "creating png file $pngName ...\n" ;
502                `inkscape --export-dpi=300 -e $pngName $fileName` ;
503        }
504
505
506
507}
508
509# -----------------------------------------------------------------------------------
510
511sub drawGrid {
512#
513# draw grid on top of map. receives number of parts in x/lon direction
514#
515
516        my $number = cv ('grid') ;
517        my $color = cv ('gridcolor') ;
518
519        my $part = $sizeX / $number ;
520        my $numY = $sizeY / $part ;
521
522        my $svgStringLine="stroke=\"$color\" stroke-width=\"5\" stroke-dasharray=\"30,30\"" ;
523
524        my $svgStringText="font-family=\"sans-serif\" font-size=\"60\" fill=\"$color\"" ;
525
526        # vertical lines
527        for (my $i = 1; $i <= $number; $i++) {
528                my @coords = ($i*$part, 0, $i*$part, $sizeY) ;
529                drawWay (\@coords, 0, $svgStringLine, "additional", undef) ;
530                drawText ( ($i-1)*$part+$part/2, 160, 0, chr($i+64), $svgStringText, "additional") ;
531
532        }
533
534        # hor. lines
535        for (my $i = 1; $i <= $numY; $i++) {
536                my @coords = (0, $i*$part, $sizeX, $i*$part) ;
537                drawWay (\@coords, 0, $svgStringLine, "additional", undef) ;
538                drawText ( 20, ($i-1)*$part+$part/2, 0, $i, $svgStringText, "additional") ;
539
540        }
541}
542
543sub drawCoords {
544#
545# draws coordinates grid on map
546#
547        my $exp = cv('coordsexp') ; 
548        my $color = cv ('coordscolor');
549        my $step = 10 ** $exp ;
550
551        # vert. lines
552        my $start = int ($left / $step) + 1 ;
553        my $actual = $start * $step ;
554
555        my $svgStringLine="stroke=\"$color\" stroke-width=\"3\"" ;
556        my $svgStringText="font-family=\"sans-serif\" font-size=\"30\" fill=\"$color\"" ;
557
558        while ($actual < $right) {
559                my ($x1, $y1) = convert ($actual, 0) ;
560
561                drawText ( $x1+10, $sizeY-50, 0, $actual, $svgStringText, "additional") ;
562
563                my @coords = ($x1, 0, $x1, $sizeY) ;
564                drawWay (\@coords, 0, $svgStringLine, "additional", undef) ;
565
566                $actual += $step ;
567        }
568
569        # hor lines
570        $start = int ($bottom / $step) + 1 ;
571        $actual = $start * $step ;
572        while ($actual < $top) {
573                # print "actualY: $actual\n" ;
574                my ($x1, $y1) = convert (0, $actual) ;
575
576                drawText ( $sizeX-180, $y1+30, 0, $actual, $svgStringText, "additional") ;
577
578                my @coords = (0, $y1, $sizeX, $y1) ;
579                drawWay (\@coords, 0, $svgStringLine, "additional", undef) ;
580
581                $actual += $step ;
582        }
583}
584
585
586
587
588# -----------------------------------------------------------------------------------
589
590sub convert {
591
592        # converts real world coordinates to system graph pixel coordinates
593
594        my ($x, $y) = @_ ;
595
596        my ($x1, $y1) = $proj->forward($y, $x) ; # lat/lon!!!
597
598        my $x2 = int ( ($x1 - $projLeft) / ($projRight - $projLeft) * $sizeX ) ;
599        my $y2 = $sizeY - int ( ($y1 - $projBottom) / ($projTop - $projBottom) * $sizeY ) ;
600
601        return ($x2, $y2) ;
602}
603
604sub simplifyPoints {
605        my $ref = shift ;
606        my @points = @$ref ;
607        my @newPoints ;
608        my $maxIndex = $#points ;
609
610        if (scalar @points > 4) {
611                # push first
612                push @newPoints, $points[0], $points[1] ;
613
614                # push other
615                for (my $i=2; $i <= $maxIndex; $i+=2) {
616                        # $simplifyTotal++ ;
617                        if ( ($points[$i]==$points[$i-2]) and ($points[$i+1]==$points[$i-1]) ) {
618                                # same
619                                # $simplified++ ;
620                        }
621                        else {
622                                push @newPoints, $points[$i], $points[$i+1] ;
623                        }
624                }
625                return (\@newPoints) ;
626        }
627        else {
628                return ($ref) ;
629        }
630
631}
632
633sub drawRuler {
634#
635# draws ruler
636#
637        my $col = cv('rulercolor') ;   
638
639        my $B ; my $B2 ;
640        my $L ; my $Lpix ;
641        my $x ;
642        my $text ;
643
644        my $lineThickness = 8 ; # at 300dpi
645        my $textSize = 40 ; # at 300 dpi
646        my $textDist = 60 ; # at 300 dpi
647        my $lineLen = 40 ; # at 300 dpi
648
649        my $xOffset = 2 * $lineThickness ;
650        my $yOffset = 2 * $lineThickness ;
651               
652        $B = $right - $left ;                           # in degrees
653        $B2 = $B * cos ($top/360*3.14*2) * 111.1 ;      # in km
654        $text = "50m" ; $x = 0.05 ;                     # default length ruler
655
656        if ($B2 > 0.5) {$text = "100 m" ; $x = 0.1 ; }  # enlarge ruler
657        if ($B2 > 1) {$text = "500 m" ; $x = 0.5 ; }    # enlarge ruler
658        if ($B2 > 5) {$text = "1 km" ; $x = 1 ; }
659        if ($B2 > 10) {$text = "5 km" ; $x = 5 ; }
660        if ($B2 > 50) {$text = "10 km" ; $x = 10 ; }
661        $L = $x / (cos ($top/360*3.14*2) * 111.1 ) ;    # length ruler in km
662        $Lpix = $L / $B * $sizeX ;                      # length ruler in pixels
663
664        my $rSizeX = int ($Lpix + 2 * $xOffset) ;
665        my $rSizeY = int ($lineLen + $textSize + 3 * $yOffset) ;
666        addToLayer ("definitions", "<g id=\"rulerdef\" width=\"$rSizeX\" height=\"$rSizeY\" >") ;
667
668        if ( cv('rulerbackground') ne "none" ) {
669                my $color = cv ('rulerbackground') ;
670                my $svgString = "fill=\"$color\"" ;
671                drawRect (0, 0, $rSizeX, $rSizeY, 0, $svgString, "definitions") ;
672        }
673
674        my $svgString = "stroke=\"$col\" stroke-width=\"$lineThickness\" stroke-linecap=\"round\" " ;
675
676        my @coords = ($xOffset, $yOffset, $xOffset+$Lpix, $yOffset) ;
677        drawWay (\@coords, 0, $svgString, "definitions", undef) ;
678
679        @coords = ($xOffset, $yOffset, $xOffset, $yOffset+$lineLen) ;
680        drawWay (\@coords, 0, $svgString, "definitions", undef) ;
681
682        @coords = ($xOffset+$Lpix, $yOffset, $xOffset+$Lpix, $yOffset+$lineLen) ;
683        drawWay (\@coords, 0, $svgString, "definitions", undef) ;
684
685        @coords = ($xOffset+$Lpix/2, $yOffset, $xOffset+$Lpix/2, $yOffset+$lineLen/2) ;
686        drawWay (\@coords, 0, $svgString, "definitions", undef) ;
687
688        $svgString = "fill=\"$col\" stroke=\"$col\" font-size=\"45\" " ;
689        my $scale= getScale() ;
690        $text .= "(1:$scale)" ;
691        drawText ($xOffset, $yOffset+$textDist+30, 0, $text, $svgString, "definitions") ;
692
693        addToLayer ("definitions", "</g>") ;
694
695        my $posX = 40 ; my $posY = 40 ;
696
697        if ( cv('ruler') eq "2") {
698                $posX = $sizeX - 40 - $rSizeX ;
699                $posY = 40 ;
700        }
701
702        if ( cv('ruler') eq "3") {
703                $posX = 40 ;
704                $posY = $sizeY - 40 - $rSizeY ;
705        }
706
707        if ( cv('ruler') eq "4") {
708                $posX = $sizeX - 40 - $rSizeX ;
709                $posY = $sizeY - 40 - $rSizeY ;
710        }
711
712        addToLayer ("ruler", "<use x=\"$posX\" y=\"$posY\" xlink:href=\"#rulerdef\" />") ;
713}
714
715sub drawScale {
716#
717# draws scale value
718#
719        my $col = cv('scalecolor') ;   
720
721        my $xOffset = 20 ;
722        my $yOffset = 20 ;
723        my $fontSize = 70 ;             
724        my $borderDist = 60 ;
725
726        my $rSizeX = int (350 + 2 * $xOffset) ;
727        my $rSizeY = int ($fontSize + 2 * $yOffset) ;
728        addToLayer ("definitions", "<g id=\"scaledef\" width=\"$rSizeX\" height=\"$rSizeY\" >") ;
729
730        if ( cv('scalebackground') ne "none" ) {
731                my $color = cv ('scalebackground') ;
732                my $svgString = "fill=\"$color\"" ;
733                drawRect (0, 0, $rSizeX, $rSizeY, 0, $svgString, "definitions") ;
734        }
735
736        my $scale= getScale() ;
737        my $svgString = "fill=\"$col\" stroke=\"$col\" font-size=\"$fontSize\" " ;
738        drawText ($xOffset, $fontSize + $yOffset, 0, "1:$scale", $svgString, "definitions") ;
739
740        addToLayer ("definitions", "</g>") ;
741
742        my $posX = $borderDist ; my $posY = $borderDist ;
743
744        if ( cv('scale') eq "2") {
745                $posX = $sizeX - $borderDist - $rSizeX ;
746                $posY = $borderDist ;
747        }
748
749        if ( cv('scale') eq "3") {
750                $posX = $borderDist ;
751                $posY = $sizeY - $borderDist - $rSizeY ;
752        }
753
754        if ( cv('scale') eq "4") {
755                $posX = $sizeX - $borderDist - $rSizeX ;
756                $posY = $sizeY - $borderDist - $rSizeY ;
757        }
758
759        addToLayer ("scale", "<use x=\"$posX\" y=\"$posY\" xlink:href=\"#scaledef\" />") ;
760}
761
762sub drawFoot {
763#
764# draws footer
765#
766        my $col = cv('footcolor') ;     
767        my $text = cv('foot') ; 
768        my $len = length $text ;
769
770        my $xOffset = 20 ;
771        my $yOffset = 20 ;
772        my $fontSize = cv('footsize') ;         
773        my $borderDistX = 60 ;
774        my $borderDistY = $fontSize + 50 ;
775
776        my $rSizeX = int ($len*cv('ppc')/10*$fontSize + 2 * $xOffset) ;
777        my $rSizeY = int ($fontSize + 2 * $yOffset) ;
778        addToLayer ("definitions", "<g id=\"footdef\" width=\"$rSizeX\" height=\"$rSizeY\" >") ;
779
780        if ( cv('footbackground') ne "none" ) {
781                my $color = cv ('footbackground') ;
782                my $svgString = "fill=\"$color\"" ;
783                drawRect (0, 0, $rSizeX, $rSizeY, 0, $svgString, "definitions") ;
784        }
785
786        my $svgString = "fill=\"$col\" stroke=\"$col\" font-size=\"$fontSize\" " ;
787        drawText ($xOffset, $fontSize + $yOffset, 0, $text, $svgString, "definitions") ;
788
789        addToLayer ("definitions", "</g>") ;
790
791        my $posX = $borderDistX ; my $posY = $sizeY - $borderDistY ;
792
793        addToLayer ("footer", "<use x=\"$posX\" y=\"$posY\" xlink:href=\"#footdef\" />") ;
794}
795
796sub drawHead {
797#
798# draws header
799#
800        my $col = cv('headcolor') ;     
801        my $text = cv('head') ; 
802        my $len = length $text ;
803
804        my $xOffset = 20 ;
805        my $yOffset = 20 ;
806        my $fontSize = cv('headsize') ;         
807        my $borderDistX = 60 ;
808        my $borderDistY = 60 ;
809
810        my $rSizeX = int ($len*cv('ppc')/10*$fontSize + 2 * $xOffset) ;
811        my $rSizeY = int ($fontSize + 2 * $yOffset) ;
812        addToLayer ("definitions", "<g id=\"headdef\" width=\"$rSizeX\" height=\"$rSizeY\" >") ;
813
814        if ( cv('headbackground') ne "none" ) {
815                my $color = cv ('headbackground') ;
816                my $svgString = "fill=\"$color\"" ;
817                drawRect (0, 0, $rSizeX, $rSizeY, 0, $svgString, "definitions") ;
818        }
819
820        my $svgString = "fill=\"$col\" stroke=\"$col\" font-size=\"$fontSize\" " ;
821        drawText ($xOffset, $fontSize + $yOffset, 0, $text, $svgString, "definitions") ;
822
823        addToLayer ("definitions", "</g>") ;
824
825        my $posX = $borderDistX ; my $posY = $borderDistY ;
826
827        addToLayer ("header", "<use x=\"$posX\" y=\"$posY\" xlink:href=\"#headdef\" />") ;
828}
829
830
831sub fitsPaper {
832#
833# calculates on what paper size the map will fit. sizes are taken from global variables
834#
835
836        my $width = $sizeX / 300 * 2.54 ;
837        my $height = $sizeY / 300 * 2.54 ;
838        my $paper = "" ;
839
840        my @sizes = () ;
841        push @sizes, ["4A0", 168.2, 237.8] ;
842        push @sizes, ["2A0", 118.9, 168.2] ;
843        push @sizes, ["A0", 84.1, 118.9] ;
844        push @sizes, ["A1", 59.4, 84.1] ;
845        push @sizes, ["A2", 42, 59.4] ;
846        push @sizes, ["A3", 29.7, 42] ;
847        push @sizes, ["A4", 21, 29.7] ;
848        push @sizes, ["A5", 14.8, 21] ;
849        push @sizes, ["A6", 10.5, 14.8] ;
850        push @sizes, ["A7", 7.4, 10.5] ;
851        push @sizes, ["none", 0, 0] ;
852
853        foreach my $size (@sizes) {
854                if ( ( ($width<=$size->[1]) and ($height<=$size->[2]) ) or ( ($width<=$size->[2]) and ($height<=$size->[1]) ) ) {
855                        $paper = $size->[0] ;
856                }
857        }
858
859        return ($paper, $width, $height) ;
860}
861
862sub getScale {
863#
864# calcs scale of map
865#
866        my ($dpi) = 300 ;
867
868        my $dist = distance ($left, $bottom, $right, $bottom) ;
869        my $inches = $sizeX / $dpi ;
870        my $cm = $inches * 2.54 ;
871        my $scale = int ( $dist / ($cm/100/1000)  ) ;
872        $scale = int ($scale / 100) * 100 ;
873
874        return ($scale) ;
875}
876
877sub gridSquare {
878#
879# returns grid square of given coordinates for directories
880#
881        my ($lon, $lat) = @_ ;
882
883        my $parts = cv('grid') ;
884
885        my ($x, $y) = convert ($lon, $lat) ;
886        my $xi = int ($x / ($sizeX / $parts)) + 1 ;
887        my $yi = int ($y / ($sizeX / $parts)) + 1 ;
888        if ( ($x >= 0) and ($x <= $sizeX) and ($y >= 0) and ($y <= $sizeY) ) {
889                return (chr($xi+64) . $yi) ;
890        }
891        else {
892                return undef ;
893        }
894}
895
896
897sub getDimensions {
898        return ($sizeX, $sizeY) ;
899}
900
9011 ;
902
903
Note: See TracBrowser for help on using the repository browser.