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 833 - (show annotations) (download) (as text)
Sat Aug 27 17:47:10 2011 UTC (13 years, 7 months ago) by amb
File MIME type: text/x-csrc
File size: 37428 byte(s)
Only log errors for highways.

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
269 nnodes++;
270
271 if(!(nnodes%10000))
272 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
273
274 current_tags=NewTagList();
275
276 /* Handle the node information */
277
278 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
279 node_id=(node_t)llid;
280 assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
281
282 XMLPARSE_ASSERT_FLOATING(_tag_,lat); latitude =atof(lat);
283 XMLPARSE_ASSERT_FLOATING(_tag_,lon); longitude=atof(lon);
284 }
285
286 if(_type_&XMLPARSE_TAG_END)
287 {
288 TagList *result=ApplyTaggingRules(&NodeRules,current_tags,node_id);
289
290 process_node_tags(result,node_id,latitude,longitude);
291
292 DeleteTagList(current_tags);
293 DeleteTagList(result);
294 }
295
296 return(0);
297 }
298
299
300 /*++++++++++++++++++++++++++++++++++++++
301 The function that is called when the ndType XSD type is seen
302
303 int ndType_function Returns 0 if no error occured or something else otherwise.
304
305 const char *_tag_ Set to the name of the element tag that triggered this function call.
306
307 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
308
309 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
310 ++++++++++++++++++++++++++++++++++++++*/
311
312 static int ndType_function(const char *_tag_,int _type_,const char *ref)
313 {
314 if(_type_&XMLPARSE_TAG_START)
315 {
316 long long llid;
317 node_t node_id;
318
319 XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */
320 node_id=(node_t)llid;
321 assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
322
323 if(way_nnodes && (way_nnodes%256)==0)
324 way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t));
325
326 way_nodes[way_nnodes++]=node_id;
327 }
328
329 return(0);
330 }
331
332
333 /*++++++++++++++++++++++++++++++++++++++
334 The function that is called when the memberType XSD type is seen
335
336 int memberType_function Returns 0 if no error occured or something else otherwise.
337
338 const char *_tag_ Set to the name of the element tag that triggered this function call.
339
340 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
341
342 const char *type The contents of the 'type' attribute (or NULL if not defined).
343
344 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
345
346 const char *role The contents of the 'role' attribute (or NULL if not defined).
347 ++++++++++++++++++++++++++++++++++++++*/
348
349 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role)
350 {
351 if(_type_&XMLPARSE_TAG_START)
352 {
353 long long llid;
354
355 XMLPARSE_ASSERT_STRING(_tag_,type);
356 XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */
357
358 if(!strcmp(type,"node"))
359 {
360 node_t node_id;
361
362 node_id=(node_t)llid;
363 assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
364
365 if(relation_nnodes && (relation_nnodes%256)==0)
366 relation_nodes=(node_t*)realloc((void*)relation_nodes,(relation_nnodes+256)*sizeof(node_t));
367
368 relation_nodes[relation_nnodes++]=node_id;
369
370 if(role)
371 {
372 if(!strcmp(role,"via"))
373 relation_via=node_id;
374 }
375 }
376 else if(!strcmp(type,"way"))
377 {
378 way_t way_id;
379
380 way_id=(way_t)llid;
381 assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */
382
383 if(relation_nways && (relation_nways%256)==0)
384 relation_ways=(way_t*)realloc((void*)relation_ways,(relation_nways+256)*sizeof(way_t));
385
386 relation_ways[relation_nways++]=way_id;
387
388 if(role)
389 {
390 if(!strcmp(role,"from"))
391 relation_from=way_id;
392 if(!strcmp(role,"to"))
393 relation_to=way_id;
394 }
395 }
396 else if(!strcmp(type,"relation"))
397 {
398 relation_t relation_id;
399
400 relation_id=(relation_t)llid;
401 assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */
402
403 if(relation_nrelations && (relation_nrelations%256)==0)
404 relation_relations=(relation_t*)realloc((void*)relation_relations,(relation_nrelations+256)*sizeof(relation_t));
405
406 relation_relations[relation_nrelations++]=relation_id;
407 }
408 }
409
410 return(0);
411 }
412
413
414 /*++++++++++++++++++++++++++++++++++++++
415 The function that is called when the wayType XSD type is seen
416
417 int wayType_function Returns 0 if no error occured or something else otherwise.
418
419 const char *_tag_ Set to the name of the element tag that triggered this function call.
420
421 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
422
423 const char *id The contents of the 'id' attribute (or NULL if not defined).
424 ++++++++++++++++++++++++++++++++++++++*/
425
426 static int wayType_function(const char *_tag_,int _type_,const char *id)
427 {
428 static way_t way_id;
429
430 if(_type_&XMLPARSE_TAG_START)
431 {
432 long long llid;
433
434 nways++;
435
436 if(!(nways%1000))
437 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
438
439 current_tags=NewTagList();
440
441 way_nnodes=0;
442
443 /* Handle the way information */
444
445 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
446
447 way_id=(way_t)llid;
448 assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */
449 }
450
451 if(_type_&XMLPARSE_TAG_END)
452 {
453 TagList *result=ApplyTaggingRules(&WayRules,current_tags,way_id);
454
455 process_way_tags(result,way_id);
456
457 DeleteTagList(current_tags);
458 DeleteTagList(result);
459 }
460
461 return(0);
462 }
463
464
465 /*++++++++++++++++++++++++++++++++++++++
466 The function that is called when the relationType XSD type is seen
467
468 int relationType_function Returns 0 if no error occured or something else otherwise.
469
470 const char *_tag_ Set to the name of the element tag that triggered this function call.
471
472 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
473
474 const char *id The contents of the 'id' attribute (or NULL if not defined).
475 ++++++++++++++++++++++++++++++++++++++*/
476
477 static int relationType_function(const char *_tag_,int _type_,const char *id)
478 {
479 static relation_t relation_id;
480
481 if(_type_&XMLPARSE_TAG_START)
482 {
483 long long llid;
484
485 nrelations++;
486
487 if(!(nrelations%1000))
488 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
489
490 current_tags=NewTagList();
491
492 relation_nnodes=relation_nways=relation_nrelations=0;
493
494 relation_from=NO_WAY_ID;
495 relation_to=NO_WAY_ID;
496 relation_via=NO_NODE_ID;
497
498 /* Handle the relation information */
499
500 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
501
502 relation_id=(relation_t)llid;
503 assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */
504 }
505
506 if(_type_&XMLPARSE_TAG_END)
507 {
508 TagList *result=ApplyTaggingRules(&RelationRules,current_tags,relation_id);
509
510 process_relation_tags(result,relation_id);
511
512 DeleteTagList(current_tags);
513 DeleteTagList(result);
514 }
515
516 return(0);
517 }
518
519
520 /*++++++++++++++++++++++++++++++++++++++
521 The function that is called when the osmType XSD type is seen
522
523 int osmType_function Returns 0 if no error occured or something else otherwise.
524
525 const char *_tag_ Set to the name of the element tag that triggered this function call.
526
527 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
528 ++++++++++++++++++++++++++++++++++++++*/
529
530 //static int osmType_function(const char *_tag_,int _type_)
531 //{
532 // return(0);
533 //}
534
535
536 /*++++++++++++++++++++++++++++++++++++++
537 The function that is called when the XML declaration is seen
538
539 int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
540
541 const char *_tag_ Set to the name of the element tag that triggered this function call.
542
543 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
544
545 const char *version The contents of the 'version' attribute (or NULL if not defined).
546
547 const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
548 ++++++++++++++++++++++++++++++++++++++*/
549
550 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
551 //{
552 // return(0);
553 //}
554
555
556 /*++++++++++++++++++++++++++++++++++++++
557 Parse an OSM XML file (from JOSM or planet download).
558
559 int ParseOSM Returns 0 if OK or something else in case of an error.
560
561 FILE *file The file to read from.
562
563 NodesX *OSMNodes The data structure of nodes to fill in.
564
565 SegmentsX *OSMSegments The data structure of segments to fill in.
566
567 WaysX *OSMWays The data structure of ways to fill in.
568
569 RelationsX *OSMRelations The data structure of relations to fill in.
570 ++++++++++++++++++++++++++++++++++++++*/
571
572 int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations)
573 {
574 int retval;
575
576 /* Copy the function parameters and initialise the variables. */
577
578 nodes=OSMNodes;
579 segments=OSMSegments;
580 ways=OSMWays;
581 relations=OSMRelations;
582
583 way_nodes=(node_t*)malloc(256*sizeof(node_t));
584
585 relation_nodes =(node_t *)malloc(256*sizeof(node_t));
586 relation_ways =(way_t *)malloc(256*sizeof(way_t));
587 relation_relations=(relation_t*)malloc(256*sizeof(relation_t));
588
589 /* Parse the file */
590
591 nnodes=0,nways=0,nrelations=0;
592
593 printf_first("Reading: Lines=0 Nodes=0 Ways=0 Relations=0");
594
595 retval=ParseXML(file,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE);
596
597 printf_last("Read: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
598
599 free(way_nodes);
600
601 free(relation_nodes);
602 free(relation_ways);
603 free(relation_relations);
604
605 return(retval);
606 }
607
608
609 /*++++++++++++++++++++++++++++++++++++++
610 Process the tags associated with a node.
611
612 TagList *tags The list of node tags.
613
614 node_t id The id of the node.
615
616 double latitude The latitude of the node.
617
618 double longitude The longitude of the node.
619 ++++++++++++++++++++++++++++++++++++++*/
620
621 static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude)
622 {
623 transports_t allow=Transports_ALL;
624 uint16_t flags=0;
625 int i;
626
627 /* Parse the tags */
628
629 for(i=0;i<tags->ntags;i++)
630 {
631 char *k=tags->k[i];
632 char *v=tags->v[i];
633
634 switch(*k)
635 {
636 case 'b':
637 if(!strcmp(k,"bicycle"))
638 {
639 if(ISFALSE(v))
640 allow&=~Transports_Bicycle;
641 else if(!ISTRUE(v))
642 logerror("Node %"Pnode_t" has an unrecognised tag value 'bicycle' = '%s' (after tagging rules); using 'yes'.\n",id,v);
643 }
644
645 break;
646
647 case 'f':
648 if(!strcmp(k,"foot"))
649 {
650 if(ISFALSE(v))
651 allow&=~Transports_Foot;
652 else if(!ISTRUE(v))
653 logerror("Node %"Pnode_t" has an unrecognised tag value 'foot' = '%s' (after tagging rules); using 'yes'.\n",id,v);
654 }
655
656 break;
657
658 case 'g':
659 if(!strcmp(k,"goods"))
660 {
661 if(ISFALSE(v))
662 allow&=~Transports_Goods;
663 else if(!ISTRUE(v))
664 logerror("Node %"Pnode_t" has an unrecognised tag value 'goods' = '%s' (after tagging rules); using 'yes'.\n",id,v);
665 }
666
667 break;
668
669 case 'h':
670 if(!strcmp(k,"highway"))
671 if(!strcmp(v,"mini_roundabout"))
672 flags|=NODE_MINIRNDBT;
673
674 if(!strcmp(k,"horse"))
675 {
676 if(ISFALSE(v))
677 allow&=~Transports_Horse;
678 else if(!ISTRUE(v))
679 logerror("Node %"Pnode_t" has an unrecognised tag value 'horse' = '%s' (after tagging rules); using 'yes'.\n",id,v);
680 }
681
682 if(!strcmp(k,"hgv"))
683 {
684 if(ISFALSE(v))
685 allow&=~Transports_HGV;
686 else if(!ISTRUE(v))
687 logerror("Node %"Pnode_t" has an unrecognised tag value 'hgv' = '%s' (after tagging rules); using 'yes'.\n",id,v);
688 }
689
690 break;
691
692 case 'm':
693 if(!strcmp(k,"moped"))
694 {
695 if(ISFALSE(v))
696 allow&=~Transports_Moped;
697 else if(!ISTRUE(v))
698 logerror("Node %"Pnode_t" has an unrecognised tag value 'moped' = '%s' (after tagging rules); using 'yes'.\n",id,v);
699 }
700
701 if(!strcmp(k,"motorbike"))
702 {
703 if(ISFALSE(v))
704 allow&=~Transports_Motorbike;
705 else if(!ISTRUE(v))
706 logerror("Node %"Pnode_t" has an unrecognised tag value 'motorbike' = '%s' (after tagging rules); using 'yes'.\n",id,v);
707 }
708
709 if(!strcmp(k,"motorcar"))
710 {
711 if(ISFALSE(v))
712 allow&=~Transports_Motorcar;
713 else if(!ISTRUE(v))
714 logerror("Node %"Pnode_t" has an unrecognised tag value 'motorcar' = '%s' (after tagging rules); using 'yes'.\n",id,v);
715 }
716
717 break;
718
719 case 'p':
720 if(!strcmp(k,"psv"))
721 {
722 if(ISFALSE(v))
723 allow&=~Transports_PSV;
724 else if(!ISTRUE(v))
725 logerror("Node %"Pnode_t" has an unrecognised tag value 'psv' = '%s' (after tagging rules); using 'yes'.\n",id,v);
726 }
727
728 break;
729
730 case 'w':
731 if(!strcmp(k,"wheelchair"))
732 {
733 if(ISFALSE(v))
734 allow&=~Transports_Wheelchair;
735 else if(!ISTRUE(v))
736 logerror("Node %"Pnode_t" has an unrecognised tag value 'wheelchair' = '%s' (after tagging rules); using 'yes'.\n",id,v);
737 }
738
739 break;
740
741 default:
742 logerror("Node %"Pnode_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
743 }
744 }
745
746 /* Create the node */
747
748 AppendNode(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,flags);
749 }
750
751
752 /*++++++++++++++++++++++++++++++++++++++
753 Process the tags associated with a way.
754
755 TagList *tags The list of way tags.
756
757 way_t id The id of the way.
758 ++++++++++++++++++++++++++++++++++++++*/
759
760 static void process_way_tags(TagList *tags,way_t id)
761 {
762 Way way={0};
763 int oneway=0;
764 char *name=NULL,*ref=NULL,*refname=NULL;
765 int i;
766
767 /* Parse the tags - just look for highway */
768
769 for(i=0;i<tags->ntags;i++)
770 {
771 char *k=tags->k[i];
772 char *v=tags->v[i];
773
774 if(!strcmp(k,"highway"))
775 {
776 way.type=HighwayType(v);
777
778 if(way.type==Way_Count)
779 logerror("Way %"Pway_t" has an unrecognised highway type '%s' (after tagging rules); ignoring it.\n",id,v);
780 }
781 }
782
783 /* Don't continue if this is not a highway (bypass error logging) */
784
785 if(way.type==0 || way.type==Way_Count)
786 return;
787
788 /* Parse the tags - look for the others */
789
790 for(i=0;i<tags->ntags;i++)
791 {
792 char *k=tags->k[i];
793 char *v=tags->v[i];
794
795 switch(*k)
796 {
797 case 'b':
798 if(!strcmp(k,"bicycle"))
799 {
800 if(ISTRUE(v))
801 way.allow|=Transports_Bicycle;
802 else if(!ISFALSE(v))
803 logerror("Way %"Pway_t" has an unrecognised tag value 'bicycle' = '%s' (after tagging rules); using 'no'.\n",id,v);
804 }
805
806 if(!strcmp(k,"bicycleroute"))
807 {
808 if(ISTRUE(v))
809 way.props|=Properties_BicycleRoute;
810 else if(!ISFALSE(v))
811 logerror("Way %"Pway_t" has an unrecognised tag value 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
812 }
813
814 if(!strcmp(k,"bridge"))
815 {
816 if(ISTRUE(v))
817 way.props|=Properties_Bridge;
818 else if(!ISFALSE(v))
819 logerror("Way %"Pway_t" has an unrecognised tag value 'bridge' = '%s' (after tagging rules); using 'no'.\n",id,v);
820 }
821
822 break;
823
824 case 'f':
825 if(!strcmp(k,"foot"))
826 {
827 if(ISTRUE(v))
828 way.allow|=Transports_Foot;
829 else if(!ISFALSE(v))
830 logerror("Way %"Pway_t" has an unrecognised tag value 'foot' = '%s' (after tagging rules); using 'no'.\n",id,v);
831 }
832
833 if(!strcmp(k,"footroute"))
834 {
835 if(ISTRUE(v))
836 way.props|=Properties_FootRoute;
837 else if(!ISFALSE(v))
838 logerror("Way %"Pway_t" has an unrecognised tag value 'footroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
839 }
840
841 break;
842
843 case 'g':
844 if(!strcmp(k,"goods"))
845 {
846 if(ISTRUE(v))
847 way.allow|=Transports_Goods;
848 else if(!ISFALSE(v))
849 logerror("Way %"Pway_t" has an unrecognised tag value 'goods' = '%s' (after tagging rules); using 'no'.\n",id,v);
850 }
851
852 break;
853
854 case 'h':
855 if(!strcmp(k,"highway"))
856 ;
857
858 if(!strcmp(k,"horse"))
859 {
860 if(ISTRUE(v))
861 way.allow|=Transports_Horse;
862 else if(!ISFALSE(v))
863 logerror("Way %"Pway_t" has an unrecognised tag value 'horse' = '%s' (after tagging rules); using 'no'.\n",id,v);
864 }
865
866 if(!strcmp(k,"hgv"))
867 {
868 if(ISTRUE(v))
869 way.allow|=Transports_HGV;
870 else if(!ISFALSE(v))
871 logerror("Way %"Pway_t" has an unrecognised tag value 'hgv' = '%s' (after tagging rules); using 'no'.\n",id,v);
872 }
873
874 break;
875
876 case 'm':
877 if(!strcmp(k,"maxspeed"))
878 way.speed=kph_to_speed(parse_speed(id,k,v));
879
880 if(!strcmp(k,"maxweight"))
881 way.weight=tonnes_to_weight(parse_weight(id,k,v));
882
883 if(!strcmp(k,"maxheight"))
884 way.height=metres_to_height(parse_length(id,k,v));
885
886 if(!strcmp(k,"maxwidth"))
887 way.width=metres_to_height(parse_length(id,k,v));
888
889 if(!strcmp(k,"maxlength"))
890 way.length=metres_to_height(parse_length(id,k,v));
891
892 if(!strcmp(k,"moped"))
893 {
894 if(ISTRUE(v))
895 way.allow|=Transports_Moped;
896 else if(!ISFALSE(v))
897 logerror("Way %"Pway_t" has an unrecognised tag value 'moped' = '%s' (after tagging rules); using 'no'.\n",id,v);
898 }
899
900 if(!strcmp(k,"motorbike"))
901 {
902 if(ISTRUE(v))
903 way.allow|=Transports_Motorbike;
904 else if(!ISFALSE(v))
905 logerror("Way %"Pway_t" has an unrecognised tag value 'motorbike' = '%s' (after tagging rules); using 'no'.\n",id,v);
906 }
907
908 if(!strcmp(k,"motorcar"))
909 {
910 if(ISTRUE(v))
911 way.allow|=Transports_Motorcar;
912 else if(!ISFALSE(v))
913 logerror("Way %"Pway_t" has an unrecognised tag value 'motorcar' = '%s' (after tagging rules); using 'no'.\n",id,v);
914 }
915
916 if(!strcmp(k,"multilane"))
917 {
918 if(ISTRUE(v))
919 way.props|=Properties_Multilane;
920 else if(!ISFALSE(v))
921 logerror("Way %"Pway_t" has an unrecognised tag value 'multilane' = '%s' (after tagging rules); using 'no'.\n",id,v);
922 }
923
924 break;
925
926 case 'n':
927 if(!strcmp(k,"name"))
928 name=v;
929
930 break;
931
932 case 'o':
933 if(!strcmp(k,"oneway"))
934 {
935 if(ISTRUE(v))
936 oneway=1;
937 else if(!strcmp(v,"-1"))
938 oneway=-1;
939 else if(!ISFALSE(v))
940 logerror("Way %"Pway_t" has an unrecognised tag value 'oneway' = '%s' (after tagging rules); using 'no'.\n",id,v);
941 }
942
943 break;
944
945 case 'p':
946 if(!strcmp(k,"paved"))
947 {
948 if(ISTRUE(v))
949 way.props|=Properties_Paved;
950 else if(!ISFALSE(v))
951 logerror("Way %"Pway_t" has an unrecognised tag value 'paved' = '%s' (after tagging rules); using 'no'.\n",id,v);
952 }
953
954 if(!strcmp(k,"psv"))
955 {
956 if(ISTRUE(v))
957 way.allow|=Transports_PSV;
958 else if(!ISFALSE(v))
959 logerror("Way %"Pway_t" has an unrecognised tag value 'psv' = '%s' (after tagging rules); using 'no'.\n",id,v);
960 }
961
962 break;
963
964 case 'r':
965 if(!strcmp(k,"ref"))
966 ref=v;
967
968 break;
969
970 case 't':
971 if(!strcmp(k,"tunnel"))
972 {
973 if(ISTRUE(v))
974 way.props|=Properties_Tunnel;
975 else if(!ISFALSE(v))
976 logerror("Way %"Pway_t" has an unrecognised tag value 'tunnel' = '%s' (after tagging rules); using 'no'.\n",id,v);
977 }
978
979 break;
980
981 case 'w':
982 if(!strcmp(k,"wheelchair"))
983 {
984 if(ISTRUE(v))
985 way.allow|=Transports_Wheelchair;
986 else if(!ISFALSE(v))
987 logerror("Way %"Pway_t" has an unrecognised tag value 'wheelchair' = '%s' (after tagging rules); using 'no'.\n",id,v);
988 }
989
990 break;
991
992 default:
993 logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
994 }
995 }
996
997 /* Create the way */
998
999 if(!way.allow)
1000 return;
1001
1002 if(way_nnodes==0)
1003 {
1004 logerror("Way %"Pway_t" has no nodes.\n",id);
1005
1006 return;
1007 }
1008
1009 if(oneway)
1010 way.type|=Way_OneWay;
1011
1012 if(ref && name)
1013 {
1014 refname=(char*)malloc(strlen(ref)+strlen(name)+4);
1015 sprintf(refname,"%s (%s)",name,ref);
1016 }
1017 else if(ref && !name)
1018 refname=ref;
1019 else if(!ref && name)
1020 refname=name;
1021 else /* if(!ref && !name) */
1022 refname="";
1023
1024 AppendWay(ways,id,&way,refname);
1025
1026 if(ref && name)
1027 free(refname);
1028
1029 for(i=1;i<way_nnodes;i++)
1030 {
1031 node_t from=way_nodes[i-1];
1032 node_t to =way_nodes[i];
1033
1034 if(oneway>0)
1035 AppendSegment(segments,id,from,to,ONEWAY_1TO2);
1036 else if(oneway<0)
1037 AppendSegment(segments,id,from,to,ONEWAY_2TO1);
1038 else
1039 AppendSegment(segments,id,from,to,0);
1040 }
1041 }
1042
1043
1044 /*++++++++++++++++++++++++++++++++++++++
1045 Process the tags associated with a relation.
1046
1047 TagList *tags The list of relation tags.
1048
1049 relation_t id The id of the relation.
1050 ++++++++++++++++++++++++++++++++++++++*/
1051
1052 static void process_relation_tags(TagList *tags,relation_t id)
1053 {
1054 transports_t routes=Transports_None;
1055 transports_t except=Transports_None;
1056 int relation_turn_restriction=0;
1057 TurnRestriction restriction=TurnRestrict_None;
1058 int i;
1059
1060 /* Parse the tags */
1061
1062 for(i=0;i<tags->ntags;i++)
1063 {
1064 char *k=tags->k[i];
1065 char *v=tags->v[i];
1066
1067 switch(*k)
1068 {
1069 case 'b':
1070 if(!strcmp(k,"bicycleroute"))
1071 {
1072 if(ISTRUE(v))
1073 routes|=Transports_Bicycle;
1074 else if(!ISFALSE(v))
1075 logerror("Relation %"Prelation_t" has an unrecognised tag value 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
1076 }
1077
1078 break;
1079
1080 case 'e':
1081 if(!strcmp(k,"except"))
1082 {
1083 for(i=1;i<Transport_Count;i++)
1084 if(!strstr(v,TransportName(i)))
1085 except|=TRANSPORTS(i);
1086
1087 if(except==Transports_None)
1088 logerror("Relation %"Prelation_t" has an unrecognised tag value 'except' = '%s' (after tagging rules); ignoring it.\n",id,v);
1089 }
1090
1091 break;
1092
1093 case 'f':
1094 if(!strcmp(k,"footroute"))
1095 {
1096 if(ISTRUE(v))
1097 routes|=Transports_Foot;
1098 else if(!ISFALSE(v))
1099 logerror("Relation %"Prelation_t" has an unrecognised tag value 'footroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
1100 }
1101
1102 break;
1103
1104 case 'r':
1105 if(!strcmp(k,"restriction"))
1106 {
1107 if(!strcmp(v,"no_right_turn" )) restriction=TurnRestrict_no_right_turn;
1108 if(!strcmp(v,"no_left_turn" )) restriction=TurnRestrict_no_left_turn;
1109 if(!strcmp(v,"no_u_turn" )) restriction=TurnRestrict_no_u_turn;
1110 if(!strcmp(v,"no_straight_on" )) restriction=TurnRestrict_no_straight_on;
1111 if(!strcmp(v,"only_right_turn" )) restriction=TurnRestrict_only_right_turn;
1112 if(!strcmp(v,"only_left_turn" )) restriction=TurnRestrict_only_left_turn;
1113 if(!strcmp(v,"only_straight_on")) restriction=TurnRestrict_only_straight_on;
1114
1115 if(restriction==TurnRestrict_None)
1116 logerror("Relation %"Prelation_t" has an unrecognised tag value 'restriction' = '%s' (after tagging rules); ignoring it.\n",id,v);
1117 }
1118
1119 break;
1120
1121 case 't':
1122 if(!strcmp(k,"type"))
1123 if(!strcmp(v,"restriction"))
1124 relation_turn_restriction=1;
1125 break;
1126
1127 default:
1128 logerror("Relation %"Prelation_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1129 }
1130 }
1131
1132 /* Create the route relation (must store all relations that have ways or
1133 relations even if they are not routes because they might be referenced by
1134 other relations that are routes) */
1135
1136 if((relation_nways || relation_nrelations) && !relation_turn_restriction)
1137 AppendRouteRelation(relations,id,routes,
1138 relation_ways,relation_nways,
1139 relation_relations,relation_nrelations);
1140
1141 /* Create the turn restriction relation. */
1142
1143 if(relation_turn_restriction && restriction!=TurnRestrict_None)
1144 {
1145 if(relation_from==NO_WAY_ID)
1146 logerror("Relation %"Prelation_t" is a turn restriction but has no 'from' way.\n",id);
1147 else if(relation_to==NO_WAY_ID)
1148 logerror("Relation %"Prelation_t" is a turn restriction but has no 'to' way.\n",id);
1149 else if(relation_via==NO_NODE_ID)
1150 logerror("Relation %"Prelation_t" is a turn restriction but has no 'via' node.\n",id);
1151 else
1152 AppendTurnRestrictRelation(relations,id,
1153 relation_from,relation_to,relation_via,
1154 restriction,except);
1155 }
1156 }
1157
1158
1159 /*++++++++++++++++++++++++++++++++++++++
1160 Convert a string containing a speed into a double precision.
1161
1162 double parse_speed Returns the speed in km/h if it can be parsed.
1163
1164 way_t id The way being processed.
1165
1166 const char *k The tag key.
1167
1168 const char *v The tag value.
1169 ++++++++++++++++++++++++++++++++++++++*/
1170
1171 static double parse_speed(way_t id,const char *k,const char *v)
1172 {
1173 char *ev;
1174 double value=strtod(v,&ev);
1175
1176 if(v==ev)
1177 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1178 else
1179 {
1180 while(isspace(*ev)) ev++;
1181
1182 if(!strcmp(ev,"mph"))
1183 return(1.609*value);
1184
1185 if(*ev==0 || !strcmp(ev,"kph"))
1186 return(value);
1187
1188 logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1189 }
1190
1191 return(0);
1192 }
1193
1194
1195 /*++++++++++++++++++++++++++++++++++++++
1196 Convert a string containing a weight into a double precision.
1197
1198 double parse_weight Returns the weight in tonnes if it can be parsed.
1199
1200 way_t id The way being processed.
1201
1202 const char *k The tag key.
1203
1204 const char *v The tag value.
1205 ++++++++++++++++++++++++++++++++++++++*/
1206
1207 static double parse_weight(way_t id,const char *k,const char *v)
1208 {
1209 char *ev;
1210 double value=strtod(v,&ev);
1211
1212 if(v==ev)
1213 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1214 else
1215 {
1216 while(isspace(*ev)) ev++;
1217
1218 if(!strcmp(ev,"kg"))
1219 return(value/1000.0);
1220
1221 if(*ev==0 || !strcmp(ev,"T") || !strcmp(ev,"t")
1222 || !strcmp(ev,"ton") || !strcmp(ev,"tons")
1223 || !strcmp(ev,"tonne") || !strcmp(ev,"tonnes"))
1224 return(value);
1225
1226 logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1227 }
1228
1229 return(0);
1230 }
1231
1232
1233 /*++++++++++++++++++++++++++++++++++++++
1234 Convert a string containing a length into a double precision.
1235
1236 double parse_length Returns the length in metres if it can be parsed.
1237
1238 way_t id The way being processed.
1239
1240 const char *k The tag key.
1241
1242 const char *v The tag value.
1243 ++++++++++++++++++++++++++++++++++++++*/
1244
1245 static double parse_length(way_t id,const char *k,const char *v)
1246 {
1247 char *ev;
1248 double value=strtod(v,&ev);
1249
1250 if(v==ev)
1251 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1252 else
1253 {
1254 int en=0;
1255 int feet=0,inches=0;
1256
1257 if(sscanf(v,"%d' %d\"%n",&feet,&inches,&en)==2 && en && !v[en])
1258 return((feet+(double)inches/12.0)*0.254);
1259
1260 if(sscanf(v,"%d - %d%n",&feet,&inches,&en)==2 && en && !v[en])
1261 return((feet+(double)inches/12.0)*0.254);
1262
1263 if(sscanf(v,"%d ft %d in%n",&feet,&inches,&en)==2 && en && !v[en])
1264 return((feet+(double)inches/12.0)*0.254);
1265
1266 if(sscanf(v,"%d feet %d inches%n",&feet,&inches,&en)==2 && en && !v[en])
1267 return((feet+(double)inches/12.0)*0.254);
1268
1269 if(!strcmp(ev,"'"))
1270 return(feet*0.254);
1271
1272 while(isspace(*ev)) ev++;
1273
1274 if(!strcmp(ev,"ft") || !strcmp(ev,"feet"))
1275 return(value*0.254);
1276
1277 if(*ev==0 || !strcmp(ev,"m") || !strcmp(ev,"metre") || !strcmp(ev,"metres"))
1278 return(value);
1279
1280 logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1281 }
1282
1283 return(0);
1284 }

Properties

Name Value
cvs:description OSM XML file parser.