source: subversion/applications/share/map-icons/update_icons.pl @ 10274

Last change on this file since 10274 was 7020, checked in by guenther, 12 years ago
  • separated map rendering icons from poi icons
  • Property svn:executable set to *
File size: 14.8 KB
Line 
1#!/usr/bin/perl
2#####################################################################
3#
4#  This script handles the XML-Files for the POI-Types in gpsdrive.
5#  It has to be run from the data directory.
6
7#  Default actions, when no options are given:
8#  - Create basic XML-File if none is available
9#  - Search icons directories for PNG files
10#  - Add those files as new POI-Types if they are not yet existent
11#  - Create overview.html from the XML-File to show all
12#    available poi_types and icons.
13#
14#####################################################################
15#
16#  Scheme for the entries (only poi_type relevant elements are shown):
17#
18#  <rule>
19#    <condition k="poi" v="$NAME" />
20#    <scale_min>$SCALE_MIN</scale_min>
21#    <scale_max>$SCALE_MAX</scale_max>
22#    <title lang="$LANG">$TITLE</title>
23#    <description lang="$LANG">$DESCRIPTION</description>
24#  </rule>
25#
26#####################################################################
27
28#use diagnostics;
29use strict;
30use warnings;
31
32use utf8;
33use IO::File;
34use File::Find;
35use File::Copy;
36use XML::Twig;
37use Getopt::Std;
38use Pod::Usage;
39use Image::Magick;
40use File::Slurp;
41use File::Basename;
42use File::Path;
43use Data::Dumper;
44
45our ($opt_v, $opt_f, $opt_h, $opt_i, $opt_n, $opt_r,$opt_s) = 0;
46getopts('hvinrsf:') or $opt_h = 1;
47pod2usage( -exitval => '1', 
48           -verbose => '1') if $opt_h;
49
50my $file_xml = './icons.xml';
51my %ICONS = ('','');
52my $i = 0;
53my $j = 0;
54my $default_scale_min = 1;
55my $default_scale_max = 100000;
56my $default_title_en = '';
57my $default_desc_en = '';
58my $VERBOSE = $opt_v;
59
60my @ALL_TYPES = qw(square.big square.small classic.big classic.small svg japan );
61
62
63#####################################################################
64#
65#  M A I N
66#
67#
68chdir('./map-icons');
69unless (-e $file_xml)
70{
71  create_xml(); # Create a new XML-File if none exists
72}
73get_icons();             # read available icons from dirs
74update_xml();            # parse and update contents  of XML-File
75chdir('..');
76exit (0);
77
78
79
80#####################################################################
81#
82#  Parse available XML-File aund update with contents from icons dirs
83#
84#
85sub update_xml
86{
87  print STDOUT "\n----- Parsing and updating '$file_xml' -----\n";
88 
89  # Parse XML-File and look for already existing POI-Type entries
90  #
91  my $twig= new XML::Twig
92    (
93      pretty_print => 'indented',
94      empty_tags => 'normal',
95      comments => 'keep',
96      TwigHandlers => { 
97          condition => \&sub_condition # also deletes the entry from %ICONS
98     }
99    );
100  $twig->parsefile( "$file_xml");       # build the twig
101  my $rules= $twig->root;       # get the root of the twig (rules)
102
103  # Insert new POI-Type entries from hash of available icons
104  #
105  $i = 0;
106  my @tmp_icons = sort(keys(%ICONS));
107 
108  for my $icon (@tmp_icons)
109  {
110     insert_poi_type($icon,\$rules);
111     $i++;
112  }
113  print STDOUT "  New POI-Types added:\t$i\n";
114
115  # Print Status for poi_type_ids
116  #
117  my @rule= $rules->children;   # get the updated rule list
118
119  $i = $j = 0;
120  foreach my $entry (@rule)
121  {
122    if  ($entry->last_child('condition')->{'att'}->{'k'} eq 'poi')
123    {
124      $i++;
125    }
126    if  ($entry->last_child('condition')->{'att'}->{'k'} eq 'rendering')
127    {
128      $j++;
129    }
130
131  }
132  print STDOUT "  Defined Points of Interest  :\t$i\n";
133  print STDOUT "  Defined Map Rendering Icons :\t$j\n";
134
135  # Write XML-File containing modified contents
136  #
137  open TMPFILE,">:utf8","./icons.tmp";
138    select TMPFILE;
139    print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
140    print "<rules>\n";
141   
142    my $j=1;
143
144
145sub entry_name($){
146    my $entry = shift;
147
148    if (($entry->last_child('condition')->{'att'}->{'k'} eq 'poi')
149      || ($entry->last_child('condition')->{'att'}->{'k'} eq 'rendering'))
150    {
151      return $entry->last_child('condition')->{'att'}->{'v'};
152    }
153}
154
155    foreach my $entry (sort {entry_name($a) cmp entry_name($b) } @rule)
156     {
157       my $name = 'unknown';
158       if (($entry->last_child('condition')->{'att'}->{'k'} eq 'poi')
159         || ($entry->last_child('condition')->{'att'}->{'k'} eq 'rendering'))
160       {
161         $name = $entry->last_child('condition')->{'att'}->{'v'};
162       }
163
164       next if not($opt_i) && $name =~ m/^incomming/;
165
166       $entry->print;
167       print "\n"; 
168     }
169    print "</rules>\n";
170  close TMPFILE;
171
172  # Create backup copy of old XML-File
173  #
174  #move("$file_xml","$file_xml.bak") or die (" Couldn't create backup file!");
175  move("./icons.tmp","$file_xml") or die (" Couldn't remove temp file!");
176  print STDOUT "\n XML-File successfully updated!\n";
177
178  $twig->purge;
179
180  return;
181
182  # look, if POI-Type already exists in the file by checking for a
183  # known name inside the condition tag. If true, kick it from the icons
184  # hash, because it's not needed anymore.
185  sub sub_condition
186   {
187     my( $twig, $condition)= @_;
188
189     if (($condition->{'att'}->{'k'} eq 'poi')
190       || ($condition->{'att'}->{'k'} eq 'rendering'))
191     {
192       my $name = $condition->{'att'}->{'v'};
193       if (exists $ICONS{$name}) 
194       {
195         print STDOUT "  o  \t$name\n" if $VERBOSE;
196         delete $ICONS{"$name"};
197       }
198     }
199   }
200}
201
202
203#####################################################################
204#
205#  Insert new POI-Type into the file
206#
207#
208sub insert_poi_type
209{
210  my $name = shift(@_);
211  my $twig_root = shift(@_);
212
213  my $new_rule = new XML::Twig::Elt( 'rule');
214 
215  my $new_condition = new XML::Twig::Elt('condition');
216  if ($name =~ m/^rendering/)
217    { $new_condition->set_att(k=>'rendering'); }
218  else
219    { $new_condition->set_att(k=>'poi'); }
220  $new_condition->set_att(v=>"$name");
221  my $new_title_en = new XML::Twig::Elt('title',$default_title_en);
222  $new_title_en->set_att(lang=>'en');
223  my $new_desc_en = new XML::Twig::Elt('description',$default_desc_en);
224  $new_desc_en->set_att(lang=>'en');
225  my $new_scale_min = new XML::Twig::Elt('scale_min',$default_scale_min);
226  my $new_scale_max = new XML::Twig::Elt('scale_max',$default_scale_max);
227
228  $new_desc_en->paste('first_child',$new_rule);
229  $new_title_en->paste('first_child',$new_rule);
230  $new_scale_max->paste('first_child',$new_rule);
231  $new_scale_min->paste('first_child',$new_rule);
232  $new_condition->paste('first_child',$new_rule);
233
234  $new_rule->paste('last_child',$$twig_root); 
235
236  print STDOUT "  +  \t$name\n" if $VERBOSE;
237}
238
239
240#####################################################################
241#
242#  Get all the available icons in data/icons
243#
244#
245sub get_icons
246{
247  print STDOUT "\n----- Looking for available icons -----\n";
248  $i = 0;
249  find( \&format_icons,  @ALL_TYPES );
250  sub format_icons()
251  { 
252      my $icon_file = $File::Find::name;
253      if ( $icon_file =~ m/\.svn/ ) {
254      } elsif ( not($opt_i) && $icon_file =~ m/incomming/ ) {
255          print STDOUT "ignore incomming: $icon_file\n" if $VERBOSE;
256      } elsif ( $icon_file =~ m/\.(png|svg)$/ && $icon_file !~ m/empty\.(png|svg)$/ ) {
257          $i++;
258          print STDOUT "  Found icon:\t$i\t$icon_file\n" if $VERBOSE;
259          for my $type ( @ALL_TYPES ) {
260              $icon_file =~ s,^$type/,,g;
261          }
262          $icon_file =~ s,\.(png|svg)$,,g;
263          $icon_file =~ s,/,.,g;
264          $ICONS{"$icon_file"} = '1';
265      }
266  }
267  delete $ICONS{''} if (exists $ICONS{''});
268  print STDOUT " $i icons for ".keys(%ICONS)." POI-Types found in data/map-icons\n";
269 
270}
271
272#####################################################################
273#
274#  Create a new XML File and fill it with the basic POI-Types
275#
276#
277sub create_xml
278 { 
279   print STDOUT "\n----- Creating new basic XML-File \"$file_xml\" -----\n";
280   print STDOUT "\n  ATTENTION: It is possible, that the IDs will change,\n";
281   print STDOUT "\n  so it would be better, if you update an existing icons.xml!\n";
282   my @poi_types = (
283
284     { name => 'unknown',
285       scale_min => '1',
286       scale_max => '50000',
287       description_en => 'Unassigned POI',
288       description_de => 'Nicht zugewiesener POI',
289       title_en => 'Unknown',
290       title_de => 'Unbekannt',
291     },
292     { name => 'accommodation',
293       scale_min => '1',
294       scale_max => '50000',
295       description_en => 'Places to stay',
296       description_de => 'Hotels, Jugendherbergen, Campingpl&#228;tze',
297       title_en => 'Accommodation',
298       title_de => 'Unterkunft',
299     },
300     { name => 'education',
301       scale_min => '1',
302       scale_max => '25000',
303       description_en => 'Schools and other educational facilities',
304       description_de => 'Schulen und andere Bildungseinrichtungen',
305       title_en => 'Education',
306       title_de => 'Bildung',
307     },
308     { name => 'food',
309       scale_min => '1',
310       scale_max => '25000',
311       description_en => 'Restaurants, Bars, and so on...',
312       description_de => 'Restaurants, Bars, usw.',
313       title_en => 'Food',
314       title_de => 'Speiselokal',
315     },
316     { name => 'geocache',
317       scale_min => '1',
318       scale_max => '50000',
319       description_en => 'Geocaches',
320       description_de => 'Geocaches',
321       title_en => 'Geocache',
322       title_de => 'Geocache',
323     },
324     { name => 'health',
325       scale_min => '1',
326       scale_max => '25000',
327       description_en => 'Hospital, Doctor, Pharmacy, etc.',
328       description_de => 'Krankenh&#228;user, &#196;rzte, Apotheken',
329       title_en => 'Health',
330       title_de => 'Gesundheit',
331     },
332     { name => 'money',
333       scale_min => '1',
334       scale_max => '25000',
335       description_en => 'Bank, ATMs, and other money-related places',
336       description_de => 'Banken, Geldautomaten, und &#228;hnliches',
337       title_en => 'Money',
338       title_de => 'Geld',
339     },
340     { name => 'nautical',
341       scale_min => '1',
342       scale_max => '50000',
343       description_en => 'Special aeronautical Points',
344       description_de => 'Spezielle aeronautische Punkte',
345       title_en => 'aeronautical',
346       title_de => 'aeronautisch',
347     },
348     { name => 'people',
349       scale_min => '1',
350       scale_max => '50000',
351       description_en => 'Your home, work, friends, and other people',
352       description_de => 'Dein Zuhause, die Arbeitsstelle, Freunde, und andere Personen',
353       title_en => 'People',
354       title_de => 'Person',
355     },
356     { name => 'places',
357       scale_min => '10000',
358       scale_max => '500000',
359       description_en => 'Settlements, Mountains, and other geographical stuff',
360       description_de => 'Siedlungen, Berggipfel, und anderes geografisches Zeug',
361       title_en => 'Place',
362       title_de => 'Ort',
363     },
364     { name => 'public',
365       scale_min => '1',
366       scale_max => '25000',
367       description_en => 'Public facilities and Administration',
368       description_de => 'Verwaltung und andere &#246;ffentliche Einrichtungen',
369
370       title_en => 'Public',
371       title_de => '&#214;ffentlich',
372     },
373     { name => 'recreation',
374       scale_min => '1',
375       scale_max => '25000',
376       description_en => 'Places used for recreation (no sports)',
377       description_de => 'Freizeiteinrichtungen (kein Sport)',
378       title_en => 'Recreation',
379       title_de => 'Freizeit',
380     },
381     { name => 'religion',
382       scale_min => '1',
383       scale_max => '25000',
384       description_en => 'Places and facilities related to religion',
385       description_de => 'Kirchen und andere religi&#246;se Einrichtungen',
386       title_en => 'Religion',
387       title_de => 'Religion',
388     },
389     { name => 'shopping',
390       scale_min => '1',
391       scale_max => '25000',
392       description_en => 'All the places, where you can buy something',
393       description_de => 'Orte, an denen man etwas k&#228;uflich erwerben kann',
394       title_en => 'Shopping',
395       title_de => 'Einkaufen',
396     },
397     { name => 'sightseeing',
398       scale_min => '1',
399       scale_max => '25000',
400       description_en => 'Historic places and other interesting buildings',
401       description_de => 'Historische Orte und andere interessante Bauwerke',
402       title_en => 'Sightseeing',
403       title_de => 'Sehensw&#252;rdigkeit',
404     },
405     { name => 'sports',
406       scale_min => '1',
407       scale_max => '25000',
408       description_en => 'Sports clubs, stadiums, and other sports facilities',
409       description_de => 'Sportpl&#228;tze und andere sportliche Einrichtungen',
410       title_en => 'Sports',
411       title_de => 'Sport',
412     },
413     { name => 'transport',
414       scale_min => '1',
415       scale_max => '25000',
416       description_en => 'Airports and public transportation',
417       description_de => 'Flugh&#228;fen und &#246;ffentliche Transportmittel',
418       title_en => 'Public Transport',
419       title_de => '&#214;ffentliches Transportmittel',
420     },
421     { name => 'vehicle',
422       scale_min => '1',
423       scale_max => '25000',
424       description_en => 'Facilites for drivers, like gas stations or parking places',
425       description_de => 'Dinge f&#252;r Selbstfahrer, z.B. Tankstellen oder Parkpl&#228;tze',
426       title_en => 'Vehicle',
427       title_de => 'Fahrzeug',
428     },
429     { name => 'wlan',
430       scale_min => '1',
431       scale_max => '25000',
432       description_en => 'WiFi-related points (Kismet)',
433       description_de => 'Accesspoints und andere WLAN-Einrichtungen (Kismet)',
434       title_en => 'WLAN',
435       title_de => 'WLAN',
436     },
437     { name => 'misc',
438       scale_min => '1',
439       scale_max => '25000',
440       description_en => 'POIs not suitable for another category, and custom types',
441       description_de => 'Eigenkreationen, und Punkte, die in keine der anderen Kategorien passen',
442       title_en => 'Miscellaneous',
443       title_de => 'Verschiedenes',
444     },
445     { name => 'waypoint',
446       scale_min => '1',
447       scale_max => '50000',
448       description_en => 'Waypoints, for example  to temporarily mark several places',
449       description_de => 'Wegpunkte, um z.B. temporäre Punkte zu markieren',
450       title_en => 'Waypoint',
451       title_de => 'Wegpunkt',
452     },
453   
454   );
455
456   open NEWFILE,">:utf8","./$file_xml";
457   select NEWFILE;
458
459   print"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
460   print"<rules>\n\n";
461   foreach (@poi_types)
462     {
463       print"  <rule>\n";
464       print"    <condition k=\"poi\" v=\"$$_{'name'}\" />\n";
465       print"    <scale_min>$$_{'scale_min'}</scale_min>\n";
466       print"    <scale_max>$$_{'scale_max'}</scale_max>\n";
467       print"    <title lang=\"de\">$$_{'title_de'}</title>\n";
468       print"    <title lang=\"en\">$$_{'title_en'}</title>\n";
469       print"    <description lang=\"de\">$$_{'description_de'}</description>\n";
470       print"    <description lang=\"en\">$$_{'description_en'}</description>\n";
471       print"  </rule>\n\n";
472       print STDOUT "  +  \t$$_{'name'}\n" if $VERBOSE;
473     }
474   print "</rules>\n";
475 
476   close NEWFILE;
477
478   if (-e $file_xml)
479     { print STDOUT " New XML-File \"$file_xml\" successfully created!\n"; }
480   else
481     { die " ERROR: Failed in creating new XML-File \"$file_xml\" !\n"; }
482
483 }
484
485
486__END__
487
488
489=head1 SYNOPSIS
490 
491update_icons.pl [-h] [-v] [-i] [-r] [-f XML-FILE]
492 
493=head1 OPTIONS
494 
495=over 2
496 
497=item B<--h>
498
499 Show this help
500
501=item B<-f> XML-FILE
502
503 Set file, that holds all the necessary icon and poi_type information.
504 The default file is 'icons.xml'.
505
506=item B<-v>
507
508 Enable verbose output
509
510=back
Note: See TracBrowser for help on using the repository browser.