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 347 - (show annotations) (download) (as text)
Sat Apr 3 14:20:16 2010 UTC (15 years ago) by amb
File MIME type: text/x-csrc
File size: 21902 byte(s)
Rename the old ParseXML() function as ParseOSM().

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/osmparser.c,v 1.64 2010-04-03 14:20:16 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-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 <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 ParseOSM 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 ParseOSM(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,way_multilane=0,way_bridge=0,way_tunnel=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; way_multilane=0; way_bridge=0; way_tunnel=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|Properties_Multilane;
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 case Way_Steps:
203 way.allow=Allow_Foot;
204 way.props=0;
205 break;
206 default:
207 way.allow=0;
208 way.props=0;
209 break;
210 }
211
212 if(way_allow_yes&Allow_Foot && !(way_allow_no&Allow_Wheelchair)) /* Allow wheelchair if foot allowed and wheelchair not disallowed. */
213 way_allow_yes|=Allow_Wheelchair;
214
215 if(way_allow_no) /* Remove the ones explicitly denied (e.g. private) */
216 way.allow&=~way_allow_no;
217
218 if(way_allow_yes) /* Add the ones explicitly allowed (e.g. footpath along private) */
219 way.allow|=way_allow_yes;
220
221 if(way.allow & profile->allow)
222 {
223 char *refname;
224 int i;
225
226 if(way_oneway)
227 way.type|=Way_OneWay;
228
229 if(way_roundabout)
230 way.type|=Way_Roundabout;
231
232 if(profile->props_yes[Property_Paved])
233 {
234 if(way_paved>0)
235 way.props|=Properties_Paved;
236 else if(way_paved<0)
237 way.props&=~Properties_Paved;
238 }
239
240 if(profile->props_yes[Property_Multilane])
241 {
242 if(way_multilane>1)
243 way.props|=Properties_Multilane;
244 else if(way_paved==1)
245 way.props&=~Properties_Multilane;
246 }
247
248 if(profile->props_yes[Property_Bridge])
249 {
250 if(way_bridge)
251 way.props|=Properties_Bridge;
252 }
253
254 if(profile->props_yes[Property_Tunnel])
255 {
256 if(way_tunnel)
257 way.props|=Properties_Tunnel;
258 }
259
260 if(way_ref && way_name)
261 {
262 refname=(char*)malloc(strlen(way_ref)+strlen(way_name)+4);
263 sprintf(refname,"%s (%s)",way_name,way_ref);
264 }
265 else if(way_ref && !way_name && way_roundabout)
266 {
267 refname=(char*)malloc(strlen(way_ref)+14);
268 sprintf(refname,"%s (roundabout)",way_ref);
269 }
270 else if(way_ref && !way_name)
271 refname=way_ref;
272 else if(!way_ref && way_name)
273 refname=way_name;
274 else if(way_roundabout)
275 {
276 refname=(char*)malloc(strlen(way_highway)+14);
277 sprintf(refname,"%s (roundabout)",way_highway);
278 }
279 else /* if(!way_ref && !way_name && !way_roundabout) */
280 refname=way_highway;
281
282 way.speed =way_maxspeed;
283 way.weight=way_maxweight;
284 way.height=way_maxheight;
285 way.width =way_maxwidth;
286 way.length=way_maxlength;
287
288 AppendWay(OSMWays,way_id,&way,refname);
289
290 if(refname!=way_ref && refname!=way_name && refname!=way_highway)
291 free(refname);
292
293 for(i=1;i<way_nnodes;i++)
294 {
295 node_t from=way_nodes[i-1];
296 node_t to =way_nodes[i];
297
298 if(way_oneway>0)
299 {
300 AppendSegment(OSMSegments,way_id,from,to,ONEWAY_1TO2);
301 AppendSegment(OSMSegments,way_id,to,from,ONEWAY_2TO1);
302 }
303 else if(way_oneway<0)
304 {
305 AppendSegment(OSMSegments,way_id,from,to,ONEWAY_2TO1);
306 AppendSegment(OSMSegments,way_id,to,from,ONEWAY_1TO2);
307 }
308 else
309 {
310 AppendSegment(OSMSegments,way_id,from,to,0);
311 AppendSegment(OSMSegments,way_id,to,from,0);
312 }
313 }
314 }
315 }
316 }
317
318 if(way_highway) free(way_highway);
319 if(way_name) free(way_name);
320 if(way_ref) free(way_ref);
321 }
322 else if(!strncmp(l,"<relation",9)) /* The start of a relation */
323 {
324 nrelations++;
325
326 isnode=0; isway=0; isrelation=1;
327 }
328 else if(!strncmp(l,"</relation",10)) /* The end of a relation */
329 {
330 isnode=0; isway=0; isrelation=0;
331 }
332 else if(isnode) /* The middle of a node */
333 {
334 }
335 else if(isway) /* The middle of a way */
336 {
337 node_t id;
338
339 if(!strncmp(l,"<nd",3)) /* The start of a node specifier */
340 {
341 m=strstr(l,"ref="); m+=4; if(*m=='"' || *m=='\'') m++; id=atoll(m);
342
343 if(way_nnodes==way_nalloc)
344 way_nodes=(node_t*)realloc((void*)way_nodes,(way_nalloc+=256)*sizeof(node_t));
345
346 way_nodes[way_nnodes++]=id;
347 }
348
349 if(!strncmp(l,"<tag",4)) /* The start of a tag specifier */
350 {
351 char delimiter,*k="",*v="";
352
353 m=strstr(l,"k="); m+=2; delimiter=*m; m++; k=m;
354 while(*m!=delimiter) m++; *m=0; l=m+1;
355
356 m=strstr(l,"v="); m+=2; delimiter=*m; m++; v=m;
357 while(*m!=delimiter) m++; *m=0;
358
359 switch(*k)
360 {
361 case 'a':
362 if(!strcmp(k,"access"))
363 {
364 if(ISALLOWED(v))
365 ;
366 else
367 way_allow_no=Allow_ALL;
368 }
369 break;
370
371 case 'b':
372 if(!strcmp(k,"bicycle"))
373 {
374 if(ISALLOWED(v))
375 way_allow_yes|=Allow_Bicycle;
376 else
377 way_allow_no |=Allow_Bicycle;
378 }
379
380 if(!strcmp(k,"bridge"))
381 way_bridge=ISTRUE(v);
382 break;
383
384 case 'd':
385 if(!strcmp(k,"designation"))
386 {
387 if(!strcmp(v,"bridleway"))
388 way_allow_yes|=Allow_Foot|Allow_Horse|Allow_Bicycle;
389 else if(!strcmp(v,"byway"))
390 way_allow_yes|=Allow_Foot|Allow_Horse|Allow_Bicycle;
391 else if(!strcmp(v,"footpath"))
392 way_allow_yes|=Allow_Foot;
393 }
394 break;
395
396 case 'f':
397 if(!strcmp(k,"foot"))
398 {
399 if(ISALLOWED(v))
400 way_allow_yes|=Allow_Foot;
401 else
402 way_allow_no |=Allow_Foot;
403 }
404 break;
405
406 case 'g':
407 if(!strcmp(k,"goods"))
408 {
409 if(ISALLOWED(v))
410 way_allow_yes|=Allow_Goods;
411 else
412 way_allow_no |=Allow_Goods;
413 }
414 break;
415
416 case 'h':
417 if(!strcmp(k,"highway"))
418 way_highway=strcpy((char*)malloc(strlen(v)+1),v);
419
420 if(!strcmp(k,"horse"))
421 {
422 if(ISALLOWED(v))
423 way_allow_yes|=Allow_Horse;
424 else
425 way_allow_no |=Allow_Horse;
426 }
427
428 if(!strcmp(k,"hgv"))
429 {
430 if(ISALLOWED(v))
431 way_allow_yes|=Allow_HGV;
432 else
433 way_allow_no |=Allow_HGV;
434 }
435 break;
436
437 case 'j':
438 if(!strcmp(k,"junction"))
439 if(!strcmp(v,"roundabout"))
440 {way_oneway=1; way_roundabout=1;}
441 break;
442
443 case 'l':
444 if(!strcmp(k,"lanes"))
445 way_multilane=atoi(v);
446
447 case 'm':
448 if(!strcmp(k,"maxspeed"))
449 {
450 if(strstr(v,"mph"))
451 way_maxspeed=kph_to_speed(1.609*atof(v));
452 else
453 way_maxspeed=kph_to_speed(atof(v));
454 }
455
456 if(!strcmp(k,"maxspeed:mph"))
457 way_maxspeed=kph_to_speed(1.609*atof(v));
458
459 if(!strcmp(k,"maxweight"))
460 {
461 if(strstr(v,"kg"))
462 way_maxweight=tonnes_to_weight(atof(v)/1000);
463 else
464 way_maxweight=tonnes_to_weight(atof(v));
465 }
466
467 if(!strcmp(k,"maxheight"))
468 {
469 if(strchr(v,'\''))
470 {
471 int feet,inches;
472
473 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
474 way_maxheight=metres_to_height((feet+(double)inches/12.0)*0.254);
475 else if(sscanf(v,"%d'",&feet)==1)
476 way_maxheight=metres_to_height((feet+(double)inches/12.0)*0.254);
477 }
478 else if(strstr(v,"ft") || strstr(v,"feet"))
479 way_maxheight=metres_to_height(atof(v)*0.254);
480 else
481 way_maxheight=metres_to_height(atof(v));
482 }
483
484 if(!strcmp(k,"maxwidth"))
485 {
486 if(strchr(v,'\''))
487 {
488 int feet,inches;
489
490 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
491 way_maxwidth=metres_to_height((feet+(double)inches/12.0)*0.254);
492 else if(sscanf(v,"%d'",&feet)==1)
493 way_maxwidth=metres_to_height((feet+(double)inches/12.0)*0.254);
494 }
495 else if(strstr(v,"ft") || strstr(v,"feet"))
496 way_maxwidth=metres_to_width(atof(v)*0.254);
497 else
498 way_maxwidth=metres_to_width(atof(v));
499 }
500
501 if(!strcmp(k,"maxlength"))
502 {
503 if(strchr(v,'\''))
504 {
505 int feet,inches;
506
507 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
508 way_maxlength=metres_to_height((feet+(double)inches/12.0)*0.254);
509 else if(sscanf(v,"%d'",&feet)==1)
510 way_maxlength=metres_to_height((feet+(double)inches/12.0)*0.254);
511 }
512 else if(strstr(v,"ft") || strstr(v,"feet"))
513 way_maxlength=metres_to_length(atof(v)*0.254);
514 else
515 way_maxlength=metres_to_length(atof(v));
516 }
517
518 if(!strcmp(k,"moped"))
519 {
520 if(ISALLOWED(v))
521 way_allow_yes|=Allow_Moped;
522 else
523 way_allow_no |=Allow_Moped;
524 }
525
526 if(!strcmp(k,"motorbike"))
527 {
528 if(ISALLOWED(v))
529 way_allow_yes|=Allow_Motorbike;
530 else
531 way_allow_no |=Allow_Motorbike;
532 }
533
534 if(!strcmp(k,"motorcar"))
535 {
536 if(ISALLOWED(v))
537 way_allow_yes|=Allow_Motorcar;
538 else
539 way_allow_no |=Allow_Motorcar;
540 }
541
542 if(!strcmp(k,"motor_vehicle"))
543 {
544 if(ISALLOWED(v))
545 way_allow_yes|=Allow_Moped|Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
546 else
547 way_allow_no |=Allow_Moped|Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
548 }
549 break;
550
551 case 'n':
552 if(!strcmp(k,"name"))
553 way_name=strcpy((char*)malloc(strlen(v)+1),v);
554 break;
555
556 case 'o':
557 if(!strcmp(k,"oneway"))
558 {
559 if(ISTRUE(v))
560 way_oneway=1;
561 else if(!strcmp(v,"-1"))
562 way_oneway=-1;
563 }
564 break;
565
566 case 'p':
567 if(!strcmp(k,"paved"))
568 {
569 if(ISTRUE(v))
570 way_paved=1;
571 else
572 way_paved=-1;
573 }
574
575 if(!strcmp(k,"psv"))
576 {
577 if(ISALLOWED(v))
578 way_allow_yes|=Allow_PSV;
579 else
580 way_allow_no |=Allow_PSV;
581 }
582 break;
583
584 case 'r':
585 if(!strcmp(k,"ref"))
586 way_ref=strcpy((char*)malloc(strlen(v)+1),v);
587 break;
588
589 case 's':
590 if(!strcmp(k,"surface"))
591 {
592 if(!strcmp(v,"paved") || !strcmp(v,"asphalt") || !strcmp(v,"concrete"))
593 way_paved=1;
594 else
595 way_paved=-1;
596 }
597 break;
598
599 case 't':
600 if(!strcmp(k,"tunnel"))
601 way_tunnel=ISTRUE(v);
602 break;
603
604 case 'v':
605 if(!strcmp(k,"vehicle"))
606 {
607 if(ISALLOWED(v))
608 way_allow_yes|=Allow_Bicycle|Allow_Moped|Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
609 else
610 way_allow_no |=Allow_Bicycle|Allow_Moped|Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
611 }
612 break;
613
614 case 'w':
615 if(!strcmp(k,"wheelchair"))
616 {
617 if(ISALLOWED(v))
618 way_allow_yes|=Allow_Wheelchair;
619 else
620 way_allow_no |=Allow_Wheelchair;
621 }
622 break;
623
624 default:
625 ;
626 }
627 }
628 }
629 else if(isrelation) /* The middle of a relation */
630 {
631 }
632
633 if(!(nlines%10000))
634 {
635 printf("\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",nlines,nnodes,nways,nrelations);
636 fflush(stdout);
637 }
638 }
639
640 printf("\rRead: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld \n",nlines,nnodes,nways,nrelations);
641 fflush(stdout);
642
643 if(line)
644 free(line);
645
646 if(way_nalloc)
647 free(way_nodes);
648
649 return(0);
650 }
651
652
653 /*++++++++++++++++++++++++++++++++++++++
654 Call fgets and realloc the buffer as needed to get a whole line.
655
656 char *fgets_realloc Returns the modified buffer (NULL at the end of the file).
657
658 char *buffer The current buffer.
659
660 FILE *file The file to read from.
661 ++++++++++++++++++++++++++++++++++++++*/
662
663 static char *fgets_realloc(char *buffer,FILE *file)
664 {
665 int n=0;
666 char *buf;
667
668 if(!buffer)
669 buffer=(char*)malloc(BUFFSIZE+1);
670
671 while((buf=fgets(&buffer[n],BUFFSIZE,file)))
672 {
673 int s=strlen(buf);
674 n+=s;
675
676 if(buffer[n-1]=='\n')
677 break;
678 else
679 buffer=(char*)realloc(buffer,n+BUFFSIZE+1);
680 }
681
682 if(!buf)
683 {free(buffer);buffer=NULL;}
684
685 return(buffer);
686 }

Properties

Name Value
cvs:description OSM XML file parser.