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 2183 - (hide annotations) (download) (as text)
Tue Aug 29 10:28:56 2023 UTC (18 months, 4 weeks ago) by amb
File MIME type: text/x-csrc
File size: 38141 byte(s)
Add new parsers for heights/widths in feet and inches format.

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

Properties

Name Value
cvs:description OSM XML file parser.