Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/planetsplitter.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1167 - (show annotations) (download) (as text)
Tue Nov 20 16:21:27 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 19064 byte(s)
Rename the '--preserve' command line option to '--keep' for simplicity.

1 /***************************************
2 OSM planet file splitter.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2012 Andrew M. Bishop
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Affero General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ***************************************/
21
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <sys/time.h>
28
29 #include "types.h"
30 #include "ways.h"
31
32 #include "typesx.h"
33 #include "nodesx.h"
34 #include "segmentsx.h"
35 #include "waysx.h"
36 #include "relationsx.h"
37 #include "superx.h"
38 #include "prunex.h"
39
40 #include "files.h"
41 #include "logging.h"
42 #include "functions.h"
43 #include "osmparser.h"
44 #include "tagging.h"
45
46
47 /* Global variables */
48
49 /*+ The name of the temporary directory. +*/
50 char *option_tmpdirname=NULL;
51
52 /*+ The amount of RAM to use for filesorting. +*/
53 size_t option_filesort_ramsize=0;
54
55 /*+ The number of threads to use for filesorting. +*/
56 int option_filesort_threads=1;
57
58 /*+ The option to apply changes (needed to suppress some error log messages) +*/
59 int option_changes=0;
60
61
62 /* Local functions */
63
64 static void print_usage(int detail,const char *argerr,const char *err);
65
66
67 /*++++++++++++++++++++++++++++++++++++++
68 The main program for the planetsplitter.
69 ++++++++++++++++++++++++++++++++++++++*/
70
71 int main(int argc,char** argv)
72 {
73 struct timeval start_time;
74 NodesX *Nodes;
75 SegmentsX *Segments,*SuperSegments=NULL,*MergedSegments=NULL;
76 WaysX *Ways;
77 RelationsX *Relations;
78 int iteration=0,quit=0;
79 int max_iterations=5;
80 char *dirname=NULL,*prefix=NULL,*tagging=NULL,*errorlog=NULL;
81 int option_parse_only=0,option_process_only=0;
82 int option_append=0,option_keep=0;
83 int option_filenames=0;
84 int option_prune_isolated=500,option_prune_short=5,option_prune_straight=3;
85 int arg;
86
87 gettimeofday(&start_time,NULL);
88
89 /* Parse the command line arguments */
90
91 for(arg=1;arg<argc;arg++)
92 {
93 if(!strcmp(argv[arg],"--help"))
94 print_usage(1,NULL,NULL);
95 else if(!strncmp(argv[arg],"--sort-ram-size=",16))
96 option_filesort_ramsize=atoi(&argv[arg][16]);
97 #if defined(USE_PTHREADS) && USE_PTHREADS
98 else if(!strncmp(argv[arg],"--sort-threads=",15))
99 option_filesort_threads=atoi(&argv[arg][15]);
100 #endif
101 else if(!strncmp(argv[arg],"--dir=",6))
102 dirname=&argv[arg][6];
103 else if(!strncmp(argv[arg],"--tmpdir=",9))
104 option_tmpdirname=&argv[arg][9];
105 else if(!strncmp(argv[arg],"--prefix=",9))
106 prefix=&argv[arg][9];
107 else if(!strcmp(argv[arg],"--parse-only"))
108 option_parse_only=1;
109 else if(!strcmp(argv[arg],"--process-only"))
110 option_process_only=1;
111 else if(!strcmp(argv[arg],"--append"))
112 option_append=1;
113 else if(!strcmp(argv[arg],"--keep"))
114 option_keep=1;
115 else if(!strcmp(argv[arg],"--changes"))
116 option_changes=1;
117 else if(!strcmp(argv[arg],"--loggable"))
118 option_loggable=1;
119 else if(!strcmp(argv[arg],"--logtime"))
120 option_logtime=1;
121 else if(!strcmp(argv[arg],"--errorlog"))
122 errorlog="error.log";
123 else if(!strncmp(argv[arg],"--errorlog=",11))
124 errorlog=&argv[arg][11];
125 else if(!strncmp(argv[arg],"--max-iterations=",17))
126 max_iterations=atoi(&argv[arg][17]);
127 else if(!strncmp(argv[arg],"--tagging=",10))
128 tagging=&argv[arg][10];
129 else if(!strncmp(argv[arg],"--prune",7))
130 {
131 if(!strcmp(&argv[arg][7],"-none"))
132 option_prune_isolated=option_prune_short=option_prune_straight=0;
133 else if(!strncmp(&argv[arg][7],"-isolated=",10))
134 option_prune_isolated=atoi(&argv[arg][17]);
135 else if(!strncmp(&argv[arg][7],"-short=",7))
136 option_prune_short=atoi(&argv[arg][14]);
137 else if(!strncmp(&argv[arg][7],"-straight=",10))
138 option_prune_straight=atoi(&argv[arg][17]);
139 else
140 print_usage(0,argv[arg],NULL);
141 }
142 else if(argv[arg][0]=='-' && argv[arg][1]=='-')
143 print_usage(0,argv[arg],NULL);
144 else
145 option_filenames++;
146 }
147
148 /* Check the specified command line options */
149
150 if(option_parse_only && option_process_only)
151 print_usage(0,NULL,"Cannot use '--parse-only' and '--process-only' at the same time.");
152
153 if(option_append && option_process_only)
154 print_usage(0,NULL,"Cannot use '--append' and '--process-only' at the same time.");
155
156 if(option_filenames && option_process_only)
157 print_usage(0,NULL,"Cannot use '--process-only' and filenames at the same time.");
158
159 if(!option_filesort_ramsize)
160 {
161 #if SLIM
162 option_filesort_ramsize=64*1024*1024;
163 #else
164 option_filesort_ramsize=256*1024*1024;
165 #endif
166 }
167 else
168 option_filesort_ramsize*=1024*1024;
169
170 if(!option_tmpdirname)
171 {
172 if(!dirname)
173 option_tmpdirname=".";
174 else
175 option_tmpdirname=dirname;
176 }
177
178 if(!option_process_only)
179 {
180 if(tagging)
181 {
182 if(!ExistsFile(tagging))
183 {
184 fprintf(stderr,"Error: The '--tagging' option specifies a file that does not exist.\n");
185 return(1);
186 }
187 }
188 else
189 {
190 if(ExistsFile(FileName(dirname,prefix,"tagging.xml")))
191 tagging=FileName(dirname,prefix,"tagging.xml");
192 else if(ExistsFile(FileName(DATADIR,NULL,"tagging.xml")))
193 tagging=FileName(DATADIR,NULL,"tagging.xml");
194 else
195 {
196 fprintf(stderr,"Error: The '--tagging' option was not used and the default 'tagging.xml' does not exist.\n");
197 return(1);
198 }
199 }
200
201 if(ParseXMLTaggingRules(tagging))
202 {
203 fprintf(stderr,"Error: Cannot read the tagging rules in the file '%s'.\n",tagging);
204 return(1);
205 }
206 }
207
208 /* Create new node, segment, way and relation variables */
209
210 Nodes=NewNodeList(option_append||option_changes,option_process_only);
211
212 Segments=NewSegmentList(option_append||option_changes,option_process_only);
213
214 Ways=NewWayList(option_append||option_changes,option_process_only);
215
216 Relations=NewRelationList(option_append||option_changes,option_process_only);
217
218 /* Create the error log file */
219
220 if(errorlog)
221 open_errorlog(FileName(dirname,prefix,errorlog),option_append||option_changes||option_process_only);
222
223 /* Parse the file */
224
225 if(!option_process_only)
226 {
227 if(option_filenames)
228 {
229 for(arg=1;arg<argc;arg++)
230 {
231 FILE *file;
232
233 if(argv[arg][0]=='-' && argv[arg][1]=='-')
234 continue;
235
236 file=fopen(argv[arg],"rb");
237
238 if(!file)
239 {
240 fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",argv[arg],strerror(errno));
241 exit(EXIT_FAILURE);
242 }
243
244 if(option_changes)
245 {
246 printf("\nParse OSC Data [%s]\n==============\n\n",argv[arg]);
247 fflush(stdout);
248
249 if(ParseOSC(file,Nodes,Segments,Ways,Relations))
250 exit(EXIT_FAILURE);
251 }
252 else
253 {
254 printf("\nParse OSM Data [%s]\n==============\n\n",argv[arg]);
255 fflush(stdout);
256
257 if(ParseOSM(file,Nodes,Segments,Ways,Relations))
258 exit(EXIT_FAILURE);
259 }
260
261 fclose(file);
262 }
263 }
264 else
265 {
266 if(option_changes)
267 {
268 printf("\nParse OSC Data\n==============\n\n");
269 fflush(stdout);
270
271 if(ParseOSC(stdin,Nodes,Segments,Ways,Relations))
272 exit(EXIT_FAILURE);
273 }
274 else
275 {
276 printf("\nParse OSM Data\n==============\n\n");
277 fflush(stdout);
278
279 if(ParseOSM(stdin,Nodes,Segments,Ways,Relations))
280 exit(EXIT_FAILURE);
281 }
282 }
283
284 DeleteXMLTaggingRules();
285 }
286
287 FinishNodeList(Nodes);
288 FinishSegmentList(Segments);
289 FinishWayList(Ways);
290 FinishRelationList(Relations);
291
292 if(option_parse_only)
293 {
294 FreeNodeList(Nodes,1);
295 FreeSegmentList(Segments,1);
296 FreeWayList(Ways,1);
297 FreeRelationList(Relations,1);
298
299 return(0);
300 }
301
302
303 /* Sort the data */
304
305 printf("\nSort OSM Data\n=============\n\n");
306 fflush(stdout);
307
308 /* Sort the nodes, segments, ways and relations */
309
310 SortNodeList(Nodes);
311
312 if(option_changes)
313 ApplySegmentChanges(Segments);
314
315 SortSegmentList(Segments);
316
317 SortWayList(Ways);
318
319 SortRelationList(Relations);
320
321 /* Process the data */
322
323 printf("\nProcess OSM Data\n================\n\n");
324 fflush(stdout);
325
326 /* Extract the way names (must be before using the ways) */
327
328 ExtractWayNames(Ways,option_keep||option_changes);
329
330 /* Remove bad segments (must be after sorting the nodes, segments and ways) */
331
332 RemoveBadSegments(Segments,Nodes,Ways,option_keep||option_changes);
333
334 /* Remove non-highway nodes (must be after removing the bad segments) */
335
336 RemoveNonHighwayNodes(Nodes,Segments,option_keep||option_changes);
337
338 /* Process the route relations and first part of turn relations (must be before compacting the ways) */
339
340 ProcessRouteRelations(Relations,Ways,option_keep||option_changes);
341
342 ProcessTurnRelations1(Relations,Nodes,Ways,option_keep||option_changes);
343
344 /* Measure the segments and replace node/way id with index (must be after removing non-highway nodes) */
345
346 MeasureSegments(Segments,Nodes,Ways);
347
348 /* Index the segments */
349
350 IndexSegments(Segments,Nodes,Ways);
351
352 /* Convert the turn relations from ways into nodes */
353
354 ProcessTurnRelations2(Relations,Nodes,Segments,Ways);
355
356 /* Compact the ways (must be after turn relations 2) */
357
358 CompactWayList(Ways,Segments);
359
360 /* Index the segments */
361
362 IndexSegments(Segments,Nodes,Ways);
363
364 /* Prune unwanted nodes/segments. */
365
366 if(option_prune_straight || option_prune_isolated || option_prune_short)
367 {
368 printf("\nPrune Unneeded Data\n===================\n\n");
369 fflush(stdout);
370
371 StartPruning(Nodes,Segments,Ways);
372
373 if(option_prune_straight)
374 PruneStraightHighwayNodes(Nodes,Segments,Ways,option_prune_straight);
375
376 if(option_prune_isolated)
377 PruneIsolatedRegions(Nodes,Segments,Ways,option_prune_isolated);
378
379 if(option_prune_short)
380 PruneShortSegments(Nodes,Segments,Ways,option_prune_short);
381
382 FinishPruning(Nodes,Segments,Ways);
383
384 /* Remove the pruned nodes and segments and update the indexes */
385
386 RemovePrunedNodes(Nodes,Segments);
387 RemovePrunedSegments(Segments,Ways);
388 CompactWayList(Ways,Segments);
389 RemovePrunedTurnRelations(Relations,Nodes);
390 IndexSegments(Segments,Nodes,Ways);
391 }
392
393 /* Repeated iteration on Super-Nodes and Super-Segments */
394
395 do
396 {
397 int nsuper;
398
399 printf("\nProcess Super-Data (iteration %d)\n================================%s\n\n",iteration,iteration>9?"=":"");
400 fflush(stdout);
401
402 if(iteration==0)
403 {
404 /* Select the super-nodes */
405
406 ChooseSuperNodes(Nodes,Segments,Ways);
407
408 /* Select the super-segments */
409
410 SuperSegments=CreateSuperSegments(Nodes,Segments,Ways);
411
412 nsuper=Segments->number;
413 }
414 else
415 {
416 SegmentsX *SuperSegments2;
417
418 /* Select the super-nodes */
419
420 ChooseSuperNodes(Nodes,SuperSegments,Ways);
421
422 /* Select the super-segments */
423
424 SuperSegments2=CreateSuperSegments(Nodes,SuperSegments,Ways);
425
426 nsuper=SuperSegments->number;
427
428 FreeSegmentList(SuperSegments,0);
429
430 SuperSegments=SuperSegments2;
431 }
432
433 /* Sort the super-segments and remove duplicates */
434
435 DeduplicateSuperSegments(SuperSegments,Ways);
436
437 /* Index the segments */
438
439 IndexSegments(SuperSegments,Nodes,Ways);
440
441 /* Check for end condition */
442
443 if(SuperSegments->number==nsuper)
444 quit=1;
445
446 iteration++;
447
448 if(iteration>max_iterations)
449 quit=1;
450 }
451 while(!quit);
452
453 /* Combine the super-segments */
454
455 printf("\nCombine Segments and Super-Segments\n===================================\n\n");
456 fflush(stdout);
457
458 /* Merge the super-segments */
459
460 MergedSegments=MergeSuperSegments(Segments,SuperSegments);
461
462 FreeSegmentList(Segments,0);
463
464 FreeSegmentList(SuperSegments,0);
465
466 Segments=MergedSegments;
467
468 /* Re-index the merged segments */
469
470 IndexSegments(Segments,Nodes,Ways);
471
472 /* Cross reference the nodes and segments */
473
474 printf("\nCross-Reference Nodes and Segments\n==================================\n\n");
475 fflush(stdout);
476
477 /* Sort the nodes and segments geographically */
478
479 SortNodeListGeographically(Nodes);
480
481 SortSegmentListGeographically(Segments,Nodes);
482
483 /* Re-index the segments */
484
485 IndexSegments(Segments,Nodes,Ways);
486
487 /* Sort the turn relations geographically */
488
489 SortTurnRelationListGeographically(Relations,Nodes,Segments);
490
491 /* Output the results */
492
493 printf("\nWrite Out Database Files\n========================\n\n");
494 fflush(stdout);
495
496 /* Write out the nodes */
497
498 SaveNodeList(Nodes,FileName(dirname,prefix,"nodes.mem"),Segments);
499
500 FreeNodeList(Nodes,0);
501
502 /* Write out the segments */
503
504 SaveSegmentList(Segments,FileName(dirname,prefix,"segments.mem"));
505
506 FreeSegmentList(Segments,0);
507
508 /* Write out the ways */
509
510 SaveWayList(Ways,FileName(dirname,prefix,"ways.mem"));
511
512 FreeWayList(Ways,0);
513
514 /* Write out the relations */
515
516 SaveRelationList(Relations,FileName(dirname,prefix,"relations.mem"));
517
518 FreeRelationList(Relations,0);
519
520 /* Close the error log file */
521
522 if(errorlog)
523 close_errorlog();
524
525 /* Print the total time */
526
527 if(option_logtime)
528 {
529 printf("\n");
530 fprintf_elapsed_time(stdout,&start_time);
531 printf("Complete\n");
532 fflush(stdout);
533 }
534
535 return(0);
536 }
537
538
539 /*++++++++++++++++++++++++++++++++++++++
540 Print out the usage information.
541
542 int detail The level of detail to use - 0 = low, 1 = high.
543
544 const char *argerr The argument that gave the error (if there is one).
545
546 const char *err Other error message (if there is one).
547 ++++++++++++++++++++++++++++++++++++++*/
548
549 static void print_usage(int detail,const char *argerr,const char *err)
550 {
551 fprintf(stderr,
552 "Usage: planetsplitter [--help]\n"
553 " [--dir=<dirname>] [--prefix=<name>]\n"
554 #if defined(USE_PTHREADS) && USE_PTHREADS
555 " [--sort-ram-size=<size>] [--sort-threads=<number>]\n"
556 #else
557 " [--sort-ram-size=<size>]\n"
558 #endif
559 " [--tmpdir=<dirname>]\n"
560 " [--tagging=<filename>]\n"
561 " [--loggable] [--logtime]\n"
562 " [--errorlog[=<name>]]\n"
563 " [--parse-only | --process-only]\n"
564 " [--append] [--keep] [--changes]\n"
565 " [--max-iterations=<number>]\n"
566 " [--prune-none]\n"
567 " [--prune-isolated=<len>]\n"
568 " [--prune-short=<len>]\n"
569 " [--prune-straight=<len>]\n"
570 " [<filename.osm> ...]\n");
571
572 if(argerr)
573 fprintf(stderr,
574 "\n"
575 "Error with command line parameter: %s\n",argerr);
576
577 if(err)
578 fprintf(stderr,
579 "\n"
580 "Error: %s\n",err);
581
582 if(detail)
583 fprintf(stderr,
584 "\n"
585 "--help Prints this information.\n"
586 "\n"
587 "--dir=<dirname> The directory containing the routing database.\n"
588 "--prefix=<name> The filename prefix for the routing database.\n"
589 "\n"
590 "--sort-ram-size=<size> The amount of RAM (in MB) to use for data sorting\n"
591 #if SLIM
592 " (defaults to 64MB otherwise.)\n"
593 #else
594 " (defaults to 256MB otherwise.)\n"
595 #endif
596 #if defined(USE_PTHREADS) && USE_PTHREADS
597 "--sort-threads=<number> The number of threads to use for data sorting.\n"
598 #endif
599 "\n"
600 "--tmpdir=<dirname> The directory name for temporary files.\n"
601 " (defaults to the '--dir' option directory.)\n"
602 "\n"
603 "--tagging=<filename> The name of the XML file containing the tagging rules\n"
604 " (defaults to 'tagging.xml' with '--dir' and\n"
605 " '--prefix' options or the file installed in\n"
606 " '" DATADIR "').\n"
607 "\n"
608 "--loggable Print progress messages suitable for logging to file.\n"
609 "--logtime Print the elapsed time for each processing step.\n"
610 "--errorlog[=<name>] Log parsing errors to 'error.log' or the given name\n"
611 " (the '--dir' and '--prefix' options are applied).\n"
612 "\n"
613 "--parse-only Parse the OSM/OSC file(s) and store the results.\n"
614 "--process-only Process the stored results from previous option.\n"
615 "--append Parse the OSM file(s) and append to existing results.\n"
616 "--keep Keep the intermediate files after parsing & sorting.\n"
617 "--changes Parse the data as an OSC file and apply the changes.\n"
618 "\n"
619 "--max-iterations=<number> The number of iterations for finding super-nodes\n"
620 " (defaults to 5).\n"
621 "\n"
622 "--prune-none Disable the prune options below, they are re-enabled\n"
623 " by adding them to the command line after this option.\n"
624 "--prune-isolated=<len> Remove access from small disconnected segment groups\n"
625 " (defaults to removing groups under 500m).\n"
626 "--prune-short=<len> Remove short segments (defaults to removing segments\n"
627 " up to a maximum length of 5m).\n"
628 "--prune-straight=<len> Remove nodes in almost straight highways (defaults to\n"
629 " removing nodes up to 3m offset from a straight line).\n"
630 "\n"
631 "<filename.osm> ... The name(s) of the file(s) to process (by default\n"
632 " data is read from standard input).\n"
633 "\n"
634 "<transport> defaults to all but can be set to:\n"
635 "%s"
636 "\n"
637 "<highway> can be selected from:\n"
638 "%s"
639 "\n"
640 "<property> can be selected from:\n"
641 "%s",
642 TransportList(),HighwayList(),PropertyList());
643
644 exit(!detail);
645 }

Properties

Name Value
cvs:description Planet file splitter.