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