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/osmparser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 228 - (show annotations) (download) (as text)
Sun Jul 12 09:01:48 2009 UTC (15 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 18770 byte(s)
Tidy up and fix comments and include files.

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/osmparser.c,v 1.46 2009-07-12 09:01:48 amb Exp $
3
4 OSM XML file parser (either JOSM or planet)
5
6 Part of the Routino routing software.
7 ******************/ /******************
8 This file Copyright 2008,2009 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 <ctype.h>
29
30 #include "typesx.h"
31 #include "functionsx.h"
32 #include "nodesx.h"
33 #include "segmentsx.h"
34 #include "waysx.h"
35 #include "ways.h"
36
37
38 /*+ The length of the buffer and the size increment for reading lines from the file. +*/
39 #define BUFFSIZE 64
40
41 /* Local functions */
42
43 static char *fgets_realloc(char *buffer,FILE *file);
44
45
46 /*++++++++++++++++++++++++++++++++++++++
47 Parse an OSM XML file (from JOSM or planet download).
48
49 int ParseXML Returns 0 if OK or something else in case of an error.
50
51 FILE *file The file to read from.
52
53 NodesX *OSMNodes The array of nodes to fill in.
54
55 SegmentsX *OSMSegments The array of segments to fill in.
56
57 WaysX *OSMWays The arrray of ways to fill in.
58
59 Profile *profile A profile of the allowed transport types and included/excluded highway types.
60 ++++++++++++++++++++++++++++++++++++++*/
61
62 int ParseXML(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,Profile *profile)
63 {
64 char *line=NULL;
65 long nlines=0;
66 long nnodes=0,nways=0,nrelations=0;
67 int isnode=0,isway=0,isrelation=0;
68 way_t way_id=0;
69 int way_oneway=0,way_roundabout=0;
70 speed_t way_maxspeed=0;
71 weight_t way_maxweight=0;
72 height_t way_maxheight=0;
73 width_t way_maxwidth=0;
74 length_t way_maxlength=0;
75 char *way_highway=NULL,*way_name=NULL,*way_ref=NULL;
76 wayallow_t way_allow_no=0,way_allow_yes=0;
77 node_t *way_nodes=NULL;
78 int way_nnodes=0,way_nalloc=0;
79
80 printf("\rReading: Lines=0 Nodes=0 Ways=0 Relations=0");
81 fflush(stdout);
82
83 /* Parse the file */
84
85 while((line=fgets_realloc(line,file)))
86 {
87 char *l=line,*m;
88
89 nlines++;
90
91 while(isspace(*l))
92 l++;
93
94 if(!strncmp(l,"<node",5)) /* The start of a node */
95 {
96 node_t id;
97 double latitude,longitude;
98
99 nnodes++;
100
101 isnode=1; isway=0; isrelation=0;
102
103 m=strstr(l,"id="); m+=4; if(*m=='"' || *m=='\'') m++; id=atoll(m);
104 m=strstr(l,"lat="); m+=5; if(*m=='"' || *m=='\'') m++; latitude=degrees_to_radians(atof(m));
105 m=strstr(l,"lon="); m+=4; if(*m=='"' || *m=='\'') m++; longitude=degrees_to_radians(atof(m));
106
107 AppendNode(OSMNodes,id,latitude,longitude);
108
109 if(strstr(l,"/>")) /* The end of a node */
110 {
111 isnode=0; isway=0; isrelation=0;
112 }
113 }
114 else if(!strncmp(l,"</node",6)) /* The end of a node */
115 {
116 isnode=0; isway=0; isrelation=0;
117 }
118 else if(!strncmp(l,"<way",4)) /* The start of a way */
119 {
120 nways++;
121
122 isnode=0; isway=1; isrelation=0;
123
124 m=strstr(l,"id="); m+=4; if(*m=='"' || *m=='\'') m++; way_id=atoll(m);
125
126 way_oneway=0; way_roundabout=0;
127 way_maxspeed=0; way_maxweight=0; way_maxheight=0; way_maxwidth=0;
128 way_maxlength=0;
129 way_highway=NULL; way_name=NULL; way_ref=NULL;
130 way_allow_no=0; way_allow_yes=0;
131 way_nnodes=0;
132 }
133 else if(!strncmp(l,"</way",5)) /* The end of a way */
134 {
135 isnode=0; isway=0; isrelation=0;
136
137 if(way_highway)
138 {
139 waytype_t type;
140 wayallow_t allow;
141
142 type=HighwayType(way_highway);
143
144 switch(type)
145 {
146 case Way_Motorway:
147 allow=Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
148 break;
149 case Way_Trunk:
150 allow=Allow_Bicycle|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
151 break;
152 case Way_Primary:
153 allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
154 break;
155 case Way_Secondary:
156 allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
157 break;
158 case Way_Tertiary:
159 allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
160 break;
161 case Way_Unclassified:
162 allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
163 break;
164 case Way_Residential:
165 allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
166 break;
167 case Way_Service:
168 allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
169 break;
170 case Way_Track:
171 allow=Allow_Foot|Allow_Bicycle|Allow_Horse;
172 break;
173 case Way_Path:
174 allow=Allow_Foot; /* Only allow bicycle and horse if so indicated. */
175 break;
176 case Way_Bridleway:
177 allow=Allow_Foot|Allow_Bicycle|Allow_Horse;
178 break;
179 case Way_Cycleway:
180 allow=Allow_Foot|Allow_Bicycle;
181 break;
182 case Way_Footway:
183 allow=Allow_Foot;
184 break;
185 default:
186 allow=0;
187 break;
188 }
189
190 if(way_allow_no) /* Remove the ones explicitly denied (e.g. private) */
191 allow&=~way_allow_no;
192
193 if(way_allow_yes) /* Add the ones explicitly allowed (e.g. footpath along private) */
194 allow|=way_allow_yes;
195
196 if(allow&profile->allow && profile->highway[HIGHWAY(type)])
197 {
198 Way *way;
199 char *refname;
200 int i;
201
202 if(way_ref && way_name)
203 {
204 refname=(char*)malloc(strlen(way_ref)+strlen(way_name)+4);
205 sprintf(refname,"%s (%s)",way_name,way_ref);
206 }
207 else if(way_ref && !way_name && way_roundabout)
208 {
209 refname=(char*)malloc(strlen(way_ref)+14);
210 sprintf(refname,"%s (roundabout)",way_ref);
211 }
212 else if(way_ref && !way_name)
213 refname=way_ref;
214 else if(!way_ref && way_name)
215 refname=way_name;
216 else if(way_roundabout)
217 {
218 refname=(char*)malloc(strlen(way_highway)+14);
219 sprintf(refname,"%s (roundabout)",way_highway);
220 }
221 else /* if(!way_ref && !way_name && !way_roundabout) */
222 refname=way_highway;
223
224 way=AppendWay(OSMWays,way_id,refname);
225
226 way->speed=way_maxspeed;
227 way->weight=way_maxweight;
228 way->height=way_maxheight;
229 way->width=way_maxwidth;
230 way->length=way_maxlength;
231
232 way->type=type;
233
234 way->allow=allow;
235
236 if(way_oneway)
237 way->type|=Way_OneWay;
238
239 if(way_roundabout)
240 way->type|=Way_Roundabout;
241
242 if(refname!=way_ref && refname!=way_name && refname!=way_highway)
243 free(refname);
244
245 for(i=1;i<way_nnodes;i++)
246 {
247 node_t from=way_nodes[i-1];
248 node_t to =way_nodes[i];
249
250 if(way_oneway>0)
251 {
252 AppendSegment(OSMSegments,way_id,from,to,ONEWAY_1TO2);
253 AppendSegment(OSMSegments,way_id,to,from,ONEWAY_2TO1);
254 }
255 else if(way_oneway<0)
256 {
257 AppendSegment(OSMSegments,way_id,from,to,ONEWAY_2TO1);
258 AppendSegment(OSMSegments,way_id,to,from,ONEWAY_1TO2);
259 }
260 else
261 {
262 AppendSegment(OSMSegments,way_id,from,to,0);
263 AppendSegment(OSMSegments,way_id,to,from,0);
264 }
265 }
266 }
267 }
268
269 if(way_highway) free(way_highway);
270 if(way_name) free(way_name);
271 if(way_ref) free(way_ref);
272 }
273 else if(!strncmp(l,"<relation",9)) /* The start of a relation */
274 {
275 nrelations++;
276
277 isnode=0; isway=0; isrelation=1;
278 }
279 else if(!strncmp(l,"</relation",10)) /* The end of a relation */
280 {
281 isnode=0; isway=0; isrelation=0;
282 }
283 else if(isnode) /* The middle of a node */
284 {
285 }
286 else if(isway) /* The middle of a way */
287 {
288 node_t id;
289
290 if(!strncmp(l,"<nd",3)) /* The start of a node specifier */
291 {
292 m=strstr(l,"ref="); m+=4; if(*m=='"' || *m=='\'') m++; id=atoll(m);
293
294 if(way_nnodes<=way_nalloc)
295 way_nodes=(node_t*)realloc((void*)way_nodes,(way_nalloc+=16)*sizeof(node_t));
296
297 way_nodes[way_nnodes++]=id;
298 }
299
300 if(!strncmp(l,"<tag",4)) /* The start of a tag specifier */
301 {
302 char delimiter,*k="",*v="";
303
304 m=strstr(l,"k="); m+=2; delimiter=*m; m++; k=m;
305 while(*m!=delimiter) m++; *m=0; l=m+1;
306
307 m=strstr(l,"v="); m+=2; delimiter=*m; m++; v=m;
308 while(*m!=delimiter) m++; *m=0;
309
310 switch(*k)
311 {
312 case 'a':
313 if(!strcmp(k,"access"))
314 {
315 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
316 ;
317 else
318 way_allow_no=~0;
319 }
320 break;
321
322 case 'b':
323 if(!strcmp(k,"bicycle"))
324 {
325 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
326 way_allow_yes|=Allow_Bicycle;
327 else
328 way_allow_no|=Allow_Bicycle;
329 }
330 break;
331
332 case 'f':
333 if(!strcmp(k,"foot"))
334 {
335 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
336 way_allow_yes|=Allow_Foot;
337 else
338 way_allow_no|=Allow_Foot;
339 }
340 break;
341
342 case 'g':
343 if(!strcmp(k,"goods"))
344 {
345 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
346 way_allow_yes|=Allow_Goods;
347 else
348 way_allow_no|=Allow_Goods;
349 }
350 break;
351
352 case 'h':
353 if(!strcmp(k,"highway"))
354 {
355 if(!strncmp(v,"motorway",8)) way_oneway=1;
356
357 way_highway=strcpy((char*)malloc(strlen(v)+1),v);
358 }
359 if(!strcmp(k,"horse"))
360 {
361 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
362 way_allow_yes|=Allow_Horse;
363 else
364 way_allow_no|=Allow_Horse;
365 }
366 if(!strcmp(k,"hgv"))
367 {
368 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
369 way_allow_yes|=Allow_HGV;
370 else
371 way_allow_no|=Allow_HGV;
372 }
373 break;
374
375 case 'j':
376 if(!strcmp(k,"junction"))
377 if(!strcmp(v,"roundabout"))
378 {way_oneway=1; way_roundabout=1;}
379 break;
380
381 case 'm':
382 if(!strcmp(k,"maxspeed"))
383 {
384 if(strstr(v,"mph"))
385 way_maxspeed=kph_to_speed(1.609*atof(v));
386 else
387 way_maxspeed=kph_to_speed(atof(v));
388 }
389 if(!strcmp(k,"maxspeed:mph"))
390 way_maxspeed=kph_to_speed(1.609*atof(v));
391 if(!strcmp(k,"maxweight"))
392 {
393 if(strstr(v,"kg"))
394 way_maxweight=tonnes_to_weight(atof(v)/1000);
395 else
396 way_maxweight=tonnes_to_weight(atof(v));
397 }
398 if(!strcmp(k,"maxheight"))
399 {
400 if(strchr(v,'\''))
401 {
402 int feet,inches;
403
404 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
405 way_maxheight=metres_to_height((feet+(double)inches/12.0)*0.254);
406 else if(sscanf(v,"%d'",&feet)==1)
407 way_maxheight=metres_to_height((feet+(double)inches/12.0)*0.254);
408 }
409 else if(strstr(v,"ft") || strstr(v,"feet"))
410 way_maxheight=metres_to_height(atof(v)*0.254);
411 else
412 way_maxheight=metres_to_height(atof(v));
413 }
414 if(!strcmp(k,"maxwidth"))
415 {
416 if(strchr(v,'\''))
417 {
418 int feet,inches;
419
420 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
421 way_maxwidth=metres_to_height((feet+(double)inches/12.0)*0.254);
422 else if(sscanf(v,"%d'",&feet)==1)
423 way_maxwidth=metres_to_height((feet+(double)inches/12.0)*0.254);
424 }
425 else if(strstr(v,"ft") || strstr(v,"feet"))
426 way_maxwidth=metres_to_width(atof(v)*0.254);
427 else
428 way_maxwidth=metres_to_width(atof(v));
429 }
430 if(!strcmp(k,"maxlength"))
431 {
432 if(strchr(v,'\''))
433 {
434 int feet,inches;
435
436 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
437 way_maxlength=metres_to_height((feet+(double)inches/12.0)*0.254);
438 else if(sscanf(v,"%d'",&feet)==1)
439 way_maxlength=metres_to_height((feet+(double)inches/12.0)*0.254);
440 }
441 else if(strstr(v,"ft") || strstr(v,"feet"))
442 way_maxlength=metres_to_length(atof(v)*0.254);
443 else
444 way_maxlength=metres_to_length(atof(v));
445 }
446 if(!strcmp(k,"motorbike"))
447 {
448 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
449 way_allow_yes|=Allow_Motorbike;
450 else
451 way_allow_no|=Allow_Motorbike;
452 }
453 if(!strcmp(k,"motorcar"))
454 {
455 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
456 way_allow_yes|=Allow_Motorcar;
457 else
458 way_allow_no|=Allow_Motorcar;
459 }
460 if(!strcmp(k,"motor_vehicle"))
461 {
462 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
463 way_allow_yes|=Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
464 else
465 way_allow_no|=Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
466 }
467 break;
468
469 case 'n':
470 if(!strcmp(k,"name"))
471 way_name=strcpy((char*)malloc(strlen(v)+1),v);
472 break;
473
474 case 'o':
475 if(!strcmp(k,"oneway"))
476 {
477 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1"))
478 way_oneway=1;
479 else if(!strcmp(v,"-1"))
480 way_oneway=-1;
481 }
482 break;
483
484 case 'p':
485 if(!strcmp(k,"psv"))
486 {
487 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
488 way_allow_yes|=Allow_PSV;
489 else
490 way_allow_no|=Allow_PSV;
491 }
492 break;
493
494 case 'r':
495 if(!strcmp(k,"ref"))
496 way_ref=strcpy((char*)malloc(strlen(v)+1),v);
497 break;
498
499 case 'v':
500 if(!strcmp(k,"vehicle"))
501 {
502 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
503 way_allow_yes|=Allow_Bicycle|Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
504 else
505 way_allow_no|=Allow_Bicycle|Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
506 }
507 break;
508
509 default:
510 ;
511 }
512 }
513 }
514 else if(isrelation) /* The middle of a relation */
515 {
516 }
517
518 if(!(nlines%10000))
519 {
520 printf("\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",nlines,nnodes,nways,nrelations);
521 fflush(stdout);
522 }
523 }
524
525 printf("\rRead: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld \n",nlines,nnodes,nways,nrelations);
526 fflush(stdout);
527
528 if(line)
529 free(line);
530
531 if(way_nalloc)
532 free(way_nodes);
533
534 return(0);
535 }
536
537
538 /*++++++++++++++++++++++++++++++++++++++
539 Call fgets and realloc the buffer as needed to get a whole line.
540
541 char *fgets_realloc Returns the modified buffer (NULL at the end of the file).
542
543 char *buffer The current buffer.
544
545 FILE *file The file to read from.
546 ++++++++++++++++++++++++++++++++++++++*/
547
548 static char *fgets_realloc(char *buffer,FILE *file)
549 {
550 int n=0;
551 char *buf;
552
553 if(!buffer)
554 buffer=(char*)malloc(BUFFSIZE+1);
555
556 while((buf=fgets(&buffer[n],BUFFSIZE,file)))
557 {
558 int s=strlen(buf);
559 n+=s;
560
561 if(buffer[n-1]=='\n')
562 break;
563 else
564 buffer=(char*)realloc(buffer,n+BUFFSIZE+1);
565 }
566
567 if(!buf)
568 {free(buffer);buffer=NULL;}
569
570 return(buffer);
571 }

Properties

Name Value
cvs:description OSM XML file parser.