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 209 - (show annotations) (download) (as text)
Tue Jun 30 18:32:42 2009 UTC (15 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 18574 byte(s)
Remove the Segment structure from the SegmentX structure to save memory.

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

Properties

Name Value
cvs:description OSM XML file parser.