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 2183 -
(hide annotations)
(download)
(as text)
Tue Aug 29 10:28:56 2023 UTC (18 months, 4 weeks ago) by amb
File MIME type: text/x-csrc
File size: 38141 byte(s)
Tue Aug 29 10:28:56 2023 UTC (18 months, 4 weeks ago) by amb
File MIME type: text/x-csrc
File size: 38141 byte(s)
Add new parsers for heights/widths in feet and inches format.
1 | amb | 2 | /*************************************** |
2 | amb | 1221 | OSM file parser (either JOSM or planet) |
3 | amb | 151 | |
4 | Part of the Routino routing software. | ||
5 | amb | 2 | ******************/ /****************** |
6 | amb | 2170 | This file Copyright 2008-2015, 2018, 2023 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 | #include <stdlib.h> | ||
24 | #include <string.h> | ||
25 | amb | 1234 | #include <stdint.h> |
26 | amb | 2 | #include <ctype.h> |
27 | |||
28 | amb | 1234 | #include "types.h" |
29 | amb | 199 | #include "typesx.h" |
30 | amb | 1234 | |
31 | amb | 109 | #include "nodesx.h" |
32 | #include "waysx.h" | ||
33 | amb | 498 | #include "relationsx.h" |
34 | |||
35 | amb | 955 | #include "osmparser.h" |
36 | amb | 394 | #include "tagging.h" |
37 | amb | 519 | #include "logging.h" |
38 | amb | 26 | |
39 | amb | 519 | |
40 | amb | 394 | /* Macros */ |
41 | amb | 2 | |
42 | amb | 680 | /*+ Checks if a value in the XML is one of the allowed values for true. +*/ |
43 | amb | 812 | #define ISTRUE(xx) (!strcmp(xx,"true") || !strcmp(xx,"yes") || !strcmp(xx,"1")) |
44 | amb | 297 | |
45 | amb | 812 | /*+ Checks if a value in the XML is one of the allowed values for false. +*/ |
46 | #define ISFALSE(xx) (!strcmp(xx,"false") || !strcmp(xx,"no") || !strcmp(xx,"0")) | ||
47 | amb | 298 | |
48 | amb | 1784 | /* Local parsing variables (re-initialised for each file) */ |
49 | amb | 394 | |
50 | amb | 498 | static NodesX *nodes; |
51 | static WaysX *ways; | ||
52 | static RelationsX *relations; | ||
53 | amb | 394 | |
54 | amb | 1784 | static node_t *way_nodes; |
55 | static int way_nnodes; | ||
56 | amb | 1234 | |
57 | amb | 1784 | static node_t *relation_nodes; |
58 | static int relation_nnodes; | ||
59 | static way_t *relation_ways; | ||
60 | static int relation_nways; | ||
61 | static relation_t *relation_relations; | ||
62 | static int relation_nrelations; | ||
63 | static way_t relation_from; | ||
64 | amb | 1953 | static int relation_from_count; |
65 | amb | 1784 | static way_t relation_to; |
66 | amb | 1953 | static int relation_to_count; |
67 | amb | 1784 | static node_t relation_via; |
68 | amb | 1954 | static int relation_via_count; |
69 | amb | 1234 | |
70 | amb | 1784 | /* Local parsing functions */ |
71 | amb | 228 | |
72 | amb | 2170 | static void ProcessNodeTags(TagList *tags,int64_t node_id,double latitude,double longitude,int mode); |
73 | static void ProcessWayTags(TagList *tags,int64_t way_id, int mode); | ||
74 | static void ProcessRelationTags(TagList *tags,int64_t relation_id,int mode); | ||
75 | |||
76 | amb | 812 | static double parse_speed(way_t id,const char *k,const char *v); |
77 | static double parse_weight(way_t id,const char *k,const char *v); | ||
78 | static double parse_length(way_t id,const char *k,const char *v); | ||
79 | amb | 2 | |
80 | amb | 812 | |
81 | amb | 1204 | /*++++++++++++++++++++++++++++++++++++++ |
82 | amb | 1356 | Initialise the OSM parser by initialising the local variables. |
83 | amb | 1140 | |
84 | amb | 1221 | NodesX *OSMNodes The data structure of nodes to fill in. |
85 | amb | 2 | |
86 | amb | 1221 | WaysX *OSMWays The data structure of ways to fill in. |
87 | amb | 2 | |
88 | amb | 1221 | RelationsX *OSMRelations The data structure of relations to fill in. |
89 | amb | 1204 | ++++++++++++++++++++++++++++++++++++++*/ |
90 | |||
91 | amb | 1356 | void InitialiseParser(NodesX *OSMNodes,WaysX *OSMWays,RelationsX *OSMRelations) |
92 | amb | 1204 | { |
93 | amb | 1221 | /* Copy the function parameters and initialise the variables */ |
94 | amb | 1204 | |
95 | amb | 1221 | nodes=OSMNodes; |
96 | ways=OSMWays; | ||
97 | relations=OSMRelations; | ||
98 | amb | 1204 | |
99 | amb | 1234 | way_nodes=(node_t*)malloc(256*sizeof(node_t)); |
100 | amb | 1204 | |
101 | amb | 1234 | relation_nodes =(node_t *)malloc(256*sizeof(node_t)); |
102 | relation_ways =(way_t *)malloc(256*sizeof(way_t)); | ||
103 | relation_relations=(relation_t*)malloc(256*sizeof(relation_t)); | ||
104 | amb | 1204 | } |
105 | |||
106 | |||
107 | /*++++++++++++++++++++++++++++++++++++++ | ||
108 | amb | 1356 | Clean up the memory after parsing. |
109 | amb | 2 | ++++++++++++++++++++++++++++++++++++++*/ |
110 | |||
111 | amb | 1356 | void CleanupParser(void) |
112 | amb | 2 | { |
113 | amb | 1221 | /* Free the variables */ |
114 | amb | 394 | |
115 | amb | 1234 | free(way_nodes); |
116 | amb | 394 | |
117 | amb | 1234 | free(relation_nodes); |
118 | free(relation_ways); | ||
119 | free(relation_relations); | ||
120 | amb | 394 | } |
121 | |||
122 | |||
123 | /*++++++++++++++++++++++++++++++++++++++ | ||
124 | amb | 1234 | Add node references to a way. |
125 | |||
126 | int64_t node_id The node ID to add or zero to clear the list. | ||
127 | ++++++++++++++++++++++++++++++++++++++*/ | ||
128 | |||
129 | void AddWayRefs(int64_t node_id) | ||
130 | { | ||
131 | if(node_id==0) | ||
132 | way_nnodes=0; | ||
133 | else | ||
134 | { | ||
135 | node_t id; | ||
136 | |||
137 | if(way_nnodes && (way_nnodes%256)==0) | ||
138 | way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t)); | ||
139 | |||
140 | id=(node_t)node_id; | ||
141 | logassert((int64_t)id==node_id,"Node ID too large (change node_t to 64-bits?)"); /* check node id can be stored in node_t data type. */ | ||
142 | |||
143 | way_nodes[way_nnodes++]=id; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | |||
148 | /*++++++++++++++++++++++++++++++++++++++ | ||
149 | Add node, way or relation references to a relation. | ||
150 | |||
151 | int64_t node_id The node ID to add or zero if it is not a node. | ||
152 | |||
153 | int64_t way_id The way ID to add or zero if it is not a way. | ||
154 | |||
155 | int64_t relation_id The relation ID to add or zero if it is not a relation. | ||
156 | |||
157 | const char *role The role played by this referenced item or NULL. | ||
158 | |||
159 | If all of node_id, way_id and relation_id are zero then the list is cleared. | ||
160 | ++++++++++++++++++++++++++++++++++++++*/ | ||
161 | |||
162 | void AddRelationRefs(int64_t node_id,int64_t way_id,int64_t relation_id,const char *role) | ||
163 | { | ||
164 | if(node_id==0 && way_id==0 && relation_id==0) | ||
165 | { | ||
166 | relation_nnodes=0; | ||
167 | relation_nways=0; | ||
168 | relation_nrelations=0; | ||
169 | amb | 1236 | |
170 | relation_from=NO_WAY_ID; | ||
171 | amb | 1953 | relation_from_count=0; |
172 | relation_from_count=0; | ||
173 | relation_to=NO_WAY_ID; | ||
174 | relation_to_count=0; | ||
175 | amb | 1236 | relation_via=NO_NODE_ID; |
176 | amb | 1954 | relation_via_count=0; |
177 | amb | 1234 | } |
178 | else if(node_id!=0) | ||
179 | { | ||
180 | node_t id; | ||
181 | |||
182 | id=(node_t)node_id; | ||
183 | logassert((int64_t)id==node_id,"Node ID too large (change node_t to 64-bits?)"); /* check node id can be stored in node_t data type. */ | ||
184 | |||
185 | if(relation_nnodes && (relation_nnodes%256)==0) | ||
186 | relation_nodes=(node_t*)realloc((void*)relation_nodes,(relation_nnodes+256)*sizeof(node_t)); | ||
187 | |||
188 | relation_nodes[relation_nnodes++]=id; | ||
189 | |||
190 | if(role) | ||
191 | { | ||
192 | if(!strcmp(role,"via")) | ||
193 | amb | 1954 | { |
194 | relation_via_count++; | ||
195 | if(relation_via==NO_NODE_ID) | ||
196 | relation_via=id; | ||
197 | } | ||
198 | amb | 1234 | } |
199 | } | ||
200 | else if(way_id!=0) | ||
201 | { | ||
202 | way_t id; | ||
203 | |||
204 | id=(way_t)way_id; | ||
205 | logassert((int64_t)id==way_id,"Way ID too large (change way_t to 64-bits?)"); /* check way id can be stored in way_t data type. */ | ||
206 | |||
207 | if(relation_nways && (relation_nways%256)==0) | ||
208 | relation_ways=(way_t*)realloc((void*)relation_ways,(relation_nways+256)*sizeof(way_t)); | ||
209 | |||
210 | relation_ways[relation_nways++]=id; | ||
211 | |||
212 | if(role) | ||
213 | { | ||
214 | if(!strcmp(role,"from")) | ||
215 | amb | 1953 | { |
216 | relation_from_count++; | ||
217 | if(relation_from==NO_WAY_ID) | ||
218 | relation_from=id; | ||
219 | } | ||
220 | amb | 1234 | else if(!strcmp(role,"to")) |
221 | amb | 1953 | { |
222 | relation_to_count++; | ||
223 | if(relation_to==NO_WAY_ID) | ||
224 | relation_to=id; | ||
225 | } | ||
226 | amb | 1234 | } |
227 | } | ||
228 | else /* if(relation_id!=0) */ | ||
229 | { | ||
230 | relation_t id; | ||
231 | |||
232 | id=(relation_t)relation_id; | ||
233 | logassert((int64_t)id==relation_id,"Relation ID too large (change relation_t to 64-bits?)"); /* check relation id can be stored in relation_t data type. */ | ||
234 | |||
235 | if(relation_nrelations && (relation_nrelations%256)==0) | ||
236 | relation_relations=(relation_t*)realloc((void*)relation_relations,(relation_nrelations+256)*sizeof(relation_t)); | ||
237 | |||
238 | relation_relations[relation_nrelations++]=relation_id; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | |||
243 | /*++++++++++++++++++++++++++++++++++++++ | ||
244 | amb | 2170 | Add a node after processing the tags associated with it. |
245 | |||
246 | int64_t node_id The id of the node. | ||
247 | |||
248 | double latitude The latitude of the node. | ||
249 | |||
250 | double longitude The longitude of the node. | ||
251 | |||
252 | int mode The mode of operation to take (create, modify, delete). | ||
253 | |||
254 | TagList *raw_tags The accumulated set of tags for the node. | ||
255 | ++++++++++++++++++++++++++++++++++++++*/ | ||
256 | |||
257 | void AddNode(int64_t node_id,double latitude,double longitude,int mode,TagList *raw_tags) | ||
258 | { | ||
259 | TagList *processed_tags=ApplyNodeTaggingRules(raw_tags,node_id); | ||
260 | |||
261 | ProcessNodeTags(processed_tags,node_id,latitude,longitude,mode); | ||
262 | |||
263 | DeleteTagList(raw_tags); | ||
264 | DeleteTagList(processed_tags); | ||
265 | } | ||
266 | |||
267 | |||
268 | /*++++++++++++++++++++++++++++++++++++++ | ||
269 | Add a way after processing the tags associated with it. | ||
270 | |||
271 | int64_t way_id The id of the way. | ||
272 | |||
273 | int mode The mode of operation to take (create, modify, delete). | ||
274 | |||
275 | TagList *raw_tags The accumulated set of tags for the node. | ||
276 | ++++++++++++++++++++++++++++++++++++++*/ | ||
277 | |||
278 | void AddWay(int64_t way_id,int mode,TagList *raw_tags) | ||
279 | { | ||
280 | TagList *processed_tags=ApplyWayTaggingRules(raw_tags,way_id); | ||
281 | |||
282 | ProcessWayTags(processed_tags,way_id,mode); | ||
283 | |||
284 | DeleteTagList(raw_tags); | ||
285 | DeleteTagList(processed_tags); | ||
286 | } | ||
287 | |||
288 | |||
289 | /*++++++++++++++++++++++++++++++++++++++ | ||
290 | Add a relation after processing the tags associated with it. | ||
291 | |||
292 | int64_t relation_id The id of the relation. | ||
293 | |||
294 | int mode The mode of operation to take (create, modify, delete). | ||
295 | |||
296 | TagList *raw_tags The accumulated set of tags for the node. | ||
297 | ++++++++++++++++++++++++++++++++++++++*/ | ||
298 | |||
299 | void AddRelation(int64_t relation_id,int mode,TagList *raw_tags) | ||
300 | { | ||
301 | TagList *processed_tags=ApplyRelationTaggingRules(raw_tags,relation_id); | ||
302 | |||
303 | ProcessRelationTags(processed_tags,relation_id,mode); | ||
304 | |||
305 | DeleteTagList(raw_tags); | ||
306 | DeleteTagList(processed_tags); | ||
307 | } | ||
308 | |||
309 | |||
310 | /*++++++++++++++++++++++++++++++++++++++ | ||
311 | amb | 469 | Process the tags associated with a node. |
312 | |||
313 | TagList *tags The list of node tags. | ||
314 | |||
315 | amb | 1234 | int64_t node_id The id of the node. |
316 | amb | 469 | |
317 | double latitude The latitude of the node. | ||
318 | |||
319 | double longitude The longitude of the node. | ||
320 | amb | 1221 | |
321 | int mode The mode of operation to take (create, modify, delete). | ||
322 | amb | 469 | ++++++++++++++++++++++++++++++++++++++*/ |
323 | |||
324 | amb | 2170 | static void ProcessNodeTags(TagList *tags,int64_t node_id,double latitude,double longitude,int mode) |
325 | amb | 469 | { |
326 | amb | 529 | transports_t allow=Transports_ALL; |
327 | amb | 1165 | nodeflags_t flags=0; |
328 | amb | 1234 | node_t id; |
329 | amb | 469 | int i; |
330 | |||
331 | amb | 1234 | /* Convert id */ |
332 | |||
333 | id=(node_t)node_id; | ||
334 | logassert((int64_t)id==node_id,"Node ID too large (change node_t to 64-bits?)"); /* check node id can be stored in node_t data type. */ | ||
335 | |||
336 | amb | 1140 | /* Delete */ |
337 | |||
338 | if(mode==MODE_DELETE) | ||
339 | { | ||
340 | amb | 1161 | AppendNodeList(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,NODE_DELETED); |
341 | amb | 1140 | |
342 | return; | ||
343 | } | ||
344 | |||
345 | amb | 469 | /* Parse the tags */ |
346 | |||
347 | for(i=0;i<tags->ntags;i++) | ||
348 | { | ||
349 | amb | 1025 | int recognised=0; |
350 | amb | 469 | char *k=tags->k[i]; |
351 | char *v=tags->v[i]; | ||
352 | |||
353 | switch(*k) | ||
354 | { | ||
355 | case 'b': | ||
356 | if(!strcmp(k,"bicycle")) | ||
357 | amb | 812 | { |
358 | if(ISFALSE(v)) | ||
359 | amb | 529 | allow&=~Transports_Bicycle; |
360 | amb | 812 | else if(!ISTRUE(v)) |
361 | amb | 1313 | logerror("Node %"Pnode_t" has an unrecognised tag 'bicycle' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
362 | amb | 1025 | recognised=1; break; |
363 | amb | 812 | } |
364 | amb | 469 | |
365 | break; | ||
366 | |||
367 | case 'f': | ||
368 | if(!strcmp(k,"foot")) | ||
369 | amb | 812 | { |
370 | if(ISFALSE(v)) | ||
371 | amb | 529 | allow&=~Transports_Foot; |
372 | amb | 812 | else if(!ISTRUE(v)) |
373 | amb | 1313 | logerror("Node %"Pnode_t" has an unrecognised tag 'foot' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
374 | amb | 1025 | recognised=1; break; |
375 | amb | 812 | } |
376 | amb | 469 | |
377 | break; | ||
378 | |||
379 | case 'g': | ||
380 | if(!strcmp(k,"goods")) | ||
381 | amb | 812 | { |
382 | if(ISFALSE(v)) | ||
383 | amb | 529 | allow&=~Transports_Goods; |
384 | amb | 812 | else if(!ISTRUE(v)) |
385 | amb | 1313 | logerror("Node %"Pnode_t" has an unrecognised tag 'goods' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
386 | amb | 1025 | recognised=1; break; |
387 | amb | 812 | } |
388 | amb | 469 | |
389 | break; | ||
390 | |||
391 | case 'h': | ||
392 | if(!strcmp(k,"horse")) | ||
393 | amb | 812 | { |
394 | if(ISFALSE(v)) | ||
395 | amb | 529 | allow&=~Transports_Horse; |
396 | amb | 812 | else if(!ISTRUE(v)) |
397 | amb | 1313 | logerror("Node %"Pnode_t" has an unrecognised tag 'horse' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
398 | amb | 1025 | recognised=1; break; |
399 | amb | 812 | } |
400 | amb | 469 | |
401 | if(!strcmp(k,"hgv")) | ||
402 | amb | 812 | { |
403 | if(ISFALSE(v)) | ||
404 | amb | 529 | allow&=~Transports_HGV; |
405 | amb | 812 | else if(!ISTRUE(v)) |
406 | amb | 1313 | logerror("Node %"Pnode_t" has an unrecognised tag 'hgv' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
407 | amb | 1025 | recognised=1; break; |
408 | amb | 812 | } |
409 | amb | 469 | |
410 | break; | ||
411 | |||
412 | case 'm': | ||
413 | if(!strcmp(k,"moped")) | ||
414 | amb | 812 | { |
415 | if(ISFALSE(v)) | ||
416 | amb | 529 | allow&=~Transports_Moped; |
417 | amb | 812 | else if(!ISTRUE(v)) |
418 | amb | 1313 | logerror("Node %"Pnode_t" has an unrecognised tag 'moped' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
419 | amb | 1025 | recognised=1; break; |
420 | amb | 812 | } |
421 | amb | 469 | |
422 | amb | 1243 | if(!strcmp(k,"motorcycle")) |
423 | amb | 812 | { |
424 | if(ISFALSE(v)) | ||
425 | amb | 1243 | allow&=~Transports_Motorcycle; |
426 | amb | 812 | else if(!ISTRUE(v)) |
427 | amb | 1313 | logerror("Node %"Pnode_t" has an unrecognised tag 'motorcycle' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
428 | amb | 1025 | recognised=1; break; |
429 | amb | 812 | } |
430 | amb | 469 | |
431 | if(!strcmp(k,"motorcar")) | ||
432 | amb | 812 | { |
433 | if(ISFALSE(v)) | ||
434 | amb | 529 | allow&=~Transports_Motorcar; |
435 | amb | 812 | else if(!ISTRUE(v)) |
436 | amb | 1313 | logerror("Node %"Pnode_t" has an unrecognised tag 'motorcar' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
437 | amb | 1025 | recognised=1; break; |
438 | amb | 812 | } |
439 | amb | 469 | |
440 | break; | ||
441 | |||
442 | case 'p': | ||
443 | if(!strcmp(k,"psv")) | ||
444 | amb | 812 | { |
445 | if(ISFALSE(v)) | ||
446 | amb | 529 | allow&=~Transports_PSV; |
447 | amb | 812 | else if(!ISTRUE(v)) |
448 | amb | 1313 | logerror("Node %"Pnode_t" has an unrecognised tag 'psv' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
449 | amb | 1025 | recognised=1; break; |
450 | amb | 812 | } |
451 | amb | 469 | |
452 | break; | ||
453 | |||
454 | amb | 1263 | case 'r': |
455 | if(!strcmp(k,"roundabout")) | ||
456 | { | ||
457 | if(ISTRUE(v)) | ||
458 | flags|=NODE_MINIRNDBT; | ||
459 | else | ||
460 | logerror("Node %"Pnode_t" has an unrecognised tag 'roundabout' = '%s' (after tagging rules); using 'no'.\n",id,v); | ||
461 | recognised=1; break; | ||
462 | } | ||
463 | |||
464 | break; | ||
465 | |||
466 | amb | 469 | case 'w': |
467 | if(!strcmp(k,"wheelchair")) | ||
468 | amb | 812 | { |
469 | if(ISFALSE(v)) | ||
470 | amb | 529 | allow&=~Transports_Wheelchair; |
471 | amb | 812 | else if(!ISTRUE(v)) |
472 | amb | 1313 | logerror("Node %"Pnode_t" has an unrecognised tag 'wheelchair' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
473 | amb | 1025 | recognised=1; break; |
474 | amb | 812 | } |
475 | amb | 469 | |
476 | break; | ||
477 | |||
478 | default: | ||
479 | amb | 1025 | break; |
480 | } | ||
481 | |||
482 | if(!recognised) | ||
483 | amb | 1313 | logerror("Node %"Pnode_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_node(id),k,v); |
484 | amb | 469 | } |
485 | |||
486 | /* Create the node */ | ||
487 | |||
488 | amb | 1161 | AppendNodeList(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,flags); |
489 | amb | 469 | } |
490 | |||
491 | |||
492 | /*++++++++++++++++++++++++++++++++++++++ | ||
493 | amb | 394 | Process the tags associated with a way. |
494 | |||
495 | TagList *tags The list of way tags. | ||
496 | |||
497 | amb | 1234 | int64_t way_id The id of the way. |
498 | amb | 1221 | |
499 | int mode The mode of operation to take (create, modify, delete). | ||
500 | amb | 394 | ++++++++++++++++++++++++++++++++++++++*/ |
501 | |||
502 | amb | 2170 | static void ProcessWayTags(TagList *tags,int64_t way_id,int mode) |
503 | amb | 394 | { |
504 | amb | 1137 | Way way={0}; |
505 | amb | 1339 | int oneway=0,area=0; |
506 | amb | 1559 | int roundabout=0,lanes=0,cyclebothways=0; |
507 | amb | 812 | char *name=NULL,*ref=NULL,*refname=NULL; |
508 | amb | 1234 | way_t id; |
509 | amb | 1347 | int i; |
510 | amb | 394 | |
511 | amb | 1234 | /* Convert id */ |
512 | |||
513 | id=(way_t)way_id; | ||
514 | logassert((int64_t)id==way_id,"Way ID too large (change way_t to 64-bits?)"); /* check way id can be stored in way_t data type. */ | ||
515 | |||
516 | amb | 1140 | /* Delete */ |
517 | |||
518 | amb | 1159 | if(mode==MODE_DELETE || mode==MODE_MODIFY) |
519 | amb | 1140 | { |
520 | way.type=WAY_DELETED; | ||
521 | |||
522 | amb | 1338 | AppendWayList(ways,id,&way,way_nodes,way_nnodes,""); |
523 | amb | 1145 | } |
524 | amb | 1140 | |
525 | amb | 1145 | if(mode==MODE_DELETE) |
526 | amb | 1140 | return; |
527 | |||
528 | amb | 1125 | /* Sanity check */ |
529 | |||
530 | amb | 1234 | if(way_nnodes==0) |
531 | amb | 1125 | { |
532 | amb | 1313 | logerror("Way %"Pway_t" has no nodes.\n",logerror_way(id)); |
533 | amb | 1125 | return; |
534 | } | ||
535 | |||
536 | amb | 1234 | if(way_nnodes==1) |
537 | amb | 1125 | { |
538 | amb | 1336 | logerror_node(way_nodes[0]); /* Extra logerror information since way isn't stored */ |
539 | amb | 1313 | logerror("Way %"Pway_t" has only one node.\n",logerror_way(id)); |
540 | amb | 1125 | return; |
541 | } | ||
542 | |||
543 | amb | 833 | /* Parse the tags - just look for highway */ |
544 | amb | 394 | |
545 | for(i=0;i<tags->ntags;i++) | ||
546 | amb | 2 | { |
547 | amb | 394 | char *k=tags->k[i]; |
548 | char *v=tags->v[i]; | ||
549 | amb | 2 | |
550 | amb | 833 | if(!strcmp(k,"highway")) |
551 | { | ||
552 | way.type=HighwayType(v); | ||
553 | |||
554 | amb | 1174 | if(way.type==Highway_None) |
555 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised highway type '%s' (after tagging rules); ignoring it.\n",logerror_way(id),v); |
556 | amb | 1174 | |
557 | break; | ||
558 | amb | 833 | } |
559 | } | ||
560 | |||
561 | /* Don't continue if this is not a highway (bypass error logging) */ | ||
562 | |||
563 | amb | 1174 | if(way.type==Highway_None) |
564 | amb | 833 | return; |
565 | |||
566 | /* Parse the tags - look for the others */ | ||
567 | |||
568 | for(i=0;i<tags->ntags;i++) | ||
569 | { | ||
570 | amb | 1025 | int recognised=0; |
571 | amb | 833 | char *k=tags->k[i]; |
572 | char *v=tags->v[i]; | ||
573 | |||
574 | amb | 394 | switch(*k) |
575 | { | ||
576 | amb | 914 | case 'a': |
577 | if(!strcmp(k,"area")) | ||
578 | { | ||
579 | if(ISTRUE(v)) | ||
580 | amb | 1339 | area=1; |
581 | amb | 914 | else if(!ISFALSE(v)) |
582 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'area' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
583 | amb | 1025 | recognised=1; break; |
584 | amb | 914 | } |
585 | |||
586 | break; | ||
587 | |||
588 | amb | 394 | case 'b': |
589 | if(!strcmp(k,"bicycle")) | ||
590 | amb | 812 | { |
591 | amb | 394 | if(ISTRUE(v)) |
592 | amb | 813 | way.allow|=Transports_Bicycle; |
593 | amb | 812 | else if(!ISFALSE(v)) |
594 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'bicycle' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
595 | amb | 1025 | recognised=1; break; |
596 | amb | 812 | } |
597 | amb | 394 | |
598 | amb | 498 | if(!strcmp(k,"bicycleroute")) |
599 | amb | 812 | { |
600 | amb | 498 | if(ISTRUE(v)) |
601 | way.props|=Properties_BicycleRoute; | ||
602 | amb | 812 | else if(!ISFALSE(v)) |
603 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
604 | amb | 1025 | recognised=1; break; |
605 | amb | 812 | } |
606 | amb | 498 | |
607 | amb | 394 | if(!strcmp(k,"bridge")) |
608 | amb | 812 | { |
609 | amb | 394 | if(ISTRUE(v)) |
610 | way.props|=Properties_Bridge; | ||
611 | amb | 812 | else if(!ISFALSE(v)) |
612 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'bridge' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
613 | amb | 1025 | recognised=1; break; |
614 | amb | 812 | } |
615 | amb | 394 | |
616 | amb | 2 | break; |
617 | amb | 394 | |
618 | amb | 1497 | case 'c': |
619 | if(!strcmp(k,"cyclebothways")) | ||
620 | { | ||
621 | if(ISTRUE(v)) | ||
622 | amb | 1559 | cyclebothways=1; |
623 | amb | 1497 | else if(!ISFALSE(v)) |
624 | logerror("Way %"Pway_t" has an unrecognised tag 'cyclebothways' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); | ||
625 | recognised=1; break; | ||
626 | } | ||
627 | break; | ||
628 | |||
629 | amb | 394 | case 'f': |
630 | if(!strcmp(k,"foot")) | ||
631 | amb | 812 | { |
632 | amb | 394 | if(ISTRUE(v)) |
633 | amb | 813 | way.allow|=Transports_Foot; |
634 | amb | 812 | else if(!ISFALSE(v)) |
635 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'foot' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
636 | amb | 1025 | recognised=1; break; |
637 | amb | 812 | } |
638 | amb | 394 | |
639 | amb | 498 | if(!strcmp(k,"footroute")) |
640 | amb | 812 | { |
641 | amb | 498 | if(ISTRUE(v)) |
642 | way.props|=Properties_FootRoute; | ||
643 | amb | 812 | else if(!ISFALSE(v)) |
644 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'footroute' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
645 | amb | 1025 | recognised=1; break; |
646 | amb | 812 | } |
647 | amb | 498 | |
648 | amb | 394 | break; |
649 | |||
650 | case 'g': | ||
651 | if(!strcmp(k,"goods")) | ||
652 | amb | 812 | { |
653 | amb | 394 | if(ISTRUE(v)) |
654 | amb | 529 | way.allow|=Transports_Goods; |
655 | amb | 812 | else if(!ISFALSE(v)) |
656 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'goods' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
657 | amb | 1025 | recognised=1; break; |
658 | amb | 812 | } |
659 | amb | 394 | |
660 | break; | ||
661 | |||
662 | case 'h': | ||
663 | if(!strcmp(k,"highway")) | ||
664 | amb | 1025 | {recognised=1; break;} |
665 | amb | 394 | |
666 | if(!strcmp(k,"horse")) | ||
667 | amb | 812 | { |
668 | amb | 394 | if(ISTRUE(v)) |
669 | amb | 529 | way.allow|=Transports_Horse; |
670 | amb | 812 | else if(!ISFALSE(v)) |
671 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'horse' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
672 | amb | 1025 | recognised=1; break; |
673 | amb | 812 | } |
674 | amb | 394 | |
675 | if(!strcmp(k,"hgv")) | ||
676 | amb | 812 | { |
677 | amb | 394 | if(ISTRUE(v)) |
678 | amb | 529 | way.allow|=Transports_HGV; |
679 | amb | 812 | else if(!ISFALSE(v)) |
680 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'hgv' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
681 | amb | 1025 | recognised=1; break; |
682 | amb | 812 | } |
683 | amb | 394 | |
684 | break; | ||
685 | |||
686 | amb | 1247 | case 'l': |
687 | if(!strcmp(k,"lanes")) | ||
688 | { | ||
689 | int en=0; | ||
690 | float lanesf; | ||
691 | if(sscanf(v,"%f%n",&lanesf,&en)==1 && en && !v[en]) | ||
692 | lanes=(int)lanesf; | ||
693 | else | ||
694 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'lanes' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),v); |
695 | amb | 1247 | recognised=1; break; |
696 | } | ||
697 | |||
698 | break; | ||
699 | |||
700 | amb | 394 | case 'm': |
701 | amb | 1025 | if(!strncmp(k,"max",3)) |
702 | { | ||
703 | if(!strcmp(k+3,"speed")) | ||
704 | { | ||
705 | way.speed=kph_to_speed(parse_speed(id,k,v)); | ||
706 | recognised=1; break; | ||
707 | } | ||
708 | amb | 394 | |
709 | amb | 1025 | if(!strcmp(k+3,"weight")) |
710 | { | ||
711 | way.weight=tonnes_to_weight(parse_weight(id,k,v)); | ||
712 | recognised=1; break; | ||
713 | } | ||
714 | amb | 394 | |
715 | amb | 1025 | if(!strcmp(k+3,"height")) |
716 | { | ||
717 | way.height=metres_to_height(parse_length(id,k,v)); | ||
718 | recognised=1; break; | ||
719 | } | ||
720 | amb | 394 | |
721 | amb | 1025 | if(!strcmp(k+3,"width")) |
722 | { | ||
723 | way.width=metres_to_height(parse_length(id,k,v)); | ||
724 | recognised=1; break; | ||
725 | } | ||
726 | amb | 394 | |
727 | amb | 1025 | if(!strcmp(k+3,"length")) |
728 | { | ||
729 | way.length=metres_to_height(parse_length(id,k,v)); | ||
730 | recognised=1; break; | ||
731 | } | ||
732 | } | ||
733 | amb | 394 | |
734 | if(!strcmp(k,"moped")) | ||
735 | amb | 812 | { |
736 | amb | 394 | if(ISTRUE(v)) |
737 | amb | 529 | way.allow|=Transports_Moped; |
738 | amb | 812 | else if(!ISFALSE(v)) |
739 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'moped' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
740 | amb | 1025 | recognised=1; break; |
741 | amb | 812 | } |
742 | amb | 394 | |
743 | amb | 1243 | if(!strcmp(k,"motorcycle")) |
744 | amb | 812 | { |
745 | amb | 394 | if(ISTRUE(v)) |
746 | amb | 1243 | way.allow|=Transports_Motorcycle; |
747 | amb | 812 | else if(!ISFALSE(v)) |
748 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'motorcycle' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
749 | amb | 1025 | recognised=1; break; |
750 | amb | 812 | } |
751 | amb | 394 | |
752 | if(!strcmp(k,"motorcar")) | ||
753 | amb | 812 | { |
754 | amb | 394 | if(ISTRUE(v)) |
755 | amb | 529 | way.allow|=Transports_Motorcar; |
756 | amb | 812 | else if(!ISFALSE(v)) |
757 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'motorcar' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
758 | amb | 1025 | recognised=1; break; |
759 | amb | 812 | } |
760 | amb | 394 | |
761 | if(!strcmp(k,"multilane")) | ||
762 | amb | 812 | { |
763 | amb | 394 | if(ISTRUE(v)) |
764 | way.props|=Properties_Multilane; | ||
765 | amb | 812 | else if(!ISFALSE(v)) |
766 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'multilane' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
767 | amb | 1025 | recognised=1; break; |
768 | amb | 812 | } |
769 | amb | 394 | |
770 | break; | ||
771 | |||
772 | case 'n': | ||
773 | if(!strcmp(k,"name")) | ||
774 | amb | 1025 | { |
775 | amb | 394 | name=v; |
776 | amb | 1025 | recognised=1; break; |
777 | } | ||
778 | amb | 394 | |
779 | break; | ||
780 | |||
781 | case 'o': | ||
782 | if(!strcmp(k,"oneway")) | ||
783 | { | ||
784 | if(ISTRUE(v)) | ||
785 | amb | 1339 | oneway=1; |
786 | amb | 394 | else if(!strcmp(v,"-1")) |
787 | amb | 1339 | oneway=-1; |
788 | amb | 812 | else if(!ISFALSE(v)) |
789 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'oneway' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
790 | amb | 1025 | recognised=1; break; |
791 | amb | 394 | } |
792 | |||
793 | break; | ||
794 | |||
795 | case 'p': | ||
796 | if(!strcmp(k,"paved")) | ||
797 | amb | 812 | { |
798 | amb | 394 | if(ISTRUE(v)) |
799 | way.props|=Properties_Paved; | ||
800 | amb | 812 | else if(!ISFALSE(v)) |
801 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'paved' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
802 | amb | 1025 | recognised=1; break; |
803 | amb | 812 | } |
804 | amb | 394 | |
805 | if(!strcmp(k,"psv")) | ||
806 | amb | 812 | { |
807 | amb | 394 | if(ISTRUE(v)) |
808 | amb | 529 | way.allow|=Transports_PSV; |
809 | amb | 812 | else if(!ISFALSE(v)) |
810 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'psv' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
811 | amb | 1025 | recognised=1; break; |
812 | amb | 812 | } |
813 | amb | 394 | |
814 | break; | ||
815 | |||
816 | case 'r': | ||
817 | if(!strcmp(k,"ref")) | ||
818 | amb | 1025 | { |
819 | amb | 394 | ref=v; |
820 | amb | 1025 | recognised=1; break; |
821 | } | ||
822 | amb | 394 | |
823 | amb | 923 | if(!strcmp(k,"roundabout")) |
824 | { | ||
825 | if(ISTRUE(v)) | ||
826 | roundabout=1; | ||
827 | else if(!ISFALSE(v)) | ||
828 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'roundabout' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
829 | amb | 1025 | recognised=1; break; |
830 | amb | 923 | } |
831 | |||
832 | amb | 394 | break; |
833 | |||
834 | case 't': | ||
835 | if(!strcmp(k,"tunnel")) | ||
836 | amb | 812 | { |
837 | amb | 394 | if(ISTRUE(v)) |
838 | way.props|=Properties_Tunnel; | ||
839 | amb | 812 | else if(!ISFALSE(v)) |
840 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'tunnel' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
841 | amb | 1025 | recognised=1; break; |
842 | amb | 812 | } |
843 | amb | 394 | |
844 | break; | ||
845 | |||
846 | case 'w': | ||
847 | if(!strcmp(k,"wheelchair")) | ||
848 | amb | 812 | { |
849 | amb | 394 | if(ISTRUE(v)) |
850 | amb | 529 | way.allow|=Transports_Wheelchair; |
851 | amb | 812 | else if(!ISFALSE(v)) |
852 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag 'wheelchair' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
853 | amb | 1025 | recognised=1; break; |
854 | amb | 812 | } |
855 | amb | 394 | |
856 | break; | ||
857 | |||
858 | default: | ||
859 | amb | 1025 | break; |
860 | } | ||
861 | |||
862 | if(!recognised) | ||
863 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
864 | amb | 2 | } |
865 | |||
866 | amb | 394 | /* Create the way */ |
867 | amb | 2 | |
868 | amb | 1233 | if(area && oneway) |
869 | { | ||
870 | amb | 1560 | logerror("Way %"Pway_t" is an area and oneway; ignoring area tag.\n",logerror_way(id)); |
871 | amb | 1233 | area=0; |
872 | } | ||
873 | |||
874 | amb | 1559 | if(cyclebothways && !oneway) |
875 | amb | 1497 | { |
876 | amb | 1560 | logerror("Way %"Pway_t" is cyclebothways but not oneway; ignoring cyclebothways tag.\n",logerror_way(id)); |
877 | amb | 1559 | cyclebothways=0; |
878 | amb | 1497 | } |
879 | |||
880 | amb | 1560 | if(roundabout && !oneway) |
881 | { | ||
882 | logerror("Way %"Pway_t" is roundabout but not oneway; adding oneway tag.\n",logerror_way(id)); | ||
883 | oneway=1; | ||
884 | } | ||
885 | |||
886 | amb | 812 | if(!way.allow) |
887 | return; | ||
888 | |||
889 | amb | 1559 | if(cyclebothways) |
890 | way.type|=Highway_CycleBothWays; | ||
891 | |||
892 | amb | 812 | if(oneway) |
893 | amb | 1339 | { |
894 | amb | 1174 | way.type|=Highway_OneWay; |
895 | amb | 394 | |
896 | amb | 1339 | if(oneway==-1) |
897 | for(i=0;i<way_nnodes/2;i++) | ||
898 | { | ||
899 | node_t temp; | ||
900 | |||
901 | temp=way_nodes[i]; | ||
902 | way_nodes[i]=way_nodes[way_nnodes-i-1]; | ||
903 | way_nodes[way_nnodes-i-1]=temp; | ||
904 | } | ||
905 | } | ||
906 | |||
907 | amb | 923 | if(roundabout) |
908 | amb | 1174 | way.type|=Highway_Roundabout; |
909 | amb | 923 | |
910 | amb | 1339 | if(area) |
911 | amb | 1347 | { |
912 | amb | 1339 | way.type|=Highway_Area; |
913 | |||
914 | amb | 1347 | if(way_nodes[0]!=way_nodes[way_nnodes-1]) |
915 | logerror("Way %"Pway_t" is an area but not closed.\n",logerror_way(id)); | ||
916 | } | ||
917 | |||
918 | amb | 1247 | if(lanes) |
919 | { | ||
920 | if(oneway || (lanes/2)>1) | ||
921 | way.props|=Properties_Multilane; | ||
922 | |||
923 | if(oneway && lanes==1) | ||
924 | way.props&=~Properties_Multilane; | ||
925 | } | ||
926 | |||
927 | amb | 812 | if(ref && name) |
928 | { | ||
929 | refname=(char*)malloc(strlen(ref)+strlen(name)+4); | ||
930 | sprintf(refname,"%s (%s)",name,ref); | ||
931 | } | ||
932 | else if(ref && !name) | ||
933 | refname=ref; | ||
934 | else if(!ref && name) | ||
935 | refname=name; | ||
936 | else /* if(!ref && !name) */ | ||
937 | refname=""; | ||
938 | amb | 394 | |
939 | amb | 1338 | AppendWayList(ways,id,&way,way_nodes,way_nnodes,refname); |
940 | amb | 394 | |
941 | amb | 812 | if(ref && name) |
942 | free(refname); | ||
943 | amb | 2 | } |
944 | amb | 498 | |
945 | |||
946 | /*++++++++++++++++++++++++++++++++++++++ | ||
947 | Process the tags associated with a relation. | ||
948 | |||
949 | TagList *tags The list of relation tags. | ||
950 | |||
951 | amb | 1234 | int64_t relation_id The id of the relation. |
952 | amb | 1221 | |
953 | int mode The mode of operation to take (create, modify, delete). | ||
954 | amb | 498 | ++++++++++++++++++++++++++++++++++++++*/ |
955 | |||
956 | amb | 2170 | static void ProcessRelationTags(TagList *tags,int64_t relation_id,int mode) |
957 | amb | 498 | { |
958 | amb | 529 | transports_t routes=Transports_None; |
959 | amb | 540 | transports_t except=Transports_None; |
960 | int relation_turn_restriction=0; | ||
961 | amb | 541 | TurnRestriction restriction=TurnRestrict_None; |
962 | amb | 1234 | relation_t id; |
963 | amb | 498 | int i; |
964 | |||
965 | amb | 1234 | /* Convert id */ |
966 | |||
967 | id=(relation_t)relation_id; | ||
968 | logassert((int64_t)id==relation_id,"Relation ID too large (change relation_t to 64-bits?)"); /* check relation id can be stored in relation_t data type. */ | ||
969 | |||
970 | amb | 1140 | /* Delete */ |
971 | |||
972 | amb | 1152 | if(mode==MODE_DELETE || mode==MODE_MODIFY) |
973 | amb | 1140 | { |
974 | amb | 1161 | AppendRouteRelationList(relations,id,RELATION_DELETED, |
975 | amb | 1370 | relation_nodes,relation_nnodes, |
976 | amb | 1234 | relation_ways,relation_nways, |
977 | relation_relations,relation_nrelations); | ||
978 | amb | 1140 | |
979 | amb | 1161 | AppendTurnRelationList(relations,id, |
980 | amb | 1234 | relation_from,relation_to,relation_via, |
981 | amb | 1161 | restriction,RELATION_DELETED); |
982 | amb | 1152 | } |
983 | amb | 1140 | |
984 | amb | 1152 | if(mode==MODE_DELETE) |
985 | amb | 1140 | return; |
986 | |||
987 | amb | 1125 | /* Sanity check */ |
988 | |||
989 | amb | 1234 | if(relation_nnodes==0 && relation_nways==0 && relation_nrelations==0) |
990 | amb | 1125 | { |
991 | amb | 1313 | logerror("Relation %"Prelation_t" has no nodes, ways or relations.\n",logerror_relation(id)); |
992 | amb | 1125 | return; |
993 | } | ||
994 | |||
995 | amb | 498 | /* Parse the tags */ |
996 | |||
997 | for(i=0;i<tags->ntags;i++) | ||
998 | { | ||
999 | amb | 1025 | int recognised=0; |
1000 | amb | 498 | char *k=tags->k[i]; |
1001 | char *v=tags->v[i]; | ||
1002 | |||
1003 | switch(*k) | ||
1004 | { | ||
1005 | case 'b': | ||
1006 | if(!strcmp(k,"bicycleroute")) | ||
1007 | amb | 812 | { |
1008 | amb | 498 | if(ISTRUE(v)) |
1009 | amb | 529 | routes|=Transports_Bicycle; |
1010 | amb | 812 | else if(!ISFALSE(v)) |
1011 | amb | 1313 | logerror("Relation %"Prelation_t" has an unrecognised tag 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",logerror_relation(id),v); |
1012 | amb | 1025 | recognised=1; break; |
1013 | amb | 812 | } |
1014 | amb | 498 | |
1015 | break; | ||
1016 | |||
1017 | amb | 540 | case 'e': |
1018 | if(!strcmp(k,"except")) | ||
1019 | amb | 812 | { |
1020 | amb | 540 | for(i=1;i<Transport_Count;i++) |
1021 | amb | 876 | if(strstr(v,TransportName(i))) |
1022 | amb | 540 | except|=TRANSPORTS(i); |
1023 | |||
1024 | amb | 812 | if(except==Transports_None) |
1025 | amb | 1313 | logerror("Relation %"Prelation_t" has an unrecognised tag 'except' = '%s' (after tagging rules); ignoring it.\n",logerror_relation(id),v); |
1026 | amb | 1025 | |
1027 | recognised=1; break; | ||
1028 | amb | 812 | } |
1029 | |||
1030 | amb | 540 | break; |
1031 | |||
1032 | amb | 498 | case 'f': |
1033 | if(!strcmp(k,"footroute")) | ||
1034 | amb | 812 | { |
1035 | amb | 498 | if(ISTRUE(v)) |
1036 | amb | 529 | routes|=Transports_Foot; |
1037 | amb | 812 | else if(!ISFALSE(v)) |
1038 | amb | 1313 | logerror("Relation %"Prelation_t" has an unrecognised tag 'footroute' = '%s' (after tagging rules); using 'no'.\n",logerror_relation(id),v); |
1039 | amb | 1025 | recognised=1; break; |
1040 | amb | 812 | } |
1041 | amb | 498 | |
1042 | break; | ||
1043 | |||
1044 | amb | 540 | case 'r': |
1045 | if(!strcmp(k,"restriction")) | ||
1046 | { | ||
1047 | amb | 541 | if(!strcmp(v,"no_right_turn" )) restriction=TurnRestrict_no_right_turn; |
1048 | if(!strcmp(v,"no_left_turn" )) restriction=TurnRestrict_no_left_turn; | ||
1049 | if(!strcmp(v,"no_u_turn" )) restriction=TurnRestrict_no_u_turn; | ||
1050 | if(!strcmp(v,"no_straight_on" )) restriction=TurnRestrict_no_straight_on; | ||
1051 | if(!strcmp(v,"only_right_turn" )) restriction=TurnRestrict_only_right_turn; | ||
1052 | if(!strcmp(v,"only_left_turn" )) restriction=TurnRestrict_only_left_turn; | ||
1053 | if(!strcmp(v,"only_straight_on")) restriction=TurnRestrict_only_straight_on; | ||
1054 | amb | 812 | |
1055 | if(restriction==TurnRestrict_None) | ||
1056 | amb | 1313 | logerror("Relation %"Prelation_t" has an unrecognised tag 'restriction' = '%s' (after tagging rules); ignoring it.\n",logerror_relation(id),v); |
1057 | amb | 1025 | |
1058 | recognised=1; break; | ||
1059 | amb | 540 | } |
1060 | |||
1061 | break; | ||
1062 | |||
1063 | case 't': | ||
1064 | if(!strcmp(k,"type")) | ||
1065 | amb | 1025 | { |
1066 | amb | 540 | if(!strcmp(v,"restriction")) |
1067 | relation_turn_restriction=1; | ||
1068 | amb | 1025 | |
1069 | /* Don't log an error for relations of types that we don't handle - there are so many */ | ||
1070 | recognised=1; break; | ||
1071 | } | ||
1072 | |||
1073 | amb | 540 | break; |
1074 | |||
1075 | amb | 498 | default: |
1076 | amb | 1025 | break; |
1077 | } | ||
1078 | |||
1079 | if(!recognised) | ||
1080 | amb | 1313 | logerror("Relation %"Prelation_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_relation(id),k,v); |
1081 | amb | 498 | } |
1082 | |||
1083 | amb | 505 | /* Create the route relation (must store all relations that have ways or |
1084 | relations even if they are not routes because they might be referenced by | ||
1085 | other relations that are routes) */ | ||
1086 | amb | 498 | |
1087 | amb | 1234 | if((relation_nways || relation_nrelations) && !relation_turn_restriction) |
1088 | amb | 1161 | AppendRouteRelationList(relations,id,routes, |
1089 | amb | 1370 | relation_nodes,relation_nnodes, |
1090 | amb | 1234 | relation_ways,relation_nways, |
1091 | relation_relations,relation_nrelations); | ||
1092 | amb | 540 | |
1093 | /* Create the turn restriction relation. */ | ||
1094 | |||
1095 | amb | 812 | if(relation_turn_restriction && restriction!=TurnRestrict_None) |
1096 | { | ||
1097 | amb | 1234 | if(relation_from==NO_WAY_ID) |
1098 | amb | 1336 | { |
1099 | /* Extra logerror information since relation isn't stored */ | ||
1100 | if(relation_to!=NO_WAY_ID) logerror_way(relation_to); | ||
1101 | if(relation_via!=NO_NODE_ID) logerror_node(relation_via); | ||
1102 | amb | 1953 | logerror("Turn Relation %"Prelation_t" has no 'from' way.\n",logerror_relation(id)); |
1103 | amb | 1336 | } |
1104 | if(relation_to==NO_WAY_ID) | ||
1105 | { | ||
1106 | /* Extra logerror information since relation isn't stored */ | ||
1107 | if(relation_via!=NO_NODE_ID) logerror_node(relation_via); | ||
1108 | if(relation_from!=NO_WAY_ID) logerror_way(relation_from); | ||
1109 | amb | 1953 | logerror("Turn Relation %"Prelation_t" has no 'to' way.\n",logerror_relation(id)); |
1110 | amb | 1336 | } |
1111 | if(relation_via==NO_NODE_ID) | ||
1112 | { | ||
1113 | /* Extra logerror information since relation isn't stored */ | ||
1114 | if(relation_to!=NO_WAY_ID) logerror_way(relation_to); | ||
1115 | if(relation_from!=NO_WAY_ID) logerror_way(relation_from); | ||
1116 | amb | 1953 | logerror("Turn Relation %"Prelation_t" has no 'via' node.\n",logerror_relation(id)); |
1117 | amb | 1336 | } |
1118 | |||
1119 | amb | 1953 | if(relation_from_count>1) |
1120 | { | ||
1121 | if(relation_to!=NO_WAY_ID) logerror_way(relation_to); | ||
1122 | if(relation_via!=NO_NODE_ID) logerror_node(relation_via); | ||
1123 | if(relation_from!=NO_WAY_ID) logerror_way(relation_from); | ||
1124 | logerror("Turn Relation %"Prelation_t" has more than one 'from' Way (used first one).\n",logerror_relation(relation_id)); | ||
1125 | } | ||
1126 | if(relation_to_count>1) | ||
1127 | { | ||
1128 | if(relation_to!=NO_WAY_ID) logerror_way(relation_to); | ||
1129 | if(relation_via!=NO_NODE_ID) logerror_node(relation_via); | ||
1130 | if(relation_from!=NO_WAY_ID) logerror_way(relation_from); | ||
1131 | logerror("Turn Relation %"Prelation_t" has more than one 'to' Way (used first one).\n",logerror_relation(relation_id)); | ||
1132 | } | ||
1133 | amb | 1954 | if(relation_via_count>1) |
1134 | { | ||
1135 | if(relation_to!=NO_WAY_ID) logerror_way(relation_to); | ||
1136 | if(relation_via!=NO_NODE_ID) logerror_node(relation_via); | ||
1137 | if(relation_from!=NO_WAY_ID) logerror_way(relation_from); | ||
1138 | logerror("Turn Relation %"Prelation_t" has more than one 'via' Node (used first one).\n",logerror_relation(relation_id)); | ||
1139 | } | ||
1140 | amb | 1953 | |
1141 | amb | 1336 | if(relation_from!=NO_WAY_ID && relation_to!=NO_WAY_ID && relation_via!=NO_NODE_ID) |
1142 | amb | 1161 | AppendTurnRelationList(relations,id, |
1143 | amb | 1234 | relation_from,relation_to,relation_via, |
1144 | amb | 1161 | restriction,except); |
1145 | amb | 812 | } |
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 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
1168 | amb | 812 | else |
1169 | { | ||
1170 | while(isspace(*ev)) ev++; | ||
1171 | |||
1172 | amb | 1467 | if(*ev==0) |
1173 | return(value); | ||
1174 | |||
1175 | if(!strcmp(ev,"km/h") || !strcmp(ev,"kph") || !strcmp(ev,"kmph")) | ||
1176 | return(value); | ||
1177 | |||
1178 | amb | 812 | if(!strcmp(ev,"mph")) |
1179 | return(1.609*value); | ||
1180 | amb | 813 | |
1181 | amb | 1467 | if(!strcmp(ev,"knots")) |
1182 | return(1.852*value); | ||
1183 | amb | 813 | |
1184 | amb | 1313 | logerror("Way %"Pway_t" has an un-parseable tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
1185 | amb | 812 | } |
1186 | |||
1187 | return(0); | ||
1188 | } | ||
1189 | |||
1190 | |||
1191 | /*++++++++++++++++++++++++++++++++++++++ | ||
1192 | Convert a string containing a weight into a double precision. | ||
1193 | |||
1194 | double parse_weight Returns the weight in tonnes if it can be parsed. | ||
1195 | |||
1196 | way_t id The way being processed. | ||
1197 | |||
1198 | const char *k The tag key. | ||
1199 | |||
1200 | const char *v The tag value. | ||
1201 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1202 | |||
1203 | static double parse_weight(way_t id,const char *k,const char *v) | ||
1204 | { | ||
1205 | char *ev; | ||
1206 | double value=strtod(v,&ev); | ||
1207 | |||
1208 | if(v==ev) | ||
1209 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
1210 | amb | 812 | else |
1211 | { | ||
1212 | while(isspace(*ev)) ev++; | ||
1213 | |||
1214 | amb | 1467 | if(*ev==0) |
1215 | return(value); | ||
1216 | |||
1217 | amb | 812 | if(!strcmp(ev,"kg")) |
1218 | return(value/1000.0); | ||
1219 | amb | 813 | |
1220 | amb | 1467 | if(!strcmp(ev,"T") || !strcmp(ev,"t") || |
1221 | !strcmp(ev,"ton") || !strcmp(ev,"tons") || | ||
1222 | !strcmp(ev,"tonne") || !strcmp(ev,"tonnes")) | ||
1223 | amb | 812 | return(value); |
1224 | amb | 813 | |
1225 | amb | 1313 | logerror("Way %"Pway_t" has an un-parseable tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
1226 | amb | 812 | } |
1227 | |||
1228 | return(0); | ||
1229 | } | ||
1230 | |||
1231 | |||
1232 | /*++++++++++++++++++++++++++++++++++++++ | ||
1233 | Convert a string containing a length into a double precision. | ||
1234 | |||
1235 | double parse_length Returns the length in metres if it can be parsed. | ||
1236 | |||
1237 | way_t id The way being processed. | ||
1238 | |||
1239 | const char *k The tag key. | ||
1240 | |||
1241 | const char *v The tag value. | ||
1242 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1243 | |||
1244 | static double parse_length(way_t id,const char *k,const char *v) | ||
1245 | { | ||
1246 | char *ev; | ||
1247 | double value=strtod(v,&ev); | ||
1248 | |||
1249 | if(v==ev) | ||
1250 | amb | 1313 | logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
1251 | amb | 812 | else |
1252 | { | ||
1253 | amb | 813 | int en=0; |
1254 | int feet=0,inches=0; | ||
1255 | amb | 812 | |
1256 | amb | 1467 | while(isspace(*ev)) ev++; |
1257 | |||
1258 | if(*ev==0) | ||
1259 | return(value); | ||
1260 | |||
1261 | if(!strcmp(ev,"m") || !strcmp(ev,"metre") || !strcmp(ev,"metres") || !strcmp(ev,"meter") || !strcmp(ev,"meters")) | ||
1262 | return(value); | ||
1263 | |||
1264 | if(!strcmp(ev,"'")) | ||
1265 | return(value*0.254); | ||
1266 | |||
1267 | if(!strcmp(ev,"′")) | ||
1268 | return(value*0.254); | ||
1269 | |||
1270 | amb | 2183 | if(!strcmp(ev,"’")) |
1271 | return(value*0.254); | ||
1272 | |||
1273 | amb | 1467 | if(!strcmp(ev,"ft") || !strcmp(ev,"feet")) |
1274 | return(value*0.254); | ||
1275 | |||
1276 | amb | 813 | if(sscanf(v,"%d' %d\"%n",&feet,&inches,&en)==2 && en && !v[en]) |
1277 | amb | 812 | return((feet+(double)inches/12.0)*0.254); |
1278 | amb | 813 | |
1279 | amb | 1127 | if(sscanf(v,"%d'%d\"%n",&feet,&inches,&en)==2 && en && !v[en]) |
1280 | return((feet+(double)inches/12.0)*0.254); | ||
1281 | |||
1282 | if(sscanf(v,"%d'-%d\"%n",&feet,&inches,&en)==2 && en && !v[en]) | ||
1283 | return((feet+(double)inches/12.0)*0.254); | ||
1284 | |||
1285 | amb | 2183 | if(sscanf(v,"%d' %d''%n",&feet,&inches,&en)==2 && en && !v[en]) |
1286 | return((feet+(double)inches/12.0)*0.254); | ||
1287 | |||
1288 | if(sscanf(v,"%d'%d''%n",&feet,&inches,&en)==2 && en && !v[en]) | ||
1289 | return((feet+(double)inches/12.0)*0.254); | ||
1290 | |||
1291 | if(sscanf(v,"%d'-%d''%n",&feet,&inches,&en)==2 && en && !v[en]) | ||
1292 | return((feet+(double)inches/12.0)*0.254); | ||
1293 | |||
1294 | amb | 1467 | if(sscanf(v,"%d′ %d″%n",&feet,&inches,&en)==2 && en && !v[en]) |
1295 | return((feet+(double)inches/12.0)*0.254); | ||
1296 | |||
1297 | if(sscanf(v,"%d′%d″%n",&feet,&inches,&en)==2 && en && !v[en]) | ||
1298 | return((feet+(double)inches/12.0)*0.254); | ||
1299 | |||
1300 | if(sscanf(v,"%d′-%d″%n",&feet,&inches,&en)==2 && en && !v[en]) | ||
1301 | return((feet+(double)inches/12.0)*0.254); | ||
1302 | |||
1303 | amb | 2183 | if(sscanf(v,"%d’ %d”%n",&feet,&inches,&en)==2 && en && !v[en]) |
1304 | return((feet+(double)inches/12.0)*0.254); | ||
1305 | |||
1306 | if(sscanf(v,"%d’%d”%n",&feet,&inches,&en)==2 && en && !v[en]) | ||
1307 | return((feet+(double)inches/12.0)*0.254); | ||
1308 | |||
1309 | if(sscanf(v,"%d’-%d”%n",&feet,&inches,&en)==2 && en && !v[en]) | ||
1310 | return((feet+(double)inches/12.0)*0.254); | ||
1311 | |||
1312 | amb | 813 | if(sscanf(v,"%d - %d%n",&feet,&inches,&en)==2 && en && !v[en]) |
1313 | return((feet+(double)inches/12.0)*0.254); | ||
1314 | |||
1315 | if(sscanf(v,"%d ft %d in%n",&feet,&inches,&en)==2 && en && !v[en]) | ||
1316 | return((feet+(double)inches/12.0)*0.254); | ||
1317 | |||
1318 | amb | 825 | if(sscanf(v,"%d feet %d inches%n",&feet,&inches,&en)==2 && en && !v[en]) |
1319 | return((feet+(double)inches/12.0)*0.254); | ||
1320 | |||
1321 | amb | 1313 | logerror("Way %"Pway_t" has an un-parseable tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
1322 | amb | 812 | } |
1323 | |||
1324 | return(0); | ||
1325 | } |
Properties
Name | Value |
---|---|
cvs:description | OSM XML file parser. |