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 302 - (show annotations) (download) (as text)
Fri Nov 13 19:26:18 2009 UTC (15 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 20159 byte(s)
Added in some more constants with the value ~0.

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

Properties

Name Value
cvs:description OSM XML file parser.