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