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 1232 - (show annotations) (download) (as text)
Fri Dec 28 11:51:48 2012 UTC (12 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 33111 byte(s)
Log errors for areas that are not closed.

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

Properties

Name Value
cvs:description OSM XML file parser.