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 30 -
(hide annotations)
(download)
(as text)
Sat Jan 10 15:59:59 2009 UTC (16 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 8881 byte(s)
Sat Jan 10 15:59:59 2009 UTC (16 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 8881 byte(s)
Store more information about ways.
1 | amb | 2 | /*************************************** |
2 | amb | 30 | $Header: /home/amb/CVS/routino/src/osmparser.c,v 1.6 2009-01-10 15:59:58 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 | 2 | ++++++++++++++++++++++++++++++++++++++*/ |
44 | |||
45 | amb | 26 | int ParseXML(FILE *file,NodesMem *OSMNodes,SegmentsMem *OSMSegments,WaysMem *OSMWays) |
46 | amb | 2 | { |
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 | amb | 6 | int way_oneway=0,way_roundabout=0; |
53 | amb | 2 | float way_maxspeed=0; |
54 | amb | 8 | char *way_highway=NULL,*way_name=NULL,*way_ref=NULL,*way_access=NULL,*way_car=NULL; |
55 | amb | 2 | node_t *way_nodes=NULL; |
56 | int way_nnodes=0,way_nalloc=0; | ||
57 | |||
58 | /* Parse the file */ | ||
59 | |||
60 | while((line=fgets_realloc(line,file))) | ||
61 | { | ||
62 | char *l=line,*m; | ||
63 | |||
64 | nlines++; | ||
65 | |||
66 | while(isspace(*l)) | ||
67 | l++; | ||
68 | |||
69 | if(!strncmp(l,"<node",5)) /* The start of a node */ | ||
70 | { | ||
71 | node_t id; | ||
72 | latlong_t latitude,longitude; | ||
73 | |||
74 | nnodes++; | ||
75 | |||
76 | isnode=1; isway=0; isrelation=0; | ||
77 | |||
78 | m=strstr(l,"id="); m+=4; if(*m=='"' || *m=='\'') m++; id=atoll(m); | ||
79 | m=strstr(l,"lat="); m+=5; if(*m=='"' || *m=='\'') m++; latitude=atof(m); | ||
80 | m=strstr(l,"lon="); m+=4; if(*m=='"' || *m=='\'') m++; longitude=atof(m); | ||
81 | |||
82 | amb | 26 | AppendNode(OSMNodes,id,latitude,longitude); |
83 | amb | 2 | } |
84 | else if(!strncmp(l,"</node",6)) /* The end of a node */ | ||
85 | { | ||
86 | isnode=0; isway=0; isrelation=0; | ||
87 | } | ||
88 | else if(!strncmp(l,"<way",4)) /* The start of a way */ | ||
89 | { | ||
90 | nways++; | ||
91 | |||
92 | isnode=0; isway=1; isrelation=0; | ||
93 | |||
94 | m=strstr(l,"id="); m+=3; if(*m=='"' || *m=='\'') m++; way_id=atol(m); | ||
95 | |||
96 | way_oneway=0; | ||
97 | amb | 6 | way_roundabout=0; |
98 | amb | 2 | way_maxspeed=0; |
99 | way_name=NULL; way_ref=NULL; | ||
100 | way_nnodes=0; | ||
101 | } | ||
102 | else if(!strncmp(l,"</way",5)) /* The end of a way */ | ||
103 | { | ||
104 | isnode=0; isway=0; isrelation=0; | ||
105 | |||
106 | amb | 30 | if(way_highway) |
107 | amb | 2 | { |
108 | amb | 30 | Way *way; |
109 | amb | 6 | char *refname; |
110 | amb | 30 | int i; |
111 | amb | 2 | |
112 | amb | 6 | if(way_ref && way_name) |
113 | { | ||
114 | refname=(char*)malloc(strlen(way_ref)+strlen(way_name)+4); | ||
115 | sprintf(refname,"%s (%s)",way_name,way_ref); | ||
116 | } | ||
117 | amb | 30 | else if(way_ref && !way_name && way_roundabout) |
118 | { | ||
119 | refname=(char*)malloc(strlen(way_ref)+14); | ||
120 | sprintf(refname,"%s (roundabout)",way_ref); | ||
121 | } | ||
122 | amb | 6 | else if(way_ref && !way_name) |
123 | refname=way_ref; | ||
124 | else if(!way_ref && way_name) | ||
125 | refname=way_name; | ||
126 | else if(way_roundabout) | ||
127 | { | ||
128 | amb | 8 | refname=(char*)malloc(strlen(way_highway)+14); |
129 | sprintf(refname,"%s (roundabout)",way_highway); | ||
130 | amb | 6 | } |
131 | else /* if(!way_ref && !way_name && !way_roundabout) */ | ||
132 | refname=way_highway; | ||
133 | |||
134 | amb | 2 | for(i=1;i<way_nnodes;i++) |
135 | { | ||
136 | node_t from=way_nodes[i-1]; | ||
137 | node_t to =way_nodes[i]; | ||
138 | |||
139 | amb | 26 | AppendSegment(OSMSegments,from,to,way_id); |
140 | amb | 2 | |
141 | if(!way_oneway) | ||
142 | amb | 26 | AppendSegment(OSMSegments,to,from,way_id); |
143 | amb | 6 | } |
144 | amb | 2 | |
145 | amb | 30 | way=AppendWay(OSMWays,way_id,refname); |
146 | amb | 6 | |
147 | amb | 30 | way->limit=way_maxspeed; |
148 | way->type=TypeOfWay(way_highway); | ||
149 | |||
150 | switch(way->type) | ||
151 | { | ||
152 | case Way_Motorway: | ||
153 | way->speed=1.6*80; break; | ||
154 | case Way_Trunk: | ||
155 | way->speed=1.6*((way_oneway&&!way_roundabout)?75:65); break; | ||
156 | case Way_Primary: | ||
157 | way->speed=1.6*((way_oneway&&!way_roundabout)?70:60); break; | ||
158 | case Way_Secondary: | ||
159 | way->speed=1.6*55; break; | ||
160 | case Way_Tertiary: | ||
161 | way->speed=1.6*50; break; | ||
162 | case Way_Unclassfied: | ||
163 | way->speed=1.6*40; break; | ||
164 | case Way_Residential: | ||
165 | way->speed=1.6*30; break; | ||
166 | case Way_Service: | ||
167 | way->speed=1.6*20; break; | ||
168 | case Way_Track: | ||
169 | way->speed=1.6*10; break; | ||
170 | case Way_Bridleway: | ||
171 | case Way_Cycleway: | ||
172 | case Way_Footway: | ||
173 | case Way_Unknown: | ||
174 | way->speed=0; | ||
175 | } | ||
176 | |||
177 | if(way_oneway) | ||
178 | way->type|=Way_ONEWAY; | ||
179 | |||
180 | if(way_roundabout) | ||
181 | way->type|=Way_ROUNDABOUT; | ||
182 | |||
183 | if(way_access && (!strcmp(way_access,"private") || !strcmp(way_access,"no"))) | ||
184 | way->type|=Way_NOTROUTABLE; | ||
185 | |||
186 | if(way_car && !strcmp(way_car,"no")) | ||
187 | way->type|=Way_NOTROUTABLE; | ||
188 | |||
189 | amb | 6 | if(refname!=way_ref && refname!=way_name && refname!=way_highway) |
190 | free(refname); | ||
191 | amb | 2 | } |
192 | |||
193 | if(way_highway) {free(way_highway); way_highway=NULL;} | ||
194 | if(way_name) {free(way_name); way_name=NULL;} | ||
195 | if(way_ref) {free(way_ref); way_ref=NULL;} | ||
196 | if(way_access) {free(way_access); way_access=NULL;} | ||
197 | amb | 8 | if(way_car) {free(way_car); way_car=NULL;} |
198 | amb | 2 | } |
199 | else if(!strncmp(l,"<relation",9)) /* The start of a relation */ | ||
200 | { | ||
201 | nrelations++; | ||
202 | |||
203 | isnode=0; isway=0; isrelation=1; | ||
204 | } | ||
205 | else if(!strncmp(l,"</relation",10)) /* The end of a relation */ | ||
206 | { | ||
207 | isnode=0; isway=0; isrelation=0; | ||
208 | } | ||
209 | else if(isnode) /* The middle of a node */ | ||
210 | { | ||
211 | } | ||
212 | else if(isway) /* The middle of a way */ | ||
213 | { | ||
214 | node_t id; | ||
215 | |||
216 | if(!strncmp(l,"<nd",3)) /* The start of a node specifier */ | ||
217 | { | ||
218 | m=strstr(l,"ref="); m+=4; if(*m=='"' || *m=='\'') m++; id=atoll(m); | ||
219 | |||
220 | if(way_nnodes<=way_nalloc) | ||
221 | way_nodes=(node_t*)realloc((void*)way_nodes,(way_nalloc+=16)*sizeof(node_t)); | ||
222 | |||
223 | way_nodes[way_nnodes++]=id; | ||
224 | } | ||
225 | |||
226 | if(!strncmp(l,"<tag",4)) /* The start of a tag specifier */ | ||
227 | { | ||
228 | char delimiter,*k="",*v=""; | ||
229 | |||
230 | m=strstr(l,"k="); m+=2; delimiter=*m; m++; k=m; | ||
231 | while(*m!=delimiter) m++; *m=0; l=m+1; | ||
232 | |||
233 | m=strstr(l,"v="); m+=2; delimiter=*m; m++; v=m; | ||
234 | while(*m!=delimiter) m++; *m=0; | ||
235 | |||
236 | if(!strcmp(k,"oneway") && (!strcmp(v,"true") || !strcmp(v,"yes"))) way_oneway=1; | ||
237 | amb | 6 | if(!strcmp(k,"junction") && !strcmp(v,"roundabout")) {way_oneway=1; way_roundabout=1;} |
238 | amb | 2 | if(!strcmp(k,"highway") && !strncmp(v,"motorway",8)) way_oneway=1; |
239 | |||
240 | if(!strcmp(k,"highway")) | ||
241 | way_highway=strcpy((char*)malloc(strlen(v)+1),v); | ||
242 | |||
243 | if(!strcmp(k,"name")) | ||
244 | way_name=strcpy((char*)malloc(strlen(v)+1),v); | ||
245 | |||
246 | if(!strcmp(k,"ref")) | ||
247 | way_ref=strcpy((char*)malloc(strlen(v)+1),v); | ||
248 | |||
249 | if(!strcmp(k,"access")) | ||
250 | way_access=strcpy((char*)malloc(strlen(v)+1),v); | ||
251 | |||
252 | amb | 8 | if(!strcmp(k,"car")) |
253 | way_car=strcpy((char*)malloc(strlen(v)+1),v); | ||
254 | |||
255 | amb | 2 | if(!strcmp(k,"maxspeed")) |
256 | { | ||
257 | way_maxspeed=atof(v); | ||
258 | if(strstr(v,"mph")) | ||
259 | way_maxspeed*=1.6; | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | else if(isrelation) /* The middle of a relation */ | ||
264 | { | ||
265 | } | ||
266 | |||
267 | if(!(nlines%10000)) | ||
268 | { | ||
269 | printf("\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",nlines,nnodes,nways,nrelations); | ||
270 | fflush(stdout); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | printf("\rRead : Lines=%ld Nodes=%ld Ways=%ld Relations=%ld\n",nlines,nnodes,nways,nrelations); | ||
275 | fflush(stdout); | ||
276 | |||
277 | if(way_nalloc) | ||
278 | free(way_nodes); | ||
279 | |||
280 | return(0); | ||
281 | } | ||
282 | |||
283 | |||
284 | /*++++++++++++++++++++++++++++++++++++++ | ||
285 | Call fgets and realloc the buffer as needed to get a whole line. | ||
286 | |||
287 | char *fgets_realloc Returns the modified buffer (NULL at the end of the file). | ||
288 | |||
289 | char *buffer The current buffer. | ||
290 | |||
291 | FILE *file The file to read from. | ||
292 | ++++++++++++++++++++++++++++++++++++++*/ | ||
293 | |||
294 | static char *fgets_realloc(char *buffer,FILE *file) | ||
295 | { | ||
296 | int n=0; | ||
297 | char *buf; | ||
298 | |||
299 | if(!buffer) | ||
300 | buffer=(char*)malloc(BUFFSIZE+1); | ||
301 | |||
302 | while((buf=fgets(&buffer[n],BUFFSIZE,file))) | ||
303 | { | ||
304 | int s=strlen(buf); | ||
305 | n+=s; | ||
306 | |||
307 | if(buffer[n-1]=='\n') | ||
308 | break; | ||
309 | else | ||
310 | buffer=(char*)realloc(buffer,n+BUFFSIZE+1); | ||
311 | } | ||
312 | |||
313 | if(!buf) | ||
314 | {free(buffer);buffer=NULL;} | ||
315 | |||
316 | return(buffer); | ||
317 | } |
Properties
Name | Value |
---|---|
cvs:description | OSM XML file parser. |