source: subversion/applications/utils/gary68/checkcross.pl

Last change on this file was 25026, checked in by gary68, 9 years ago

new checkcross version, sorted output

File size: 17.7 KB
Line 
1#
2#
3# checkcross.pl by gary68
4#
5# this program checks an osm file for crossing ways which don't share a common node at the intersection and are on the same layer
6#
7#
8# Copyright (C) 2008, Gerhard Schwanz
9#
10# This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the
11# Free Software Foundation; either version 3 of the License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>
17#
18#
19# example definition file:
20# (IMPORTANT: don't enter a tag in both sections!)
21#
22#<XML>
23#  <k="check" v="highway:motorway">
24#  <k="check" v="highway:motorway_link">
25#  <k="check" v="highway:trunk">
26#  <k="check" v="highway:trunk_link">
27#  <k="against" v="highway:primary">
28#  <k="against" v="highway:primary_link">
29#  <k="against" v="highway:secondary">
30#  <k="against" v="highway:tertiary">
31#  <k="against" v="junction:roundabout">
32#</XML>
33#
34# Version 1.0
35#
36# Version 1.1
37# - don't consider short oneways (false positives in large intersections)
38#
39# Version 1.2
40# - stat
41#
42# Version 1.3
43# - stat 2
44#
45# Version 1.4
46# - select both ways in josm
47#
48# Version 1.5
49# - get bugs implemented
50#
51# Version 1.6
52# - get bugs NEW OSB additionally implemented
53# - gpx file with open bugs for germany can be obtained here: http://openstreetbugs.schokokeks.org/api/0.1/getGPX?b=47.4&t=55.0&l=5.9&r=15.0&limit=100000&open=yes
54# - added map compare link
55#
56# Version 2.0
57# - faster execution parameters
58#
59#
60# Version 3.0
61# - quad trees
62#
63# Version 3.1
64# - sorted output
65#
66
67use strict ;
68use warnings ;
69
70use List::Util qw[min max] ;
71use OSM::osm 5.1 ;
72use OSM::QuadTree ;
73use File::stat;
74use Time::localtime;
75use LWP::Simple;
76
77my $olc = 0 ;
78
79my $program = "checkcross.pl" ;
80my $usage = $program . " [N|B] def.xml file.osm out.htm out.gpx (mode N = normal or B = also get openstreetbugs" ;
81my $version = "3.1" ;
82my $mode = "N" ;
83
84my $gpxFileName = "../../web/osm/qa/bugs/OpenStreetBugsOpen.gpx" ;
85my $bugsMaxDist = 0.05 ; # in km
86my $bugsDownDist = 0.02 ; # in deg
87my $minLength = 100 ; # min length of way to be considered in result list (in meters)
88
89my (%gpxLon, %gpxLat, %gpxId, %gpxClosed, %gpxDesc) ;
90
91my $qt ;
92
93my $wayId ; my $wayId1 ; my $wayId2 ;
94my $wayUser ; my @wayNodes ; my @wayTags ;
95my $nodeId ; my $nodeId2 ;
96my $nodeUser ; my $nodeLat ; my $nodeLon ; my @nodeTags ;
97my $aRef1 ; my $aRef2 ;
98my $wayCount = 0 ;
99my $againstCount = 0 ;
100my $checkWayCount = 0 ;
101my $againstWayCount = 0 ;
102my $invalidWays ;
103
104my @check ;
105my @against ;
106my @checkWays ;
107my @againstWays ;
108
109my $time0 = time() ; my $time1 ; my $timeA ;
110my $i ;
111my $key ;
112my $num ;
113my $tag1 ; my $tag2 ;
114my $progress ;
115my $potential ;
116my $checksDone ;
117
118my $html ;
119my $def ;
120my $gpx ;
121my $osmName ;
122my $htmlName ;
123my $defName ;
124my $gpxName ;
125
126my %wayNodesHash ;
127my @neededNodes ;
128my %lon ; my %lat ;
129my %xMax ; my %xMin ; my %yMax ; my %yMin ; 
130my %layer ;
131my %wayCategory ;
132my %wayHash ;
133my %length ;
134my %oneway ;
135
136my $crossings = 0 ;
137my %crossingsHash ;
138
139###############
140# get parameter
141###############
142$mode = shift||'';
143if (!$mode)
144{
145        $mode = "N" ;
146}
147
148$defName = shift||'';
149if (!$defName)
150{
151        die (print $usage, "\n");
152}
153
154$osmName = shift||'';
155if (!$osmName)
156{
157        die (print $usage, "\n");
158}
159
160$htmlName = shift||'';
161if (!$htmlName)
162{
163        die (print $usage, "\n");
164}
165
166$gpxName = shift||'';
167if (!$gpxName)
168{
169        $gpxName = $htmlName ;
170        $gpxName =~ s/htm/gpx/ ;
171}
172
173print "\n$program $version for file $osmName\n\n" ;
174
175
176##################
177# read definitions
178##################
179
180print "read definitions file $defName...\n" ;
181open ($def, , "<", $defName) or die "definition file $defName not found" ;
182
183while (my $line = <$def>) {
184        #print "read line: ", $line, "\n" ;
185        my ($k)   = ($line =~ /^\s*<k=[\'\"]([:\w\s\d]+)[\'\"]/); # get key
186        my ($v) = ($line =~ /^.+v=[\'\"]([:\w\s\d]+)[\'\"]/);       # get value
187       
188        if ($k and defined ($v)) {
189                #print "key: ", $k, "\n" ;
190                #print "val: ", $v, "\n" ;
191
192                if ($k eq "check") {
193                        push @check, $v ;
194                }
195                if ($k eq "against") {
196                        push @against, $v ;
197                }
198        }
199}
200
201close ($def) ;
202
203
204
205
206print "Check ways: " ;
207foreach (@check) { print $_, " " ;} print "\n" ;
208print "Against: " ;
209foreach (@against) { print $_, " " ;} print "\n\n" ;
210
211
212if ($mode eq "B") {
213        readGPXFile ($gpxFileName) ;
214}
215
216
217######################
218# skip all nodes first
219######################
220openOsmFile ($osmName) ;
221print "pass1: skipping nodes...\n" ;
222skipNodes () ;
223
224
225#############################
226# identify check/against ways
227#############################
228print "pass1: identify check ways...\n" ;
229($wayId, $wayUser, $aRef1, $aRef2) = getWay () ;
230if ($wayId != -1) {
231        @wayNodes = @$aRef1 ;
232        @wayTags = @$aRef2 ;
233}
234while ($wayId != -1) { 
235        $wayCount++ ;
236        if (scalar (@wayNodes) >= 2) {
237
238
239                my $found = 0 ;
240                my $layerTemp = "0" ; my $onewayTemp = 0 ;
241                # check tags ONLY ONCE
242                foreach $tag1 (@wayTags) {
243                        if (grep (/layer/, $tag1)) { $layerTemp = $tag1 ; $layerTemp =~ s/layer:// ; }
244                        if ( ($tag1 eq "oneway:yes") or ($tag1 eq "oneway:1") or ($tag1 eq "oneway:-1") or ($tag1 eq "oneway:true") ) {
245                                $onewayTemp = 1 ;
246                        }
247                        foreach $tag2 (@against) {
248                                if ($tag1 eq $tag2) { $found = 1 ; }
249                        }
250                }
251                if ($found) {
252                        $againstWayCount++ ;
253                        push @againstWays, $wayId ;
254                        @{$wayNodesHash{$wayId}} = @wayNodes ;
255                        push @neededNodes, @wayNodes ;
256                        $layer{$wayId} = $layerTemp ;
257                        $oneway{$wayId} = $onewayTemp ;
258                        $wayCategory{$wayId} = 2 ;
259                }
260
261                $found = 0 ; 
262                foreach $tag1 (@wayTags) {
263                        # if (grep (/layer/, $tag1)) { $layerTemp = $tag1 ; }
264                        foreach $tag2 (@check) {
265                                if ($tag1 eq $tag2) { $found = 1 ; }
266                        }
267                }
268                if ($found)  { 
269                        push @checkWays, $wayId ; 
270                        $checkWayCount++ ;
271                        @{$wayNodesHash{$wayId}} = @wayNodes ;
272                        push @neededNodes, @wayNodes ;
273                        $layer{$wayId} = $layerTemp ;
274                        $oneway{$wayId} = $onewayTemp ;
275                        $wayCategory{$wayId} = 1 ;
276                }
277        }
278        else {
279                #print "invalid way (one node only): ", $wayId, "\n" ;
280                $invalidWays++ ;
281        }
282
283        # next way
284        ($wayId, $wayUser, $aRef1, $aRef2) = getWay () ;
285        if ($wayId != -1) {
286                @wayNodes = @$aRef1 ;
287                @wayTags = @$aRef2 ;
288        }
289}
290
291closeOsmFile () ;
292
293print "number total ways: $wayCount\n" ;
294print "number invalid ways (1 node only): $invalidWays\n" ;
295print "number check ways: $checkWayCount\n" ;
296print "number against ways: $againstWayCount\n" ;
297
298
299
300
301######################
302# get node information
303######################
304print "pass2: get node information...\n" ;
305
306my $minLon = 999 ;
307my $maxLon = -999 ;
308my $minLat = 999 ;
309my $maxLat = -999 ;
310
311openOsmFile ($osmName) ;
312
313@neededNodes = sort { $a <=> $b } @neededNodes ;
314
315($nodeId, $nodeLon, $nodeLat, $nodeUser, $aRef1) = getNode () ;
316if ($nodeId != -1) {
317        #@nodeTags = @$aRef1 ;
318}
319
320while ($nodeId != -1) {
321        my $needed = 0 ;
322
323        $needed = binSearch ($nodeId, \@neededNodes ) ;
324
325        if ($needed >= 0) { $lon{$nodeId} = $nodeLon ; $lat{$nodeId} = $nodeLat ; }
326
327        if ($nodeLon > $maxLon) { $maxLon = $nodeLon ; }
328        if ($nodeLon < $minLon) { $minLon = $nodeLon ; }
329        if ($nodeLat > $maxLat) { $maxLat = $nodeLat ; }
330        if ($nodeLat < $minLat) { $minLat = $nodeLat ; }
331
332        # next
333        ($nodeId, $nodeLon, $nodeLat, $nodeUser, $aRef1) = getNode () ;
334        if ($nodeId != -1) {
335                #@nodeTags = @$aRef1 ;
336        }
337}
338
339closeOsmFile () ;
340
341$qt = OSM::QuadTree->new (      -xmin => $minLon, 
342                                -xmax => $maxLon, 
343                                -ymin => $minLat, 
344                                -ymax => $maxLat, 
345                                -depth => 8) ;
346
347##############
348# calc lengths
349##############
350
351my $lengthTemp = 0 ;
352foreach $wayId (@checkWays) {
353        $lengthTemp = 0 ;
354        for ($i = 0; $i < scalar (@{$wayNodesHash{$wayId}}) - 1 ; $i++) {
355                $lengthTemp += distance ($lon{$wayNodesHash{$wayId}[$i]}, $lat{$wayNodesHash{$wayId}[$i]}, 
356                        $lon{$wayNodesHash{$wayId}[$i+1]}, $lat{$wayNodesHash{$wayId}[$i+1]}) ;
357        }
358        $length{$wayId} = $lengthTemp ;
359}
360
361$lengthTemp = 0 ;
362foreach $wayId (@againstWays) {
363        $lengthTemp = 0 ;
364        for ($i = 0; $i < scalar (@{$wayNodesHash{$wayId}}) - 1 ; $i++) {
365                $lengthTemp += distance ($lon{$wayNodesHash{$wayId}[$i]}, $lat{$wayNodesHash{$wayId}[$i]}, 
366                        $lon{$wayNodesHash{$wayId}[$i+1]}, $lat{$wayNodesHash{$wayId}[$i+1]}) ;
367        }
368        $length{$wayId} = $lengthTemp ;
369}
370
371
372
373##########################
374# init areas for chechWays
375##########################
376print "init areas for checkways...\n" ;
377foreach $wayId (@checkWays) {
378
379        ($xMin{$wayId}, $xMax{$wayId}, $yMin{$wayId}, $yMax{$wayId}) = getArea ( @{$wayNodesHash{$wayId}} );
380
381        $qt->add ($wayId, $xMin{$wayId}, $yMin{$wayId}, $xMax{$wayId}, $yMax{$wayId}) ;
382}
383
384
385
386###############################
387# check for crossings
388###############################
389print "check for crossings...\n" ;
390
391$progress = 0 ;
392$timeA = time() ;
393
394push @againstWays, @checkWays ;
395my $total = scalar (@againstWays) ;
396
397$potential = $total * scalar (@checkWays) ;
398
399foreach $wayId1 (@againstWays) {
400        $progress++ ;
401        if ( ($progress % 1000) == 0 ) {
402                printProgress ($program, $osmName, $timeA, $total, $progress) ;
403        }
404
405        # create temp array according to hash
406
407        my ($aXMin, $aXMax, $aYMin, $aYMax) = getArea ( @{$wayNodesHash{$wayId1}} );
408        my $ref = $qt->getEnclosedObjects ($aXMin, $aYMin, $aXMax, $aYMax) ;
409        my @temp = @$ref ;
410
411        foreach $wayId2 (@temp) {
412                if ( $layer{$wayId1} ne $layer{$wayId2} ) {
413                        # don't do anything, ways on different layer
414                }
415                else { # ways on same layer
416                        # check for overlapping "way areas"
417
418                        if (checkOverlap ($aXMin, $aYMin, $aXMax, $aYMax, $xMin{$wayId2}, $yMin{$wayId2}, $xMax{$wayId2}, $yMax{$wayId2})) {
419                                $olc++ ;
420                                if ( ($wayCategory{$wayId1} == $wayCategory{$wayId2}) and ($wayId1 <= $wayId2) ) {
421                                        # don't do anything because cat1/cat1 only if id1>id2
422                                }
423                                else {
424                                        my $a ; my $b ;
425                                        $checksDone++ ;
426                                        for ($a=0; $a<$#{$wayNodesHash{$wayId1}}; $a++) {
427                                                for ($b=0; $b<$#{$wayNodesHash{$wayId2}}; $b++) {
428                                                        my ($x, $y) = crossing ($lon{$wayNodesHash{$wayId1}[$a]}, 
429                                                                        $lat{$wayNodesHash{$wayId1}[$a]}, 
430                                                                        $lon{$wayNodesHash{$wayId1}[$a+1]}, 
431                                                                        $lat{$wayNodesHash{$wayId1}[$a+1]}, 
432                                                                        $lon{$wayNodesHash{$wayId2}[$b]}, 
433                                                                        $lat{$wayNodesHash{$wayId2}[$b]}, 
434                                                                        $lon{$wayNodesHash{$wayId2}[$b+1]}, 
435                                                                        $lat{$wayNodesHash{$wayId2}[$b+1]}) ;
436                                                        if (($x != 0) and ($y != 0)) {
437                                                                $crossings++ ;
438                                                                @{$crossingsHash{$crossings}} = ($x, $y, $wayId1, $wayId2) ;
439                                                                #print "crossing: $x, $y, $wayId1, $wayId2\n" ;
440                                                        } # found
441                                                } # for
442                                        } # for
443                                } # categories
444                        } # overlap
445                } 
446        }
447}
448
449print "potential checks: $potential\n" ;
450print "checks actually done: $checksDone\n" ;
451my $percent = $checksDone / $potential * 100 ;
452printf "work: %2.3f percent\n", $percent ;
453print "crossings found: $crossings. some may be omitted because length of way under threshold.\n" ;
454print "olc done: $olc\n" ;
455
456$time1 = time () ;
457
458
459##################
460# PRINT HTML INFOS
461##################
462print "\nwrite HTML tables and GPX file, get bugs if specified...\n" ;
463
464open ($html, ">", $htmlName) || die ("Can't open html output file") ;
465open ($gpx, ">", $gpxName) || die ("Can't open gpx output file") ;
466
467
468printHTMLiFrameHeader ($html, "Crossings Check by Gary68") ;
469printGPXHeader ($gpx) ;
470
471print $html "<H1>Crossing Check by Gary68</H1>\n" ;
472print $html "<p>Version ", $version, "</p>\n" ;
473print $html "<p>Mode ", $mode, "</p>\n" ;
474print $html "<H2>Statistics</H2>\n" ;
475print $html "<p>", stringFileInfo ($osmName), "<br>\n" ;
476print $html "number ways total: $wayCount<br>\n" ;
477print $html "number invalid ways (1 node only): $invalidWays<br>\n" ;
478print $html "number check ways: $checkWayCount<br>\n" ;
479print $html "number against ways: $againstWayCount</p>\n" ;
480
481print $html "<p>Check ways: " ;
482foreach (@check) { print $html $_, " " ;} print $html "</p>\n" ;
483print $html "<p>Against: " ;
484foreach (@against) { print $html $_, " " ;} print $html "</p>\n" ;
485
486
487print $html "<H2>Crossings found where layer is the same</H2>\n" ;
488print $html "<p>At the given location two ways intersect without a common node and on the same layer." ;
489print $html "<table border=\"1\">\n";
490print $html "<tr>\n" ;
491print $html "<th>Line</th>\n" ;
492print $html "<th>WayId1</th>\n" ;
493print $html "<th>WayId2</th>\n" ;
494print $html "<th>Links</th>\n" ;
495print $html "<th>JOSM</th>\n" ;
496print $html "<th>Pic</th>\n" ;
497print $html "<th>Bugs found</th>\n" ;
498print $html "</tr>\n" ;
499$i = 0 ;
500
501
502
503
504my @sorted = () ;
505foreach $key (keys %crossingsHash) {
506        my ($x, $y, $id1, $id2) = @{$crossingsHash{$key}} ;
507        push @sorted, [$key, $x] ;
508}
509
510@sorted = sort { $a->[1] <=> $b->[1]} @sorted ;
511
512foreach my $s (@sorted) {
513
514        my $key ;       
515        $key = $s->[0] ;
516
517        my ($x, $y, $id1, $id2) = @{$crossingsHash{$key}} ;
518
519        my $len1 = int ( $length{$id1} * 1000) ;
520        my $len2 = int ( $length{$id2} * 1000) ;
521
522        if ( ( ($len1 < $minLength) and ($oneway{$id1} == 1) ) or 
523                ( ($len2 < $minLength) and ($oneway{$id2} == 1) ) ) {
524                # do nothing
525        }
526        else {
527                $i++ ;
528                # HTML
529                print $html "<tr>\n" ;
530                print $html "<td>", $i , "</td>\n" ;
531                print $html "<td>", historyLink ("way", $id1) , " (oneway=$oneway{$id1}; $len1 m)</td>\n" ;
532                print $html "<td>", historyLink ("way", $id2) , " (oneway=$oneway{$id2}; $len2 m)</td>\n" ;
533                print $html "<td>", osmLink ($x, $y, 16) , "<br>\n" ;
534                print $html osbLink ($x, $y, 16) , "<br>\n" ;
535                print $html mapCompareLink ($x, $y, 16) , "</td>\n" ;
536                print $html "<td>", josmLinkSelectWays ($x, $y, 0.01, $id1, $id2), "</td>\n" ;
537                print $html "<td>", picLinkOsmarender ($x, $y, 16), "</td>\n" ;
538                if ($mode eq "B") {
539                        print "get bugs for line $i...\n" ;
540                        print $html "<td><h3>Old OSB</h3>", getBugs ($x, $y, $bugsDownDist, $bugsMaxDist), "<br>\n" ;
541                        print $html "<h3>NEW OSB</h3>", getGPXWaypoints ($x, $y, $bugsMaxDist), "</td>\n"
542                }
543                else {
544                        print $html "<td>bugs not enabled</td>\n" ;
545                }
546                print $html "</tr>\n" ;
547
548                # GPX
549                my $text = "ChkCross - " . $id1 . "/" . $id2 . " level way crossing without common node" ;
550                printGPXWaypoint ($gpx, $x, $y, $text) ;
551        }
552}
553print $html "</table>\n" ;
554print $html "<p>$i lines total</p>\n" ;
555
556
557
558########
559# FINISH
560########
561print $html "<p>", stringTimeSpent ($time1-$time0), "</p>\n" ;
562printHTMLFoot ($html) ;
563printGPXFoot ($gpx) ;
564
565close ($html) ;
566close ($gpx) ;
567
568statistics ( ctime(stat($osmName)->mtime),  $program,  $defName, $osmName,  $checkWayCount,  $i) ;
569
570print "\n$program finished after ", stringTimeSpent ($time1-$time0), "\n\n" ;
571
572
573sub statistics {
574        my ($date, $program, $def, $area, $total, $errors) = @_ ;
575        my $statfile ; my ($statfileName) = "statistics.csv" ;
576
577        if (grep /\.bz2/, $area) { $area =~ s/\.bz2// ; }
578        if (grep /\.osm/, $area) { $area =~ s/\.osm// ; }
579        my ($area2) = ($area =~ /.+\/([\w\-]+)$/ ) ;
580
581        if (grep /\.xml/, $def) { $def =~ s/\.xml// ; }
582        my ($def2) = ($def =~ /([\w\d\_]+)$/ ) ;
583
584        my ($success) = open ($statfile, "<", $statfileName) ;
585
586        if ($success) {
587                print "statfile found. writing stats...\n" ;
588                close $statfile ;
589                open $statfile, ">>", $statfileName ;
590                printf $statfile "%02d.%02d.%4d;", localtime->mday(), localtime->mon()+1, localtime->year() + 1900 ;
591                printf $statfile "%02d/%02d/%4d;", localtime->mon()+1, localtime->mday(), localtime->year() + 1900 ;
592                print $statfile $date, ";" ;
593                print $statfile $program, ";" ;
594                print $statfile $def2, ";" ;
595                print $statfile $area2, ";" ;
596                print $statfile $total, ";" ;
597                print $statfile $errors ;
598                print $statfile "\n" ;
599                close $statfile ;
600        }
601        return ;
602}
603
604
605
606sub readGPXFile {
607        my ($gpxFileName) = shift ;
608        my $gpxFile ;
609        my $line ;
610        my $i = 0 ;
611        my $o = 0 ;
612        my $c = 0 ;
613
614        open ($gpxFile, "<", $gpxFileName) or die ("can't open gpx file") ;
615        $line = <$gpxFile> ;
616        while ( ! (grep /<wpt /, $line) ) {
617                $line = <$gpxFile> ;   
618        }
619
620        while (grep /<wpt /, $line) {
621                $i++ ; 
622                my ($desc)   = ($line =~ /^.*<desc>(.+)<\/desc>/);     
623                my ($closed)   = ($line =~ /^.*<closed>(.+)<\/closed>/);       
624                my ($name)   = ($line =~ /^.*<id>(.*)<\/id>/); 
625                my ($lon) = ($line =~ /^.+lon=[\'\"]([-\d,\.]+)[\'\"]/) ;
626                my ($lat) = ($line =~ /^.+lat=[\'\"]([-\d,\.]+)[\'\"]/) ;
627
628                if (!(defined $closed)) { $closed = 0 ; }               
629                if (!(defined $name)) { $name = "noId" ; }             
630
631                $desc =~ s/<hr \/>/:::/g ;
632
633                $gpxLon{$i} = $lon ;
634                $gpxLat{$i} = $lat ;
635                $gpxId{$i} = $name ;
636                $gpxDesc{$i} = $desc ;
637                $gpxClosed{$i} = $closed ;
638                # print "$name, $closed, $lon, $lat, $desc\n" ;
639
640                $line = <$gpxFile> ;   
641        }
642        close ($gpxFile) ;
643        print "$i waypoints read from gpx file\n\n" ;
644}
645
646
647sub getGPXWaypoints {
648        my ($lon, $lat, $bugsMaxDist) = @_ ;
649
650        my $result = "<p>\n" ;
651
652        my $key ;
653        my $j = 0 ;
654        foreach $key (keys %gpxLon) {
655                my $dist = distance ($lon, $lat, $gpxLon{$key}, $gpxLat{$key}) ;
656                if ( $dist < $bugsMaxDist ) {
657                        $j++ ;
658                        my ($d) = int (distance ($lon, $lat, $gpxLon{$key}, $gpxLat{$key}) * 1000)  ;
659                        $result = $result . "id=" . $gpxId{$key} . " dist=" . $d . "m " . $gpxClosed{$key} . " " . $gpxDesc{$key} . "<br>\n" ;
660                }
661        }
662        # print "$j found inside distance\n" ;
663        $result = $result . "</p>\n" ;
664        return $result ;
665}
666
667
668
669sub getArea {
670        my @nodes = @_ ;
671
672        my $minLon = 999 ;
673        my $maxLon = -999 ;
674        my $minLat = 999 ;
675        my $maxLat = -999 ;
676
677
678        foreach my $node (@nodes) {
679                if ($lon{$node} > $maxLon) { $maxLon = $lon{$node} ; }
680                if ($lon{$node} < $minLon) { $minLon = $lon{$node} ; }
681                if ($lat{$node} > $maxLat) { $maxLat = $lat{$node} ; }
682                if ($lat{$node} < $minLat) { $minLat = $lat{$node} ; }
683        }       
684        return ($minLon, $maxLon, $minLat, $maxLat) ;
685}
Note: See TracBrowser for help on using the repository browser.