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 1145 -
(hide annotations)
(download)
(as text)
Sat Nov 17 13:31:14 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 47952 byte(s)
Sat Nov 17 13:31:14 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 47952 byte(s)
Fix applying changes for ways (highways that have been modified to be non-highways were not added to the database so the original remains).
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 | 955 | This file Copyright 2008-2012 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 | amb | 109 | #include "nodesx.h" |
31 | #include "segmentsx.h" | ||
32 | #include "waysx.h" | ||
33 | amb | 498 | #include "relationsx.h" |
34 | |||
35 | amb | 955 | #include "osmparser.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 | 1140 | /* Constants */ |
53 | |||
54 | amb | 1145 | #define MODE_NORMAL 3 |
55 | amb | 1140 | #define MODE_CREATE 2 |
56 | #define MODE_MODIFY 1 | ||
57 | #define MODE_DELETE -1 | ||
58 | |||
59 | |||
60 | amb | 394 | /* Local variables */ |
61 | |||
62 | amb | 1145 | static int mode=MODE_NORMAL; |
63 | amb | 1140 | |
64 | amb | 790 | static index_t nnodes=0; |
65 | static index_t nways=0; | ||
66 | static index_t nrelations=0; | ||
67 | |||
68 | amb | 401 | static TagList *current_tags=NULL; |
69 | amb | 394 | |
70 | static node_t *way_nodes=NULL; | ||
71 | static int way_nnodes=0; | ||
72 | |||
73 | amb | 498 | static node_t *relation_nodes=NULL; |
74 | static int relation_nnodes=0; | ||
75 | static way_t *relation_ways=NULL; | ||
76 | static int relation_nways=0; | ||
77 | static relation_t *relation_relations=NULL; | ||
78 | static int relation_nrelations=0; | ||
79 | amb | 755 | static way_t relation_from=NO_WAY_ID; |
80 | static way_t relation_to=NO_WAY_ID; | ||
81 | static node_t relation_via=NO_NODE_ID; | ||
82 | amb | 394 | |
83 | amb | 498 | static NodesX *nodes; |
84 | static SegmentsX *segments; | ||
85 | static WaysX *ways; | ||
86 | static RelationsX *relations; | ||
87 | amb | 394 | |
88 | amb | 498 | |
89 | amb | 228 | /* Local functions */ |
90 | |||
91 | amb | 469 | static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude); |
92 | amb | 394 | static void process_way_tags(TagList *tags,way_t id); |
93 | amb | 498 | static void process_relation_tags(TagList *tags,relation_t id); |
94 | amb | 2 | |
95 | amb | 812 | static double parse_speed(way_t id,const char *k,const char *v); |
96 | static double parse_weight(way_t id,const char *k,const char *v); | ||
97 | static double parse_length(way_t id,const char *k,const char *v); | ||
98 | amb | 2 | |
99 | amb | 812 | |
100 | amb | 394 | /* The XML tag processing function prototypes */ |
101 | amb | 2 | |
102 | amb | 394 | //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding); |
103 | amb | 919 | static int osmType_function(const char *_tag_,int _type_,const char *version); |
104 | amb | 1140 | static int osmChangeType_function(const char *_tag_,int _type_,const char *version); |
105 | static int deleteType_function(const char *_tag_,int _type_); | ||
106 | static int createType_function(const char *_tag_,int _type_); | ||
107 | static int modifyType_function(const char *_tag_,int _type_); | ||
108 | amb | 394 | static int relationType_function(const char *_tag_,int _type_,const char *id); |
109 | static int wayType_function(const char *_tag_,int _type_,const char *id); | ||
110 | amb | 498 | static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role); |
111 | amb | 394 | static int ndType_function(const char *_tag_,int _type_,const char *ref); |
112 | static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon); | ||
113 | amb | 990 | static int changesetType_function(const char *_tag_,int _type_); |
114 | amb | 394 | static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v); |
115 | amb | 399 | //static int boundType_function(const char *_tag_,int _type_); |
116 | amb | 394 | //static int boundsType_function(const char *_tag_,int _type_); |
117 | amb | 2 | |
118 | amb | 26 | |
119 | amb | 394 | /* The XML tag definitions */ |
120 | amb | 26 | |
121 | amb | 394 | /*+ The boundsType type tag. +*/ |
122 | static xmltag boundsType_tag= | ||
123 | {"bounds", | ||
124 | 0, {NULL}, | ||
125 | NULL, | ||
126 | {NULL}}; | ||
127 | amb | 26 | |
128 | amb | 399 | /*+ The boundType type tag. +*/ |
129 | static xmltag boundType_tag= | ||
130 | {"bound", | ||
131 | 0, {NULL}, | ||
132 | NULL, | ||
133 | {NULL}}; | ||
134 | |||
135 | amb | 394 | /*+ The tagType type tag. +*/ |
136 | static xmltag tagType_tag= | ||
137 | {"tag", | ||
138 | 2, {"k","v"}, | ||
139 | tagType_function, | ||
140 | {NULL}}; | ||
141 | amb | 75 | |
142 | amb | 990 | /*+ The changesetType type tag. +*/ |
143 | static xmltag changesetType_tag= | ||
144 | {"changeset", | ||
145 | 0, {NULL}, | ||
146 | changesetType_function, | ||
147 | {&tagType_tag,NULL}}; | ||
148 | |||
149 | amb | 394 | /*+ The nodeType type tag. +*/ |
150 | static xmltag nodeType_tag= | ||
151 | {"node", | ||
152 | 3, {"id","lat","lon"}, | ||
153 | nodeType_function, | ||
154 | {&tagType_tag,NULL}}; | ||
155 | amb | 2 | |
156 | amb | 394 | /*+ The ndType type tag. +*/ |
157 | static xmltag ndType_tag= | ||
158 | {"nd", | ||
159 | 1, {"ref"}, | ||
160 | ndType_function, | ||
161 | {NULL}}; | ||
162 | amb | 2 | |
163 | amb | 394 | /*+ The memberType type tag. +*/ |
164 | static xmltag memberType_tag= | ||
165 | {"member", | ||
166 | 3, {"type","ref","role"}, | ||
167 | amb | 498 | memberType_function, |
168 | amb | 394 | {NULL}}; |
169 | amb | 227 | |
170 | amb | 394 | /*+ The wayType type tag. +*/ |
171 | static xmltag wayType_tag= | ||
172 | {"way", | ||
173 | 1, {"id"}, | ||
174 | wayType_function, | ||
175 | {&ndType_tag,&tagType_tag,NULL}}; | ||
176 | amb | 2 | |
177 | amb | 394 | /*+ The relationType type tag. +*/ |
178 | static xmltag relationType_tag= | ||
179 | {"relation", | ||
180 | 1, {"id"}, | ||
181 | relationType_function, | ||
182 | {&memberType_tag,&tagType_tag,NULL}}; | ||
183 | amb | 2 | |
184 | amb | 1140 | /*+ The deleteType type tag. +*/ |
185 | static xmltag deleteType_tag= | ||
186 | {"delete", | ||
187 | 0, {NULL}, | ||
188 | deleteType_function, | ||
189 | {&nodeType_tag,&wayType_tag,&relationType_tag,NULL}}; | ||
190 | |||
191 | /*+ The createType type tag. +*/ | ||
192 | static xmltag createType_tag= | ||
193 | {"create", | ||
194 | 0, {NULL}, | ||
195 | createType_function, | ||
196 | {&nodeType_tag,&wayType_tag,&relationType_tag,NULL}}; | ||
197 | |||
198 | /*+ The modifyType type tag. +*/ | ||
199 | static xmltag modifyType_tag= | ||
200 | {"modify", | ||
201 | 0, {NULL}, | ||
202 | modifyType_function, | ||
203 | {&nodeType_tag,&wayType_tag,&relationType_tag,NULL}}; | ||
204 | |||
205 | /*+ The osmChangeType type tag. +*/ | ||
206 | static xmltag osmChangeType_tag= | ||
207 | {"osmChange", | ||
208 | 1, {"version"}, | ||
209 | osmChangeType_function, | ||
210 | {&boundsType_tag,&modifyType_tag,&createType_tag,&deleteType_tag,NULL}}; | ||
211 | |||
212 | amb | 394 | /*+ The osmType type tag. +*/ |
213 | static xmltag osmType_tag= | ||
214 | {"osm", | ||
215 | amb | 919 | 1, {"version"}, |
216 | osmType_function, | ||
217 | amb | 990 | {&boundsType_tag,&boundType_tag,&changesetType_tag,&nodeType_tag,&wayType_tag,&relationType_tag,NULL}}; |
218 | amb | 2 | |
219 | amb | 394 | /*+ The xmlDeclaration type tag. +*/ |
220 | static xmltag xmlDeclaration_tag= | ||
221 | {"xml", | ||
222 | 2, {"version","encoding"}, | ||
223 | NULL, | ||
224 | {NULL}}; | ||
225 | amb | 2 | |
226 | |||
227 | amb | 1140 | /*+ The complete set of tags at the top level for OSM. +*/ |
228 | static xmltag *xml_osm_toplevel_tags[]={&xmlDeclaration_tag,&osmType_tag,NULL}; | ||
229 | amb | 2 | |
230 | amb | 1140 | /*+ The complete set of tags at the top level for OSC. +*/ |
231 | static xmltag *xml_osc_toplevel_tags[]={&xmlDeclaration_tag,&osmChangeType_tag,NULL}; | ||
232 | amb | 2 | |
233 | amb | 1140 | |
234 | amb | 394 | /* The XML tag processing functions */ |
235 | amb | 2 | |
236 | amb | 159 | |
237 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
238 | The function that is called when the boundsType XSD type is seen | ||
239 | amb | 2 | |
240 | amb | 394 | int boundsType_function Returns 0 if no error occured or something else otherwise. |
241 | amb | 2 | |
242 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
243 | amb | 203 | |
244 | 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. |
245 | ++++++++++++++++++++++++++++++++++++++*/ | ||
246 | amb | 2 | |
247 | amb | 394 | //static int boundsType_function(const char *_tag_,int _type_) |
248 | //{ | ||
249 | // return(0); | ||
250 | //} | ||
251 | amb | 2 | |
252 | amb | 6 | |
253 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
254 | amb | 399 | The function that is called when the boundType XSD type is seen |
255 | |||
256 | int boundType_function Returns 0 if no error occured or something else otherwise. | ||
257 | |||
258 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
259 | |||
260 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
261 | ++++++++++++++++++++++++++++++++++++++*/ | ||
262 | |||
263 | //static int boundType_function(const char *_tag_,int _type_) | ||
264 | //{ | ||
265 | // return(0); | ||
266 | //} | ||
267 | |||
268 | |||
269 | /*++++++++++++++++++++++++++++++++++++++ | ||
270 | amb | 394 | The function that is called when the tagType XSD type is seen |
271 | amb | 2 | |
272 | amb | 394 | int tagType_function Returns 0 if no error occured or something else otherwise. |
273 | amb | 314 | |
274 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
275 | amb | 2 | |
276 | 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. |
277 | amb | 30 | |
278 | amb | 394 | const char *k The contents of the 'k' attribute (or NULL if not defined). |
279 | amb | 30 | |
280 | amb | 394 | const char *v The contents of the 'v' attribute (or NULL if not defined). |
281 | ++++++++++++++++++++++++++++++++++++++*/ | ||
282 | amb | 30 | |
283 | amb | 394 | static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v) |
284 | { | ||
285 | amb | 401 | if(_type_&XMLPARSE_TAG_START && current_tags) |
286 | amb | 394 | { |
287 | XMLPARSE_ASSERT_STRING(_tag_,k); | ||
288 | XMLPARSE_ASSERT_STRING(_tag_,v); | ||
289 | amb | 30 | |
290 | amb | 401 | AppendTag(current_tags,k,v); |
291 | amb | 394 | } |
292 | amb | 262 | |
293 | amb | 394 | return(0); |
294 | } | ||
295 | amb | 308 | |
296 | amb | 313 | |
297 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
298 | amb | 990 | The function that is called when the changesetType XSD type is seen |
299 | |||
300 | int changesetType_function Returns 0 if no error occured or something else otherwise. | ||
301 | |||
302 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
303 | |||
304 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
305 | ++++++++++++++++++++++++++++++++++++++*/ | ||
306 | |||
307 | static int changesetType_function(const char *_tag_,int _type_) | ||
308 | { | ||
309 | current_tags=NULL; | ||
310 | |||
311 | return(0); | ||
312 | } | ||
313 | |||
314 | |||
315 | /*++++++++++++++++++++++++++++++++++++++ | ||
316 | amb | 394 | The function that is called when the nodeType XSD type is seen |
317 | amb | 313 | |
318 | amb | 394 | int nodeType_function Returns 0 if no error occured or something else otherwise. |
319 | amb | 298 | |
320 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
321 | amb | 298 | |
322 | 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. |
323 | amb | 298 | |
324 | amb | 394 | const char *id The contents of the 'id' attribute (or NULL if not defined). |
325 | amb | 298 | |
326 | amb | 394 | const char *lat The contents of the 'lat' attribute (or NULL if not defined). |
327 | amb | 298 | |
328 | amb | 394 | const char *lon The contents of the 'lon' attribute (or NULL if not defined). |
329 | ++++++++++++++++++++++++++++++++++++++*/ | ||
330 | amb | 2 | |
331 | amb | 394 | static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon) |
332 | { | ||
333 | amb | 469 | static node_t node_id; |
334 | static double latitude,longitude; | ||
335 | |||
336 | amb | 394 | if(_type_&XMLPARSE_TAG_START) |
337 | { | ||
338 | amb | 775 | long long llid; |
339 | amb | 825 | |
340 | amb | 394 | nnodes++; |
341 | |||
342 | amb | 757 | if(!(nnodes%10000)) |
343 | amb | 791 | printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations); |
344 | amb | 2 | |
345 | amb | 469 | current_tags=NewTagList(); |
346 | |||
347 | amb | 394 | /* Handle the node information */ |
348 | amb | 2 | |
349 | amb | 775 | XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */ |
350 | node_id=(node_t)llid; | ||
351 | assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */ | ||
352 | |||
353 | amb | 1140 | if(mode!=MODE_DELETE) |
354 | { | ||
355 | XMLPARSE_ASSERT_FLOATING(_tag_,lat); latitude =atof(lat); | ||
356 | XMLPARSE_ASSERT_FLOATING(_tag_,lon); longitude=atof(lon); | ||
357 | } | ||
358 | amb | 469 | } |
359 | amb | 2 | |
360 | amb | 469 | if(_type_&XMLPARSE_TAG_END) |
361 | { | ||
362 | amb | 826 | TagList *result=ApplyTaggingRules(&NodeRules,current_tags,node_id); |
363 | amb | 2 | |
364 | amb | 469 | process_node_tags(result,node_id,latitude,longitude); |
365 | |||
366 | amb | 990 | DeleteTagList(current_tags); current_tags=NULL; |
367 | amb | 469 | DeleteTagList(result); |
368 | amb | 394 | } |
369 | amb | 2 | |
370 | amb | 394 | return(0); |
371 | } | ||
372 | amb | 2 | |
373 | |||
374 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
375 | The function that is called when the ndType XSD type is seen | ||
376 | amb | 313 | |
377 | amb | 394 | int ndType_function Returns 0 if no error occured or something else otherwise. |
378 | amb | 2 | |
379 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
380 | amb | 297 | |
381 | 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. |
382 | amb | 2 | |
383 | amb | 394 | const char *ref The contents of the 'ref' attribute (or NULL if not defined). |
384 | ++++++++++++++++++++++++++++++++++++++*/ | ||
385 | amb | 2 | |
386 | amb | 394 | static int ndType_function(const char *_tag_,int _type_,const char *ref) |
387 | { | ||
388 | if(_type_&XMLPARSE_TAG_START) | ||
389 | { | ||
390 | amb | 775 | long long llid; |
391 | amb | 394 | node_t node_id; |
392 | amb | 2 | |
393 | amb | 775 | XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */ |
394 | node_id=(node_t)llid; | ||
395 | assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */ | ||
396 | amb | 298 | |
397 | amb | 498 | if(way_nnodes && (way_nnodes%256)==0) |
398 | amb | 394 | way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t)); |
399 | amb | 8 | |
400 | amb | 394 | way_nodes[way_nnodes++]=node_id; |
401 | } | ||
402 | amb | 51 | |
403 | amb | 394 | return(0); |
404 | } | ||
405 | amb | 308 | |
406 | amb | 298 | |
407 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
408 | The function that is called when the memberType XSD type is seen | ||
409 | amb | 298 | |
410 | amb | 394 | int memberType_function Returns 0 if no error occured or something else otherwise. |
411 | amb | 298 | |
412 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
413 | amb | 183 | |
414 | 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. |
415 | amb | 298 | |
416 | amb | 394 | const char *type The contents of the 'type' attribute (or NULL if not defined). |
417 | amb | 183 | |
418 | amb | 394 | const char *ref The contents of the 'ref' attribute (or NULL if not defined). |
419 | amb | 298 | |
420 | amb | 394 | const char *role The contents of the 'role' attribute (or NULL if not defined). |
421 | ++++++++++++++++++++++++++++++++++++++*/ | ||
422 | amb | 183 | |
423 | amb | 498 | static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role) |
424 | { | ||
425 | if(_type_&XMLPARSE_TAG_START) | ||
426 | { | ||
427 | amb | 775 | long long llid; |
428 | |||
429 | amb | 498 | XMLPARSE_ASSERT_STRING(_tag_,type); |
430 | amb | 775 | XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */ |
431 | amb | 298 | |
432 | amb | 498 | if(!strcmp(type,"node")) |
433 | { | ||
434 | amb | 775 | node_t node_id; |
435 | amb | 298 | |
436 | amb | 775 | node_id=(node_t)llid; |
437 | assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */ | ||
438 | |||
439 | amb | 498 | if(relation_nnodes && (relation_nnodes%256)==0) |
440 | relation_nodes=(node_t*)realloc((void*)relation_nodes,(relation_nnodes+256)*sizeof(node_t)); | ||
441 | |||
442 | relation_nodes[relation_nnodes++]=node_id; | ||
443 | amb | 540 | |
444 | if(role) | ||
445 | { | ||
446 | if(!strcmp(role,"via")) | ||
447 | relation_via=node_id; | ||
448 | } | ||
449 | amb | 498 | } |
450 | else if(!strcmp(type,"way")) | ||
451 | { | ||
452 | amb | 775 | way_t way_id; |
453 | amb | 498 | |
454 | amb | 775 | way_id=(way_t)llid; |
455 | assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */ | ||
456 | |||
457 | amb | 498 | if(relation_nways && (relation_nways%256)==0) |
458 | relation_ways=(way_t*)realloc((void*)relation_ways,(relation_nways+256)*sizeof(way_t)); | ||
459 | |||
460 | relation_ways[relation_nways++]=way_id; | ||
461 | amb | 540 | |
462 | if(role) | ||
463 | { | ||
464 | if(!strcmp(role,"from")) | ||
465 | relation_from=way_id; | ||
466 | if(!strcmp(role,"to")) | ||
467 | relation_to=way_id; | ||
468 | } | ||
469 | amb | 498 | } |
470 | else if(!strcmp(type,"relation")) | ||
471 | { | ||
472 | amb | 775 | relation_t relation_id; |
473 | amb | 498 | |
474 | amb | 775 | relation_id=(relation_t)llid; |
475 | assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */ | ||
476 | |||
477 | amb | 498 | if(relation_nrelations && (relation_nrelations%256)==0) |
478 | relation_relations=(relation_t*)realloc((void*)relation_relations,(relation_nrelations+256)*sizeof(relation_t)); | ||
479 | |||
480 | relation_relations[relation_nrelations++]=relation_id; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | return(0); | ||
485 | } | ||
486 | |||
487 | |||
488 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
489 | The function that is called when the wayType XSD type is seen | ||
490 | amb | 298 | |
491 | amb | 394 | int wayType_function Returns 0 if no error occured or something else otherwise. |
492 | amb | 298 | |
493 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
494 | amb | 51 | |
495 | 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. |
496 | amb | 51 | |
497 | amb | 394 | const char *id The contents of the 'id' attribute (or NULL if not defined). |
498 | ++++++++++++++++++++++++++++++++++++++*/ | ||
499 | amb | 51 | |
500 | amb | 394 | static int wayType_function(const char *_tag_,int _type_,const char *id) |
501 | { | ||
502 | static way_t way_id; | ||
503 | amb | 299 | |
504 | amb | 394 | if(_type_&XMLPARSE_TAG_START) |
505 | { | ||
506 | amb | 775 | long long llid; |
507 | |||
508 | amb | 394 | nways++; |
509 | amb | 51 | |
510 | amb | 394 | if(!(nways%1000)) |
511 | amb | 791 | printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations); |
512 | amb | 51 | |
513 | amb | 401 | current_tags=NewTagList(); |
514 | amb | 498 | |
515 | amb | 394 | way_nnodes=0; |
516 | amb | 298 | |
517 | amb | 394 | /* Handle the way information */ |
518 | amb | 313 | |
519 | amb | 775 | XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */ |
520 | |||
521 | way_id=(way_t)llid; | ||
522 | assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */ | ||
523 | amb | 394 | } |
524 | amb | 196 | |
525 | amb | 394 | if(_type_&XMLPARSE_TAG_END) |
526 | { | ||
527 | amb | 826 | TagList *result=ApplyTaggingRules(&WayRules,current_tags,way_id); |
528 | amb | 314 | |
529 | amb | 394 | process_way_tags(result,way_id); |
530 | amb | 2 | |
531 | amb | 990 | DeleteTagList(current_tags); current_tags=NULL; |
532 | amb | 394 | DeleteTagList(result); |
533 | } | ||
534 | |||
535 | return(0); | ||
536 | } | ||
537 | |||
538 | |||
539 | /*++++++++++++++++++++++++++++++++++++++ | ||
540 | The function that is called when the relationType XSD type is seen | ||
541 | |||
542 | int relationType_function Returns 0 if no error occured or something else otherwise. | ||
543 | |||
544 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
545 | |||
546 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
547 | |||
548 | const char *id The contents of the 'id' attribute (or NULL if not defined). | ||
549 | ++++++++++++++++++++++++++++++++++++++*/ | ||
550 | |||
551 | static int relationType_function(const char *_tag_,int _type_,const char *id) | ||
552 | { | ||
553 | amb | 498 | static relation_t relation_id; |
554 | |||
555 | amb | 394 | if(_type_&XMLPARSE_TAG_START) |
556 | { | ||
557 | amb | 775 | long long llid; |
558 | |||
559 | amb | 394 | nrelations++; |
560 | |||
561 | if(!(nrelations%1000)) | ||
562 | amb | 791 | printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations); |
563 | amb | 394 | |
564 | amb | 498 | current_tags=NewTagList(); |
565 | |||
566 | relation_nnodes=relation_nways=relation_nrelations=0; | ||
567 | |||
568 | amb | 755 | relation_from=NO_WAY_ID; |
569 | relation_to=NO_WAY_ID; | ||
570 | relation_via=NO_NODE_ID; | ||
571 | amb | 540 | |
572 | amb | 498 | /* Handle the relation information */ |
573 | |||
574 | amb | 775 | XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */ |
575 | |||
576 | relation_id=(relation_t)llid; | ||
577 | assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */ | ||
578 | amb | 2 | } |
579 | |||
580 | amb | 498 | if(_type_&XMLPARSE_TAG_END) |
581 | { | ||
582 | amb | 826 | TagList *result=ApplyTaggingRules(&RelationRules,current_tags,relation_id); |
583 | amb | 2 | |
584 | amb | 498 | process_relation_tags(result,relation_id); |
585 | |||
586 | amb | 990 | DeleteTagList(current_tags); current_tags=NULL; |
587 | amb | 498 | DeleteTagList(result); |
588 | } | ||
589 | |||
590 | amb | 2 | return(0); |
591 | } | ||
592 | |||
593 | |||
594 | /*++++++++++++++++++++++++++++++++++++++ | ||
595 | amb | 1140 | The function that is called when the deleteType XSD type is seen |
596 | |||
597 | int deleteType_function Returns 0 if no error occured or something else otherwise. | ||
598 | |||
599 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
600 | |||
601 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
602 | ++++++++++++++++++++++++++++++++++++++*/ | ||
603 | |||
604 | static int deleteType_function(const char *_tag_,int _type_) | ||
605 | { | ||
606 | if(_type_&XMLPARSE_TAG_START) | ||
607 | mode=MODE_DELETE; | ||
608 | |||
609 | return(0); | ||
610 | } | ||
611 | |||
612 | |||
613 | /*++++++++++++++++++++++++++++++++++++++ | ||
614 | The function that is called when the createType XSD type is seen | ||
615 | |||
616 | int createType_function Returns 0 if no error occured or something else otherwise. | ||
617 | |||
618 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
619 | |||
620 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
621 | ++++++++++++++++++++++++++++++++++++++*/ | ||
622 | |||
623 | static int createType_function(const char *_tag_,int _type_) | ||
624 | { | ||
625 | if(_type_&XMLPARSE_TAG_START) | ||
626 | mode=MODE_CREATE; | ||
627 | |||
628 | return(0); | ||
629 | } | ||
630 | |||
631 | |||
632 | /*++++++++++++++++++++++++++++++++++++++ | ||
633 | The function that is called when the modifyType XSD type is seen | ||
634 | |||
635 | int modifyType_function Returns 0 if no error occured or something else otherwise. | ||
636 | |||
637 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
638 | |||
639 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
640 | ++++++++++++++++++++++++++++++++++++++*/ | ||
641 | |||
642 | static int modifyType_function(const char *_tag_,int _type_) | ||
643 | { | ||
644 | if(_type_&XMLPARSE_TAG_START) | ||
645 | mode=MODE_MODIFY; | ||
646 | |||
647 | return(0); | ||
648 | } | ||
649 | |||
650 | |||
651 | /*++++++++++++++++++++++++++++++++++++++ | ||
652 | The function that is called when the osmChangeType XSD type is seen | ||
653 | |||
654 | int osmChangeType_function Returns 0 if no error occured or something else otherwise. | ||
655 | |||
656 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
657 | |||
658 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
659 | |||
660 | const char *version The contents of the 'version' attribute (or NULL if not defined). | ||
661 | ++++++++++++++++++++++++++++++++++++++*/ | ||
662 | |||
663 | static int osmChangeType_function(const char *_tag_,int _type_,const char *version) | ||
664 | { | ||
665 | if(_type_&XMLPARSE_TAG_START) | ||
666 | { | ||
667 | if(!version || strcmp(version,"0.6")) | ||
668 | XMLPARSE_MESSAGE(_tag_,"Invalid value for 'version' (only '0.6' accepted)"); | ||
669 | } | ||
670 | |||
671 | return(0); | ||
672 | } | ||
673 | |||
674 | |||
675 | /*++++++++++++++++++++++++++++++++++++++ | ||
676 | amb | 394 | The function that is called when the osmType XSD type is seen |
677 | amb | 2 | |
678 | amb | 394 | int osmType_function Returns 0 if no error occured or something else otherwise. |
679 | amb | 2 | |
680 | amb | 394 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
681 | amb | 2 | |
682 | 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. |
683 | amb | 919 | |
684 | const char *version The contents of the 'version' attribute (or NULL if not defined). | ||
685 | amb | 394 | ++++++++++++++++++++++++++++++++++++++*/ |
686 | |||
687 | amb | 919 | static int osmType_function(const char *_tag_,int _type_,const char *version) |
688 | { | ||
689 | if(_type_&XMLPARSE_TAG_START) | ||
690 | { | ||
691 | amb | 1145 | mode=MODE_NORMAL; |
692 | amb | 1140 | |
693 | amb | 919 | if(!version || strcmp(version,"0.6")) |
694 | XMLPARSE_MESSAGE(_tag_,"Invalid value for 'version' (only '0.6' accepted)"); | ||
695 | } | ||
696 | amb | 394 | |
697 | amb | 919 | return(0); |
698 | } | ||
699 | amb | 394 | |
700 | amb | 919 | |
701 | amb | 394 | /*++++++++++++++++++++++++++++++++++++++ |
702 | The function that is called when the XML declaration is seen | ||
703 | |||
704 | int xmlDeclaration_function Returns 0 if no error occured or something else otherwise. | ||
705 | |||
706 | const char *_tag_ Set to the name of the element tag that triggered this function call. | ||
707 | |||
708 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. | ||
709 | |||
710 | const char *version The contents of the 'version' attribute (or NULL if not defined). | ||
711 | |||
712 | const char *encoding The contents of the 'encoding' attribute (or NULL if not defined). | ||
713 | ++++++++++++++++++++++++++++++++++++++*/ | ||
714 | |||
715 | //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding) | ||
716 | //{ | ||
717 | // return(0); | ||
718 | //} | ||
719 | |||
720 | |||
721 | /*++++++++++++++++++++++++++++++++++++++ | ||
722 | Parse an OSM XML file (from JOSM or planet download). | ||
723 | |||
724 | int ParseOSM Returns 0 if OK or something else in case of an error. | ||
725 | |||
726 | amb | 2 | FILE *file The file to read from. |
727 | amb | 394 | |
728 | amb | 498 | NodesX *OSMNodes The data structure of nodes to fill in. |
729 | amb | 394 | |
730 | amb | 498 | SegmentsX *OSMSegments The data structure of segments to fill in. |
731 | amb | 394 | |
732 | amb | 498 | WaysX *OSMWays The data structure of ways to fill in. |
733 | |||
734 | RelationsX *OSMRelations The data structure of relations to fill in. | ||
735 | amb | 2 | ++++++++++++++++++++++++++++++++++++++*/ |
736 | |||
737 | amb | 498 | int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations) |
738 | amb | 2 | { |
739 | amb | 394 | int retval; |
740 | amb | 2 | |
741 | amb | 498 | /* Copy the function parameters and initialise the variables. */ |
742 | amb | 2 | |
743 | amb | 394 | nodes=OSMNodes; |
744 | segments=OSMSegments; | ||
745 | ways=OSMWays; | ||
746 | amb | 498 | relations=OSMRelations; |
747 | amb | 394 | |
748 | amb | 498 | way_nodes=(node_t*)malloc(256*sizeof(node_t)); |
749 | |||
750 | relation_nodes =(node_t *)malloc(256*sizeof(node_t)); | ||
751 | relation_ways =(way_t *)malloc(256*sizeof(way_t)); | ||
752 | relation_relations=(relation_t*)malloc(256*sizeof(relation_t)); | ||
753 | |||
754 | /* Parse the file */ | ||
755 | |||
756 | amb | 394 | nnodes=0,nways=0,nrelations=0; |
757 | |||
758 | amb | 519 | printf_first("Reading: Lines=0 Nodes=0 Ways=0 Relations=0"); |
759 | amb | 394 | |
760 | amb | 1140 | retval=ParseXML(file,xml_osm_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE); |
761 | amb | 394 | |
762 | amb | 791 | printf_last("Read: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations); |
763 | amb | 394 | |
764 | amb | 796 | free(way_nodes); |
765 | |||
766 | free(relation_nodes); | ||
767 | free(relation_ways); | ||
768 | free(relation_relations); | ||
769 | |||
770 | amb | 394 | return(retval); |
771 | } | ||
772 | |||
773 | |||
774 | /*++++++++++++++++++++++++++++++++++++++ | ||
775 | amb | 1140 | Parse an OSC XML file (from planet download). |
776 | |||
777 | int ParseOSC Returns 0 if OK or something else in case of an error. | ||
778 | |||
779 | FILE *file The file to read from. | ||
780 | |||
781 | NodesX *OSMNodes The data structure of nodes to fill in. | ||
782 | |||
783 | SegmentsX *OSMSegments The data structure of segments to fill in. | ||
784 | |||
785 | WaysX *OSMWays The data structure of ways to fill in. | ||
786 | |||
787 | RelationsX *OSMRelations The data structure of relations to fill in. | ||
788 | ++++++++++++++++++++++++++++++++++++++*/ | ||
789 | |||
790 | int ParseOSC(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations) | ||
791 | { | ||
792 | int retval; | ||
793 | |||
794 | /* Copy the function parameters and initialise the variables. */ | ||
795 | |||
796 | nodes=OSMNodes; | ||
797 | segments=OSMSegments; | ||
798 | ways=OSMWays; | ||
799 | relations=OSMRelations; | ||
800 | |||
801 | way_nodes=(node_t*)malloc(256*sizeof(node_t)); | ||
802 | |||
803 | relation_nodes =(node_t *)malloc(256*sizeof(node_t)); | ||
804 | relation_ways =(way_t *)malloc(256*sizeof(way_t)); | ||
805 | relation_relations=(relation_t*)malloc(256*sizeof(relation_t)); | ||
806 | |||
807 | /* Parse the file */ | ||
808 | |||
809 | nnodes=0,nways=0,nrelations=0; | ||
810 | |||
811 | printf_first("Reading: Lines=0 Nodes=0 Ways=0 Relations=0"); | ||
812 | |||
813 | retval=ParseXML(file,xml_osc_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE); | ||
814 | |||
815 | printf_last("Read: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations); | ||
816 | |||
817 | free(way_nodes); | ||
818 | |||
819 | free(relation_nodes); | ||
820 | free(relation_ways); | ||
821 | free(relation_relations); | ||
822 | |||
823 | return(retval); | ||
824 | } | ||
825 | |||
826 | |||
827 | /*++++++++++++++++++++++++++++++++++++++ | ||
828 | amb | 469 | Process the tags associated with a node. |
829 | |||
830 | TagList *tags The list of node tags. | ||
831 | |||
832 | node_t id The id of the node. | ||
833 | |||
834 | double latitude The latitude of the node. | ||
835 | |||
836 | double longitude The longitude of the node. | ||
837 | ++++++++++++++++++++++++++++++++++++++*/ | ||
838 | |||
839 | static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude) | ||
840 | { | ||
841 | amb | 529 | transports_t allow=Transports_ALL; |
842 | amb | 538 | uint16_t flags=0; |
843 | amb | 469 | int i; |
844 | |||
845 | amb | 1140 | /* Delete */ |
846 | |||
847 | if(mode==MODE_DELETE) | ||
848 | { | ||
849 | AppendNode(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,NODE_DELETED); | ||
850 | |||
851 | return; | ||
852 | } | ||
853 | |||
854 | amb | 469 | /* Parse the tags */ |
855 | |||
856 | for(i=0;i<tags->ntags;i++) | ||
857 | { | ||
858 | amb | 1025 | int recognised=0; |
859 | amb | 469 | char *k=tags->k[i]; |
860 | char *v=tags->v[i]; | ||
861 | |||
862 | switch(*k) | ||
863 | { | ||
864 | case 'b': | ||
865 | if(!strcmp(k,"bicycle")) | ||
866 | amb | 812 | { |
867 | if(ISFALSE(v)) | ||
868 | amb | 529 | allow&=~Transports_Bicycle; |
869 | amb | 812 | else if(!ISTRUE(v)) |
870 | amb | 813 | logerror("Node %"Pnode_t" has an unrecognised tag value 'bicycle' = '%s' (after tagging rules); using 'yes'.\n",id,v); |
871 | amb | 1025 | recognised=1; break; |
872 | amb | 812 | } |
873 | amb | 469 | |
874 | break; | ||
875 | |||
876 | case 'f': | ||
877 | if(!strcmp(k,"foot")) | ||
878 | amb | 812 | { |
879 | if(ISFALSE(v)) | ||
880 | amb | 529 | allow&=~Transports_Foot; |
881 | amb | 812 | else if(!ISTRUE(v)) |
882 | amb | 813 | logerror("Node %"Pnode_t" has an unrecognised tag value 'foot' = '%s' (after tagging rules); using 'yes'.\n",id,v); |
883 | amb | 1025 | recognised=1; break; |
884 | amb | 812 | } |
885 | amb | 469 | |
886 | break; | ||
887 | |||
888 | case 'g': | ||
889 | if(!strcmp(k,"goods")) | ||
890 | amb | 812 | { |
891 | if(ISFALSE(v)) | ||
892 | amb | 529 | allow&=~Transports_Goods; |
893 | amb | 812 | else if(!ISTRUE(v)) |
894 | amb | 813 | logerror("Node %"Pnode_t" has an unrecognised tag value 'goods' = '%s' (after tagging rules); using 'yes'.\n",id,v); |
895 | amb | 1025 | recognised=1; break; |
896 | amb | 812 | } |
897 | amb | 469 | |
898 | break; | ||
899 | |||
900 | case 'h': | ||
901 | amb | 537 | if(!strcmp(k,"highway")) |
902 | if(!strcmp(v,"mini_roundabout")) | ||
903 | amb | 1025 | { |
904 | amb | 538 | flags|=NODE_MINIRNDBT; |
905 | amb | 1025 | recognised=1; break; |
906 | } | ||
907 | amb | 537 | |
908 | amb | 469 | if(!strcmp(k,"horse")) |
909 | amb | 812 | { |
910 | if(ISFALSE(v)) | ||
911 | amb | 529 | allow&=~Transports_Horse; |
912 | amb | 812 | else if(!ISTRUE(v)) |
913 | amb | 813 | logerror("Node %"Pnode_t" has an unrecognised tag value 'horse' = '%s' (after tagging rules); using 'yes'.\n",id,v); |
914 | amb | 1025 | recognised=1; break; |
915 | amb | 812 | } |
916 | amb | 469 | |
917 | if(!strcmp(k,"hgv")) | ||
918 | amb | 812 | { |
919 | if(ISFALSE(v)) | ||
920 | amb | 529 | allow&=~Transports_HGV; |
921 | amb | 812 | else if(!ISTRUE(v)) |
922 | amb | 813 | logerror("Node %"Pnode_t" has an unrecognised tag value 'hgv' = '%s' (after tagging rules); using 'yes'.\n",id,v); |
923 | amb | 1025 | recognised=1; break; |
924 | amb | 812 | } |
925 | amb | 469 | |
926 | break; | ||
927 | |||
928 | case 'm': | ||
929 | if(!strcmp(k,"moped")) | ||
930 | amb | 812 | { |
931 | if(ISFALSE(v)) | ||
932 | amb | 529 | allow&=~Transports_Moped; |
933 | amb | 812 | else if(!ISTRUE(v)) |
934 | amb | 813 | logerror("Node %"Pnode_t" has an unrecognised tag value 'moped' = '%s' (after tagging rules); using 'yes'.\n",id,v); |
935 | amb | 1025 | recognised=1; break; |
936 | amb | 812 | } |
937 | amb | 469 | |
938 | if(!strcmp(k,"motorbike")) | ||
939 | amb | 812 | { |
940 | if(ISFALSE(v)) | ||
941 | amb | 529 | allow&=~Transports_Motorbike; |
942 | amb | 812 | else if(!ISTRUE(v)) |
943 | amb | 813 | logerror("Node %"Pnode_t" has an unrecognised tag value 'motorbike' = '%s' (after tagging rules); using 'yes'.\n",id,v); |
944 | amb | 1025 | recognised=1; break; |
945 | amb | 812 | } |
946 | amb | 469 | |
947 | if(!strcmp(k,"motorcar")) | ||
948 | amb | 812 | { |
949 | if(ISFALSE(v)) | ||
950 | amb | 529 | allow&=~Transports_Motorcar; |
951 | amb | 812 | else if(!ISTRUE(v)) |
952 | amb | 813 | logerror("Node %"Pnode_t" has an unrecognised tag value 'motorcar' = '%s' (after tagging rules); using 'yes'.\n",id,v); |
953 | amb | 1025 | recognised=1; break; |
954 | amb | 812 | } |
955 | amb | 469 | |
956 | break; | ||
957 | |||
958 | case 'p': | ||
959 | if(!strcmp(k,"psv")) | ||
960 | amb | 812 | { |
961 | if(ISFALSE(v)) | ||
962 | amb | 529 | allow&=~Transports_PSV; |
963 | amb | 812 | else if(!ISTRUE(v)) |
964 | amb | 813 | logerror("Node %"Pnode_t" has an unrecognised tag value 'psv' = '%s' (after tagging rules); using 'yes'.\n",id,v); |
965 | amb | 1025 | recognised=1; break; |
966 | amb | 812 | } |
967 | amb | 469 | |
968 | break; | ||
969 | |||
970 | case 'w': | ||
971 | if(!strcmp(k,"wheelchair")) | ||
972 | amb | 812 | { |
973 | if(ISFALSE(v)) | ||
974 | amb | 529 | allow&=~Transports_Wheelchair; |
975 | amb | 812 | else if(!ISTRUE(v)) |
976 | amb | 813 | logerror("Node %"Pnode_t" has an unrecognised tag value 'wheelchair' = '%s' (after tagging rules); using 'yes'.\n",id,v); |
977 | amb | 1025 | recognised=1; break; |
978 | amb | 812 | } |
979 | amb | 469 | |
980 | break; | ||
981 | |||
982 | default: | ||
983 | amb | 1025 | break; |
984 | } | ||
985 | |||
986 | if(!recognised) | ||
987 | amb | 813 | logerror("Node %"Pnode_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v); |
988 | amb | 469 | } |
989 | |||
990 | /* Create the node */ | ||
991 | |||
992 | amb | 538 | AppendNode(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,flags); |
993 | amb | 469 | } |
994 | |||
995 | |||
996 | /*++++++++++++++++++++++++++++++++++++++ | ||
997 | amb | 394 | Process the tags associated with a way. |
998 | |||
999 | TagList *tags The list of way tags. | ||
1000 | |||
1001 | way_t id The id of the way. | ||
1002 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1003 | |||
1004 | static void process_way_tags(TagList *tags,way_t id) | ||
1005 | { | ||
1006 | amb | 1137 | Way way={0}; |
1007 | distance_t oneway=0,area=0; | ||
1008 | int roundabout=0; | ||
1009 | amb | 812 | char *name=NULL,*ref=NULL,*refname=NULL; |
1010 | amb | 394 | int i; |
1011 | |||
1012 | amb | 1140 | /* Delete */ |
1013 | |||
1014 | amb | 1145 | if(mode==MODE_DELETE || (mode!=MODE_NORMAL && IndexWayX(ways,id)!=NO_WAY)) |
1015 | amb | 1140 | { |
1016 | way.type=WAY_DELETED; | ||
1017 | |||
1018 | AppendWay(ways,id,&way,""); | ||
1019 | |||
1020 | AppendSegment(segments,id,NO_NODE_ID,NO_NODE_ID,0); | ||
1021 | amb | 1145 | } |
1022 | amb | 1140 | |
1023 | amb | 1145 | if(mode==MODE_DELETE) |
1024 | amb | 1140 | return; |
1025 | |||
1026 | amb | 1125 | /* Sanity check */ |
1027 | |||
1028 | if(way_nnodes==0) | ||
1029 | { | ||
1030 | logerror("Way %"Pway_t" has no nodes.\n",id); | ||
1031 | return; | ||
1032 | } | ||
1033 | |||
1034 | if(way_nnodes==1) | ||
1035 | { | ||
1036 | logerror("Way %"Pway_t" has only one node.\n",id); | ||
1037 | return; | ||
1038 | } | ||
1039 | |||
1040 | amb | 833 | /* Parse the tags - just look for highway */ |
1041 | amb | 394 | |
1042 | for(i=0;i<tags->ntags;i++) | ||
1043 | amb | 2 | { |
1044 | amb | 394 | char *k=tags->k[i]; |
1045 | char *v=tags->v[i]; | ||
1046 | amb | 2 | |
1047 | amb | 833 | if(!strcmp(k,"highway")) |
1048 | { | ||
1049 | way.type=HighwayType(v); | ||
1050 | |||
1051 | if(way.type==Way_Count) | ||
1052 | logerror("Way %"Pway_t" has an unrecognised highway type '%s' (after tagging rules); ignoring it.\n",id,v); | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | /* Don't continue if this is not a highway (bypass error logging) */ | ||
1057 | |||
1058 | if(way.type==0 || way.type==Way_Count) | ||
1059 | return; | ||
1060 | |||
1061 | /* Parse the tags - look for the others */ | ||
1062 | |||
1063 | for(i=0;i<tags->ntags;i++) | ||
1064 | { | ||
1065 | amb | 1025 | int recognised=0; |
1066 | amb | 833 | char *k=tags->k[i]; |
1067 | char *v=tags->v[i]; | ||
1068 | |||
1069 | amb | 394 | switch(*k) |
1070 | { | ||
1071 | amb | 914 | case 'a': |
1072 | if(!strcmp(k,"area")) | ||
1073 | { | ||
1074 | if(ISTRUE(v)) | ||
1075 | amb | 1137 | area=SEGMENT_AREA; |
1076 | amb | 914 | else if(!ISFALSE(v)) |
1077 | logerror("Way %"Pway_t" has an unrecognised tag value 'area' = '%s' (after tagging rules); using 'no'.\n",id,v); | ||
1078 | amb | 1025 | recognised=1; break; |
1079 | amb | 914 | } |
1080 | |||
1081 | break; | ||
1082 | |||
1083 | amb | 394 | case 'b': |
1084 | if(!strcmp(k,"bicycle")) | ||
1085 | amb | 812 | { |
1086 | amb | 394 | if(ISTRUE(v)) |
1087 | amb | 813 | way.allow|=Transports_Bicycle; |
1088 | amb | 812 | else if(!ISFALSE(v)) |
1089 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'bicycle' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1090 | amb | 1025 | recognised=1; break; |
1091 | amb | 812 | } |
1092 | amb | 394 | |
1093 | amb | 498 | if(!strcmp(k,"bicycleroute")) |
1094 | amb | 812 | { |
1095 | amb | 498 | if(ISTRUE(v)) |
1096 | way.props|=Properties_BicycleRoute; | ||
1097 | amb | 812 | else if(!ISFALSE(v)) |
1098 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1099 | amb | 1025 | recognised=1; break; |
1100 | amb | 812 | } |
1101 | amb | 498 | |
1102 | amb | 394 | if(!strcmp(k,"bridge")) |
1103 | amb | 812 | { |
1104 | amb | 394 | if(ISTRUE(v)) |
1105 | way.props|=Properties_Bridge; | ||
1106 | amb | 812 | else if(!ISFALSE(v)) |
1107 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'bridge' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1108 | amb | 1025 | recognised=1; break; |
1109 | amb | 812 | } |
1110 | amb | 394 | |
1111 | amb | 2 | break; |
1112 | amb | 394 | |
1113 | case 'f': | ||
1114 | if(!strcmp(k,"foot")) | ||
1115 | amb | 812 | { |
1116 | amb | 394 | if(ISTRUE(v)) |
1117 | amb | 813 | way.allow|=Transports_Foot; |
1118 | amb | 812 | else if(!ISFALSE(v)) |
1119 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'foot' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1120 | amb | 1025 | recognised=1; break; |
1121 | amb | 812 | } |
1122 | amb | 394 | |
1123 | amb | 498 | if(!strcmp(k,"footroute")) |
1124 | amb | 812 | { |
1125 | amb | 498 | if(ISTRUE(v)) |
1126 | way.props|=Properties_FootRoute; | ||
1127 | amb | 812 | else if(!ISFALSE(v)) |
1128 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'footroute' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1129 | amb | 1025 | recognised=1; break; |
1130 | amb | 812 | } |
1131 | amb | 498 | |
1132 | amb | 394 | break; |
1133 | |||
1134 | case 'g': | ||
1135 | if(!strcmp(k,"goods")) | ||
1136 | amb | 812 | { |
1137 | amb | 394 | if(ISTRUE(v)) |
1138 | amb | 529 | way.allow|=Transports_Goods; |
1139 | amb | 812 | else if(!ISFALSE(v)) |
1140 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'goods' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1141 | amb | 1025 | recognised=1; break; |
1142 | amb | 812 | } |
1143 | amb | 394 | |
1144 | break; | ||
1145 | |||
1146 | case 'h': | ||
1147 | if(!strcmp(k,"highway")) | ||
1148 | amb | 1025 | {recognised=1; break;} |
1149 | amb | 394 | |
1150 | if(!strcmp(k,"horse")) | ||
1151 | amb | 812 | { |
1152 | amb | 394 | if(ISTRUE(v)) |
1153 | amb | 529 | way.allow|=Transports_Horse; |
1154 | amb | 812 | else if(!ISFALSE(v)) |
1155 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'horse' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1156 | amb | 1025 | recognised=1; break; |
1157 | amb | 812 | } |
1158 | amb | 394 | |
1159 | if(!strcmp(k,"hgv")) | ||
1160 | amb | 812 | { |
1161 | amb | 394 | if(ISTRUE(v)) |
1162 | amb | 529 | way.allow|=Transports_HGV; |
1163 | amb | 812 | else if(!ISFALSE(v)) |
1164 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'hgv' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1165 | amb | 1025 | recognised=1; break; |
1166 | amb | 812 | } |
1167 | amb | 394 | |
1168 | break; | ||
1169 | |||
1170 | case 'm': | ||
1171 | amb | 1025 | if(!strncmp(k,"max",3)) |
1172 | { | ||
1173 | if(!strcmp(k+3,"speed")) | ||
1174 | { | ||
1175 | way.speed=kph_to_speed(parse_speed(id,k,v)); | ||
1176 | recognised=1; break; | ||
1177 | } | ||
1178 | amb | 394 | |
1179 | amb | 1025 | if(!strcmp(k+3,"weight")) |
1180 | { | ||
1181 | way.weight=tonnes_to_weight(parse_weight(id,k,v)); | ||
1182 | recognised=1; break; | ||
1183 | } | ||
1184 | amb | 394 | |
1185 | amb | 1025 | if(!strcmp(k+3,"height")) |
1186 | { | ||
1187 | way.height=metres_to_height(parse_length(id,k,v)); | ||
1188 | recognised=1; break; | ||
1189 | } | ||
1190 | amb | 394 | |
1191 | amb | 1025 | if(!strcmp(k+3,"width")) |
1192 | { | ||
1193 | way.width=metres_to_height(parse_length(id,k,v)); | ||
1194 | recognised=1; break; | ||
1195 | } | ||
1196 | amb | 394 | |
1197 | amb | 1025 | if(!strcmp(k+3,"length")) |
1198 | { | ||
1199 | way.length=metres_to_height(parse_length(id,k,v)); | ||
1200 | recognised=1; break; | ||
1201 | } | ||
1202 | } | ||
1203 | amb | 394 | |
1204 | if(!strcmp(k,"moped")) | ||
1205 | amb | 812 | { |
1206 | amb | 394 | if(ISTRUE(v)) |
1207 | amb | 529 | way.allow|=Transports_Moped; |
1208 | amb | 812 | else if(!ISFALSE(v)) |
1209 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'moped' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1210 | amb | 1025 | recognised=1; break; |
1211 | amb | 812 | } |
1212 | amb | 394 | |
1213 | if(!strcmp(k,"motorbike")) | ||
1214 | amb | 812 | { |
1215 | amb | 394 | if(ISTRUE(v)) |
1216 | amb | 529 | way.allow|=Transports_Motorbike; |
1217 | amb | 812 | else if(!ISFALSE(v)) |
1218 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'motorbike' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1219 | amb | 1025 | recognised=1; break; |
1220 | amb | 812 | } |
1221 | amb | 394 | |
1222 | if(!strcmp(k,"motorcar")) | ||
1223 | amb | 812 | { |
1224 | amb | 394 | if(ISTRUE(v)) |
1225 | amb | 529 | way.allow|=Transports_Motorcar; |
1226 | amb | 812 | else if(!ISFALSE(v)) |
1227 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'motorcar' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1228 | amb | 1025 | recognised=1; break; |
1229 | amb | 812 | } |
1230 | amb | 394 | |
1231 | if(!strcmp(k,"multilane")) | ||
1232 | amb | 812 | { |
1233 | amb | 394 | if(ISTRUE(v)) |
1234 | way.props|=Properties_Multilane; | ||
1235 | amb | 812 | else if(!ISFALSE(v)) |
1236 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'multilane' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1237 | amb | 1025 | recognised=1; break; |
1238 | amb | 812 | } |
1239 | amb | 394 | |
1240 | break; | ||
1241 | |||
1242 | case 'n': | ||
1243 | if(!strcmp(k,"name")) | ||
1244 | amb | 1025 | { |
1245 | amb | 394 | name=v; |
1246 | amb | 1025 | recognised=1; break; |
1247 | } | ||
1248 | amb | 394 | |
1249 | break; | ||
1250 | |||
1251 | case 'o': | ||
1252 | if(!strcmp(k,"oneway")) | ||
1253 | { | ||
1254 | if(ISTRUE(v)) | ||
1255 | amb | 1137 | oneway=ONEWAY_1TO2; |
1256 | amb | 394 | else if(!strcmp(v,"-1")) |
1257 | amb | 1137 | oneway=ONEWAY_2TO1; |
1258 | amb | 812 | else if(!ISFALSE(v)) |
1259 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'oneway' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1260 | amb | 1025 | recognised=1; break; |
1261 | amb | 394 | } |
1262 | |||
1263 | break; | ||
1264 | |||
1265 | case 'p': | ||
1266 | if(!strcmp(k,"paved")) | ||
1267 | amb | 812 | { |
1268 | amb | 394 | if(ISTRUE(v)) |
1269 | way.props|=Properties_Paved; | ||
1270 | amb | 812 | else if(!ISFALSE(v)) |
1271 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'paved' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1272 | amb | 1025 | recognised=1; break; |
1273 | amb | 812 | } |
1274 | amb | 394 | |
1275 | if(!strcmp(k,"psv")) | ||
1276 | amb | 812 | { |
1277 | amb | 394 | if(ISTRUE(v)) |
1278 | amb | 529 | way.allow|=Transports_PSV; |
1279 | amb | 812 | else if(!ISFALSE(v)) |
1280 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'psv' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1281 | amb | 1025 | recognised=1; break; |
1282 | amb | 812 | } |
1283 | amb | 394 | |
1284 | break; | ||
1285 | |||
1286 | case 'r': | ||
1287 | if(!strcmp(k,"ref")) | ||
1288 | amb | 1025 | { |
1289 | amb | 394 | ref=v; |
1290 | amb | 1025 | recognised=1; break; |
1291 | } | ||
1292 | amb | 394 | |
1293 | amb | 923 | if(!strcmp(k,"roundabout")) |
1294 | { | ||
1295 | if(ISTRUE(v)) | ||
1296 | roundabout=1; | ||
1297 | else if(!ISFALSE(v)) | ||
1298 | logerror("Way %"Pway_t" has an unrecognised tag value 'roundabout' = '%s' (after tagging rules); using 'no'.\n",id,v); | ||
1299 | amb | 1025 | recognised=1; break; |
1300 | amb | 923 | } |
1301 | |||
1302 | amb | 394 | break; |
1303 | |||
1304 | case 't': | ||
1305 | if(!strcmp(k,"tunnel")) | ||
1306 | amb | 812 | { |
1307 | amb | 394 | if(ISTRUE(v)) |
1308 | way.props|=Properties_Tunnel; | ||
1309 | amb | 812 | else if(!ISFALSE(v)) |
1310 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'tunnel' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1311 | amb | 1025 | recognised=1; break; |
1312 | amb | 812 | } |
1313 | amb | 394 | |
1314 | break; | ||
1315 | |||
1316 | case 'w': | ||
1317 | if(!strcmp(k,"wheelchair")) | ||
1318 | amb | 812 | { |
1319 | amb | 394 | if(ISTRUE(v)) |
1320 | amb | 529 | way.allow|=Transports_Wheelchair; |
1321 | amb | 812 | else if(!ISFALSE(v)) |
1322 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value 'wheelchair' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1323 | amb | 1025 | recognised=1; break; |
1324 | amb | 812 | } |
1325 | amb | 394 | |
1326 | break; | ||
1327 | |||
1328 | default: | ||
1329 | amb | 1025 | break; |
1330 | } | ||
1331 | |||
1332 | if(!recognised) | ||
1333 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v); |
1334 | amb | 2 | } |
1335 | |||
1336 | amb | 394 | /* Create the way */ |
1337 | amb | 2 | |
1338 | amb | 812 | if(!way.allow) |
1339 | return; | ||
1340 | |||
1341 | if(oneway) | ||
1342 | way.type|=Way_OneWay; | ||
1343 | amb | 394 | |
1344 | amb | 923 | if(roundabout) |
1345 | way.type|=Way_Roundabout; | ||
1346 | |||
1347 | amb | 812 | if(ref && name) |
1348 | { | ||
1349 | refname=(char*)malloc(strlen(ref)+strlen(name)+4); | ||
1350 | sprintf(refname,"%s (%s)",name,ref); | ||
1351 | } | ||
1352 | else if(ref && !name) | ||
1353 | refname=ref; | ||
1354 | else if(!ref && name) | ||
1355 | refname=name; | ||
1356 | else /* if(!ref && !name) */ | ||
1357 | refname=""; | ||
1358 | amb | 394 | |
1359 | amb | 812 | AppendWay(ways,id,&way,refname); |
1360 | amb | 394 | |
1361 | amb | 812 | if(ref && name) |
1362 | free(refname); | ||
1363 | amb | 394 | |
1364 | amb | 812 | for(i=1;i<way_nnodes;i++) |
1365 | { | ||
1366 | node_t from=way_nodes[i-1]; | ||
1367 | node_t to =way_nodes[i]; | ||
1368 | |||
1369 | amb | 1137 | AppendSegment(segments,id,from,to,area+oneway); |
1370 | amb | 394 | } |
1371 | amb | 2 | } |
1372 | amb | 498 | |
1373 | |||
1374 | /*++++++++++++++++++++++++++++++++++++++ | ||
1375 | Process the tags associated with a relation. | ||
1376 | |||
1377 | TagList *tags The list of relation tags. | ||
1378 | |||
1379 | relation_t id The id of the relation. | ||
1380 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1381 | |||
1382 | static void process_relation_tags(TagList *tags,relation_t id) | ||
1383 | { | ||
1384 | amb | 529 | transports_t routes=Transports_None; |
1385 | amb | 540 | transports_t except=Transports_None; |
1386 | int relation_turn_restriction=0; | ||
1387 | amb | 541 | TurnRestriction restriction=TurnRestrict_None; |
1388 | amb | 498 | int i; |
1389 | |||
1390 | amb | 1140 | /* Delete */ |
1391 | |||
1392 | if(mode==MODE_DELETE) | ||
1393 | { | ||
1394 | AppendRouteRelation(relations,id,RELATION_DELETED, | ||
1395 | relation_ways,relation_nways, | ||
1396 | relation_relations,relation_nrelations); | ||
1397 | |||
1398 | AppendTurnRestrictRelation(relations,id, | ||
1399 | relation_from,relation_to,relation_via, | ||
1400 | restriction,RELATION_DELETED); | ||
1401 | |||
1402 | return; | ||
1403 | } | ||
1404 | |||
1405 | amb | 1125 | /* Sanity check */ |
1406 | |||
1407 | if(relation_nnodes==0 && relation_nways==0 && relation_nrelations==0) | ||
1408 | { | ||
1409 | logerror("Relation %"Prelation_t" has no nodes, ways or relations.\n",id); | ||
1410 | return; | ||
1411 | } | ||
1412 | |||
1413 | amb | 498 | /* Parse the tags */ |
1414 | |||
1415 | for(i=0;i<tags->ntags;i++) | ||
1416 | { | ||
1417 | amb | 1025 | int recognised=0; |
1418 | amb | 498 | char *k=tags->k[i]; |
1419 | char *v=tags->v[i]; | ||
1420 | |||
1421 | switch(*k) | ||
1422 | { | ||
1423 | case 'b': | ||
1424 | if(!strcmp(k,"bicycleroute")) | ||
1425 | amb | 812 | { |
1426 | amb | 498 | if(ISTRUE(v)) |
1427 | amb | 529 | routes|=Transports_Bicycle; |
1428 | amb | 812 | else if(!ISFALSE(v)) |
1429 | amb | 813 | logerror("Relation %"Prelation_t" has an unrecognised tag value 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1430 | amb | 1025 | recognised=1; break; |
1431 | amb | 812 | } |
1432 | amb | 498 | |
1433 | break; | ||
1434 | |||
1435 | amb | 540 | case 'e': |
1436 | if(!strcmp(k,"except")) | ||
1437 | amb | 812 | { |
1438 | amb | 540 | for(i=1;i<Transport_Count;i++) |
1439 | amb | 876 | if(strstr(v,TransportName(i))) |
1440 | amb | 540 | except|=TRANSPORTS(i); |
1441 | |||
1442 | amb | 812 | if(except==Transports_None) |
1443 | amb | 813 | logerror("Relation %"Prelation_t" has an unrecognised tag value 'except' = '%s' (after tagging rules); ignoring it.\n",id,v); |
1444 | amb | 1025 | |
1445 | recognised=1; break; | ||
1446 | amb | 812 | } |
1447 | |||
1448 | amb | 540 | break; |
1449 | |||
1450 | amb | 498 | case 'f': |
1451 | if(!strcmp(k,"footroute")) | ||
1452 | amb | 812 | { |
1453 | amb | 498 | if(ISTRUE(v)) |
1454 | amb | 529 | routes|=Transports_Foot; |
1455 | amb | 812 | else if(!ISFALSE(v)) |
1456 | amb | 813 | logerror("Relation %"Prelation_t" has an unrecognised tag value 'footroute' = '%s' (after tagging rules); using 'no'.\n",id,v); |
1457 | amb | 1025 | recognised=1; break; |
1458 | amb | 812 | } |
1459 | amb | 498 | |
1460 | break; | ||
1461 | |||
1462 | amb | 540 | case 'r': |
1463 | if(!strcmp(k,"restriction")) | ||
1464 | { | ||
1465 | amb | 541 | if(!strcmp(v,"no_right_turn" )) restriction=TurnRestrict_no_right_turn; |
1466 | if(!strcmp(v,"no_left_turn" )) restriction=TurnRestrict_no_left_turn; | ||
1467 | if(!strcmp(v,"no_u_turn" )) restriction=TurnRestrict_no_u_turn; | ||
1468 | if(!strcmp(v,"no_straight_on" )) restriction=TurnRestrict_no_straight_on; | ||
1469 | if(!strcmp(v,"only_right_turn" )) restriction=TurnRestrict_only_right_turn; | ||
1470 | if(!strcmp(v,"only_left_turn" )) restriction=TurnRestrict_only_left_turn; | ||
1471 | if(!strcmp(v,"only_straight_on")) restriction=TurnRestrict_only_straight_on; | ||
1472 | amb | 812 | |
1473 | if(restriction==TurnRestrict_None) | ||
1474 | amb | 813 | logerror("Relation %"Prelation_t" has an unrecognised tag value 'restriction' = '%s' (after tagging rules); ignoring it.\n",id,v); |
1475 | amb | 1025 | |
1476 | recognised=1; break; | ||
1477 | amb | 540 | } |
1478 | |||
1479 | break; | ||
1480 | |||
1481 | case 't': | ||
1482 | if(!strcmp(k,"type")) | ||
1483 | amb | 1025 | { |
1484 | amb | 540 | if(!strcmp(v,"restriction")) |
1485 | relation_turn_restriction=1; | ||
1486 | amb | 1025 | |
1487 | /* Don't log an error for relations of types that we don't handle - there are so many */ | ||
1488 | recognised=1; break; | ||
1489 | } | ||
1490 | |||
1491 | amb | 540 | break; |
1492 | |||
1493 | amb | 498 | default: |
1494 | amb | 1025 | break; |
1495 | } | ||
1496 | |||
1497 | if(!recognised) | ||
1498 | amb | 813 | logerror("Relation %"Prelation_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v); |
1499 | amb | 498 | } |
1500 | |||
1501 | amb | 505 | /* Create the route relation (must store all relations that have ways or |
1502 | relations even if they are not routes because they might be referenced by | ||
1503 | other relations that are routes) */ | ||
1504 | amb | 498 | |
1505 | amb | 540 | if((relation_nways || relation_nrelations) && !relation_turn_restriction) |
1506 | amb | 498 | AppendRouteRelation(relations,id,routes, |
1507 | relation_ways,relation_nways, | ||
1508 | relation_relations,relation_nrelations); | ||
1509 | amb | 540 | |
1510 | /* Create the turn restriction relation. */ | ||
1511 | |||
1512 | amb | 812 | if(relation_turn_restriction && restriction!=TurnRestrict_None) |
1513 | { | ||
1514 | if(relation_from==NO_WAY_ID) | ||
1515 | amb | 813 | logerror("Relation %"Prelation_t" is a turn restriction but has no 'from' way.\n",id); |
1516 | amb | 812 | else if(relation_to==NO_WAY_ID) |
1517 | amb | 813 | logerror("Relation %"Prelation_t" is a turn restriction but has no 'to' way.\n",id); |
1518 | amb | 812 | else if(relation_via==NO_NODE_ID) |
1519 | amb | 813 | logerror("Relation %"Prelation_t" is a turn restriction but has no 'via' node.\n",id); |
1520 | amb | 812 | else |
1521 | AppendTurnRestrictRelation(relations,id, | ||
1522 | relation_from,relation_to,relation_via, | ||
1523 | restriction,except); | ||
1524 | } | ||
1525 | amb | 498 | } |
1526 | amb | 812 | |
1527 | |||
1528 | /*++++++++++++++++++++++++++++++++++++++ | ||
1529 | Convert a string containing a speed into a double precision. | ||
1530 | |||
1531 | double parse_speed Returns the speed in km/h if it can be parsed. | ||
1532 | |||
1533 | way_t id The way being processed. | ||
1534 | |||
1535 | const char *k The tag key. | ||
1536 | |||
1537 | const char *v The tag value. | ||
1538 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1539 | |||
1540 | static double parse_speed(way_t id,const char *k,const char *v) | ||
1541 | { | ||
1542 | char *ev; | ||
1543 | double value=strtod(v,&ev); | ||
1544 | |||
1545 | if(v==ev) | ||
1546 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v); |
1547 | amb | 812 | else |
1548 | { | ||
1549 | while(isspace(*ev)) ev++; | ||
1550 | |||
1551 | if(!strcmp(ev,"mph")) | ||
1552 | return(1.609*value); | ||
1553 | amb | 813 | |
1554 | if(*ev==0 || !strcmp(ev,"kph")) | ||
1555 | amb | 812 | return(value); |
1556 | amb | 813 | |
1557 | logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v); | ||
1558 | amb | 812 | } |
1559 | |||
1560 | return(0); | ||
1561 | } | ||
1562 | |||
1563 | |||
1564 | /*++++++++++++++++++++++++++++++++++++++ | ||
1565 | Convert a string containing a weight into a double precision. | ||
1566 | |||
1567 | double parse_weight Returns the weight in tonnes if it can be parsed. | ||
1568 | |||
1569 | way_t id The way being processed. | ||
1570 | |||
1571 | const char *k The tag key. | ||
1572 | |||
1573 | const char *v The tag value. | ||
1574 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1575 | |||
1576 | static double parse_weight(way_t id,const char *k,const char *v) | ||
1577 | { | ||
1578 | char *ev; | ||
1579 | double value=strtod(v,&ev); | ||
1580 | |||
1581 | if(v==ev) | ||
1582 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v); |
1583 | amb | 812 | else |
1584 | { | ||
1585 | while(isspace(*ev)) ev++; | ||
1586 | |||
1587 | if(!strcmp(ev,"kg")) | ||
1588 | return(value/1000.0); | ||
1589 | amb | 813 | |
1590 | amb | 825 | if(*ev==0 || !strcmp(ev,"T") || !strcmp(ev,"t") |
1591 | || !strcmp(ev,"ton") || !strcmp(ev,"tons") | ||
1592 | || !strcmp(ev,"tonne") || !strcmp(ev,"tonnes")) | ||
1593 | amb | 812 | return(value); |
1594 | amb | 813 | |
1595 | logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v); | ||
1596 | amb | 812 | } |
1597 | |||
1598 | return(0); | ||
1599 | } | ||
1600 | |||
1601 | |||
1602 | /*++++++++++++++++++++++++++++++++++++++ | ||
1603 | Convert a string containing a length into a double precision. | ||
1604 | |||
1605 | double parse_length Returns the length in metres if it can be parsed. | ||
1606 | |||
1607 | way_t id The way being processed. | ||
1608 | |||
1609 | const char *k The tag key. | ||
1610 | |||
1611 | const char *v The tag value. | ||
1612 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1613 | |||
1614 | static double parse_length(way_t id,const char *k,const char *v) | ||
1615 | { | ||
1616 | char *ev; | ||
1617 | double value=strtod(v,&ev); | ||
1618 | |||
1619 | if(v==ev) | ||
1620 | amb | 813 | logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v); |
1621 | amb | 812 | else |
1622 | { | ||
1623 | amb | 813 | int en=0; |
1624 | int feet=0,inches=0; | ||
1625 | amb | 812 | |
1626 | amb | 813 | if(sscanf(v,"%d' %d\"%n",&feet,&inches,&en)==2 && en && !v[en]) |
1627 | amb | 812 | return((feet+(double)inches/12.0)*0.254); |
1628 | amb | 813 | |
1629 | amb | 1127 | if(sscanf(v,"%d'%d\"%n",&feet,&inches,&en)==2 && en && !v[en]) |
1630 | return((feet+(double)inches/12.0)*0.254); | ||
1631 | |||
1632 | if(sscanf(v,"%d'-%d\"%n",&feet,&inches,&en)==2 && en && !v[en]) | ||
1633 | return((feet+(double)inches/12.0)*0.254); | ||
1634 | |||
1635 | amb | 813 | if(sscanf(v,"%d - %d%n",&feet,&inches,&en)==2 && en && !v[en]) |
1636 | return((feet+(double)inches/12.0)*0.254); | ||
1637 | |||
1638 | if(sscanf(v,"%d ft %d in%n",&feet,&inches,&en)==2 && en && !v[en]) | ||
1639 | return((feet+(double)inches/12.0)*0.254); | ||
1640 | |||
1641 | amb | 825 | if(sscanf(v,"%d feet %d inches%n",&feet,&inches,&en)==2 && en && !v[en]) |
1642 | return((feet+(double)inches/12.0)*0.254); | ||
1643 | |||
1644 | if(!strcmp(ev,"'")) | ||
1645 | amb | 812 | return(feet*0.254); |
1646 | amb | 813 | |
1647 | while(isspace(*ev)) ev++; | ||
1648 | |||
1649 | if(!strcmp(ev,"ft") || !strcmp(ev,"feet")) | ||
1650 | amb | 812 | return(value*0.254); |
1651 | amb | 813 | |
1652 | amb | 825 | if(*ev==0 || !strcmp(ev,"m") || !strcmp(ev,"metre") || !strcmp(ev,"metres")) |
1653 | amb | 812 | return(value); |
1654 | amb | 813 | |
1655 | logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v); | ||
1656 | amb | 812 | } |
1657 | |||
1658 | return(0); | ||
1659 | } |
Properties
Name | Value |
---|---|
cvs:description | OSM XML file parser. |