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 1338 - (show annotations) (download) (as text)
Wed May 22 17:31:03 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 38254 byte(s)
Store the list of nodes in the raw ways file for use by the errorlog functions.

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

Properties

Name Value
cvs:description OSM XML file parser.