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