/docs/MyDocs

To get this branch, use:
bzr branch http://darksoft.org/webbzr/docs/MyDocs

« back to all changes in this revision

Viewing changes to Methods/Mapping/scripts/osm2mp/osm2mp.pl

  • Committer: Suren A. Chilingaryan
  • Date: 2009-04-09 03:21:08 UTC
  • Revision ID: csa@dside.dyndns.org-20090409032108-w4edamdh4adrgdu3
import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl
 
2
 
 
3
 
 
4
####    Settings
 
5
 
 
6
my $cfgpoi      = "poi.cfg";
 
7
my $cfgpoly     = "poly.cfg";
 
8
my $cfgheader   = "header.cfg";
 
9
 
 
10
my $codepage    = "1251";
 
11
my $mapid       = "12345432";
 
12
my $mapname     = "OSM-test";
 
13
 
 
14
my $mergeroads     = 1;
 
15
my $mergecos       = 0.2;
 
16
 
 
17
my $detectdupes    = 1;
 
18
 
 
19
my $splitroads     = 1;
 
20
 
 
21
my $fixclosenodes  = 1;
 
22
my $fixclosedist   = 5.5;
 
23
 
 
24
my $restrictions   = 1;
 
25
 
 
26
 
 
27
 
 
28
 
 
29
####    Init
 
30
 
 
31
my $version = "0.53";
 
32
 
 
33
my %yesno = (  "yes"       => 1,
 
34
               "true"      => 1,
 
35
               "1"         => 1,
 
36
               "no"        => 0,
 
37
               "false"     => 0,
 
38
               "0"         => 0);  
 
39
 
 
40
 
 
41
 
 
42
 
 
43
####    Action
 
44
 
 
45
use strict;
 
46
 
 
47
print STDERR "\n  ---|   OSM -> MP converter  $version   (c) 2008  liosha, xliosha\@gmail.com\n\n";
 
48
 
 
49
 
 
50
 
 
51
 
 
52
####    Reading configs
 
53
 
 
54
my %poitype;
 
55
 
 
56
open CFG, $cfgpoi;
 
57
while (<CFG>) { 
 
58
   if ( (!$_) || /^\s*[\#\;]/ ) { next; }
 
59
   chomp;
 
60
   my ($k, $v, $type, $llev, $hlev, $city) = split /\s+/;
 
61
   if ($type) {
 
62
     $llev = 0          if ($llev eq "");
 
63
     $hlev = 1          if ($hlev eq "");
 
64
     $city = (($city ne "") ? 1 : 0);
 
65
     $poitype{"$k=$v"} = [ $type, $llev, $hlev, $city ];
 
66
   }
 
67
}
 
68
close CFG;
 
69
 
 
70
 
 
71
my %polytype;
 
72
 
 
73
open CFG, $cfgpoly;
 
74
while (<CFG>) { 
 
75
   if ( (!$_) || /^\s*[\#\;]/ ) { next; }
 
76
   chomp;
 
77
 
 
78
   my $prio = 0;
 
79
   my ($k, $v, $mode, $type, $llev, $hlev, $rp, @p) = split /\s+/;
 
80
   
 
81
   if ($type) {
 
82
     if ($type =~ /(.+),(\d)/) {     $type = $1;    $prio = $2;    }
 
83
     $llev = 0          if ($llev eq "");
 
84
     $hlev = 1          if ($hlev eq "");
 
85
 
 
86
     $polytype{"$k=$v"} = [ $mode, $type, $prio, $llev, $hlev, $rp ]; 
 
87
   }
 
88
}
 
89
close CFG;
 
90
 
 
91
 
 
92
 
 
93
 
 
94
 
 
95
####    Header
 
96
 
 
97
open HEAD, $cfgheader;
 
98
while (<HEAD>) {
 
99
    s/^ID=.*$/ID=$mapid/i                       if ($mapid);
 
100
    s/^Name=.*$/Name=$mapname/i                 if ($mapname);
 
101
    s/^CodePage=.*$/CodePage=$codepage/i        if ($codepage);
 
102
    print;
 
103
}
 
104
close HEAD;
 
105
 
 
106
open IN, $ARGV[0];
 
107
 
 
108
 
 
109
use POSIX qw(strftime);
 
110
print "\n; Converted from OpenStreetMap data with  osm2mp $version  (" . strftime ("%Y-%m-%d %H:%M:%S", localtime) . ")\n\n";
 
111
 
 
112
 
 
113
 
 
114
 
 
115
 
 
116
 
 
117
####    Loading nodes and writing POIs
 
118
 
 
119
my %nodes;
 
120
 
 
121
print STDERR "Loading nodes...          ";
 
122
print "\n\n\n; ### Points\n\n";
 
123
 
 
124
my $countpoi = 0;
 
125
 
 
126
my $id;
 
127
my $latlon;
 
128
my ($poi, $poiname);
 
129
 
 
130
while (<IN>) {             
 
131
   last if /\<way/;
 
132
 
 
133
   if ( /\<node/ ) {                   
 
134
      /^.*id=["'](\-?\d+)["'].*lat=["'](\-?\d+\.?\d*)["'].*lon=["'](\-?\d+\.?\d*)["'].*$/;
 
135
      $id = $1;
 
136
      $latlon = "$2,$3";
 
137
      $nodes{$1} = $latlon;
 
138
 
 
139
      $poi = "";
 
140
      $poiname = "";
 
141
      next;
 
142
   }
 
143
 
 
144
   if ( /\<tag/ ) {                   
 
145
      /^.*k=["'](.*)["'].*v=["'](.*)["'].*$/;
 
146
      $poi = "$1=$2"                            if ($poitype{"$1=$2"});
 
147
      $poiname = convert_string ($2)            if ($1 eq "name");
 
148
      next;
 
149
   }
 
150
 
 
151
   if ( /\<\/node/ ) {                   
 
152
 
 
153
      if ($poi) {
 
154
         $countpoi ++;
 
155
         my @type = @{$poitype{$poi}};
 
156
 
 
157
         print  "; NodeID = $id\n";
 
158
         print  "; $poi\n";
 
159
         print  "[POI]\n";
 
160
         printf "Type=%s\n",            $type[0];
 
161
         printf "Data%d=($latlon)\n",   $type[1];
 
162
         printf "EndLevel=%d\n",        $type[2]        if ($type[2] > $type[1]);
 
163
         printf "City=Y\n",                             if ($type[3]);
 
164
         print  "Label=$poiname\n"                      if ($poiname);
 
165
         print  "[END]\n\n";
 
166
      }
 
167
   }
 
168
}
 
169
 
 
170
printf STDERR "%d loaded, %d POIs dumped\n", scalar keys %nodes, $countpoi;
 
171
 
 
172
 
 
173
 
 
174
 
 
175
 
 
176
 
 
177
####    Skipping ways
 
178
 
 
179
my $waypos  = tell IN;
 
180
my $waystr  = $_;
 
181
 
 
182
while (<IN>) {     last if /\<relation/;     }
 
183
 
 
184
my $relpos  = tell IN;
 
185
my $relstr  = $_;
 
186
 
 
187
 
 
188
 
 
189
 
 
190
 
 
191
 
 
192
####    Loading relations
 
193
 
 
194
my %mpoly;
 
195
my %mpholes;
 
196
my %trest;
 
197
my %waytr;
 
198
 
 
199
print STDERR "Loading relations...      ";
 
200
 
 
201
my $id;
 
202
my $reltype;
 
203
 
 
204
my $mp_outer;
 
205
my @mp_inner;
 
206
 
 
207
my ($tr_from, $tr_via, $tr_to);
 
208
 
 
209
while ($_) {
 
210
 
 
211
    if ( /\<relation/ ) {                   
 
212
        /^.*id=["'](\-?\d+)["'].*$/;
 
213
 
 
214
        $id = $1;           
 
215
        undef $reltype;     
 
216
        undef $mp_outer;        undef @mp_inner;
 
217
        undef $tr_from;         undef $tr_via;          undef $tr_to;
 
218
        next;
 
219
    }
 
220
 
 
221
    if ( /\<member/ ) {                   
 
222
        /type=["'](\w+)["'].*ref=["'](\-?\d+)["'].*role=["'](\w+)["']/;
 
223
 
 
224
        $mp_outer = $2                  if ($3 eq "outer" && $1 eq "way");
 
225
        push @mp_inner, $2              if ($3 eq "inner" && $1 eq "way");
 
226
 
 
227
        $tr_from = $2                   if ($3 eq "from"  && $1 eq "way");
 
228
        $tr_to = $2                     if ($3 eq "to"    && $1 eq "way");
 
229
        $tr_via = $2                    if ($3 eq "via"   && $1 eq "node");
 
230
 
 
231
        next;
 
232
    }
 
233
 
 
234
    if ( /\<tag/ ) {
 
235
        /k=["'](\w+)["'].*v=["'](\w+)["']/;
 
236
        $reltype = $2                           if ( $1 eq "type" );
 
237
        next;
 
238
    }
 
239
 
 
240
    if ( /\<\/relation/ ) {                   
 
241
        if ( $reltype eq "multipolygon" ) {
 
242
            $mpoly{$mp_outer} = [ @mp_inner ];
 
243
            @mpholes{@mp_inner} = @mp_inner;
 
244
        }
 
245
        if ( $restrictions && $reltype eq "restriction" ) {
 
246
            $trest{$id} = [ $tr_via, $tr_from, 0, -1, $tr_to, 0, -1 ];
 
247
            push @{$waytr{$tr_from}}, $id;
 
248
            push @{$waytr{$tr_to}}, $id;
 
249
        }
 
250
        next;
 
251
    }
 
252
 
 
253
} continue { $_ = <IN>; }
 
254
 
 
255
printf STDERR "%d multipolygons, %d turn restrictions\n", scalar keys %mpoly, scalar keys %trest;
 
256
 
 
257
 
 
258
 
 
259
 
 
260
 
 
261
 
 
262
####    Loading multipolygon holes and checking node dupes
 
263
 
 
264
print STDERR "Loading holes...          ";
 
265
 
 
266
seek IN, $waypos, 0;
 
267
$_ = $waystr;
 
268
 
 
269
   my $id;
 
270
   my @chain;
 
271
   my $dupcount;
 
272
 
 
273
while ($_) {
 
274
 
 
275
   last if /\<relation/;
 
276
 
 
277
   if ( /\<way/ ) {                   
 
278
      /^.*id=["'](\-?\d+)["'].*$/;
 
279
 
 
280
      $id = $1;
 
281
      @chain = ();
 
282
      $dupcount = 0;
 
283
      next;
 
284
   }
 
285
 
 
286
   if ( /\<nd/ ) {                   
 
287
      /^.*ref=["'](.*)["'].*$/;
 
288
      if ($nodes{$1}  &&  $1 ne $chain[-1] ) {
 
289
          push @chain, $1;
 
290
      } else {
 
291
          print "; ERROR: WayID=$id has dupes at ($nodes{$1})\n";
 
292
          $dupcount ++;
 
293
      }
 
294
      next;
 
295
   }
 
296
 
 
297
   if ( /\<\/way/ ) {
 
298
 
 
299
#       print "; ERROR: WayID=$id has dupes\n"           if ($dupcount>0);
 
300
 
 
301
       ##       this way is multipolygon inner
 
302
       if ( $mpholes{$id} ) {
 
303
           $mpholes{$id} = [ @chain ];
 
304
       }
 
305
   }
 
306
 
 
307
} continue { $_ = <IN>; }
 
308
 
 
309
printf STDERR "%d loaded\n", scalar keys %mpholes;
 
310
 
 
311
 
 
312
 
 
313
 
 
314
 
 
315
 
 
316
####    Loading roads and writing other ways
 
317
 
 
318
my %rchain;
 
319
my %rprops;
 
320
 
 
321
print STDERR "Processing ways...        ";
 
322
print "\n\n\n; ### Lines and polygons\n\n";
 
323
 
 
324
seek IN, $waypos, 0;
 
325
$_ = $waystr;
 
326
 
 
327
my $countlines = 0;
 
328
my $countpolygons = 0;
 
329
 
 
330
   my $id;
 
331
   my @chain;
 
332
   my ($poly, $polyname);
 
333
   my $polydir;
 
334
   my ($polytoll, $polynoauto, $polynobus, $polynoped, $polynobic, $polynohgv);
 
335
 
 
336
while ($_) {
 
337
 
 
338
   last if /\<relation/;
 
339
   
 
340
   if ( /\<way/ ) {                   
 
341
      /^.*id=["'](\-?\d+)["'].*$/;
 
342
      
 
343
      $id = $1;
 
344
      @chain = ();
 
345
 
 
346
      undef ($poly);
 
347
 
 
348
      undef ($polyname);
 
349
      undef ($polydir);
 
350
      undef ($polytoll);
 
351
      undef ($polynoauto);
 
352
      undef ($polynobus);
 
353
      undef ($polynoped);
 
354
      undef ($polynobic);
 
355
      undef ($polynohgv);
 
356
 
 
357
      next;
 
358
   }
 
359
 
 
360
   if ( /\<nd/ ) {                   
 
361
      /^.*ref=["'](.*)["'].*$/;
 
362
      if ($nodes{$1}  &&  $1 ne $chain[-1] ) {
 
363
          push @chain, $1;
 
364
      } 
 
365
      next;
 
366
   }
 
367
 
 
368
   if ( /\<tag/ ) {                   
 
369
       /^.*k=["'](.*)["'].*v=["'](.*)["'].*$/;
 
370
       $poly       = "$1=$2"                    if ($polytype{"$1=$2"} && ($polytype{"$1=$2"}->[2] >= $polytype{$poly}->[2]));
 
371
       $polyname   = convert_string ($2)        if ($1 eq "name");
 
372
 
 
373
       $polydir    = $yesno{$2}                 if ($1 eq "oneway");
 
374
       $polytoll   = $yesno{$2}                 if ($1 eq "toll");
 
375
       $polynoauto = 1 - $yesno{$2}             if ($1 eq "motorcar");
 
376
       $polynobus  = 1 - $yesno{$2}             if ($1 eq "psv");
 
377
       $polynoped  = 1 - $yesno{$2}             if ($1 eq "foot");
 
378
       $polynobic  = 1 - $yesno{$2}             if ($1 eq "bicycle");
 
379
       $polynohgv  = 1 - $yesno{$2}             if ($1 eq "hgv");
 
380
 
 
381
       next;
 
382
   }
 
383
 
 
384
   if ( /\<\/way/ ) {
 
385
 
 
386
       ##       this way is road
 
387
       if ( $polytype{$poly}->[0] eq "r"  &&  scalar @chain <= 1 ) {
 
388
           print "; ERROR: Road WayID=$id has too few nodes at ($nodes{$chain[0]})\n";
 
389
       }
 
390
       if ( $polytype{$poly}->[0] eq "r"  &&  scalar @chain > 1 ) {
 
391
           my @rp = split /,/, $polytype{$poly}->[5];
 
392
           $rp[2]  = $polydir                           if defined $polydir;
 
393
           $rp[3]  = $polytoll                          if defined $polytoll;
 
394
           $rp[5]  = $rp[6] = $rp[8] = $polynoauto      if defined $polynoauto;
 
395
           $rp[7]  = $polynobus                         if defined $polynobus;
 
396
           $rp[9]  = $polynoped                         if defined $polynoped;
 
397
           $rp[10] = $polynobic                         if defined $polynobic;
 
398
           $rp[11] = $polynohgv                         if defined $polynohgv;
 
399
 
 
400
           $rchain{$id} = [ @chain ];
 
401
           $rprops{$id} = [ $poly, $polyname, join (",",@rp) ];
 
402
 
 
403
           # processing associated turn restrictions
 
404
           if ($restrictions) {
 
405
             for my $relid (@{$waytr{$id}}) {
 
406
               if ($trest{$relid}->[1] eq $id) {
 
407
                   $trest{$relid}->[3] = indexof (\@chain, $trest{$relid}->[0]);
 
408
                   if ($rp[2] && $trest{$relid}->[3] != 0)              { $trest{$relid}->[2] = 1; }
 
409
                    elsif ($trest{$relid}->[3] == 0 && !$rp[2])         { $trest{$relid}->[2] = -1; }
 
410
                    elsif ($trest{$relid}->[3] == $#chain)              { $trest{$relid}->[2] = 1; }
 
411
               }
 
412
               if ($trest{$relid}->[4] eq $id) {
 
413
                   $trest{$relid}->[6] = indexof (\@chain, $trest{$relid}->[0]);
 
414
                   if ($rp[2] && $trest{$relid}->[6] != $#chain)        { $trest{$relid}->[5] = 1; }
 
415
                    elsif ($trest{$relid}->[6] == 0)                    { $trest{$relid}->[5] = 1; }
 
416
                    elsif ($trest{$relid}->[6] == $#chain && !$rp[2])   { $trest{$relid}->[5] = -1; }
 
417
               }
 
418
             }
 
419
           }
 
420
       }
 
421
 
 
422
       ##       this way is map line
 
423
       if ( $polytype{$poly}->[0] eq "l" ) {
 
424
           $countlines ++;
 
425
           my $d = "";
 
426
           if ( scalar @chain < 2 ) {
 
427
               print "; ERROR: WayID=$id has too few nodes at ($nodes{$chain[0]})\n";
 
428
               $d = "; ";
 
429
           } 
 
430
         
 
431
           my @type = @{$polytype{$poly}};
 
432
           print  "; WayID = $id\n";
 
433
           print  "; $poly\n";
 
434
           print  "${d}[POLYLINE]\n";
 
435
           printf "${d}Type=%s\n",        $type[1];
 
436
           printf "${d}EndLevel=%d\n",    $type[4]              if ($type[4] > $type[3]);
 
437
           print  "${d}Label=$polyname\n"                       if ($polyname);
 
438
           print  "${d}DirIndicator=$polydir\n"                 if defined $polydir;
 
439
           printf "${d}Data%d=(%s)\n",    $type[3], join ("), (", @nodes{@chain});
 
440
           print  "${d}[END]\n\n\n";
 
441
       }
 
442
 
 
443
       ##       this way is map polygon
 
444
       if ( $polytype{$poly}->[0] eq "p" ) {
 
445
           $countpolygons ++;
 
446
           my $d = "";
 
447
           if ( scalar @chain < 4 ) {
 
448
               print "; ERROR: WayID=$id has too few nodes near ($nodes{$chain[0]})\n";
 
449
               $d = "; ";
 
450
           } 
 
451
           if ( $chain[0] ne $chain[-1] ) {
 
452
               print "; ERROR: area WayID=$id is not closed at ($nodes{$chain[0]})\n";
 
453
           }
 
454
         
 
455
           my @type = @{$polytype{$poly}};
 
456
           print  "; WayID = $id\n";
 
457
           print  "; $poly\n";
 
458
           print  "${d}[POLYGON]\n";
 
459
           printf "${d}Type=%s\n",        $type[1];
 
460
           printf "${d}EndLevel=%d\n",    $type[4]              if ($type[4] > $type[3]);
 
461
           print  "${d}Label=$polyname\n"                       if ($polyname);
 
462
           printf "${d}Data%d=(%s)\n",    $type[3], join ("), (", @nodes{@chain});
 
463
           if ($mpoly{$id}) {
 
464
               printf "; this is multipolygon with %d holes: %s\n", scalar @{$mpoly{$id}}, join (", ", @{$mpoly{$id}});
 
465
               for my $hole (@{$mpoly{$id}}) {
 
466
                   if ($mpholes{$hole} ne $hole && @{$mpholes{$hole}}) {
 
467
                       printf "${d}Data%d=(%s)\n",    $type[3], join ("), (", @nodes{@{$mpholes{$hole}}});
 
468
                   }
 
469
               }
 
470
           }
 
471
           print  "${d}[END]\n\n\n";
 
472
       }
 
473
   }
 
474
 
 
475
} continue { $_ = <IN>; }
 
476
 
 
477
printf STDERR "%d roads loaded
 
478
                          $countlines lines and $countpolygons polygons dumped\n", scalar keys %rchain;
 
479
 
 
480
 
 
481
 
 
482
 
 
483
 
 
484
####    Detecting end nodes
 
485
 
 
486
my %enodes;
 
487
my %rstart;
 
488
 
 
489
while (my ($road, $pchain) = each %rchain) {
 
490
    $enodes{$pchain->[0]}  ++;
 
491
    $enodes{$pchain->[-1]} ++;
 
492
    push @{$rstart{$pchain->[0]}}, $road;
 
493
}
 
494
 
 
495
 
 
496
 
 
497
 
 
498
 
 
499
####    Merging roads
 
500
 
 
501
my %rmove;
 
502
 
 
503
if ($mergeroads) {
 
504
    print "\n\n\n";
 
505
    print STDERR "Merging roads...          ";
 
506
 
 
507
    my $countmerg = 0;
 
508
    my @keys = keys %rchain;
 
509
 
 
510
    my $i = 0;
 
511
    while ($i < scalar @keys) {
 
512
 
 
513
        my $r1 = $keys[$i];
 
514
        if ($rmove{$r1}) {      $i++;   next;   }
 
515
        my $p1 = $rchain{$r1};
 
516
 
 
517
        my @list = ();
 
518
        for my $r2 (@{$rstart{$p1->[-1]}}) {
 
519
            if ( $r1 ne $r2  &&  $rprops{$r2} 
 
520
              && join(":",@{$rprops{$r1}})  eq  join(":",@{$rprops{$r2}}) 
 
521
              && lcos($p1->[-2],$p1->[-1],$rchain{$r2}->[1]) > $mergecos ) {
 
522
                push @list, $r2    
 
523
            }
 
524
        }
 
525
            
 
526
        if (scalar @list) {
 
527
            $countmerg ++;
 
528
            @list = sort { lcos($p1->[-2],$p1->[-1],$rchain{$b}->[1]) <=> lcos($p1->[-2],$p1->[-1],$rchain{$a}->[1]) }  @list;
 
529
            printf "; FIX: Road WayID=$r1 may be merged with %s at (%s)\n", join (", ", @list), $nodes{$p1->[-1]};
 
530
 
 
531
            my $r2 = $list[0];
 
532
            $rmove{$r2} = $r1;
 
533
 
 
534
            if ($restrictions) {
 
535
              for my $relid (@{$waytr{$r2}}) {
 
536
                if ($trest{$relid}->[1] eq $r2) {
 
537
                    print "; FIX: RelID=$relid FROM moved from WayID=$r2 to WayID=$r1\n";
 
538
                    $trest{$relid}->[1] = $r1;
 
539
                    $trest{$relid}->[3] += ( (scalar @{$rchain{$r1}}) - 1 );
 
540
                    push @{$waytr{$r1}}, $relid;
 
541
                }
 
542
                if ($trest{$relid}->[4] eq $r2) {
 
543
                    print "; FIX: RelID=$relid TO moved from WayID=$r2 to WayID=$r1\n";
 
544
                    $trest{$relid}->[4] = $r1;
 
545
                    $trest{$relid}->[6] += ( (scalar @{$rchain{$r1}}) - 1 );
 
546
                    push @{$waytr{$r1}}, $relid;
 
547
                }
 
548
              }
 
549
              delete $waytr{$r2};
 
550
            }
 
551
 
 
552
            $enodes{$rchain{$r2}->[0]} -= 2;
 
553
            push @{$rchain{$r1}}, @{$rchain{$r2}}[1..$#{$rchain{$r2}}];
 
554
            delete $rchain{$r2};
 
555
            delete $rprops{$r2};
 
556
            @{$rstart{$p1->[-1]}} = grep { $_ ne $r2 } @{$rstart{$p1->[-1]}};
 
557
        } else {
 
558
            $i ++;
 
559
        }
 
560
    }
 
561
 
 
562
    print STDERR "$countmerg merged\n";
 
563
}
 
564
 
 
565
 
 
566
 
 
567
 
 
568
 
 
569
####    Generating routing graph
 
570
 
 
571
my %rnodes;
 
572
my %nodid;
 
573
 
 
574
print STDERR "Detecting road nodes...   ";
 
575
print "\n\n\n; ### Routing nodes\n\n";
 
576
 
 
577
while (my ($road, $pchain) = each %rchain) {
 
578
    for my $node (@{$pchain}) {    $rnodes{$node} ++;    }
 
579
}
 
580
 
 
581
my $nodcount = 1;
 
582
for my $node (keys %rnodes) {
 
583
    if ($rnodes{$node}>1 || $enodes{$node}>0) {
 
584
#        printf "; NodID=$nodcount - NodeID=$node at (%s) - $rnodes{$node} roads, $enodes{$node} ends\n", $nodes{$node};
 
585
        $nodid{$node} = $nodcount++;
 
586
    }
 
587
}
 
588
 
 
589
printf STDERR "%d found\n", scalar keys %nodid;
 
590
 
 
591
 
 
592
 
 
593
 
 
594
 
 
595
####    Detecting duplicate road segments
 
596
 
 
597
 
 
598
if ($detectdupes) {
 
599
 
 
600
    my %segways;
 
601
 
 
602
    print STDERR "Detecting duplicates...   ";
 
603
    print "\n\n\n; ### Duplicate roads\n\n";
 
604
 
 
605
    while (my ($road, $pchain) = each %rchain) {
 
606
        for (my $i=0; $i<$#{$pchain}; $i++) {
 
607
            if ( $nodid{$pchain->[$i]} && $nodid{$pchain->[$i+1]} )   { 
 
608
                push @{$segways{join(":",( sort {$a cmp $b} ($pchain->[$i],$pchain->[$i+1]) ))}}, $road;
 
609
            }
 
610
        }
 
611
    }
 
612
 
 
613
    my $countdupsegs  = 0;
 
614
    my $countduproads = 0;
 
615
 
 
616
    my %roadsegs;
 
617
    my %roadpos;
 
618
 
 
619
    for my $seg (keys %segways) {
 
620
        if ( $#{$segways{$seg}} > 0 ) {
 
621
#            printf "; ERROR: Segment $seg is a part of %d roads - %s\n", scalar @{$segways{$seg}}, join (", ", @{$segways{$seg}});
 
622
            $countdupsegs ++;
 
623
            my $roads = join ", ", ( sort {$a cmp $b} @{$segways{$seg}} );
 
624
            $roadsegs{$roads} ++;
 
625
            my ($point) = split (":", $seg);
 
626
            $roadpos{$roads} = $nodes{$point};
 
627
        }
 
628
    }
 
629
 
 
630
    for my $road (keys %roadsegs) {
 
631
        $countduproads ++;
 
632
        printf "; ERROR: Roads $road has $roadsegs{$road} duplicate segments near ($roadpos{$road})\n";
 
633
    }
 
634
 
 
635
    printf STDERR "$countdupsegs segments, $countduproads roads\n";
 
636
}
 
637
 
 
638
 
 
639
 
 
640
 
 
641
####    Fixing self-intersections and long roads
 
642
 
 
643
if ($splitroads) {
 
644
    my $countself = 0;
 
645
    my $countlong = 0;
 
646
    print "\n\n\n";
 
647
 
 
648
    print STDERR "Splitting roads...        ";
 
649
    while (my ($road, $pchain) = each %rchain) {
 
650
        my $j = 0;
 
651
        my @breaks = ();
 
652
        my $break = 0;
 
653
        my $rnod = 1;
 
654
        for (my $i=1; $i < scalar @{$pchain}; $i++) {
 
655
            $rnod ++  if ( ${nodid{$pchain->[$i]}} );
 
656
            if (scalar (grep { $_ eq $pchain->[$i] } @{$pchain}[$break..$i-1]) > 0) {
 
657
                $countself ++;
 
658
#                print "; ERROR: WayID=$road has self-intersecton near (${nodes{$pchain->[$i]}})  ($i $j)\n";
 
659
                if ($pchain->[$i] ne $pchain->[$j]) {
 
660
                    $break = $j;
 
661
                    push @breaks, $break;
 
662
                } else {
 
663
                    $break = ($i + $j) >> 1;
 
664
                    push @breaks, $break;
 
665
                    $nodid{$pchain->[$break]} = $nodcount++;
 
666
                    printf "; FIX: Added NodID=%d for NodeID=%s at (%s)\n", $nodid{$pchain->[$break]}, $pchain->[$break], $nodes{$pchain->[$break]};
 
667
                }
 
668
                $rnod = 1;
 
669
            }
 
670
            if ($rnod == 60) {
 
671
                $countlong ++;
 
672
#                print "; ERROR: WayID=$road has too many nodes  ($i $j)\n";
 
673
                $break = $j;
 
674
                push @breaks, $break;
 
675
                $rnod = 1;
 
676
            }
 
677
            $j = $i             if ($nodid{$pchain->[$i]});
 
678
        }
 
679
        if (scalar @breaks > 0) {
 
680
            if ($restrictions) {
 
681
              for my $relid (@{$waytr{$road}}) {
 
682
                # FIXME: processing turn restrictions for splitted roads
 
683
                print STDERR "Warning! Turn restriction RelID=$relid is not properly processed\n";
 
684
                delete $trest{$relid};
 
685
              }
 
686
            }
 
687
            printf "; FIX: WayID=$road is splitted at %s\n", join (", ", @breaks);
 
688
            push @breaks, $#{$pchain};
 
689
            for (my $i=0; $i<$#breaks; $i++) {
 
690
                my $id = $road."/".($i+1);
 
691
                printf "; FIX: Added road %s, nodes from %d to %d\n", $id, $breaks[$i], $breaks[$i+1];
 
692
                $rchain{$id} = [ @{$pchain}[$breaks[$i] .. $breaks[$i+1]] ];
 
693
                $rprops{$id} = $rprops{$road};
 
694
            }
 
695
            $#{$pchain} = $breaks[0];
 
696
        }
 
697
    }
 
698
    print STDERR "$countself self-intersections, $countlong long roads\n";
 
699
}
 
700
 
 
701
 
 
702
 
 
703
 
 
704
####    Fixing "too close nodes" error
 
705
 
 
706
if ($fixclosenodes) {
 
707
    my $countclose = 0;
 
708
 
 
709
    print "\n\n\n";
 
710
    print STDERR "Fixing close nodes...     ";
 
711
    while (my ($road, $pchain) = each %rchain) {
 
712
        my $cnode = $pchain->[0];
 
713
        for my $node (@{$pchain}[1..$#{$pchain}]) {
 
714
            if ($node ne $cnode && $nodid{$node}) {
 
715
                if (closenodes($cnode, $node)) {
 
716
                    print "; ERROR: too close nodes $cnode and $node, WayID=$road near (${nodes{$node}})\n";
 
717
                    $countclose ++;
 
718
                } 
 
719
                $cnode = $node;
 
720
            }
 
721
        }
 
722
    }
 
723
    print STDERR "$countclose pairs fixed\n";
 
724
}
 
725
 
 
726
 
 
727
 
 
728
 
 
729
 
 
730
 
 
731
####    Dumping roads
 
732
 
 
733
my %roadid;
 
734
 
 
735
print STDERR "Writing roads...          ";
 
736
print "\n\n\n; ### Roads\n\n";
 
737
 
 
738
my $roadcount = 1;
 
739
while (my ($road, $pchain) = each %rchain) {
 
740
    my ($poly, $name, $rp) = @{$rprops{$road}};
 
741
    my @type = @{$polytype{$poly}};
 
742
 
 
743
    $roadid{$road} = $roadcount         if ($waytr{$road});
 
744
 
 
745
    #  @type == [ $mode, $type, $prio, $llev, $hlev, $rp ]
 
746
    print  "; WayID = $road\n";
 
747
    print  "; $poly\n";
 
748
    print  "[POLYLINE]\n";
 
749
    printf "Type=%s\n",        $type[1];
 
750
    printf "EndLevel=%d\n",    $type[4]             if ($type[4] > $type[3]);
 
751
    print  "Label=$name\n"                          if ($name);
 
752
    print  "DirIndicator=1\n"                       if ((split /\,/, $rp)[2]);
 
753
 
 
754
    printf "Data%d=(%s)\n", $type[3], join ("), (", @nodes{@{$pchain}});
 
755
    printf "RoadID=%d\n", $roadcount++;
 
756
    printf "RouteParams=%s\n", $rp;
 
757
 
 
758
    my $nodcount=0;
 
759
    for (my $i=0; $i < scalar @{$pchain}; $i++) {
 
760
        my $node = $pchain->[$i];
 
761
        if ($nodid{$node}) {
 
762
            printf "Nod%d=%d,%d,0\n", $nodcount++, $i, $nodid{$node};
 
763
        }
 
764
    }
 
765
    
 
766
    print  "[END]\n\n\n";
 
767
}
 
768
 
 
769
printf STDERR "%d written\n", $roadcount-1;
 
770
 
 
771
 
 
772
 
 
773
 
 
774
 
 
775
####    Writing turn restrictions
 
776
 
 
777
if ($restrictions) {
 
778
    my $counttrest = 0;
 
779
    
 
780
    print "\n\n\n; ### Turn restrictions\n\n";
 
781
 
 
782
    print STDERR "Writing restrictions...   ";
 
783
    
 
784
    while ( my ($relid, $rel) = each %trest ) {
 
785
    
 
786
        printf "\n; RelID = $relid, %s\n", join(":", @{$rel});
 
787
    
 
788
        if      ($rel->[2] == 0) {
 
789
            print "; ERROR: RelID=$relid has undefined FROM direction\n";
 
790
        } elsif ($rel->[5] == 0) {
 
791
            print "; ERROR: RelID=$relid has undefined TO direction\n";
 
792
        } elsif ($rel->[3] == -1) {
 
793
            print "; ERROR: RelID=$relid FROM road does'n contain VIA node\n";
 
794
        } elsif ($rel->[6] == -1) {
 
795
            print "; ERROR: RelID=$relid TO road does'n contain VIA node\n";
 
796
        } else {
 
797
    
 
798
            $counttrest ++;
 
799
    
 
800
            my $i = $rel->[3] - $rel->[2];
 
801
            $i -= $rel->[2]         while ($i>=0 && $i < $#{$rchain{$rel->[1]}} && !$nodid{$rchain{$rel->[1]}->[$i]});
 
802
            my $j = $rel->[6] + $rel->[5];
 
803
            $j += $rel->[5]         while ($j>=0 && $j < $#{$rchain{$rel->[4]}} && !$nodid{$rchain{$rel->[4]}->[$j]});
 
804
    
 
805
            print  "[Restrict]\n";
 
806
            printf "Nod=${nodid{$rel->[0]}}\n";
 
807
            print  "TraffPoints=${nodid{$rchain{$rel->[1]}->[$i]}},${nodid{$rel->[0]}},${nodid{$rchain{$rel->[4]}->[$j]}}\n";
 
808
            print  "TraffRoads=${roadid{$rel->[1]}},${roadid{$rel->[4]}}\n";
 
809
            print  "Time=\n";
 
810
            print  "[END-Restrict]\n";
 
811
        }    
 
812
    }
 
813
    
 
814
    print STDERR "$counttrest written\n";
 
815
}
 
816
 
 
817
 
 
818
 
 
819
 
 
820
 
 
821
print STDERR "All done!!\n\n";
 
822
 
 
823
 
 
824
 
 
825
 
 
826
 
 
827
 
 
828
 
 
829
 
 
830
####    Functions
 
831
 
 
832
use Encode;
 
833
 
 
834
sub convert_string {            # String
 
835
 
 
836
   my $str = encode ("cp".$codepage, decode("utf8", $_[0]));
 
837
 
 
838
   $str =~ s/\&amp\;/\&/gi;
 
839
   $str =~ s/\&#38\;/\&/gi;
 
840
   $str =~ s/\&quot\;/\"/gi;
 
841
   $str =~ s/\&apos\;/\'/gi;
 
842
   $str =~ s/\&#39\;/\'/gi;
 
843
   $str =~ s/\&#47\;/\//gi;
 
844
   $str =~ s/\&#92\;/\\/gi;
 
845
 
 
846
   return $str;
 
847
}
 
848
 
 
849
 
 
850
 
 
851
sub closenodes {                # NodeID1, NodeID2
 
852
 
 
853
    my ($lat1, $lon1) = split ",", $nodes{$_[0]};
 
854
    my ($lat2, $lon2) = split ",", $nodes{$_[1]};
 
855
    
 
856
    my ($clat, $clon) = ( ($lat1+$lat2)/2, ($lon1+$lon2)/2 );
 
857
    my ($dlat, $dlon) = ( ($lat2-$lat1), ($lon2-$lon1) );
 
858
    my $klon = cos ($clat*3.14159/180);
 
859
 
 
860
    my $ldist = $fixclosedist * 180 / 20_000_000;
 
861
 
 
862
    my $res = ($dlat**2 + ($dlon*$klon)**2) < $ldist**2;
 
863
 
 
864
    # fixing
 
865
    if ($res) {
 
866
        if ($dlon == 0) {
 
867
            $nodes{$_[0]} = ($clat - $ldist/2 * ($dlat==0 ? 1 : ($dlat <=> 0) )) . "," . $clon;
 
868
            $nodes{$_[1]} = ($clat + $ldist/2 * ($dlat==0 ? 1 : ($dlat <=> 0) )) . "," . $clon;
 
869
        } else {
 
870
            my $azim = $dlat / $dlon;
 
871
            my $ndlon = sqrt ($ldist**2 / ($klon**2 + $azim**2)) / 2;
 
872
            my $ndlat = $ndlon * abs($azim);
 
873
        
 
874
            $nodes{$_[0]} = ($clat - $ndlat * ($dlat <=> 0)) . "," . ($clon - $ndlon * ($dlon <=> 0));
 
875
            $nodes{$_[1]} = ($clat + $ndlat * ($dlat <=> 0)) . "," . ($clon + $ndlon * ($dlon <=> 0));
 
876
        }
 
877
    }
 
878
    return $res;
 
879
}
 
880
 
 
881
 
 
882
 
 
883
sub lcos {                      # NodeID1, NodeID2, NodeID3
 
884
 
 
885
    my ($lat1, $lon1) = split ",", $nodes{$_[0]};
 
886
    my ($lat2, $lon2) = split ",", $nodes{$_[1]};
 
887
    my ($lat3, $lon3) = split ",", $nodes{$_[2]};
 
888
 
 
889
    my $klon = cos (($lat1+$lat2+$lat3)/3*3.14159/180);
 
890
 
 
891
    my $xx = (($lat2-$lat1)**2+($lon2-$lon1)**2*$klon**2)*(($lat3-$lat2)**2+($lon3-$lon2)**2*$klon**2);
 
892
    return -1   if ( $xx == 0);
 
893
    return (($lat2-$lat1)*($lat3-$lat2)+($lon2-$lon1)*($lon3-$lon2)*$klon**2) / sqrt ($xx);
 
894
}
 
895
 
 
896
 
 
897
 
 
898
sub indexof {                   # \@array, $elem
 
899
 
 
900
    for (my $i=0; $i < scalar @{$_[0]}; $i++) 
 
901
        { return $i if ($_[0]->[$i] eq $_[1]); }
 
902
    return -1;
 
903
}
 
904