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 964 - (show annotations) (download) (as text)
Sat Feb 11 19:51:46 2012 UTC (13 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 14967 byte(s)
Prune short segments.

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
28 #include "types.h"
29 #include "ways.h"
30
31 #include "typesx.h"
32 #include "nodesx.h"
33 #include "segmentsx.h"
34 #include "waysx.h"
35 #include "relationsx.h"
36 #include "superx.h"
37 #include "prunex.h"
38
39 #include "files.h"
40 #include "logging.h"
41 #include "functions.h"
42 #include "osmparser.h"
43 #include "tagging.h"
44
45
46 /* Global variables */
47
48 /*+ The name of the temporary directory. +*/
49 char *option_tmpdirname=NULL;
50
51 /*+ The amount of RAM to use for filesorting. +*/
52 size_t option_filesort_ramsize=0;
53
54
55 /* Local functions */
56
57 static void print_usage(int detail,const char *argerr,const char *err);
58
59
60 /*++++++++++++++++++++++++++++++++++++++
61 The main program for the planetsplitter.
62 ++++++++++++++++++++++++++++++++++++++*/
63
64 int main(int argc,char** argv)
65 {
66 NodesX *Nodes;
67 SegmentsX *Segments,*SuperSegments=NULL,*MergedSegments=NULL;
68 WaysX *Ways;
69 RelationsX *Relations;
70 int iteration=0,quit=0;
71 int max_iterations=5;
72 char *dirname=NULL,*prefix=NULL,*tagging=NULL,*errorlog=NULL;
73 int option_parse_only=0,option_process_only=0;
74 int option_filenames=0;
75 int option_prune=0,prune_isolated=0,prune_short=0;
76 int arg;
77
78 /* Parse the command line arguments */
79
80 for(arg=1;arg<argc;arg++)
81 {
82 if(!strcmp(argv[arg],"--help"))
83 print_usage(1,NULL,NULL);
84 else if(!strncmp(argv[arg],"--sort-ram-size=",16))
85 option_filesort_ramsize=atoi(&argv[arg][16]);
86 else if(!strncmp(argv[arg],"--dir=",6))
87 dirname=&argv[arg][6];
88 else if(!strncmp(argv[arg],"--tmpdir=",9))
89 option_tmpdirname=&argv[arg][9];
90 else if(!strncmp(argv[arg],"--prefix=",9))
91 prefix=&argv[arg][9];
92 else if(!strcmp(argv[arg],"--parse-only"))
93 option_parse_only=1;
94 else if(!strcmp(argv[arg],"--process-only"))
95 option_process_only=1;
96 else if(!strcmp(argv[arg],"--loggable"))
97 option_loggable=1;
98 else if(!strcmp(argv[arg],"--errorlog"))
99 errorlog="error.log";
100 else if(!strncmp(argv[arg],"--errorlog=",11))
101 errorlog=&argv[arg][11];
102 else if(!strncmp(argv[arg],"--max-iterations=",17))
103 max_iterations=atoi(&argv[arg][17]);
104 else if(!strncmp(argv[arg],"--tagging=",10))
105 tagging=&argv[arg][10];
106 else if(!strncmp(argv[arg],"--prune",7))
107 {
108 option_prune=1;
109
110 if(!strcmp(&argv[arg][7],"-isolated"))
111 prune_isolated=500;
112 else if(!strncmp(&argv[arg][7],"-isolated=",10))
113 prune_isolated=atoi(&argv[arg][17]);
114 else if(!strcmp(&argv[arg][7],"-short"))
115 prune_short=5;
116 else if(!strncmp(&argv[arg][7],"-short=",7))
117 prune_short=atoi(&argv[arg][14]);
118 else
119 print_usage(0,argv[arg],NULL);
120 }
121 else if(argv[arg][0]=='-' && argv[arg][1]=='-')
122 print_usage(0,argv[arg],NULL);
123 else
124 option_filenames++;
125 }
126
127 /* Check the specified command line options */
128
129 if(option_parse_only && option_process_only)
130 print_usage(0,NULL,"Cannot use '--parse-only' and '--process-only' at the same time.");
131
132 if(option_filenames && option_process_only)
133 print_usage(0,NULL,"Cannot use '--process-only' and filenames at the same time.");
134
135 if(!option_filesort_ramsize)
136 {
137 #if SLIM
138 option_filesort_ramsize=64*1024*1024;
139 #else
140 option_filesort_ramsize=256*1024*1024;
141 #endif
142 }
143 else
144 option_filesort_ramsize*=1024*1024;
145
146 if(!option_tmpdirname)
147 {
148 if(!dirname)
149 option_tmpdirname=".";
150 else
151 option_tmpdirname=dirname;
152 }
153
154 if(tagging)
155 {
156 if(!ExistsFile(tagging))
157 {
158 fprintf(stderr,"Error: The '--tagging' option specifies a file that does not exist.\n");
159 return(1);
160 }
161 }
162 else
163 {
164 if(ExistsFile(FileName(dirname,prefix,"tagging.xml")))
165 tagging=FileName(dirname,prefix,"tagging.xml");
166 else if(ExistsFile(FileName(DATADIR,NULL,"tagging.xml")))
167 tagging=FileName(DATADIR,NULL,"tagging.xml");
168 else
169 {
170 fprintf(stderr,"Error: The '--tagging' option was not used and the default 'tagging.xml' does not exist.\n");
171 return(1);
172 }
173 }
174
175 if(ParseXMLTaggingRules(tagging))
176 {
177 fprintf(stderr,"Error: Cannot read the tagging rules in the file '%s'.\n",tagging);
178 return(1);
179 }
180
181 /* Create new node, segment, way and relation variables */
182
183 Nodes=NewNodeList(option_parse_only||option_process_only);
184
185 Segments=NewSegmentList(option_parse_only||option_process_only);
186
187 Ways=NewWayList(option_parse_only||option_process_only);
188
189 Relations=NewRelationList(option_parse_only||option_process_only);
190
191 /* Create the error log file */
192
193 if(errorlog)
194 open_errorlog(FileName(dirname,prefix,errorlog),option_parse_only||option_process_only);
195
196 /* Parse the file */
197
198 if(option_filenames)
199 {
200 for(arg=1;arg<argc;arg++)
201 {
202 FILE *file;
203
204 if(argv[arg][0]=='-' && argv[arg][1]=='-')
205 continue;
206
207 file=fopen(argv[arg],"rb");
208
209 if(!file)
210 {
211 fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",argv[arg],strerror(errno));
212 exit(EXIT_FAILURE);
213 }
214
215 printf("\nParse OSM Data [%s]\n==============\n\n",argv[arg]);
216 fflush(stdout);
217
218 if(ParseOSM(file,Nodes,Segments,Ways,Relations))
219 exit(EXIT_FAILURE);
220
221 fclose(file);
222 }
223 }
224 else if(!option_process_only)
225 {
226 printf("\nParse OSM Data\n==============\n\n");
227 fflush(stdout);
228
229 if(ParseOSM(stdin,Nodes,Segments,Ways,Relations))
230 exit(EXIT_FAILURE);
231 }
232
233 if(option_parse_only)
234 {
235 FreeNodeList(Nodes,1);
236 FreeSegmentList(Segments,1);
237 FreeWayList(Ways,1);
238 FreeRelationList(Relations,1);
239
240 return(0);
241 }
242
243 DeleteXMLTaggingRules();
244
245 /* Process the data */
246
247 printf("\nProcess OSM Data\n================\n\n");
248 fflush(stdout);
249
250 /* Sort the nodes, segments, ways and relations */
251
252 SortNodeList(Nodes);
253
254 SortSegmentList(Segments,0);
255
256 SortWayList(Ways);
257
258 SortRelationList(Relations);
259
260 /* Remove bad segments (must be after sorting the nodes and segments) */
261
262 RemoveBadSegments(Nodes,Segments);
263
264 /* Remove non-highway nodes (must be after removing the bad segments) */
265
266 RemoveNonHighwayNodes(Nodes,Segments);
267
268 /* Process the route relations and first part of turn relations (must be before compacting the ways) */
269
270 ProcessRouteRelations(Relations,Ways);
271
272 ProcessTurnRelations1(Relations,Nodes,Ways);
273
274 /* Compact the ways (must be before measuring the segments) */
275
276 CompactWayList(Ways);
277
278 /* Measure the segments and replace node/way id with index (must be after removing non-highway nodes) */
279
280 MeasureSegments(Segments,Nodes,Ways);
281
282 /* Index the segments */
283
284 IndexSegments(Segments,Nodes);
285
286 /* Convert the turn relations from ways into nodes */
287
288 ProcessTurnRelations2(Relations,Nodes,Segments,Ways);
289
290 /* Prune unwanted nodes/segments. */
291
292 if(option_prune)
293 {
294 StartPruning(Nodes,Segments,Ways);
295
296 if(prune_isolated)
297 PruneIsolatedRegions(Nodes,Segments,Ways,prune_isolated);
298
299 if(prune_short)
300 PruneShortSegments(Nodes,Segments,Ways,prune_short);
301
302 FinishPruning(Nodes,Segments,Ways);
303 }
304
305 /* Repeated iteration on Super-Nodes and Super-Segments */
306
307 do
308 {
309 int nsuper;
310
311 printf("\nProcess Super-Data (iteration %d)\n================================%s\n\n",iteration,iteration>9?"=":"");
312 fflush(stdout);
313
314 if(iteration==0)
315 {
316 /* Select the super-nodes */
317
318 ChooseSuperNodes(Nodes,Segments,Ways);
319
320 /* Select the super-segments */
321
322 SuperSegments=CreateSuperSegments(Nodes,Segments,Ways);
323
324 nsuper=Segments->number;
325 }
326 else
327 {
328 SegmentsX *SuperSegments2;
329
330 /* Select the super-nodes */
331
332 ChooseSuperNodes(Nodes,SuperSegments,Ways);
333
334 /* Select the super-segments */
335
336 SuperSegments2=CreateSuperSegments(Nodes,SuperSegments,Ways);
337
338 nsuper=SuperSegments->number;
339
340 FreeSegmentList(SuperSegments,0);
341
342 SuperSegments=SuperSegments2;
343 }
344
345 /* Sort the super-segments */
346
347 SortSegmentList(SuperSegments,0);
348
349 /* Remove duplicated super-segments */
350
351 DeduplicateSegments(SuperSegments,Nodes,Ways);
352
353 /* Index the segments */
354
355 IndexSegments(SuperSegments,Nodes);
356
357 /* Check for end condition */
358
359 if(SuperSegments->number==nsuper)
360 quit=1;
361
362 iteration++;
363
364 if(iteration>max_iterations)
365 quit=1;
366 }
367 while(!quit);
368
369 /* Combine the super-segments */
370
371 printf("\nCombine Segments and Super-Segments\n===================================\n\n");
372 fflush(stdout);
373
374 /* Merge the super-segments */
375
376 MergedSegments=MergeSuperSegments(Segments,SuperSegments);
377
378 FreeSegmentList(Segments,0);
379
380 FreeSegmentList(SuperSegments,0);
381
382 Segments=MergedSegments;
383
384 /* Sort and re-index the segments */
385
386 SortSegmentList(Segments,0);
387
388 IndexSegments(Segments,Nodes);
389
390 /* Cross reference the nodes and segments */
391
392 printf("\nCross-Reference Nodes and Segments\n==================================\n\n");
393 fflush(stdout);
394
395 /* Sort the nodes geographically and update the segment indexes accordingly */
396
397 SortNodeListGeographically(Nodes);
398
399 UpdateSegments(Segments,Nodes,Ways);
400
401 /* Sort the segments geographically and re-index them */
402
403 SortSegmentList(Segments,0);
404
405 IndexSegments(Segments,Nodes);
406
407 /* Update the nodes */
408
409 UpdateNodes(Nodes,Segments);
410
411 /* Fix the turn relations after sorting nodes geographically */
412
413 UpdateTurnRelations(Relations,Nodes,Segments);
414
415 SortTurnRelationList(Relations);
416
417 /* Output the results */
418
419 printf("\nWrite Out Database Files\n========================\n\n");
420 fflush(stdout);
421
422 /* Write out the nodes */
423
424 SaveNodeList(Nodes,FileName(dirname,prefix,"nodes.mem"));
425
426 FreeNodeList(Nodes,0);
427
428 /* Write out the segments */
429
430 SaveSegmentList(Segments,FileName(dirname,prefix,"segments.mem"));
431
432 FreeSegmentList(Segments,0);
433
434 /* Write out the ways */
435
436 SaveWayList(Ways,FileName(dirname,prefix,"ways.mem"));
437
438 FreeWayList(Ways,0);
439
440 /* Write out the relations */
441
442 SaveRelationList(Relations,FileName(dirname,prefix,"relations.mem"));
443
444 FreeRelationList(Relations,0);
445
446 /* Close the error log file */
447
448 if(errorlog)
449 close_errorlog();
450
451 return(0);
452 }
453
454
455 /*++++++++++++++++++++++++++++++++++++++
456 Print out the usage information.
457
458 int detail The level of detail to use - 0 = low, 1 = high.
459
460 const char *argerr The argument that gave the error (if there is one).
461
462 const char *err Other error message (if there is one).
463 ++++++++++++++++++++++++++++++++++++++*/
464
465 static void print_usage(int detail,const char *argerr,const char *err)
466 {
467 fprintf(stderr,
468 "Usage: planetsplitter [--help]\n"
469 " [--dir=<dirname>] [--prefix=<name>]\n"
470 " [--sort-ram-size=<size>]\n"
471 " [--tmpdir=<dirname>]\n"
472 " [--tagging=<filename>]\n"
473 " [--loggable] [--errorlog[=<name>]]\n"
474 " [--parse-only | --process-only]\n"
475 " [--max-iterations=<number>]\n"
476 " [--prune-isolated[=<len>]]\n"
477 " [--prune-short[=<len>]]\n"
478 " [<filename.osm> ...]\n");
479
480 if(argerr)
481 fprintf(stderr,
482 "\n"
483 "Error with command line parameter: %s\n",argerr);
484
485 if(err)
486 fprintf(stderr,
487 "\n"
488 "Error: %s\n",err);
489
490 if(detail)
491 fprintf(stderr,
492 "\n"
493 "--help Prints this information.\n"
494 "\n"
495 "--dir=<dirname> The directory containing the routing database.\n"
496 "--prefix=<name> The filename prefix for the routing database.\n"
497 "\n"
498 "--sort-ram-size=<size> The amount of RAM (in MB) to use for data sorting\n"
499 #if SLIM
500 " (defaults to 64MB otherwise.)\n"
501 #else
502 " (defaults to 256MB otherwise.)\n"
503 #endif
504 "--tmpdir=<dirname> The directory name for temporary files.\n"
505 " (defaults to the '--dir' option directory.)\n"
506 "\n"
507 "--tagging=<filename> The name of the XML file containing the tagging rules\n"
508 " (defaults to 'tagging.xml' with '--dir' and\n"
509 " '--prefix' options or the file installed in\n"
510 " '" DATADIR "').\n"
511 "\n"
512 "--loggable Print progress messages suitable for logging to file.\n"
513 "--errorlog[=<name>] Log parsing errors to 'error.log' or the given name\n"
514 " (the '--dir' and '--prefix' options are applied).\n"
515 "\n"
516 "--parse-only Parse the input OSM files and store the results.\n"
517 "--process-only Process the stored results from previous option.\n"
518 "\n"
519 "--max-iterations=<number> The number of iterations for finding super-nodes\n"
520 " (defaults to 5).\n"
521 "\n"
522 "--prune-isolated[=<len>] Remove small disconnected groups of segments\n"
523 " (if no length given then 500m length is used).\n"
524 "--prune-short[=<len>] Remove short segments\n"
525 " (if no length given then 5m length is used).\n"
526 "\n"
527 "<filename.osm> ... The name(s) of the file(s) to process (by default\n"
528 " data is read from standard input).\n"
529 "\n"
530 "<transport> defaults to all but can be set to:\n"
531 "%s"
532 "\n"
533 "<highway> can be selected from:\n"
534 "%s"
535 "\n"
536 "<property> can be selected from:\n"
537 "%s",
538 TransportList(),HighwayList(),PropertyList());
539
540 exit(!detail);
541 }

Properties

Name Value
cvs:description Planet file splitter.