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