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 812 -
(hide annotations)
(download)
(as text)
Thu Jul 21 18:44:52 2011 UTC (13 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 36768 byte(s)
Thu Jul 21 18:44:52 2011 UTC (13 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 36768 byte(s)
Add logging of parsing and processing errors.
1 | amb | 2 | /*************************************** |
2 | OSM XML file parser (either JOSM or planet) | ||
3 | amb | 151 | |
4 | Part of the Routino routing software. | ||
5 | amb | 2 | ******************/ /****************** |
6 | amb | 643 | This file Copyright 2008-2011 Andrew M. Bishop |
7 | amb | 2 | |
8 | amb | 151 | This program is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU Affero General Public License as published by | ||
10 | the Free Software Foundation, either version 3 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU Affero General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU Affero General Public License | ||
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | amb | 2 | ***************************************/ |
21 | |||
22 | |||
23 | amb | 776 | #include <assert.h> |
24 | amb | 2 | #include <stdio.h> |
25 | #include <stdlib.h> | ||
26 | #include <string.h> | ||
27 | #include <ctype.h> | ||
28 | |||
29 | amb | 199 | #include "typesx.h" |
30 | #include "functionsx.h" | ||
31 | amb | 498 | |
32 | amb | 109 | #include "nodesx.h" |
33 | #include "segmentsx.h" | ||
34 | #include "waysx.h" | ||
35 | amb | 498 | #include "relationsx.h" |
36 | |||
37 | amb | 394 | #include "xmlparse.h" |
38 | #include "tagging.h" | ||
39 | amb | 2 | |
40 | amb | 519 | #include "logging.h" |
41 | amb | 26 | |
42 | amb | 519 | |
43 | amb | 394 | /* Macros */ |
44 | amb | 2 | |
45 | amb | 680 | /*+ Checks if a value in the XML is one of the allowed values for true. +*/ |
46 | amb | 812 | #define ISTRUE(xx) (!strcmp(xx,"true") || !strcmp(xx,"yes") || !strcmp(xx,"1")) |
47 | amb | 297 | |
48 | amb | 812 | /*+ Checks if a value in the XML is one of the allowed values for false. +*/ |
49 | #define ISFALSE(xx) (!strcmp(xx,"false") || !strcmp(xx,"no") || !strcmp(xx,"0")) | ||
50 | amb | 298 | |
51 | amb | 812 | |
52 | amb | 394 | /* Local variables */ |
53 | |||
54 | amb | 790 | static index_t nnodes=0; |
55 | static index_t nways=0; | ||
56 | static index_t nrelations=0; | ||
57 | |||
58 | amb | 401 | static TagList *current_tags=NULL; |
59 | amb | 394 | |
60 | static node_t *way_nodes=NULL; | ||
61 | static int way_nnodes=0; | ||
62 | |||
63 | amb | 498 | static node_t *relation_nodes=NULL; |
64 | static int relation_nnodes=0; | ||
65 | static way_t *relation_ways=NULL; | ||
66 | static int relation_nways=0; | ||
67 | static relation_t *relation_relations=NULL; | ||
68 | static int relation_nrelations=0; | ||
69 | amb | 755 | static way_t relation_from=NO_WAY_ID; |
70 | static way_t relation_to=NO_WAY_ID; | ||
71 | static node_t relation_via=NO_NODE_ID; | ||
72 | amb | 394 | |
73 | amb | 498 | static NodesX *nodes; |
74 | static SegmentsX *segments; | ||
75 | static WaysX *ways; | ||
76 | static RelationsX *relations; | ||
77 | amb | 394 | |
78 | amb | 498 | |
79 | amb | 228 | /* Local functions */ |
80 | |||
81 | amb | 469 | static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude); |
82 | amb | 394 | static void process_way_tags(TagList *tags,way_t id); |
83 | amb | 498 | static void process_relation_tags(TagList *tags,relation_t id); |
84 | amb | 2 | |
85 | amb | 812 | static double parse_speed(way_t id,const char *k,const char *v); |
86 | static double parse_weight(way_t id,const char *k,const char *v); | ||
87 | static double parse_length(way_t id,const char *k,const char *v); | ||
88 | amb | 2 | |
89 | amb | 812 | |
90 | amb | 394 | /* The XML tag processing function prototypes */ |
91 | amb | 2 | |
92 | amb | 394 | //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding); |
93 | //static int osmType_function(const char *_tag_,int _type_); | ||
94 | static int relationType_function(const char *_tag_,int _type_,const char *id); | ||
95 | static int wayType_function(const char *_tag_,int _type_,const char *id); | ||
96 | amb | 498 | static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role); |
97 | amb | 394 | static int ndType_function(const char *_tag_,int _type_,const char *ref); |
98 | static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon); | ||
99 | static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v); | ||
100 | amb | 399 | //static int boundType_function(const char *_tag_,int _type_); |
101 | amb | 394 | //static int boundsType_function(const char *_tag_,int _type_); |
102 | amb | 2 | |
103 | amb | 26 | |
104 | amb | 394 | /* The XML tag definitions */ |
105 | amb | 26 | |
106 | amb | 394 | /*+ The boundsType type tag. +*/ |
107 | static xmltag boundsType_tag= | ||
108 | {"bounds", | ||
109 | 0, {NULL}, | ||
110 | NULL, | ||
111 | {NULL}}; | ||
112 | amb | 26 | |
113 | amb | 399 | /*+ The boundType type tag. +*/ |
114 | static xmltag boundType_tag= | ||
115 | {"bound", | ||
116 | 0, {NULL}, | ||
117 | NULL, | ||
118 | {NULL}}; | ||
119 | |||
120 | amb | 394 | /*+ The tagType type tag. +*/ |
121 | static xmltag tagType_tag= | ||
122 | {"tag", | ||
123 | 2, {"k","v"}, | ||
124 | tagType_function, | ||
125 | {NULL}}; | ||
126 | amb | 75 | |
127 | amb | 394 | /*+ The nodeType type tag. +*/ |
128 | static xmltag nodeType_tag= | ||
129 | {"node", | ||
130 | 3, {"id","lat","lon"}, | ||
131 | nodeType_function, | ||
132 | {&tagType_tag,NULL}}; | ||
133 | amb | 2 | |
134 | amb | 394 | /*+ The ndType type tag. +*/ |
135 | static xmltag ndType_tag= | ||
136 | {"nd", | ||
137 | 1, {"ref"}, | ||
138 | ndType_function, | ||
139 | {NULL}}; | ||
140 | amb | 2 | |
141 | amb | 394 | /*+ The memberType type tag. +*/ |
142 | static xmltag memberType_tag= | ||
143 | {"member", | ||
144 | 3, {"type","ref","role"}, | ||
145 | amb | 498 | memberType_function, |
146 | amb | 394 | {NULL}}; |
147 | amb | 227 | |
148 | amb | 394 | /*+ The wayType type tag. +*/ |
149 | static xmltag wayType_tag= | ||
150 | {"way", | ||
151 | 1, {"id"}, | ||
152 | wayType_function, | ||
153 | {&ndType_tag,&tagType_tag,NULL}}; | ||
154 | amb | 2 | |
155 | amb | 394 | /*+ The relationType type tag. +*/ |
156 | static xmltag relationType_tag= | ||
157 | {"relation", | ||
158 | 1, {"id"}, | ||
159 | relationType_function, | ||
160 | {&memberType_tag,&tagType_tag,NULL}}; | ||
161 | amb | 2 | |
162 | amb | 394 | /*+ The osmType type tag. +*/ |
163 | static xmltag osmType_tag= | ||
164 | {"osm", | ||
165 | 0, {NULL}, | ||
166 | NULL, | ||
167 | amb | 399 | {&boundsType_tag,&boundType_tag,&nodeType_tag,&wayType_tag,&relationType_tag,NULL}}; |
168 | amb | 2 | |
169 | amb | 394 | /*+ The xmlDeclaration type tag. +*/ |
170 | static xmltag xmlDeclaration_tag= | ||
171 | {"xml", | ||
172 | 2, {"version","encoding"}, | ||
173 | NULL, | ||
174 | {NULL}}; | ||
175 | amb | 2 | |
176 | |||
177 | amb | 394 | /*+ The complete set of tags at the top level. +*/ |
178 | static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&osmType_tag,NULL}; | ||
179 | amb | 2 | |
180 | |||
181 | amb | 394 | /* The XML tag processing functions */ |
182 | amb | 2 | |
183 | amb | 159 | |
184 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
185 | The function that is called when the boundsType XSD type is seen | ||
186 | amb | 2 | |
187 | amb | 394 | int boundsType_function Returns 0 if no error occured or something else otherwise. |
188 | amb | 2 | |
189 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
190 | amb | 203 | |
191 | amb | 394 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
192 | ++++++++++++++++++++++++++++++++++++++*/ | ||
193 | amb | 2 | |
194 | amb | 394 | //static int boundsType_function(const char *_tag_,int _type_) |
195 | //{ | ||
196 | // return(0); | ||
197 | //} | ||
198 | amb | 2 | |
199 | amb | 6 | |
200 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
201 | amb | 399 | The function that is called when the boundType XSD type is seen |
202 | |||
203 | int boundType_function Returns 0 if no error occured or something else otherwise. | ||
204 | |||
205 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
206 | |||
207 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
208 | ++++++++++++++++++++++++++++++++++++++*/ | ||
209 | |||
210 | //static int boundType_function(const char *_tag_,int _type_) | ||
211 | //{ | ||
212 | // return(0); | ||
213 | //} | ||
214 | |||
215 | |||
216 | /*++++++++++++++++++++++++++++++++++++++ | ||
217 | amb | 394 | The function that is called when the tagType XSD type is seen |
218 | amb | 2 | |
219 | amb | 394 | int tagType_function Returns 0 if no error occured or something else otherwise. |
220 | amb | 314 | |
221 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
222 | amb | 2 | |
223 | amb | 394 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
224 | amb | 30 | |
225 | amb | 394 | const char *k The contents of the 'k' attribute (or NULL if not defined). |
226 | amb | 30 | |
227 | amb | 394 | const char *v The contents of the 'v' attribute (or NULL if not defined). |
228 | ++++++++++++++++++++++++++++++++++++++*/ | ||
229 | amb | 30 | |
230 | amb | 394 | static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v) |
231 | { | ||
232 | amb | 401 | if(_type_&XMLPARSE_TAG_START && current_tags) |
233 | amb | 394 | { |
234 | XMLPARSE_ASSERT_STRING(_tag_,k); | ||
235 | XMLPARSE_ASSERT_STRING(_tag_,v); | ||
236 | amb | 30 | |
237 | amb | 401 | AppendTag(current_tags,k,v); |
238 | amb | 394 | } |
239 | amb | 262 | |
240 | amb | 394 | return(0); |
241 | } | ||
242 | amb | 308 | |
243 | amb | 313 | |
244 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
245 | The function that is called when the nodeType XSD type is seen | ||
246 | amb | 313 | |
247 | amb | 394 | int nodeType_function Returns 0 if no error occured or something else otherwise. |
248 | amb | 298 | |
249 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
250 | amb | 298 | |
251 | amb | 394 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
252 | amb | 298 | |
253 | amb | 394 | const char *id The contents of the 'id' attribute (or NULL if not defined). |
254 | amb | 298 | |
255 | amb | 394 | const char *lat The contents of the 'lat' attribute (or NULL if not defined). |
256 | amb | 298 | |
257 | amb | 394 | const char *lon The contents of the 'lon' attribute (or NULL if not defined). |
258 | ++++++++++++++++++++++++++++++++++++++*/ | ||
259 | amb | 2 | |
260 | amb | 394 | static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon) |
261 | { | ||
262 | amb | 469 | static node_t node_id; |
263 | static double latitude,longitude; | ||
264 | |||
265 | amb | 394 | if(_type_&XMLPARSE_TAG_START) |
266 | { | ||
267 | amb | 775 | long long llid; |
268 | amb | 394 | nnodes++; |
269 | |||
270 | amb | 757 | if(!(nnodes%10000)) |
271 | amb | 791 | printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations); |
272 | amb | 2 | |
273 | amb | 469 | current_tags=NewTagList(); |
274 | |||
275 | amb | 394 | /* Handle the node information */ |
276 | amb | 2 | |
277 | amb | 775 | XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */ |
278 | node_id=(node_t)llid; | ||
279 | assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */ | ||
280 | |||
281 | amb | 812 | XMLPARSE_ASSERT_FLOATING(_tag_,lat); latitude =atof(lat); |
282 | amb | 775 | XMLPARSE_ASSERT_FLOATING(_tag_,lon); longitude=atof(lon); |
283 | amb | 469 | } |
284 | amb | 2 | |
285 | amb | 469 | if(_type_&XMLPARSE_TAG_END) |
286 | { | ||
287 | TagList *result=ApplyTaggingRules(&NodeRules,current_tags); | ||
288 | amb | 2 | |
289 | amb | 469 | process_node_tags(result,node_id,latitude,longitude); |
290 | |||
291 | DeleteTagList(current_tags); | ||
292 | DeleteTagList(result); | ||
293 | amb | 394 | } |
294 | amb | 2 | |
295 | amb | 394 | return(0); |
296 | } | ||
297 | amb | 2 | |
298 | |||
299 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
300 | The function that is called when the ndType XSD type is seen | ||
301 | amb | 313 | |
302 | amb | 394 | int ndType_function Returns 0 if no error occured or something else otherwise. |
303 | amb | 2 | |
304 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
305 | amb | 297 | |
306 | amb | 394 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
307 | amb | 2 | |
308 | amb | 394 | const char *ref The contents of the 'ref' attribute (or NULL if not defined). |
309 | ++++++++++++++++++++++++++++++++++++++*/ | ||
310 | amb | 2 | |
311 | amb | 394 | static int ndType_function(const char *_tag_,int _type_,const char *ref) |
312 | { | ||
313 | if(_type_&XMLPARSE_TAG_START) | ||
314 | { | ||
315 | amb | 775 | long long llid; |
316 | amb | 394 | node_t node_id; |
317 | amb | 2 | |
318 | amb | 775 | XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */ |
319 | node_id=(node_t)llid; | ||
320 | assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */ | ||
321 | amb | 298 | |
322 | amb | 498 | if(way_nnodes && (way_nnodes%256)==0) |
323 | amb | 394 | way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t)); |
324 | amb | 8 | |
325 | amb | 394 | way_nodes[way_nnodes++]=node_id; |
326 | } | ||
327 | amb | 51 | |
328 | amb | 394 | return(0); |
329 | } | ||
330 | amb | 308 | |
331 | amb | 298 | |
332 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
333 | The function that is called when the memberType XSD type is seen | ||
334 | amb | 298 | |
335 | amb | 394 | int memberType_function Returns 0 if no error occured or something else otherwise. |
336 | amb | 298 | |
337 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
338 | amb | 183 | |
339 | amb | 394 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
340 | amb | 298 | |
341 | amb | 394 | const char *type The contents of the 'type' attribute (or NULL if not defined). |
342 | amb | 183 | |
343 | amb | 394 | const char *ref The contents of the 'ref' attribute (or NULL if not defined). |
344 | amb | 298 | |
345 | amb | 394 | const char *role The contents of the 'role' attribute (or NULL if not defined). |
346 | ++++++++++++++++++++++++++++++++++++++*/ | ||
347 | amb | 183 | |
348 | amb | 498 | static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role) |
349 | { | ||
350 | if(_type_&XMLPARSE_TAG_START) | ||
351 | { | ||
352 | amb | 775 | long long llid; |
353 | |||
354 | amb | 498 | XMLPARSE_ASSERT_STRING(_tag_,type); |
355 | amb | 775 | XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */ |
356 | amb | 298 | |
357 | amb | 498 | if(!strcmp(type,"node")) |
358 | { | ||
359 | amb | 775 | node_t node_id; |
360 | amb | 298 | |
361 | amb | 775 | node_id=(node_t)llid; |
362 | assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */ | ||
363 | |||
364 | amb | 498 | if(relation_nnodes && (relation_nnodes%256)==0) |
365 | relation_nodes=(node_t*)realloc((void*)relation_nodes,(relation_nnodes+256)*sizeof(node_t)); | ||
366 | |||
367 | relation_nodes[relation_nnodes++]=node_id; | ||
368 | amb | 540 | |
369 | if(role) | ||
370 | { | ||
371 | if(!strcmp(role,"via")) | ||
372 | relation_via=node_id; | ||
373 | } | ||
374 | amb | 498 | } |
375 | else if(!strcmp(type,"way")) | ||
376 | { | ||
377 | amb | 775 | way_t way_id; |
378 | amb | 498 | |
379 | amb | 775 | way_id=(way_t)llid; |
380 | assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */ | ||
381 | |||
382 | amb | 498 | if(relation_nways && (relation_nways%256)==0) |
383 | relation_ways=(way_t*)realloc((void*)relation_ways,(relation_nways+256)*sizeof(way_t)); | ||
384 | |||
385 | relation_ways[relation_nways++]=way_id; | ||
386 | amb | 540 | |
387 | if(role) | ||
388 | { | ||
389 | if(!strcmp(role,"from")) | ||
390 | relation_from=way_id; | ||
391 | if(!strcmp(role,"to")) | ||
392 | relation_to=way_id; | ||
393 | } | ||
394 | amb | 498 | } |
395 | else if(!strcmp(type,"relation")) | ||
396 | { | ||
397 | amb | 775 | relation_t relation_id; |
398 | amb | 498 | |
399 | amb | 775 | relation_id=(relation_t)llid; |
400 | assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */ | ||
401 | |||
402 | amb | 498 | if(relation_nrelations && (relation_nrelations%256)==0) |
403 | relation_relations=(relation_t*)realloc((void*)relation_relations,(relation_nrelations+256)*sizeof(relation_t)); | ||
404 | |||
405 | relation_relations[relation_nrelations++]=relation_id; | ||
406 | } | ||
407 | } | ||
408 | |||
409 | return(0); | ||
410 | } | ||
411 | |||
412 | |||
413 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
414 | The function that is called when the wayType XSD type is seen | ||
415 | amb | 298 | |
416 | amb | 394 | int wayType_function Returns 0 if no error occured or something else otherwise. |
417 | amb | 298 | |
418 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
419 | amb | 51 | |
420 | amb | 394 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
421 | amb | 51 | |
422 | amb | 394 | const char *id The contents of the 'id' attribute (or NULL if not defined). |
423 | ++++++++++++++++++++++++++++++++++++++*/ | ||
424 | amb | 51 | |
425 | amb | 394 | static int wayType_function(const char *_tag_,int _type_,const char *id) |
426 | { | ||
427 | static way_t way_id; | ||
428 | amb | 299 | |
429 | amb | 394 | if(_type_&XMLPARSE_TAG_START) |
430 | { | ||
431 | amb | 775 | long long llid; |
432 | |||
433 | amb | 394 | nways++; |
434 | amb | 51 | |
435 | amb | 394 | if(!(nways%1000)) |
436 | amb | 791 | printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations); |
437 | amb | 51 | |
438 | amb | 401 | current_tags=NewTagList(); |
439 | amb | 498 | |
440 | amb | 394 | way_nnodes=0; |
441 | amb | 298 | |
442 | amb | 394 | /* Handle the way information */ |
443 | amb | 313 | |
444 | amb | 775 | XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */ |
445 | |||
446 | way_id=(way_t)llid; | ||
447 | assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */ | ||
448 | amb | 394 | } |
449 | amb | 196 | |
450 | amb | 394 | if(_type_&XMLPARSE_TAG_END) |
451 | { | ||
452 | amb | 401 | TagList *result=ApplyTaggingRules(&WayRules,current_tags); |
453 | amb | 314 | |
454 | amb | 394 | process_way_tags(result,way_id); |
455 | amb | 2 | |
456 | amb | 401 | DeleteTagList(current_tags); |
457 | amb | 394 | DeleteTagList(result); |
458 | } | ||
459 | |||
460 | return(0); | ||
461 | } | ||
462 | |||
463 | |||
464 | /*++++++++++++++++++++++++++++++++++++++ | ||
465 | The function that is called when the relationType XSD type is seen | ||
466 | |||
467 | int relationType_function Returns 0 if no error occured or something else otherwise. | ||
468 | |||
469 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
470 | |||
471 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
472 | |||
473 | const char *id The contents of the 'id' attribute (or NULL if not defined). | ||
474 | ++++++++++++++++++++++++++++++++++++++*/ | ||
475 | |||
476 | static int relationType_function(const char *_tag_,int _type_,const char *id) | ||
477 | { | ||
478 | amb | 498 | static relation_t relation_id; |
479 | |||
480 | amb | 394 | if(_type_&XMLPARSE_TAG_START) |
481 | { | ||
482 | amb | 775 | long long llid; |
483 | |||
484 | amb | 394 | nrelations++; |
485 | |||
486 | if(!(nrelations%1000)) | ||
487 | amb | 791 | printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations); |
488 | amb | 394 | |
489 | amb | 498 | current_tags=NewTagList(); |
490 | |||
491 | relation_nnodes=relation_nways=relation_nrelations=0; | ||
492 | |||
493 | amb | 755 | relation_from=NO_WAY_ID; |
494 | relation_to=NO_WAY_ID; | ||
495 | relation_via=NO_NODE_ID; | ||
496 | amb | 540 | |
497 | amb | 498 | /* Handle the relation information */ |
498 | |||
499 | amb | 775 | XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */ |
500 | |||
501 | relation_id=(relation_t)llid; | ||
502 | assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */ | ||
503 | amb | 2 | } |
504 | |||
505 | amb | 498 | if(_type_&XMLPARSE_TAG_END) |
506 | { | ||
507 | TagList *result=ApplyTaggingRules(&RelationRules,current_tags); | ||
508 | amb | 2 | |
509 | amb | 498 | process_relation_tags(result,relation_id); |
510 | |||
511 | DeleteTagList(current_tags); | ||
512 | DeleteTagList(result); | ||
513 | } | ||
514 | |||
515 | amb | 2 | return(0); |
516 | } | ||
517 | |||
518 | |||
519 | /*++++++++++++++++++++++++++++++++++++++ | ||
520 | amb | 394 | The function that is called when the osmType XSD type is seen |
521 | amb | 2 | |
522 | amb | 394 | int osmType_function Returns 0 if no error occured or something else otherwise. |
523 | amb | 2 | |
524 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
525 | amb | 2 | |
526 | amb | 394 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
527 | ++++++++++++++++++++++++++++++++++++++*/ | ||
528 | |||
529 | //static int osmType_function(const char *_tag_,int _type_) | ||
530 | //{ | ||
531 | // return(0); | ||
532 | //} | ||
533 | |||
534 | |||
535 | /*++++++++++++++++++++++++++++++++++++++ | ||
536 | The function that is called when the XML declaration is seen | ||
537 | |||
538 | int xmlDeclaration_function Returns 0 if no error occured or something else otherwise. | ||
539 | |||
540 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
541 | |||
542 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
543 | |||
544 | const char *version The contents of the 'version' attribute (or NULL if not defined). | ||
545 | |||
546 | const char *encoding The contents of the 'encoding' attribute (or NULL if not defined). | ||
547 | ++++++++++++++++++++++++++++++++++++++*/ | ||
548 | |||
549 | //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding) | ||
550 | //{ | ||
551 | // return(0); | ||
552 | //} | ||
553 | |||
554 | |||
555 | /*++++++++++++++++++++++++++++++++++++++ | ||
556 | Parse an OSM XML file (from JOSM or planet download). | ||
557 | |||
558 | int ParseOSM Returns 0 if OK or something else in case of an error. | ||
559 | |||
560 | amb | 2 | FILE *file The file to read from. |
561 | amb | 394 | |
562 | amb | 498 | NodesX *OSMNodes The data structure of nodes to fill in. |
563 | amb | 394 | |
564 | amb | 498 | SegmentsX *OSMSegments The data structure of segments to fill in. |
565 | amb | 394 | |
566 | amb | 498 | WaysX *OSMWays The data structure of ways to fill in. |
567 | |||
568 | RelationsX *OSMRelations The data structure of relations to fill in. | ||
569 | amb | 2 | ++++++++++++++++++++++++++++++++++++++*/ |
570 | |||
571 | amb | 498 | int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations) |
572 | amb | 2 | { |
573 | amb | 394 | int retval; |
574 | amb | 2 | |
575 | amb | 498 | /* Copy the function parameters and initialise the variables. */ |
576 | amb | 2 | |
577 | amb | 394 | nodes=OSMNodes; |
578 | segments=OSMSegments; | ||
579 | ways=OSMWays; | ||
580 | amb | 498 | relations=OSMRelations; |
581 | amb | 394 | |
582 | amb | 498 | way_nodes=(node_t*)malloc(256*sizeof(node_t)); |
583 | |||
584 | relation_nodes =(node_t *)malloc(256*sizeof(node_t)); | ||
585 | relation_ways =(way_t *)malloc(256*sizeof(way_t)); | ||
586 | relation_relations=(relation_t*)malloc(256*sizeof(relation_t)); | ||
587 | |||
588 | /* Parse the file */ | ||
589 | |||
590 | amb | 394 | nnodes=0,nways=0,nrelations=0; |
591 | |||
592 | amb | 519 | printf_first("Reading: Lines=0 Nodes=0 Ways=0 Relations=0"); |
593 | amb | 394 | |
594 | retval=ParseXML(file,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE); | ||
595 | |||
596 | amb | 791 | printf_last("Read: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations); |
597 | amb | 394 | |
598 | amb | 796 | free(way_nodes); |
599 | |||
600 | free(relation_nodes); | ||
601 | free(relation_ways); | ||
602 | free(relation_relations); | ||
603 | |||
604 | amb | 394 | return(retval); |
605 | } | ||
606 | |||
607 | |||
608 | /*++++++++++++++++++++++++++++++++++++++ | ||
609 | amb | 469 | Process the tags associated with a node. |
610 | |||
611 | TagList *tags The list of node tags. | ||
612 | |||
613 | node_t id The id of the node. | ||
614 | |||
615 | double latitude The latitude of the node. | ||
616 | |||
617 | double longitude The longitude of the node. | ||
618 | ++++++++++++++++++++++++++++++++++++++*/ | ||
619 | |||
620 | static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude) | ||
621 | { | ||
622 | amb | 529 | transports_t allow=Transports_ALL; |
623 | amb | 538 | uint16_t flags=0; |
624 | amb | 469 | int i; |
625 | |||
626 | /* Parse the tags */ | ||
627 | |||
628 | for(i=0;i<tags->ntags;i++) | ||
629 | { | ||
630 | char *k=tags->k[i]; | ||
631 | char *v=tags->v[i]; | ||
632 | |||
633 | switch(*k) | ||
634 | { | ||
635 | case 'b': | ||
636 | if(!strcmp(k,"bicycle")) | ||
637 | amb | 812 | { |
638 | if(ISFALSE(v)) | ||
639 | amb | 529 | allow&=~Transports_Bicycle; |
640 | amb | 812 | else if(!ISTRUE(v)) |
641 | logerror("Node %"Pnode_t" has an unrecognised tag value 'bicycle' = '%s' (after processing tagging rules).\n",id,v); | ||
642 | } | ||
643 | amb | 469 | |
644 | break; | ||
645 | |||
646 | case 'f': | ||
647 | if(!strcmp(k,"foot")) | ||
648 | amb | 812 | { |
649 | if(ISFALSE(v)) | ||
650 | amb | 529 | allow&=~Transports_Foot; |
651 | amb | 812 | else if(!ISTRUE(v)) |
652 | logerror("Node %"Pnode_t" has an unrecognised tag value 'foot' = '%s' (after processing tagging rules).\n",id,v); | ||
653 | } | ||
654 | amb | 469 | |
655 | break; | ||
656 | |||
657 | case 'g': | ||
658 | if(!strcmp(k,"goods")) | ||
659 | amb | 812 | { |
660 | if(ISFALSE(v)) | ||
661 | amb | 529 | allow&=~Transports_Goods; |
662 | amb | 812 | else if(!ISTRUE(v)) |
663 | logerror("Node %"Pnode_t" has an unrecognised tag value 'goods' = '%s' (after processing tagging rules).\n",id,v); | ||
664 | } | ||
665 | amb | 469 | |
666 | break; | ||
667 | |||
668 | case 'h': | ||
669 | amb | 537 | if(!strcmp(k,"highway")) |
670 | if(!strcmp(v,"mini_roundabout")) | ||
671 | amb | 538 | flags|=NODE_MINIRNDBT; |
672 | amb | 537 | |
673 | amb | 469 | if(!strcmp(k,"horse")) |
674 | amb | 812 | { |
675 | if(ISFALSE(v)) | ||
676 | amb | 529 | allow&=~Transports_Horse; |
677 | amb | 812 | else if(!ISTRUE(v)) |
678 | logerror("Node %"Pnode_t" has an unrecognised tag value 'horse' = '%s' (after processing tagging rules).\n",id,v); | ||
679 | } | ||
680 | amb | 469 | |
681 | if(!strcmp(k,"hgv")) | ||
682 | amb | 812 | { |
683 | if(ISFALSE(v)) | ||
684 | amb | 529 | allow&=~Transports_HGV; |
685 | amb | 812 | else if(!ISTRUE(v)) |
686 | logerror("Node %"Pnode_t" has an unrecognised tag value 'hgv' = '%s' (after processing tagging rules).\n",id,v); | ||
687 | } | ||
688 | amb | 469 | |
689 | break; | ||
690 | |||
691 | case 'm': | ||
692 | if(!strcmp(k,"moped")) | ||
693 | amb | 812 | { |
694 | if(ISFALSE(v)) | ||
695 | amb | 529 | allow&=~Transports_Moped; |
696 | amb | 812 | else if(!ISTRUE(v)) |
697 | logerror("Node %"Pnode_t" has an unrecognised tag value 'moped' = '%s' (after processing tagging rules).\n",id,v); | ||
698 | } | ||
699 | amb | 469 | |
700 | if(!strcmp(k,"motorbike")) | ||
701 | amb | 812 | { |
702 | if(ISFALSE(v)) | ||
703 | amb | 529 | allow&=~Transports_Motorbike; |
704 | amb | 812 | else if(!ISTRUE(v)) |
705 | logerror("Node %"Pnode_t" has an unrecognised tag value 'motorbike' = '%s' (after processing tagging rules).\n",id,v); | ||
706 | } | ||
707 | amb | 469 | |
708 | if(!strcmp(k,"motorcar")) | ||
709 | amb | 812 | { |
710 | if(ISFALSE(v)) | ||
711 | amb | 529 | allow&=~Transports_Motorcar; |
712 | amb | 812 | else if(!ISTRUE(v)) |
713 | logerror("Node %"Pnode_t" has an unrecognised tag value 'motorcar' = '%s' (after processing tagging rules).\n",id,v); | ||
714 | } | ||
715 | amb | 469 | |
716 | break; | ||
717 | |||
718 | case 'p': | ||
719 | if(!strcmp(k,"psv")) | ||
720 | amb | 812 | { |
721 | if(ISFALSE(v)) | ||
722 | amb | 529 | allow&=~Transports_PSV; |
723 | amb | 812 | else if(!ISTRUE(v)) |
724 | logerror("Node %"Pnode_t" has an unrecognised tag value 'psv' = '%s' (after processing tagging rules).\n",id,v); | ||
725 | } | ||
726 | amb | 469 | |
727 | break; | ||
728 | |||
729 | case 'w': | ||
730 | if(!strcmp(k,"wheelchair")) | ||
731 | amb | 812 | { |
732 | if(ISFALSE(v)) | ||
733 | amb | 529 | allow&=~Transports_Wheelchair; |
734 | amb | 812 | else if(!ISTRUE(v)) |
735 | logerror("Node %"Pnode_t" has an unrecognised tag value 'wheelchair' = '%s' (after processing tagging rules).\n",id,v); | ||
736 | } | ||
737 | amb | 469 | |
738 | break; | ||
739 | |||
740 | default: | ||
741 | amb | 812 | logerror("Node %"Pnode_t" has an unrecognised tag '%s' = '%s' (after processing tagging rules).\n",id,k,v); |
742 | amb | 469 | } |
743 | } | ||
744 | |||
745 | /* Create the node */ | ||
746 | |||
747 | amb | 538 | AppendNode(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,flags); |
748 | amb | 469 | } |
749 | |||
750 | |||
751 | /*++++++++++++++++++++++++++++++++++++++ | ||
752 | amb | 394 | Process the tags associated with a way. |
753 | |||
754 | TagList *tags The list of way tags. | ||
755 | |||
756 | way_t id The id of the way. | ||
757 | ++++++++++++++++++++++++++++++++++++++*/ | ||
758 | |||
759 | static void process_way_tags(TagList *tags,way_t id) | ||
760 | { | ||
761 | Way way={0}; | ||
762 | amb | 536 | int oneway=0; |
763 | amb | 812 | char *name=NULL,*ref=NULL,*refname=NULL; |
764 | amb | 394 | int i; |
765 | |||
766 | /* Parse the tags */ | ||
767 | |||
768 | for(i=0;i<tags->ntags;i++) | ||
769 | amb | 2 | { |
770 | amb | 394 | char *k=tags->k[i]; |
771 | char *v=tags->v[i]; | ||
772 | amb | 2 | |
773 | amb | 394 | switch(*k) |
774 | { | ||
775 | case 'b': | ||
776 | if(!strcmp(k,"bicycle")) | ||
777 | amb | 812 | { |
778 | amb | 394 | if(ISTRUE(v)) |
779 | amb | 529 | way.allow|= Transports_Bicycle; |
780 | amb | 812 | else if(!ISFALSE(v)) |
781 | logerror("Way %"Pway_t" has an unrecognised tag value 'bicycle' = '%s' (after processing tagging rules).\n",id,v); | ||
782 | } | ||
783 | amb | 394 | |
784 | amb | 498 | if(!strcmp(k,"bicycleroute")) |
785 | amb | 812 | { |
786 | amb | 498 | if(ISTRUE(v)) |
787 | way.props|=Properties_BicycleRoute; | ||
788 | amb | 812 | else if(!ISFALSE(v)) |
789 | logerror("Way %"Pway_t" has an unrecognised tag value 'bicycleroute' = '%s' (after processing tagging rules).\n",id,v); | ||
790 | } | ||
791 | amb | 498 | |
792 | amb | 394 | if(!strcmp(k,"bridge")) |
793 | amb | 812 | { |
794 | amb | 394 | if(ISTRUE(v)) |
795 | way.props|=Properties_Bridge; | ||
796 | amb | 812 | else if(!ISFALSE(v)) |
797 | logerror("Way %"Pway_t" has an unrecognised tag value 'bridge' = '%s' (after processing tagging rules).\n",id,v); | ||
798 | } | ||
799 | amb | 394 | |
800 | amb | 2 | break; |
801 | amb | 394 | |
802 | case 'f': | ||
803 | if(!strcmp(k,"foot")) | ||
804 | amb | 812 | { |
805 | amb | 394 | if(ISTRUE(v)) |
806 | amb | 529 | way.allow|= Transports_Foot; |
807 | amb | 812 | else if(!ISFALSE(v)) |
808 | logerror("Way %"Pway_t" has an unrecognised tag value 'foot' = '%s' (after processing tagging rules).\n",id,v); | ||
809 | } | ||
810 | amb | 394 | |
811 | amb | 498 | if(!strcmp(k,"footroute")) |
812 | amb | 812 | { |
813 | amb | 498 | if(ISTRUE(v)) |
814 | way.props|=Properties_FootRoute; | ||
815 | amb | 812 | else if(!ISFALSE(v)) |
816 | logerror("Way %"Pway_t" has an unrecognised tag value 'footroute' = '%s' (after processing tagging rules).\n",id,v); | ||
817 | } | ||
818 | amb | 498 | |
819 | amb | 394 | break; |
820 | |||
821 | case 'g': | ||
822 | if(!strcmp(k,"goods")) | ||
823 | amb | 812 | { |
824 | amb | 394 | if(ISTRUE(v)) |
825 | amb | 529 | way.allow|=Transports_Goods; |
826 | amb | 812 | else if(!ISFALSE(v)) |
827 | logerror("Way %"Pway_t" has an unrecognised tag value 'goods' = '%s' (after processing tagging rules).\n",id,v); | ||
828 | } | ||
829 | amb | 394 | |
830 | break; | ||
831 | |||
832 | case 'h': | ||
833 | if(!strcmp(k,"highway")) | ||
834 | amb | 812 | { |
835 | amb | 394 | way.type=HighwayType(v); |
836 | |||
837 | amb | 812 | if(way.type==Way_Count) |
838 | logerror("Way %"Pway_t" has an unrecognised highway type '%s' (after processing tagging rules).\n",id,v); | ||
839 | } | ||
840 | |||
841 | amb | 394 | if(!strcmp(k,"horse")) |
842 | amb | 812 | { |
843 | amb | 394 | if(ISTRUE(v)) |
844 | amb | 529 | way.allow|=Transports_Horse; |
845 | amb | 812 | else if(!ISFALSE(v)) |
846 | logerror("Way %"Pway_t" has an unrecognised tag value 'horse' = '%s' (after processing tagging rules).\n",id,v); | ||
847 | } | ||
848 | amb | 394 | |
849 | if(!strcmp(k,"hgv")) | ||
850 | amb | 812 | { |
851 | amb | 394 | if(ISTRUE(v)) |
852 | amb | 529 | way.allow|=Transports_HGV; |
853 | amb | 812 | else if(!ISFALSE(v)) |
854 | logerror("Way %"Pway_t" has an unrecognised tag value 'hgv' = '%s' (after processing tagging rules).\n",id,v); | ||
855 | } | ||
856 | amb | 394 | |
857 | break; | ||
858 | |||
859 | case 'm': | ||
860 | if(!strcmp(k,"maxspeed")) | ||
861 | amb | 812 | way.speed=kph_to_speed(parse_speed(id,k,v)); |
862 | amb | 394 | |
863 | if(!strcmp(k,"maxweight")) | ||
864 | amb | 812 | way.weight=tonnes_to_weight(parse_weight(id,k,v)); |
865 | amb | 394 | |
866 | if(!strcmp(k,"maxheight")) | ||
867 | amb | 812 | way.height=metres_to_height(parse_length(id,k,v)); |
868 | amb | 394 | |
869 | if(!strcmp(k,"maxwidth")) | ||
870 | amb | 812 | way.width=metres_to_height(parse_length(id,k,v)); |
871 | amb | 394 | |
872 | if(!strcmp(k,"maxlength")) | ||
873 | amb | 812 | way.length=metres_to_height(parse_length(id,k,v)); |
874 | amb | 394 | |
875 | if(!strcmp(k,"moped")) | ||
876 | amb | 812 | { |
877 | amb | 394 | if(ISTRUE(v)) |
878 | amb | 529 | way.allow|=Transports_Moped; |
879 | amb | 812 | else if(!ISFALSE(v)) |
880 | logerror("Way %"Pway_t" has an unrecognised tag value 'moped' = '%s' (after processing tagging rules).\n",id,v); | ||
881 | } | ||
882 | amb | 394 | |
883 | if(!strcmp(k,"motorbike")) | ||
884 | amb | 812 | { |
885 | amb | 394 | if(ISTRUE(v)) |
886 | amb | 529 | way.allow|=Transports_Motorbike; |
887 | amb | 812 | else if(!ISFALSE(v)) |
888 | logerror("Way %"Pway_t" has an unrecognised tag value 'motorbike' = '%s' (after processing tagging rules).\n",id,v); | ||
889 | } | ||
890 | amb | 394 | |
891 | if(!strcmp(k,"motorcar")) | ||
892 | amb | 812 | { |
893 | amb | 394 | if(ISTRUE(v)) |
894 | amb | 529 | way.allow|=Transports_Motorcar; |
895 | amb | 812 | else if(!ISFALSE(v)) |
896 | logerror("Way %"Pway_t" has an unrecognised tag value 'motorcar' = '%s' (after processing tagging rules).\n",id,v); | ||
897 | } | ||
898 | amb | 394 | |
899 | if(!strcmp(k,"multilane")) | ||
900 | amb | 812 | { |
901 | amb | 394 | if(ISTRUE(v)) |
902 | way.props|=Properties_Multilane; | ||
903 | amb | 812 | else if(!ISFALSE(v)) |
904 | logerror("Way %"Pway_t" has an unrecognised tag value 'multilane' = '%s' (after processing tagging rules).\n",id,v); | ||
905 | } | ||
906 | amb | 394 | |
907 | break; | ||
908 | |||
909 | case 'n': | ||
910 | if(!strcmp(k,"name")) | ||
911 | name=v; | ||
912 | |||
913 | break; | ||
914 | |||
915 | case 'o': | ||
916 | if(!strcmp(k,"oneway")) | ||
917 | { | ||
918 | if(ISTRUE(v)) | ||
919 | oneway=1; | ||
920 | else if(!strcmp(v,"-1")) | ||
921 | oneway=-1; | ||
922 | amb | 812 | else if(!ISFALSE(v)) |
923 | logerror("Way %"Pway_t" has an unrecognised tag value 'oneway' = '%s' (after processing tagging rules).\n",id,v); | ||
924 | amb | 394 | } |
925 | |||
926 | break; | ||
927 | |||
928 | case 'p': | ||
929 | if(!strcmp(k,"paved")) | ||
930 | amb | 812 | { |
931 | amb | 394 | if(ISTRUE(v)) |
932 | way.props|=Properties_Paved; | ||
933 | amb | 812 | else if(!ISFALSE(v)) |
934 | logerror("Way %"Pway_t" has an unrecognised tag value 'paved' = '%s' (after processing tagging rules).\n",id,v); | ||
935 | } | ||
936 | amb | 394 | |
937 | if(!strcmp(k,"psv")) | ||
938 | amb | 812 | { |
939 | amb | 394 | if(ISTRUE(v)) |
940 | amb | 529 | way.allow|=Transports_PSV; |
941 | amb | 812 | else if(!ISFALSE(v)) |
942 | logerror("Way %"Pway_t" has an unrecognised tag value 'psv' = '%s' (after processing tagging rules).\n",id,v); | ||
943 | } | ||
944 | amb | 394 | |
945 | break; | ||
946 | |||
947 | case 'r': | ||
948 | if(!strcmp(k,"ref")) | ||
949 | ref=v; | ||
950 | |||
951 | break; | ||
952 | |||
953 | case 't': | ||
954 | if(!strcmp(k,"tunnel")) | ||
955 | amb | 812 | { |
956 | amb | 394 | if(ISTRUE(v)) |
957 | way.props|=Properties_Tunnel; | ||
958 | amb | 812 | else if(!ISFALSE(v)) |
959 | logerror("Way %"Pway_t" has an unrecognised tag value 'tunnel' = '%s' (after processing tagging rules).\n",id,v); | ||
960 | } | ||
961 | amb | 394 | |
962 | break; | ||
963 | |||
964 | case 'w': | ||
965 | if(!strcmp(k,"wheelchair")) | ||
966 | amb | 812 | { |
967 | amb | 394 | if(ISTRUE(v)) |
968 | amb | 529 | way.allow|=Transports_Wheelchair; |
969 | amb | 812 | else if(!ISFALSE(v)) |
970 | logerror("Way %"Pway_t" has an unrecognised tag value 'wheelchair' = '%s' (after processing tagging rules).\n",id,v); | ||
971 | } | ||
972 | amb | 394 | |
973 | break; | ||
974 | |||
975 | default: | ||
976 | amb | 812 | logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after processing tagging rules).\n",id,k,v); |
977 | amb | 394 | } |
978 | amb | 2 | } |
979 | |||
980 | amb | 394 | /* Create the way */ |
981 | amb | 2 | |
982 | amb | 812 | if(way.type==0 || way.type==Way_Count) |
983 | return; | ||
984 | |||
985 | if(!way.allow) | ||
986 | return; | ||
987 | |||
988 | if(way_nnodes==0) | ||
989 | amb | 394 | { |
990 | amb | 812 | logerror("Way %"Pway_t" has no nodes.\n",id); |
991 | amb | 394 | |
992 | amb | 812 | return; |
993 | } | ||
994 | amb | 394 | |
995 | amb | 812 | if(oneway) |
996 | way.type|=Way_OneWay; | ||
997 | amb | 394 | |
998 | amb | 812 | if(ref && name) |
999 | { | ||
1000 | refname=(char*)malloc(strlen(ref)+strlen(name)+4); | ||
1001 | sprintf(refname,"%s (%s)",name,ref); | ||
1002 | } | ||
1003 | else if(ref && !name) | ||
1004 | refname=ref; | ||
1005 | else if(!ref && name) | ||
1006 | refname=name; | ||
1007 | else /* if(!ref && !name) */ | ||
1008 | refname=""; | ||
1009 | amb | 394 | |
1010 | amb | 812 | AppendWay(ways,id,&way,refname); |
1011 | amb | 394 | |
1012 | amb | 812 | if(ref && name) |
1013 | free(refname); | ||
1014 | amb | 394 | |
1015 | amb | 812 | for(i=1;i<way_nnodes;i++) |
1016 | { | ||
1017 | node_t from=way_nodes[i-1]; | ||
1018 | node_t to =way_nodes[i]; | ||
1019 | |||
1020 | if(oneway>0) | ||
1021 | AppendSegment(segments,id,from,to,ONEWAY_1TO2); | ||
1022 | else if(oneway<0) | ||
1023 | AppendSegment(segments,id,from,to,ONEWAY_2TO1); | ||
1024 | else | ||
1025 | AppendSegment(segments,id,from,to,0); | ||
1026 | amb | 394 | } |
1027 | amb | 2 | } |
1028 | amb | 498 | |
1029 | |||
1030 | /*++++++++++++++++++++++++++++++++++++++ | ||
1031 | Process the tags associated with a relation. | ||
1032 | |||
1033 | TagList *tags The list of relation tags. | ||
1034 | |||
1035 | relation_t id The id of the relation. | ||
1036 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1037 | |||
1038 | static void process_relation_tags(TagList *tags,relation_t id) | ||
1039 | { | ||
1040 | amb | 529 | transports_t routes=Transports_None; |
1041 | amb | 540 | transports_t except=Transports_None; |
1042 | int relation_turn_restriction=0; | ||
1043 | amb | 541 | TurnRestriction restriction=TurnRestrict_None; |
1044 | amb | 498 | int i; |
1045 | |||
1046 | /* Parse the tags */ | ||
1047 | |||
1048 | for(i=0;i<tags->ntags;i++) | ||
1049 | { | ||
1050 | char *k=tags->k[i]; | ||
1051 | char *v=tags->v[i]; | ||
1052 | |||
1053 | switch(*k) | ||
1054 | { | ||
1055 | case 'b': | ||
1056 | if(!strcmp(k,"bicycleroute")) | ||
1057 | amb | 812 | { |
1058 | amb | 498 | if(ISTRUE(v)) |
1059 | amb | 529 | routes|=Transports_Bicycle; |
1060 | amb | 812 | else if(!ISFALSE(v)) |
1061 | logerror("Relation %"Prelation_t" has an unrecognised tag value 'bicycleroute' = '%s' (after processing tagging rules).\n",id,v); | ||
1062 | } | ||
1063 | amb | 498 | |
1064 | break; | ||
1065 | |||
1066 | amb | 540 | case 'e': |
1067 | if(!strcmp(k,"except")) | ||
1068 | amb | 812 | { |
1069 | amb | 540 | for(i=1;i<Transport_Count;i++) |
1070 | if(!strstr(v,TransportName(i))) | ||
1071 | except|=TRANSPORTS(i); | ||
1072 | |||
1073 | amb | 812 | if(except==Transports_None) |
1074 | logerror("Relation %"Prelation_t" has an unrecognised tag value 'except' = '%s' (after processing tagging rules).\n",id,v); | ||
1075 | } | ||
1076 | |||
1077 | amb | 540 | break; |
1078 | |||
1079 | amb | 498 | case 'f': |
1080 | if(!strcmp(k,"footroute")) | ||
1081 | amb | 812 | { |
1082 | amb | 498 | if(ISTRUE(v)) |
1083 | amb | 529 | routes|=Transports_Foot; |
1084 | amb | 812 | else if(!ISFALSE(v)) |
1085 | logerror("Relation %"Prelation_t" has an unrecognised tag value 'footroute' = '%s' (after processing tagging rules).\n",id,v); | ||
1086 | } | ||
1087 | amb | 498 | |
1088 | break; | ||
1089 | |||
1090 | amb | 540 | case 'r': |
1091 | if(!strcmp(k,"restriction")) | ||
1092 | { | ||
1093 | amb | 541 | if(!strcmp(v,"no_right_turn" )) restriction=TurnRestrict_no_right_turn; |
1094 | if(!strcmp(v,"no_left_turn" )) restriction=TurnRestrict_no_left_turn; | ||
1095 | if(!strcmp(v,"no_u_turn" )) restriction=TurnRestrict_no_u_turn; | ||
1096 | if(!strcmp(v,"no_straight_on" )) restriction=TurnRestrict_no_straight_on; | ||
1097 | if(!strcmp(v,"only_right_turn" )) restriction=TurnRestrict_only_right_turn; | ||
1098 | if(!strcmp(v,"only_left_turn" )) restriction=TurnRestrict_only_left_turn; | ||
1099 | if(!strcmp(v,"only_straight_on")) restriction=TurnRestrict_only_straight_on; | ||
1100 | amb | 812 | |
1101 | if(restriction==TurnRestrict_None) | ||
1102 | logerror("Relation %"Prelation_t" has an unrecognised tag value 'restriction' = '%s' (after processing tagging rules).\n",id,v); | ||
1103 | amb | 540 | } |
1104 | |||
1105 | break; | ||
1106 | |||
1107 | case 't': | ||
1108 | if(!strcmp(k,"type")) | ||
1109 | amb | 812 | { |
1110 | amb | 540 | if(!strcmp(v,"restriction")) |
1111 | relation_turn_restriction=1; | ||
1112 | amb | 812 | else |
1113 | logerror("Relation %"Prelation_t" has an unrecognised tag value 'type' = '%s' (after processing tagging rules).\n",id,v); | ||
1114 | } | ||
1115 | amb | 540 | break; |
1116 | |||
1117 | amb | 498 | default: |
1118 | amb | 812 | logerror("Relation %"Prelation_t" has an unrecognised tag '%s' = '%s' (after processing tagging rules).\n",id,k,v); |
1119 | amb | 498 | } |
1120 | } | ||
1121 | |||
1122 | amb | 505 | /* Create the route relation (must store all relations that have ways or |
1123 | relations even if they are not routes because they might be referenced by | ||
1124 | other relations that are routes) */ | ||
1125 | amb | 498 | |
1126 | amb | 540 | if((relation_nways || relation_nrelations) && !relation_turn_restriction) |
1127 | amb | 498 | AppendRouteRelation(relations,id,routes, |
1128 | relation_ways,relation_nways, | ||
1129 | relation_relations,relation_nrelations); | ||
1130 | amb | 540 | |
1131 | /* Create the turn restriction relation. */ | ||
1132 | |||
1133 | amb | 812 | if(relation_turn_restriction && restriction!=TurnRestrict_None) |
1134 | { | ||
1135 | if(relation_from==NO_WAY_ID) | ||
1136 | logerror("Relation %"Prelation_t" is a turn restriction but has no 'from' way (after processing tagging rules).\n",id); | ||
1137 | else if(relation_to==NO_WAY_ID) | ||
1138 | logerror("Relation %"Prelation_t" is a turn restriction but has no 'to' way (after processing tagging rules).\n",id); | ||
1139 | else if(relation_via==NO_NODE_ID) | ||
1140 | logerror("Relation %"Prelation_t" is a turn restriction but has no 'via' node (after processing tagging rules).\n",id); | ||
1141 | else | ||
1142 | AppendTurnRestrictRelation(relations,id, | ||
1143 | relation_from,relation_to,relation_via, | ||
1144 | restriction,except); | ||
1145 | } | ||
1146 | amb | 498 | } |
1147 | amb | 812 | |
1148 | |||
1149 | /*++++++++++++++++++++++++++++++++++++++ | ||
1150 | Convert a string containing a speed into a double precision. | ||
1151 | |||
1152 | double parse_speed Returns the speed in km/h if it can be parsed. | ||
1153 | |||
1154 | way_t id The way being processed. | ||
1155 | |||
1156 | const char *k The tag key. | ||
1157 | |||
1158 | const char *v The tag value. | ||
1159 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1160 | |||
1161 | static double parse_speed(way_t id,const char *k,const char *v) | ||
1162 | { | ||
1163 | char *ev; | ||
1164 | double value=strtod(v,&ev); | ||
1165 | |||
1166 | if(v==ev) | ||
1167 | logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v); | ||
1168 | else | ||
1169 | { | ||
1170 | while(isspace(*ev)) ev++; | ||
1171 | |||
1172 | if(!strcmp(ev,"mph")) | ||
1173 | return(1.609*value); | ||
1174 | else if(*ev==0) | ||
1175 | return(value); | ||
1176 | else | ||
1177 | logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v); | ||
1178 | } | ||
1179 | |||
1180 | return(0); | ||
1181 | } | ||
1182 | |||
1183 | |||
1184 | /*++++++++++++++++++++++++++++++++++++++ | ||
1185 | Convert a string containing a weight into a double precision. | ||
1186 | |||
1187 | double parse_weight Returns the weight in tonnes if it can be parsed. | ||
1188 | |||
1189 | way_t id The way being processed. | ||
1190 | |||
1191 | const char *k The tag key. | ||
1192 | |||
1193 | const char *v The tag value. | ||
1194 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1195 | |||
1196 | static double parse_weight(way_t id,const char *k,const char *v) | ||
1197 | { | ||
1198 | char *ev; | ||
1199 | double value=strtod(v,&ev); | ||
1200 | |||
1201 | if(v==ev) | ||
1202 | logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v); | ||
1203 | else | ||
1204 | { | ||
1205 | while(isspace(*ev)) ev++; | ||
1206 | |||
1207 | if(!strcmp(ev,"kg")) | ||
1208 | return(value/1000.0); | ||
1209 | else if(*ev==0) | ||
1210 | return(value); | ||
1211 | else | ||
1212 | logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v); | ||
1213 | } | ||
1214 | |||
1215 | return(0); | ||
1216 | } | ||
1217 | |||
1218 | |||
1219 | /*++++++++++++++++++++++++++++++++++++++ | ||
1220 | Convert a string containing a length into a double precision. | ||
1221 | |||
1222 | double parse_length Returns the length in metres if it can be parsed. | ||
1223 | |||
1224 | way_t id The way being processed. | ||
1225 | |||
1226 | const char *k The tag key. | ||
1227 | |||
1228 | const char *v The tag value. | ||
1229 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1230 | |||
1231 | static double parse_length(way_t id,const char *k,const char *v) | ||
1232 | { | ||
1233 | char *ev; | ||
1234 | double value=strtod(v,&ev); | ||
1235 | |||
1236 | if(v==ev) | ||
1237 | logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v); | ||
1238 | else | ||
1239 | { | ||
1240 | int feet,inches; | ||
1241 | while(isspace(*ev)) ev++; | ||
1242 | |||
1243 | if(sscanf(v,"%d'%d\"",&feet,&inches)==2) | ||
1244 | return((feet+(double)inches/12.0)*0.254); | ||
1245 | else if(sscanf(v,"%d'",&feet)==1) | ||
1246 | return(feet*0.254); | ||
1247 | else if(!strcmp(ev,"ft") || !strcmp(ev,"feet")) | ||
1248 | return(value*0.254); | ||
1249 | else if(*ev==0) | ||
1250 | return(value); | ||
1251 | else | ||
1252 | logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v); | ||
1253 | } | ||
1254 | |||
1255 | return(0); | ||
1256 | } |
Properties
Name | Value |
---|---|
cvs:description | OSM XML file parser. |