source: subversion/applications/utils/gary68/hikingbook.pl @ 26199

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

new hikingbook version

  • Property svn:executable set to *
File size: 62.2 KB
Line 
1
2
3
4
5# todo
6#
7# LATER
8# - negative ids for steps
9# - print parameters
10#
11
12# history
13# 0.91 autorotate corrected
14# 0.92 bigger overview and detail maps; added names to pois in description; less steps
15# 0.93 variable discs, taginfo -> pdf
16# 0.94 role selection; title and outName defaults
17# 0.95 sanitize
18# 0.96 contour data
19# 0.97 street directory
20# 0.98 street atlas
21#
22
23use strict ;
24use warnings ;
25use Getopt::Long ;
26use OSM::osm ;
27use OSM::QuadTree ;
28
29
30my $programName = "hikingbook.pl" ;
31my $version = "0.98" ;
32
33my $inFileName = "hessen.osm" ;
34my $outFileName = "hikingbook.pdf" ;
35my $overviewStyleFileName = "hikingRules.csv" ;
36my $detailStyleFileName = "hikingRules.csv" ;
37my $poiFileName = "hikingbook.poi" ;
38my $relationId = 0 ;
39my $relationName = "" ;
40my $relationRef = "" ;
41my @relationTags ;
42my $scale = 10000 ; # default detail scale
43my %pageHeight = () ;
44$pageHeight{"A4"} = 27.7 ;
45$pageHeight{"A5"} = 19 ;
46my %pageWidth = () ;
47$pageWidth{"A4"} = 19 ;
48$pageWidth{"A5"} = 13.8 ;
49my @overviewScales = (10000,25000,50000,75000,100000,200000,500000,1000000) ; # best fit will be taken
50my $title = "Hiking book" ;
51my $workDir = "" ;
52my $logFileName = "hikingbooklog.txt" ;
53my @tempFiles = () ; # to be deleted later
54
55my %lon ; my %lat ;
56my @ways ;
57my @nodes ;
58my %nodeDirCount ; 
59my %wayNodesHash = () ;
60my %wayNameHash = () ;
61my $mapNumber = 0 ; # counts detail maps
62my $scaleOverview = 0 ;
63my $rectangles = "" ; # collect data for overview map
64
65my $languageOpt = "EN" ;
66my $noOutputOpt = 0 ;
67my $verboseOpt = 0 ;
68my $dirNumberOpt = 8 ; # number of different directions used (N,S,SW...)
69my $pageSizeOpt = "A4" ;
70my $overlapOpt = 5 ; # in percent
71my $landscapeOpt = 0 ;
72my $reverseOpt = 0 ;
73my $roundtripOpt = 0 ;
74my $noDeleteOpt = 0 ;
75my $pnSizeOverview = 48 ;
76my $pnSizeDetail = 64 ;
77my $descName = "" ;
78my $stepDescName = "" ;
79my $autorotateOpt = 0 ;
80my $lessStepsOpt = 0 ;
81my $stepSizeOpt = 15 ;
82my $stepColorOpt = "black" ;
83my $stepFontSizeOpt = 35 ;
84my $atlasOpt = "" ;
85
86my $poiOpt = 0 ;
87my $gridNumber = 5 ;
88my %pois = () ;
89my $streetOpt = 0 ;
90my %streets = () ;
91
92my $extraMapData1 = 0.1 ; # overlap for osm temp file 1 in degrees
93my $extraMapData2 = 0.005 ; # for temp file 2s
94
95my $mapgenCommandOverview = "perl mapgen.pl -pdf -declutter -legend=0 -scale -allowiconmove -pagenumbers=$pnSizeOverview,black,0" ;
96my $mapgenCommandDetail = "perl mapgen.pl -pdf -declutter -legend=0 -scale -allowiconmove" ;
97
98# relation bounding box. all data.
99my $relLonMax = -999 ;
100my $relLonMin = 999 ;
101my $relLatMax = -999 ;
102my $relLatMin = 999 ;
103
104# detail boxes outer bounds 0.92
105my $detailLonMax = -999 ;
106my $detailLonMin = 999 ;
107my $detailLatMax = -999 ;
108my $detailLatMin = 999 ;
109
110# initial file
111my $fileLonMax = -999 ;
112my $fileLonMin = 999 ;
113my $fileLatMax = -999 ;
114my $fileLatMin = 999 ;
115
116# temp osm file 1 data
117my $file1LonMax = -999 ;
118my $file1LonMin = 999 ;
119my $file1LatMax = -999 ;
120my $file1LatMin = 999 ;
121
122my $temp1FileName = "temp1.osm" ;
123my $temp2FileName = "temp2.osm" ;
124
125my %nodeName = () ;
126my %nodeElevation = () ;
127my %nodeInfo = () ;
128my $segmentLength = 0 ;
129my %stepInformation = () ;
130my %contourData = () ;
131my %contourWays = () ;
132my $qt ;
133
134my @poiList ;   # POIs actually found
135my @pois = () ; # POIs to be used
136
137my %translations = () ;
138$translations{"DE"}{"station"} = "Bahnhof" ;
139$translations{"DE"}{"bus_stop"} = "Bushaltestelle" ;
140$translations{"DE"}{"viewpoint"} = "Aussichtspunkt" ;
141$translations{"DE"}{"restaurant"} = "Restaurant" ;
142$translations{"DE"}{"pharmacy"} = "Apotheke" ;
143$translations{"DE"}{"hospital"} = "Krankenhaus" ;
144$translations{"DE"}{"peak"} = "Gipfel" ;
145$translations{"DE"}{"fuel"} = "Tankstelle" ;
146$translations{"DE"}{"place_of_worship"} = "Kirche" ;
147$translations{"DE"}{"bar"} = "Bar" ;
148$translations{"DE"}{"hotel"} = "Hotel" ;
149$translations{"DE"}{"attraction"} = "Attraktion" ;
150$translations{"DE"}{"supermarket"} = "Supermarkt" ;
151$translations{"DE"}{"fast food"} = "Fast Food" ;
152$translations{"DE"}{"suburb"} = "Vorort" ;
153$translations{"DE"}{"hamlet"} = "Weiler" ;
154$translations{"DE"}{"city"} = "Großstadt" ;
155$translations{"DE"}{"town"} = "Stadt" ;
156$translations{"DE"}{"information"} = "Information" ;
157$translations{"DE"}{"spring"} = "Quelle" ;
158$translations{"DE"}{"parking"} = "Parkplatz" ;
159$translations{"DE"}{"pub"} = "Kneipe" ;
160$translations{"DE"}{"bank"} = "Bank" ;
161$translations{"DE"}{"castle"} = "Burg" ;
162$translations{"DE"}{"village"} = "Dorf" ;
163$translations{"DE"}{"hostel"} = "Herberge" ;
164# $translations{"DE"}{""} = "" ;
165
166my %validLatex = () ;
167my %replaceLatex = () ;
168
169initializeLatex() ;
170getProgramOptions () ;
171
172if ($atlasOpt eq "") {
173        print "HIKING/ROUTE MODE\n" ;
174        getPoiFiledata () ;
175        getRelationData() ;
176        getStepInformation() ;
177        createTemp1 () ;
178        buildCompleteWay() ;
179        compileElevationData () ;
180        addPois() ;
181        createDirections() ;
182        createDetailMaps() ;
183}
184else {
185        print "ATLAS MODE\n" ;
186
187        if ($title eq "Hiking book") { $title = "Atlas" ; }
188
189        # print "opt = $atlasOpt\n" ;
190        ($relLonMin, $relLatMin, $relLonMax, $relLatMax) = ( $atlasOpt =~ /([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)/ ) ;
191        # print "$relLonMin, $relLatMin, $relLonMax, $relLatMax\n" ;
192        if ((! defined $relLonMin) or (! defined $relLatMin) or (! defined $relLonMax) or (! defined $relLatMax)) {
193                die "ERROR in atlas coordinates: $atlasOpt\n" ;
194        }
195
196        openOsmFile ($inFileName) ;
197        print "reading nodes of input file...\n" ;
198
199        my $propRef ; my $tagsRef ;     
200        ($propRef, $tagsRef) = getNode3() ;
201        while (defined $propRef) {
202                # collect data of big file
203                if ( $$propRef{"lon"} > $fileLonMax ) { $fileLonMax = $$propRef{"lon"} ; }
204                if ( $$propRef{"lon"} < $fileLonMin ) { $fileLonMin = $$propRef{"lon"} ; }
205                if ( $$propRef{"lat"} > $fileLatMax ) { $fileLatMax = $$propRef{"lat"} ; }
206                if ( $$propRef{"lat"} < $fileLatMin ) { $fileLatMin = $$propRef{"lat"} ; }
207
208                ($propRef, $tagsRef) = getNode3() ;
209        }
210        closeOsmFile() ;
211        print "done.\n" ;
212
213        createTemp1 () ;
214        createDetailMapsAtlas() ;
215}
216
217createOverviewMap() ;
218createTitlePage () ;
219createDirectory () ;
220mergeAllFiles() ;
221
222print "\ndeleting temp files (disable with -nodelete)...\n" ;
223if ($noDeleteOpt == 0) {
224        push @tempFiles, $temp2FileName ;
225        foreach my $f (@tempFiles) {
226                `rm $f` ;
227        }
228}
229print "done.\n\n" ;
230
231
232sub getRelationData {
233        my %neededWays = () ;
234        my %neededNodes = () ;
235        my @relationMembers = () ;
236        # my @relationTags = () ; # now GLOBAL
237
238        # get relation data
239
240        print "\nget data from file...\n" ;
241        print "parsing relations...\n" ;
242        openOsmFile ($inFileName) ;
243        skipNodes() ;
244        skipWays() ;
245
246        my $propRef ; my $membersRef ; my $tagsRef ;
247        ($propRef, $membersRef, $tagsRef) = getRelation3() ;
248
249        my $found = 0 ;
250        my $name = "" ; my $ref = "" ;
251        while ( (defined $propRef) and (! $found) ) {
252                if ($$propRef{"id"} == $relationId) {
253                        $found = 1 ;
254                        @relationMembers = @$membersRef ;
255                        @relationTags = @$tagsRef ;
256                }
257
258                foreach my $t (@$tagsRef) {
259                        if ($t->[0] eq "name") { $name = $t->[1] ; }
260                        if ($t->[0] eq "ref") { $ref = $t->[1] ; }
261                }
262
263                if ( ($relationName ne "") and (grep /^$relationName$/i, $name) ) {
264                        $found = 1 ;
265                        $relationId = $$propRef{'id'} ;
266                        @relationMembers = @$membersRef ;
267                        @relationTags = @$tagsRef ;
268                }
269                if ( ($relationRef ne "") and (grep /^$relationRef$/i, $ref) ) {
270                        $found = 1 ;
271                        $relationId = $$propRef{'id'} ;
272                        @relationMembers = @$membersRef ;
273                        @relationTags = @$tagsRef ;
274                }
275
276                if ($found) {
277                        print "\nRelation $$propRef{'id'} found.\n" ;
278                        print "Name: $name\n" ;
279                        print "Ref: $ref\n\n" ;
280
281                }
282
283                ($propRef, $membersRef, $tagsRef) = getRelation3() ;
284        }
285        closeOsmFile() ;
286
287        if ( ($name ne "") and ($title eq "Hiking book") ) { $title = $name ; } # 0.94
288        if ( ($name ne "") and ($outFileName eq "hikingbook.pdf") ) { $outFileName = $name . ".pdf" ; }
289
290        if ($found == 0) {
291                die ("relation not found!\n") ;
292        }
293
294        @ways = () ;
295
296        my $wc = 0 ;
297        my %types = () ;
298        foreach my $m (@relationMembers) {
299                if ($m->[0] eq "way") {
300                        $types{$m->[2]} = 1 ;
301                        my $validRole = 0 ; # 0.94
302                        foreach my $r (qw (none forward route) ) { 
303                                if ( $m->[2] eq $r ) { $validRole = 1 ; }
304                        }
305                        if ($validRole) {
306                                $wc++ ;
307                                $neededWays{$m->[1]} = 1 ;
308                                push @ways, $m->[1] ;
309                        }
310                        else {
311                                my $role = $m->[2] ;
312                                print "WARNING: invalid role $role detected.\n" ;
313                        }
314                }
315        }
316        if ($verboseOpt eq "1") {
317                print "relation contains $wc ways.\n" ;
318                my @nw = keys %neededWays ;
319                print "NEEDED WAYS: @nw\n" ;
320        }
321
322        if ($verboseOpt eq "1") {
323                print "ROLES: " ;
324                foreach my $r (keys %types) { print $r, " " ; }
325                print "\n" ;
326        }
327
328        # get way data
329
330        print "parsing ways...\n" ;
331        openOsmFile ($inFileName) ;
332        skipNodes() ;
333
334        my $nodesRef ; 
335        ($propRef, $nodesRef, $tagsRef) = getWay3() ;
336        while (defined $propRef) {
337                if (defined $neededWays{$$propRef{"id"}}) {
338
339                        delete $neededWays{$$propRef{"id"}} ;
340
341                        if (scalar @$nodesRef < 2) { print "ERROR: needed way $$propRef{'id'} has less than 2 nodes!\n" ; } 
342
343                        foreach my $n (@$nodesRef) {
344                                $neededNodes{$n} = 1 ;
345                        }
346                        @{$wayNodesHash{ $$propRef{"id"}} } = @$nodesRef ;
347
348                        my $n = "" ; 
349                        my $r = "" ;
350                        foreach my $t (@$tagsRef) {
351                                if ($t->[0] eq "name") { $n = $t->[1] ; }
352                                if ($t->[0] eq "ref") { $r = $t->[1] ; }
353                        }
354
355                        my $name = "" ;
356                        if ($n ne "") { $name = $n ; }
357                        if ($r ne "") { $name = $r . " " . $name ; }
358                        $wayNameHash{$$propRef{"id"}} = $name ;
359                        # print "name: $name\n" ;
360
361                }
362
363
364                ($propRef, $nodesRef, $tagsRef) = getWay3() ;
365        }
366        closeOsmFile() ;
367
368        if (scalar keys %neededWays > 0) {
369                foreach my $w (keys %neededWays) {
370                        print "ERROR: needed way $w missing.\n" ;
371                }
372                die ("ERROR: ways missing.\n") ;
373        }
374
375        # get node data
376
377        openOsmFile ($inFileName) ;
378        print "reading nodes...\n" ;
379
380        ($propRef, $tagsRef) = getNode3() ;
381        while (defined $propRef) {
382                if (defined $neededNodes{$$propRef{"id"}}) {
383                        delete $neededNodes{$$propRef{"id"}} ;
384
385                        $lon{ $$propRef{"id"} } = $$propRef{"lon"} ; 
386                        $lat{ $$propRef{"id"} } = $$propRef{"lat"} ; 
387
388                        if ( $$propRef{"lon"} > $relLonMax ) { $relLonMax = $$propRef{"lon"} ; }
389                        if ( $$propRef{"lon"} < $relLonMin ) { $relLonMin = $$propRef{"lon"} ; }
390                        if ( $$propRef{"lat"} > $relLatMax ) { $relLatMax = $$propRef{"lat"} ; }
391                        if ( $$propRef{"lat"} < $relLatMin ) { $relLatMin = $$propRef{"lat"} ; }
392
393                        my $ele = "" ;
394                        foreach my $t (@$tagsRef) {
395                                if ($t->[0] eq "ele") { $ele = $t->[1] ; }
396                        }
397                        $nodeElevation{$$propRef{"id"}} = $ele ;
398       
399                }
400
401                my $extra = 0.000 ;
402                $relLonMin = $relLonMin - $extra ;
403                $relLonMax = $relLonMax + $extra ;
404                $relLatMin = $relLatMin - $extra ;
405                $relLatMax = $relLatMax + $extra ;
406
407
408                # also collect data of big file
409                if ( $$propRef{"lon"} > $fileLonMax ) { $fileLonMax = $$propRef{"lon"} ; }
410                if ( $$propRef{"lon"} < $fileLonMin ) { $fileLonMin = $$propRef{"lon"} ; }
411                if ( $$propRef{"lat"} > $fileLatMax ) { $fileLatMax = $$propRef{"lat"} ; }
412                if ( $$propRef{"lat"} < $fileLatMin ) { $fileLatMin = $$propRef{"lat"} ; }
413
414                ($propRef, $tagsRef) = getNode3() ;
415        }
416        closeOsmFile() ;
417        print "done.\n" ;
418
419        if (scalar keys %neededNodes > 0) {
420                foreach my $n (keys %neededNodes) {
421                        print "ERROR: needed node $n missing.\n" ;
422                }
423                die ("ERROR: nodes missing.\n") ;
424        }
425
426
427        if ($verboseOpt eq "1") {
428                print "relation bounding box: $relLonMin, $relLatMin, $relLonMax, $relLatMax\n" ;
429        }
430
431
432
433}
434
435
436sub createTemp1 {
437        # this file is used to draw the overview and further osm files for details are generated from this one to save time.
438        print "\ncreate temp file 1...\n" ;
439
440
441        if ($noOutputOpt eq "0") {
442                shrinkFile ($inFileName, $temp1FileName, $fileLonMin, $fileLatMin, $fileLonMax, $fileLatMax, $relLonMin, $relLatMin, $relLonMax, $relLatMax, $extraMapData1) ;
443
444                push @tempFiles, $temp1FileName ;
445
446                print "reading temp file...\n" ;
447
448                my $contourCount = 0 ;
449                my %neededNodes = () ;
450
451                my $nodesRef ; my $propRef ; my $tagsRef ;
452
453                if ($atlasOpt eq "") {
454
455                        # openOsmFile ($inFileName) ;
456                        openOsmFile ($temp1FileName) ; # 0.92
457                        skipNodes() ;
458
459                        ($propRef, $nodesRef, $tagsRef) = getWay3() ;
460                        while (defined $propRef) {
461                                my $needed = 0 ;
462                                my $contourNeeded = 0 ;
463                                my $ele = -999 ;
464                                foreach my $t (@$tagsRef) {
465                                        if ($t->[0] eq "highway") { $needed = 1 ; }
466                                        if ($t->[0] eq "contour_ext") { $contourNeeded = 1 ; }
467                                        if ($t->[0] eq "ele") { $ele = $t->[1] ; }
468                                }
469
470                                if ($needed) {
471                                        @nodes = @$nodesRef ;
472                                        for (my $i=0 ; $i <= $#nodes; $i++) {
473                                                my $n = $nodes[$i] ;
474                                                if ( ($i == 0) or ($i ==$#nodes) ) {
475                                                        $nodeDirCount{$n} += 1 ;
476                                                }
477                                                else {
478                                                        $nodeDirCount{$n} += 2 ;
479                                                }
480                                        }
481                                }
482
483                                if ( ($contourNeeded) and ($ele != -999) and (scalar @$nodesRef > 1) ) {
484                                        $contourCount++ ;
485                                        @{ $wayNodesHash{ $$propRef{"id"} } } = @$nodesRef ;
486                                        $contourWays { $$propRef{"id"} } = $ele ;
487                                        foreach my $n ( @$nodesRef ) {
488                                                $neededNodes{$n} = 1 ;
489                                        }
490                                }
491
492                                ($propRef, $nodesRef, $tagsRef) = getWay3() ;
493                        }
494                        closeOsmFile() ;
495                        print "$contourCount contour ways found.\n" ;
496
497                }
498
499                # store min / max of temp file
500
501
502                openOsmFile ($temp1FileName) ;
503                ($propRef, $tagsRef) = getNode3() ;
504                while (defined $propRef) {
505
506                        if (defined $neededNodes { $$propRef{"id"} }) {
507                                $lon { $$propRef{"id"} } = $$propRef{"lon"} ;
508                                $lat { $$propRef{"id"} } = $$propRef{"lat"} ;
509                        }
510
511                        if ( $$propRef{"lon"} > $file1LonMax ) { $file1LonMax = $$propRef{"lon"} ; }
512                        if ( $$propRef{"lon"} < $file1LonMin ) { $file1LonMin = $$propRef{"lon"} ; }
513                        if ( $$propRef{"lat"} > $file1LatMax ) { $file1LatMax = $$propRef{"lat"} ; }
514                        if ( $$propRef{"lat"} < $file1LatMin ) { $file1LatMin = $$propRef{"lat"} ; }
515
516                        if ($atlasOpt eq "") {
517
518                                # poi check and data collection
519                                foreach my $t (@$tagsRef) {
520                                        foreach my $p (@pois) {
521                                                if ( ($t->[0] eq $p->[0]) and ($t->[1] eq $p->[1]) ) {
522                                                        my $name = "" ;
523                                                        foreach my $t1 (@$tagsRef) {
524                                                                if ($t1->[0] eq "name") { $name = $t1->[1] ; }
525                                                        }
526                                                        my $info ;
527                                                        if ($languageOpt eq "EN") { $info = $p->[3] ; }
528                                                        if ($languageOpt eq "DE") { $info = $p->[4] ; }
529                                                        $name = sanitizeLatexString ($name) ;
530                                                        push @poiList, [ $info, $name, $$propRef{"id"}, $p->[2] ] ;
531                                                        $lon{ $$propRef{"id"} } = $$propRef{"lon"} ;
532                                                        $lat{ $$propRef{"id"} } = $$propRef{"lat"} ;
533                                                }
534                                        }
535                                }
536
537                        }
538
539                        ($propRef, $tagsRef) = getNode3() ;
540                }
541                closeOsmFile() ;
542
543                # print "temp1: $file1LonMin, $file1LatMin, $file1LonMax, $file1LatMax\n" ;
544
545                $qt = OSM::QuadTree->new (      -xmin => $file1LonMin, 
546                                                -xmax => $file1LonMax, 
547                                                -ymin => $file1LatMin, 
548                                                -ymax => $file1LatMax, 
549                                                -depth => 6) ;
550
551
552        }
553}
554
555sub createOverviewMap {
556        print "\ncreate overview map...\n" ;
557
558        my $scale ;
559        # my $distLon = distance ($relLonMin, $relLatMin, $relLonMax, $relLatMin) ; # in km
560        # my $distLat = distance ($relLonMin, $relLatMin, $relLonMin, $relLatMax) ; # in km
561        # 0.92
562        my $distLon = distance ($detailLonMin, $detailLatMin, $detailLonMax, $detailLatMin) ; # in km
563        my $distLat = distance ($detailLonMin, $detailLatMin, $detailLonMin, $detailLatMax) ; # in km
564
565        $distLon = int ($distLon * 1000) / 1000 ;
566        $distLat = int ($distLat * 1000) / 1000 ;
567
568        if ($verboseOpt eq "1") {
569                print "overview distances lon / lat in km: $distLon $distLat\n" ;
570        }
571
572        my $distWidth = $pageWidth{$pageSizeOpt} / 100 / 1000 ;
573        my $distHeight = $pageHeight{$pageSizeOpt} / 100 / 1000 ;
574        my $scaleWidth =  int ($distLon / $distWidth) ;
575        my $scaleHeight =  int ($distLat / $distHeight) ;
576
577        if ($verboseOpt eq "1") {
578                print "overview scales W/H: $scaleWidth / $scaleHeight\n" ;
579        }
580
581        # select min scale
582        $scale = $scaleWidth ;
583        if ($scaleHeight > $scale) { $scale = $scaleHeight ; }
584
585        # select fitting scale
586        foreach my $s (@overviewScales) {
587                if ($s > $scale) {
588                        $scale = $s ;
589                        last ;
590                }
591        }
592
593        $scaleOverview = $scale ;
594
595        if ($verboseOpt eq "1") {
596                print "selected overview scale: $scale\n" ;
597        }
598
599
600        my $outName = $workDir . "overview.svg" ;
601        if ($noOutputOpt eq "0") {
602
603                my $pdfName = $outName ; $pdfName =~ s/\.svg/\.pdf/ ;
604                my $ndlName = $outName ; $ndlName =~ s/\.svg/\_NotDrawnLabels\.txt/ ;
605                push @tempFiles, $outName ;
606                push @tempFiles, $pdfName ;
607                push @tempFiles, $ndlName ;
608
609                # allow for some more data than just the relation 0.92
610                my $more = 0.005 ;
611                my $ovLonMin = $detailLonMin - $more ;
612                my $ovLonMax = $detailLonMax + $more ;
613                my $ovLatMin = $detailLatMin - $more ;
614                my $ovLatMax = $detailLatMax + $more ;
615
616                # but check if data is present
617                if ($ovLonMin < $file1LonMin) { $ovLonMin = $file1LonMin ; }
618                if ($ovLonMax > $file1LonMax) { $ovLonMax = $file1LonMax ; }
619                if ($ovLatMin < $file1LatMin) { $ovLatMin = $file1LatMin ; }
620                if ($ovLatMax > $file1LatMax) { $ovLatMax = $file1LatMax ; }
621
622
623                print "call mapgen and log to $logFileName...\n" ;
624
625                `$mapgenCommandOverview -in=$temp1FileName -out=$outName -style=$overviewStyleFileName -scaleset=$scaleOverview -clipbbox=$ovLonMin,$ovLatMin,$ovLonMax,$ovLatMax -relid=$relationId $rectangles >> $logFileName 2>&1` ;
626
627                print "done.\n" ;
628        }
629}
630
631
632
633sub buildCompleteWay {
634#
635# this function tries to make sense of all the ways collected from the relation
636#
637        my %leftWays = () ;
638
639        my @orderedWays ;
640
641        print "\nbuilding complete way for relation...\n" ;
642
643        my $firstWay = shift @ways ;
644        @orderedWays = ($firstWay) ;
645
646        if ($roundtripOpt eq "1") {
647                # assure that first way can be expanded at the end
648                my @n = @{$wayNodesHash{ $firstWay }} ;
649                my $end = $n[-1] ;
650                my $found = 0 ;
651                foreach my $w (@ways) {
652                        my @tn = @{$wayNodesHash{ $w }} ;
653                        if ( ($tn[0] == $end) or ($tn[-1] == $end) ) { $found = 1 ; }
654                }
655                if ($found == 0) {
656                        @{$wayNodesHash{ $firstWay }} = reverse @{$wayNodesHash{ $firstWay }} ;
657                }
658        }
659
660
661        @nodes = @{$wayNodesHash{ $firstWay }} ;
662
663        foreach my $w (@ways) { $leftWays{ $w } = 1 ; }
664
665        my $success = 1 ;
666        while ( $success and ( scalar (keys %leftWays) > 0 ) ) {
667                $success = 0 ;
668
669                foreach my $w (keys %leftWays) {
670                        my @wayNodes = @{$wayNodesHash{$w}} ;
671
672                        if ( ( $nodes[0] == $wayNodes[0] ) and ($roundtripOpt == 0) ) {
673                        # if ( ( $nodes[0] == $wayNodes[0] ) ) {
674                                # reverse unshift
675                                @wayNodes = reverse @wayNodes ;
676                                pop @wayNodes ; # remove last element
677                                unshift @nodes, @wayNodes ;
678                                unshift @orderedWays, $w ;
679                                $success = 1 ;
680                                delete $leftWays{ $w } ;
681                                last ;
682                        }
683
684                        if ( ( $nodes[0] == $wayNodes[-1] ) and ($roundtripOpt == 0) ) {
685                        # if ( ( $nodes[0] == $wayNodes[-1] ) ) {
686                                # unshift
687                                pop @wayNodes ; # remove last element
688                                unshift @nodes, @wayNodes ;
689                                unshift @orderedWays, $w ;
690                                $success = 1 ;
691                                delete $leftWays{ $w } ;
692                                last ;
693                        }
694
695                        if ( $nodes[-1] == $wayNodes[0] ) {
696                                # push
697                                shift @wayNodes ; # remove first element
698                                push @nodes, @wayNodes ;
699                                push @orderedWays, $w ;
700                                $success = 1 ;
701                                delete $leftWays{ $w } ;
702                                last ;
703                        }
704
705                        if ( $nodes[-1] == $wayNodes[-1] ) {
706                                # push reverse
707                                @wayNodes = reverse @wayNodes ;
708                                shift @wayNodes ; # remove first element
709                                push @nodes, @wayNodes ;
710                                push @orderedWays, $w ;
711                                $success = 1 ;
712                                delete $leftWays{ $w } ;
713                                last ;
714                        }
715
716                }
717        }
718
719        if ( $nodes[0] == $nodes[-1]) { print "found segment is closed.\n" ; }
720        if ( scalar (keys %leftWays) > 0) { print "WARNING: relation consists of more than one segment. using only first one.\n" ; }
721
722        my $nc = scalar @nodes ;
723
724        if ($verboseOpt eq "1") {
725                print "used segment consists of $nc nodes.\n" ;
726        }
727
728        @ways = @orderedWays ;
729
730        if ( $lon{ $nodes[0] } > $lon{ $nodes[-1] } ) { 
731                @nodes = reverse @nodes ; 
732                @ways = reverse @ways ;
733        } 
734
735        if ($reverseOpt eq "1") {
736                print "reversing ways and nodes.\n" ;
737                @nodes = reverse @nodes ; 
738                @ways = reverse @ways ;
739        }
740       
741        # get names of ways to nodes for directions
742        foreach my $w (@ways) {
743                foreach my $n (@{$wayNodesHash{$w}}) {
744                        $nodeName{$n} = $wayNameHash{$w} ;
745                }
746        }
747
748        # calc distances // nodeinfo is indexed by node number, not ID!
749        my $dist = 0 ;
750        $nodeInfo{0}{"distance"} = 0 ;
751        for (my $i = 1;  $i<=$#nodes; $i++) {
752                $dist += distance ($lon{$nodes[$i-1]}, $lat{$nodes[$i-1]}, $lon{$nodes[$i]}, $lat{$nodes[$i]}) ;
753                $nodeInfo{$i}{"distance"} = int ($dist * 100) / 100 ;
754        }
755        $segmentLength = $dist ;
756        $dist = int ($dist * 1000) / 1000 ;
757        print "used route segment is $dist km long.\n" ;
758
759        # nodeinfo is indexed by nodeNumber, NOT id!
760        for (my $i = 0;  $i<$#nodes; $i++) {
761                $nodeInfo{$i}{"direction"} = direction ($nodes[$i], $nodes[$i+1]) ;             
762                $nodeInfo{$i}{"angle"} = angle ($lon{$nodes[$i]}, $lat{$nodes[$i]}, $lon{$nodes[$i+1]}, $lat{$nodes[$i+1]}) ;
763                $nodeInfo{$i}{"name"} = sanitizeLatexString ( $nodeName{ $nodes[$i] } ) ;               
764                $nodeInfo{$i}{"ele"} = $nodeElevation{ $nodes[$i] } ;           
765                $nodeInfo{$i}{"dirs"} = $nodeDirCount{ $nodes[$i] } ;           
766        }
767
768        $nodeInfo{$#nodes}{"ele"} = $nodeElevation{ $nodes[ -1 ] } ;
769        $nodeInfo{$#nodes}{"dirs"} = $nodeDirCount{ $nodes[ -1 ] } ;
770        $nodeInfo{$#nodes}{"direction"} = "" ;
771        $nodeInfo{$#nodes}{"angle"} = 0 ;
772        $nodeInfo{$#nodes}{"name"} = "" ;
773
774        my %info = () ;
775        $info{"EN"}{"start"} = "Start" ;
776        $info{"EN"}{"end"} = "End" ;
777        $info{"DE"}{"start"} = "Start" ;
778        $info{"DE"}{"end"} = "Ende" ;
779        @{$nodeInfo{0}{"information"}} = ( $info{$languageOpt}{"start"} ) ;
780        @{$nodeInfo{$#nodes}{"information"}} = ( $info{$languageOpt}{"end"} ) ;
781
782       
783
784        if ($verboseOpt eq "1") {
785                print "ordered ways: @ways\n" ;
786                print "\nordered nodes: @nodes\n\n" ;
787        }
788}
789
790
791
792sub createDetailMaps {
793
794        print "\ncreate detail maps...\n" ;
795
796        my $first = 1 ;
797
798        my $maxDistLon = $pageWidth{$pageSizeOpt} / 100 / 1000 * $scale ; # in km
799        my $maxDistLat = $pageHeight{$pageSizeOpt} / 100 / 1000 * $scale ; # in km
800
801        my $maxDistLonOverlap = $maxDistLon * ( 1 - 2 * $overlapOpt / 100) ;
802        my $maxDistLatOverlap  = $maxDistLat * ( 1 - 2 * $overlapOpt / 100) ;
803
804        # print "DETAIL:  page max dists $maxDistLon / $maxDistLat\n" ;
805
806        my $mapName = "detail" ;
807        my $start = 0 ;
808        my $finished = 0 ;
809
810        while ( ! $finished ) {
811               
812                my $actual = $start ;
813                my $rotated = 0 ;
814                my $lonMin = $lon{$nodes[$start]} ;
815                my $lonMax = $lon{$nodes[$start]} ;
816                my $latMin = $lat{$nodes[$start]} ;
817                my $latMax = $lat{$nodes[$start]} ;
818               
819                my $busted = 0 ;
820                while ( ( ! $busted ) and ($actual < $#nodes) ) {
821
822                        # print " $actual\n" ;
823                        my $tempLonMax = $lonMax ;
824                        my $tempLonMin = $lonMin ;
825                        my $tempLatMax = $latMax ;
826                        my $tempLatMin = $latMin ;
827
828                        # add point
829                        $actual++ ;
830                        if ( $lon{ $nodes[ $actual ] } > $lonMax) { $lonMax = $lon{ $nodes[ $actual ] } ; }
831                        if ( $lon{ $nodes[ $actual ] } < $lonMin) { $lonMin = $lon{ $nodes[ $actual ] } ; }
832                        if ( $lat{ $nodes[ $actual ] } > $latMax) { $latMax = $lat{ $nodes[ $actual ] } ; }
833                        if ( $lat{ $nodes[ $actual ] } < $latMin) { $latMin = $lat{ $nodes[ $actual ] } ; }
834
835                        my $distLon = distance ($lonMin, $latMin, $lonMax, $latMin) ;
836                        my $distLat = distance ($lonMin, $latMin, $lonMin, $latMax) ;
837
838                        # print "$actual:  $distLon / $distLat\n" ;
839
840                        # autorotate
841                        if ( ($autorotateOpt eq "1") and ( ! $rotated) ) {
842                                if      ( ( ($distLon > $maxDistLonOverlap) and ( $distLat < $maxDistLonOverlap) and ($maxDistLatOverlap > $maxDistLonOverlap) )
843                                        or ( ($distLat > $maxDistLatOverlap) and ( $distLon < $maxDistLatOverlap)  and ($maxDistLatOverlap < $maxDistLonOverlap) )
844                                        ) { 
845                                        if ($verboseOpt eq "1") { print "actual page automatically rotated.\n" ; }
846
847                                        # print "rotated\n" ;
848
849                                        $rotated = 1 ;
850                                        $maxDistLon = $pageHeight{$pageSizeOpt} / 100 / 1000 * $scale ; # in km
851                                        $maxDistLat = $pageWidth{$pageSizeOpt} / 100 / 1000 * $scale ; # in km
852
853                                        $maxDistLonOverlap = $maxDistLon * ( 1 - 2 * $overlapOpt / 100) ;
854                                        $maxDistLatOverlap  = $maxDistLat * ( 1 - 2 * $overlapOpt / 100) ;
855                                }
856                        }       
857
858                        if ( ($distLon > $maxDistLonOverlap) or ($distLat > $maxDistLatOverlap) ) { 
859                                # print "BUSTED\n" ;
860                                $busted = 1 ; 
861                                $actual-- ;
862                                # restore max and min
863                                $lonMax = $tempLonMax ;
864                                $lonMin = $tempLonMin ;
865                                $latMax = $tempLatMax ;
866                                $latMin = $tempLatMin;
867                        }
868                }
869
870                if ($actual == $#nodes) { $finished = 1 ; }
871
872                # create map
873                my $percent = int ($actual / $#nodes * 100) ;
874                print "\ncreate map for nodes $start to $actual ($percent \%).\n" ;
875
876                # print "DETAIL: initial bbox = $lonMin,$latMin,$lonMax,$latMax\n" ;
877                # print "DETAIL: max dists = $maxDistLon $maxDistLat\n" ;
878
879                my $distLon = distance ($lonMin, $latMin, $lonMax, $latMin) ;
880                my $distLat = distance ($lonMin, $latMin, $lonMin, $latMax) ;
881                # print "DETAIL: actual dists: $distLon, $distLat\n" ;
882
883
884                my $missingLat = $maxDistLat - $distLat ;
885                my $missingLatFactor = $missingLat / $distLat ;
886                my $additionalLat = ($latMax-$latMin) * $missingLatFactor / 2 ;
887                # print "DETAIL: LAT: $missingLat $missingLatFactor $additionalLat\n" ;
888               
889                $latMin = $latMin - $additionalLat ;
890                $latMax = $latMax + $additionalLat ;
891
892                my $missingLon = $maxDistLon - $distLon ;
893                my $missingLonFactor = $missingLon / $distLon ;
894                my $additionalLon = ($lonMax-$lonMin) * $missingLonFactor / 2 ;
895                # print "DETAIL: LON: $missingLon $missingLonFactor $additionalLon\n" ;
896
897                $lonMin = $lonMin - $additionalLon ;
898                $lonMax = $lonMax + $additionalLon ;
899
900                # print "DETAIL: bbox after factor = $lonMin,$latMin,$lonMax,$latMax\n" ;
901
902
903
904                $mapNumber++ ;
905                my $outName = $workDir . $mapName . $mapNumber . ".svg" ;
906                my $actualScale = $scale ;
907                if ($noOutputOpt eq "0") {
908
909
910                        shrinkFile ($temp1FileName, $temp2FileName, $file1LonMin, $file1LatMin, $file1LonMax, $file1LatMax, $lonMin, $latMin, $lonMax, $latMax, $extraMapData2) ;
911
912                        my ($file2LonMin, $file2LatMin, $file2LonMax, $file2LatMax) = getMinMax ($temp2FileName)  ;
913
914                        if ($lonMin < $file2LonMin) { $lonMin = $file2LonMin ; }
915                        if ($lonMax > $file2LonMax) { $lonMax = $file2LonMax ; }
916                        if ($latMin < $file2LatMin) { $latMin = $file2LatMin ; }
917                        if ($latMax > $file2LatMax) { $latMax = $file2LatMax ; }
918
919                        # maintain details outer box 0.92
920                        if ($lonMin < $detailLonMin) { $detailLonMin = $lonMin ; }
921                        if ($lonMax > $detailLonMax) { $detailLonMax = $lonMax ; }
922                        if ($latMin < $detailLatMin) { $detailLatMin = $latMin ; }
923                        if ($latMax > $detailLatMax) { $detailLatMax = $latMax ; }
924
925                        # print "DETAIL: bbox before mapgen = $lonMin,$latMin,$lonMax,$latMax\n" ;
926
927                        if ($first) {
928                                $first = 0 ;
929                                $rectangles = "-rectangles=" ;
930                        }
931                        else {
932                                $rectangles .= "#" ;
933                        }
934                        $rectangles .= "$lonMin,$latMin,$lonMax,$latMax" ;
935
936                        my $pdfName = $outName ; $pdfName =~ s/\.svg/\.pdf/ ;
937                        my $ndlName = $outName ; $ndlName =~ s/\.svg/\_NotDrawnLabels\.txt/ ;
938                        push @tempFiles, $outName ;
939                        push @tempFiles, $pdfName ;
940                        push @tempFiles, $ndlName ;
941
942                        my $poiParams = "" ;
943                        if ($poiOpt > 0) {
944                                $poiParams = "-poi -grid=$gridNumber" ;
945                        }
946
947                        my $streetParams = "" ;
948                        if ($streetOpt > 0) {
949                                $streetParams = "-dir -grid=$gridNumber" ;
950                        }
951
952                        print "call mapgen and log to $logFileName...\n" ;
953                        `$mapgenCommandDetail -in=$temp2FileName -out=$outName -style=$detailStyleFileName -scaleset=$actualScale -clipbbox=$lonMin,$latMin,$lonMax,$latMax -poifile=step.txt -relid=$relationId -pagenumbers=$pnSizeDetail,black,$mapNumber $poiParams $streetParams >> $logFileName 2>&1` ;
954                        print "done.\n" ;
955
956                        loadExternalFiles($outName) ;
957
958                }
959
960                # next
961                $start = $actual ;
962
963                # restore sizes (after rotate)
964                $maxDistLon = $pageWidth{$pageSizeOpt} / 100 / 1000 * $scale ; # in km
965                $maxDistLat = $pageHeight{$pageSizeOpt} / 100 / 1000 * $scale ; # in km
966
967                $maxDistLonOverlap = $maxDistLon * ( 1 - 2 * $overlapOpt / 100) ;
968                $maxDistLatOverlap  = $maxDistLat * ( 1 - 2 * $overlapOpt / 100) ;
969
970
971        }
972
973}
974
975sub createDetailMapsAtlas {
976        my $mapName = "detail" ;
977        my $first = 1 ;
978
979        # calc dists
980
981        my $maxDistLon = $pageWidth{$pageSizeOpt} / 100 / 1000 * $scale ; # in km
982        my $maxDistLat = $pageHeight{$pageSizeOpt} / 100 / 1000 * $scale ; # in km
983        my $sizeX = $maxDistLon / (111.11 * cos ($relLatMin / 360 * 3.14 * 2) ) ;
984        my $sizeY = $maxDistLat / 111.11 ;
985        if ($verboseOpt eq "1") {
986                print "MAX dists: $maxDistLon, $maxDistLat (km)   $sizeX, $sizeY (degrees)\n" ; 
987        }
988
989
990        my @hor = () ;
991        my @ver = () ;
992
993        my $x = $relLonMin ; 
994        my $x2 = $x + $sizeX ;
995        push @hor, [$x, $x2] ;
996        # print "$x $x2\n" ;
997        while ($x2 < $relLonMax) {
998                $x = $x2 - $sizeX * ($overlapOpt/100) ;
999                $x2 = $x + $sizeX ;
1000                if ($x2 > $relLonMax) { $x2 = $relLonMax ; }
1001                push @hor, [$x, $x2] ;
1002                # print "$x $x2\n" ;
1003        }
1004
1005        my $y = $relLatMax ; 
1006        my $y2 = $y - $sizeY ;
1007        push @ver, [$y2, $y] ;
1008        # print "$y $y2\n" ;
1009        while ($y2 > $relLatMin) {
1010                $y = $y2 + $sizeY * ($overlapOpt/100) ;
1011                $y2 = $y - $sizeY ;
1012                if ($y2 < $relLatMin) { $y2 = $relLatMin ; }
1013                push @ver, [$y2, $y] ;
1014                # print "$y $y2\n" ;
1015        }
1016        my $nx = scalar @hor ;
1017        my $ny = scalar @ver ;
1018        print "Dimensions: $nx * $ny (width * height)\n" ;
1019        my $ntot = $nx * $ny ;
1020
1021        my $page ; my $py = 1 ; my $tot ;
1022        foreach my $v (@ver) {
1023                my $px = 1 ; 
1024                foreach my $h (@hor) {
1025                        $tot = ($py-1) * (scalar @hor) + $px ;
1026                        print "\n\ndetail maps progress: y=$py, x=$px  -  $h->[0] $v->[0] $h->[1] $v->[1]  -   page: $tot/$ntot\n" ;
1027
1028                        my $left ; my $right ; my $top ; my $bottom ;
1029                        if ($px > 1) { $left = $px - 1 + ($py - 1) * (scalar @hor) ; } else { $left = 0 ; }
1030                        if ($px < scalar @hor) { $right = $px + 1 + ($py - 1) * scalar @hor ; } else { $right = 0 ; }
1031                        # print "TEST ", ($py - 2) * (scalar @hor) + $px, "\n" ;
1032                        if ($py > 1) { $top = ($py - 2) * (scalar @hor) + $px ; } else { $top = 0 ; }
1033                        if ($py < scalar @ver) { $bottom = ($py) * (scalar @hor) + $px ; } else { $bottom = 0 ; }
1034                        if ($verboseOpt eq "1") {
1035                                print "neighbour pages: $bottom $top // $left $right\n\n" ;
1036                        }
1037
1038                        my $lonMin = $h->[0] ;
1039                        my $lonMax = $h->[1] ;
1040                        my $latMin = $v->[0] ;
1041                        my $latMax = $v->[1] ;
1042       
1043                        #
1044                        # create map
1045                        #
1046
1047                        $mapNumber++ ;
1048                        my $outName = $workDir . $mapName . $mapNumber . ".svg" ;
1049
1050                        shrinkFile ($temp1FileName, $temp2FileName, $file1LonMin, $file1LatMin, $file1LonMax, $file1LatMax, $lonMin, $latMin, $lonMax, $latMax, $extraMapData2) ;
1051
1052                        my ($file2LonMin, $file2LatMin, $file2LonMax, $file2LatMax) = getMinMax ($temp2FileName)  ;
1053
1054                        if ($lonMin < $file2LonMin) { $lonMin = $file2LonMin ; }
1055                        if ($lonMax > $file2LonMax) { $lonMax = $file2LonMax ; }
1056                        if ($latMin < $file2LatMin) { $latMin = $file2LatMin ; }
1057                        if ($latMax > $file2LatMax) { $latMax = $file2LatMax ; }
1058
1059                        # maintain details outer box
1060                        if ($lonMin < $detailLonMin) { $detailLonMin = $lonMin ; }
1061                        if ($lonMax > $detailLonMax) { $detailLonMax = $lonMax ; }
1062                        if ($latMin < $detailLatMin) { $detailLatMin = $latMin ; }
1063                        if ($latMax > $detailLatMax) { $detailLatMax = $latMax ; }
1064
1065                        # print "DETAIL: bbox before mapgen = $lonMin,$latMin,$lonMax,$latMax\n" ;
1066
1067                        if ($first) {
1068                                $first = 0 ;
1069                                $rectangles = "-rectangles=" ;
1070                        }
1071                        else {
1072                                $rectangles .= "#" ;
1073                        }
1074                        $rectangles .= "$lonMin,$latMin,$lonMax,$latMax" ;
1075
1076                        my $pdfName = $outName ; $pdfName =~ s/\.svg/\.pdf/ ;
1077                        my $ndlName = $outName ; $ndlName =~ s/\.svg/\_NotDrawnLabels\.txt/ ;
1078                        push @tempFiles, $outName ;
1079                        push @tempFiles, $pdfName ;
1080                        push @tempFiles, $ndlName ;
1081
1082                        my $poiParams = "" ;
1083                        if ($poiOpt > 0) {
1084                                $poiParams = "-poi -grid=$gridNumber" ;
1085                        }
1086
1087                        my $streetParams = "" ;
1088                        if ($streetOpt > 0) {
1089                                $streetParams = "-dir -grid=$gridNumber" ;
1090                        }
1091
1092                        my $pageNumbers = "$pnSizeDetail,black,$mapNumber,$left,$bottom,$right,$top" ;
1093
1094                        print "call mapgen and log to $logFileName...\n" ;
1095                        `$mapgenCommandDetail -in=$temp2FileName -out=$outName -style=$detailStyleFileName -scaleset=$scale -clipbbox=$lonMin,$latMin,$lonMax,$latMax -pagenumbers=$pageNumbers $poiParams $streetParams >> $logFileName 2>&1` ;
1096                        print "done.\n" ;
1097
1098                        loadExternalFiles($outName) ;
1099
1100
1101
1102                        $px ++ ;
1103                }
1104                $py ++ ;
1105        }
1106}
1107
1108
1109sub shrinkFile {
1110        my ($inFileName, $outFileName, $inLonMin, $inLatMin, $inLonMax, $inLatMax, $outLonMin, $outLatMin, $outLonMax, $outLatMax, $pad) = @_ ;
1111
1112        # print "SHRINK:\n" ;
1113        # print "$inFileName, $outFileName, $inLonMin, $inLatMin, $inLonMax, $inLatMax, $outLonMin, $outLatMin, $outLonMax, $outLatMax, $percentPad\n" ;
1114
1115        # calc new bbox
1116        $outLonMax += $pad ; # 0.92
1117        $outLonMin -= $pad ;
1118        $outLatMax += $pad ;
1119        $outLatMin -= $pad ;
1120       
1121        # check against source bbox
1122        if ($outLonMin < $inLonMin) { $outLonMin = $inLonMin ; }
1123        if ($outLonMax > $inLonMax) { $outLonMax = $inLonMax ; }
1124        if ($outLatMin < $inLatMin) { $outLatMin = $inLatMin ; }
1125        if ($outLatMax > $inLatMax) { $outLatMax = $inLatMax ; }
1126
1127        # print "bottom=$outLatMin top=$outLatMax left=$outLonMin right=$outLonMax\n" ;
1128        # print "SHRINK END\n" ;
1129
1130
1131        # call osmosis
1132        print "call osmosis and log to $logFileName...\n" ;
1133
1134        # `osmosis --read-xml $inFileName  --bounding-box clipIncompleteEntities=true bottom=$outLatMin top=$outLatMax left=$outLonMin right=$outLonMax --write-xml $outFileName >> $logFileName 2>&1` ;
1135
1136        `osmosis --read-xml $inFileName  --bounding-box completeWays=yes completeRelations=yes bottom=$outLatMin top=$outLatMax left=$outLonMin right=$outLonMax --write-xml $outFileName >> $logFileName 2>&1` ;
1137
1138        print "osmosis done.\n" ;
1139
1140}
1141
1142sub direction {
1143        my ($node1, $node2) = @_ ;
1144
1145        my %direction = () ;
1146        $direction{"EN"}{"N"} = "North" ;
1147        $direction{"EN"}{"S"} = "South" ;
1148        $direction{"EN"}{"W"} = "West" ;
1149        $direction{"EN"}{"E"} = "East" ;
1150        $direction{"EN"}{"NE"} = "North-East" ;
1151        $direction{"EN"}{"NW"} = "North-West" ;
1152        $direction{"EN"}{"SE"} = "South-East" ;
1153        $direction{"EN"}{"SW"} = "South-West" ;
1154
1155        $direction{"DE"}{"N"} = "Nord" ;
1156        $direction{"DE"}{"S"} = "Süd" ;
1157        $direction{"DE"}{"W"} = "West" ;
1158        $direction{"DE"}{"E"} = "Ost" ;
1159        $direction{"DE"}{"NE"} = "Nordost" ;
1160        $direction{"DE"}{"NW"} = "Nordwest" ;
1161        $direction{"DE"}{"SE"} = "Südost" ;
1162        $direction{"DE"}{"SW"} = "Südwest" ;
1163
1164        my $a = angle ($lon{$node1}, $lat{$node1}, $lon{$node2}, $lat{$node2}) ;       
1165
1166        my $dir = "" ;
1167
1168        if ($dirNumberOpt eq "8") {
1169                if ( ($a < 22.5) or ($a >= 337.5) ) { $dir = $direction {$languageOpt}{"N"} ; }
1170                if ( ($a >= 22.5) and ($a < 67.5) ) { $dir = $direction {$languageOpt}{"NE"} ; }
1171                if ( ($a >= 67.5) and ($a < 112.5) ) { $dir = $direction {$languageOpt}{"E"} ; }
1172                if ( ($a >= 112.5) and ($a < 167.5) ) { $dir = $direction {$languageOpt}{"SE"} ; }
1173                if ( ($a >= 167.5) and ($a < 202.5) ) { $dir = $direction {$languageOpt}{"S"} ; }
1174                if ( ($a >= 202.5) and ($a < 247.5) ) { $dir = $direction {$languageOpt}{"SW"} ; }
1175                if ( ($a >= 247.5) and ($a < 292.5) ) { $dir = $direction {$languageOpt}{"W"} ; }
1176                if ( ($a >= 292.5) and ($a < 337.5) ) { $dir = $direction {$languageOpt}{"NW"} ; }
1177        }
1178        else {
1179                if ( ($a < 45) or ($a >= 315) ) { $dir = $direction {$languageOpt}{"N"} ; }
1180                if ( ($a >= 45) and ($a < 135) ) { $dir = $direction {$languageOpt}{"E"} ; }
1181                if ( ($a >= 135) and ($a < 225) ) { $dir = $direction {$languageOpt}{"S"} ; }
1182                if ( ($a >= 225) and ($a < 315) ) { $dir = $direction {$languageOpt}{"W"} ; }
1183        }
1184
1185        return $dir ;
1186}
1187
1188
1189sub mergeAllFiles {
1190        my $files ;
1191
1192        $files .= $workDir . "title.pdf" ;
1193        $files .= " " . $workDir . "overview.pdf" ;
1194
1195        if ($atlasOpt eq "") {
1196                $files .= " " . $workDir . "directions.pdf" ;
1197        }
1198
1199        for (my $i = 1; $i <= $mapNumber; $i++) {
1200                my $name ;
1201                $name = " " . $workDir . "detail" . $i . ".pdf" ; 
1202                $files .= $name ;
1203        }
1204
1205        if ( ($poiOpt > 0) or ($streetOpt > 0) ) {
1206                $files .= " " . $workDir . "directory.pdf" ; 
1207        }
1208
1209        print "\nmerge pdfs ($files) into $outFileName and log to $logFileName\n" ;
1210
1211        `pdfjoin --outfile \"$outFileName\" $files >> $logFileName 2>&1` ;
1212
1213}
1214
1215
1216sub createDirections {
1217        print "\ncreating directions...\n" ;
1218
1219        my $stepFileName = "step.txt" ;
1220        open (my $stepFile, ">", $stepFileName) or die ("can't open step output file") ;
1221
1222        my $texFileName ; 
1223        my $ltxFileName ; 
1224        $texFileName = "directions.tex" ;
1225        $ltxFileName = "directionsltx.tex" ;
1226        push @tempFiles, $texFileName ;
1227        push @tempFiles, $stepFileName ;
1228        push @tempFiles, $ltxFileName ;
1229        my %label = () ;
1230        $label{"EN"}{"directions"} = "Directions" ;
1231        $label{"DE"}{"directions"} = "Wegbeschreibung" ;
1232        $label{"EN"}{"number"} = "Nr" ;
1233        $label{"DE"}{"number"} = "Nr" ;
1234        $label{"EN"}{"distance"} = "Distance" ;
1235        $label{"DE"}{"distance"} = "Entfernung" ;
1236        $label{"EN"}{"name"} = "Name" ;
1237        $label{"DE"}{"name"} = "Name" ;
1238        $label{"EN"}{"direction"} = "Direction" ;
1239        $label{"DE"}{"direction"} = "Richtung" ;
1240        $label{"EN"}{"elevation"} = "Elevation" ;
1241        $label{"DE"}{"elevation"} = "Höhe" ;
1242        $label{"EN"}{"info"} = "Information" ;
1243        $label{"DE"}{"info"} = "Informationen" ;
1244        $label{"EN"}{"eleprofile"} = "Elevation profile" ;
1245        $label{"DE"}{"eleprofile"} = "Höhenprofil" ;
1246
1247        open (my $texFile, ">", $texFileName) or die ("can't open tex output file") ;
1248        open (my $ltxFile, ">", $ltxFileName) or die ("can't open tex ltx output file") ;
1249        if ($pageSizeOpt eq "A5") {
1250                print $texFile "\\documentclass[a5paper,12pt]{book}\n" ;
1251        }
1252        else {
1253                print $texFile "\\documentclass[a4paper,12pt]{book}\n" ;
1254        }
1255        print $texFile "\\usepackage[utf8]{inputenc}\n" ;
1256        print $texFile "\\usepackage{longtable}\n" ;
1257        print $texFile "\\usepackage{ltxtable}\n" ;
1258        print $texFile "\\columnsep7mm\n" ;
1259        print $texFile "\\begin{document}\n" ;
1260        print $texFile "\\section*{" .  $label{$languageOpt}{"directions"} . "}\n" ;
1261        print $texFile "\\LTXtable{\\textwidth}{directionsltx}\n" ;
1262
1263        my $elevationDataPresent = 0 ;
1264        for (my $i=0; $i <= $#nodes; $i++) {
1265                if ($nodeInfo{$i}{'ele'} ne "") { $elevationDataPresent = 1 ; }
1266        }
1267
1268        print $ltxFile "\\tiny\n" ;
1269
1270        if ($elevationDataPresent) {
1271                print $ltxFile "\\begin{longtable}{|p{1cm}|p{2cm}|p{1.5cm}|p{3cm}|p{2cm}|p{3cm}|}\n" ;
1272        }
1273        else {
1274                print $ltxFile "\\begin{longtable}{|p{1cm}|p{2cm}|p{3cm}|p{2cm}|p{4.5cm}|}\n" ;
1275        }
1276
1277        print $ltxFile "\\hline\n" ;
1278
1279        if ($elevationDataPresent) {
1280                print $ltxFile "$label{$languageOpt}{'number'} & $label{$languageOpt}{'distance'} & $label{$languageOpt}{'elevation'} & $label{$languageOpt}{'name'} & $label{$languageOpt}{'direction'} & $label{$languageOpt}{'info'} \\\\ \n" ;
1281        }
1282        else {
1283                print $ltxFile "$label{$languageOpt}{'number'} & $label{$languageOpt}{'distance'} & $label{$languageOpt}{'name'} & $label{$languageOpt}{'direction'} & $label{$languageOpt}{'info'} \\\\ \n" ;
1284        }
1285        print $ltxFile "\\hline\n" ;
1286
1287
1288        my %toPrint = () ;
1289        $toPrint{0} = 1 ; 
1290        $toPrint{ $#nodes } = 1 ; 
1291        for (my $i=1; $i<$#nodes; $i++) {
1292                # if ($nodeInfo{$i-1}{"direction"} ne $nodeInfo{$i}{"direction"}) { $toPrint{$i} = 1 ; }
1293
1294                # if ($nodeInfo{$i}{"dirs"} > 2) { $toPrint{$i} = 1 ; } #0.92
1295                if ( ($nodeInfo{$i}{"dirs"} > 2) and ( dirChange ($nodeInfo{$i-1}{"angle"}, $nodeInfo{$i}{"angle"}) > $lessStepsOpt) ) { $toPrint{$i} = 1 ; } #0.92
1296
1297                if ($nodeInfo{$i-1}{"name"} ne $nodeInfo{$i}{"name"}) { $toPrint{$i} = 1 ; }
1298                if ($nodeInfo{$i}{"ele"} ne "") { $toPrint{$i} = 1 ; }
1299                if ( defined $nodeInfo{$i}{"information"} ) { $toPrint{$i} = 1 ; }
1300        }
1301
1302        # prepare information
1303        my %info = () ;
1304        for (my $i=0; $i <= $#nodes; $i++) {
1305                $info{$i} = "" ;
1306                if (defined $nodeInfo{$i}{'information'} ) {
1307                        my @a = () ; 
1308                        @a = @{$nodeInfo{$i}{'information'}} ;
1309                        my $t ; 
1310                        my $first = 1 ;
1311                        foreach my $e (@a) {
1312                                if ($first) { $first = 0 ; } else { $t .= " * " ; }
1313                                $t .= $e  ;
1314                        }
1315                        $info{$i} = $t ;
1316                }
1317        }
1318
1319        my $lastDist = 0 ;
1320        my $line = 0 ;
1321        for (my $i=0; $i <= $#nodes; $i++) {
1322                if (defined $toPrint{$i}) {
1323                        $line++ ;
1324                        my $stepDist = $nodeInfo{$i}{"distance"} - $lastDist ;
1325                        $stepDist = int ($stepDist * 100) / 100 ;
1326
1327                        if (defined $stepInformation{$line}) {
1328                                if ($info{$i} eq "") {
1329                                        $info{$i} = $stepInformation{$line} ;
1330                                }
1331                                else {
1332                                        $info{$i} .= " * " . $stepInformation{$line} ;
1333                                } 
1334                        }
1335
1336
1337                        if ($elevationDataPresent) {
1338                                print $ltxFile "$line & " . $nodeInfo{$i}{"distance"} . " ($stepDist)" . " & " . $nodeInfo{$i}{"ele"} . " & " . $nodeInfo{$i}{"name"} . " & " . $nodeInfo{$i}{"direction"} . " & " . $info{$i} . "\\\\\n" ;
1339                        }
1340                        else {
1341                                print $ltxFile "$line & " . $nodeInfo{$i}{"distance"} . " ($stepDist)" . " & " . $nodeInfo{$i}{"name"} . " & " . $nodeInfo{$i}{"direction"} . " & " . $info{$i} . "\\\\\n" ;
1342                        }
1343
1344                        print $ltxFile "\\hline\n" ;
1345                        $lastDist = $nodeInfo{$i}{"distance"} ;
1346
1347                        if ($stepSizeOpt > 0) {
1348                                print $stepFile $lon{ $nodes[$i] } . " " ;
1349                                print $stepFile $lat{ $nodes[$i] } . " " ;
1350                                print $stepFile "$stepSizeOpt " ;
1351                                print $stepFile "\"$stepColorOpt\" " ;
1352                                print $stepFile "\"$line\" " ;
1353                                print $stepFile "$stepFontSizeOpt" ;
1354                                print $stepFile "\n" ;
1355                        }
1356                }               
1357        }
1358
1359        print $ltxFile "\\end{longtable}\n" ;
1360
1361
1362        my $countEle = 0 ; my $eleMin = 999 ; my $eleMax = -999 ;
1363        for (my $i=0; $i<=$#nodes; $i++) {
1364                if ($nodeInfo{$i}{'ele'} ne "") { 
1365                        $countEle++ ; 
1366                        if ($nodeInfo{$i}{'ele'} > $eleMax) { $eleMax = $nodeInfo{$i}{'ele'} ; }
1367                        if ($nodeInfo{$i}{'ele'} < $eleMin) { $eleMin = $nodeInfo{$i}{'ele'} ; }
1368                }
1369        }
1370
1371        foreach my $d (keys %contourData) {
1372                $countEle++ ; 
1373                if ($contourData{$d} > $eleMax) { $eleMax = $contourData{$d} ; }
1374                if ($contourData{$d} < $eleMin) { $eleMin = $contourData{$d} ; }
1375
1376        }
1377
1378        if ($countEle >= 2) {
1379
1380                my $picWidth = 110 ;
1381                my $xOffset = 10 ;
1382                my $yOffset = 10 ;
1383               
1384                print $texFile "\\section*{" .  $label{$languageOpt}{"eleprofile"} . "}\n" ;
1385                print $texFile "\\setlength{\\unitlength}{1mm}\n" ;
1386                my $height = int ( ($eleMax - $eleMin) / 10 ) ;
1387                my $lh = $height + 10 ;
1388                print $texFile "\\begin{picture} ($picWidth,$lh)\n" ;
1389
1390                my $width = 0 ;
1391                foreach my $d (1, 2, 3, 5, 7, 10, 15, 20, 25, 30, 35, 40, 45, 50, 75, 100, 150, 200, 300, 500, 750, 1000) {
1392                        if ($d > $segmentLength) {
1393                                $width = $d ;
1394                                last ;
1395                        } 
1396                }
1397                my $tx = $picWidth-$xOffset ;
1398
1399                print $texFile "\\put($xOffset,$yOffset){\\line($picWidth,0){$tx}}\n" ;
1400                print $texFile "\\put($xOffset,$lh){\\line($picWidth,0){$tx}}\n" ;
1401
1402                print $texFile "\\put($xOffset,$yOffset){\\line(0,$height){$height}}\n" ;
1403                print $texFile "\\put($picWidth,$yOffset){\\line(0,$height){$height}}\n" ;
1404
1405                my $h1 = int ($eleMin) ;
1406                my $h2 = int ($eleMax) ;
1407                my $pos2 = $height + $yOffset ;
1408                my $ty = $yOffset + 2 ;
1409                print $texFile "\\put(0,$ty){\\tiny $h1 m}\n" ;
1410                print $texFile "\\put(0,$pos2){\\tiny $h2 m}\n" ;
1411                $tx = $picWidth-$xOffset ;
1412                print $texFile "\\put($tx,2){\\tiny $width km}\n" ;
1413
1414
1415                for (my $i=0; $i<=$#nodes; $i++) {
1416                        if ($nodeInfo{$i}{"ele"} ne "") {
1417                                my $x = int ($nodeInfo{$i}{"distance"} / $width * ($picWidth - $xOffset)) + $xOffset ;
1418                                my $y = ($nodeInfo{$i}{"ele"} - $eleMin) / 10 + $yOffset ;
1419                                print $texFile "\\put($x,$y){\\circle*{1}}\n" ;
1420                        }
1421                }
1422
1423                foreach my $d (keys %contourData) {
1424                        my $x = int ($d / $width * ($picWidth - $xOffset)) + $xOffset ;
1425                        my $y = ($contourData{$d} - $eleMin) / 10 + $yOffset ;
1426                        print $texFile "\\put($x,$y){\\circle*{1}}\n" ;
1427                }
1428
1429                print $texFile "\\end{picture}\n" ;
1430        }
1431
1432
1433        print $texFile "\\end{document}\n" ;
1434        close ($texFile) ;
1435        close ($ltxFile) ;
1436
1437        close ($stepFile) ;
1438
1439        my $dviFileName = $texFileName ;
1440        $dviFileName =~ s/.tex/.dvi/ ;
1441        my $psFileName = $texFileName ;
1442        $psFileName =~ s/.tex/.ps/ ;
1443        my $pdfFileName = "directions.pdf" ;
1444
1445        push @tempFiles, $pdfFileName ;
1446
1447        print "call latex, dvips and ps2pdf and log to $logFileName\n" ;
1448        `latex $texFileName >> $logFileName 2>&1` ;
1449        `latex $texFileName >> $logFileName 2>&1` ;
1450        `dvips -D600 $dviFileName -o >> $logFileName 2>&1` ;
1451        `ps2pdf $psFileName $pdfFileName >> $logFileName 2>&1` ;
1452        `rm *.dvi` ;
1453        # `rm *.tex` ;
1454        `rm *.ps` ;
1455        `rm *.aux` ;
1456        `rm *.log` ;
1457        my $target = $workDir . "directions.pdf" ;
1458        # `mv directions.pdf $target` ;
1459        print "done\n" ;
1460}
1461
1462sub createTitlePage {
1463
1464        my %heading = () ;
1465        $heading{"EN"} = "Disclaimer" ;
1466        $heading{"DE"} = "Haftungsauschluss" ;
1467        my %heading2 = () ;
1468        $heading2{"EN"} = "Tour description" ;
1469        $heading2{"DE"} = "Tourenbeschreibung" ;
1470        my %heading3 = () ;
1471        $heading3{"EN"} = "Basic route data" ;
1472        $heading3{"DE"} = "Basisroutendaten" ;
1473        my %disclaimer = () ;
1474        $disclaimer{"EN"} = << "END1" ;
1475The user of this book is always responsible for all his steps and actions.
1476The authors of this documentation are not responsible for the correctness and completeness of the data.
1477Data is derived from openstreetmap and is licensed by CC-BY-SA.
1478END1
1479        $disclaimer{"DE"} = << "END2" ;
1480Der Nutzer dieses Werkes ist stets selbst für seine Schritte und Aktionen ver\\-antwortlich.
1481Die Ersteller dieser Dokumentation übernehmen keine Garantie für Richtigkeit und Vollständigkeit selbiger.
1482Die Daten stammen von openstreetmap und stehen unter der CC-BY-SA Lizenz.
1483END2
1484
1485       
1486        print "create title page...\n" ;
1487        my $texFileName ; 
1488        $texFileName = "title.tex" ;
1489
1490        push @tempFiles, $texFileName ;
1491
1492        open (my $texFile, ">", $texFileName) or die ("can't open tex output file") ;
1493
1494        if ($pageSizeOpt eq "A5") {
1495                print $texFile "\\documentclass[a5paper,12pt]{book}\n" ;
1496        }
1497        else {
1498                print $texFile "\\documentclass[a4paper,12pt]{book}\n" ;
1499        }
1500
1501        print $texFile "\\usepackage[utf8]{inputenc}\n" ;
1502        print $texFile "\\begin{document}\n" ;
1503
1504
1505        #
1506        # title
1507        #
1508
1509        print $texFile "\\thispagestyle{empty}\n" ;
1510        print $texFile "\\vspace*{8cm}\n" ;
1511        print $texFile "\\Huge\n" ;
1512        $title = sanitizeLatexString ($title) ;
1513        print $texFile "$title \\par\n" ;
1514        # print $texFile "\\newline\n" ;
1515        print $texFile "\\vspace*{2cm}\n" ;
1516        print $texFile "\\normalsize\n" ;
1517        my %created = () ;
1518        $created{"EN"} = "created with hikingbook.pl" ;
1519        $created{"DE"} = "erstellt mit hikingbook.pl" ;
1520        print $texFile "$created{$languageOpt}\n" ;
1521
1522
1523        #
1524        # description
1525        #
1526
1527        if ($descName ne "") {
1528                print $texFile "\\newpage\n" ;
1529                print "\nreading description file...\n" ;
1530                open (my $file, "<", $descName) or die ("ERROR: could not open description file $descName\n") ;
1531                        print $texFile "\\section*{$heading2{$languageOpt}}\n" ;
1532                        my $line = "" ; my $c = 0 ;
1533                        while ($line = <$file>) {
1534                                print $texFile $line ;
1535                                $c++ ;
1536                        }
1537                close ($file) ; 
1538                print "done. $c lines read.\n" ;
1539        }
1540
1541
1542
1543        #
1544        # basic relation data
1545        #
1546
1547        print $texFile "\\newpage\n" ;
1548        print $texFile "\\thispagestyle{empty}\n" ;
1549
1550        if ($atlasOpt eq "") {
1551                print $texFile "\\section*{$heading3{$languageOpt}}\n" ;
1552                my %tags = () ;
1553                foreach my $t (@relationTags) {
1554                        my $temp = $t->[1] ;
1555                        $temp = sanitizeLatexString ($temp) ;
1556                        $temp = convertHTML ($temp) ; 
1557                        $tags{ $t->[0] } = $temp ; 
1558                }
1559                print $texFile "\\begin{tabular}{|p{4cm}|p{10cm}|}\n" ;
1560                print $texFile "\\hline\n" ;
1561                print $texFile "Key & Value \\\\ \n" ;
1562                print $texFile "\\hline\n" ;
1563                foreach my $t (sort keys %tags) {
1564                        print $texFile "$t & $tags{$t} \\\\ \n" ;
1565                        print $texFile "\\hline\n" ;
1566                }
1567                print $texFile "\\end{tabular}\n" ;
1568        }
1569
1570
1571        #
1572        # disclaimer
1573        #
1574
1575        print $texFile "\\section*{$heading{$languageOpt}}\n" ;
1576        print $texFile "$disclaimer{$languageOpt}\n" ;
1577       
1578
1579        print $texFile "\\end{document}\n" ;
1580        close ($texFile) ;
1581
1582        my $dviFileName = $texFileName ;
1583        $dviFileName =~ s/.tex/.dvi/ ;
1584        my $psFileName = $texFileName ;
1585        $psFileName =~ s/.tex/.ps/ ;
1586        my $pdfFileName = "title.pdf" ;
1587
1588        push @tempFiles, $pdfFileName ;
1589
1590        print "call latex, dvips and ps2pdf and log to $logFileName\n" ;
1591        `latex $texFileName >> $logFileName 2>&1` ;
1592        `latex $texFileName >> $logFileName 2>&1` ;
1593        `dvips -D600 $dviFileName -o >> $logFileName 2>&1` ;
1594        `ps2pdf $psFileName $pdfFileName >> $logFileName 2>&1` ;
1595        `rm *.dvi` ;
1596        # `rm *.tex` ;
1597        `rm *.ps` ;
1598        `rm *.aux` ;
1599        `rm *.log` ;
1600        my $target = $workDir . "title.pdf" ;
1601        print "done.\n" ;
1602}
1603
1604
1605sub getProgramOptions {
1606        my $helpOpt = 0 ;
1607        my $optResult = GetOptions (    "in=s"          => \$inFileName,
1608                                        "out=s"         => \$outFileName,               # output file
1609                                        "detailstyle=s" => \$detailStyleFileName,
1610                                        "overviewstyle=s"       => \$overviewStyleFileName,
1611                                        "title=s"       => \$title,
1612                                        "language=s"    => \$languageOpt,
1613                                        "pagesize=s"    => \$pageSizeOpt,
1614                                        "relation=i"    => \$relationId,
1615                                        "atlas=s"       => \$atlasOpt,
1616                                        "name=s"        => \$relationName,
1617                                        "desc=s"        => \$descName,
1618                                        "steps=s"       => \$stepDescName,
1619                                        "ref=s" => \$relationRef,
1620                                        "overlap=i"     => \$overlapOpt,
1621                                        "dirnumber=i"   => \$dirNumberOpt,
1622                                        "lesssteps=i"   => \$lessStepsOpt,
1623                                        "poi=i"         => \$poiOpt,
1624                                        "street=i"              => \$streetOpt,
1625                                        "scale=i"       => \$scale,
1626                                        "stepsize=i"            => \$stepSizeOpt,
1627                                        "stepcolor=s"           => \$stepColorOpt,
1628                                        "stepfontsize=i"        => \$stepFontSizeOpt,
1629                                        "pnsizeoverview=i"      => \$pnSizeOverview,
1630                                        "pnsizedetail=i"        => \$pnSizeDetail,
1631                                        "landscape"     => \$landscapeOpt,
1632                                        "reverse"       => \$reverseOpt,
1633                                        "autorotate"    => \$autorotateOpt,
1634                                        "nodelete"      => \$noDeleteOpt,
1635                                        "roundtrip"     => \$roundtripOpt,
1636                                        "help"          => \$helpOpt,
1637                                        "verbose"       => \$verboseOpt ) ;
1638
1639        if ( (uc $languageOpt) eq "DE") { 
1640                $languageOpt = "DE" ;
1641        }
1642        else {
1643                $languageOpt = "EN" ;
1644        }
1645        if ( (uc $pageSizeOpt) eq "A5") { 
1646                $pageSizeOpt = "A5" ;
1647        }
1648        else {
1649                $pageSizeOpt = "A4" ;
1650        }
1651
1652        if ($landscapeOpt eq "1") {
1653                foreach my $f (keys %pageHeight) {
1654                        my $temp = $pageHeight{$f} ;
1655                        $pageHeight{$f} = $pageWidth{$f} ;
1656                        $pageWidth{$f} = $temp ;
1657                }
1658        }
1659
1660        if ($helpOpt eq "1") {
1661                usage() ;
1662                die() ;
1663        }
1664}
1665
1666sub usage {
1667        print "$programName version $version\n" ;
1668        print "-in=<infile.osm>\n" ;
1669        print "-out=<outfile.pdf>\n" ;
1670        print "-relation=<relation id>\n" ;
1671        print "-name=<relation name>\n" ;
1672        print "-ref=<relation ref>\n" ;
1673        print "-atlas=FLOAT,FLOAT,FLOAT,FLOAT (create street atlas for bounding box)\n" ;
1674        print "-detailstyle=<mapgen rules file for detail maps>\n" ;
1675        print "-overviewstyle=<mapgen rules file for overview maps>\n" ;
1676        print "-scale=<integer> (scale for detail maps); default = 10000\n\n" ;
1677
1678        print "-language=EN|DE\n" ;
1679        print "-title=\"title text\" (for title page)\n" ;
1680        print "-desc=<tex file> (for long text after title page; tex format, max heading subsection\n" ;
1681        print "-steps=<step description file> (for descriptions of single steps or nodes; format: stepNr<space>TEXT)\n" ;
1682        print "-poi=<integer> (add poi directory to description, specify column number like 1,2,3)\n" ;
1683        print "-street=<integer> (add street directory to description, specify column number like 1,2,3)\n" ;
1684        print "-dirnumber=4|8 (4 or 8 different directions like N, S, E, W...); default=8\n" ;
1685        print "-lesssteps=INTEGER (reduce number of steps in description, step only if direction change > integer degrees)\n" ;
1686        print "-stepsize=INTEGER (size of step disc in map; 0 will suppress discs and labels)\n" ;
1687        print "-stepcolor=TEXT (color of step disc in map)\n" ;
1688        print "-stepfontsize=INTEGER (size of label for step disc in map)\n" ;
1689        print "\n" ;
1690
1691        print "-pagesize=A4|A5\n" ;
1692        print "-overlap=<percent> (10 for 10\% overlap on each side; default=5)\n" ;
1693        print "-pnsizeoverview=INTEGER (size of page numbers in overview map)\n" ;
1694        print "-pnsizedetail=INTEGER (size of page numbers in detail maps)\n" ;
1695        print "-landscape\n" ;
1696        print "-autorotate (rotate paper format automatically)\n" ;
1697        print "\n" ;
1698
1699        print "-reverse (reverse direction of relation/route)\n" ;
1700        print "-roundtrip (force route to begin/end with first way in relation)\n" ;
1701        print "\n" ;
1702
1703        print "-verbose\n" ;
1704        print "-nodelete (temp files will not be deleted)\n" ;
1705        print "-help\n" ;
1706}
1707
1708
1709sub addPois {
1710        print "\nadding POIs to description...\n" ;
1711        foreach my $p (@poiList) {
1712                my $minDist = 999 ;
1713                my $nodeNumber = -1 ;
1714                my $dir = "" ;
1715                for (my $i = 0; $i <= $#nodes; $i++) {
1716                        my $dist = distance ( $lon {$p->[2]}, $lat {$p->[2]}, $lon{ $nodes[$i] }, $lat{ $nodes[$i] }) ;
1717                        if ($dist < $minDist) {
1718                                $minDist = $dist ;
1719                                $nodeNumber = $i ;
1720                                $dir = direction ( $nodes[$i], $p->[2] ) ;
1721                        }
1722                }
1723                if ($minDist < $p->[3]) {
1724                        my $info = $p->[0] ; my $name = $p->[1] ;
1725                        $minDist = int ($minDist * 100) / 100 ;
1726                        push @{$nodeInfo{$nodeNumber}{"information"}}, "$info $name ($dir $minDist)" ;
1727                }
1728        }
1729}
1730
1731sub getPoiFiledata {
1732        print "\nreading poi file...\n" ;
1733        my $result = open (my $file, "<", $poiFileName) ;
1734        if ($result) {
1735                my $line = "" ;
1736                my $count = 0 ;
1737                while ($line = <$file>) {
1738                        my ($k, $v, $d, $en, $de) = ( $line =~ /(.+),(.+),(.+),(.+),(.+)/ ) ;
1739                        if ( (defined $k) and (defined $v) and (defined $d) and (defined $en) and (defined $de) ) {
1740                                $count++ ;
1741                                push @pois, [$k, $v, $d, $en, $de] ;
1742                                if ($verboseOpt eq "1") { print "POI $k=$v read from file.\n" ; }
1743                        }
1744                }
1745                close ($file) ;
1746                print "$count pois read.\n" ;
1747        }
1748        else {
1749                print "WARNING: poi file $poiFileName could not be opened!\n" ;
1750        }
1751}
1752
1753sub getStepInformation {
1754        if ($stepDescName ne "") {
1755                print "\nreading step information file...\n" ;
1756                open (my $file, "<", $stepDescName) or die ("ERROR: step information file $stepDescName could not be opened!\n") ;
1757                my $line = "" ; my $c = 0 ;
1758                while ($line = <$file>) {
1759                        my ($nr, $text) = ($line =~ /([\d\-]+)\s(.+)/ ) ;
1760                        if ( (defined $nr) and (defined $text) ) {
1761                                $c++ ;
1762                                $stepInformation{$nr} = $text ;
1763                                if ($verboseOpt eq "1") {
1764                                        print "$nr $text\n" ;
1765                                }
1766                        }
1767                        else {
1768                                print "problem reading line from step information file:\n$line\n" ;
1769                        }
1770                }
1771                close ($file) ;
1772                print "done. $c lines read.\n" ;
1773        }
1774}
1775
1776
1777
1778
1779sub createDirectory {
1780
1781        if ( ($poiOpt > 0) or ($streetOpt > 0) ) {
1782
1783                if ($poiOpt < 1) { $poiOpt = 1 ; } 
1784                if ($poiOpt > 3) { $poiOpt = 3 ; } 
1785                if ($streetOpt < 1) { $streetOpt = 1 ; } 
1786                if ($streetOpt > 3) { $streetOpt = 3 ; } 
1787                $poiOpt = int $poiOpt ;
1788                $streetOpt = int $streetOpt ;
1789
1790                print "create directory...\n" ;
1791                my $texFileName ; 
1792                $texFileName = "directory.tex" ;
1793
1794                push @tempFiles, $texFileName ;
1795
1796                open (my $texFile, ">", $texFileName) or die ("can't open tex output file") ;
1797
1798                if ($pageSizeOpt eq "A5") {
1799                        print $texFile "\\documentclass[a5paper,12pt]{book}\n" ;
1800                }
1801                else {
1802                        print $texFile "\\documentclass[a4paper,12pt]{book}\n" ;
1803                }
1804
1805                print $texFile "\\usepackage[utf8]{inputenc}\n" ;
1806                print $texFile "\\usepackage{multicol}\n" ;
1807                print $texFile "\\begin{document}\n" ;
1808
1809                if ($poiOpt > 0) {
1810                        print $texFile "\\thispagestyle{empty}\n" ;
1811
1812                        my %heading3 = () ;
1813                        $heading3{"EN"} = "Points of interest" ;
1814                        $heading3{"DE"} = "Interessante Punkte" ;
1815
1816                        if ($poiOpt > 1) {
1817                                print $texFile "\\begin{multicols}{$poiOpt}[\\section*{$heading3{$languageOpt}}]\n" ;
1818                        }
1819                        else {
1820                                print $texFile "\\section*{$heading3{$languageOpt}}\n" ;
1821                        }
1822                        print $texFile "\\tiny\n" ;
1823
1824                        foreach my $poi (sort keys %pois) {
1825                                my $sqText = "" ; my $first = 1 ;
1826                                foreach my $sq ( @{$pois{$poi}} ) {
1827                                        if ($first) {
1828                                                $first = 0 ;
1829                                                $sqText .= $sq ;
1830                                        }
1831                                        else {
1832                                                $sqText .= " " ;
1833                                                $sqText .= $sq ;
1834                                        }
1835                                }
1836                                $poi = sanitizeLatexString ($poi) ;
1837                                print $texFile $poi ;
1838                                print $texFile " \\dotfill " ;
1839                                print $texFile $sqText, "\\\\\n" ;
1840                        }
1841
1842                        if ($poiOpt > 1) {
1843                                print $texFile "\\end{multicols}\n" ;
1844                        }
1845                        print $texFile "\\normalsize\n" ;
1846                } # poiOpt > 0
1847       
1848                if ($streetOpt > 0) {
1849                        print $texFile "\\thispagestyle{empty}\n" ;
1850
1851                        my %heading4 = () ;
1852                        $heading4{"EN"} = "Street Directory" ;
1853                        $heading4{"DE"} = "Straßenverzeichnis" ; 
1854
1855                        if ($streetOpt > 1) {
1856                                print $texFile "\\begin{multicols}{$streetOpt}[\\section*{$heading4{$languageOpt}}]\n" ;
1857                        }
1858                        else {
1859                                print $texFile "\\section*{$heading4{$languageOpt}}\n" ;
1860                        }
1861                        print $texFile "\\tiny\n" ;
1862
1863                        foreach my $street (sort keys %streets) {
1864                                my $sqText = "" ; my $first = 1 ;
1865                                foreach my $sq ( @{$streets{$street}} ) {
1866                                        if ($first) {
1867                                                $first = 0 ;
1868                                                $sqText .= $sq ;
1869                                        }
1870                                        else {
1871                                                $sqText .= " " ;
1872                                                $sqText .= $sq ;
1873                                        }
1874                                }
1875                                $street = sanitizeLatexString ($street) ;
1876                                print $texFile $street ;
1877                                print $texFile " \\dotfill " ;
1878                                print $texFile $sqText, "\\\\\n" ;
1879                        }
1880
1881                        if ($streetOpt > 1) {
1882                                print $texFile "\\end{multicols}\n" ;
1883                        }
1884                        print $texFile "\\normalsize\n" ;
1885                } # streetOpt > 0
1886       
1887
1888                print $texFile "\\end{document}\n" ;
1889                close ($texFile) ;
1890
1891                my $dviFileName = $texFileName ;
1892                $dviFileName =~ s/.tex/.dvi/ ;
1893                my $psFileName = $texFileName ;
1894                $psFileName =~ s/.tex/.ps/ ;
1895                my $pdfFileName = "directory.pdf" ;
1896
1897                push @tempFiles, $pdfFileName ;
1898
1899                print "call latex, dvips and ps2pdf and log to $logFileName\n" ;
1900                `latex $texFileName >> $logFileName 2>&1` ;
1901                `latex $texFileName >> $logFileName 2>&1` ;
1902                `dvips -D600 $dviFileName -o >> $logFileName 2>&1` ;
1903                `ps2pdf $psFileName $pdfFileName >> $logFileName 2>&1` ;
1904                `rm *.dvi` ;
1905                `rm *.ps` ;
1906                `rm *.aux` ;
1907                `rm *.log` ;
1908                print "done.\n" ;
1909
1910        }
1911}
1912
1913
1914sub convertHTML {
1915        my $line = shift ;
1916
1917        ($line) = ($line =~ /^(.*)$/ ) ;
1918
1919        $line =~ s/\&apos;/\'/g ;
1920        $line =~ s/\&quot;/\'/g ;
1921
1922        return $line ;
1923}
1924
1925sub dirChange {
1926        my ($a, $b) = @_ ;
1927
1928        my $c1 = abs ($a - $b) ;
1929        my $c2 = 360 - max ($a, $b) + min ($a, $b) ;
1930
1931        my $c3 = min ($c1, $c2) ;
1932        return $c3 ;
1933}
1934
1935
1936sub min {
1937        my ($a, $b) = @_ ;
1938        if ($a < $b) {
1939                return $a ;
1940        }
1941        else {
1942                return $b ;
1943        }
1944}
1945
1946sub max {
1947        my ($a, $b) = @_ ;
1948        if ($a > $b) {
1949                return $a ;
1950        }
1951        else {
1952                return $b ;
1953        }
1954}
1955
1956sub initializeLatex {
1957
1958        $replaceLatex{'_'} = '\\_' ;   
1959        $replaceLatex{'&'} = '\\&' ;   
1960        $replaceLatex{'$'} = '\\$' ;   
1961        $replaceLatex{'%'} = '\\%' ;   
1962        $replaceLatex{'{'} = '\\{' ;   
1963        $replaceLatex{'}'} = '\\}' ;   
1964        $replaceLatex{'#'} = '\\#' ;   
1965
1966        foreach my $c (0..9) {
1967                $validLatex{$c} = 1 ;
1968        }
1969        foreach my $c ("a".."z") {
1970                $validLatex{$c} = 1 ;
1971        }
1972        foreach my $c ("A".."Z") {
1973                $validLatex{$c} = 1 ;
1974        }
1975        foreach my $c ( qw (! + * - : . ; § / = ?) ) {
1976                $validLatex{$c} = 1 ;
1977        }
1978        foreach my $c ( ' ', '"', "\'", '(', ')', '[', ']', ',' ) {
1979                $validLatex{$c} = 1 ;
1980        }
1981}
1982
1983sub sanitizeLatexString {
1984        my $text = shift ;
1985
1986        my $out = "" ;
1987        my @chars ;
1988        @chars = split //, $text ;
1989
1990        for (my $i=0; $i<=$#chars; $i++) {
1991                my $c = $chars[$i] ;
1992                # print "$c ", ord ($c), "\n" ;
1993                if (defined $validLatex{$c}) {
1994                        $out .= $c ;
1995                }
1996                elsif (defined $replaceLatex{$c}) {
1997                        $out .= $replaceLatex{$c} ;
1998                }
1999                else {
2000                        if ( ($i < $#chars) and ($c eq chr (195)) ) {
2001                                my $found = 0 ;
2002                                foreach my $c2 (164, 182, 188, 132, 150, 156, 159) {
2003                                        if ($chars[$i+1] eq chr($c2)) {
2004                                                $found = 1 ;
2005                                        }
2006                                }
2007                                if ($found) {
2008                                        $out .= $c . $chars[$i+1] ;
2009                                        $i++ ;
2010                                }
2011                        }
2012                }
2013        } 
2014        return $out ;
2015}
2016
2017
2018sub compileElevationData {
2019        print "evaluating contour data...\n" ;
2020
2021        foreach my $wayId (keys %contourWays) {
2022
2023                my ($x1, $x2, $y1, $y2) = getArea ( @{$wayNodesHash{$wayId}} );
2024
2025                $qt->add ($wayId, $x1, $y1, $x2, $y2) ;
2026        }
2027
2028
2029        my $count = 0 ;
2030        for (my $a = 0; $a < $#nodes; $a++) { #way 1
2031                # print "a = $a\n" ;
2032
2033                my $ref = $qt->getEnclosedObjects (     min( $lon{$nodes[$a]}, $lon{$nodes[$a+1]}),
2034                                                        min( $lat{$nodes[$a]}, $lat{$nodes[$a+1]}),
2035                                                        max( $lon{$nodes[$a]}, $lon{$nodes[$a+1]}),
2036                                                        max( $lat{$nodes[$a]}, $lat{$nodes[$a+1]}) ) ;
2037                my @temp = @$ref ;
2038
2039                foreach my $cw ( @temp ) { #way 2
2040                # foreach my $cw (keys %contourWays) { #way 2
2041                        for ($b=0; $b<$#{$wayNodesHash{$cw}}; $b++) {
2042                                # print "cw= $cw\n" ;
2043                                # print "b = $b\n" ;
2044                                my ($x, $y) = crossing ($lon{ $nodes[$a] }, 
2045                                                $lat{ $nodes[$a] }, 
2046                                                $lon{ $nodes[$a+1] }, 
2047                                                $lat{ $nodes[$a+1] }, 
2048                                                $lon{$wayNodesHash{$cw}[$b]}, 
2049                                                $lat{$wayNodesHash{$cw}[$b]}, 
2050                                                $lon{$wayNodesHash{$cw}[$b+1]}, 
2051                                                $lat{$wayNodesHash{$cw}[$b+1]}) ;
2052                                if (($x != 0) and ($y != 0)) {
2053                                        $count ++ ;
2054                                        my $dist = $nodeInfo{$a}{"distance"} + distance ($lon{$nodes[$a]}, $lat{$nodes[$a]}, $x, $y) ;
2055                                        $contourData{$dist} = $contourWays { $cw } ;
2056                                        if ($verboseOpt eq "1") {
2057                                                print "contour intersection found: ($x, $y), $dist, $contourWays{$cw}\n" ;
2058                                        }
2059                                }
2060                        }
2061                }
2062        }
2063        print "done. $count intersections found.\n" ;
2064}
2065
2066
2067sub getArea {
2068        my @nodes = @_ ;
2069
2070        my $minLon = 999 ;
2071        my $maxLon = -999 ;
2072        my $minLat = 999 ;
2073        my $maxLat = -999 ;
2074
2075
2076        foreach my $node (@nodes) {
2077                if ($lon{$node} > $maxLon) { $maxLon = $lon{$node} ; }
2078                if ($lon{$node} < $minLon) { $minLon = $lon{$node} ; }
2079                if ($lat{$node} > $maxLat) { $maxLat = $lat{$node} ; }
2080                if ($lat{$node} < $minLat) { $minLat = $lat{$node} ; }
2081        }       
2082        return ($minLon, $maxLon, $minLat, $maxLat) ;
2083}
2084
2085
2086sub getMinMax {
2087        my $fileName = shift ;
2088        # store min / max of temp file
2089        openOsmFile ($fileName) ;
2090        print "reading temp file nodes...\n" ;
2091
2092        my $file2LonMax = -999 ;
2093        my $file2LonMin = 999 ;
2094        my $file2LatMax = -999 ;
2095        my $file2LatMin = 999 ;
2096        my $propRef ; my $tagsRef ;
2097        ($propRef, $tagsRef) = getNode3() ;
2098        while (defined $propRef) {
2099                if ( $$propRef{"lon"} > $file2LonMax ) { $file2LonMax = $$propRef{"lon"} ; }
2100
2101                if ( $$propRef{"lon"} < $file2LonMin ) { $file2LonMin = $$propRef{"lon"} ; }
2102                if ( $$propRef{"lat"} > $file2LatMax ) { $file2LatMax = $$propRef{"lat"} ; }
2103                if ( $$propRef{"lat"} < $file2LatMin ) { $file2LatMin = $$propRef{"lat"} ; }
2104
2105                ($propRef, $tagsRef) = getNode3() ;
2106        }
2107        closeOsmFile() ;
2108        print "done.\n" ;
2109        return ($file2LonMin, $file2LatMin, $file2LonMax, $file2LatMax) ;
2110}
2111
2112
2113sub loadExternalFiles {
2114        my $outName = shift ;
2115        my $poiName = $outName ;
2116        if ($poiOpt > 0) {
2117                $poiName =~ s/\.svg/\_pois\.txt/ ;
2118                open (my $file, "<", $poiName) or die ("ERRROR: could not open poi file name $poiName\n") ;
2119
2120                my $line = "" ;
2121                while ($line = <$file>) {
2122                        # print "POI line read : $line" ;
2123                        my ($poi, $fields) = ( $line =~ /(.+)\t(.*)/ ) ;
2124                        if ( (defined $poi) and (defined $fields) ) {
2125                                my @f = split / /, $fields ;
2126                                foreach my $sq (@f) {
2127                                        $poi = convertHTML ($poi) ;
2128
2129                                        # translation German
2130                                        if ($languageOpt ne "EN") {
2131                                                foreach my $k (keys %{ $translations{$languageOpt} } ) {
2132                                                        my $v = $translations{$languageOpt}{$k} ;
2133                                                        $poi =~ s/\($k\)/\($v\)/gi ;
2134                                                }
2135                                        }
2136
2137                                        $poi =~ s/\_/ /g ;
2138                                        push @{$pois{$poi}}, $mapNumber . "-" . $sq ;
2139                                }
2140                        }
2141                }
2142                close ($file) ;
2143                push @tempFiles, $poiName ;
2144        }
2145
2146        my $streetName = $outName ;
2147        if ($streetOpt > 0) {
2148                $streetName =~ s/\.svg/\_streets\.txt/ ;
2149                open (my $file, "<", $streetName) or die ("ERRROR: could not open street file name $streetName\n") ;
2150                my $line = "" ;
2151                while ($line = <$file>) {
2152                        # print "STREET line read : $line" ;
2153                        my ($street, $fields) = ( $line =~ /(.+)\t(.*)/ ) ;
2154                        if ( (defined $street) and (defined $fields) ) {
2155                                my @f = split / /, $fields ;
2156                                foreach my $sq (@f) {
2157                                        $street = convertHTML ($street) ;
2158                                        push @{$streets{$street}}, $mapNumber . "-" . $sq ;
2159                                }
2160                        }
2161                }
2162                close ($file) ;
2163                push @tempFiles, $streetName ;
2164        }
2165
2166}
Note: See TracBrowser for help on using the repository browser.