source: subversion/applications/utils/gary68/useractivity.pl @ 17676

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

useractivity 2.0

  • Property svn:executable set to *
File size: 39.9 KB
Line 
1#
2#
3# useractivity.pl by gary68
4#
5#
6#
7# Copyright (C) 2009, Gerhard Schwanz
8#
9# This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the
10# Free Software Foundation; either version 3 of the License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>
16#
17#
18# Version 2
19# - map support added
20# - way support added
21#
22
23use strict ;
24use warnings ;
25
26use OSM::osm ;
27use OSM::osmgraph ;
28use File::stat;
29use Time::localtime;
30
31my $program = "useractivity.pl" ;
32my $usage = $program . " file1.osm file2.osm out.htm Mode numTopUsers picSize (Mode = [N|P|D|S|PD], picSize x in pixels)" ;
33my $version = "2.0" ;
34
35my $topMax = 10 ;
36
37my %lon1 ; my %lat1 ; my %lon2 ; my %lat2 ;
38my $wayId1 ; my $wayVersion1 ; my $wayTimestamp1 ; my $wayUid1 ; my $wayUser1 ; my $wayChangeset1 ; my @wayNodes1 ; my @wayTags1 ;
39my $wayId2 ; my $wayVersion2 ; my $wayTimestamp2 ; my $wayUid2 ; my $wayUser2 ; my $wayChangeset2 ; my @wayNodes2 ; my @wayTags2 ;
40
41my $nodeId1 ; my $nodeUser1 ; my $nodeLat1 ; my $nodeLon1 ; my @nodeTags1 ; my $nodeVersion1 ; my $nodeTimestamp1 ; my $nodeUid1 ; my $nodeChangeset1 ;
42my $nodeId2 ; my $nodeUser2 ; my $nodeLat2 ; my $nodeLon2 ; my @nodeTags2 ; my $nodeVersion2 ; my $nodeTimestamp2 ; my $nodeUid2 ; my $nodeChangeset2 ;
43my $aRef1 ; my $aRef2 ;
44
45my $time0 = time() ; 
46
47my $mode = "" ; my $sizeX = 1024 ;
48my $html ; my $htmlName ;
49my $osm1Name ; my $osm2Name ;
50
51my $file1 ; my $file2 ; my $bz1 ; my $bz2 ; my $isBz21 ; my $isBz22 ; my $line1 ; my $line2 ; my $bzerrno ;
52my $file1Name ; my $file2Name ;
53
54my %minLon ; my %minLat ; my %maxLon ; my %maxLat ; # per user
55my $deletedNodes = 0 ; my $deletedNodesWithTags = 0 ;
56my $deletedWays = 0 ; my $deletedWaysWithTags = 0 ;
57my %nodesAdded ; my %nodesMovedNumber ; my %nodesMovedDistance ; my %nodesMovedMax ;
58my %waysAdded ;
59my %tagsAdded ; my %tagsDeleted ; my %tagsRenamed ; my %tagsReclassified ; my %tagsRereffed ;
60my %tagsDeletedName ;
61my %renames ; my %reclassifications ; my %rerefs ;
62my @deletedNodesIds = () ; my %deletedNodesTags = () ;
63my @deletedWaysIds = () ; my %deletedWaysTags = () ;
64my %versionJumpsNodes = () ;
65my %versionJumpsWays = () ;
66my %opTime ;
67my %neededNodes = () ;
68
69my $reName ; my $reClass ; my $reRef ;
70my $name1 ; my $name2 ; my $ref1 ; my $ref2 ; my $class1 ; my $class2 ;
71
72my $objectProcessed = 0 ; # 0=node, 1=way
73
74###############
75# get parameter
76###############
77$osm1Name = shift||'';
78if (!$osm1Name) { die (print $usage, "\n") ; }
79
80$osm2Name = shift||'';
81if (!$osm2Name) { die (print $usage, "\n") ; }
82
83$htmlName = shift||'';
84if (!$htmlName) { die (print $usage, "\n") ; }
85
86$mode = shift||'';
87if (!$mode) {   $mode = "N" ; }
88
89$topMax = shift||'';
90if (!$topMax) { $topMax = 10 ; }
91
92$sizeX = shift||'';
93if (!$sizeX) {  $sizeX = 1024 ; }
94
95print "\n$program $version for files:\n\n" ;
96print stringFileInfo ($osm1Name), "\n"  ;
97print stringFileInfo ($osm2Name), "\n\n"  ;
98
99#------------------------------------------------------------------------------------
100# Main
101#------------------------------------------------------------------------------------
102
103if (grep /P/, $mode) { initializeMap() ; }
104
105openOsm1File ($osm1Name) ;
106moveNodeFile1() ;
107
108openOsm2File ($osm2Name) ;
109moveNodeFile2() ;
110
111processNodes() ;
112
113moveWayFile1() ;
114moveWayFile2() ;
115
116processWays() ;
117
118closeOsm1File () ;
119closeOsm2File () ;
120
121if ( ! (grep /P/, $mode) )  { 
122        processNeededWayNodes() ; 
123}
124
125if (grep /P/, $mode) { print "paint areas and save map...\n" ; }
126if (grep /P/, $mode) { paintAreas() ; }
127if (grep /P/, $mode) { saveMap() ; }
128if (grep /P/, $mode) { print "done.\n" ; }
129
130
131output() ;
132
133#-------
134# FINISH
135#-------
136
137print "\n$program finished after ", stringTimeSpent (time()-$time0), "\n\n" ;
138
139
140#------------------------------------------------------------------------------------
141# Node procesing
142#------------------------------------------------------------------------------------
143
144sub processNodes {
145        print "processing nodes...\n" ;
146        while ( ($nodeId1 > -1) or ($nodeId2 > -1) ) {
147                # print "while $nodeId1     $nodeId2\n" ;
148                if ($nodeId1 == -1) {
149                        # get rest from file 2, new nodes
150                        while ( $nodeId2 != -1 ) {
151                                # print "$nodeId1     $nodeId2   2-NEW\n" ;
152                                $nodesAdded{$nodeUser2}++ ;
153                                addOperationTime ($nodeUser2, $nodeTimestamp2) ;
154                                if (grep /P/, $mode) { paintNewNode() ; }
155                                userArea ($nodeUser2, $nodeLon2, $nodeLat2) ;
156                                moveNodeFile2() ;
157                        }
158                }
159
160                if ($nodeId2 == -1) {
161                        # get rest from file 1, deleted nodes
162                        while ( $nodeId1 != -1 ) {
163                                $deletedNodes++ ;
164                                if (scalar @nodeTags1 > 0) { 
165                                        $deletedNodesWithTags++ ; 
166                                        if (grep /P/, $mode) { paintDeletedNodeWithTag() ; }
167                                        push @deletedNodesIds, $nodeId1 ;
168                                        @{$deletedNodesTags{$nodeId1}} = @nodeTags1 ;
169                                }
170                                else {
171                                        if (grep /P/, $mode) { paintDeletedNode() ; }
172                                }
173                                moveNodeFile1() ;
174                        }
175                }
176
177                if ( ($nodeId1 == $nodeId2) and ($nodeId1 != -1) ) {
178                        # print "equal $nodeId1     $nodeId2\n" ;
179
180                        # place?
181                        if (grep /P/, $mode) {
182                                my $place = 0 ; my $placeName = "" ; my $placeNameGiven = 0 ;
183                                foreach my $t (@nodeTags1) {
184                                        if ($t->[0] eq "place") { $place = 1 ; }
185                                        if ($t->[0] eq "name") { $placeNameGiven = 1 ; $placeName = $t->[1] ; }
186                                }
187                                if ( ($place == 1) and ($placeNameGiven == 1) ) { paintPlace ($nodeLon1, $nodeLat1, $placeName) ; } 
188                        }
189
190                        # position...
191                        if ( ($nodeLon1 != $nodeLon2) or ($nodeLat1 != $nodeLat2) ) {
192                                $nodesMovedNumber{$nodeUser2}++ ;
193                                addOperationTime ($nodeUser2, $nodeTimestamp2) ;
194                                if (grep /P/, $mode) { paintMovedNode() ; }
195                                my ($d) = distance ($nodeLon1, $nodeLat1, $nodeLon2, $nodeLat2) ;
196                                $nodesMovedDistance{$nodeUser2} += $d ;
197                                if (defined $nodesMovedMax{$nodeUser2}) {
198                                        if ($nodesMovedMax{$nodeUser2} < $d) { $nodesMovedMax{$nodeUser2} = $d ; }
199                                }
200                                else {
201                                        $nodesMovedMax{$nodeUser2} = $d ;
202                                }
203                                userArea ($nodeUser2, $nodeLon1, $nodeLat1) ;
204                                userArea ($nodeUser2, $nodeLon2, $nodeLat2) ;
205                        } # moved
206
207                        if ($nodeVersion2 - $nodeVersion1 > 2) { 
208                                push @{$versionJumpsNodes{$nodeUser2}}, [$nodeId2, $nodeVersion2 - $nodeVersion1] ;
209                        }
210
211                        # process tags
212                        my ($added, $deleted, $renamed, $reclassified) = compareTags (\@nodeTags1, \@nodeTags2) ; 
213                        if ($added) { $tagsAdded{$nodeUser2} += $added ; }
214                        if ($deleted) { $tagsDeleted{$nodeUser2} += $deleted ; }
215                        if ($renamed) { 
216                                $tagsRenamed{$nodeUser2} += $renamed ; 
217                                if (grep /P/, $mode) { paintRenamedNode() ; }
218                        }
219                        if ($added or $deleted or $renamed or $reclassified) {
220                                addOperationTime ($nodeUser2, $nodeTimestamp2) ;
221                        }
222                        moveNodeFile1() ;
223                        moveNodeFile2() ;
224                }
225
226                if ( ($nodeId1 > $nodeId2) and ($nodeId2 != -1) ) {
227                        # print "1 > 2 $nodeId1     $nodeId2   2-NEW\n" ;
228                        # id 2 not found in file 1, nodeId2 new
229                        $nodesAdded{$nodeUser2}++ ;
230                        addOperationTime ($nodeUser2, $nodeTimestamp2) ;
231                        if (grep /P/, $mode) { paintNewNode() ; }
232                        userArea ($nodeUser2, $nodeLon2, $nodeLat2) ;
233                        # move file2 until id2>=id1
234                        while ( ($nodeId2 < $nodeId1) and ($nodeId2 != -1) ) {
235                                moveNodeFile2() ;
236                        }
237                }
238
239                if ( ($nodeId1 < $nodeId2) and ($nodeId1 != -1) ) {
240                        # print "1 < 2 $nodeId1     $nodeId2   1-DELETED\n" ;
241                        # id 1 not found in file 2, nodeId1 deleted
242                        $deletedNodes++ ;
243                        if (scalar @nodeTags1 > 0) { 
244                                $deletedNodesWithTags++ ; 
245                                if (grep /P/, $mode) { paintDeletedNodeWithTag() ; }
246                                push @deletedNodesIds, $nodeId1 ;
247                                @{$deletedNodesTags{$nodeId1}} = @nodeTags1 ;
248                        }
249                        else {
250                                if (grep /P/, $mode) { paintDeletedNode() ; }
251                        }
252                        # move file1 until id1>=id2
253                        while ( ($nodeId1 < $nodeId2) and ($nodeId1 != -1) ) {
254                                moveNodeFile1() ;
255                        }
256                }
257        }
258        print "finished.\n" ;
259}
260
261#------------------------------------------------------------------------------------
262# Way procesing
263#------------------------------------------------------------------------------------
264
265sub processWays {
266        $objectProcessed = 1 ;
267        print "processing ways...\n" ;
268        while ( ($wayId1 > -1) or ($wayId2 > -1) ) {
269                if ($wayId1 == -1) {
270                        # get rest from file 2, new ways
271                        while ( $wayId2 != -1 ) {
272                                # print "$wayId1     $wayId2   2-NEW\n" ;
273                                $waysAdded{$wayUser2}++ ;
274                                addOperationTime ($wayUser2, $wayTimestamp2) ;
275                                if (scalar @wayNodes2 >= 2) {
276                                        #userArea ($wayUser2, $lon2{$wayNodes2[0]}, $lat2{$wayNodes2[0]}) ;
277                                        #userArea ($wayUser2, $lon2{$wayNodes2[-1]}, $lat2{$wayNodes2[-1]}) ;
278                                        userAreaWay ($wayUser2, $wayNodes2[0]) ;
279                                        userAreaWay ($wayUser2, $wayNodes2[-1]) ;
280                                        if (grep /P/, $mode) { paintNewWay() ; }
281                                }
282                                #next
283                                moveWayFile2() ;
284                        }
285                }
286
287                if ($wayId2 == -1) {
288                        # get rest from file 1, deleted ways
289                        while ( $wayId1 != -1 ) {
290                                $deletedWays++ ;
291                                if (scalar @wayTags1 > 0) { 
292                                        $deletedWaysWithTags++ ; 
293                                        if (scalar @wayNodes1 >= 2) {
294                                                if (grep /P/, $mode) { paintDeletedWayWithTag() ; }
295                                        }
296                                        push @deletedWaysIds, $wayId1 ;
297                                        @{$deletedWaysTags{$wayId1}} = @wayTags1 ;
298                                }
299                                else {
300                                        if (scalar @wayNodes1 >= 2) {
301                                                if (grep /P/, $mode) { paintDeletedWay() ; }
302                                        }
303                                }
304                                #next
305                                moveWayFile1() ;
306                        }
307                }
308
309                if ( ($wayId1 == $wayId2) and ($wayId1 != -1) ) {
310                        # print "equal $wayId1     $wayId2\n" ;
311                        # TODO position
312                        # TODO nodes number
313
314                        if ($wayVersion2 - $wayVersion1 > 2) { 
315                                push @{$versionJumpsWays{$wayUser2}}, [$wayId2, $wayVersion2 - $wayVersion1] ;
316                        }
317
318                        # process tags
319                        my ($added, $deleted, $renamed, $reclassified, $rereffed) = compareTags (\@wayTags1, \@wayTags2) ; 
320                        if ($added) { $tagsAdded{$wayUser2} += $added ; }
321                        if ($deleted) { $tagsDeleted{$wayUser2} += $deleted ; }
322                        if ($renamed) { 
323                                $tagsRenamed{$wayUser2} += $renamed ; 
324                                # TODO draw
325                        }
326                        if ($reclassified) { 
327                                $tagsReclassified{$wayUser2} += $reclassified ; 
328                                if (scalar @wayNodes1 >= 2) {
329                                        if (grep /P/, $mode) { paintReclassifiedWay() ; }
330                                }
331                        } 
332                        if ($rereffed) { 
333                                $tagsRereffed{$wayUser2} += $rereffed ; 
334                                if (scalar @wayNodes1 >= 2) {
335                                        if (grep /P/, $mode) { paintRereffedWay() ; }
336                                }
337                        } 
338                        if ($added or $deleted or $renamed or $reclassified or $rereffed) { 
339                                addOperationTime ($wayUser2, $wayTimestamp2) ; 
340                                if ( (scalar @wayNodes1 >= 2) and (scalar @wayNodes2 >= 2) ) {
341                                        # userArea ($wayUser2, $lon2{$wayNodes2[0]}, $lat2{$wayNodes2[0]}) ;
342                                        # userArea ($wayUser2, $lon2{$wayNodes2[-1]}, $lat2{$wayNodes2[-1]}) ;
343                                        userAreaWay ($wayUser2, $wayNodes2[0]) ;
344                                        userAreaWay ($wayUser2, $wayNodes2[-1]) ;
345                                }
346                        }
347                        moveWayFile1() ;
348                        moveWayFile2() ;
349                }
350
351                if ( ($wayId1 > $wayId2) and ($wayId2 != -1) ) {
352                        # print "1 > 2 $wayId1     $wayId2   2-NEW\n" ;
353                        # id 2 not found in file 1, wayId2 new
354                        $waysAdded{$wayUser2}++ ;
355                        addOperationTime ($wayUser2, $wayTimestamp2) ; 
356                        if (scalar @wayNodes2 >= 2) {
357                                # userArea ($wayUser2, $lon2{$wayNodes2[0]}, $lat2{$wayNodes2[0]}) ;
358                                # userArea ($wayUser2, $lon2{$wayNodes2[-1]}, $lat2{$wayNodes2[-1]}) ;
359                                userAreaWay ($wayUser2, $wayNodes2[0]) ;
360                                userAreaWay ($wayUser2, $wayNodes2[-1]) ;
361                                if (grep /P/, $mode) { paintNewWay() ; }
362                        }
363                        # move file2 until id2>=id1
364                        while ( ($wayId2 < $wayId1) and ($wayId2 != -1) ) {
365                                moveWayFile2() ;
366                        }
367                }
368
369                if ( ($wayId1 < $wayId2) and ($wayId1 != -1) ) {
370                        # print "1 < 2 $wayId1     $wayId2   1-DELETED\n" ;
371                        # id 1 not found in file 2, wayId1 deleted
372                        $deletedWays++ ;
373                        if (scalar @wayTags1 > 0) { 
374                                $deletedWaysWithTags++ ; 
375                                if (scalar @wayNodes1 >= 2) {
376                                        if (grep /P/, $mode) { paintDeletedWayWithTag() ; }
377                                }
378                                push @deletedWaysIds, $wayId1 ;
379                                @{$deletedWaysTags{$wayId1}} = @wayTags1 ;
380                        }
381                        else {
382                                if (scalar @wayNodes1 >= 2) {
383                                        if (grep /P/, $mode) { paintDeletedWay() ; }
384                                }
385                        }
386                        # move file1 until id1>=id2
387                        while ( ($wayId1 < $wayId2) and ($wayId1 != -1) ) {
388                                moveWayFile1() ;
389                        }
390                }
391        }
392        print "finished.\n" ;
393}
394
395
396#------------------------------------------------------------------------------------
397# Output functions
398#------------------------------------------------------------------------------------
399
400sub output {
401        print "outputting html...\n" ;
402        my @a ; my @list ;
403        open ($html, ">", $htmlName) or die ("can't open html output file") ;
404        printHTMLHeader ($html, "UserActvity by Gary68") ;
405        print $html "<H1>UserActvity by gary68</H1>" ;
406        print $html "<p>", stringFileInfo ($osm1Name), "</p>\n"  ;
407        print $html "<p>", stringFileInfo ($osm2Name), "</p>\n"  ;
408        print $html "<p>A deleted tag can result out of a change of a tag. The same is true for the addition of a tag. Real changes are not counted.</p>" ;
409        print $html "<H1>Results</H1>" ;
410        print $html "<p>DELETED NODES: $deletedNodes</p>\n" ;
411        print $html "<p>DELETED NODES WITH TAGS: $deletedNodesWithTags (details see further down)</p>\n" ;
412       
413        @a = () ;
414        foreach my $u (keys %opTime) { push @a, [$u, numOpHours ($u)] ; }
415        printTop ("TOP operation hour slots", 0, @a) ;
416
417        @list = reverse (sort {$a->[1]<=>$b->[1]} @a) ;
418        if (scalar @list > $topMax) { @list = @list[0..$topMax-1] ; }
419        print $html "<h2>Operation time slots TOP users</h2>\n" ;
420        printHTMLTableHead ($html) ;
421        printHTMLTableHeadings ($html, "User", "00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23") ; 
422        foreach my $e (@list) {
423                printHTMLRowStart ($html) ;
424                printHTMLCellLeft ($html, userLink ($e->[0])) ;                 
425                my $max = 0 ;
426                foreach my $h ("00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23") {
427                        if ( (defined $opTime{$e->[0]}{$h}) and ($opTime{$e->[0]}{$h} > $max) )  { $max = $opTime{$e->[0]}{$h} ; } 
428                }
429                # print "$e->[0] $max\n" ;
430                my $value = 0 ;
431                foreach my $h ("00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23") {
432                        if (defined $opTime{$e->[0]}{$h}) { $value = $opTime{$e->[0]}{$h} ; } else { $value = 0 ; }
433                        my ($colorValue) = 255 - ( int ($value / $max * 255) / 2) ; my ($colorString) = sprintf "%02x", $colorValue ;
434                        # print "$value $colorValue $colorString\n" ;
435                        my ($htmlString) = "<td align=\"right\" bgcolor=\"#" . $colorString . $colorString . $colorString . "\">" . $value . "</td>" ;
436                        print $html $htmlString ;
437                }
438                printHTMLRowEnd ($html) ;
439        }
440        printHTMLTableFoot ($html) ;
441
442        @a = () ;
443        foreach my $e (keys %nodesMovedNumber) { push @a, [$e, $nodesMovedNumber{$e}] ; }
444        printTop ("TOP moved nodes number", 0, @a) ;
445        @a = () ;
446        foreach my $e (keys %nodesMovedDistance) { push @a, [$e, $nodesMovedDistance{$e}] ; }
447        printTop ("TOP moved nodes total distance (km)", 1, @a) ;
448        @a = () ;
449        foreach my $e (keys %nodesMovedDistance) { push @a, [$e, $nodesMovedDistance{$e}/$nodesMovedNumber{$e}] ; }
450        printTop ("TOP moved nodes average distance (km)", 1, @a) ;
451        @a = () ;
452        foreach my $e (keys %nodesMovedMax) { push @a, [$e, $nodesMovedMax{$e}] ; }
453        printTop ("TOP moved nodes maximum distance (km)", 1, @a) ;
454
455        @a = () ;
456        foreach my $u (keys %maxLon) {
457                # print "calc area for user: $u\n" ;
458                push @a, [$u, distance ($minLon{$u}, $minLat{$u}, $minLon{$u}, $maxLat{$u}) * distance ($minLon{$u}, $minLat{$u}, $maxLon{$u}, $minLat{$u})] ;
459        }
460        printTop ("TOP work areas (km²)", 1, @a) ;
461
462        @a = () ;
463        foreach my $e (keys %tagsAdded) { push @a, [$e, $tagsAdded{$e}] ; }
464        printTop ("TOP tags added", 0, @a) ;
465
466        @a = () ;
467        foreach my $e (keys %tagsRenamed) { push @a, [$e, $tagsRenamed{$e}] ; }
468        printTop ("TOP objects renamed", 0, @a) ;
469
470        @list = @a ; @list = reverse (sort {$a->[1]<=>$b->[1]} @list) ;
471        # if (scalar @list > $topMax) { @list = @list[0..$topMax-1] ; }
472        print $html "<h2>Renames by ALL users</h2>\n" ;
473        printHTMLTableHead ($html) ;
474        printHTMLTableHeadings ($html, "User", "Tag", "Number") ; 
475        foreach my $e (@list) {
476                foreach my $t (keys %{$renames{$e->[0]}}) {
477                        # printf $html "%-25s %-80s %5i<br>\n" , $e->[0], $t, $renames{$e->[0]}{$t} ;
478                        printHTMLRowStart ($html) ;
479                        printHTMLCellLeft ($html, userLink ($e->[0])) ;                 
480                        printHTMLCellLeft ($html, $t) ;                 
481                        printHTMLCellRight ($html, $renames{$e->[0]}{$t}) ;                     
482                        printHTMLRowEnd ($html) ;
483                }
484        }
485        printHTMLTableFoot ($html) ;
486
487        @a = () ;
488        foreach my $e (keys %tagsRereffed) { push @a, [$e, $tagsRereffed{$e}] ; }
489        printTop ("TOP objects rereffed", 0, @a) ;
490
491        @list = @a ; @list = reverse (sort {$a->[1]<=>$b->[1]} @list) ;
492        # if (scalar @list > $topMax) { @list = @list[0..$topMax-1] ; }
493        print $html "<h2>Rerefs by ALL users</h2>\n" ;
494        printHTMLTableHead ($html) ;
495        printHTMLTableHeadings ($html, "User", "Tag", "Number") ; 
496        foreach my $e (@list) {
497                foreach my $t (keys %{$rerefs{$e->[0]}}) {
498                        # printf $html "%-25s %-80s %5i<br>\n" , $e->[0], $t, $rerefs{$e->[0]}{$t} ;
499                        printHTMLRowStart ($html) ;
500                        printHTMLCellLeft ($html, userLink ($e->[0])) ;                 
501                        printHTMLCellLeft ($html, $t) ;                 
502                        printHTMLCellRight ($html, $rerefs{$e->[0]}{$t}) ;                     
503                        printHTMLRowEnd ($html) ;
504                }
505        }
506        printHTMLTableFoot ($html) ;
507
508        @a = () ;
509        foreach my $e (keys %tagsReclassified) { push @a, [$e, $tagsReclassified{$e}] ; }
510        printTop ("TOP ways reclassified", 0, @a) ;
511
512        @list = @a ; @list = reverse (sort {$a->[1]<=>$b->[1]} @list) ;
513        # if (scalar @list > $topMax) { @list = @list[0..$topMax-1] ; }
514        print $html "<h2>Reclassifications by ALL users</h2>\n" ;
515        printHTMLTableHead ($html) ;
516        printHTMLTableHeadings ($html, "User", "Tag", "Number") ; 
517        foreach my $e (@list) {
518                foreach my $t (keys %{$reclassifications{$e->[0]}}) {
519                        # printf $html "%-25s %-80s %5i<br>\n" , $e->[0], $t, $reclassifications{$e->[0]}{$t} ;
520                        printHTMLRowStart ($html) ;
521                        printHTMLCellLeft ($html, userLink ($e->[0])) ;                 
522                        printHTMLCellLeft ($html, $t) ;                 
523                        printHTMLCellRight ($html, $reclassifications{$e->[0]}{$t}) ;                   
524                        printHTMLRowEnd ($html) ;
525                }
526        }
527        printHTMLTableFoot ($html) ;
528
529#       print $html "<h2>Version jumps nodes by ALL users</h2>\n" ;
530#       printHTMLTableHead ($html) ;
531#       printHTMLTableHeadings ($html, "User", "Nodes") ;
532#       foreach my $u (keys %versionJumpsNodes) {
533#               printHTMLRowStart ($html) ;
534#               printHTMLCellLeft ($html, userLink ($u)) ;                     
535#               my $jumps = "" ;
536#               foreach my $v (@{$versionJumpsNodes{$u}}) {
537#                       $jumps = $jumps . historyLink ("node", $v->[0]) . " (" . $v->[1] . ") " ;
538#               }
539#               printHTMLCellLeft ($html, $jumps) ;                     
540#               printHTMLRowEnd ($html) ;
541#       }
542#       printHTMLTableFoot ($html) ;
543
544#       print $html "<h2>Version jumps ways by ALL users</h2>\n" ;
545#       printHTMLTableHead ($html) ;
546#       printHTMLTableHeadings ($html, "User", "Ways") ;
547#       foreach my $u (keys %versionJumpsWays) {
548#               printHTMLRowStart ($html) ;
549#               printHTMLCellLeft ($html, userLink ($u)) ;                     
550#               my $jumps = "" ;
551#               foreach my $v (@{$versionJumpsWays{$u}}) {
552#                       $jumps = $jumps . historyLink ("node", $v->[0]) . " (" . $v->[1] . ") " ;
553#               }
554#               printHTMLCellLeft ($html, $jumps) ;                     
555#               printHTMLRowEnd ($html) ;
556#       }
557#       printHTMLTableFoot ($html) ;
558
559        @a = () ;
560        foreach my $e (keys %tagsDeleted) { push @a, [$e, $tagsDeleted{$e}] ; }
561        printTop ("TOP tags deleted", 0, @a) ;
562
563        @list = @a ; @list = reverse (sort {$a->[1]<=>$b->[1]} @list) ;
564        if (scalar @list > $topMax) { @list = @list[0..$topMax-1] ; }
565        print $html "<h2>Tags removed by TOP users</h2>\n" ;
566        printHTMLTableHead ($html) ;
567        printHTMLTableHeadings ($html, "User", "Removed", "Number") ; 
568        foreach my $e (@list) {
569                foreach my $t (keys %{$tagsDeletedName{$e->[0]}}) {
570                        # printf $html "%-25s %-50s %5i<br>\n" , $e->[0], $t, $tagsDeletedName{$e->[0]}{$t} ;
571                        printHTMLRowStart ($html) ;
572                        printHTMLCellLeft ($html, userLink ($e->[0])) ;                 
573                        printHTMLCellLeft ($html, $t) ;                 
574                        printHTMLCellRight ($html, $tagsDeletedName{$e->[0]}{$t}) ;                     
575                        printHTMLRowEnd ($html) ;
576                }
577        }
578        printHTMLTableFoot ($html) ;
579
580        print $html "<h2>ALL deleted Nodes with tags (details)</h2>\n" ;
581        printHTMLTableHead ($html) ;
582        printHTMLTableHeadings ($html, "NodeId", "Tags") ; 
583        foreach my $n (@deletedNodesIds) {
584                printHTMLRowStart ($html) ;
585                printHTMLCellLeft ($html, historyLink ("node", $n) ) ;                 
586                my $tagText = "" ;
587                foreach my $t (@{$deletedNodesTags{$n}}) { $tagText = $tagText . $t->[0] . ":" . $t->[1] . "<br>\n" ; }
588                printHTMLCellLeft ($html, $tagText) ;   
589                printHTMLRowEnd ($html) ;
590        }
591        printHTMLTableFoot ($html) ;
592
593        print $html "<h2>ALL deleted ways with tags (details)</h2>\n" ;
594        printHTMLTableHead ($html) ;
595        printHTMLTableHeadings ($html, "WayId", "Tags") ; 
596        foreach my $n (@deletedWaysIds) {
597                printHTMLRowStart ($html) ;
598                printHTMLCellLeft ($html, historyLink ("way", $n) ) ;                   
599                my $tagText = "" ;
600                foreach my $t (@{$deletedWaysTags{$n}}) { $tagText = $tagText . $t->[0] . ":" . $t->[1] . "<br>\n" ; }
601                printHTMLCellLeft ($html, $tagText) ;   
602                printHTMLRowEnd ($html) ;
603        }
604        printHTMLTableFoot ($html) ;
605
606        printHTMLFoot ($html) ;
607        print $html "<p>$program finished after ", stringTimeSpent (time()-$time0), "</p>\n" ;
608        close ($html) ;
609
610        print "done.\n" ;
611}
612
613sub printTop {
614        my ($heading, $decimal, @list) = @_ ;
615        print $html "<h2>$heading</h2>\n" ;
616        printHTMLTableHead ($html) ;
617        printHTMLTableHeadings ($html, "User", "Data") ; 
618        @list = reverse (sort {$a->[1]<=>$b->[1]} @list) ;
619        if (scalar @list > $topMax) { @list = @list[0..$topMax-1] ; }
620        foreach my $e (@list) {
621                printHTMLRowStart ($html) ;
622                my $s ;
623                if ($decimal) { 
624                        $s = sprintf "%8.3f", $e->[1] ;
625                }
626                else {
627                        $s = sprintf "%8i", $e->[1] ;
628                }
629                printHTMLCellLeft ($html, userLink ($e->[0]) ) ;                       
630                printHTMLCellRight ($html, $s) ;                       
631                printHTMLRowEnd ($html) ;
632        } 
633        printHTMLTableFoot ($html) ;
634}
635
636
637#------------------------------------------------------------------------------------
638# some functions
639#------------------------------------------------------------------------------------
640
641sub addOperationTime {
642        my ($user, $timestamp) = @_ ;
643        # timestamp="2008-04-13T13:23:55+01:00"
644        my ($hour) = substr ($timestamp, 11, 2) ;
645        $opTime{$user}{$hour}++ ;
646}
647
648sub numOpHours {
649        my ($user) = shift ;
650        my $hours = 0 ;
651        foreach my $hour ("00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23") {
652                if (defined $opTime{$user}{$hour}) { $hours++ ; }
653        }
654        return ($hours) ;
655}
656
657sub userAreaWay {
658        my ($u, $n) = @_ ;
659        if (grep /P/, $mode) {
660                userArea ($u, $lon2{$n}, $lat2{$n}) ;
661        }
662        else {
663                $neededNodes{$n} = $u ;
664        }
665}
666
667sub processNeededWayNodes {
668        print "get needed nodes for touched ways...\n" ;
669        openOsm2File ($osm2Name) ;
670        moveNodeFile2() ;
671        while ( $nodeId2 != -1 ) {
672                if (defined $neededNodes{$nodeId2}) {
673                        userArea ($neededNodes{$nodeId2}, $nodeLon2, $nodeLat2) ;
674                }
675                moveNodeFile2() ;
676        }
677        closeOsm2File () ;
678        print "done.\n" ;
679}
680
681sub userArea {
682        my ($u, $lon, $lat) = @_ ;
683
684        if ( (!defined $lon) or (! defined $lat) ) {
685                print "userArea ERROR user $u nodes $nodeId1 $nodeId2 ways $wayId1 $wayId2\n" ;
686        }
687
688        if (! defined $maxLon{$u}) {
689                $minLon{$u} = $lon ;
690                $minLat{$u} = $lat ;
691                $maxLon{$u} = $lon ;
692                $maxLat{$u} = $lat ;
693        }
694        else {
695                if ($lon > $maxLon{$u}) { $maxLon{$u} = $lon ; }
696                if ($lon < $minLon{$u}) { $minLon{$u} = $lon ; }
697                if ($lat > $maxLat{$u}) { $maxLat{$u} = $lat ; }
698                if ($lat < $minLat{$u}) { $minLat{$u} = $lat ; }
699        }
700}
701
702sub compareTags {
703        my ($aRef1, $aRef2) = @_ ;
704        my $added = 0 ; my $deleted = 0 ; my $renamed = 0 ; my $reclassified = 0 ; my $rereffed = 0 ;
705        my (@tags1) = @$aRef1 ; my (@tags2) = @$aRef2 ;
706
707        $reName = 0 ; $reClass = 0 ; $reRef = 0 ;
708
709        # RENAMED?
710        my $nameGiven = 0 ;
711        my $nameOld = "" ; 
712        my $nameNew = "" ;
713        foreach my $t (@tags1) { 
714                if ($t->[0] eq "name") { $nameGiven = 1 ; $nameOld = $t->[1] ; }
715        }
716        foreach my $t (@tags2) { 
717                if ($t->[0] eq "name") { $nameNew = $t->[1] ; }
718        }
719        if ( ($nameGiven == 1) and ($nameNew ne $nameOld) ) { 
720                $renamed = 1 ; 
721                $renames{$nodeUser2}{$nameOld . " > " . $nameNew} ++ ;
722                $reName = 1 ; $name1 = $nameOld ; $name2 = $nameNew ;
723        }
724       
725        if ($objectProcessed == 1 ) {
726                # REREF?
727                my $refGiven = 0 ;
728                my $refOld = "" ; 
729                my $refNew = "" ;
730                foreach my $t (@tags1) { 
731                        if ($t->[0] eq "ref") { $refGiven = 1 ; $refOld = $t->[1] ; }
732                }
733                foreach my $t (@tags2) { 
734                        if ($t->[0] eq "ref") { $refNew = $t->[1] ; }
735                }
736                if ( ($refGiven == 1) and ($refNew ne $refOld) ) { 
737                        $rereffed = 1 ; 
738                        $rerefs{$wayUser2}{$refOld . " > " . $refNew} ++ ;
739                        $reRef = 1 ; $ref1 = $refOld ; $name2 = $refNew ;
740                }
741                # RECLASSIFIED?
742                my $highwayGiven = 0 ;
743                my $highwayOld = "" ;
744                my $highwayNew = "" ;
745                foreach my $t (@tags1) { 
746                        if ($t->[0] eq "highway") { $highwayGiven = 1 ; $highwayOld = $t->[1] ; }
747                }
748                foreach my $t (@tags2) { 
749                        if ($t->[0] eq "highway") { $highwayNew = $t->[1] ; }
750                }
751                if ( ($highwayGiven == 1) and ($highwayNew ne $highwayOld) ) { 
752                        $reclassified = 1 ; 
753                        $reclassifications{$wayUser2}{$highwayOld . " > " . $highwayNew} ++ ;
754                        $reClass = 1 ; $class1 = $highwayOld ; $class2 = $highwayNew ;
755                }
756        } # objectProcessed
757
758        # ADDED?
759        foreach my $t2 (@tags2) {
760                my $found = 0 ;
761                foreach my $t1 (@tags1) {
762                        if ( ($t1->[0] eq $t2->[0]) and ($t1->[1] eq $t2->[1]) ) { $found = 1 ; }
763                }
764                if ($found == 0) { $added++ ; }
765        }
766
767        # DELETED?
768        foreach my $t1 (@tags1) {
769                my $found = 0 ;
770                foreach my $t2 (@tags2) {
771                        if ( ($t1->[0] eq $t2->[0]) and ($t1->[1] eq $t2->[1]) ) { $found = 1 ; }
772                }
773                # if ($found == 0) {
774                if ( ($found == 0) and ($t1->[0] ne "created_by") ) { 
775                        $deleted++ ; 
776                        $tagsDeletedName{$nodeUser2}{$t1->[0].":".$t1->[1]}++ ;
777                }
778        }
779
780        return ($added, $deleted, $renamed, $reclassified, $rereffed) ;
781} # compareTags
782
783sub userLink {
784        my ($user) = shift ;
785        return "<a href=\"http://www.openstreetmap.org/user/" . $user . "\">" . $user . "</a>" ;
786}
787
788
789
790#------------------------------------------------------------------------------------
791# Map functions
792#------------------------------------------------------------------------------------
793
794sub paintNewWay {
795        drawWay ("black", 2, nodes2Coordinates2 (@wayNodes2) ) ;
796        if (grep /D/, $mode) { drawTextPos ($lon2{$wayNodes2[0]}, $lat2{$wayNodes2[0]}, 0, 0, $wayUser2, "black", 2) ; }
797}
798
799sub paintDeletedWay {
800        drawWay ("red", 2, nodes2Coordinates1 (@wayNodes1) ) ;
801}
802
803sub paintDeletedWayWithTag {
804        drawWay ("red", 3, nodes2Coordinates1 (@wayNodes1) ) ;
805}
806
807sub paintRenamedWay {
808        drawWay ("orange", 3, nodes2Coordinates1 (@wayNodes1) ) ;
809        if (grep /D/, $mode) { 
810                drawTextPos ($lon1{$wayNodes1[0]}, $lat1{$wayNodes1[0]}, 0, 0, $wayUser2, "orange", 2) ; 
811                drawTextPos ($lon1{$wayNodes1[0]}, $lat1{$wayNodes1[0]}, 0, -8, $name1 . "->" . $name2, "black", 2) ; 
812        }
813}
814
815sub paintRereffedWay {
816        drawWay ("orange", 3, nodes2Coordinates1 (@wayNodes1) ) ;
817        if (grep /D/, $mode) { 
818                drawTextPos ($lon1{$wayNodes1[0]}, $lat1{$wayNodes1[0]}, 0, 0, $wayUser2, "orange", 2) ; 
819                drawTextPos ($lon1{$wayNodes1[0]}, $lat1{$wayNodes1[0]}, 0, -8, $ref1 . "->" . $ref2, "black", 2) ; 
820        }
821}
822
823sub paintReclassifiedWay {
824        drawWay ("pink", 3, nodes2Coordinates1 (@wayNodes1) ) ;
825        if (grep /D/, $mode) { 
826                drawTextPos ($lon1{$wayNodes1[0]}, $lat1{$wayNodes1[0]}, 0, 0, $wayUser2, "pink", 2) ; 
827                drawTextPos ($lon1{$wayNodes1[0]}, $lat1{$wayNodes1[0]}, 0, -8, $class1 . "->" . $class2, "black", 2) ; 
828        }
829}
830
831sub paintMovedWay {
832}
833
834
835sub paintNewNode {
836        drawNodeDot ($nodeLon2, $nodeLat2, "black", 4) ;
837        if (grep /D/, $mode) { drawTextPos ($nodeLon2, $nodeLat2, 0, 0, $nodeUser2, "black", 2) ; }
838}
839
840sub paintDeletedNode {
841        drawNodeDot ($nodeLon1, $nodeLat1, "red", 4) ;
842}
843
844sub paintDeletedNodeWithTag {
845        drawNodeDot ($nodeLon1, $nodeLat1, "red", 5) ;
846}
847
848sub paintRenamedNode {
849        drawNodeDot ($nodeLon1, $nodeLat1, "orange", 4) ;
850        if (grep /D/, $mode) { 
851                drawTextPos ($nodeLon1, $nodeLat1, 0, 0, $nodeUser2, "orange", 2) ; 
852                drawTextPos ($nodeLon1, $nodeLat1, 0, -8, $name1 . "->" . $name2, "black", 2) ; 
853        }
854}
855
856sub paintMovedNode {
857        # blue
858        drawNodeDot ($nodeLon1, $nodeLat1, "lightblue", 4) ;
859        drawWay ("lightblue", 1, ($nodeLon1, $nodeLat1, $nodeLon2, $nodeLat2) ) ;
860        drawNodeDot ($nodeLon2, $nodeLat2, "blue", 4) ;
861        if (grep /D/, $mode) { drawTextPos ($nodeLon1, $nodeLat1, 0, 0, $nodeUser2, "blue", 2) ; }
862}
863
864sub paintAreas {
865        foreach my $user (keys %minLon) {
866                drawWay ("tomato", 1, $minLon{$user}, $minLat{$user}, $minLon{$user}, $maxLat{$user}, $maxLon{$user}, $maxLat{$user}, $maxLon{$user}, $minLat{$user}, $minLon{$user}, $minLat{$user} ) ;
867                drawTextPos ($minLon{$user}, $minLat{$user}, 0, 0, $user, "black", 2) ;
868        }
869}
870
871sub paintPlace {
872        my ($lon, $lat, $name) = @_ ;
873        drawTextPos ($lon, $lat, 0, 0, $name, "black", 4) ;     
874        drawNodeDot ($lon, $lat, "black", 2) ;
875}
876
877sub initializeMap {
878        print "initializing map...\n" ;
879        print "- parsing nodes file1...\n" ;
880        my $lonMax = -999 ; my $lonMin = 999 ; my $latMax = -999 ; my $latMin = 999 ;
881        openOsm1File ($osm1Name) ;
882        moveNodeFile1() ;       
883
884        # get all node information from file 1         
885        while ($nodeId1 != -1) {
886                $lon1{$nodeId1} = $nodeLon1 ; $lat1{$nodeId1} = $nodeLat1 ;
887                if ($nodeLon1 > $lonMax) { $lonMax = $nodeLon1 ; }
888                if ($nodeLat1 > $latMax) { $latMax = $nodeLat1 ; }
889                if ($nodeLon1 < $lonMin) { $lonMin = $nodeLon1 ; }
890                if ($nodeLat1 < $latMin) { $latMin = $nodeLat1 ; }
891                # next
892                moveNodeFile1() ;       
893        }
894        initGraph ($sizeX, $lonMin, $latMin, $lonMax, $latMax) ;
895        if (grep /S/, $mode) {
896                enableSVG() ;
897        }
898
899        # ways
900        print "- parsing ways file1...\n" ;
901        moveWayFile1() ;
902        while ($wayId1 != -1) {
903                drawWay ("lightgray", 1, nodes2Coordinates1 (@wayNodes1) ) ;
904                moveWayFile1() ;
905        }
906        closeOsm1File() ;
907
908        print "- parsing nodes file2...\n" ;
909        openOsm2File ($osm2Name) ;
910        moveNodeFile2() ;
911
912        # get all node information from file 2
913        while ($nodeId2 != -1) {
914                $lon2{$nodeId2} = $nodeLon2 ; $lat2{$nodeId2} = $nodeLat2 ;
915                # next
916                moveNodeFile2() ;
917        }
918        closeOsm2File() ;
919
920        print "done.\n" ;
921}
922
923sub saveMap {
924        print "saving map...\n" ;
925        drawHead ($program . " ". $version . " by Gary68", "black", 3) ;
926        drawFoot ("data by openstreetmap.org" . " " . $osm1Name . " " .ctime(stat($osm1Name)->mtime) . $osm2Name . " " .ctime(stat($osm2Name)->mtime), "black", 3) ;
927        drawLegend (3, "New", "black", "Deleted", "red", "Moved", "blue", "Renamed", "orange", "Reclassified", "pink", "User Area", "tomato") ;
928        drawRuler ("black") ;
929        my ($pngName) = $htmlName ;
930        $pngName =~ s/.htm/.png/ ;
931        writeGraph ($pngName) ; 
932        if (grep /S/, $mode) {
933                my ($svgName) = $htmlName ;
934                $svgName =~ s/.htm/.svg/ ;
935                writeSVG ($svgName) ; 
936        }
937        print "done.\n" ;
938}
939
940sub nodes2Coordinates1 {
941        my @nodes = @_ ;
942        my $i ;
943        my @result = () ;
944        for ($i=0; $i<=$#nodes; $i++) {
945                push @result, $lon1{$nodes[$i]} ;
946                push @result, $lat1{$nodes[$i]} ;
947        }
948        return @result ;
949}
950
951sub nodes2Coordinates2 {
952        my @nodes = @_ ;
953        my $i ;
954        my @result = () ;
955        for ($i=0; $i<=$#nodes; $i++) {
956                push @result, $lon2{$nodes[$i]} ;
957                push @result, $lat2{$nodes[$i]} ;
958        }
959        return @result ;
960}
961
962
963
964#------------------------------------------------------------------------------------
965# Basic object operations
966#------------------------------------------------------------------------------------
967
968sub getNode1 {
969        my ($id, $version, $timestamp, $uid, $user, $changeset, $lat, $lon) ;
970        my @gTags = () ;
971        if($line1 =~ /^\s*\<node/) {
972                if (! grep /changeset/, $line1) { $line1 =~ s/lat=/changeset=\"0\" lat=/ ; }
973                if ( (grep /user=/, $line1) and (grep /uid=/, $line1) ) {
974                        ($id, $version, $timestamp, $uid, $user, $changeset, $lat, $lon) = 
975                        ($line1 =~ /^\s*\<node id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+uid=[\'\"](.+)[\'\"].+user=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"].+lat=[\'\"](.+)[\'\"].+lon=[\'\"](.+)[\'\"]/) ;
976                }
977                else {
978                        ($id, $version, $timestamp, $changeset, $lat, $lon) = 
979                        ($line1 =~ /^\s*\<node id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"].+lat=[\'\"](.+)[\'\"].+lon=[\'\"](.+)[\'\"]/) ;
980                        $user = "unknown" ; $uid = 0 ;
981                }
982                if (!defined $user) { $user = "unknown" ; }
983                if (!defined $uid) { $uid = 0 ; }
984
985                if (!$id or (! (defined ($lat))) or ( ! (defined ($lon))) ) {
986                        print "WARNING reading osm file1, line follows (expecting id, lon, lat and user for node):\n", $line1, "\n" ; 
987                }
988                else {
989                        if ( (grep (/">/, $line1)) or (grep (/'>/, $line1)) ) {                  # more lines, get tags
990                                nextLine1() ;
991                                while (!grep(/<\/node>/, $line1)) {
992                                        my ($k, $v) = ($line1 =~ /^\s*\<tag k=[\'\"](.+)[\'\"]\s*v=[\'\"](.+)[\'\"]/) ;
993                                        if ( (defined ($k)) and (defined ($v)) ) {
994                                                my $tag = [$k, $v] ; push @gTags, $tag ;
995                                        }
996                                        else { 
997                                                #print "WARNING tag not recognized file1: ", $line1, "\n" ;
998                                        }
999                                        nextLine1() ;
1000                                }
1001                                nextLine1() ;
1002                        }
1003                        else {
1004                                nextLine1() ;
1005                        }
1006                }
1007        }
1008        else {
1009                return (-1, -1, -1, -1, -1) ; 
1010        } # node
1011        return ($id, $version, $timestamp, $uid, $user, $changeset, $lat, $lon, \@gTags) ; # in main @array = @$ref
1012} # getNode1
1013
1014sub getNodeFile2 {
1015        my ($id, $version, $timestamp, $uid, $user, $changeset, $lat, $lon) ;
1016        my @gTags = () ;
1017        if($line2 =~ /^\s*\<node/) {
1018                if (! grep /changeset/, $line2) { $line2 =~ s/lat=/changeset=\"0\" lat=/ ; }
1019                if ( (grep /user=/, $line2) and (grep /uid=/, $line2) ) {
1020                        ($id, $version, $timestamp, $uid, $user, $changeset, $lat, $lon) = 
1021                        ($line2 =~ /^\s*\<node id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+uid=[\'\"](.+)[\'\"].+user=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"].+lat=[\'\"](.+)[\'\"].+lon=[\'\"](.+)[\'\"]/) ;
1022                }
1023                else {
1024                        ($id, $version, $timestamp, $changeset, $lat, $lon) = 
1025                        ($line2 =~ /^\s*\<node id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"].+lat=[\'\"](.+)[\'\"].+lon=[\'\"](.+)[\'\"]/) ;
1026                        $user = "unknown" ; $uid = 0 ;
1027                }
1028                if (!defined $user) { $user = "unknown" ; }
1029                if (!defined $uid) { $uid = 0 ; }
1030
1031                if (!$id or (! (defined ($lat))) or ( ! (defined ($lon))) ) {
1032                        print "WARNING reading osm file 2, line follows (expecting id, lon, lat and user for node):\n", $line2, "\n" ; 
1033                }
1034                else {
1035                        if ( (grep (/">/, $line2)) or (grep (/'>/, $line2)) ) {                  # more lines, get tags
1036                                nextLine2() ;
1037                                while (!grep(/<\/node>/, $line2)) {
1038                                        my ($k, $v) = ($line2 =~ /^\s*\<tag k=[\'\"](.+)[\'\"]\s*v=[\'\"](.+)[\'\"]/) ;
1039                                        if ( (defined ($k)) and (defined ($v)) ) {
1040                                                my $tag = [$k, $v] ; push @gTags, $tag ;
1041                                        }
1042                                        else { 
1043                                                #print "WARNING tag not recognized file 2: ", $line2, "\n" ;
1044                                        }
1045                                        nextLine2() ;
1046                                }
1047                                nextLine2() ;
1048                        }
1049                        else {
1050                                nextLine2() ;
1051                        }
1052                }
1053        }
1054        else {
1055                return (-1, -1, -1, -1, -1) ; 
1056        } # node
1057        return ($id, $version, $timestamp, $uid, $user, $changeset, $lat, $lon, \@gTags) ; # in main @array = @$ref
1058} # getNodeFile2
1059
1060
1061
1062sub getWay1 {
1063        my $id ; my $u ; my @tags ; my @nodes ; my $version ; my $timestamp ; my $uid ; my $changeset ;
1064        if($line1 =~ /^\s*\<way/) {
1065
1066                if (! grep /changeset/, $line1) { $line1 =~ s/\">/\" changeset=\"0\">/ ; }
1067                if ( (grep /user=/, $line1) and (grep /uid=/, $line1) ) {
1068                        ($id, $version, $timestamp, $uid, $u, $changeset) = ($line1 =~ /^\s*\<way id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+uid=[\'\"](\d+)[\'\"].+user=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"]>/) ;
1069                }
1070                else {
1071                        ($id, $version, $timestamp, $changeset) = ($line1 =~ /^\s*\<way id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"]>/) ;
1072                        $uid = 0 ; $u = "unknown" ;
1073                }
1074
1075                if (!$u) { $u = "unknown" ; }
1076                if (!$id) { print "ERROR reading osm file1, line follows (expecting way id):\n", $line1, "\n" ; }
1077                unless ($id) { next; }
1078                nextLine1() ;
1079                while (not($line1 =~ /\/way>/)) { # more way data
1080                        my ($node) = ($line1 =~ /^\s*\<nd ref=[\'\"](\d+)[\'\"]/); # get node id
1081                        my ($k, $v) = ($line1 =~ /^\s*\<tag k=[\'\"](.+)[\'\"]\s*v=[\'\"](.+)[\'\"]/) ;
1082                        if ($node) {
1083                                push @nodes, $node ;
1084                        }
1085                        if ($k and defined($v)) { my $tag = [$k, $v] ; push @tags, $tag ; }
1086                        nextLine1() ;
1087                }
1088                nextLine1() ;
1089        }
1090        else {
1091                return (-1, -1, -1, -1, -1, -1, -1, -1) ;
1092        }
1093        return ($id, $version, $timestamp, $uid, $u, $changeset, \@nodes, \@tags) ;
1094} # getWay1
1095
1096sub getWayFile2 {
1097        my $id ; my $u ; my @tags ; my @nodes ; my $version ; my $timestamp ; my $uid ; my $changeset ;
1098        if($line2 =~ /^\s*\<way/) {
1099
1100                if (! grep /changeset/, $line2) { $line2 =~ s/\">/\" changeset=\"0\">/ ; }
1101                if ( (grep /user=/, $line2) and (grep /uid=/, $line2) ) {
1102                        ($id, $version, $timestamp, $uid, $u, $changeset) = ($line2 =~ /^\s*\<way id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+uid=[\'\"](\d+)[\'\"].+user=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"]>/) ;
1103                }
1104                else {
1105                        ($id, $version, $timestamp, $changeset) = ($line2 =~ /^\s*\<way id=[\'\"](\d+)[\'\"].+version=[\'\"](\d+)[\'\"].+timestamp=[\'\"](.+)[\'\"].+changeset=[\'\"](\d+)[\'\"]>/) ;
1106                        $uid = 0 ; $u = "unknown" ;
1107                }
1108                if (!$u) { $u = "unknown" ; }
1109                if (!$id) { print "ERROR reading osm file2, line follows (expecting way id):\n", $line1, "\n" ; }
1110                unless ($id) { next; }
1111                nextLine2() ;
1112                while (not($line2 =~ /\/way>/)) { # more way data
1113                        my ($node) = ($line2 =~ /^\s*\<nd ref=[\'\"](\d+)[\'\"]/); # get node id
1114                        my ($k, $v) = ($line2 =~ /^\s*\<tag k=[\'\"](.+)[\'\"]\s*v=[\'\"](.+)[\'\"]/) ;
1115                        if ($node) {
1116                                push @nodes, $node ;
1117                        }
1118                        if ($k and defined($v)) { my $tag = [$k, $v] ; push @tags, $tag ; }
1119                        nextLine2() ;
1120                }
1121                nextLine2() ;
1122        }
1123        else {
1124                return (-1, -1, -1, -1, -1, -1, -1, -1) ;
1125        }
1126        return ($id, $version, $timestamp, $uid, $u, $changeset, \@nodes, \@tags) ;
1127} # getWayFile2
1128
1129
1130sub moveNodeFile1 {
1131        ($nodeId1, $nodeVersion1, $nodeTimestamp1, $nodeUid1, $nodeUser1, $nodeChangeset1, $nodeLat1, $nodeLon1, $aRef1) = getNode1 () ;
1132        if ($nodeId1 != -1) {
1133                @nodeTags1 = @$aRef1 ;
1134        }
1135}
1136
1137sub moveNodeFile2 {
1138        ($nodeId2, $nodeVersion2, $nodeTimestamp2, $nodeUid2, $nodeUser2, $nodeChangeset2, $nodeLat2, $nodeLon2, $aRef1) = getNodeFile2 () ;
1139        if ($nodeId2 != -1) {
1140                @nodeTags2 = @$aRef1 ;
1141        }
1142}
1143
1144sub moveWayFile1 {
1145        ($wayId1, $wayVersion1, $wayTimestamp1, $wayUid1, $wayUser1, $wayChangeset1, $aRef1, $aRef2) = getWay1() ;
1146        if ($wayId1 != -1) {
1147                @wayNodes1 = @$aRef1 ;
1148                @wayTags1 = @$aRef2 ;
1149        }
1150}
1151
1152sub moveWayFile2 {
1153        ($wayId2, $wayVersion2, $wayTimestamp2, $wayUid2, $wayUser2, $wayChangeset2, $aRef1, $aRef2) = getWayFile2() ;
1154        if ($wayId2 != -1) {
1155                @wayNodes2 = @$aRef1 ;
1156                @wayTags2 = @$aRef2 ;
1157        }
1158}
1159
1160
1161#------------------------------------------------------------------------------------
1162# Basic file operations
1163#------------------------------------------------------------------------------------
1164
1165sub openOsm1File {
1166        $file1Name = shift ;
1167        if (grep /.bz2/, $file1Name) { $isBz21 = 1 ; } else { $isBz21 = 0 ; }
1168        if ($isBz21) {
1169                $bz1 = bzopen($file1Name, "rb") or die "Cannot open $file1Name: $bzerrno\n" ;
1170        }
1171        else {
1172                open ($file1, "<", $file1Name) || die "can't open osm file1" ;
1173        }
1174        nextLine1() ;           
1175        while ( ! (grep /\<node/, $line1) ) {
1176                nextLine1() ;
1177        }
1178        return 1 ;
1179}
1180
1181sub closeOsm1File {
1182        if ($isBz21) { $bz1->bzclose() ; }
1183        else { close ($file1) ; }
1184}
1185
1186sub nextLine1 {
1187        if ($isBz21) { $bz1->bzreadline($line1) ; }
1188        else { $line1 = <$file1> ; }
1189}
1190
1191sub openOsm2File {
1192        $file2Name = shift ;
1193        if (grep /.bz2/, $file2Name) { $isBz22 = 1 ; } else { $isBz22 = 0 ; }
1194        if ($isBz22) {
1195                $bz2 = bzopen($file2Name, "rb") or die "Cannot open $file2Name: $bzerrno\n" ;
1196        }
1197        else {
1198                open ($file2, "<", $file2Name) || die "can't open osm file2" ;
1199        }
1200        nextLine2() ;           
1201        while ( ! (grep /\<node/, $line2) ) {
1202                nextLine2() ;
1203        }
1204        return 1 ;
1205}
1206
1207sub closeOsm2File {
1208        if ($isBz22) { $bz2->bzclose() ; }
1209        else { close ($file2) ; }
1210}
1211
1212sub nextLine2 {
1213        if ($isBz22) { $bz2->bzreadline($line2) ; }
1214        else { $line2 = <$file2> ; }
1215}
1216
Note: See TracBrowser for help on using the repository browser.