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 1339 - (show annotations) (download) (as text)
Thu May 23 17:47:16 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 37686 byte(s)
Don't create segments when parsing input file but create the segments later
using the nodes stored in the ways file.  This makes applying changes simpler
(segments file is not kept with the --keep option) and handling changed ways is
simpler than changed segments.

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

Properties

Name Value
cvs:description OSM XML file parser.