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 293 - (show annotations) (download) (as text)
Mon Oct 26 19:04:40 2009 UTC (15 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 18747 byte(s)
Remove the Bridleway and Footway highway types and use the Path type instead
(also re-ordered the types so that Cycleway comes before Path).

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/osmparser.c,v 1.52 2009-10-26 19:04:40 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 256
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_Cycleway:
174 allow=Allow_Foot|Allow_Bicycle;
175 break;
176 case Way_Path:
177 if(!strcmp(way_highway,"bridleway"))
178 allow=Allow_Foot|Allow_Bicycle|Allow_Horse; /* Special case for UK "bridleway". */
179 else
180 allow=Allow_Foot; /* Only allow bicycle and horse if so indicated. */
181 break;
182 default:
183 allow=0;
184 break;
185 }
186
187 if(way_allow_no) /* Remove the ones explicitly denied (e.g. private) */
188 allow&=~way_allow_no;
189
190 if(way_allow_yes) /* Add the ones explicitly allowed (e.g. footpath along private) */
191 allow|=way_allow_yes;
192
193 if(allow&profile->allow && profile->highway[HIGHWAY(type)])
194 {
195 Way way={0};
196 char *refname;
197 int i;
198
199 if(way_ref && way_name)
200 {
201 refname=(char*)malloc(strlen(way_ref)+strlen(way_name)+4);
202 sprintf(refname,"%s (%s)",way_name,way_ref);
203 }
204 else if(way_ref && !way_name && way_roundabout)
205 {
206 refname=(char*)malloc(strlen(way_ref)+14);
207 sprintf(refname,"%s (roundabout)",way_ref);
208 }
209 else if(way_ref && !way_name)
210 refname=way_ref;
211 else if(!way_ref && way_name)
212 refname=way_name;
213 else if(way_roundabout)
214 {
215 refname=(char*)malloc(strlen(way_highway)+14);
216 sprintf(refname,"%s (roundabout)",way_highway);
217 }
218 else /* if(!way_ref && !way_name && !way_roundabout) */
219 refname=way_highway;
220
221 way.speed=way_maxspeed;
222 way.weight=way_maxweight;
223 way.height=way_maxheight;
224 way.width=way_maxwidth;
225 way.length=way_maxlength;
226
227 way.type=type;
228
229 way.allow=allow;
230
231 if(way_oneway)
232 way.type|=Way_OneWay;
233
234 if(way_roundabout)
235 way.type|=Way_Roundabout;
236
237 AppendWay(OSMWays,way_id,&way,refname);
238
239 if(refname!=way_ref && refname!=way_name && refname!=way_highway)
240 free(refname);
241
242 for(i=1;i<way_nnodes;i++)
243 {
244 node_t from=way_nodes[i-1];
245 node_t to =way_nodes[i];
246
247 if(way_oneway>0)
248 {
249 AppendSegment(OSMSegments,way_id,from,to,ONEWAY_1TO2);
250 AppendSegment(OSMSegments,way_id,to,from,ONEWAY_2TO1);
251 }
252 else if(way_oneway<0)
253 {
254 AppendSegment(OSMSegments,way_id,from,to,ONEWAY_2TO1);
255 AppendSegment(OSMSegments,way_id,to,from,ONEWAY_1TO2);
256 }
257 else
258 {
259 AppendSegment(OSMSegments,way_id,from,to,0);
260 AppendSegment(OSMSegments,way_id,to,from,0);
261 }
262 }
263 }
264 }
265
266 if(way_highway) free(way_highway);
267 if(way_name) free(way_name);
268 if(way_ref) free(way_ref);
269 }
270 else if(!strncmp(l,"<relation",9)) /* The start of a relation */
271 {
272 nrelations++;
273
274 isnode=0; isway=0; isrelation=1;
275 }
276 else if(!strncmp(l,"</relation",10)) /* The end of a relation */
277 {
278 isnode=0; isway=0; isrelation=0;
279 }
280 else if(isnode) /* The middle of a node */
281 {
282 }
283 else if(isway) /* The middle of a way */
284 {
285 node_t id;
286
287 if(!strncmp(l,"<nd",3)) /* The start of a node specifier */
288 {
289 m=strstr(l,"ref="); m+=4; if(*m=='"' || *m=='\'') m++; id=atoll(m);
290
291 if(way_nnodes==way_nalloc)
292 way_nodes=(node_t*)realloc((void*)way_nodes,(way_nalloc+=256)*sizeof(node_t));
293
294 way_nodes[way_nnodes++]=id;
295 }
296
297 if(!strncmp(l,"<tag",4)) /* The start of a tag specifier */
298 {
299 char delimiter,*k="",*v="";
300
301 m=strstr(l,"k="); m+=2; delimiter=*m; m++; k=m;
302 while(*m!=delimiter) m++; *m=0; l=m+1;
303
304 m=strstr(l,"v="); m+=2; delimiter=*m; m++; v=m;
305 while(*m!=delimiter) m++; *m=0;
306
307 switch(*k)
308 {
309 case 'a':
310 if(!strcmp(k,"access"))
311 {
312 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
313 ;
314 else
315 way_allow_no=~0;
316 }
317 break;
318
319 case 'b':
320 if(!strcmp(k,"bicycle"))
321 {
322 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
323 way_allow_yes|=Allow_Bicycle;
324 else
325 way_allow_no|=Allow_Bicycle;
326 }
327 break;
328
329 case 'f':
330 if(!strcmp(k,"foot"))
331 {
332 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
333 way_allow_yes|=Allow_Foot;
334 else
335 way_allow_no|=Allow_Foot;
336 }
337 break;
338
339 case 'g':
340 if(!strcmp(k,"goods"))
341 {
342 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
343 way_allow_yes|=Allow_Goods;
344 else
345 way_allow_no|=Allow_Goods;
346 }
347 break;
348
349 case 'h':
350 if(!strcmp(k,"highway"))
351 {
352 if(!strncmp(v,"motorway",8)) way_oneway=1;
353
354 way_highway=strcpy((char*)malloc(strlen(v)+1),v);
355 }
356 if(!strcmp(k,"horse"))
357 {
358 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
359 way_allow_yes|=Allow_Horse;
360 else
361 way_allow_no|=Allow_Horse;
362 }
363 if(!strcmp(k,"hgv"))
364 {
365 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
366 way_allow_yes|=Allow_HGV;
367 else
368 way_allow_no|=Allow_HGV;
369 }
370 break;
371
372 case 'j':
373 if(!strcmp(k,"junction"))
374 if(!strcmp(v,"roundabout"))
375 {way_oneway=1; way_roundabout=1;}
376 break;
377
378 case 'm':
379 if(!strcmp(k,"maxspeed"))
380 {
381 if(strstr(v,"mph"))
382 way_maxspeed=kph_to_speed(1.609*atof(v));
383 else
384 way_maxspeed=kph_to_speed(atof(v));
385 }
386 if(!strcmp(k,"maxspeed:mph"))
387 way_maxspeed=kph_to_speed(1.609*atof(v));
388 if(!strcmp(k,"maxweight"))
389 {
390 if(strstr(v,"kg"))
391 way_maxweight=tonnes_to_weight(atof(v)/1000);
392 else
393 way_maxweight=tonnes_to_weight(atof(v));
394 }
395 if(!strcmp(k,"maxheight"))
396 {
397 if(strchr(v,'\''))
398 {
399 int feet,inches;
400
401 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
402 way_maxheight=metres_to_height((feet+(double)inches/12.0)*0.254);
403 else if(sscanf(v,"%d'",&feet)==1)
404 way_maxheight=metres_to_height((feet+(double)inches/12.0)*0.254);
405 }
406 else if(strstr(v,"ft") || strstr(v,"feet"))
407 way_maxheight=metres_to_height(atof(v)*0.254);
408 else
409 way_maxheight=metres_to_height(atof(v));
410 }
411 if(!strcmp(k,"maxwidth"))
412 {
413 if(strchr(v,'\''))
414 {
415 int feet,inches;
416
417 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
418 way_maxwidth=metres_to_height((feet+(double)inches/12.0)*0.254);
419 else if(sscanf(v,"%d'",&feet)==1)
420 way_maxwidth=metres_to_height((feet+(double)inches/12.0)*0.254);
421 }
422 else if(strstr(v,"ft") || strstr(v,"feet"))
423 way_maxwidth=metres_to_width(atof(v)*0.254);
424 else
425 way_maxwidth=metres_to_width(atof(v));
426 }
427 if(!strcmp(k,"maxlength"))
428 {
429 if(strchr(v,'\''))
430 {
431 int feet,inches;
432
433 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
434 way_maxlength=metres_to_height((feet+(double)inches/12.0)*0.254);
435 else if(sscanf(v,"%d'",&feet)==1)
436 way_maxlength=metres_to_height((feet+(double)inches/12.0)*0.254);
437 }
438 else if(strstr(v,"ft") || strstr(v,"feet"))
439 way_maxlength=metres_to_length(atof(v)*0.254);
440 else
441 way_maxlength=metres_to_length(atof(v));
442 }
443 if(!strcmp(k,"motorbike"))
444 {
445 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
446 way_allow_yes|=Allow_Motorbike;
447 else
448 way_allow_no|=Allow_Motorbike;
449 }
450 if(!strcmp(k,"motorcar"))
451 {
452 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
453 way_allow_yes|=Allow_Motorcar;
454 else
455 way_allow_no|=Allow_Motorcar;
456 }
457 if(!strcmp(k,"motor_vehicle"))
458 {
459 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
460 way_allow_yes|=Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
461 else
462 way_allow_no|=Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
463 }
464 break;
465
466 case 'n':
467 if(!strcmp(k,"name"))
468 way_name=strcpy((char*)malloc(strlen(v)+1),v);
469 break;
470
471 case 'o':
472 if(!strcmp(k,"oneway"))
473 {
474 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1"))
475 way_oneway=1;
476 else if(!strcmp(v,"-1"))
477 way_oneway=-1;
478 }
479 break;
480
481 case 'p':
482 if(!strcmp(k,"psv"))
483 {
484 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
485 way_allow_yes|=Allow_PSV;
486 else
487 way_allow_no|=Allow_PSV;
488 }
489 break;
490
491 case 'r':
492 if(!strcmp(k,"ref"))
493 way_ref=strcpy((char*)malloc(strlen(v)+1),v);
494 break;
495
496 case 'v':
497 if(!strcmp(k,"vehicle"))
498 {
499 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
500 way_allow_yes|=Allow_Bicycle|Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
501 else
502 way_allow_no|=Allow_Bicycle|Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
503 }
504 break;
505
506 default:
507 ;
508 }
509 }
510 }
511 else if(isrelation) /* The middle of a relation */
512 {
513 }
514
515 if(!(nlines%10000))
516 {
517 printf("\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",nlines,nnodes,nways,nrelations);
518 fflush(stdout);
519 }
520 }
521
522 printf("\rRead: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld \n",nlines,nnodes,nways,nrelations);
523 fflush(stdout);
524
525 if(line)
526 free(line);
527
528 if(way_nalloc)
529 free(way_nodes);
530
531 return(0);
532 }
533
534
535 /*++++++++++++++++++++++++++++++++++++++
536 Call fgets and realloc the buffer as needed to get a whole line.
537
538 char *fgets_realloc Returns the modified buffer (NULL at the end of the file).
539
540 char *buffer The current buffer.
541
542 FILE *file The file to read from.
543 ++++++++++++++++++++++++++++++++++++++*/
544
545 static char *fgets_realloc(char *buffer,FILE *file)
546 {
547 int n=0;
548 char *buf;
549
550 if(!buffer)
551 buffer=(char*)malloc(BUFFSIZE+1);
552
553 while((buf=fgets(&buffer[n],BUFFSIZE,file)))
554 {
555 int s=strlen(buf);
556 n+=s;
557
558 if(buffer[n-1]=='\n')
559 break;
560 else
561 buffer=(char*)realloc(buffer,n+BUFFSIZE+1);
562 }
563
564 if(!buf)
565 {free(buffer);buffer=NULL;}
566
567 return(buffer);
568 }

Properties

Name Value
cvs:description OSM XML file parser.