source: subversion/applications/utils/gary68/checkrelation.pl @ 23856

Last change on this file since 23856 was 19238, checked in by gary68, 10 years ago

checkrelation 1.5, ignore list implemented

  • Property svn:executable set to *
File size: 43.5 KB
Line 
1#
2#
3# checkrelation.pl by gary68
4#
5#
6# Copyright (C) 2009, Gerhard Schwanz
7#
8# 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
9# Free Software Foundation; either version 3 of the License, or (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>
15#
16#
17# format boder file (defining the border polygon of the checked area) - same format osmosis accepts for cut polygons
18#
19# name
20# 1
21# lon lat
22# lon lat
23# ...
24# END
25#
26# version 1.2
27# - analyzerLink definition removed from file. is defined in osm.pm
28#
29# version 1.3
30# - double way in relation check added. according output added to html
31#
32# version 1.4 removed ERROR message
33#
34# version 1.5 ignore list implemented
35#
36
37
38use strict ;
39use warnings ;
40
41use File::stat ;
42use Time::localtime ; 
43#use String::Scanf ;
44
45use OSM::osm 4.0 ;
46use OSM::osmgraph 2.1 ;
47
48my $program = "checkrelation.pl" ;
49my $usage = $program . " <mode> file.osm baseDir baseName [borderName]\nmode=[M|Re|Ro|B|P]\nM=multipolygon, Re=restriction, Ro=route, B=boundary P=picture" ;
50my $version = "1.5" ;
51
52my @restrictions = qw (no_right_turn no_left_turn no_u_turn no_straight_on only_right_turn only_left_turn only_straight_on) ;
53my @typesChecked = qw (restriction multipolygon boundary route) ; 
54
55my $buffer = 0.15 ;
56my $picSize = 1024 ;
57my $borderThreshold = 1 ;
58
59my %typehash ;
60
61my $wayId ;
62my $wayUser ;
63my @wayNodes ;
64my @wayTags ;
65my $nodeId ;
66my $nodeUser ;
67my $nodeLat ;
68my $nodeLon ;
69my @nodeTags ;
70my $aRef1 ;
71my $aRef2 ;
72
73my $relationId ;
74my $relationUser ;
75my @relationMembers ;
76my @relationTags ;
77my $placeCount = 0 ;
78
79my $relationCount = 0 ;
80my $checkedRelationCount = 0 ;
81my $members = 0 ;
82my @member;
83my $wayCount = 0 ; my $invalidWayCount = 0 ; my %invalidWays ;
84my $nodeCount = 0 ;
85my $problems = 0 ;
86
87my @neededWays = () ;
88my @neededNodes = () ;
89
90my %lon ; my %lat ;
91my %lineMax = () ; my %lineMin = () ;
92my %wayNodesHash ;
93my %placeName ;
94my %ignoredRelations = () ;
95
96my @borderWay = () ;
97
98my $mode ;
99
100my $baseDirName ;
101my $baseName ;
102my $osmName ; 
103my $borderFileName = "" ; 
104my $htmlName ; my $html ;
105my $gpxName ; my $gpx ;
106
107my $time0 = time() ;
108my $totalBorderCheckTime = 0 ;
109my $maxBorderCheckTime = 0 ;
110my $totalSegmentsCheckTime = 0 ;
111my $maxSegmentsCheckTime = 0 ;
112
113
114$mode = shift||'';
115if (!$mode)
116{
117        $mode = "MRoReB" ; # all
118}
119
120$osmName = shift||'';
121if (!$osmName)
122{
123        die (print $usage, "\n");
124}
125
126$baseDirName = shift||'';
127if (!$baseDirName)
128{
129        die (print $usage, "\n");
130}
131
132$baseName = shift||'';
133if (!$baseName)
134{
135        die (print $usage, "\n");
136}
137
138$borderFileName = shift||'';
139if (!$borderFileName)
140{
141        $borderFileName = "" ;
142}
143
144$htmlName = $baseDirName . "/" . $baseName . ".htm" ;
145$gpxName = $baseDirName . "/" . $baseName . ".gpx" ;
146
147print "\n$program $version \nfor file $osmName\nmode = $mode\nborder threshold = $borderThreshold km\n\n" ;
148
149if ($borderFileName ne "") {
150        readBorder ($borderFileName) ;
151}
152
153readIgnoreFile() ;
154
155print "parsing relations...\n" ;
156openOsmFile ($osmName) ;
157print "- skipping nodes...\n" ;
158skipNodes() ;
159print "- skipping ways...\n" ;
160skipWays() ;
161print "- checking...\n" ;
162
163
164($relationId, $relationUser, $aRef1, $aRef2) = getRelation () ;
165if ($relationId != -1) {
166        @relationMembers = @$aRef1 ;
167        @relationTags = @$aRef2 ;
168}
169
170while ($relationId != -1) {
171        $relationCount++ ;     
172        $members += scalar (@relationMembers) ;
173
174        my $i ;
175        for ($i=0; $i<scalar (@relationMembers); $i++) {
176                #print "${$relationMembers[$i]}[0] ${$relationMembers[$i]}[1] ${$relationMembers[$i]}[2]\n" ; # type, id, role
177                if (${$relationMembers[$i]}[0] eq "way") { push @neededWays, ${$relationMembers[$i]}[1] ; }
178                if (${$relationMembers[$i]}[0] eq "node") { push @neededNodes, ${$relationMembers[$i]}[1] ; }
179        }
180
181        if (scalar (@relationTags) > 0) {
182                for ($i=0; $i<scalar (@relationTags); $i++) {
183                        #print "${$relationTags[$i]}[0] = ${$relationTags[$i]}[1]\n" ;
184                        if ( ${$relationTags[$i]}[0] eq "type") { $typehash{   ${$relationTags[$i]}[1]     } = 1 ; }
185                }
186        }
187
188        #next
189        ($relationId, $relationUser, $aRef1, $aRef2) = getRelation () ;
190        if ($relationId != -1) {
191                @relationMembers = @$aRef1 ;
192                @relationTags = @$aRef2 ;
193        }
194}
195
196closeOsmFile () ;
197
198# parse ways for nodes
199print "parsing ways...\n" ;
200openOsmFile ($osmName) ;
201print "- skipping nodes...\n" ;
202skipNodes() ;
203
204@neededWays = sort { $a <=> $b } @neededWays ;
205
206($wayId, $wayUser, $aRef1, $aRef2) = getWay () ;
207if ($wayId != -1) {
208        @wayNodes = @$aRef1 ;
209        @wayTags = @$aRef2 ;
210}
211while ($wayId != -1) { 
212        my $needed = 0 ;
213        $needed = binSearch ($wayId, \@neededWays ) ;
214        if (scalar (@wayNodes) >= 2) {
215                if ($needed >= 0) {
216                        $wayCount++ ;
217                        @{$wayNodesHash{$wayId}} = @wayNodes ;
218                        push @neededNodes, @wayNodes ;
219                }
220        }
221        else {
222                #print "invalid way (one node only): ", $wayId, "\n" ;
223                $invalidWayCount++ ;
224                $invalidWays{$wayId} = 1 ;
225        }
226
227        # next way
228        ($wayId, $wayUser, $aRef1, $aRef2) = getWay () ;
229        if ($wayId != -1) {
230                @wayNodes = @$aRef1 ;
231                @wayTags = @$aRef2 ;
232        }
233}
234
235closeOsmFile () ;
236
237
238# parse nodes for position and places
239print "parsing nodes...\n" ;
240openOsmFile ($osmName) ;
241
242@neededNodes = sort { $a <=> $b } @neededNodes ;
243
244($nodeId, $nodeLon, $nodeLat, $nodeUser, $aRef1) = getNode () ;
245if ($nodeId != -1) {
246        @nodeTags = @$aRef1 ;
247}
248
249while ($nodeId != -1) {
250        my $needed = 0 ;
251
252        my $Name = "" ; my $place = 0 ; my $tag ;
253        foreach $tag (@nodeTags) {
254                if ( (grep /^place:city/, $tag) and ( ($tag =~ s/://g ) == 1 ) ) { $place = 1 ; }
255                if (grep /^place:town/, $tag) { $place = 1 ; }
256                if (grep /^place_name:/, $tag) { $tag =~ s/^place_name:// ; $Name = $tag ; }
257                my $tag2 = $tag ;
258                if ( (grep /^name:/, $tag) and ( ($tag2 =~ s/://g ) == 1 ) ) { $tag =~ s/^name:// ; $Name = $tag ; }
259        }
260        if ( ($place == 1) and ($Name ne "") ) { $placeName{$nodeId} = $Name ; $placeCount++ ; }
261
262        $needed = binSearch ($nodeId, \@neededNodes ) ;
263        if ( ($needed >= 0) or ($place == 1) ) { $nodeCount++ ; $lon{$nodeId} = $nodeLon ; $lat{$nodeId} = $nodeLat }
264
265        # lineExtr
266        my $latKey = int ($nodeLat*100) / 100 ;
267        if (defined $lineMax{$latKey}) {
268                if ($nodeLon > $lineMax{$latKey}) {
269                        $lineMax{$latKey} = $nodeLon ;
270                }
271                if ($nodeLon < $lineMin{$latKey}) {
272                        $lineMin{$latKey} = $nodeLon ;
273                }
274        }
275        else {
276                $lineMax{$latKey} = $nodeLon ;
277                $lineMin{$latKey} = $nodeLon ;
278        }
279
280        # next
281        ($nodeId, $nodeLon, $nodeLat, $nodeUser, $aRef1) = getNode () ;
282        if ($nodeId != -1) {
283                @nodeTags = @$aRef1 ;
284        }
285}
286
287open ($html, ">", $htmlName) || die ("Can't open html output file") ;
288open ($gpx, ">", $gpxName) || die ("Can't open gpx output file") ;
289
290my $line = 0 ;
291printHTMLHeader ($html, "Relation Check by Gary68") ;
292printGPXHeader ($gpx) ;
293
294print $html "<H1>Relation Check by Gary68</H1>\n" ;
295print $html "<p>Version ", $version, "</p>\n" ;
296print $html "<H2>Info</H2>\n" ;
297print $html "<p>", stringFileInfo ($osmName), "<br>\n" ;
298print $html "<p>Mode: $mode</p>\n" ;
299
300# print $html "<p>Checked relation types: @typesChecked</p>\n" ; # see mode !!!
301print $html "<p>Valid restrictions: @restrictions</p>\n" ;
302print $html "<p>Border threshold: $borderThreshold km</p>\n" ;
303print $html "<p>Ignored relation Ids: " ;
304foreach my $id (sort keys %ignoredRelations) { print $html "$id " ; }
305print $html "</p>\n" ;
306
307
308print "parsing relations 2...\n" ;
309print "- skipping ways...\n" ;
310skipWays() ;
311print "- checking...\n" ;
312
313print "\nnumber relations found: $relationCount\n" ;
314
315printHTMLTableHead ($html) ;
316printHTMLTableHeadings ($html, "Line", "RelationId", "Tags", "Issues", "Links") ;
317
318($relationId, $relationUser, $aRef1, $aRef2) = getRelation () ;
319if ($relationId != -1) {
320        @relationMembers = @$aRef1 ;
321        @relationTags = @$aRef2 ;
322}
323
324my $work = 0 ;
325while ($relationId != -1) {
326        my $i ;
327        my $type = "" ; my $tagText = "" ; my $double = 0 ;
328        my $from = 0 ; my $via = 0  ; my $to = 0  ; my $restrictionType = "" ; my $viaNode = 0 ; my $viaWay = 0 ;
329        my @openEnds ;
330
331        $work++ ;
332        # print "checking relation $relationId\n" ;
333        if (($work % 1000) == 0) { print "...$work relations checked.\n" ; }
334
335        if (scalar (@relationTags) > 0) {
336                for ($i=0; $i<scalar (@relationTags); $i++) {
337                        if ( ${$relationTags[$i]}[0] eq "type") { $type = ${$relationTags[$i]}[1] ; }
338                        if ( ${$relationTags[$i]}[0] eq "restriction") { $restrictionType= ${$relationTags[$i]}[1] ; }
339                        if (grep /^type/, ${$relationTags[$i]}[0]) {
340                                $tagText = $tagText . "<strong>" . ${$relationTags[$i]}[0] . " : " . ${$relationTags[$i]}[1] . "</strong><br>\n" ;
341                        }
342                        else {
343                                $tagText = $tagText . ${$relationTags[$i]}[0] . " : " . ${$relationTags[$i]}[1] . "<br>\n" ;
344                        }
345                }
346        }
347
348        my %count = () ;
349        my @doubleWays = () ;
350        foreach my $member (@relationMembers) {
351                if ($member->[0] eq "way") {
352                        if (defined ($count{$member->[1]})) {
353                                $count{$member->[1]}++ ;
354                        }
355                        else {
356                                $count{$member->[1]} = 1 ;
357                        }
358                }
359        }
360
361        foreach my $way (keys %count) {
362                if ( $count{$way} > 1 ) {
363                        # print "ERROR: relation $relationId contains way $way at least TWICE\n" ;
364                        $double = 1 ;
365                        push @doubleWays, $way ;
366                }
367        }
368
369        ##############
370        # RESTRICTIONS
371        ##############
372
373        if ( ($type eq "restriction") and (grep /Re/, $mode) ) {
374                $checkedRelationCount++ ;
375                for ($i=0; $i<scalar (@relationMembers); $i++) {
376                        #print "${$relationMembers[$i]}[0] ${$relationMembers[$i]}[1] ${$relationMembers[$i]}[2]\n" ; # type, id, role
377                        if ( (${$relationMembers[$i]}[0] eq "node") and (${$relationMembers[$i]}[2] eq "via") ) { $via++ ; $viaNode = ${$relationMembers[$i]}[1] ; }
378                        if ( (${$relationMembers[$i]}[0] eq "way") and (${$relationMembers[$i]}[2] eq "via") ) { $via++ ; $viaWay = ${$relationMembers[$i]}[1] ; }
379                        if ( (${$relationMembers[$i]}[0] eq "way") and (${$relationMembers[$i]}[2] eq "from") ) { $from++ ; }
380                        if ( (${$relationMembers[$i]}[0] eq "way") and (${$relationMembers[$i]}[2] eq "to") ) { $to++ ; }
381                }
382                my $validRestriction = 0 ;
383                foreach (@restrictions) {
384                        if ($_ eq $restrictionType) { $validRestriction = 1 ; }
385                }
386                if ( ( (!$validRestriction) or ($via != 1) or ($from != 1) or ($from != 1) )
387                        and (!defined $ignoredRelations{$relationId}) ) {
388                        $problems++ ;
389                        $line++ ;
390                        my $problemText = "" ;
391                        if (!$validRestriction) { $problemText = $problemText . "<strong>invalid restriction string: $restrictionType</strong> * " ; }
392                        if ($via == 0) { $problemText = $problemText . "<strong>no \"via\" specified</strong> * " ; }
393                        if ($via > 1) { $problemText = $problemText . "<strong>more than one \"via\" specified</strong> * " ; }
394                        if ($from !=1) { $problemText = $problemText . "<strong>number \"from\" ways != 1</strong> * " ; }
395                        if ($to !=1) { $problemText = $problemText . "<strong>number \"to\" ways != 1</strong> * " ; }
396                        printHTMLRowStart ($html) ;
397                        printHTMLCellLeft ($html, $line ) ;
398                        printHTMLCellLeft ($html, historyLink ("relation", $relationId) . "(OSM)<br>" . analyzerLink ($relationId) ) ;
399                        printHTMLCellLeft ($html, $tagText ) ;
400                        printHTMLCellLeft ($html, $problemText ) ;
401                        if ($viaNode != 0) {
402                                my $temp = "\"via\" node " . historyLink("node", $viaNode) . " in " ;
403                                $temp = $temp . josmLinkSelectNode ($lon{$viaNode}, $lat{$viaNode}, 0.003, $viaNode) . " * " ;
404                                $temp = $temp . osmLink ($lon{$viaNode}, $lat{$viaNode}, 16) . " * " ;
405                                $temp = $temp . osbLink ($lon{$viaNode}, $lat{$viaNode}, 16) ;
406                                printGPXWaypoint ($gpx, $lon{$viaNode}, $lat{$viaNode}, "restriction relation with problem(s)") ;
407                                printHTMLCellLeft ($html, $temp) ;
408                        }
409                        else {
410                                printHTMLCellLeft ($html, "") ;
411                        }
412                        printHTMLRowEnd ($html) ;
413                }
414        } # restriction
415
416
417        ##############
418        # MULTIPOLYGON
419        ##############
420        if ( ($type eq "multipolygon")  and (grep /M/, $mode) ) {
421                $checkedRelationCount++ ;
422                my $text = "" ; my $textInner = "" ; my $textOuter = "" ; my $textBoundary = "" ;
423                my $inner = 0 ; my $outer = 0 ; my @innerWays = () ; my @outerWays = () ; my @noRoleWays = () ;
424                my $check = 1 ; # 0 = contains invalid ways ;
425                my $firstWay = 0 ;
426
427                # parse members
428                for ($i=0; $i<scalar (@relationMembers); $i++) {
429
430                        if ( (${$relationMembers[$i]}[0] eq "way") and (${$relationMembers[$i]}[2] eq "inner") ) { 
431                                if (defined ($invalidWays{${$relationMembers[$i]}[1]})) { $check = 0 ; }
432                                $inner++ ; push @innerWays, ${$relationMembers[$i]}[1] ; 
433                                if ($firstWay == 0) { $firstWay = ${$relationMembers[$i]}[1] ;}
434                        }
435                        if ( (${$relationMembers[$i]}[0] eq "way") and (${$relationMembers[$i]}[2] eq "outer") ) { 
436                                if (defined ($invalidWays{${$relationMembers[$i]}[1]})) { $check = 0 ; }
437                                $outer++ ; push @outerWays, ${$relationMembers[$i]}[1] ; 
438                                if ($firstWay == 0) { $firstWay = ${$relationMembers[$i]}[1] ;}
439                        }
440                        if ( (${$relationMembers[$i]}[0] eq "way") and (${$relationMembers[$i]}[2] eq "none") ) { 
441                                if ($firstWay == 0) { $firstWay = ${$relationMembers[$i]}[1] ;}
442                                push @noRoleWays, ${$relationMembers[$i]}[1] ;
443                                $text = "<strong>at least one way given without role</strong><br>" ;
444                        }
445                }
446
447                if ( ($check) and ($double == 0) ) {
448                        my $openTextInner = "" ; my $openTextOuter = "" ; my $noOuterText = "" ; 
449       
450                        # CHECK OPEN WAYS/SEGMENTS
451                        my $segCount ; my $segOpenCount ; my @openEndsList = () ;
452       
453                        if (scalar @innerWays > 0) {
454                                ($segCount, $segOpenCount, @openEnds) = checkSegments2 (@innerWays) ;
455                                $textInner = "#inner segs: " . $segCount . " #open segs: " . $segOpenCount . "<br>" ;
456                                if ($segOpenCount != 0) {
457                                        $text = $text . "<strong>at least one open inner segment</strong><br>\n" ;
458                                        #$openTextInner = "<strong>JOSM links open ends inner ways:</strong><br> " . listEnds (@openEndsList) ;
459                                        $openTextInner = "<strong>JOSM links open ends inner ways:</strong><br> " . listEnds (@openEnds) ;
460                                        push @openEndsList, @openEnds ;
461                                }
462                        }
463       
464                        if (scalar @outerWays > 0) {
465                                ($segCount, $segOpenCount, @openEnds) = checkSegments2 (@outerWays) ;
466                                $textOuter = "#outer segs: " . $segCount . " #open segs: " . $segOpenCount . "<br>" ;
467                                if ($segOpenCount > 0) {
468                                        $text = $text . "<strong>at least one open outer segment</strong><br>\n" ;
469                                        #$openTextOuter = "<strong>JOSM links open ends outer ways:</strong><br> " . listEnds (@openEndsList) ;
470                                        $openTextOuter = "<strong>JOSM links open ends outer ways:</strong><br> " . listEnds (@openEnds) ;
471                                        push @openEndsList, @openEnds ;
472                                }
473                        }
474                        else {
475                                $text = $text . "<strong>no outer way</strong><br>\n" ;
476                                if ($firstWay != 0) {
477                                        $noOuterText = "Link to first given way: " . 
478                                                josmLinkSelectWay ($lon{$wayNodesHash{$firstWay}[0]}, $lat{$wayNodesHash{$firstWay}[0]}, 0.003, $firstWay) ;
479                                }
480                        }
481                        if ( ( ($text ne "") and (minDistToBorderOK (@openEndsList) ) )
482                                and (!defined $ignoredRelations{$relationId}) ) {
483                                $line++ ;
484                                $problems++ ;
485                                #print "relation: $relationId distance: ", minDistToBorder(@innerWays, @outerWays), "\n" ;
486                                printHTMLRowStart ($html) ;
487                                printHTMLCellLeft ($html, $line ) ;
488                                if (grep /P/, $mode) {
489                                        printHTMLCellLeft ($html, historyLink ("relation", $relationId) . "(OSM)<br>" . analyzerLink ($relationId) . "<br>" . linkLocal ($relationId) ) ;
490                                }
491                                else {
492                                        printHTMLCellLeft ($html, historyLink ("relation", $relationId) . "(OSM)<br>" . analyzerLink ($relationId) ) ;
493                                }
494                                printHTMLCellLeft ($html, $tagText ) ;
495                                printHTMLCellLeft ($html, $textOuter . $textInner . $text ) ;
496                                printHTMLCellLeft ($html, $openTextInner . "<br>" . $openTextOuter  . "<br>" . $noOuterText) ;
497                                printHTMLRowEnd ($html) ;
498
499                                my $node ;
500                                foreach $node (@openEndsList) {
501                                        printGPXWaypoint ($gpx, $lon{$node}, $lat{$node}, "open end from multypolygon relation id=" . $relationId ) ;
502                                }
503
504                                if (grep /P/, $mode) {
505                                        my @initWays ; 
506                                        push @initWays, @innerWays, @outerWays, @noRoleWays ;
507                                        if (scalar @initWays > 0) {
508                                                my ($lonMin, $latMin, $lonMax, $latMax) = calcRange (@initWays) ;
509                                                my $way ; my $node ;
510                                                initGraph ($picSize, $lonMin, $latMin, $lonMax, $latMax) ;
511                                                drawPlaces() ;
512                                                drawBorder2 (@borderWay) ;
513                                                foreach $way (@innerWays) {
514                                                        drawWay ("blue", 2, nodes2Coordinates (@{$wayNodesHash{$way}}) ) ;
515                                                }
516                                                foreach $way (@outerWays) {
517                                                        drawWay ("black", 2, nodes2Coordinates (@{$wayNodesHash{$way}}) ) ;
518                                                }
519                                                foreach $way (@noRoleWays) {
520                                                        drawWay ("gray", 2, nodes2Coordinates (@{$wayNodesHash{$way}}) ) ;
521                                                }
522                                                foreach $node (@openEndsList) {
523                                                        drawNodeCircle ($lon{$node}, $lat{$node}, "red", 7) ; # / size (1..5)
524                                                        drawTextPos ($lon{$node}, $lat{$node}, 3, 3, $node, "red", 2)
525                                                }
526                                                drawHead ($program . " ". $version . " by Gary68 for Id: " . $relationId . ", " . $type, "black", 3) ;
527                                                drawFoot ("data by openstreetmap.org" . " " . $osmName . " " .ctime(stat($osmName)->mtime), "gray", 3) ;
528                                                drawLegend (3, "Border of file", "green", "Open end", "red", "Inner way", "blue", "No role (defaults to outer)", "gray", "Outer way", "black") ;
529                                                drawRuler ("black") ;
530                                                writeGraph ($baseDirName . "/" . $baseName . $relationId . ".png") ;
531                                        }
532                                }
533                        }
534                }
535                else {
536                        if ($double == 1) {
537                                $line++ ;
538                                $problems++ ;
539                                printHTMLRowStart ($html) ;
540                                printHTMLCellLeft ($html, $line ) ;
541                                printHTMLCellLeft ($html, historyLink ("relation", $relationId) . "(OSM)<br>" . analyzerLink ($relationId) ) ;
542                                printHTMLCellLeft ($html, $tagText ) ;
543                                printHTMLCellLeft ($html, "Relation contains ways twice: @doubleWays\n" ) ;
544                                printHTMLCellLeft ($html, "" ) ;
545                                printHTMLRowEnd ($html) ;
546                        }
547                }
548        } # multipolygon
549
550
551        ##########
552        # BOUNDARY
553        ##########
554        if ( ($type eq "boundary") and (grep /B/, $mode) ) {
555                $checkedRelationCount++ ;
556                my $text = "" ;
557                my $textInner = "" ; my $textOuter = "" ; my $textBoundary = "" ;
558                my $inner = 0 ; my $outer = 0 ; my $boundary = 0 ; my @innerWays = () ; my @outerWays = () ; my @boundaryWays = () ; 
559                my @openEndsList = () ;
560                my $check = 1 ; # 0 = contains invalid ways ;
561
562                # parse members
563                for ($i=0; $i<scalar (@relationMembers); $i++) {
564                        if ( (${$relationMembers[$i]}[0] eq "way") and ((${$relationMembers[$i]}[2] eq "inner") or (${$relationMembers[$i]}[2] eq "enclave") ) ) { 
565                                if (defined ($invalidWays{${$relationMembers[$i]}[1]})) { $check = 0 ; }
566                                $inner++ ; push @innerWays, ${$relationMembers[$i]}[1] ; 
567                        }
568                        if ( (${$relationMembers[$i]}[0] eq "way") and ((${$relationMembers[$i]}[2] eq "outer") or (${$relationMembers[$i]}[2] eq "exclave") ) ) { 
569                                if (defined ($invalidWays{${$relationMembers[$i]}[1]})) { $check = 0 ; }
570                                $outer++ ; push @outerWays, ${$relationMembers[$i]}[1] ; 
571                        }
572                        if ( (${$relationMembers[$i]}[0] eq "way") and (${$relationMembers[$i]}[2] eq "none") ) { 
573                                if (defined ($invalidWays{${$relationMembers[$i]}[1]})) { $check = 0 ; }
574                                $boundary++ ; push @boundaryWays, ${$relationMembers[$i]}[1] ; 
575                        }
576
577                        # RELATION?
578                        if  (${$relationMembers[$i]}[0] eq "relation") { 
579                                $check = 0 ; # TODO
580                        }
581                }
582
583                if ( ($check) and ($double == 0) ) {
584                        my $segCount ; my $segOpenCount ;
585                        my $openTextInner = "" ; my $openTextOuter = "" ; my $openTextBoundary = "" ;
586
587                        #boundary
588                        if (scalar @boundaryWays > 0) {
589                                ($segCount, $segOpenCount, @openEnds) = checkSegments2 (@boundaryWays) ;
590                                $textBoundary = "#boundary segs: " . $segCount . " #open segs: " . $segOpenCount . "<br>" ;
591                                if ($segOpenCount != 0) {
592                                        $text = "<strong>at least one open boundary segment</strong><br>\n" ;
593                                        $openTextBoundary = "<strong>JOSM links open ends boundary ways:</strong><br> " . listEnds (@openEnds) ;
594                                        push @openEndsList, @openEnds ;
595                                }
596                        }
597                        else {
598                                $text = $text . "<strong>no boundary ways</strong><br>" ;
599                        }
600
601                        #enclave
602                        if (scalar @innerWays > 0) {
603                                ($segCount, $segOpenCount, @openEnds) = checkSegments2 (@innerWays) ;
604                                $textInner = "#inner segs: " . $segCount . " #open segs: " . $segOpenCount . "<br>" ;
605                                if ($segOpenCount != 0) {
606                                        $text = "<strong>at least one open inner (enclave) segment</strong><br>\n" ;
607                                        $openTextInner = "<strong>JOSM links open ends inner/enclave ways:</strong><br> " . listEnds (@openEnds) ;
608                                        push @openEndsList, @openEnds ;
609                                }
610                        }
611
612                        #exclave
613                        if (scalar @outerWays > 0) {
614                                ($segCount, $segOpenCount, @openEnds) = checkSegments2 (@outerWays) ;
615                                $textOuter = "#outer segs: " . $segCount . " #open segs: " . $segOpenCount . "<br>" ;
616                                if ($segOpenCount != 0) {
617                                        $text = "<strong>at least one open outer (exclave) segment</strong><br>\n" ;
618                                        $openTextOuter = "<strong>JOSM links open ends outer/exclave ways:</strong><br> " . listEnds (@openEnds) ;
619                                        push @openEndsList, @openEnds ;
620                                }
621                        }
622                        if (    ($text ne "") and 
623                                ( minDistToBorderOK (@openEndsList) ) and 
624                                (!defined $ignoredRelations{$relationId}) ) {
625                                $line++ ;
626                                $problems++ ;
627                                printHTMLRowStart ($html) ;
628                                printHTMLCellLeft ($html, $line ) ;
629                                if (grep /P/, $mode) {
630                                        printHTMLCellLeft ($html, historyLink ("relation", $relationId) . "(OSM)<br>" . analyzerLink ($relationId) . "<br>" . linkLocal ($relationId) ) ;
631                                }
632                                else {
633                                        printHTMLCellLeft ($html, historyLink ("relation", $relationId) . "(OSM)<br>" . analyzerLink ($relationId) ) ;
634                                }
635                                printHTMLCellLeft ($html, $tagText ) ;
636                                printHTMLCellLeft ($html, $textBoundary . $textOuter . $textInner . $text ) ;
637                                printHTMLCellLeft ($html, $openTextBoundary . "<br>" . $openTextInner . "<br>" . $openTextOuter ) ;
638                                printHTMLRowEnd ($html) ;
639
640                                my $node ;
641                                foreach $node (@openEndsList) {
642                                        printGPXWaypoint ($gpx, $lon{$node}, $lat{$node}, "open end from boundary relation id=" . $relationId ) ;
643                                }
644
645                                if (grep /P/, $mode) {
646                                        my @initWays ; 
647                                        push @initWays, @innerWays, @outerWays, @boundaryWays ;
648                                        if (scalar @initWays > 0) {
649                                                my ($lonMin, $latMin, $lonMax, $latMax) = calcRange (@initWays) ;
650                                                my $way ; my $node ;
651                                                initGraph ($picSize, $lonMin, $latMin, $lonMax, $latMax) ;
652                                                drawPlaces() ;
653                                                drawBorder2 (@borderWay) ;
654                                                foreach $way (@innerWays) {
655                                                        drawWay ("blue", 2, nodes2Coordinates (@{$wayNodesHash{$way}}) ) ;
656                                                }
657                                                foreach $way (@outerWays) {
658                                                        drawWay ("red", 2, nodes2Coordinates (@{$wayNodesHash{$way}}) ) ;
659                                                }
660                                                foreach $way (@boundaryWays) {
661                                                        drawWay ("black", 2, nodes2Coordinates (@{$wayNodesHash{$way}}) ) ;
662                                                }
663                                                foreach $node (@openEndsList) {
664                                                        drawNodeCircle ($lon{$node}, $lat{$node}, "red", 7) ; # / size (1..5)
665                                                        drawTextPos ($lon{$node}, $lat{$node}, 3, 3, $node, "red", 2)
666                                                }
667                                                drawHead ($program . " ". $version . " by Gary68 for Id: " . $relationId . ", " . $type, "black", 3) ;
668                                                drawFoot ("data by openstreetmap.org" . " " . $osmName . " " .ctime(stat($osmName)->mtime), "gray", 3) ;
669                                                drawLegend (3, "Border of file", "green", "Open end", "red", "Inner way", "blue", "Outer way", "red", "Boundary way", "black") ;
670                                                drawRuler ("black") ;
671                                                writeGraph ($baseDirName . "/" . $baseName . $relationId . ".png") ;
672                                        }
673                                }
674
675                        }
676                }
677                else {
678                        if ($double == 1) {
679                                $line++ ;
680                                $problems++ ;
681                                printHTMLRowStart ($html) ;
682                                printHTMLCellLeft ($html, $line ) ;
683                                printHTMLCellLeft ($html, historyLink ("relation", $relationId) . "(OSM)<br>" . analyzerLink ($relationId) ) ;
684                                printHTMLCellLeft ($html, $tagText ) ;
685                                printHTMLCellLeft ($html, "Relation contains ways twice: @doubleWays\n" ) ;
686                                printHTMLCellLeft ($html, "" ) ;
687                                printHTMLRowEnd ($html) ;
688                        }
689                }
690        } # boundary
691
692        #######
693        # ROUTE
694        #######
695        if ( ($type eq "route") and (grep /Ro/, $mode) ) {
696                $checkedRelationCount++ ;
697                my $text = "" ;
698                my $textForward = "" ; my $textBackward = "" ;
699                my $route = 0 ; my @forwardWays = () ; my @backwardWays = () ; 
700                my $openTextForward = "" ; my $openTextBackward = "" ; 
701                my @normalWaysDraw = () ; my @forwardWaysDraw = () ; my @backwardWaysDraw = () ; my @openEndsList = () ; my @otherWaysDraw = () ;
702                my $check = 1 ; # 0 = contains invalid ways ;
703
704                # parse members
705                for ($i=0; $i<scalar (@relationMembers); $i++) {
706                        my ($role) = ${$relationMembers[$i]}[2] ;
707                        #print "${$relationMembers[$i]}[0] ${$relationMembers[$i]}[1] ROLE: ${$relationMembers[$i]}[2]\n" ; # type, id, role
708                        if ( (${$relationMembers[$i]}[0] eq "way") and (${$relationMembers[$i]}[2] eq "none") ) { 
709                                if (defined ($invalidWays{${$relationMembers[$i]}[1]})) { $check = 0 ; }
710                                $route++ ; 
711                                push @forwardWays, ${$relationMembers[$i]}[1] ; 
712                                push @backwardWays, ${$relationMembers[$i]}[1] ; 
713                                push @normalWaysDraw, ${$relationMembers[$i]}[1] ;
714                        }
715                        if ( (${$relationMembers[$i]}[0] eq "way") and (${$relationMembers[$i]}[2] eq "forward") ) { 
716                                if (defined ($invalidWays{${$relationMembers[$i]}[1]})) { $check = 0 ; }
717                                $route++ ; 
718                                push @forwardWays, ${$relationMembers[$i]}[1] ; 
719                                push @forwardWaysDraw, ${$relationMembers[$i]}[1] ; 
720                        }
721                        if ( (${$relationMembers[$i]}[0] eq "way") and (${$relationMembers[$i]}[2] eq "backward") ) { 
722                                if (defined ($invalidWays{${$relationMembers[$i]}[1]})) { $check = 0 ; }
723                                $route++ ; 
724                                push @backwardWays, ${$relationMembers[$i]}[1] ; 
725                                push @backwardWaysDraw, ${$relationMembers[$i]}[1] ; 
726                        }
727                        if ( (${$relationMembers[$i]}[0] eq "way") and 
728                                ( ($role eq "shortcut") or ($role eq "variation") or ($role eq "excursion") ) ) { 
729                                if (defined ($invalidWays{${$relationMembers[$i]}[1]})) { $check = 0 ; }
730                                $route++ ; 
731                                push @otherWaysDraw, ${$relationMembers[$i]}[1] ; 
732                        }
733                }
734
735                if ( ($check) and ($double == 0) ) {
736                        my $segCount ; my $segOpenCount ;
737
738                        # forward
739                        if (scalar (@forwardWays) > 0) {
740                                ($segCount, $segOpenCount, @openEnds) = checkSegments2 (@forwardWays) ;
741                                $textForward = "#fw segs: " . $segCount . "<br>" ;
742                                if ($segCount > 1) {
743                                        $text = $text . "<strong>forward route segmented</strong><br>\n" ;
744                                        $openTextForward = "<strong>JOSM links open ends forward ways:</strong><br> " . listEnds (@openEnds) ;
745                                        push @openEndsList, @openEnds ;
746                                }
747                        }
748                        else {
749                                $text = $text . "<strong>no forward ways</strong><br>" ;
750                        }
751
752                        # backward
753                        if (scalar (@backwardWays) > 0) {
754                                ($segCount, $segOpenCount, @openEnds) = checkSegments2 (@backwardWays) ;
755                                $textBackward = "#bw segs: " . $segCount . "<br>" ;
756                                if ($segCount > 1) {
757                                        $text = $text . "<strong>backward route segmented</strong><br>\n" ;
758                                        $openTextBackward = "<strong>JOSM links open ends backward ways:</strong><br> " . listEnds (@openEnds) ;
759                                        push @openEndsList, @openEnds ;
760                                }
761                        }
762                        else {
763                                $text = $text . "<strong>no backward ways</strong><br>" ;
764                        }
765
766                        if (    ($text ne "") and 
767                                ( minDistToBorderOK (@openEndsList) ) and 
768                                ( !defined $ignoredRelations{$relationId}) ) {
769                                $line++ ;
770                                $problems++ ;
771
772                                printHTMLRowStart ($html) ;
773                                printHTMLCellLeft ($html, $line ) ;
774                                if (grep /P/, $mode) {
775                                        printHTMLCellLeft ($html, historyLink ("relation", $relationId) . "(OSM)<br>" . analyzerLink ($relationId) . "<br>" . linkLocal ($relationId) ) ;
776                                }
777                                else {
778                                        printHTMLCellLeft ($html, historyLink ("relation", $relationId) . "(OSM)<br>" . analyzerLink ($relationId) ) ;
779                                }
780                                printHTMLCellLeft ($html, $tagText ) ;
781                                printHTMLCellLeft ($html, $textForward . $textBackward . $text ) ;
782                                printHTMLCellLeft ($html, $openTextForward . "<br>" . $openTextBackward ) ;
783                                printHTMLRowEnd ($html) ;
784
785                                if (grep /P/, $mode) {
786                                        my @initWays ; 
787                                        push @initWays, @forwardWaysDraw, @backwardWaysDraw, @normalWaysDraw, @otherWaysDraw ;
788                                        if (scalar @initWays > 0) {
789                                                my ($lonMin, $latMin, $lonMax, $latMax) = calcRange (@initWays) ;
790                                                my $way ; my $node ;
791                                                initGraph ($picSize, $lonMin, $latMin, $lonMax, $latMax) ;
792                                                drawPlaces() ;
793                                                drawBorder2 (@borderWay) ;
794                                                foreach $way (@normalWaysDraw) {
795                                                        drawWay ("black", 2, nodes2Coordinates (@{$wayNodesHash{$way}}) ) ;
796                                                }
797                                                foreach $way (@forwardWaysDraw) {
798                                                        drawWay ("blue", 2, nodes2Coordinates (@{$wayNodesHash{$way}}) ) ;
799                                                }
800                                                foreach $way (@backwardWaysDraw) {
801                                                        drawWay ("red", 2, nodes2Coordinates (@{$wayNodesHash{$way}}) ) ;
802                                                }
803                                                foreach $way (@otherWaysDraw) {
804                                                        drawWay ("gray", 2, nodes2Coordinates (@{$wayNodesHash{$way}}) ) ;
805                                                }
806                                                foreach $node (@openEndsList) {
807                                                        drawNodeCircle ($lon{$node}, $lat{$node}, "red", 7) ; # / size (1..5)
808                                                        drawTextPos ($lon{$node}, $lat{$node}, 3, 3, $node, "red", 2)
809                                                }
810                                                drawHead ($program . " ". $version . " by Gary68 for Id: " . $relationId . ", " . $type, "black", 3) ;
811                                                drawFoot ("data by openstreetmap.org" . " " . $osmName . " " .ctime(stat($osmName)->mtime), "gray", 3) ;
812                                                drawLegend (3, "Border of file", "green", "Open end", "red", "Other way", "gray", "Forward way", "blue", "Backward way", "red", "Normal way", "black") ;
813                                                drawRuler ("black") ;
814                                                writeGraph ($baseDirName . "/" . $baseName . $relationId . ".png") ;
815                                        }
816                                }
817
818                        }
819                }
820                else {
821                        if ($double == 1) {
822                                $line++ ;
823                                $problems++ ;
824                                printHTMLRowStart ($html) ;
825                                printHTMLCellLeft ($html, $line ) ;
826                                printHTMLCellLeft ($html, historyLink ("relation", $relationId) . "(OSM)<br>" . analyzerLink ($relationId) ) ;
827                                printHTMLCellLeft ($html, $tagText ) ;
828                                printHTMLCellLeft ($html, "Relation contains ways twice: @doubleWays\n" ) ;
829                                printHTMLCellLeft ($html, "" ) ;
830                                printHTMLRowEnd ($html) ;
831                        }
832                }
833        } # route
834
835        #next
836        ($relationId, $relationUser, $aRef1, $aRef2) = getRelation () ;
837        if ($relationId != -1) {
838                @relationMembers = @$aRef1 ;
839                @relationTags = @$aRef2 ;
840        }
841}
842
843closeOsmFile () ;
844
845print "\nTYPES FOUND\n" ;
846foreach (sort keys %typehash) { print "- ", $_, "\n" ; }
847print "\n" ;
848
849print "STATISTICS\n" ;
850print "number problems $problems\n" ;
851print "number relations $relationCount\n" ;
852print "number checked relations $checkedRelationCount\n" ;
853print "number members $members\n" ;
854print "number member ways $wayCount\n" ;
855print "number member ways invalid $invalidWayCount\n" ;
856print "number related nodes $nodeCount\n" ;
857print "number places $placeCount\n" ;
858print "total segments check time $totalSegmentsCheckTime\n" ;
859print "max segments check time $maxSegmentsCheckTime\n" ;
860print "total border check time $totalBorderCheckTime\n" ;
861print "max border check time $maxBorderCheckTime\n" ;
862
863
864
865printHTMLTableFoot ($html) ;
866
867
868print $html "<H2>Stats and counts</H2>\n" ;
869
870print $html "<H3>TYPES FOUND</H3>\n" ;
871print $html "<p>" ;
872foreach (sort keys %typehash) { print $html "- ", $_, "<br>\n" ; }
873print $html "</p>\n" ;
874
875print $html "<H3>STATISTICS</H3>\n" ;
876print $html "<p>number problems $problems<br>\n" ;
877print $html "number relations $relationCount<br>\n" ;
878print $html "number checked relations $checkedRelationCount<br>\n" ;
879print $html "number members $members<br>\n" ;
880print $html "number member ways $wayCount<br>\n" ;
881print $html "number member ways invalid $invalidWayCount<br>\n" ;
882print $html "number related nodes $nodeCount<br></p>\n" ;
883print $html "number places $placeCount<br></p>\n" ;
884print $html  "<p>total segments check time $totalSegmentsCheckTime<br>\n" ;
885print $html  "max segments check time $maxSegmentsCheckTime<br>\n" ;
886print $html  "total border check time $totalBorderCheckTime<br>\n" ;
887print $html  "max border check time $maxBorderCheckTime</p>\n" ;
888
889my $time1 = time() ;
890
891print $html "<p>", stringTimeSpent ($time1-$time0), "</p>\n" ;
892printHTMLFoot ($html) ;
893printGPXFoot ($gpx) ;
894
895close ($html) ;
896close ($gpx) ;
897
898statistics ( ctime(stat($osmName)->mtime),  $program,  $baseName, $osmName,  $checkedRelationCount,  $problems) ;
899
900print "\n$program finished after ", stringTimeSpent ($time1-$time0), "\n\n" ;
901
902sub listEnds {
903        my (@ends) = @_ ;
904        my $text = "" ;
905        my $node ;
906        if (scalar (@ends) > 0) {
907                foreach $node (@ends) {
908                        $text = $text . "(" . historyLink ("node", $node) . " " . josmLinkSelectNode ($lon{$node}, $lat{$node}, 0.003, $node) . ") " ;
909                }
910        }
911        return $text ;
912}
913
914
915sub calcRange {
916        my (@ways) = @_ ;
917        my $lonMin = 999 ;
918        my $latMin = 999 ;
919        my $lonMax = -999 ; 
920        my $latMax = -999 ; 
921        my $way ; my $node ;
922        #print "ways: @ways\n" ;
923        foreach $way (@ways) {
924                #print "  way: $way\n" ;
925                foreach $node (@{$wayNodesHash{$way}}) {
926                        #print "    node: $node\n" ;
927                        if ($lon{$node} > $lonMax) { $lonMax = $lon{$node} ; }
928                        if ($lat{$node} > $latMax) { $latMax = $lat{$node} ; }
929                        if ($lon{$node} < $lonMin) { $lonMin = $lon{$node} ; }
930                        if ($lat{$node} < $latMin) { $latMin = $lat{$node} ; }
931                }
932        }
933        $lonMin = $lonMin - ($buffer * ($lonMax - $lonMin)) ;
934        $latMin = $latMin - ($buffer * ($latMax - $latMin)) ;
935        $lonMax = $lonMax + ($buffer * ($lonMax - $lonMin)) ;
936        $latMax = $latMax + ($buffer * ($latMax - $latMin)) ;
937        return ($lonMin, $latMin, $lonMax, $latMax) ;
938}
939
940sub nodes2Coordinates {
941# transform list of nodeIds to list of lons/lats
942
943        my @nodes = @_ ;
944        my $i ;
945        my @result = () ;
946
947        for ($i=0; $i<=$#nodes; $i++) {
948                push @result, $lon{$nodes[$i]} ;
949                push @result, $lat{$nodes[$i]} ;
950        }
951        return @result ;
952}
953
954sub linkLocal {
955        my ($id) = shift ;
956        my $result = "<A HREF=\"./" . $baseName . $id . ".png\">Picture</A>" ;
957        return $result ;
958}
959
960sub drawPlaces {
961        my $place ; my $count = 0 ;
962        foreach $place (keys %placeName) {
963                drawNodeDot ($lon{$place}, $lat{$place}, "black", 2) ;
964                drawTextPos ($lon{$place}, $lat{$place}, 0, 0, $placeName{$place}, "black", 2) ;
965        }
966}
967
968sub drawBorder2 {
969        my (@way) = @_ ;
970        drawWay ("green", 2, nodes2Coordinates (@way) ) ;
971}
972
973sub statistics {
974        my ($date, $program, $def, $area, $total, $errors) = @_ ;
975        my $statfile ; my ($statfileName) = "statistics.csv" ;
976
977        if (grep /\.bz2/, $area) { $area =~ s/\.bz2// ; }
978        if (grep /\.osm/, $area) { $area =~ s/\.osm// ; }
979        my ($area2) = ($area =~ /.+\/([\w\-]+)$/ ) ;
980        if (! defined ($area2) ) { $area2 = "unknown" ; }
981
982        my ($def2) = $baseName ;
983
984        my ($success) = open ($statfile, "<", $statfileName) ;
985
986        if ($success) {
987                print "statfile found. writing stats...\n" ;
988                close $statfile ;
989                open $statfile, ">>", $statfileName ;
990                printf $statfile "%02d.%02d.%4d;", localtime->mday(), localtime->mon()+1, localtime->year() + 1900 ;
991                printf $statfile "%02d/%02d/%4d;", localtime->mon()+1, localtime->mday(), localtime->year() + 1900 ;
992                print $statfile $date, ";" ;
993                print $statfile $program, ";" ;
994                print $statfile $def2, ";" ;
995                print $statfile $area2, ";" ;
996                print $statfile $total, ";" ;
997                print $statfile $errors ;
998                print $statfile "\n" ;
999                close $statfile ;
1000        }
1001        return ;
1002}
1003
1004sub readBorder {
1005        my ($borderFileName) = shift ;
1006        my $borderFile ;
1007        my $line ;
1008        my $id = 0 ;
1009        my $dist ;
1010        my $lastLon = 0 ; my $lastLat = 0 ; my $maxDist = 0 ;
1011       
1012        open ($borderFile, "<", $borderFileName) || die ("couldn't open border file");
1013        print "parsing border file...\n" ;     
1014        $line = <$borderFile> ;
1015        $line = <$borderFile> ;
1016        $line = <$borderFile> ;
1017        while (! (grep /END/, $line) ) {
1018                $id-- ; # negative ids for border nodes
1019                #($lo, $la) = sscanf ("%g %g", $line) ;
1020                #print "line: $line\n" ;
1021                my ($lo, $la)   = ($line =~ /^\s*([\-\+\d\.Ee]+)\s+([\-\+\d\.Ee]+)+/ ) ;       
1022                if (!defined ($lo))  { print "id: $id line: $line\n" ; }
1023                $lon{$id} = $lo ; $lat{$id} = $la ;
1024                if ($lastLon == 0) {
1025                        $lastLon = $lo ;
1026                        $lastLat = $la ;
1027                }
1028                push @borderWay, $id ;
1029                $line = <$borderFile> ;
1030                $dist = distance ($lo, $la, $lastLon, $lastLat) ;
1031                if ($dist > $maxDist) { $maxDist = $dist ; }
1032                #printf "%3d \n", distance ($lo, $la, $lastLon, $lastLat) ;
1033                $lastLon = $lo ;
1034                $lastLat = $la ;
1035        }
1036        close ($borderFile) ;
1037        print $id*(-1), " border nodes read.\nmax distance between border nodes: $maxDist\n\n" ;
1038}
1039
1040sub minDistToBorderOK {
1041        my (@nodes) = @_ ;
1042        my $way ; my $node ; my $borderNode ;
1043        my $ok = 1 ;
1044        #print "checking distance...\n" ;
1045
1046
1047        my ($startTime) = time() ;
1048        loopA:
1049        foreach $node (@nodes) {
1050                foreach $borderNode (@borderWay) {
1051                        my ($dist) = distance ($lon{$borderNode}, $lat{$borderNode}, $lon{$node}, $lat{$node}) ;
1052                        if ($dist < $borderThreshold) { 
1053                                $ok = 0 ; 
1054                                last loopA ; 
1055                        }
1056                }
1057        }
1058
1059        my ($secs) = time() - $startTime ;
1060        #print "done extensive border check in $secs seconds...\n" ;
1061        $totalBorderCheckTime += $secs ;
1062        if ( $secs > $maxBorderCheckTime ) {
1063                $maxBorderCheckTime = $secs ;
1064                print "max border check now $maxBorderCheckTime secs\n" ;
1065        }
1066
1067        return $ok ;
1068}
1069
1070sub checkSegments2 {
1071        my (@ways) = @_ ;
1072        my $way ; my $node ;
1073        my @openEnds = () ;
1074        my $segments = 0 ; my $openSegments = 0 ;
1075        my $found = 1 ;
1076        my $way1 ; my $way2 ;
1077        my $endNodeWay2 ;       my $startNodeWay2 ;
1078        my %starts = () ; my %ends = () ;
1079        my %wayStart = () ; my %wayEnd = () ;
1080
1081        my $time1  = time() ;
1082
1083        #init
1084        foreach $way (@ways) {
1085                push @{$starts{$wayNodesHash{$way}[0]}}, $way ;
1086                push @{$ends{$wayNodesHash{$way}[-1]}}, $way ;
1087                $wayStart{$way} = $wayNodesHash{$way}[0] ;
1088                $wayEnd{$way} = $wayNodesHash{$way}[-1] ;
1089        }
1090
1091        while ($found == 1) {
1092                $found = 0 ;
1093
1094                # check start/start
1095                loop1:
1096                foreach $node (keys %starts) {
1097
1098                        # if node with more than 1 connecting way...
1099                        if (scalar (@{$starts{$node}}) > 1) {
1100                                $way1 = ${$starts{$node}}[0] ; $way2 = ${$starts{$node}}[1] ;
1101                                #print "merge start/start $way1 and $way2 at node $node\n" ;
1102
1103                                $endNodeWay2 = $wayEnd{$way2} ;
1104                                #print "end node way2 = $endNodeWay2\n" ;
1105
1106                                # way1 gets new start: end way2
1107                                push @{$starts{ $endNodeWay2 }}, $way1 ;
1108                                $wayStart{$way1} = $endNodeWay2 ;
1109
1110                                # remove end way2
1111                                if (scalar (@{$ends{$endNodeWay2}}) == 1) {
1112                                        delete $ends{$endNodeWay2} ;
1113                                        #print "$endNodeWay2 removed from end hash\n" ;
1114                                }
1115                                else {
1116                                        @{$ends{$endNodeWay2}} = removeElement ($way2, @{$ends{$endNodeWay2}}) ;
1117                                        #print "way $way2 removed from node $endNodeWay2 from end hash\n" ;
1118                                }
1119                               
1120                                # remove way2
1121                                delete $wayEnd{$way2} ;
1122                                delete $wayStart{$way2} ;
1123
1124                                # remove connecting starts
1125                                if (scalar @{$starts{$node}} == 2) {
1126                                        delete $starts{$node} ;
1127                                        #print "$node removed from start hash\n" ;
1128                                }
1129                                else {
1130                                        @{$starts{$node}} = @{$starts{$node}}[2..$#{$starts{$node}}] ;
1131                                        #print "first two elements removed from start hash node = $node\n" ;
1132                                }
1133                                #print "\n" ;
1134                                $found = 1 ; 
1135                                last loop1 ;
1136                        }
1137                }
1138
1139                # check end/end
1140                if (!$found) {
1141                        loop2:
1142                        foreach $node (keys %ends) {
1143
1144                                # if node with more than 1 connecting way...
1145                                if (scalar @{$ends{$node}} > 1) {
1146                                        $way1 = ${$ends{$node}}[0] ; $way2 = ${$ends{$node}}[1] ;
1147                                        #print "merge end/end $way1 and $way2 at node $node\n" ;
1148       
1149                                        $startNodeWay2 = $wayStart{$way2} ;
1150                                        #print "start node way2 = $startNodeWay2\n" ;
1151       
1152                                        # way1 gets new end: start way2
1153                                        push @{$ends{ $startNodeWay2 }}, $way1 ;
1154                                        $wayEnd{$way1} = $startNodeWay2 ;
1155       
1156                                        # remove start way2
1157                                        if (scalar (@{$starts{$startNodeWay2}}) == 1) {
1158                                                delete $starts{$startNodeWay2} ;
1159                                                #print "$startNodeWay2 removed from start hash\n" ;
1160                                        }
1161                                        else {
1162                                                @{$starts{$startNodeWay2}} = removeElement ($way2, @{$starts{$startNodeWay2}}) ;
1163                                                #print "way $way2 removed from node $startNodeWay2 from start hash\n" ;
1164                                        }
1165                               
1166                                        # remove way2
1167                                        delete $wayEnd{$way2} ;
1168                                        delete $wayStart{$way2} ;
1169
1170                                        # remove connecting ends
1171                                        if (scalar @{$ends{$node}} == 2) {
1172                                                delete $ends{$node} ;
1173                                                #print "$node removed from end hash\n" ;
1174                                        }
1175                                        else {
1176                                                @{$ends{$node}} = @{$ends{$node}}[2..$#{$ends{$node}}] ;
1177                                                #print "first two elements removed from end hash node = $node\n" ;
1178                                        }
1179                                        #print "\n" ;
1180                                        $found = 1 ; 
1181                                        last loop2 ;
1182                                }
1183                        }
1184                }
1185
1186
1187                # check start/end
1188                if (!$found) {
1189                        my $wayFound = 0 ;
1190                        loop3:
1191                        foreach $node (keys %starts) {
1192                                if (exists ($ends{$node})) {
1193                                        #look for different! ways
1194                                        my (@startingWays) = @{$starts{$node}} ;
1195                                        my (@endingWays) = @{$ends{$node}} ;
1196                                        my $w1 ; my $w2 ;
1197                                        loop4:
1198                                        foreach $w1 (@startingWays) {
1199                                                foreach $w2 (@endingWays) {
1200                                                        if ($w1 != $w2) {
1201                                                                $wayFound = 1 ;
1202                                                                $way1 = $w1 ; 
1203                                                                $way2 = $w2 ; # merge w1 and w2
1204                                                                #print "start/end: merge ways $way1 and $way2 connected at node $node\n" ;
1205                                                                last loop4 ;
1206                                                        }
1207                                                }
1208                                        } # look for ways
1209                                        if ($wayFound) {
1210                                                #print "way $way1 start $wayStart{$way1} end $wayEnd{$way1}\n" ;
1211                                                #print "way $way2 start $wayStart{$way2} end $wayEnd{$way2}\n" ;
1212
1213                                                # way1 gets new start: start way2
1214                                                $wayStart{$way1} = $wayStart{$way2} ;
1215                                                my ($way2StartNode) = $wayStart{$way2} ;
1216
1217                                                push @{$starts{$way2StartNode}}, $way1 ;
1218                                                #print "way $way1 added to starts for node $way2StartNode\n" ;
1219
1220                                                # remove start way1
1221                                                if (scalar (@{$starts{$node}}) == 1) {
1222                                                        delete $starts{$node} ;
1223                                                        #print "$way1 removed from start hash for node $node\n" ;
1224                                                }
1225                                                else {
1226                                                        @{$starts{$node}} = removeElement ($way1, @{$starts{$node}}) ;
1227                                                        #print "$way1 removed from start hash for node $node\n" ;
1228                                                }
1229
1230                                                #remove end way2
1231                                                if (scalar (@{$ends{$node}}) == 1) {
1232                                                        delete $ends{$node} ;
1233                                                        #print "$way2 removed from end hash for node $node\n" ;
1234                                                }
1235                                                else {
1236                                                        @{$ends{$node}} = removeElement ($way2, @{$ends{$node}}) ;
1237                                                        #print "$way2 removed from end hash for node $node\n" ;
1238                                                }
1239                                                #remove start way2
1240                                                if (scalar (@{$starts{$way2StartNode}}) == 1) {
1241                                                        delete $starts{$way2StartNode} ;
1242                                                        #print "$way2 removed from start hash for node $way2StartNode\n" ;
1243                                                }
1244                                                else {
1245                                                        @{$starts{$way2StartNode}} = removeElement ($way2, @{$starts{$way2StartNode}}) ;
1246                                                        #print "$way2 removed from start hash for node $way2StartNode\n" ;
1247                                                }
1248
1249                                                # remove way2
1250                                                delete $wayEnd{$way2} ;
1251                                                delete $wayStart{$way2} ;
1252                                                #print "way $way2 removed from waystart and wayend hashes\n" ;
1253
1254                                                #print "\n" ;
1255                                                $found = 1 ; 
1256                                                last loop3 ;
1257                                        }
1258                                }
1259                        }
1260                }
1261        }
1262
1263        # evaluation
1264
1265
1266        #print "\nSUB RESULT\n" ;
1267        foreach $way (keys %wayStart) {
1268                #print "way $way start $wayStart{$way} end $wayEnd{$way}\n" ;
1269                if ($wayStart{$way} != $wayEnd{$way}) {
1270                        $openSegments++ ;
1271                        #print "   open!\n" ;
1272                        push @openEnds, $wayStart{$way}, $wayEnd{$way} ;
1273                }
1274        }
1275        #print "SUB RESULT END\n" ;
1276
1277        #print "check segments took ", time() - $time1, "seconds\n" ;
1278        $totalSegmentsCheckTime += time() - $time1 ;
1279        if ( (time () - $time1) > $maxSegmentsCheckTime ) {
1280                $maxSegmentsCheckTime = time () - $time1 ;
1281                print "max segment check now $maxSegmentsCheckTime secs\n" ;
1282        }
1283
1284        return (scalar (keys %wayStart), $openSegments, @openEnds) ;
1285}
1286
1287sub removeElement {
1288        my ($element, @array) = @_ ;
1289        my @arrayNew = () ;
1290        my $pos = -1 ; my $i ;
1291        for ($i=0; $i<=$#array; $i++) { if ($array[$i] == $element) { $pos = $i ; } }
1292        if ($pos != -1) {
1293                if ($pos == 0) {
1294                        @arrayNew = @array[1..$#array] ;
1295                }
1296                if ($pos == $#array) {
1297                        @arrayNew = @array[0..$#array-1] ;
1298                }
1299                if ( ($pos > 0) and ($pos < $#array) ) {
1300                        @arrayNew = @array[0..$pos-1, $pos+1..$#array] ;
1301                }
1302        }
1303        return @arrayNew ;
1304}
1305sub readIgnoreFile {
1306        my $ignoreFile ;
1307        my ($success) = open ($ignoreFile, "<", "./ignoredrelations.txt") ;
1308        if ($success) {
1309                print "ignore file found.\n" ;
1310                while ($line = <$ignoreFile>) {
1311                        my ($relationId) = ($line =~ /([\d]+)/) ;
1312                        if (defined $relationId) { 
1313                                $ignoredRelations{$relationId} = 1 ;
1314                                print "will ignore relation id $relationId\n" ;
1315                        }
1316                }
1317                close ($ignoreFile) ;
1318        } 
1319}
Note: See TracBrowser for help on using the repository browser.