Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /trunk/src/osmparser.c

Parent Directory Parent Directory | Revision Log 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)
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.