Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /trunk/src/osmparser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 199 - (hide annotations) (download) (as text)
Mon Jun 15 18:56:09 2009 UTC (15 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 18429 byte(s)
Put some of types.h into typesx.h (for extended data types).
Put some of functions.h into functionsx.h (for OSM parser).
Change included files to match.

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

Properties

Name Value
cvs:description OSM XML file parser.