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 1140 - (show annotations) (download) (as text)
Fri Nov 16 18:47:07 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 47973 byte(s)
Code to allow adding OSC change files (.osc files) to an existing set of parsed
(and preserved) data.

1 /***************************************
2 OSM XML 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 <assert.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28
29 #include "typesx.h"
30 #include "nodesx.h"
31 #include "segmentsx.h"
32 #include "waysx.h"
33 #include "relationsx.h"
34
35 #include "osmparser.h"
36
37 #include "xmlparse.h"
38 #include "tagging.h"
39
40 #include "logging.h"
41
42
43 /* Macros */
44
45 /*+ Checks if a value in the XML is one of the allowed values for true. +*/
46 #define ISTRUE(xx) (!strcmp(xx,"true") || !strcmp(xx,"yes") || !strcmp(xx,"1"))
47
48 /*+ Checks if a value in the XML is one of the allowed values for false. +*/
49 #define ISFALSE(xx) (!strcmp(xx,"false") || !strcmp(xx,"no") || !strcmp(xx,"0"))
50
51
52 /* Constants */
53
54 #define MODE_CREATE 2
55 #define MODE_MODIFY 1
56 #define MODE_DELETE -1
57
58
59 /* Local variables */
60
61 static int mode=MODE_CREATE;
62
63 static index_t nnodes=0;
64 static index_t nways=0;
65 static index_t nrelations=0;
66
67 static TagList *current_tags=NULL;
68
69 static node_t *way_nodes=NULL;
70 static int way_nnodes=0;
71
72 static node_t *relation_nodes=NULL;
73 static int relation_nnodes=0;
74 static way_t *relation_ways=NULL;
75 static int relation_nways=0;
76 static relation_t *relation_relations=NULL;
77 static int relation_nrelations=0;
78 static way_t relation_from=NO_WAY_ID;
79 static way_t relation_to=NO_WAY_ID;
80 static node_t relation_via=NO_NODE_ID;
81
82 static NodesX *nodes;
83 static SegmentsX *segments;
84 static WaysX *ways;
85 static RelationsX *relations;
86
87
88 /* Local functions */
89
90 static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude);
91 static void process_way_tags(TagList *tags,way_t id);
92 static void process_relation_tags(TagList *tags,relation_t id);
93
94 static double parse_speed(way_t id,const char *k,const char *v);
95 static double parse_weight(way_t id,const char *k,const char *v);
96 static double parse_length(way_t id,const char *k,const char *v);
97
98
99 /* The XML tag processing function prototypes */
100
101 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding);
102 static int osmType_function(const char *_tag_,int _type_,const char *version);
103 static int osmChangeType_function(const char *_tag_,int _type_,const char *version);
104 static int deleteType_function(const char *_tag_,int _type_);
105 static int createType_function(const char *_tag_,int _type_);
106 static int modifyType_function(const char *_tag_,int _type_);
107 static int relationType_function(const char *_tag_,int _type_,const char *id);
108 static int wayType_function(const char *_tag_,int _type_,const char *id);
109 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role);
110 static int ndType_function(const char *_tag_,int _type_,const char *ref);
111 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon);
112 static int changesetType_function(const char *_tag_,int _type_);
113 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v);
114 //static int boundType_function(const char *_tag_,int _type_);
115 //static int boundsType_function(const char *_tag_,int _type_);
116
117
118 /* The XML tag definitions */
119
120 /*+ The boundsType type tag. +*/
121 static xmltag boundsType_tag=
122 {"bounds",
123 0, {NULL},
124 NULL,
125 {NULL}};
126
127 /*+ The boundType type tag. +*/
128 static xmltag boundType_tag=
129 {"bound",
130 0, {NULL},
131 NULL,
132 {NULL}};
133
134 /*+ The tagType type tag. +*/
135 static xmltag tagType_tag=
136 {"tag",
137 2, {"k","v"},
138 tagType_function,
139 {NULL}};
140
141 /*+ The changesetType type tag. +*/
142 static xmltag changesetType_tag=
143 {"changeset",
144 0, {NULL},
145 changesetType_function,
146 {&tagType_tag,NULL}};
147
148 /*+ The nodeType type tag. +*/
149 static xmltag nodeType_tag=
150 {"node",
151 3, {"id","lat","lon"},
152 nodeType_function,
153 {&tagType_tag,NULL}};
154
155 /*+ The ndType type tag. +*/
156 static xmltag ndType_tag=
157 {"nd",
158 1, {"ref"},
159 ndType_function,
160 {NULL}};
161
162 /*+ The memberType type tag. +*/
163 static xmltag memberType_tag=
164 {"member",
165 3, {"type","ref","role"},
166 memberType_function,
167 {NULL}};
168
169 /*+ The wayType type tag. +*/
170 static xmltag wayType_tag=
171 {"way",
172 1, {"id"},
173 wayType_function,
174 {&ndType_tag,&tagType_tag,NULL}};
175
176 /*+ The relationType type tag. +*/
177 static xmltag relationType_tag=
178 {"relation",
179 1, {"id"},
180 relationType_function,
181 {&memberType_tag,&tagType_tag,NULL}};
182
183 /*+ The deleteType type tag. +*/
184 static xmltag deleteType_tag=
185 {"delete",
186 0, {NULL},
187 deleteType_function,
188 {&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
189
190 /*+ The createType type tag. +*/
191 static xmltag createType_tag=
192 {"create",
193 0, {NULL},
194 createType_function,
195 {&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
196
197 /*+ The modifyType type tag. +*/
198 static xmltag modifyType_tag=
199 {"modify",
200 0, {NULL},
201 modifyType_function,
202 {&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
203
204 /*+ The osmChangeType type tag. +*/
205 static xmltag osmChangeType_tag=
206 {"osmChange",
207 1, {"version"},
208 osmChangeType_function,
209 {&boundsType_tag,&modifyType_tag,&createType_tag,&deleteType_tag,NULL}};
210
211 /*+ The osmType type tag. +*/
212 static xmltag osmType_tag=
213 {"osm",
214 1, {"version"},
215 osmType_function,
216 {&boundsType_tag,&boundType_tag,&changesetType_tag,&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
217
218 /*+ The xmlDeclaration type tag. +*/
219 static xmltag xmlDeclaration_tag=
220 {"xml",
221 2, {"version","encoding"},
222 NULL,
223 {NULL}};
224
225
226 /*+ The complete set of tags at the top level for OSM. +*/
227 static xmltag *xml_osm_toplevel_tags[]={&xmlDeclaration_tag,&osmType_tag,NULL};
228
229 /*+ The complete set of tags at the top level for OSC. +*/
230 static xmltag *xml_osc_toplevel_tags[]={&xmlDeclaration_tag,&osmChangeType_tag,NULL};
231
232
233 /* The XML tag processing functions */
234
235
236 /*++++++++++++++++++++++++++++++++++++++
237 The function that is called when the boundsType XSD type is seen
238
239 int boundsType_function Returns 0 if no error occured or something else otherwise.
240
241 const char *_tag_ Set to the name of the element tag that triggered this function call.
242
243 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
244 ++++++++++++++++++++++++++++++++++++++*/
245
246 //static int boundsType_function(const char *_tag_,int _type_)
247 //{
248 // return(0);
249 //}
250
251
252 /*++++++++++++++++++++++++++++++++++++++
253 The function that is called when the boundType XSD type is seen
254
255 int boundType_function Returns 0 if no error occured or something else otherwise.
256
257 const char *_tag_ Set to the name of the element tag that triggered this function call.
258
259 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
260 ++++++++++++++++++++++++++++++++++++++*/
261
262 //static int boundType_function(const char *_tag_,int _type_)
263 //{
264 // return(0);
265 //}
266
267
268 /*++++++++++++++++++++++++++++++++++++++
269 The function that is called when the tagType XSD type is seen
270
271 int tagType_function Returns 0 if no error occured or something else otherwise.
272
273 const char *_tag_ Set to the name of the element tag that triggered this function call.
274
275 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
276
277 const char *k The contents of the 'k' attribute (or NULL if not defined).
278
279 const char *v The contents of the 'v' attribute (or NULL if not defined).
280 ++++++++++++++++++++++++++++++++++++++*/
281
282 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v)
283 {
284 if(_type_&XMLPARSE_TAG_START && current_tags)
285 {
286 XMLPARSE_ASSERT_STRING(_tag_,k);
287 XMLPARSE_ASSERT_STRING(_tag_,v);
288
289 AppendTag(current_tags,k,v);
290 }
291
292 return(0);
293 }
294
295
296 /*++++++++++++++++++++++++++++++++++++++
297 The function that is called when the changesetType XSD type is seen
298
299 int changesetType_function Returns 0 if no error occured or something else otherwise.
300
301 const char *_tag_ Set to the name of the element tag that triggered this function call.
302
303 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
304 ++++++++++++++++++++++++++++++++++++++*/
305
306 static int changesetType_function(const char *_tag_,int _type_)
307 {
308 current_tags=NULL;
309
310 return(0);
311 }
312
313
314 /*++++++++++++++++++++++++++++++++++++++
315 The function that is called when the nodeType XSD type is seen
316
317 int nodeType_function Returns 0 if no error occured or something else otherwise.
318
319 const char *_tag_ Set to the name of the element tag that triggered this function call.
320
321 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
322
323 const char *id The contents of the 'id' attribute (or NULL if not defined).
324
325 const char *lat The contents of the 'lat' attribute (or NULL if not defined).
326
327 const char *lon The contents of the 'lon' attribute (or NULL if not defined).
328 ++++++++++++++++++++++++++++++++++++++*/
329
330 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon)
331 {
332 static node_t node_id;
333 static double latitude,longitude;
334
335 if(_type_&XMLPARSE_TAG_START)
336 {
337 long long llid;
338
339 nnodes++;
340
341 if(!(nnodes%10000))
342 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
343
344 current_tags=NewTagList();
345
346 /* Handle the node information */
347
348 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
349 node_id=(node_t)llid;
350 assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
351
352 if(mode!=MODE_DELETE)
353 {
354 XMLPARSE_ASSERT_FLOATING(_tag_,lat); latitude =atof(lat);
355 XMLPARSE_ASSERT_FLOATING(_tag_,lon); longitude=atof(lon);
356 }
357 }
358
359 if(_type_&XMLPARSE_TAG_END)
360 {
361 TagList *result=ApplyTaggingRules(&NodeRules,current_tags,node_id);
362
363 process_node_tags(result,node_id,latitude,longitude);
364
365 DeleteTagList(current_tags); current_tags=NULL;
366 DeleteTagList(result);
367 }
368
369 return(0);
370 }
371
372
373 /*++++++++++++++++++++++++++++++++++++++
374 The function that is called when the ndType XSD type is seen
375
376 int ndType_function Returns 0 if no error occured or something else otherwise.
377
378 const char *_tag_ Set to the name of the element tag that triggered this function call.
379
380 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
381
382 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
383 ++++++++++++++++++++++++++++++++++++++*/
384
385 static int ndType_function(const char *_tag_,int _type_,const char *ref)
386 {
387 if(_type_&XMLPARSE_TAG_START)
388 {
389 long long llid;
390 node_t node_id;
391
392 XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */
393 node_id=(node_t)llid;
394 assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
395
396 if(way_nnodes && (way_nnodes%256)==0)
397 way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t));
398
399 way_nodes[way_nnodes++]=node_id;
400 }
401
402 return(0);
403 }
404
405
406 /*++++++++++++++++++++++++++++++++++++++
407 The function that is called when the memberType XSD type is seen
408
409 int memberType_function Returns 0 if no error occured or something else otherwise.
410
411 const char *_tag_ Set to the name of the element tag that triggered this function call.
412
413 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
414
415 const char *type The contents of the 'type' attribute (or NULL if not defined).
416
417 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
418
419 const char *role The contents of the 'role' attribute (or NULL if not defined).
420 ++++++++++++++++++++++++++++++++++++++*/
421
422 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role)
423 {
424 if(_type_&XMLPARSE_TAG_START)
425 {
426 long long llid;
427
428 XMLPARSE_ASSERT_STRING(_tag_,type);
429 XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */
430
431 if(!strcmp(type,"node"))
432 {
433 node_t node_id;
434
435 node_id=(node_t)llid;
436 assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
437
438 if(relation_nnodes && (relation_nnodes%256)==0)
439 relation_nodes=(node_t*)realloc((void*)relation_nodes,(relation_nnodes+256)*sizeof(node_t));
440
441 relation_nodes[relation_nnodes++]=node_id;
442
443 if(role)
444 {
445 if(!strcmp(role,"via"))
446 relation_via=node_id;
447 }
448 }
449 else if(!strcmp(type,"way"))
450 {
451 way_t way_id;
452
453 way_id=(way_t)llid;
454 assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */
455
456 if(relation_nways && (relation_nways%256)==0)
457 relation_ways=(way_t*)realloc((void*)relation_ways,(relation_nways+256)*sizeof(way_t));
458
459 relation_ways[relation_nways++]=way_id;
460
461 if(role)
462 {
463 if(!strcmp(role,"from"))
464 relation_from=way_id;
465 if(!strcmp(role,"to"))
466 relation_to=way_id;
467 }
468 }
469 else if(!strcmp(type,"relation"))
470 {
471 relation_t relation_id;
472
473 relation_id=(relation_t)llid;
474 assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */
475
476 if(relation_nrelations && (relation_nrelations%256)==0)
477 relation_relations=(relation_t*)realloc((void*)relation_relations,(relation_nrelations+256)*sizeof(relation_t));
478
479 relation_relations[relation_nrelations++]=relation_id;
480 }
481 }
482
483 return(0);
484 }
485
486
487 /*++++++++++++++++++++++++++++++++++++++
488 The function that is called when the wayType XSD type is seen
489
490 int wayType_function Returns 0 if no error occured or something else otherwise.
491
492 const char *_tag_ Set to the name of the element tag that triggered this function call.
493
494 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
495
496 const char *id The contents of the 'id' attribute (or NULL if not defined).
497 ++++++++++++++++++++++++++++++++++++++*/
498
499 static int wayType_function(const char *_tag_,int _type_,const char *id)
500 {
501 static way_t way_id;
502
503 if(_type_&XMLPARSE_TAG_START)
504 {
505 long long llid;
506
507 nways++;
508
509 if(!(nways%1000))
510 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
511
512 current_tags=NewTagList();
513
514 way_nnodes=0;
515
516 /* Handle the way information */
517
518 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
519
520 way_id=(way_t)llid;
521 assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */
522 }
523
524 if(_type_&XMLPARSE_TAG_END)
525 {
526 TagList *result=ApplyTaggingRules(&WayRules,current_tags,way_id);
527
528 process_way_tags(result,way_id);
529
530 DeleteTagList(current_tags); current_tags=NULL;
531 DeleteTagList(result);
532 }
533
534 return(0);
535 }
536
537
538 /*++++++++++++++++++++++++++++++++++++++
539 The function that is called when the relationType XSD type is seen
540
541 int relationType_function Returns 0 if no error occured or something else otherwise.
542
543 const char *_tag_ Set to the name of the element tag that triggered this function call.
544
545 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
546
547 const char *id The contents of the 'id' attribute (or NULL if not defined).
548 ++++++++++++++++++++++++++++++++++++++*/
549
550 static int relationType_function(const char *_tag_,int _type_,const char *id)
551 {
552 static relation_t relation_id;
553
554 if(_type_&XMLPARSE_TAG_START)
555 {
556 long long llid;
557
558 nrelations++;
559
560 if(!(nrelations%1000))
561 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
562
563 current_tags=NewTagList();
564
565 relation_nnodes=relation_nways=relation_nrelations=0;
566
567 relation_from=NO_WAY_ID;
568 relation_to=NO_WAY_ID;
569 relation_via=NO_NODE_ID;
570
571 /* Handle the relation information */
572
573 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
574
575 relation_id=(relation_t)llid;
576 assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */
577 }
578
579 if(_type_&XMLPARSE_TAG_END)
580 {
581 TagList *result=ApplyTaggingRules(&RelationRules,current_tags,relation_id);
582
583 process_relation_tags(result,relation_id);
584
585 DeleteTagList(current_tags); current_tags=NULL;
586 DeleteTagList(result);
587 }
588
589 return(0);
590 }
591
592
593 /*++++++++++++++++++++++++++++++++++++++
594 The function that is called when the deleteType XSD type is seen
595
596 int deleteType_function Returns 0 if no error occured or something else otherwise.
597
598 const char *_tag_ Set to the name of the element tag that triggered this function call.
599
600 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
601 ++++++++++++++++++++++++++++++++++++++*/
602
603 static int deleteType_function(const char *_tag_,int _type_)
604 {
605 if(_type_&XMLPARSE_TAG_START)
606 mode=MODE_DELETE;
607
608 return(0);
609 }
610
611
612 /*++++++++++++++++++++++++++++++++++++++
613 The function that is called when the createType XSD type is seen
614
615 int createType_function Returns 0 if no error occured or something else otherwise.
616
617 const char *_tag_ Set to the name of the element tag that triggered this function call.
618
619 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
620 ++++++++++++++++++++++++++++++++++++++*/
621
622 static int createType_function(const char *_tag_,int _type_)
623 {
624 if(_type_&XMLPARSE_TAG_START)
625 mode=MODE_CREATE;
626
627 return(0);
628 }
629
630
631 /*++++++++++++++++++++++++++++++++++++++
632 The function that is called when the modifyType XSD type is seen
633
634 int modifyType_function Returns 0 if no error occured or something else otherwise.
635
636 const char *_tag_ Set to the name of the element tag that triggered this function call.
637
638 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
639 ++++++++++++++++++++++++++++++++++++++*/
640
641 static int modifyType_function(const char *_tag_,int _type_)
642 {
643 if(_type_&XMLPARSE_TAG_START)
644 mode=MODE_MODIFY;
645
646 return(0);
647 }
648
649
650 /*++++++++++++++++++++++++++++++++++++++
651 The function that is called when the osmChangeType XSD type is seen
652
653 int osmChangeType_function Returns 0 if no error occured or something else otherwise.
654
655 const char *_tag_ Set to the name of the element tag that triggered this function call.
656
657 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
658
659 const char *version The contents of the 'version' attribute (or NULL if not defined).
660 ++++++++++++++++++++++++++++++++++++++*/
661
662 static int osmChangeType_function(const char *_tag_,int _type_,const char *version)
663 {
664 if(_type_&XMLPARSE_TAG_START)
665 {
666 if(!version || strcmp(version,"0.6"))
667 XMLPARSE_MESSAGE(_tag_,"Invalid value for 'version' (only '0.6' accepted)");
668 }
669
670 return(0);
671 }
672
673
674 /*++++++++++++++++++++++++++++++++++++++
675 The function that is called when the osmType XSD type is seen
676
677 int osmType_function Returns 0 if no error occured or something else otherwise.
678
679 const char *_tag_ Set to the name of the element tag that triggered this function call.
680
681 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
682
683 const char *version The contents of the 'version' attribute (or NULL if not defined).
684 ++++++++++++++++++++++++++++++++++++++*/
685
686 static int osmType_function(const char *_tag_,int _type_,const char *version)
687 {
688 if(_type_&XMLPARSE_TAG_START)
689 {
690 mode=MODE_CREATE;
691
692 if(!version || strcmp(version,"0.6"))
693 XMLPARSE_MESSAGE(_tag_,"Invalid value for 'version' (only '0.6' accepted)");
694 }
695
696 return(0);
697 }
698
699
700 /*++++++++++++++++++++++++++++++++++++++
701 The function that is called when the XML declaration is seen
702
703 int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
704
705 const char *_tag_ Set to the name of the element tag that triggered this function call.
706
707 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
708
709 const char *version The contents of the 'version' attribute (or NULL if not defined).
710
711 const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
712 ++++++++++++++++++++++++++++++++++++++*/
713
714 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
715 //{
716 // return(0);
717 //}
718
719
720 /*++++++++++++++++++++++++++++++++++++++
721 Parse an OSM XML file (from JOSM or planet download).
722
723 int ParseOSM Returns 0 if OK or something else in case of an error.
724
725 FILE *file The file to read from.
726
727 NodesX *OSMNodes The data structure of nodes to fill in.
728
729 SegmentsX *OSMSegments The data structure of segments to fill in.
730
731 WaysX *OSMWays The data structure of ways to fill in.
732
733 RelationsX *OSMRelations The data structure of relations to fill in.
734 ++++++++++++++++++++++++++++++++++++++*/
735
736 int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations)
737 {
738 int retval;
739
740 /* Copy the function parameters and initialise the variables. */
741
742 nodes=OSMNodes;
743 segments=OSMSegments;
744 ways=OSMWays;
745 relations=OSMRelations;
746
747 way_nodes=(node_t*)malloc(256*sizeof(node_t));
748
749 relation_nodes =(node_t *)malloc(256*sizeof(node_t));
750 relation_ways =(way_t *)malloc(256*sizeof(way_t));
751 relation_relations=(relation_t*)malloc(256*sizeof(relation_t));
752
753 /* Parse the file */
754
755 mode=MODE_CREATE;
756
757 nnodes=0,nways=0,nrelations=0;
758
759 printf_first("Reading: Lines=0 Nodes=0 Ways=0 Relations=0");
760
761 retval=ParseXML(file,xml_osm_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE);
762
763 printf_last("Read: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
764
765 free(way_nodes);
766
767 free(relation_nodes);
768 free(relation_ways);
769 free(relation_relations);
770
771 return(retval);
772 }
773
774
775 /*++++++++++++++++++++++++++++++++++++++
776 Parse an OSC XML file (from planet download).
777
778 int ParseOSC Returns 0 if OK or something else in case of an error.
779
780 FILE *file The file to read from.
781
782 NodesX *OSMNodes The data structure of nodes to fill in.
783
784 SegmentsX *OSMSegments The data structure of segments to fill in.
785
786 WaysX *OSMWays The data structure of ways to fill in.
787
788 RelationsX *OSMRelations The data structure of relations to fill in.
789 ++++++++++++++++++++++++++++++++++++++*/
790
791 int ParseOSC(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations)
792 {
793 int retval;
794
795 /* Copy the function parameters and initialise the variables. */
796
797 nodes=OSMNodes;
798 segments=OSMSegments;
799 ways=OSMWays;
800 relations=OSMRelations;
801
802 way_nodes=(node_t*)malloc(256*sizeof(node_t));
803
804 relation_nodes =(node_t *)malloc(256*sizeof(node_t));
805 relation_ways =(way_t *)malloc(256*sizeof(way_t));
806 relation_relations=(relation_t*)malloc(256*sizeof(relation_t));
807
808 /* Parse the file */
809
810 mode=MODE_CREATE;
811
812 nnodes=0,nways=0,nrelations=0;
813
814 printf_first("Reading: Lines=0 Nodes=0 Ways=0 Relations=0");
815
816 retval=ParseXML(file,xml_osc_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE);
817
818 printf_last("Read: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
819
820 free(way_nodes);
821
822 free(relation_nodes);
823 free(relation_ways);
824 free(relation_relations);
825
826 return(retval);
827 }
828
829
830 /*++++++++++++++++++++++++++++++++++++++
831 Process the tags associated with a node.
832
833 TagList *tags The list of node tags.
834
835 node_t id The id of the node.
836
837 double latitude The latitude of the node.
838
839 double longitude The longitude of the node.
840 ++++++++++++++++++++++++++++++++++++++*/
841
842 static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude)
843 {
844 transports_t allow=Transports_ALL;
845 uint16_t flags=0;
846 int i;
847
848 /* Delete */
849
850 if(mode==MODE_DELETE)
851 {
852 AppendNode(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,NODE_DELETED);
853
854 return;
855 }
856
857 /* Parse the tags */
858
859 for(i=0;i<tags->ntags;i++)
860 {
861 int recognised=0;
862 char *k=tags->k[i];
863 char *v=tags->v[i];
864
865 switch(*k)
866 {
867 case 'b':
868 if(!strcmp(k,"bicycle"))
869 {
870 if(ISFALSE(v))
871 allow&=~Transports_Bicycle;
872 else if(!ISTRUE(v))
873 logerror("Node %"Pnode_t" has an unrecognised tag value 'bicycle' = '%s' (after tagging rules); using 'yes'.\n",id,v);
874 recognised=1; break;
875 }
876
877 break;
878
879 case 'f':
880 if(!strcmp(k,"foot"))
881 {
882 if(ISFALSE(v))
883 allow&=~Transports_Foot;
884 else if(!ISTRUE(v))
885 logerror("Node %"Pnode_t" has an unrecognised tag value 'foot' = '%s' (after tagging rules); using 'yes'.\n",id,v);
886 recognised=1; break;
887 }
888
889 break;
890
891 case 'g':
892 if(!strcmp(k,"goods"))
893 {
894 if(ISFALSE(v))
895 allow&=~Transports_Goods;
896 else if(!ISTRUE(v))
897 logerror("Node %"Pnode_t" has an unrecognised tag value 'goods' = '%s' (after tagging rules); using 'yes'.\n",id,v);
898 recognised=1; break;
899 }
900
901 break;
902
903 case 'h':
904 if(!strcmp(k,"highway"))
905 if(!strcmp(v,"mini_roundabout"))
906 {
907 flags|=NODE_MINIRNDBT;
908 recognised=1; break;
909 }
910
911 if(!strcmp(k,"horse"))
912 {
913 if(ISFALSE(v))
914 allow&=~Transports_Horse;
915 else if(!ISTRUE(v))
916 logerror("Node %"Pnode_t" has an unrecognised tag value 'horse' = '%s' (after tagging rules); using 'yes'.\n",id,v);
917 recognised=1; break;
918 }
919
920 if(!strcmp(k,"hgv"))
921 {
922 if(ISFALSE(v))
923 allow&=~Transports_HGV;
924 else if(!ISTRUE(v))
925 logerror("Node %"Pnode_t" has an unrecognised tag value 'hgv' = '%s' (after tagging rules); using 'yes'.\n",id,v);
926 recognised=1; break;
927 }
928
929 break;
930
931 case 'm':
932 if(!strcmp(k,"moped"))
933 {
934 if(ISFALSE(v))
935 allow&=~Transports_Moped;
936 else if(!ISTRUE(v))
937 logerror("Node %"Pnode_t" has an unrecognised tag value 'moped' = '%s' (after tagging rules); using 'yes'.\n",id,v);
938 recognised=1; break;
939 }
940
941 if(!strcmp(k,"motorbike"))
942 {
943 if(ISFALSE(v))
944 allow&=~Transports_Motorbike;
945 else if(!ISTRUE(v))
946 logerror("Node %"Pnode_t" has an unrecognised tag value 'motorbike' = '%s' (after tagging rules); using 'yes'.\n",id,v);
947 recognised=1; break;
948 }
949
950 if(!strcmp(k,"motorcar"))
951 {
952 if(ISFALSE(v))
953 allow&=~Transports_Motorcar;
954 else if(!ISTRUE(v))
955 logerror("Node %"Pnode_t" has an unrecognised tag value 'motorcar' = '%s' (after tagging rules); using 'yes'.\n",id,v);
956 recognised=1; break;
957 }
958
959 break;
960
961 case 'p':
962 if(!strcmp(k,"psv"))
963 {
964 if(ISFALSE(v))
965 allow&=~Transports_PSV;
966 else if(!ISTRUE(v))
967 logerror("Node %"Pnode_t" has an unrecognised tag value 'psv' = '%s' (after tagging rules); using 'yes'.\n",id,v);
968 recognised=1; break;
969 }
970
971 break;
972
973 case 'w':
974 if(!strcmp(k,"wheelchair"))
975 {
976 if(ISFALSE(v))
977 allow&=~Transports_Wheelchair;
978 else if(!ISTRUE(v))
979 logerror("Node %"Pnode_t" has an unrecognised tag value 'wheelchair' = '%s' (after tagging rules); using 'yes'.\n",id,v);
980 recognised=1; break;
981 }
982
983 break;
984
985 default:
986 break;
987 }
988
989 if(!recognised)
990 logerror("Node %"Pnode_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
991 }
992
993 /* Create the node */
994
995 AppendNode(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,flags);
996 }
997
998
999 /*++++++++++++++++++++++++++++++++++++++
1000 Process the tags associated with a way.
1001
1002 TagList *tags The list of way tags.
1003
1004 way_t id The id of the way.
1005 ++++++++++++++++++++++++++++++++++++++*/
1006
1007 static void process_way_tags(TagList *tags,way_t id)
1008 {
1009 Way way={0};
1010 distance_t oneway=0,area=0;
1011 int roundabout=0;
1012 char *name=NULL,*ref=NULL,*refname=NULL;
1013 int i;
1014
1015 /* Delete */
1016
1017 if(mode==MODE_DELETE)
1018 {
1019 way.type=WAY_DELETED;
1020
1021 AppendWay(ways,id,&way,"");
1022
1023 AppendSegment(segments,id,NO_NODE_ID,NO_NODE_ID,0);
1024
1025 return;
1026 }
1027
1028 /* Sanity check */
1029
1030 if(way_nnodes==0)
1031 {
1032 logerror("Way %"Pway_t" has no nodes.\n",id);
1033 return;
1034 }
1035
1036 if(way_nnodes==1)
1037 {
1038 logerror("Way %"Pway_t" has only one node.\n",id);
1039 return;
1040 }
1041
1042 /* Parse the tags - just look for highway */
1043
1044 for(i=0;i<tags->ntags;i++)
1045 {
1046 char *k=tags->k[i];
1047 char *v=tags->v[i];
1048
1049 if(!strcmp(k,"highway"))
1050 {
1051 way.type=HighwayType(v);
1052
1053 if(way.type==Way_Count)
1054 logerror("Way %"Pway_t" has an unrecognised highway type '%s' (after tagging rules); ignoring it.\n",id,v);
1055 }
1056 }
1057
1058 /* Don't continue if this is not a highway (bypass error logging) */
1059
1060 if(way.type==0 || way.type==Way_Count)
1061 return;
1062
1063 /* Parse the tags - look for the others */
1064
1065 for(i=0;i<tags->ntags;i++)
1066 {
1067 int recognised=0;
1068 char *k=tags->k[i];
1069 char *v=tags->v[i];
1070
1071 switch(*k)
1072 {
1073 case 'a':
1074 if(!strcmp(k,"area"))
1075 {
1076 if(ISTRUE(v))
1077 area=SEGMENT_AREA;
1078 else if(!ISFALSE(v))
1079 logerror("Way %"Pway_t" has an unrecognised tag value 'area' = '%s' (after tagging rules); using 'no'.\n",id,v);
1080 recognised=1; break;
1081 }
1082
1083 break;
1084
1085 case 'b':
1086 if(!strcmp(k,"bicycle"))
1087 {
1088 if(ISTRUE(v))
1089 way.allow|=Transports_Bicycle;
1090 else if(!ISFALSE(v))
1091 logerror("Way %"Pway_t" has an unrecognised tag value 'bicycle' = '%s' (after tagging rules); using 'no'.\n",id,v);
1092 recognised=1; break;
1093 }
1094
1095 if(!strcmp(k,"bicycleroute"))
1096 {
1097 if(ISTRUE(v))
1098 way.props|=Properties_BicycleRoute;
1099 else if(!ISFALSE(v))
1100 logerror("Way %"Pway_t" has an unrecognised tag value 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
1101 recognised=1; break;
1102 }
1103
1104 if(!strcmp(k,"bridge"))
1105 {
1106 if(ISTRUE(v))
1107 way.props|=Properties_Bridge;
1108 else if(!ISFALSE(v))
1109 logerror("Way %"Pway_t" has an unrecognised tag value 'bridge' = '%s' (after tagging rules); using 'no'.\n",id,v);
1110 recognised=1; break;
1111 }
1112
1113 break;
1114
1115 case 'f':
1116 if(!strcmp(k,"foot"))
1117 {
1118 if(ISTRUE(v))
1119 way.allow|=Transports_Foot;
1120 else if(!ISFALSE(v))
1121 logerror("Way %"Pway_t" has an unrecognised tag value 'foot' = '%s' (after tagging rules); using 'no'.\n",id,v);
1122 recognised=1; break;
1123 }
1124
1125 if(!strcmp(k,"footroute"))
1126 {
1127 if(ISTRUE(v))
1128 way.props|=Properties_FootRoute;
1129 else if(!ISFALSE(v))
1130 logerror("Way %"Pway_t" has an unrecognised tag value 'footroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
1131 recognised=1; break;
1132 }
1133
1134 break;
1135
1136 case 'g':
1137 if(!strcmp(k,"goods"))
1138 {
1139 if(ISTRUE(v))
1140 way.allow|=Transports_Goods;
1141 else if(!ISFALSE(v))
1142 logerror("Way %"Pway_t" has an unrecognised tag value 'goods' = '%s' (after tagging rules); using 'no'.\n",id,v);
1143 recognised=1; break;
1144 }
1145
1146 break;
1147
1148 case 'h':
1149 if(!strcmp(k,"highway"))
1150 {recognised=1; break;}
1151
1152 if(!strcmp(k,"horse"))
1153 {
1154 if(ISTRUE(v))
1155 way.allow|=Transports_Horse;
1156 else if(!ISFALSE(v))
1157 logerror("Way %"Pway_t" has an unrecognised tag value 'horse' = '%s' (after tagging rules); using 'no'.\n",id,v);
1158 recognised=1; break;
1159 }
1160
1161 if(!strcmp(k,"hgv"))
1162 {
1163 if(ISTRUE(v))
1164 way.allow|=Transports_HGV;
1165 else if(!ISFALSE(v))
1166 logerror("Way %"Pway_t" has an unrecognised tag value 'hgv' = '%s' (after tagging rules); using 'no'.\n",id,v);
1167 recognised=1; break;
1168 }
1169
1170 break;
1171
1172 case 'm':
1173 if(!strncmp(k,"max",3))
1174 {
1175 if(!strcmp(k+3,"speed"))
1176 {
1177 way.speed=kph_to_speed(parse_speed(id,k,v));
1178 recognised=1; break;
1179 }
1180
1181 if(!strcmp(k+3,"weight"))
1182 {
1183 way.weight=tonnes_to_weight(parse_weight(id,k,v));
1184 recognised=1; break;
1185 }
1186
1187 if(!strcmp(k+3,"height"))
1188 {
1189 way.height=metres_to_height(parse_length(id,k,v));
1190 recognised=1; break;
1191 }
1192
1193 if(!strcmp(k+3,"width"))
1194 {
1195 way.width=metres_to_height(parse_length(id,k,v));
1196 recognised=1; break;
1197 }
1198
1199 if(!strcmp(k+3,"length"))
1200 {
1201 way.length=metres_to_height(parse_length(id,k,v));
1202 recognised=1; break;
1203 }
1204 }
1205
1206 if(!strcmp(k,"moped"))
1207 {
1208 if(ISTRUE(v))
1209 way.allow|=Transports_Moped;
1210 else if(!ISFALSE(v))
1211 logerror("Way %"Pway_t" has an unrecognised tag value 'moped' = '%s' (after tagging rules); using 'no'.\n",id,v);
1212 recognised=1; break;
1213 }
1214
1215 if(!strcmp(k,"motorbike"))
1216 {
1217 if(ISTRUE(v))
1218 way.allow|=Transports_Motorbike;
1219 else if(!ISFALSE(v))
1220 logerror("Way %"Pway_t" has an unrecognised tag value 'motorbike' = '%s' (after tagging rules); using 'no'.\n",id,v);
1221 recognised=1; break;
1222 }
1223
1224 if(!strcmp(k,"motorcar"))
1225 {
1226 if(ISTRUE(v))
1227 way.allow|=Transports_Motorcar;
1228 else if(!ISFALSE(v))
1229 logerror("Way %"Pway_t" has an unrecognised tag value 'motorcar' = '%s' (after tagging rules); using 'no'.\n",id,v);
1230 recognised=1; break;
1231 }
1232
1233 if(!strcmp(k,"multilane"))
1234 {
1235 if(ISTRUE(v))
1236 way.props|=Properties_Multilane;
1237 else if(!ISFALSE(v))
1238 logerror("Way %"Pway_t" has an unrecognised tag value 'multilane' = '%s' (after tagging rules); using 'no'.\n",id,v);
1239 recognised=1; break;
1240 }
1241
1242 break;
1243
1244 case 'n':
1245 if(!strcmp(k,"name"))
1246 {
1247 name=v;
1248 recognised=1; break;
1249 }
1250
1251 break;
1252
1253 case 'o':
1254 if(!strcmp(k,"oneway"))
1255 {
1256 if(ISTRUE(v))
1257 oneway=ONEWAY_1TO2;
1258 else if(!strcmp(v,"-1"))
1259 oneway=ONEWAY_2TO1;
1260 else if(!ISFALSE(v))
1261 logerror("Way %"Pway_t" has an unrecognised tag value 'oneway' = '%s' (after tagging rules); using 'no'.\n",id,v);
1262 recognised=1; break;
1263 }
1264
1265 break;
1266
1267 case 'p':
1268 if(!strcmp(k,"paved"))
1269 {
1270 if(ISTRUE(v))
1271 way.props|=Properties_Paved;
1272 else if(!ISFALSE(v))
1273 logerror("Way %"Pway_t" has an unrecognised tag value 'paved' = '%s' (after tagging rules); using 'no'.\n",id,v);
1274 recognised=1; break;
1275 }
1276
1277 if(!strcmp(k,"psv"))
1278 {
1279 if(ISTRUE(v))
1280 way.allow|=Transports_PSV;
1281 else if(!ISFALSE(v))
1282 logerror("Way %"Pway_t" has an unrecognised tag value 'psv' = '%s' (after tagging rules); using 'no'.\n",id,v);
1283 recognised=1; break;
1284 }
1285
1286 break;
1287
1288 case 'r':
1289 if(!strcmp(k,"ref"))
1290 {
1291 ref=v;
1292 recognised=1; break;
1293 }
1294
1295 if(!strcmp(k,"roundabout"))
1296 {
1297 if(ISTRUE(v))
1298 roundabout=1;
1299 else if(!ISFALSE(v))
1300 logerror("Way %"Pway_t" has an unrecognised tag value 'roundabout' = '%s' (after tagging rules); using 'no'.\n",id,v);
1301 recognised=1; break;
1302 }
1303
1304 break;
1305
1306 case 't':
1307 if(!strcmp(k,"tunnel"))
1308 {
1309 if(ISTRUE(v))
1310 way.props|=Properties_Tunnel;
1311 else if(!ISFALSE(v))
1312 logerror("Way %"Pway_t" has an unrecognised tag value 'tunnel' = '%s' (after tagging rules); using 'no'.\n",id,v);
1313 recognised=1; break;
1314 }
1315
1316 break;
1317
1318 case 'w':
1319 if(!strcmp(k,"wheelchair"))
1320 {
1321 if(ISTRUE(v))
1322 way.allow|=Transports_Wheelchair;
1323 else if(!ISFALSE(v))
1324 logerror("Way %"Pway_t" has an unrecognised tag value 'wheelchair' = '%s' (after tagging rules); using 'no'.\n",id,v);
1325 recognised=1; break;
1326 }
1327
1328 break;
1329
1330 default:
1331 break;
1332 }
1333
1334 if(!recognised)
1335 logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1336 }
1337
1338 /* Create the way */
1339
1340 if(!way.allow)
1341 return;
1342
1343 if(oneway)
1344 way.type|=Way_OneWay;
1345
1346 if(roundabout)
1347 way.type|=Way_Roundabout;
1348
1349 if(ref && name)
1350 {
1351 refname=(char*)malloc(strlen(ref)+strlen(name)+4);
1352 sprintf(refname,"%s (%s)",name,ref);
1353 }
1354 else if(ref && !name)
1355 refname=ref;
1356 else if(!ref && name)
1357 refname=name;
1358 else /* if(!ref && !name) */
1359 refname="";
1360
1361 AppendWay(ways,id,&way,refname);
1362
1363 if(ref && name)
1364 free(refname);
1365
1366 if(mode==MODE_MODIFY)
1367 AppendSegment(segments,id,NO_NODE_ID,NO_NODE_ID,0);
1368
1369 for(i=1;i<way_nnodes;i++)
1370 {
1371 node_t from=way_nodes[i-1];
1372 node_t to =way_nodes[i];
1373
1374 AppendSegment(segments,id,from,to,area+oneway);
1375 }
1376 }
1377
1378
1379 /*++++++++++++++++++++++++++++++++++++++
1380 Process the tags associated with a relation.
1381
1382 TagList *tags The list of relation tags.
1383
1384 relation_t id The id of the relation.
1385 ++++++++++++++++++++++++++++++++++++++*/
1386
1387 static void process_relation_tags(TagList *tags,relation_t id)
1388 {
1389 transports_t routes=Transports_None;
1390 transports_t except=Transports_None;
1391 int relation_turn_restriction=0;
1392 TurnRestriction restriction=TurnRestrict_None;
1393 int i;
1394
1395 /* Delete */
1396
1397 if(mode==MODE_DELETE)
1398 {
1399 AppendRouteRelation(relations,id,RELATION_DELETED,
1400 relation_ways,relation_nways,
1401 relation_relations,relation_nrelations);
1402
1403 AppendTurnRestrictRelation(relations,id,
1404 relation_from,relation_to,relation_via,
1405 restriction,RELATION_DELETED);
1406
1407 return;
1408 }
1409
1410 /* Sanity check */
1411
1412 if(relation_nnodes==0 && relation_nways==0 && relation_nrelations==0)
1413 {
1414 logerror("Relation %"Prelation_t" has no nodes, ways or relations.\n",id);
1415 return;
1416 }
1417
1418 /* Parse the tags */
1419
1420 for(i=0;i<tags->ntags;i++)
1421 {
1422 int recognised=0;
1423 char *k=tags->k[i];
1424 char *v=tags->v[i];
1425
1426 switch(*k)
1427 {
1428 case 'b':
1429 if(!strcmp(k,"bicycleroute"))
1430 {
1431 if(ISTRUE(v))
1432 routes|=Transports_Bicycle;
1433 else if(!ISFALSE(v))
1434 logerror("Relation %"Prelation_t" has an unrecognised tag value 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
1435 recognised=1; break;
1436 }
1437
1438 break;
1439
1440 case 'e':
1441 if(!strcmp(k,"except"))
1442 {
1443 for(i=1;i<Transport_Count;i++)
1444 if(strstr(v,TransportName(i)))
1445 except|=TRANSPORTS(i);
1446
1447 if(except==Transports_None)
1448 logerror("Relation %"Prelation_t" has an unrecognised tag value 'except' = '%s' (after tagging rules); ignoring it.\n",id,v);
1449
1450 recognised=1; break;
1451 }
1452
1453 break;
1454
1455 case 'f':
1456 if(!strcmp(k,"footroute"))
1457 {
1458 if(ISTRUE(v))
1459 routes|=Transports_Foot;
1460 else if(!ISFALSE(v))
1461 logerror("Relation %"Prelation_t" has an unrecognised tag value 'footroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
1462 recognised=1; break;
1463 }
1464
1465 break;
1466
1467 case 'r':
1468 if(!strcmp(k,"restriction"))
1469 {
1470 if(!strcmp(v,"no_right_turn" )) restriction=TurnRestrict_no_right_turn;
1471 if(!strcmp(v,"no_left_turn" )) restriction=TurnRestrict_no_left_turn;
1472 if(!strcmp(v,"no_u_turn" )) restriction=TurnRestrict_no_u_turn;
1473 if(!strcmp(v,"no_straight_on" )) restriction=TurnRestrict_no_straight_on;
1474 if(!strcmp(v,"only_right_turn" )) restriction=TurnRestrict_only_right_turn;
1475 if(!strcmp(v,"only_left_turn" )) restriction=TurnRestrict_only_left_turn;
1476 if(!strcmp(v,"only_straight_on")) restriction=TurnRestrict_only_straight_on;
1477
1478 if(restriction==TurnRestrict_None)
1479 logerror("Relation %"Prelation_t" has an unrecognised tag value 'restriction' = '%s' (after tagging rules); ignoring it.\n",id,v);
1480
1481 recognised=1; break;
1482 }
1483
1484 break;
1485
1486 case 't':
1487 if(!strcmp(k,"type"))
1488 {
1489 if(!strcmp(v,"restriction"))
1490 relation_turn_restriction=1;
1491
1492 /* Don't log an error for relations of types that we don't handle - there are so many */
1493 recognised=1; break;
1494 }
1495
1496 break;
1497
1498 default:
1499 break;
1500 }
1501
1502 if(!recognised)
1503 logerror("Relation %"Prelation_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1504 }
1505
1506 /* Create the route relation (must store all relations that have ways or
1507 relations even if they are not routes because they might be referenced by
1508 other relations that are routes) */
1509
1510 if((relation_nways || relation_nrelations) && !relation_turn_restriction)
1511 AppendRouteRelation(relations,id,routes,
1512 relation_ways,relation_nways,
1513 relation_relations,relation_nrelations);
1514
1515 /* Create the turn restriction relation. */
1516
1517 if(relation_turn_restriction && restriction!=TurnRestrict_None)
1518 {
1519 if(relation_from==NO_WAY_ID)
1520 logerror("Relation %"Prelation_t" is a turn restriction but has no 'from' way.\n",id);
1521 else if(relation_to==NO_WAY_ID)
1522 logerror("Relation %"Prelation_t" is a turn restriction but has no 'to' way.\n",id);
1523 else if(relation_via==NO_NODE_ID)
1524 logerror("Relation %"Prelation_t" is a turn restriction but has no 'via' node.\n",id);
1525 else
1526 AppendTurnRestrictRelation(relations,id,
1527 relation_from,relation_to,relation_via,
1528 restriction,except);
1529 }
1530 }
1531
1532
1533 /*++++++++++++++++++++++++++++++++++++++
1534 Convert a string containing a speed into a double precision.
1535
1536 double parse_speed Returns the speed in km/h if it can be parsed.
1537
1538 way_t id The way being processed.
1539
1540 const char *k The tag key.
1541
1542 const char *v The tag value.
1543 ++++++++++++++++++++++++++++++++++++++*/
1544
1545 static double parse_speed(way_t id,const char *k,const char *v)
1546 {
1547 char *ev;
1548 double value=strtod(v,&ev);
1549
1550 if(v==ev)
1551 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1552 else
1553 {
1554 while(isspace(*ev)) ev++;
1555
1556 if(!strcmp(ev,"mph"))
1557 return(1.609*value);
1558
1559 if(*ev==0 || !strcmp(ev,"kph"))
1560 return(value);
1561
1562 logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1563 }
1564
1565 return(0);
1566 }
1567
1568
1569 /*++++++++++++++++++++++++++++++++++++++
1570 Convert a string containing a weight into a double precision.
1571
1572 double parse_weight Returns the weight in tonnes if it can be parsed.
1573
1574 way_t id The way being processed.
1575
1576 const char *k The tag key.
1577
1578 const char *v The tag value.
1579 ++++++++++++++++++++++++++++++++++++++*/
1580
1581 static double parse_weight(way_t id,const char *k,const char *v)
1582 {
1583 char *ev;
1584 double value=strtod(v,&ev);
1585
1586 if(v==ev)
1587 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1588 else
1589 {
1590 while(isspace(*ev)) ev++;
1591
1592 if(!strcmp(ev,"kg"))
1593 return(value/1000.0);
1594
1595 if(*ev==0 || !strcmp(ev,"T") || !strcmp(ev,"t")
1596 || !strcmp(ev,"ton") || !strcmp(ev,"tons")
1597 || !strcmp(ev,"tonne") || !strcmp(ev,"tonnes"))
1598 return(value);
1599
1600 logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1601 }
1602
1603 return(0);
1604 }
1605
1606
1607 /*++++++++++++++++++++++++++++++++++++++
1608 Convert a string containing a length into a double precision.
1609
1610 double parse_length Returns the length in metres if it can be parsed.
1611
1612 way_t id The way being processed.
1613
1614 const char *k The tag key.
1615
1616 const char *v The tag value.
1617 ++++++++++++++++++++++++++++++++++++++*/
1618
1619 static double parse_length(way_t id,const char *k,const char *v)
1620 {
1621 char *ev;
1622 double value=strtod(v,&ev);
1623
1624 if(v==ev)
1625 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1626 else
1627 {
1628 int en=0;
1629 int feet=0,inches=0;
1630
1631 if(sscanf(v,"%d' %d\"%n",&feet,&inches,&en)==2 && en && !v[en])
1632 return((feet+(double)inches/12.0)*0.254);
1633
1634 if(sscanf(v,"%d'%d\"%n",&feet,&inches,&en)==2 && en && !v[en])
1635 return((feet+(double)inches/12.0)*0.254);
1636
1637 if(sscanf(v,"%d'-%d\"%n",&feet,&inches,&en)==2 && en && !v[en])
1638 return((feet+(double)inches/12.0)*0.254);
1639
1640 if(sscanf(v,"%d - %d%n",&feet,&inches,&en)==2 && en && !v[en])
1641 return((feet+(double)inches/12.0)*0.254);
1642
1643 if(sscanf(v,"%d ft %d in%n",&feet,&inches,&en)==2 && en && !v[en])
1644 return((feet+(double)inches/12.0)*0.254);
1645
1646 if(sscanf(v,"%d feet %d inches%n",&feet,&inches,&en)==2 && en && !v[en])
1647 return((feet+(double)inches/12.0)*0.254);
1648
1649 if(!strcmp(ev,"'"))
1650 return(feet*0.254);
1651
1652 while(isspace(*ev)) ev++;
1653
1654 if(!strcmp(ev,"ft") || !strcmp(ev,"feet"))
1655 return(value*0.254);
1656
1657 if(*ev==0 || !strcmp(ev,"m") || !strcmp(ev,"metre") || !strcmp(ev,"metres"))
1658 return(value);
1659
1660 logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1661 }
1662
1663 return(0);
1664 }

Properties

Name Value
cvs:description OSM XML file parser.