Imported Upstream version 1.4.1
[routino] / src / planetsplitter.c
1 /***************************************
2  $Header: /home/amb/routino/src/RCS/planetsplitter.c,v 1.73 2010/05/22 18:40:47 amb Exp $
3
4  OSM planet file splitter.
5
6  Part of the Routino routing software.
7  ******************/ /******************
8  This file Copyright 2008-2010 Andrew M. Bishop
9
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU Affero General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU Affero General Public License for more details.
19
20  You should have received a copy of the GNU Affero General Public License
21  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  ***************************************/
23
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29
30 #include "typesx.h"
31 #include "types.h"
32 #include "functionsx.h"
33 #include "functions.h"
34 #include "nodesx.h"
35 #include "segmentsx.h"
36 #include "waysx.h"
37 #include "superx.h"
38 #include "ways.h"
39 #include "tagging.h"
40
41
42 /* Global variables */
43
44 /*+ The option to use a slim mode with file-backed read-only intermediate storage. +*/
45 int option_slim=0;
46
47 /*+ The name of the temporary directory. +*/
48 char *option_tmpdirname=NULL;
49
50 /*+ The amount of RAM to use for filesorting. +*/
51 size_t option_filesort_ramsize=0;
52
53
54 /* Local functions */
55
56 static void print_usage(int detail);
57
58
59 /*++++++++++++++++++++++++++++++++++++++
60   The main program for the planetsplitter.
61   ++++++++++++++++++++++++++++++++++++++*/
62
63 int main(int argc,char** argv)
64 {
65  NodesX    *Nodes;
66  SegmentsX *Segments,*SuperSegments=NULL,*MergedSegments=NULL;
67  WaysX     *Ways;
68  int        iteration=0,quit=0;
69  int        max_iterations=10;
70  char      *dirname=NULL,*prefix=NULL,*tagging=NULL;
71  int        option_parse_only=0,option_process_only=0;
72  int        option_filenames=0;
73  int        arg;
74
75  /* Parse the command line arguments */
76
77  for(arg=1;arg<argc;arg++)
78    {
79     if(!strcmp(argv[arg],"--help"))
80        print_usage(1);
81     else if(!strcmp(argv[arg],"--slim"))
82        option_slim=1;
83     else if(!strncmp(argv[arg],"--sort-ram-size=",16))
84        option_filesort_ramsize=atoi(&argv[arg][16]);
85     else if(!strncmp(argv[arg],"--dir=",6))
86        dirname=&argv[arg][6];
87     else if(!strncmp(argv[arg],"--tmpdir=",9))
88        option_tmpdirname=&argv[arg][9];
89     else if(!strncmp(argv[arg],"--prefix=",9))
90        prefix=&argv[arg][9];
91     else if(!strcmp(argv[arg],"--parse-only"))
92        option_parse_only=1;
93     else if(!strcmp(argv[arg],"--process-only"))
94        option_process_only=1;
95     else if(!strncmp(argv[arg],"--max-iterations=",17))
96        max_iterations=atoi(&argv[arg][17]);
97     else if(!strncmp(argv[arg],"--tagging=",10))
98        tagging=&argv[arg][10];
99     else if(argv[arg][0]=='-' && argv[arg][1]=='-')
100        print_usage(0);
101     else
102        option_filenames++;
103    }
104
105  /* Check the specified command line options */
106
107  if(option_parse_only && option_process_only)
108     print_usage(0);
109
110  if(option_filenames && option_process_only)
111     print_usage(0);
112
113  if(!option_filesort_ramsize)
114    {
115     if(option_slim)
116        option_filesort_ramsize=64*1024*1024;
117     else
118        option_filesort_ramsize=256*1024*1024;
119    }
120  else
121     option_filesort_ramsize*=1024*1024;
122
123  if(!option_tmpdirname)
124    {
125     if(!dirname)
126        option_tmpdirname=".";
127     else
128        option_tmpdirname=dirname;
129    }
130
131  if(tagging && ExistsFile(tagging))
132     ;
133  else if(!tagging && ExistsFile(FileName(dirname,prefix,"tagging.xml")))
134     tagging=FileName(dirname,prefix,"tagging.xml");
135
136  if(tagging && ParseXMLTaggingRules(tagging))
137    {
138     fprintf(stderr,"Error: Cannot read the tagging rules in the file '%s'.\n",tagging);
139     return(1);
140    }
141
142  if(!tagging)
143    {
144     fprintf(stderr,"Error: Cannot run without reading some tagging rules.\n");
145     return(1);
146    }
147
148  /* Create new node, segment and way variables */
149
150  Nodes=NewNodeList(option_parse_only||option_process_only);
151
152  Segments=NewSegmentList(option_parse_only||option_process_only);
153
154  Ways=NewWayList(option_parse_only||option_process_only);
155
156  /* Parse the file */
157
158  if(option_filenames)
159    {
160     for(arg=1;arg<argc;arg++)
161       {
162        FILE *file;
163
164        if(argv[arg][0]=='-' && argv[arg][1]=='-')
165           continue;
166
167        file=fopen(argv[arg],"rb");
168
169        if(!file)
170          {
171           fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",argv[arg],strerror(errno));
172           exit(EXIT_FAILURE);
173          }
174
175        printf("\nParse OSM Data [%s]\n==============\n\n",argv[arg]);
176        fflush(stdout);
177
178        if(ParseOSM(file,Nodes,Segments,Ways))
179           exit(EXIT_FAILURE);
180
181        fclose(file);
182       }
183    }
184  else if(!option_process_only)
185    {
186     printf("\nParse OSM Data\n==============\n\n");
187     fflush(stdout);
188
189     if(ParseOSM(stdin,Nodes,Segments,Ways))
190        exit(EXIT_FAILURE);
191    }
192
193  if(option_parse_only)
194    {
195     FreeNodeList(Nodes,1);
196     FreeSegmentList(Segments,1);
197     FreeWayList(Ways,1);
198
199     return(0);
200    }
201
202  /* Process the data */
203
204  printf("\nProcess OSM Data\n================\n\n");
205  fflush(stdout);
206
207  /* Sort the nodes, segments and ways */
208
209  SortNodeList(Nodes);
210
211  SortSegmentList(Segments);
212
213  SortWayList(Ways);
214
215  /* Remove bad segments (must be after sorting the nodes and segments) */
216
217  RemoveBadSegments(Nodes,Segments);
218
219  /* Remove non-highway nodes (must be after removing the bad segments) */
220
221  RemoveNonHighwayNodes(Nodes,Segments);
222
223  /* Measure the segments and replace node/way id with index (must be after removing non-highway nodes) */
224
225  UpdateSegments(Segments,Nodes,Ways);
226
227
228  /* Repeated iteration on Super-Nodes and Super-Segments */
229
230  do
231    {
232     printf("\nProcess Super-Data (iteration %d)\n================================%s\n\n",iteration,iteration>9?"=":"");
233     fflush(stdout);
234
235     if(iteration==0)
236       {
237        /* Select the super-nodes */
238
239        ChooseSuperNodes(Nodes,Segments,Ways);
240
241        /* Select the super-segments */
242
243        SuperSegments=CreateSuperSegments(Nodes,Segments,Ways,iteration);
244       }
245     else
246       {
247        SegmentsX *SuperSegments2;
248
249        /* Select the super-nodes */
250
251        ChooseSuperNodes(Nodes,SuperSegments,Ways);
252
253        /* Select the super-segments */
254
255        SuperSegments2=CreateSuperSegments(Nodes,SuperSegments,Ways,iteration);
256
257        if(SuperSegments->xnumber==SuperSegments2->xnumber)
258           quit=1;
259
260        FreeSegmentList(SuperSegments,0);
261
262        SuperSegments=SuperSegments2;
263       }
264
265     /* Sort the super-segments */
266
267     SortSegmentList(SuperSegments);
268
269     /* Remove duplicated super-segments */
270
271     DeduplicateSegments(SuperSegments,Nodes,Ways);
272
273     iteration++;
274
275     if(iteration>max_iterations)
276        quit=1;
277    }
278  while(!quit);
279
280  /* Combine the super-segments */
281
282  printf("\nCombine Segments and Super-Segments\n===================================\n\n");
283  fflush(stdout);
284
285  /* Merge the super-segments */
286
287  MergedSegments=MergeSuperSegments(Segments,SuperSegments);
288
289  FreeSegmentList(Segments,0);
290
291  FreeSegmentList(SuperSegments,0);
292
293  Segments=MergedSegments;
294
295  /* Rotate segments so that node1<node2 */
296
297  RotateSegments(Segments);
298
299  /* Sort the segments */
300
301  SortSegmentList(Segments);
302
303  /* Remove duplicated segments */
304
305  DeduplicateSegments(Segments,Nodes,Ways);
306
307  /* Cross reference the nodes and segments */
308
309  printf("\nCross-Reference Nodes and Segments\n==================================\n\n");
310  fflush(stdout);
311
312  /* Sort the node list geographically */
313
314  SortNodeListGeographically(Nodes);
315
316  /* Create the real segments and nodes */
317
318  CreateRealNodes(Nodes,iteration);
319
320  CreateRealSegments(Segments,Ways);
321
322  /* Fix the segment and node indexes */
323
324  IndexNodes(Nodes,Segments);
325
326  IndexSegments(Segments,Nodes);
327
328  /* Output the results */
329
330  printf("\nWrite Out Database Files\n========================\n\n");
331  fflush(stdout);
332
333  /* Write out the nodes */
334
335  SaveNodeList(Nodes,FileName(dirname,prefix,"nodes.mem"));
336
337  FreeNodeList(Nodes,0);
338
339  /* Write out the segments */
340
341  SaveSegmentList(Segments,FileName(dirname,prefix,"segments.mem"));
342
343  FreeSegmentList(Segments,0);
344
345  /* Write out the ways */
346
347  SaveWayList(Ways,FileName(dirname,prefix,"ways.mem"));
348
349  FreeWayList(Ways,0);
350
351  return(0);
352 }
353
354
355 /*++++++++++++++++++++++++++++++++++++++
356   Print out the usage information.
357
358   int detail The level of detail to use - 0 = low, 1 = high.
359   ++++++++++++++++++++++++++++++++++++++*/
360
361 static void print_usage(int detail)
362 {
363  fprintf(stderr,
364          "Usage: planetsplitter [--help]\n"
365          "                      [--dir=<dirname>] [--prefix=<name>]\n"
366          "                      [--slim] [--sort-ram-size=<size>]\n"
367          "                      [--tmpdir=<dirname>]\n"
368          "                      [--parse-only | --process-only]\n"
369          "                      [--max-iterations=<number>]\n"
370          "                      [--tagging=<filename>]\n"
371          "                      [<filename.osm> ...]\n");
372
373  if(detail)
374     fprintf(stderr,
375             "\n"
376             "--help                    Prints this information.\n"
377             "\n"
378             "--dir=<dirname>           The directory containing the routing database.\n"
379             "--prefix=<name>           The filename prefix for the routing database.\n"
380             "\n"
381             "--slim                    Use less RAM and more temporary files.\n"
382             "--sort-ram-size=<size>    The amount of RAM (in MB) to use for data sorting\n"
383             "                          (defaults to 64MB with '--slim' or 256MB otherwise.)\n"
384             "--tmpdir=<dirname>        The directory name for temporary files.\n"
385             "                          (defaults to the '--dir' option directory.)\n"
386             "\n"
387             "--parse-only              Parse the input OSM files and store the results.\n"
388             "--process-only            Process the stored results from previous option.\n"
389             "\n"
390             "--max-iterations=<number> The number of iterations for finding super-nodes.\n"
391             "\n"
392             "--tagging=<filename>      The name of the XML file containing the tagging rules\n"
393             "                          (defaults to 'tagging.xml' with '--dirname' and\n"
394             "                           '--prefix' options).\n"
395             "\n"
396             "<filename.osm> ...        The name(s) of the file(s) to process (by default\n"
397             "                          data is read from standard input).\n"
398             "\n"
399             "<transport> defaults to all but can be set to:\n"
400             "%s"
401             "\n"
402             "<highway> can be selected from:\n"
403             "%s"
404             "\n"
405             "<property> can be selected from:\n"
406             "%s",
407             TransportList(),HighwayList(),PropertyList());
408
409  exit(!detail);
410 }