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