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 1243 - (hide annotations) (download) (as text)
Sun Jan 20 14:17:14 2013 UTC (12 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 36075 byte(s)
Replace 'motorbike' with 'motorcycle' everywhere.

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 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 amb 1236
368     relation_from=NO_WAY_ID;
369     relation_via=NO_NODE_ID;
370     relation_to=NO_WAY_ID;
371 amb 1234 }
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 amb 469 Process the tags associated with a node.
427    
428     TagList *tags The list of node tags.
429    
430 amb 1234 int64_t node_id The id of the node.
431 amb 469
432     double latitude The latitude of the node.
433    
434     double longitude The longitude of the node.
435 amb 1221
436     int mode The mode of operation to take (create, modify, delete).
437 amb 469 ++++++++++++++++++++++++++++++++++++++*/
438    
439 amb 1234 void ProcessNodeTags(TagList *tags,int64_t node_id,double latitude,double longitude,int mode)
440 amb 469 {
441 amb 529 transports_t allow=Transports_ALL;
442 amb 1165 nodeflags_t flags=0;
443 amb 1234 node_t id;
444 amb 469 int i;
445    
446 amb 1234 /* 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 amb 1140 /* Delete */
452    
453     if(mode==MODE_DELETE)
454     {
455 amb 1161 AppendNodeList(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,NODE_DELETED);
456 amb 1140
457     return;
458     }
459    
460 amb 469 /* Parse the tags */
461    
462     for(i=0;i<tags->ntags;i++)
463     {
464 amb 1025 int recognised=0;
465 amb 469 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 amb 812 {
473     if(ISFALSE(v))
474 amb 529 allow&=~Transports_Bicycle;
475 amb 812 else if(!ISTRUE(v))
476 amb 813 logerror("Node %"Pnode_t" has an unrecognised tag value 'bicycle' = '%s' (after tagging rules); using 'yes'.\n",id,v);
477 amb 1025 recognised=1; break;
478 amb 812 }
479 amb 469
480     break;
481    
482     case 'f':
483     if(!strcmp(k,"foot"))
484 amb 812 {
485     if(ISFALSE(v))
486 amb 529 allow&=~Transports_Foot;
487 amb 812 else if(!ISTRUE(v))
488 amb 813 logerror("Node %"Pnode_t" has an unrecognised tag value 'foot' = '%s' (after tagging rules); using 'yes'.\n",id,v);
489 amb 1025 recognised=1; break;
490 amb 812 }
491 amb 469
492     break;
493    
494     case 'g':
495     if(!strcmp(k,"goods"))
496 amb 812 {
497     if(ISFALSE(v))
498 amb 529 allow&=~Transports_Goods;
499 amb 812 else if(!ISTRUE(v))
500 amb 813 logerror("Node %"Pnode_t" has an unrecognised tag value 'goods' = '%s' (after tagging rules); using 'yes'.\n",id,v);
501 amb 1025 recognised=1; break;
502 amb 812 }
503 amb 469
504     break;
505    
506     case 'h':
507 amb 537 if(!strcmp(k,"highway"))
508     if(!strcmp(v,"mini_roundabout"))
509 amb 1025 {
510 amb 538 flags|=NODE_MINIRNDBT;
511 amb 1025 recognised=1; break;
512     }
513 amb 537
514 amb 469 if(!strcmp(k,"horse"))
515 amb 812 {
516     if(ISFALSE(v))
517 amb 529 allow&=~Transports_Horse;
518 amb 812 else if(!ISTRUE(v))
519 amb 813 logerror("Node %"Pnode_t" has an unrecognised tag value 'horse' = '%s' (after tagging rules); using 'yes'.\n",id,v);
520 amb 1025 recognised=1; break;
521 amb 812 }
522 amb 469
523     if(!strcmp(k,"hgv"))
524 amb 812 {
525     if(ISFALSE(v))
526 amb 529 allow&=~Transports_HGV;
527 amb 812 else if(!ISTRUE(v))
528 amb 813 logerror("Node %"Pnode_t" has an unrecognised tag value 'hgv' = '%s' (after tagging rules); using 'yes'.\n",id,v);
529 amb 1025 recognised=1; break;
530 amb 812 }
531 amb 469
532     break;
533    
534     case 'm':
535     if(!strcmp(k,"moped"))
536 amb 812 {
537     if(ISFALSE(v))
538 amb 529 allow&=~Transports_Moped;
539 amb 812 else if(!ISTRUE(v))
540 amb 813 logerror("Node %"Pnode_t" has an unrecognised tag value 'moped' = '%s' (after tagging rules); using 'yes'.\n",id,v);
541 amb 1025 recognised=1; break;
542 amb 812 }
543 amb 469
544 amb 1243 if(!strcmp(k,"motorcycle"))
545 amb 812 {
546     if(ISFALSE(v))
547 amb 1243 allow&=~Transports_Motorcycle;
548 amb 812 else if(!ISTRUE(v))
549 amb 1243 logerror("Node %"Pnode_t" has an unrecognised tag value 'motorcycle' = '%s' (after tagging rules); using 'yes'.\n",id,v);
550 amb 1025 recognised=1; break;
551 amb 812 }
552 amb 469
553     if(!strcmp(k,"motorcar"))
554 amb 812 {
555     if(ISFALSE(v))
556 amb 529 allow&=~Transports_Motorcar;
557 amb 812 else if(!ISTRUE(v))
558 amb 813 logerror("Node %"Pnode_t" has an unrecognised tag value 'motorcar' = '%s' (after tagging rules); using 'yes'.\n",id,v);
559 amb 1025 recognised=1; break;
560 amb 812 }
561 amb 469
562     break;
563    
564     case 'p':
565     if(!strcmp(k,"psv"))
566 amb 812 {
567     if(ISFALSE(v))
568 amb 529 allow&=~Transports_PSV;
569 amb 812 else if(!ISTRUE(v))
570 amb 813 logerror("Node %"Pnode_t" has an unrecognised tag value 'psv' = '%s' (after tagging rules); using 'yes'.\n",id,v);
571 amb 1025 recognised=1; break;
572 amb 812 }
573 amb 469
574     break;
575    
576     case 'w':
577     if(!strcmp(k,"wheelchair"))
578 amb 812 {
579     if(ISFALSE(v))
580 amb 529 allow&=~Transports_Wheelchair;
581 amb 812 else if(!ISTRUE(v))
582 amb 813 logerror("Node %"Pnode_t" has an unrecognised tag value 'wheelchair' = '%s' (after tagging rules); using 'yes'.\n",id,v);
583 amb 1025 recognised=1; break;
584 amb 812 }
585 amb 469
586     break;
587    
588     default:
589 amb 1025 break;
590     }
591    
592     if(!recognised)
593 amb 813 logerror("Node %"Pnode_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
594 amb 469 }
595    
596     /* Create the node */
597    
598 amb 1161 AppendNodeList(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,flags);
599 amb 469 }
600    
601    
602     /*++++++++++++++++++++++++++++++++++++++
603 amb 394 Process the tags associated with a way.
604    
605     TagList *tags The list of way tags.
606    
607 amb 1234 int64_t way_id The id of the way.
608 amb 1221
609     int mode The mode of operation to take (create, modify, delete).
610 amb 394 ++++++++++++++++++++++++++++++++++++++*/
611    
612 amb 1234 void ProcessWayTags(TagList *tags,int64_t way_id,int mode)
613 amb 394 {
614 amb 1137 Way way={0};
615 amb 1168 distance_t oneway=0,area=0;
616 amb 1137 int roundabout=0;
617 amb 812 char *name=NULL,*ref=NULL,*refname=NULL;
618 amb 1234 way_t id;
619 amb 1173 int i,j;
620 amb 394
621 amb 1234 /* Convert id */
622    
623     id=(way_t)way_id;
624     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. */
625    
626 amb 1140 /* Delete */
627    
628 amb 1159 if(mode==MODE_DELETE || mode==MODE_MODIFY)
629 amb 1140 {
630     way.type=WAY_DELETED;
631    
632 amb 1161 AppendWayList(ways,id,&way,"");
633 amb 1140
634 amb 1174 way.type=Highway_None;
635 amb 1154
636 amb 1168 AppendSegmentList(segments,id,NO_NODE_ID,NO_NODE_ID,0);
637 amb 1145 }
638 amb 1140
639 amb 1145 if(mode==MODE_DELETE)
640 amb 1140 return;
641    
642 amb 1125 /* Sanity check */
643    
644 amb 1234 if(way_nnodes==0)
645 amb 1125 {
646     logerror("Way %"Pway_t" has no nodes.\n",id);
647     return;
648     }
649    
650 amb 1234 if(way_nnodes==1)
651 amb 1125 {
652     logerror("Way %"Pway_t" has only one node.\n",id);
653     return;
654     }
655    
656 amb 833 /* Parse the tags - just look for highway */
657 amb 394
658     for(i=0;i<tags->ntags;i++)
659 amb 2 {
660 amb 394 char *k=tags->k[i];
661     char *v=tags->v[i];
662 amb 2
663 amb 833 if(!strcmp(k,"highway"))
664     {
665     way.type=HighwayType(v);
666    
667 amb 1174 if(way.type==Highway_None)
668 amb 833 logerror("Way %"Pway_t" has an unrecognised highway type '%s' (after tagging rules); ignoring it.\n",id,v);
669 amb 1174
670     break;
671 amb 833 }
672     }
673    
674     /* Don't continue if this is not a highway (bypass error logging) */
675    
676 amb 1174 if(way.type==Highway_None)
677 amb 833 return;
678    
679     /* Parse the tags - look for the others */
680    
681     for(i=0;i<tags->ntags;i++)
682     {
683 amb 1025 int recognised=0;
684 amb 833 char *k=tags->k[i];
685     char *v=tags->v[i];
686    
687 amb 394 switch(*k)
688     {
689 amb 914 case 'a':
690     if(!strcmp(k,"area"))
691     {
692     if(ISTRUE(v))
693 amb 1137 area=SEGMENT_AREA;
694 amb 914 else if(!ISFALSE(v))
695     logerror("Way %"Pway_t" has an unrecognised tag value 'area' = '%s' (after tagging rules); using 'no'.\n",id,v);
696 amb 1025 recognised=1; break;
697 amb 914 }
698    
699     break;
700    
701 amb 394 case 'b':
702     if(!strcmp(k,"bicycle"))
703 amb 812 {
704 amb 394 if(ISTRUE(v))
705 amb 813 way.allow|=Transports_Bicycle;
706 amb 812 else if(!ISFALSE(v))
707 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'bicycle' = '%s' (after tagging rules); using 'no'.\n",id,v);
708 amb 1025 recognised=1; break;
709 amb 812 }
710 amb 394
711 amb 498 if(!strcmp(k,"bicycleroute"))
712 amb 812 {
713 amb 498 if(ISTRUE(v))
714     way.props|=Properties_BicycleRoute;
715 amb 812 else if(!ISFALSE(v))
716 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
717 amb 1025 recognised=1; break;
718 amb 812 }
719 amb 498
720 amb 394 if(!strcmp(k,"bridge"))
721 amb 812 {
722 amb 394 if(ISTRUE(v))
723     way.props|=Properties_Bridge;
724 amb 812 else if(!ISFALSE(v))
725 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'bridge' = '%s' (after tagging rules); using 'no'.\n",id,v);
726 amb 1025 recognised=1; break;
727 amb 812 }
728 amb 394
729 amb 2 break;
730 amb 394
731     case 'f':
732     if(!strcmp(k,"foot"))
733 amb 812 {
734 amb 394 if(ISTRUE(v))
735 amb 813 way.allow|=Transports_Foot;
736 amb 812 else if(!ISFALSE(v))
737 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'foot' = '%s' (after tagging rules); using 'no'.\n",id,v);
738 amb 1025 recognised=1; break;
739 amb 812 }
740 amb 394
741 amb 498 if(!strcmp(k,"footroute"))
742 amb 812 {
743 amb 498 if(ISTRUE(v))
744     way.props|=Properties_FootRoute;
745 amb 812 else if(!ISFALSE(v))
746 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'footroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
747 amb 1025 recognised=1; break;
748 amb 812 }
749 amb 498
750 amb 394 break;
751    
752     case 'g':
753     if(!strcmp(k,"goods"))
754 amb 812 {
755 amb 394 if(ISTRUE(v))
756 amb 529 way.allow|=Transports_Goods;
757 amb 812 else if(!ISFALSE(v))
758 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'goods' = '%s' (after tagging rules); using 'no'.\n",id,v);
759 amb 1025 recognised=1; break;
760 amb 812 }
761 amb 394
762     break;
763    
764     case 'h':
765     if(!strcmp(k,"highway"))
766 amb 1025 {recognised=1; break;}
767 amb 394
768     if(!strcmp(k,"horse"))
769 amb 812 {
770 amb 394 if(ISTRUE(v))
771 amb 529 way.allow|=Transports_Horse;
772 amb 812 else if(!ISFALSE(v))
773 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'horse' = '%s' (after tagging rules); using 'no'.\n",id,v);
774 amb 1025 recognised=1; break;
775 amb 812 }
776 amb 394
777     if(!strcmp(k,"hgv"))
778 amb 812 {
779 amb 394 if(ISTRUE(v))
780 amb 529 way.allow|=Transports_HGV;
781 amb 812 else if(!ISFALSE(v))
782 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'hgv' = '%s' (after tagging rules); using 'no'.\n",id,v);
783 amb 1025 recognised=1; break;
784 amb 812 }
785 amb 394
786     break;
787    
788     case 'm':
789 amb 1025 if(!strncmp(k,"max",3))
790     {
791     if(!strcmp(k+3,"speed"))
792     {
793     way.speed=kph_to_speed(parse_speed(id,k,v));
794     recognised=1; break;
795     }
796 amb 394
797 amb 1025 if(!strcmp(k+3,"weight"))
798     {
799     way.weight=tonnes_to_weight(parse_weight(id,k,v));
800     recognised=1; break;
801     }
802 amb 394
803 amb 1025 if(!strcmp(k+3,"height"))
804     {
805     way.height=metres_to_height(parse_length(id,k,v));
806     recognised=1; break;
807     }
808 amb 394
809 amb 1025 if(!strcmp(k+3,"width"))
810     {
811     way.width=metres_to_height(parse_length(id,k,v));
812     recognised=1; break;
813     }
814 amb 394
815 amb 1025 if(!strcmp(k+3,"length"))
816     {
817     way.length=metres_to_height(parse_length(id,k,v));
818     recognised=1; break;
819     }
820     }
821 amb 394
822     if(!strcmp(k,"moped"))
823 amb 812 {
824 amb 394 if(ISTRUE(v))
825 amb 529 way.allow|=Transports_Moped;
826 amb 812 else if(!ISFALSE(v))
827 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'moped' = '%s' (after tagging rules); using 'no'.\n",id,v);
828 amb 1025 recognised=1; break;
829 amb 812 }
830 amb 394
831 amb 1243 if(!strcmp(k,"motorcycle"))
832 amb 812 {
833 amb 394 if(ISTRUE(v))
834 amb 1243 way.allow|=Transports_Motorcycle;
835 amb 812 else if(!ISFALSE(v))
836 amb 1243 logerror("Way %"Pway_t" has an unrecognised tag value 'motorcycle' = '%s' (after tagging rules); using 'no'.\n",id,v);
837 amb 1025 recognised=1; break;
838 amb 812 }
839 amb 394
840     if(!strcmp(k,"motorcar"))
841 amb 812 {
842 amb 394 if(ISTRUE(v))
843 amb 529 way.allow|=Transports_Motorcar;
844 amb 812 else if(!ISFALSE(v))
845 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'motorcar' = '%s' (after tagging rules); using 'no'.\n",id,v);
846 amb 1025 recognised=1; break;
847 amb 812 }
848 amb 394
849     if(!strcmp(k,"multilane"))
850 amb 812 {
851 amb 394 if(ISTRUE(v))
852     way.props|=Properties_Multilane;
853 amb 812 else if(!ISFALSE(v))
854 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'multilane' = '%s' (after tagging rules); using 'no'.\n",id,v);
855 amb 1025 recognised=1; break;
856 amb 812 }
857 amb 394
858     break;
859    
860     case 'n':
861     if(!strcmp(k,"name"))
862 amb 1025 {
863 amb 394 name=v;
864 amb 1025 recognised=1; break;
865     }
866 amb 394
867     break;
868    
869     case 'o':
870     if(!strcmp(k,"oneway"))
871     {
872     if(ISTRUE(v))
873 amb 1137 oneway=ONEWAY_1TO2;
874 amb 394 else if(!strcmp(v,"-1"))
875 amb 1137 oneway=ONEWAY_2TO1;
876 amb 812 else if(!ISFALSE(v))
877 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'oneway' = '%s' (after tagging rules); using 'no'.\n",id,v);
878 amb 1025 recognised=1; break;
879 amb 394 }
880    
881     break;
882    
883     case 'p':
884     if(!strcmp(k,"paved"))
885 amb 812 {
886 amb 394 if(ISTRUE(v))
887     way.props|=Properties_Paved;
888 amb 812 else if(!ISFALSE(v))
889 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'paved' = '%s' (after tagging rules); using 'no'.\n",id,v);
890 amb 1025 recognised=1; break;
891 amb 812 }
892 amb 394
893     if(!strcmp(k,"psv"))
894 amb 812 {
895 amb 394 if(ISTRUE(v))
896 amb 529 way.allow|=Transports_PSV;
897 amb 812 else if(!ISFALSE(v))
898 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'psv' = '%s' (after tagging rules); using 'no'.\n",id,v);
899 amb 1025 recognised=1; break;
900 amb 812 }
901 amb 394
902     break;
903    
904     case 'r':
905     if(!strcmp(k,"ref"))
906 amb 1025 {
907 amb 394 ref=v;
908 amb 1025 recognised=1; break;
909     }
910 amb 394
911 amb 923 if(!strcmp(k,"roundabout"))
912     {
913     if(ISTRUE(v))
914     roundabout=1;
915     else if(!ISFALSE(v))
916     logerror("Way %"Pway_t" has an unrecognised tag value 'roundabout' = '%s' (after tagging rules); using 'no'.\n",id,v);
917 amb 1025 recognised=1; break;
918 amb 923 }
919    
920 amb 394 break;
921    
922     case 't':
923     if(!strcmp(k,"tunnel"))
924 amb 812 {
925 amb 394 if(ISTRUE(v))
926     way.props|=Properties_Tunnel;
927 amb 812 else if(!ISFALSE(v))
928 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'tunnel' = '%s' (after tagging rules); using 'no'.\n",id,v);
929 amb 1025 recognised=1; break;
930 amb 812 }
931 amb 394
932     break;
933    
934     case 'w':
935     if(!strcmp(k,"wheelchair"))
936 amb 812 {
937 amb 394 if(ISTRUE(v))
938 amb 529 way.allow|=Transports_Wheelchair;
939 amb 812 else if(!ISFALSE(v))
940 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value 'wheelchair' = '%s' (after tagging rules); using 'no'.\n",id,v);
941 amb 1025 recognised=1; break;
942 amb 812 }
943 amb 394
944     break;
945    
946     default:
947 amb 1025 break;
948     }
949    
950     if(!recognised)
951 amb 813 logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
952 amb 2 }
953    
954 amb 394 /* Create the way */
955 amb 2
956 amb 1233 if(area && oneway)
957     {
958     logerror("Way %"Pway_t" is an area and oneway; ignoring area tagging.\n",id);
959     area=0;
960     }
961    
962 amb 812 if(!way.allow)
963     return;
964    
965     if(oneway)
966 amb 1174 way.type|=Highway_OneWay;
967 amb 394
968 amb 923 if(roundabout)
969 amb 1174 way.type|=Highway_Roundabout;
970 amb 923
971 amb 812 if(ref && name)
972     {
973     refname=(char*)malloc(strlen(ref)+strlen(name)+4);
974     sprintf(refname,"%s (%s)",name,ref);
975     }
976     else if(ref && !name)
977     refname=ref;
978     else if(!ref && name)
979     refname=name;
980     else /* if(!ref && !name) */
981     refname="";
982 amb 394
983 amb 1161 AppendWayList(ways,id,&way,refname);
984 amb 394
985 amb 812 if(ref && name)
986     free(refname);
987 amb 394
988 amb 1234 if(area && way_nodes[0]!=way_nodes[way_nnodes-1])
989 amb 1232 logerror("Way %"Pway_t" is an area but not closed.\n",id);
990    
991 amb 1234 for(i=1;i<way_nnodes;i++)
992 amb 812 {
993 amb 1234 node_t from=way_nodes[i-1];
994     node_t to =way_nodes[i];
995 amb 812
996 amb 1231 if(from==to)
997     logerror("Node %"Pnode_t" in way %"Pway_t" is connected to itself.\n",from,id);
998     else
999 amb 1173 {
1000 amb 1231 int nto=1,duplicated=0;
1001 amb 1173
1002 amb 1231 for(j=1;j<i;j++)
1003     {
1004 amb 1234 node_t n1=way_nodes[j-1];
1005     node_t n2=way_nodes[j];
1006 amb 1231
1007 amb 1234 if(n1==to && (i!=way_nnodes-1 || j!=1))
1008 amb 1231 nto++;
1009    
1010     if((n1==from && n2==to) || (n2==from && n1==to))
1011     {
1012     duplicated=1;
1013     logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" in way %"Pway_t" is duplicated.\n",n1,n2,id);
1014     }
1015     }
1016    
1017     if(nto>=2 && !duplicated)
1018     logerror("Node %"Pnode_t" in way %"Pway_t" appears more than once.\n",to,id);
1019    
1020     if(!duplicated)
1021     AppendSegmentList(segments,id,from,to,area+oneway);
1022 amb 1173 }
1023 amb 394 }
1024 amb 2 }
1025 amb 498
1026    
1027     /*++++++++++++++++++++++++++++++++++++++
1028     Process the tags associated with a relation.
1029    
1030     TagList *tags The list of relation tags.
1031    
1032 amb 1234 int64_t relation_id The id of the relation.
1033 amb 1221
1034     int mode The mode of operation to take (create, modify, delete).
1035 amb 498 ++++++++++++++++++++++++++++++++++++++*/
1036    
1037 amb 1234 void ProcessRelationTags(TagList *tags,int64_t relation_id,int mode)
1038 amb 498 {
1039 amb 529 transports_t routes=Transports_None;
1040 amb 540 transports_t except=Transports_None;
1041     int relation_turn_restriction=0;
1042 amb 541 TurnRestriction restriction=TurnRestrict_None;
1043 amb 1234 relation_t id;
1044 amb 498 int i;
1045    
1046 amb 1234 /* Convert id */
1047    
1048     id=(relation_t)relation_id;
1049     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. */
1050    
1051 amb 1140 /* Delete */
1052    
1053 amb 1152 if(mode==MODE_DELETE || mode==MODE_MODIFY)
1054 amb 1140 {
1055 amb 1161 AppendRouteRelationList(relations,id,RELATION_DELETED,
1056 amb 1234 relation_ways,relation_nways,
1057     relation_relations,relation_nrelations);
1058 amb 1140
1059 amb 1161 AppendTurnRelationList(relations,id,
1060 amb 1234 relation_from,relation_to,relation_via,
1061 amb 1161 restriction,RELATION_DELETED);
1062 amb 1152 }
1063 amb 1140
1064 amb 1152 if(mode==MODE_DELETE)
1065 amb 1140 return;
1066    
1067 amb 1125 /* Sanity check */
1068    
1069 amb 1234 if(relation_nnodes==0 && relation_nways==0 && relation_nrelations==0)
1070 amb 1125 {
1071     logerror("Relation %"Prelation_t" has no nodes, ways or relations.\n",id);
1072     return;
1073     }
1074    
1075 amb 498 /* Parse the tags */
1076    
1077     for(i=0;i<tags->ntags;i++)
1078     {
1079 amb 1025 int recognised=0;
1080 amb 498 char *k=tags->k[i];
1081     char *v=tags->v[i];
1082    
1083     switch(*k)
1084     {
1085     case 'b':
1086     if(!strcmp(k,"bicycleroute"))
1087 amb 812 {
1088 amb 498 if(ISTRUE(v))
1089 amb 529 routes|=Transports_Bicycle;
1090 amb 812 else if(!ISFALSE(v))
1091 amb 813 logerror("Relation %"Prelation_t" has an unrecognised tag value 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
1092 amb 1025 recognised=1; break;
1093 amb 812 }
1094 amb 498
1095     break;
1096    
1097 amb 540 case 'e':
1098     if(!strcmp(k,"except"))
1099 amb 812 {
1100 amb 540 for(i=1;i<Transport_Count;i++)
1101 amb 876 if(strstr(v,TransportName(i)))
1102 amb 540 except|=TRANSPORTS(i);
1103    
1104 amb 812 if(except==Transports_None)
1105 amb 813 logerror("Relation %"Prelation_t" has an unrecognised tag value 'except' = '%s' (after tagging rules); ignoring it.\n",id,v);
1106 amb 1025
1107     recognised=1; break;
1108 amb 812 }
1109    
1110 amb 540 break;
1111    
1112 amb 498 case 'f':
1113     if(!strcmp(k,"footroute"))
1114 amb 812 {
1115 amb 498 if(ISTRUE(v))
1116 amb 529 routes|=Transports_Foot;
1117 amb 812 else if(!ISFALSE(v))
1118 amb 813 logerror("Relation %"Prelation_t" has an unrecognised tag value 'footroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
1119 amb 1025 recognised=1; break;
1120 amb 812 }
1121 amb 498
1122     break;
1123    
1124 amb 540 case 'r':
1125     if(!strcmp(k,"restriction"))
1126     {
1127 amb 541 if(!strcmp(v,"no_right_turn" )) restriction=TurnRestrict_no_right_turn;
1128     if(!strcmp(v,"no_left_turn" )) restriction=TurnRestrict_no_left_turn;
1129     if(!strcmp(v,"no_u_turn" )) restriction=TurnRestrict_no_u_turn;
1130     if(!strcmp(v,"no_straight_on" )) restriction=TurnRestrict_no_straight_on;
1131     if(!strcmp(v,"only_right_turn" )) restriction=TurnRestrict_only_right_turn;
1132     if(!strcmp(v,"only_left_turn" )) restriction=TurnRestrict_only_left_turn;
1133     if(!strcmp(v,"only_straight_on")) restriction=TurnRestrict_only_straight_on;
1134 amb 812
1135     if(restriction==TurnRestrict_None)
1136 amb 813 logerror("Relation %"Prelation_t" has an unrecognised tag value 'restriction' = '%s' (after tagging rules); ignoring it.\n",id,v);
1137 amb 1025
1138     recognised=1; break;
1139 amb 540 }
1140    
1141     break;
1142    
1143     case 't':
1144     if(!strcmp(k,"type"))
1145 amb 1025 {
1146 amb 540 if(!strcmp(v,"restriction"))
1147     relation_turn_restriction=1;
1148 amb 1025
1149     /* Don't log an error for relations of types that we don't handle - there are so many */
1150     recognised=1; break;
1151     }
1152    
1153 amb 540 break;
1154    
1155 amb 498 default:
1156 amb 1025 break;
1157     }
1158    
1159     if(!recognised)
1160 amb 813 logerror("Relation %"Prelation_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1161 amb 498 }
1162    
1163 amb 505 /* Create the route relation (must store all relations that have ways or
1164     relations even if they are not routes because they might be referenced by
1165     other relations that are routes) */
1166 amb 498
1167 amb 1234 if((relation_nways || relation_nrelations) && !relation_turn_restriction)
1168 amb 1161 AppendRouteRelationList(relations,id,routes,
1169 amb 1234 relation_ways,relation_nways,
1170     relation_relations,relation_nrelations);
1171 amb 540
1172     /* Create the turn restriction relation. */
1173    
1174 amb 812 if(relation_turn_restriction && restriction!=TurnRestrict_None)
1175     {
1176 amb 1234 if(relation_from==NO_WAY_ID)
1177 amb 813 logerror("Relation %"Prelation_t" is a turn restriction but has no 'from' way.\n",id);
1178 amb 1234 else if(relation_to==NO_WAY_ID)
1179 amb 813 logerror("Relation %"Prelation_t" is a turn restriction but has no 'to' way.\n",id);
1180 amb 1234 else if(relation_via==NO_NODE_ID)
1181 amb 813 logerror("Relation %"Prelation_t" is a turn restriction but has no 'via' node.\n",id);
1182 amb 812 else
1183 amb 1161 AppendTurnRelationList(relations,id,
1184 amb 1234 relation_from,relation_to,relation_via,
1185 amb 1161 restriction,except);
1186 amb 812 }
1187 amb 498 }
1188 amb 812
1189    
1190     /*++++++++++++++++++++++++++++++++++++++
1191     Convert a string containing a speed into a double precision.
1192    
1193     double parse_speed Returns the speed in km/h if it can be parsed.
1194    
1195     way_t id The way being processed.
1196    
1197     const char *k The tag key.
1198    
1199     const char *v The tag value.
1200     ++++++++++++++++++++++++++++++++++++++*/
1201    
1202     static double parse_speed(way_t id,const char *k,const char *v)
1203     {
1204     char *ev;
1205     double value=strtod(v,&ev);
1206    
1207     if(v==ev)
1208 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1209 amb 812 else
1210     {
1211     while(isspace(*ev)) ev++;
1212    
1213     if(!strcmp(ev,"mph"))
1214     return(1.609*value);
1215 amb 813
1216     if(*ev==0 || !strcmp(ev,"kph"))
1217 amb 812 return(value);
1218 amb 813
1219     logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1220 amb 812 }
1221    
1222     return(0);
1223     }
1224    
1225    
1226     /*++++++++++++++++++++++++++++++++++++++
1227     Convert a string containing a weight into a double precision.
1228    
1229     double parse_weight Returns the weight in tonnes if it can be parsed.
1230    
1231     way_t id The way being processed.
1232    
1233     const char *k The tag key.
1234    
1235     const char *v The tag value.
1236     ++++++++++++++++++++++++++++++++++++++*/
1237    
1238     static double parse_weight(way_t id,const char *k,const char *v)
1239     {
1240     char *ev;
1241     double value=strtod(v,&ev);
1242    
1243     if(v==ev)
1244 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1245 amb 812 else
1246     {
1247     while(isspace(*ev)) ev++;
1248    
1249     if(!strcmp(ev,"kg"))
1250     return(value/1000.0);
1251 amb 813
1252 amb 825 if(*ev==0 || !strcmp(ev,"T") || !strcmp(ev,"t")
1253     || !strcmp(ev,"ton") || !strcmp(ev,"tons")
1254     || !strcmp(ev,"tonne") || !strcmp(ev,"tonnes"))
1255 amb 812 return(value);
1256 amb 813
1257     logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1258 amb 812 }
1259    
1260     return(0);
1261     }
1262    
1263    
1264     /*++++++++++++++++++++++++++++++++++++++
1265     Convert a string containing a length into a double precision.
1266    
1267     double parse_length Returns the length in metres if it can be parsed.
1268    
1269     way_t id The way being processed.
1270    
1271     const char *k The tag key.
1272    
1273     const char *v The tag value.
1274     ++++++++++++++++++++++++++++++++++++++*/
1275    
1276     static double parse_length(way_t id,const char *k,const char *v)
1277     {
1278     char *ev;
1279     double value=strtod(v,&ev);
1280    
1281     if(v==ev)
1282 amb 813 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1283 amb 812 else
1284     {
1285 amb 813 int en=0;
1286     int feet=0,inches=0;
1287 amb 812
1288 amb 813 if(sscanf(v,"%d' %d\"%n",&feet,&inches,&en)==2 && en && !v[en])
1289 amb 812 return((feet+(double)inches/12.0)*0.254);
1290 amb 813
1291 amb 1127 if(sscanf(v,"%d'%d\"%n",&feet,&inches,&en)==2 && en && !v[en])
1292     return((feet+(double)inches/12.0)*0.254);
1293    
1294     if(sscanf(v,"%d'-%d\"%n",&feet,&inches,&en)==2 && en && !v[en])
1295     return((feet+(double)inches/12.0)*0.254);
1296    
1297 amb 813 if(sscanf(v,"%d - %d%n",&feet,&inches,&en)==2 && en && !v[en])
1298     return((feet+(double)inches/12.0)*0.254);
1299    
1300     if(sscanf(v,"%d ft %d in%n",&feet,&inches,&en)==2 && en && !v[en])
1301     return((feet+(double)inches/12.0)*0.254);
1302    
1303 amb 825 if(sscanf(v,"%d feet %d inches%n",&feet,&inches,&en)==2 && en && !v[en])
1304     return((feet+(double)inches/12.0)*0.254);
1305    
1306     if(!strcmp(ev,"'"))
1307 amb 812 return(feet*0.254);
1308 amb 813
1309     while(isspace(*ev)) ev++;
1310    
1311     if(!strcmp(ev,"ft") || !strcmp(ev,"feet"))
1312 amb 812 return(value*0.254);
1313 amb 813
1314 amb 825 if(*ev==0 || !strcmp(ev,"m") || !strcmp(ev,"metre") || !strcmp(ev,"metres"))
1315 amb 812 return(value);
1316 amb 813
1317     logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1318 amb 812 }
1319    
1320     return(0);
1321     }

Properties

Name Value
cvs:description OSM XML file parser.