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

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

Properties

Name Value
cvs:description OSM XML file parser.