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