Routino SVN Repository Browser

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

ViewVC logotype

Contents of /trunk/src/osmparser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 812 - (show annotations) (download) (as text)
Thu Jul 21 18:44:52 2011 UTC (13 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 36768 byte(s)
Add logging of parsing and processing errors.

1 /***************************************
2 OSM XML file parser (either JOSM or planet)
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2011 Andrew M. Bishop
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Affero General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ***************************************/
21
22
23 #include <assert.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28
29 #include "typesx.h"
30 #include "functionsx.h"
31
32 #include "nodesx.h"
33 #include "segmentsx.h"
34 #include "waysx.h"
35 #include "relationsx.h"
36
37 #include "xmlparse.h"
38 #include "tagging.h"
39
40 #include "logging.h"
41
42
43 /* Macros */
44
45 /*+ Checks if a value in the XML is one of the allowed values for true. +*/
46 #define ISTRUE(xx) (!strcmp(xx,"true") || !strcmp(xx,"yes") || !strcmp(xx,"1"))
47
48 /*+ Checks if a value in the XML is one of the allowed values for false. +*/
49 #define ISFALSE(xx) (!strcmp(xx,"false") || !strcmp(xx,"no") || !strcmp(xx,"0"))
50
51
52 /* Local variables */
53
54 static index_t nnodes=0;
55 static index_t nways=0;
56 static index_t nrelations=0;
57
58 static TagList *current_tags=NULL;
59
60 static node_t *way_nodes=NULL;
61 static int way_nnodes=0;
62
63 static node_t *relation_nodes=NULL;
64 static int relation_nnodes=0;
65 static way_t *relation_ways=NULL;
66 static int relation_nways=0;
67 static relation_t *relation_relations=NULL;
68 static int relation_nrelations=0;
69 static way_t relation_from=NO_WAY_ID;
70 static way_t relation_to=NO_WAY_ID;
71 static node_t relation_via=NO_NODE_ID;
72
73 static NodesX *nodes;
74 static SegmentsX *segments;
75 static WaysX *ways;
76 static RelationsX *relations;
77
78
79 /* Local functions */
80
81 static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude);
82 static void process_way_tags(TagList *tags,way_t id);
83 static void process_relation_tags(TagList *tags,relation_t id);
84
85 static double parse_speed(way_t id,const char *k,const char *v);
86 static double parse_weight(way_t id,const char *k,const char *v);
87 static double parse_length(way_t id,const char *k,const char *v);
88
89
90 /* The XML tag processing function prototypes */
91
92 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding);
93 //static int osmType_function(const char *_tag_,int _type_);
94 static int relationType_function(const char *_tag_,int _type_,const char *id);
95 static int wayType_function(const char *_tag_,int _type_,const char *id);
96 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role);
97 static int ndType_function(const char *_tag_,int _type_,const char *ref);
98 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon);
99 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v);
100 //static int boundType_function(const char *_tag_,int _type_);
101 //static int boundsType_function(const char *_tag_,int _type_);
102
103
104 /* The XML tag definitions */
105
106 /*+ The boundsType type tag. +*/
107 static xmltag boundsType_tag=
108 {"bounds",
109 0, {NULL},
110 NULL,
111 {NULL}};
112
113 /*+ The boundType type tag. +*/
114 static xmltag boundType_tag=
115 {"bound",
116 0, {NULL},
117 NULL,
118 {NULL}};
119
120 /*+ The tagType type tag. +*/
121 static xmltag tagType_tag=
122 {"tag",
123 2, {"k","v"},
124 tagType_function,
125 {NULL}};
126
127 /*+ The nodeType type tag. +*/
128 static xmltag nodeType_tag=
129 {"node",
130 3, {"id","lat","lon"},
131 nodeType_function,
132 {&tagType_tag,NULL}};
133
134 /*+ The ndType type tag. +*/
135 static xmltag ndType_tag=
136 {"nd",
137 1, {"ref"},
138 ndType_function,
139 {NULL}};
140
141 /*+ The memberType type tag. +*/
142 static xmltag memberType_tag=
143 {"member",
144 3, {"type","ref","role"},
145 memberType_function,
146 {NULL}};
147
148 /*+ The wayType type tag. +*/
149 static xmltag wayType_tag=
150 {"way",
151 1, {"id"},
152 wayType_function,
153 {&ndType_tag,&tagType_tag,NULL}};
154
155 /*+ The relationType type tag. +*/
156 static xmltag relationType_tag=
157 {"relation",
158 1, {"id"},
159 relationType_function,
160 {&memberType_tag,&tagType_tag,NULL}};
161
162 /*+ The osmType type tag. +*/
163 static xmltag osmType_tag=
164 {"osm",
165 0, {NULL},
166 NULL,
167 {&boundsType_tag,&boundType_tag,&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
168
169 /*+ The xmlDeclaration type tag. +*/
170 static xmltag xmlDeclaration_tag=
171 {"xml",
172 2, {"version","encoding"},
173 NULL,
174 {NULL}};
175
176
177 /*+ The complete set of tags at the top level. +*/
178 static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&osmType_tag,NULL};
179
180
181 /* The XML tag processing functions */
182
183
184 /*++++++++++++++++++++++++++++++++++++++
185 The function that is called when the boundsType XSD type is seen
186
187 int boundsType_function Returns 0 if no error occured or something else otherwise.
188
189 const char *_tag_ Set to the name of the element tag that triggered this function call.
190
191 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
192 ++++++++++++++++++++++++++++++++++++++*/
193
194 //static int boundsType_function(const char *_tag_,int _type_)
195 //{
196 // return(0);
197 //}
198
199
200 /*++++++++++++++++++++++++++++++++++++++
201 The function that is called when the boundType XSD type is seen
202
203 int boundType_function Returns 0 if no error occured or something else otherwise.
204
205 const char *_tag_ Set to the name of the element tag that triggered this function call.
206
207 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
208 ++++++++++++++++++++++++++++++++++++++*/
209
210 //static int boundType_function(const char *_tag_,int _type_)
211 //{
212 // return(0);
213 //}
214
215
216 /*++++++++++++++++++++++++++++++++++++++
217 The function that is called when the tagType XSD type is seen
218
219 int tagType_function Returns 0 if no error occured or something else otherwise.
220
221 const char *_tag_ Set to the name of the element tag that triggered this function call.
222
223 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
224
225 const char *k The contents of the 'k' attribute (or NULL if not defined).
226
227 const char *v The contents of the 'v' attribute (or NULL if not defined).
228 ++++++++++++++++++++++++++++++++++++++*/
229
230 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v)
231 {
232 if(_type_&XMLPARSE_TAG_START && current_tags)
233 {
234 XMLPARSE_ASSERT_STRING(_tag_,k);
235 XMLPARSE_ASSERT_STRING(_tag_,v);
236
237 AppendTag(current_tags,k,v);
238 }
239
240 return(0);
241 }
242
243
244 /*++++++++++++++++++++++++++++++++++++++
245 The function that is called when the nodeType XSD type is seen
246
247 int nodeType_function Returns 0 if no error occured or something else otherwise.
248
249 const char *_tag_ Set to the name of the element tag that triggered this function call.
250
251 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
252
253 const char *id The contents of the 'id' attribute (or NULL if not defined).
254
255 const char *lat The contents of the 'lat' attribute (or NULL if not defined).
256
257 const char *lon The contents of the 'lon' attribute (or NULL if not defined).
258 ++++++++++++++++++++++++++++++++++++++*/
259
260 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon)
261 {
262 static node_t node_id;
263 static double latitude,longitude;
264
265 if(_type_&XMLPARSE_TAG_START)
266 {
267 long long llid;
268 nnodes++;
269
270 if(!(nnodes%10000))
271 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
272
273 current_tags=NewTagList();
274
275 /* Handle the node information */
276
277 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
278 node_id=(node_t)llid;
279 assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
280
281 XMLPARSE_ASSERT_FLOATING(_tag_,lat); latitude =atof(lat);
282 XMLPARSE_ASSERT_FLOATING(_tag_,lon); longitude=atof(lon);
283 }
284
285 if(_type_&XMLPARSE_TAG_END)
286 {
287 TagList *result=ApplyTaggingRules(&NodeRules,current_tags);
288
289 process_node_tags(result,node_id,latitude,longitude);
290
291 DeleteTagList(current_tags);
292 DeleteTagList(result);
293 }
294
295 return(0);
296 }
297
298
299 /*++++++++++++++++++++++++++++++++++++++
300 The function that is called when the ndType XSD type is seen
301
302 int ndType_function Returns 0 if no error occured or something else otherwise.
303
304 const char *_tag_ Set to the name of the element tag that triggered this function call.
305
306 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
307
308 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
309 ++++++++++++++++++++++++++++++++++++++*/
310
311 static int ndType_function(const char *_tag_,int _type_,const char *ref)
312 {
313 if(_type_&XMLPARSE_TAG_START)
314 {
315 long long llid;
316 node_t node_id;
317
318 XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */
319 node_id=(node_t)llid;
320 assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
321
322 if(way_nnodes && (way_nnodes%256)==0)
323 way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t));
324
325 way_nodes[way_nnodes++]=node_id;
326 }
327
328 return(0);
329 }
330
331
332 /*++++++++++++++++++++++++++++++++++++++
333 The function that is called when the memberType XSD type is seen
334
335 int memberType_function Returns 0 if no error occured or something else otherwise.
336
337 const char *_tag_ Set to the name of the element tag that triggered this function call.
338
339 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
340
341 const char *type The contents of the 'type' attribute (or NULL if not defined).
342
343 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
344
345 const char *role The contents of the 'role' attribute (or NULL if not defined).
346 ++++++++++++++++++++++++++++++++++++++*/
347
348 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role)
349 {
350 if(_type_&XMLPARSE_TAG_START)
351 {
352 long long llid;
353
354 XMLPARSE_ASSERT_STRING(_tag_,type);
355 XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */
356
357 if(!strcmp(type,"node"))
358 {
359 node_t node_id;
360
361 node_id=(node_t)llid;
362 assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
363
364 if(relation_nnodes && (relation_nnodes%256)==0)
365 relation_nodes=(node_t*)realloc((void*)relation_nodes,(relation_nnodes+256)*sizeof(node_t));
366
367 relation_nodes[relation_nnodes++]=node_id;
368
369 if(role)
370 {
371 if(!strcmp(role,"via"))
372 relation_via=node_id;
373 }
374 }
375 else if(!strcmp(type,"way"))
376 {
377 way_t way_id;
378
379 way_id=(way_t)llid;
380 assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */
381
382 if(relation_nways && (relation_nways%256)==0)
383 relation_ways=(way_t*)realloc((void*)relation_ways,(relation_nways+256)*sizeof(way_t));
384
385 relation_ways[relation_nways++]=way_id;
386
387 if(role)
388 {
389 if(!strcmp(role,"from"))
390 relation_from=way_id;
391 if(!strcmp(role,"to"))
392 relation_to=way_id;
393 }
394 }
395 else if(!strcmp(type,"relation"))
396 {
397 relation_t relation_id;
398
399 relation_id=(relation_t)llid;
400 assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */
401
402 if(relation_nrelations && (relation_nrelations%256)==0)
403 relation_relations=(relation_t*)realloc((void*)relation_relations,(relation_nrelations+256)*sizeof(relation_t));
404
405 relation_relations[relation_nrelations++]=relation_id;
406 }
407 }
408
409 return(0);
410 }
411
412
413 /*++++++++++++++++++++++++++++++++++++++
414 The function that is called when the wayType XSD type is seen
415
416 int wayType_function Returns 0 if no error occured or something else otherwise.
417
418 const char *_tag_ Set to the name of the element tag that triggered this function call.
419
420 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
421
422 const char *id The contents of the 'id' attribute (or NULL if not defined).
423 ++++++++++++++++++++++++++++++++++++++*/
424
425 static int wayType_function(const char *_tag_,int _type_,const char *id)
426 {
427 static way_t way_id;
428
429 if(_type_&XMLPARSE_TAG_START)
430 {
431 long long llid;
432
433 nways++;
434
435 if(!(nways%1000))
436 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
437
438 current_tags=NewTagList();
439
440 way_nnodes=0;
441
442 /* Handle the way information */
443
444 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
445
446 way_id=(way_t)llid;
447 assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */
448 }
449
450 if(_type_&XMLPARSE_TAG_END)
451 {
452 TagList *result=ApplyTaggingRules(&WayRules,current_tags);
453
454 process_way_tags(result,way_id);
455
456 DeleteTagList(current_tags);
457 DeleteTagList(result);
458 }
459
460 return(0);
461 }
462
463
464 /*++++++++++++++++++++++++++++++++++++++
465 The function that is called when the relationType XSD type is seen
466
467 int relationType_function Returns 0 if no error occured or something else otherwise.
468
469 const char *_tag_ Set to the name of the element tag that triggered this function call.
470
471 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
472
473 const char *id The contents of the 'id' attribute (or NULL if not defined).
474 ++++++++++++++++++++++++++++++++++++++*/
475
476 static int relationType_function(const char *_tag_,int _type_,const char *id)
477 {
478 static relation_t relation_id;
479
480 if(_type_&XMLPARSE_TAG_START)
481 {
482 long long llid;
483
484 nrelations++;
485
486 if(!(nrelations%1000))
487 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
488
489 current_tags=NewTagList();
490
491 relation_nnodes=relation_nways=relation_nrelations=0;
492
493 relation_from=NO_WAY_ID;
494 relation_to=NO_WAY_ID;
495 relation_via=NO_NODE_ID;
496
497 /* Handle the relation information */
498
499 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
500
501 relation_id=(relation_t)llid;
502 assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */
503 }
504
505 if(_type_&XMLPARSE_TAG_END)
506 {
507 TagList *result=ApplyTaggingRules(&RelationRules,current_tags);
508
509 process_relation_tags(result,relation_id);
510
511 DeleteTagList(current_tags);
512 DeleteTagList(result);
513 }
514
515 return(0);
516 }
517
518
519 /*++++++++++++++++++++++++++++++++++++++
520 The function that is called when the osmType XSD type is seen
521
522 int osmType_function Returns 0 if no error occured or something else otherwise.
523
524 const char *_tag_ Set to the name of the element tag that triggered this function call.
525
526 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
527 ++++++++++++++++++++++++++++++++++++++*/
528
529 //static int osmType_function(const char *_tag_,int _type_)
530 //{
531 // return(0);
532 //}
533
534
535 /*++++++++++++++++++++++++++++++++++++++
536 The function that is called when the XML declaration is seen
537
538 int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
539
540 const char *_tag_ Set to the name of the element tag that triggered this function call.
541
542 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
543
544 const char *version The contents of the 'version' attribute (or NULL if not defined).
545
546 const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
547 ++++++++++++++++++++++++++++++++++++++*/
548
549 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
550 //{
551 // return(0);
552 //}
553
554
555 /*++++++++++++++++++++++++++++++++++++++
556 Parse an OSM XML file (from JOSM or planet download).
557
558 int ParseOSM Returns 0 if OK or something else in case of an error.
559
560 FILE *file The file to read from.
561
562 NodesX *OSMNodes The data structure of nodes to fill in.
563
564 SegmentsX *OSMSegments The data structure of segments to fill in.
565
566 WaysX *OSMWays The data structure of ways to fill in.
567
568 RelationsX *OSMRelations The data structure of relations to fill in.
569 ++++++++++++++++++++++++++++++++++++++*/
570
571 int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations)
572 {
573 int retval;
574
575 /* Copy the function parameters and initialise the variables. */
576
577 nodes=OSMNodes;
578 segments=OSMSegments;
579 ways=OSMWays;
580 relations=OSMRelations;
581
582 way_nodes=(node_t*)malloc(256*sizeof(node_t));
583
584 relation_nodes =(node_t *)malloc(256*sizeof(node_t));
585 relation_ways =(way_t *)malloc(256*sizeof(way_t));
586 relation_relations=(relation_t*)malloc(256*sizeof(relation_t));
587
588 /* Parse the file */
589
590 nnodes=0,nways=0,nrelations=0;
591
592 printf_first("Reading: Lines=0 Nodes=0 Ways=0 Relations=0");
593
594 retval=ParseXML(file,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE);
595
596 printf_last("Read: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
597
598 free(way_nodes);
599
600 free(relation_nodes);
601 free(relation_ways);
602 free(relation_relations);
603
604 return(retval);
605 }
606
607
608 /*++++++++++++++++++++++++++++++++++++++
609 Process the tags associated with a node.
610
611 TagList *tags The list of node tags.
612
613 node_t id The id of the node.
614
615 double latitude The latitude of the node.
616
617 double longitude The longitude of the node.
618 ++++++++++++++++++++++++++++++++++++++*/
619
620 static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude)
621 {
622 transports_t allow=Transports_ALL;
623 uint16_t flags=0;
624 int i;
625
626 /* Parse the tags */
627
628 for(i=0;i<tags->ntags;i++)
629 {
630 char *k=tags->k[i];
631 char *v=tags->v[i];
632
633 switch(*k)
634 {
635 case 'b':
636 if(!strcmp(k,"bicycle"))
637 {
638 if(ISFALSE(v))
639 allow&=~Transports_Bicycle;
640 else if(!ISTRUE(v))
641 logerror("Node %"Pnode_t" has an unrecognised tag value 'bicycle' = '%s' (after processing tagging rules).\n",id,v);
642 }
643
644 break;
645
646 case 'f':
647 if(!strcmp(k,"foot"))
648 {
649 if(ISFALSE(v))
650 allow&=~Transports_Foot;
651 else if(!ISTRUE(v))
652 logerror("Node %"Pnode_t" has an unrecognised tag value 'foot' = '%s' (after processing tagging rules).\n",id,v);
653 }
654
655 break;
656
657 case 'g':
658 if(!strcmp(k,"goods"))
659 {
660 if(ISFALSE(v))
661 allow&=~Transports_Goods;
662 else if(!ISTRUE(v))
663 logerror("Node %"Pnode_t" has an unrecognised tag value 'goods' = '%s' (after processing tagging rules).\n",id,v);
664 }
665
666 break;
667
668 case 'h':
669 if(!strcmp(k,"highway"))
670 if(!strcmp(v,"mini_roundabout"))
671 flags|=NODE_MINIRNDBT;
672
673 if(!strcmp(k,"horse"))
674 {
675 if(ISFALSE(v))
676 allow&=~Transports_Horse;
677 else if(!ISTRUE(v))
678 logerror("Node %"Pnode_t" has an unrecognised tag value 'horse' = '%s' (after processing tagging rules).\n",id,v);
679 }
680
681 if(!strcmp(k,"hgv"))
682 {
683 if(ISFALSE(v))
684 allow&=~Transports_HGV;
685 else if(!ISTRUE(v))
686 logerror("Node %"Pnode_t" has an unrecognised tag value 'hgv' = '%s' (after processing tagging rules).\n",id,v);
687 }
688
689 break;
690
691 case 'm':
692 if(!strcmp(k,"moped"))
693 {
694 if(ISFALSE(v))
695 allow&=~Transports_Moped;
696 else if(!ISTRUE(v))
697 logerror("Node %"Pnode_t" has an unrecognised tag value 'moped' = '%s' (after processing tagging rules).\n",id,v);
698 }
699
700 if(!strcmp(k,"motorbike"))
701 {
702 if(ISFALSE(v))
703 allow&=~Transports_Motorbike;
704 else if(!ISTRUE(v))
705 logerror("Node %"Pnode_t" has an unrecognised tag value 'motorbike' = '%s' (after processing tagging rules).\n",id,v);
706 }
707
708 if(!strcmp(k,"motorcar"))
709 {
710 if(ISFALSE(v))
711 allow&=~Transports_Motorcar;
712 else if(!ISTRUE(v))
713 logerror("Node %"Pnode_t" has an unrecognised tag value 'motorcar' = '%s' (after processing tagging rules).\n",id,v);
714 }
715
716 break;
717
718 case 'p':
719 if(!strcmp(k,"psv"))
720 {
721 if(ISFALSE(v))
722 allow&=~Transports_PSV;
723 else if(!ISTRUE(v))
724 logerror("Node %"Pnode_t" has an unrecognised tag value 'psv' = '%s' (after processing tagging rules).\n",id,v);
725 }
726
727 break;
728
729 case 'w':
730 if(!strcmp(k,"wheelchair"))
731 {
732 if(ISFALSE(v))
733 allow&=~Transports_Wheelchair;
734 else if(!ISTRUE(v))
735 logerror("Node %"Pnode_t" has an unrecognised tag value 'wheelchair' = '%s' (after processing tagging rules).\n",id,v);
736 }
737
738 break;
739
740 default:
741 logerror("Node %"Pnode_t" has an unrecognised tag '%s' = '%s' (after processing tagging rules).\n",id,k,v);
742 }
743 }
744
745 /* Create the node */
746
747 AppendNode(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,flags);
748 }
749
750
751 /*++++++++++++++++++++++++++++++++++++++
752 Process the tags associated with a way.
753
754 TagList *tags The list of way tags.
755
756 way_t id The id of the way.
757 ++++++++++++++++++++++++++++++++++++++*/
758
759 static void process_way_tags(TagList *tags,way_t id)
760 {
761 Way way={0};
762 int oneway=0;
763 char *name=NULL,*ref=NULL,*refname=NULL;
764 int i;
765
766 /* Parse the tags */
767
768 for(i=0;i<tags->ntags;i++)
769 {
770 char *k=tags->k[i];
771 char *v=tags->v[i];
772
773 switch(*k)
774 {
775 case 'b':
776 if(!strcmp(k,"bicycle"))
777 {
778 if(ISTRUE(v))
779 way.allow|= Transports_Bicycle;
780 else if(!ISFALSE(v))
781 logerror("Way %"Pway_t" has an unrecognised tag value 'bicycle' = '%s' (after processing tagging rules).\n",id,v);
782 }
783
784 if(!strcmp(k,"bicycleroute"))
785 {
786 if(ISTRUE(v))
787 way.props|=Properties_BicycleRoute;
788 else if(!ISFALSE(v))
789 logerror("Way %"Pway_t" has an unrecognised tag value 'bicycleroute' = '%s' (after processing tagging rules).\n",id,v);
790 }
791
792 if(!strcmp(k,"bridge"))
793 {
794 if(ISTRUE(v))
795 way.props|=Properties_Bridge;
796 else if(!ISFALSE(v))
797 logerror("Way %"Pway_t" has an unrecognised tag value 'bridge' = '%s' (after processing tagging rules).\n",id,v);
798 }
799
800 break;
801
802 case 'f':
803 if(!strcmp(k,"foot"))
804 {
805 if(ISTRUE(v))
806 way.allow|= Transports_Foot;
807 else if(!ISFALSE(v))
808 logerror("Way %"Pway_t" has an unrecognised tag value 'foot' = '%s' (after processing tagging rules).\n",id,v);
809 }
810
811 if(!strcmp(k,"footroute"))
812 {
813 if(ISTRUE(v))
814 way.props|=Properties_FootRoute;
815 else if(!ISFALSE(v))
816 logerror("Way %"Pway_t" has an unrecognised tag value 'footroute' = '%s' (after processing tagging rules).\n",id,v);
817 }
818
819 break;
820
821 case 'g':
822 if(!strcmp(k,"goods"))
823 {
824 if(ISTRUE(v))
825 way.allow|=Transports_Goods;
826 else if(!ISFALSE(v))
827 logerror("Way %"Pway_t" has an unrecognised tag value 'goods' = '%s' (after processing tagging rules).\n",id,v);
828 }
829
830 break;
831
832 case 'h':
833 if(!strcmp(k,"highway"))
834 {
835 way.type=HighwayType(v);
836
837 if(way.type==Way_Count)
838 logerror("Way %"Pway_t" has an unrecognised highway type '%s' (after processing tagging rules).\n",id,v);
839 }
840
841 if(!strcmp(k,"horse"))
842 {
843 if(ISTRUE(v))
844 way.allow|=Transports_Horse;
845 else if(!ISFALSE(v))
846 logerror("Way %"Pway_t" has an unrecognised tag value 'horse' = '%s' (after processing tagging rules).\n",id,v);
847 }
848
849 if(!strcmp(k,"hgv"))
850 {
851 if(ISTRUE(v))
852 way.allow|=Transports_HGV;
853 else if(!ISFALSE(v))
854 logerror("Way %"Pway_t" has an unrecognised tag value 'hgv' = '%s' (after processing tagging rules).\n",id,v);
855 }
856
857 break;
858
859 case 'm':
860 if(!strcmp(k,"maxspeed"))
861 way.speed=kph_to_speed(parse_speed(id,k,v));
862
863 if(!strcmp(k,"maxweight"))
864 way.weight=tonnes_to_weight(parse_weight(id,k,v));
865
866 if(!strcmp(k,"maxheight"))
867 way.height=metres_to_height(parse_length(id,k,v));
868
869 if(!strcmp(k,"maxwidth"))
870 way.width=metres_to_height(parse_length(id,k,v));
871
872 if(!strcmp(k,"maxlength"))
873 way.length=metres_to_height(parse_length(id,k,v));
874
875 if(!strcmp(k,"moped"))
876 {
877 if(ISTRUE(v))
878 way.allow|=Transports_Moped;
879 else if(!ISFALSE(v))
880 logerror("Way %"Pway_t" has an unrecognised tag value 'moped' = '%s' (after processing tagging rules).\n",id,v);
881 }
882
883 if(!strcmp(k,"motorbike"))
884 {
885 if(ISTRUE(v))
886 way.allow|=Transports_Motorbike;
887 else if(!ISFALSE(v))
888 logerror("Way %"Pway_t" has an unrecognised tag value 'motorbike' = '%s' (after processing tagging rules).\n",id,v);
889 }
890
891 if(!strcmp(k,"motorcar"))
892 {
893 if(ISTRUE(v))
894 way.allow|=Transports_Motorcar;
895 else if(!ISFALSE(v))
896 logerror("Way %"Pway_t" has an unrecognised tag value 'motorcar' = '%s' (after processing tagging rules).\n",id,v);
897 }
898
899 if(!strcmp(k,"multilane"))
900 {
901 if(ISTRUE(v))
902 way.props|=Properties_Multilane;
903 else if(!ISFALSE(v))
904 logerror("Way %"Pway_t" has an unrecognised tag value 'multilane' = '%s' (after processing tagging rules).\n",id,v);
905 }
906
907 break;
908
909 case 'n':
910 if(!strcmp(k,"name"))
911 name=v;
912
913 break;
914
915 case 'o':
916 if(!strcmp(k,"oneway"))
917 {
918 if(ISTRUE(v))
919 oneway=1;
920 else if(!strcmp(v,"-1"))
921 oneway=-1;
922 else if(!ISFALSE(v))
923 logerror("Way %"Pway_t" has an unrecognised tag value 'oneway' = '%s' (after processing tagging rules).\n",id,v);
924 }
925
926 break;
927
928 case 'p':
929 if(!strcmp(k,"paved"))
930 {
931 if(ISTRUE(v))
932 way.props|=Properties_Paved;
933 else if(!ISFALSE(v))
934 logerror("Way %"Pway_t" has an unrecognised tag value 'paved' = '%s' (after processing tagging rules).\n",id,v);
935 }
936
937 if(!strcmp(k,"psv"))
938 {
939 if(ISTRUE(v))
940 way.allow|=Transports_PSV;
941 else if(!ISFALSE(v))
942 logerror("Way %"Pway_t" has an unrecognised tag value 'psv' = '%s' (after processing tagging rules).\n",id,v);
943 }
944
945 break;
946
947 case 'r':
948 if(!strcmp(k,"ref"))
949 ref=v;
950
951 break;
952
953 case 't':
954 if(!strcmp(k,"tunnel"))
955 {
956 if(ISTRUE(v))
957 way.props|=Properties_Tunnel;
958 else if(!ISFALSE(v))
959 logerror("Way %"Pway_t" has an unrecognised tag value 'tunnel' = '%s' (after processing tagging rules).\n",id,v);
960 }
961
962 break;
963
964 case 'w':
965 if(!strcmp(k,"wheelchair"))
966 {
967 if(ISTRUE(v))
968 way.allow|=Transports_Wheelchair;
969 else if(!ISFALSE(v))
970 logerror("Way %"Pway_t" has an unrecognised tag value 'wheelchair' = '%s' (after processing tagging rules).\n",id,v);
971 }
972
973 break;
974
975 default:
976 logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after processing tagging rules).\n",id,k,v);
977 }
978 }
979
980 /* Create the way */
981
982 if(way.type==0 || way.type==Way_Count)
983 return;
984
985 if(!way.allow)
986 return;
987
988 if(way_nnodes==0)
989 {
990 logerror("Way %"Pway_t" has no nodes.\n",id);
991
992 return;
993 }
994
995 if(oneway)
996 way.type|=Way_OneWay;
997
998 if(ref && name)
999 {
1000 refname=(char*)malloc(strlen(ref)+strlen(name)+4);
1001 sprintf(refname,"%s (%s)",name,ref);
1002 }
1003 else if(ref && !name)
1004 refname=ref;
1005 else if(!ref && name)
1006 refname=name;
1007 else /* if(!ref && !name) */
1008 refname="";
1009
1010 AppendWay(ways,id,&way,refname);
1011
1012 if(ref && name)
1013 free(refname);
1014
1015 for(i=1;i<way_nnodes;i++)
1016 {
1017 node_t from=way_nodes[i-1];
1018 node_t to =way_nodes[i];
1019
1020 if(oneway>0)
1021 AppendSegment(segments,id,from,to,ONEWAY_1TO2);
1022 else if(oneway<0)
1023 AppendSegment(segments,id,from,to,ONEWAY_2TO1);
1024 else
1025 AppendSegment(segments,id,from,to,0);
1026 }
1027 }
1028
1029
1030 /*++++++++++++++++++++++++++++++++++++++
1031 Process the tags associated with a relation.
1032
1033 TagList *tags The list of relation tags.
1034
1035 relation_t id The id of the relation.
1036 ++++++++++++++++++++++++++++++++++++++*/
1037
1038 static void process_relation_tags(TagList *tags,relation_t id)
1039 {
1040 transports_t routes=Transports_None;
1041 transports_t except=Transports_None;
1042 int relation_turn_restriction=0;
1043 TurnRestriction restriction=TurnRestrict_None;
1044 int i;
1045
1046 /* Parse the tags */
1047
1048 for(i=0;i<tags->ntags;i++)
1049 {
1050 char *k=tags->k[i];
1051 char *v=tags->v[i];
1052
1053 switch(*k)
1054 {
1055 case 'b':
1056 if(!strcmp(k,"bicycleroute"))
1057 {
1058 if(ISTRUE(v))
1059 routes|=Transports_Bicycle;
1060 else if(!ISFALSE(v))
1061 logerror("Relation %"Prelation_t" has an unrecognised tag value 'bicycleroute' = '%s' (after processing tagging rules).\n",id,v);
1062 }
1063
1064 break;
1065
1066 case 'e':
1067 if(!strcmp(k,"except"))
1068 {
1069 for(i=1;i<Transport_Count;i++)
1070 if(!strstr(v,TransportName(i)))
1071 except|=TRANSPORTS(i);
1072
1073 if(except==Transports_None)
1074 logerror("Relation %"Prelation_t" has an unrecognised tag value 'except' = '%s' (after processing tagging rules).\n",id,v);
1075 }
1076
1077 break;
1078
1079 case 'f':
1080 if(!strcmp(k,"footroute"))
1081 {
1082 if(ISTRUE(v))
1083 routes|=Transports_Foot;
1084 else if(!ISFALSE(v))
1085 logerror("Relation %"Prelation_t" has an unrecognised tag value 'footroute' = '%s' (after processing tagging rules).\n",id,v);
1086 }
1087
1088 break;
1089
1090 case 'r':
1091 if(!strcmp(k,"restriction"))
1092 {
1093 if(!strcmp(v,"no_right_turn" )) restriction=TurnRestrict_no_right_turn;
1094 if(!strcmp(v,"no_left_turn" )) restriction=TurnRestrict_no_left_turn;
1095 if(!strcmp(v,"no_u_turn" )) restriction=TurnRestrict_no_u_turn;
1096 if(!strcmp(v,"no_straight_on" )) restriction=TurnRestrict_no_straight_on;
1097 if(!strcmp(v,"only_right_turn" )) restriction=TurnRestrict_only_right_turn;
1098 if(!strcmp(v,"only_left_turn" )) restriction=TurnRestrict_only_left_turn;
1099 if(!strcmp(v,"only_straight_on")) restriction=TurnRestrict_only_straight_on;
1100
1101 if(restriction==TurnRestrict_None)
1102 logerror("Relation %"Prelation_t" has an unrecognised tag value 'restriction' = '%s' (after processing tagging rules).\n",id,v);
1103 }
1104
1105 break;
1106
1107 case 't':
1108 if(!strcmp(k,"type"))
1109 {
1110 if(!strcmp(v,"restriction"))
1111 relation_turn_restriction=1;
1112 else
1113 logerror("Relation %"Prelation_t" has an unrecognised tag value 'type' = '%s' (after processing tagging rules).\n",id,v);
1114 }
1115 break;
1116
1117 default:
1118 logerror("Relation %"Prelation_t" has an unrecognised tag '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1119 }
1120 }
1121
1122 /* Create the route relation (must store all relations that have ways or
1123 relations even if they are not routes because they might be referenced by
1124 other relations that are routes) */
1125
1126 if((relation_nways || relation_nrelations) && !relation_turn_restriction)
1127 AppendRouteRelation(relations,id,routes,
1128 relation_ways,relation_nways,
1129 relation_relations,relation_nrelations);
1130
1131 /* Create the turn restriction relation. */
1132
1133 if(relation_turn_restriction && restriction!=TurnRestrict_None)
1134 {
1135 if(relation_from==NO_WAY_ID)
1136 logerror("Relation %"Prelation_t" is a turn restriction but has no 'from' way (after processing tagging rules).\n",id);
1137 else if(relation_to==NO_WAY_ID)
1138 logerror("Relation %"Prelation_t" is a turn restriction but has no 'to' way (after processing tagging rules).\n",id);
1139 else if(relation_via==NO_NODE_ID)
1140 logerror("Relation %"Prelation_t" is a turn restriction but has no 'via' node (after processing tagging rules).\n",id);
1141 else
1142 AppendTurnRestrictRelation(relations,id,
1143 relation_from,relation_to,relation_via,
1144 restriction,except);
1145 }
1146 }
1147
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 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1168 else
1169 {
1170 while(isspace(*ev)) ev++;
1171
1172 if(!strcmp(ev,"mph"))
1173 return(1.609*value);
1174 else if(*ev==0)
1175 return(value);
1176 else
1177 logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1178 }
1179
1180 return(0);
1181 }
1182
1183
1184 /*++++++++++++++++++++++++++++++++++++++
1185 Convert a string containing a weight into a double precision.
1186
1187 double parse_weight Returns the weight in tonnes if it can be parsed.
1188
1189 way_t id The way being processed.
1190
1191 const char *k The tag key.
1192
1193 const char *v The tag value.
1194 ++++++++++++++++++++++++++++++++++++++*/
1195
1196 static double parse_weight(way_t id,const char *k,const char *v)
1197 {
1198 char *ev;
1199 double value=strtod(v,&ev);
1200
1201 if(v==ev)
1202 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1203 else
1204 {
1205 while(isspace(*ev)) ev++;
1206
1207 if(!strcmp(ev,"kg"))
1208 return(value/1000.0);
1209 else if(*ev==0)
1210 return(value);
1211 else
1212 logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1213 }
1214
1215 return(0);
1216 }
1217
1218
1219 /*++++++++++++++++++++++++++++++++++++++
1220 Convert a string containing a length into a double precision.
1221
1222 double parse_length Returns the length in metres if it can be parsed.
1223
1224 way_t id The way being processed.
1225
1226 const char *k The tag key.
1227
1228 const char *v The tag value.
1229 ++++++++++++++++++++++++++++++++++++++*/
1230
1231 static double parse_length(way_t id,const char *k,const char *v)
1232 {
1233 char *ev;
1234 double value=strtod(v,&ev);
1235
1236 if(v==ev)
1237 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1238 else
1239 {
1240 int feet,inches;
1241 while(isspace(*ev)) ev++;
1242
1243 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
1244 return((feet+(double)inches/12.0)*0.254);
1245 else if(sscanf(v,"%d'",&feet)==1)
1246 return(feet*0.254);
1247 else if(!strcmp(ev,"ft") || !strcmp(ev,"feet"))
1248 return(value*0.254);
1249 else if(*ev==0)
1250 return(value);
1251 else
1252 logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1253 }
1254
1255 return(0);
1256 }

Properties

Name Value
cvs:description OSM XML file parser.