source: subversion/applications/utils/gary68/unmappedplaces.pl @ 26424

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

initial upload of several programs

  • Property svn:executable set to *
File size: 12.7 KB
Line 
1#!/usr/bin/perl
2#
3# unmappedplaces.pl
4# program takes osm file and outputs unmapped and potentially unmapped places in html or openlayers poi format
5#
6# written by Gary68
7#
8# Copyright (C) 2008, Gerhard Schwanz
9#
10# This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the
11# Free Software Foundation; either version 3 of the License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>
17#
18# v4
19# - new output format
20#
21# v5
22# - places eingeschränkt
23#
24# v6
25# - sorted output
26# - unmapped / sparsely mapped
27# - different parameters for different places
28# - output for slippy map openlayers
29# - much better performance
30# - time spent format changed
31# - count of more places
32# - file date now shown in stats
33# - grouped lists
34# v61
35# - minor bug fixed regarding major cities/towns in vincinity
36#
37# v62
38# - other symbol names and sizes
39#
40# v63
41# - error correction
42#
43
44
45use strict;
46use warnings;
47
48use File::stat;
49use Time::localtime;
50
51use Exporter ;
52
53# constants
54my $version = "6.3" ;
55my $usage = "usage:  unmappedplaces.pl <osmfile> <htmlfile> <slippyfile>\n" ;
56my %dists ; # in km // STAY BELOW 10km !!!
57$dists{"city"} =  4.0 ;
58$dists{"town"} =  1.0 ;
59$dists{"suburb"} =  0.5 ;
60$dists{"village"} =  0.5 ;
61
62my %sparse ; # in km
63$sparse{"city"} =  4800 ;
64$sparse{"town"} =  400 ;
65$sparse{"suburb"} =  60 ;
66$sparse{"village"} =  60 ;
67
68my %unmapped ; # in km
69$unmapped{"city"} =  2400 ;
70$unmapped{"town"} =  200 ;
71$unmapped{"suburb"} =  30 ;
72$unmapped{"village"} =  30 ;
73
74my $iconRed = "unmapped_red.png" ;
75my $iconYellow = "unmapped_yellow.png" ;
76
77# variables
78my $dist ;
79my $node_count = 0 ;
80my $city_count = 0 ;
81my $town_count = 0 ;
82my $village_count = 0 ;
83my $suburb_count = 0 ;
84
85my $place_count = 0 ;
86my $unmapped = 0 ;
87my $sparselyMapped = 0 ;
88
89my $placekey ;
90my $placekey1 ;
91my $placekey2 ;
92my $nodekey ;
93my $progress ;
94my $i ;
95my $key ;
96my $key2 ;
97
98my $place_type_temp ;
99my $place_name_temp ;
100
101my $d_lat ;
102my $d_lon ;
103
104my $time0 ;
105my $time1 ;
106my $time2 ;
107my $timespent ;
108
109my $html_file ;
110my $slippy_file ;
111
112my %node_lon ;
113my %node_lat ;
114
115my %place_name ;
116my %place_type ;
117my %place_lon ;
118my %place_lat ;
119my %place_nodes_inside ;
120my %place_superior ;
121my %place_superior_dist ;
122
123my %node_hash ;
124my $hash_value ;
125
126my @outputData ;
127my @outputDataSorted ;
128my %outputGrouped ;
129
130# get filename from cmd line
131my $xml = shift||'';
132if (!$xml)
133{
134        print STDERR $usage ;
135        die () ;
136}
137
138# file present?
139unless( -f $xml || $xml eq "-" ) {
140        die("input file '$xml' not found\n");
141}
142
143my $html = shift||'';
144if (!$html)
145{
146        print STDERR $usage ;
147        die () ;
148}
149
150my $slippyout = shift||'';
151if (!$slippyout)
152{
153        print STDERR $usage ;
154        die () ;
155}
156
157$time0 = time() ;
158
159# open input file
160open(XML, "<$xml") or die("$!");
161
162# parse data
163while(my $line = <XML>) {
164
165        # node data
166        if($line =~ /^\s*\<node/) {
167                # get all needed information
168                my ($id)   = ($line =~ /^\s*\<node id=[\'\"](\d+)[\'\"]/); # get node id
169                my ($lon) = ($line =~ /^.+lon=[\'\"]([\d,\.\-]+)[\'\"]/);    # get position
170                my ($lat) = ($line =~ /^.+lat=[\'\"]([\d,\.\-]+)[\'\"]/);    # get position
171
172                unless ($id) { next; }
173                unless ($lat) { next; }
174                unless ($lon) { next; }
175
176                # print "Node: ", $id, "\n" ;
177                $node_count++ ;
178
179                #store node
180                $node_lon {$id} = $lon ;
181                $node_lat {$id} = $lat ;
182
183                # put in hash
184                $hash_value = hashValue ($lon, $lat) ;
185                #print $hash_value, "\n" ;
186                push @{$node_hash {$hash_value}}, $id ;
187
188                if ($line =~ /\//) {
189                } 
190                else {
191                        # print "processing tags...\n" ;
192                        #get tags
193                        $place_type_temp ="" ;
194                        $place_name_temp = "" ;
195                        while (not($line =~ /\/node/)) {
196                                $line = <XML> ;
197                                # print $line, "\n" ;
198                                my ($key)   = ($line =~ /^\s*\<tag k=[\'\"](\w+)[\'\"]/); # get key
199                                # my ($value)   = ($line =~ /^\s*v=[\'\"](\w+)[\'\"]/); # get value
200                                #my ($value) = ($line =~ /^.+v=[\'\"](\w+)[\'\"]/);       # get value // PROBLEM WITH UMLAUTE
201
202                                my ($value) = ($line =~ /v=[\'\"](.*)[\'\"]/) ; # NEW
203                               
204                                unless ($key) { next; }
205                                unless ($value) { next; }
206
207                                if ($key eq "place") {
208                                        $place_type_temp = $value ;
209                                }                       
210                                if ($key eq "name") {
211                                        $place_name_temp = $value ;
212
213                                }       
214                                # print "K/v: ", $key, "/", $value, "\n" ;
215                        }
216                        if (($place_type_temp ne "") and ($place_name_temp ne "") and 
217                                ( ($place_type_temp eq "city") or ($place_type_temp eq "town") or 
218                                ($place_type_temp eq "village") or ($place_type_temp eq "suburb") ) ) {
219                                $place_name {$id} = $place_name_temp ;
220                                $place_type {$id} = $place_type_temp ;
221                                $place_lat {$id} = $lat ;
222                                $place_lon {$id} = $lon ;
223                                $place_nodes_inside {$id} = 0 ;
224                                $place_count = $place_count + 1 ;
225                                if ($place_type_temp eq "city") { $city_count++ } ;
226                                if ($place_type_temp eq "town") { $town_count++ } ;
227                                if ($place_type_temp eq "village") { $village_count++ } ;
228                                if ($place_type_temp eq "suburb") { $suburb_count++ } ;
229                                #print $place_type_temp, " ", $place_name_temp, " ", $lon, " ", $lat, "\n" ;
230                        }
231                }               
232        }
233}
234
235#foreach $placekey (keys %node_hash) {
236#       print $placekey, " " ;
237#       foreach (@{$node_hash{$placekey}}) {
238#               print $_, " " ;
239#       }
240#       print "\n" ;
241#}
242
243$time1 = time() ;
244
245$i = 0 ;
246foreach $placekey (keys %place_name) {
247        $i++ ;
248        $progress = int ($i / $place_count * 100) ;
249        if ($i % 10 == 0) { print $xml, " ", $progress, "%\n" ; }
250
251        #print "Name: ", $place_name{$placekey}, "\n" ;
252        #print "Type: ", $place_type{$placekey}, "\n" ;
253        #print "max dist: ", $dists{$place_type{$placekey}}, "\n" ;
254       
255        my $lo ;
256        my $la ;
257        for ($lo=$place_lon{$placekey}-0.1; $lo<=$place_lon{$placekey}+0.1; $lo=$lo+0.1) {
258                for ($la=$place_lat{$placekey}-0.1; $la<=$place_lat{$placekey}+0.1; $la=$la+0.1) {
259                        #print $lo, " ", $la, "\n" ;
260                        $hash_value = hashValue ($lo, $la) ;
261               
262                        #if (defined @{$node_hash{$hash_value}}) {
263                                early1: foreach $nodekey ( @{$node_hash{$hash_value}} ) {
264                                        #print $nodekey, "\n" ;
265                                        my $d_lat = ($node_lat{$nodekey} - $place_lat{$placekey}) * 111.11 ;
266                                        my $d_lon = ($node_lon{$nodekey} - $place_lon{$placekey}) * cos ( $node_lat{$nodekey} / 360 * 3.14 * 2 ) * 111.11;
267                                        $dist = sqrt ($d_lat*$d_lat+$d_lon*$d_lon);
268                                        if ($dist < $dists{$place_type{$placekey}}) {
269                                                $place_nodes_inside {$placekey} = $place_nodes_inside {$placekey} + 1 ;
270                                        }
271                                        if ($place_nodes_inside {$placekey} > $sparse{$place_type{$placekey}}) {
272                                                last early1 ;
273                                        }
274                                }
275                        #}
276                }
277        }
278}
279
280
281# count unmapped/sparsely mapped places
282
283foreach $placekey (keys %place_name) {
284        print "Name: ", $place_name{$placekey}, "\n" ;
285        print "Type: ", $place_type{$placekey}, "\n" ;
286        print "max dist: ", $dists{$place_type{$placekey}}, "\n" ;
287        print "Nodes in: ", $place_nodes_inside {$placekey}, "\n" ;
288        if ($place_nodes_inside {$placekey} < $sparse{$place_type{$placekey}}) {
289                if ($place_nodes_inside {$placekey} < $unmapped{$place_type{$placekey}}) {
290                        $unmapped = $unmapped + 1 ;
291                }
292                else {
293                        $sparselyMapped ++ ;
294                }
295        }
296        print "\n" ;
297}
298
299# find superior city/town
300foreach $placekey1 (keys %place_name) {
301        $place_superior {$placekey1} = "-" ;
302        $place_superior_dist {$placekey1} = 9999 ;
303        if (($place_type {$placekey1} eq "city") or ($place_type {$placekey1} eq "town")) {
304                # do nothing
305        } 
306        else {
307                # look for sup
308                foreach $placekey2 (keys %place_name) {
309                        my $d_lat = ($place_lat{$placekey1} - $place_lat{$placekey2}) * 111.11;
310                        my $d_lon = ($place_lon{$placekey1} - $place_lon{$placekey2}) * cos ( $place_lat{$placekey2} / 360 * 3.14 * 2 ) * 111.11 ;
311                        $dist = sqrt($d_lat*$d_lat+$d_lon*$d_lon);
312                        if (  ($dist < $place_superior_dist {$placekey1}) 
313                                and ( 
314                                        ($place_type {$placekey2} eq "city") or 
315                                        ($place_type {$placekey2} eq "town"))   ) {
316                                $place_superior {$placekey1} = $place_name {$placekey2} ;
317                                $place_superior_dist {$placekey1} = $dist ;
318                        }
319                }
320        }
321}
322
323$time2 = time() ;
324$timespent = $time2 - $time0 ;
325
326# print output files
327
328open ($html_file, , ">", $html) ; 
329open ($slippy_file, ">", $slippyout) ; 
330
331print_html_header() ;
332print $slippy_file "lat\tlon\ttitle\tdescription\ticon\ticonSize\ticonOffset\n" ;
333
334# print stats
335print $html_file "<h1>Unmapped places for ", $xml, "</h1>\n" ;
336print $html_file "<p>by Gary68</p>\n" ;
337print $html_file "<p>Program Version: $version</p>\n" ;
338
339print $html_file "<h2>Stats</h2>\n" ;
340print $html_file "<p>File date: ", ctime(stat($xml)->mtime), "<br>\n" ;
341print $html_file "Node count:      ", $node_count, "<br>\n" ;
342print $html_file "place count:     ", $place_count, "<br>\n" ;
343print $html_file "Cities:          ", $city_count, "<br>\n" ;
344print $html_file "Towns:           ", $town_count, "<br>\n" ;
345print $html_file "Suburbs:         ", $suburb_count, "<br>\n" ;
346print $html_file "Villages:        ", $village_count, "<br>\n" ;
347print $html_file "Unmapped places: ", $unmapped, "<br>\n" ;
348print $html_file "Sparsely mapped: ", $sparselyMapped, "<br>\n" ;
349printf $html_file "Unmapped:        %2d percent<br>\n", ($unmapped*100/$place_count) ;
350printf $html_file "Sparsely mapped: %2d percent<br>\n", ($sparselyMapped*100/$place_count) ;
351print $html_file "runtime1 =       ", $time1-$time0, "secs<br>\n" ;
352print $html_file "<p>Time: ", ($timespent/(60*60))%99, " hours, ", ($timespent/60)%60, " minutes and ", $timespent%60, " seconds</p>" ;
353
354print $html_file "<h2>Definitions</h2>\n" ;
355print $html_file "<p>City: ",  $dists{'city'}, " km radius - sparse/unmapped thresholds ", $sparse{'city'}, "/", $unmapped{'city'}, "<br>\n" ;
356print $html_file "Town: ",  $dists{'town'}, " km radius - sparse/unmapped thresholds ", $sparse{'town'}, "/", $unmapped{'town'}, "<br>\n" ;
357print $html_file "Village: ",  $dists{'village'}, " km radius - sparse/unmapped thresholds ", $sparse{'village'}, "/", $unmapped{'village'}, "<br>\n" ;
358print $html_file "Suburb: ",  $dists{'suburb'}, " km radius - sparse/unmapped thresholds ", $sparse{'suburb'}, "/", $unmapped{'suburb'}, "</p>\n" ;
359
360print $html_file "<h2>Details</h2>\n" ; 
361print $html_file "<p>Grouped list follows below!</p>\n" ;
362foreach $placekey (keys %place_name) { 
363        if ($place_nodes_inside {$placekey} < $sparse{$place_type{$placekey}}) { 
364                my $temp ;
365
366                $temp = "<!--" . $place_name {$placekey} . "-->" ;
367                $temp = $temp . "<A HREF=\"http://www.openstreetmap.org/?lat=" . $place_lat {$placekey} . "&lon=" . $place_lon {$placekey} . "&zoom=13\">" ; 
368                $temp = $temp . $place_name {$placekey} . "</A>" ; 
369                $temp = $temp . " (" . $place_type {$placekey} . " near " . $place_superior {$placekey} . ", " . $place_nodes_inside{$placekey} . ")\n"  ; 
370                if ($place_nodes_inside {$placekey} < $unmapped{$place_type{$placekey}}) { 
371                        $temp = $temp . " - potentially unmapped<br>" ;
372                }
373                else {
374                        $temp = $temp . " - potentially sparsely mapped<br>" ;
375                }
376                $temp = $temp . "\n" ;
377
378                push @outputData, $temp ;
379                push @{$outputGrouped{$place_superior{$placekey}}}, $place_name {$placekey} ;
380
381                print $slippy_file $place_lat {$placekey}, "\t" ;
382                print $slippy_file $place_lon {$placekey}, "\t" ;
383                print $slippy_file $place_name {$placekey}, "\t" ;
384                if ($place_nodes_inside {$placekey} < $unmapped{$place_type{$placekey}}) { 
385                        print $slippy_file "Potentially unmapped place", "\t" ;
386                        print $slippy_file "./", $iconRed, "\t" ;
387                }
388                else {
389                        print $slippy_file "Potentially sparsely mapped place", "\t" ;
390                        print $slippy_file "./", $iconYellow, "\t" ;
391                }
392                print $slippy_file "24,24", "\t" ;
393                print $slippy_file "-12,-12", "\n" ;
394        } 
395} 
396
397
398@outputDataSorted = sort @outputData ;
399
400foreach (@outputDataSorted) {
401        print $html_file $_ ;
402}
403
404print $html_file "<h2>Grouped</h2>\n" ;
405
406foreach $key (sort keys %outputGrouped) {
407        if ($key ne "-") {
408                print $html_file "<h3>$key</h3>\n<p>" ;
409                foreach $key2 (@{$outputGrouped{$key}}) {
410                        print $html_file $key2, "<br>\n" ;
411                }
412                print $html_file "</p>\n" ;
413        }
414}
415
416
417print_html_foot() ;
418
419close $html_file ;
420close $slippy_file ;
421
422print "\nTime: ", ($timespent/(60*60))%99, " hours, ", ($timespent/60)%60, " minutes and ", $timespent%60, " seconds\n" ;
423
424
425######
426# HTML
427######
428
429sub print_html_header {
430        print $html_file "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"";
431        print $html_file "  \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">";
432        print $html_file "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">\n";
433        print $html_file "<head><title>unmapped by Gary68</title>\n";
434        print $html_file "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n";
435        print $html_file "</head>\n<body>\n";
436}
437
438sub print_html_foot {
439        print $html_file "</body>\n</html>\n" ;
440}
441
442
443sub hashValue {
444        my $lon = shift ;
445        my $lat = shift ;
446
447        my $lo = int ($lon*10) * 10000 ;
448        my $la = int ($lat*10) ;
449
450        return ($lo+$la) ;
451}
452
Note: See TracBrowser for help on using the repository browser.