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