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 1234 - (hide annotations) (download) (as text)
Sat Dec 29 11:11:11 2012 UTC (12 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 35983 byte(s)
Re-factor parsing code to remove duplicated parts from three parsers
(osmo5mparse.c, osmpbfparse.c and osmxmlparse.c) into a common place
(osmparser.c), also removes lots of global variables.
Change the node, way and relation count to uint64_t instead of index_t to avoid
wrap-around (although it would have been a cosmetic problem only), also removes
dependency on types.h.
Make the node, way and relation counters be 'int64_t' instead of 'long long' in
the XML parsers for consistency with the non-XML parsers.

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

Properties

Name Value
cvs:description OSM XML file parser.