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 1164 - (show annotations) (download) (as text)
Tue Nov 20 15:24:30 2012 UTC (12 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 48009 byte(s)
Replace the 32-bit combined distance and flags in the segment with 16 bits for
each.

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_NORMAL 3
55 #define MODE_CREATE 2
56 #define MODE_MODIFY 1
57 #define MODE_DELETE -1
58
59
60 /* Local variables */
61
62 static int mode=MODE_NORMAL;
63
64 static index_t nnodes=0;
65 static index_t nways=0;
66 static index_t nrelations=0;
67
68 static TagList *current_tags=NULL;
69
70 static node_t *way_nodes=NULL;
71 static int way_nnodes=0;
72
73 static node_t *relation_nodes=NULL;
74 static int relation_nnodes=0;
75 static way_t *relation_ways=NULL;
76 static int relation_nways=0;
77 static relation_t *relation_relations=NULL;
78 static int relation_nrelations=0;
79 static way_t relation_from=NO_WAY_ID;
80 static way_t relation_to=NO_WAY_ID;
81 static node_t relation_via=NO_NODE_ID;
82
83 static NodesX *nodes;
84 static SegmentsX *segments;
85 static WaysX *ways;
86 static RelationsX *relations;
87
88
89 /* Local functions */
90
91 static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude);
92 static void process_way_tags(TagList *tags,way_t id);
93 static void process_relation_tags(TagList *tags,relation_t id);
94
95 static double parse_speed(way_t id,const char *k,const char *v);
96 static double parse_weight(way_t id,const char *k,const char *v);
97 static double parse_length(way_t id,const char *k,const char *v);
98
99
100 /* The XML tag processing function prototypes */
101
102 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding);
103 static int osmType_function(const char *_tag_,int _type_,const char *version);
104 static int osmChangeType_function(const char *_tag_,int _type_,const char *version);
105 static int deleteType_function(const char *_tag_,int _type_);
106 static int createType_function(const char *_tag_,int _type_);
107 static int modifyType_function(const char *_tag_,int _type_);
108 static int relationType_function(const char *_tag_,int _type_,const char *id);
109 static int wayType_function(const char *_tag_,int _type_,const char *id);
110 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role);
111 static int ndType_function(const char *_tag_,int _type_,const char *ref);
112 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon);
113 static int changesetType_function(const char *_tag_,int _type_);
114 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v);
115 //static int boundType_function(const char *_tag_,int _type_);
116 //static int boundsType_function(const char *_tag_,int _type_);
117
118
119 /* The XML tag definitions */
120
121 /*+ The boundsType type tag. +*/
122 static xmltag boundsType_tag=
123 {"bounds",
124 0, {NULL},
125 NULL,
126 {NULL}};
127
128 /*+ The boundType type tag. +*/
129 static xmltag boundType_tag=
130 {"bound",
131 0, {NULL},
132 NULL,
133 {NULL}};
134
135 /*+ The tagType type tag. +*/
136 static xmltag tagType_tag=
137 {"tag",
138 2, {"k","v"},
139 tagType_function,
140 {NULL}};
141
142 /*+ The changesetType type tag. +*/
143 static xmltag changesetType_tag=
144 {"changeset",
145 0, {NULL},
146 changesetType_function,
147 {&tagType_tag,NULL}};
148
149 /*+ The nodeType type tag. +*/
150 static xmltag nodeType_tag=
151 {"node",
152 3, {"id","lat","lon"},
153 nodeType_function,
154 {&tagType_tag,NULL}};
155
156 /*+ The ndType type tag. +*/
157 static xmltag ndType_tag=
158 {"nd",
159 1, {"ref"},
160 ndType_function,
161 {NULL}};
162
163 /*+ The memberType type tag. +*/
164 static xmltag memberType_tag=
165 {"member",
166 3, {"type","ref","role"},
167 memberType_function,
168 {NULL}};
169
170 /*+ The wayType type tag. +*/
171 static xmltag wayType_tag=
172 {"way",
173 1, {"id"},
174 wayType_function,
175 {&ndType_tag,&tagType_tag,NULL}};
176
177 /*+ The relationType type tag. +*/
178 static xmltag relationType_tag=
179 {"relation",
180 1, {"id"},
181 relationType_function,
182 {&memberType_tag,&tagType_tag,NULL}};
183
184 /*+ The deleteType type tag. +*/
185 static xmltag deleteType_tag=
186 {"delete",
187 0, {NULL},
188 deleteType_function,
189 {&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
190
191 /*+ The createType type tag. +*/
192 static xmltag createType_tag=
193 {"create",
194 0, {NULL},
195 createType_function,
196 {&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
197
198 /*+ The modifyType type tag. +*/
199 static xmltag modifyType_tag=
200 {"modify",
201 0, {NULL},
202 modifyType_function,
203 {&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
204
205 /*+ The osmChangeType type tag. +*/
206 static xmltag osmChangeType_tag=
207 {"osmChange",
208 1, {"version"},
209 osmChangeType_function,
210 {&boundsType_tag,&modifyType_tag,&createType_tag,&deleteType_tag,NULL}};
211
212 /*+ The osmType type tag. +*/
213 static xmltag osmType_tag=
214 {"osm",
215 1, {"version"},
216 osmType_function,
217 {&boundsType_tag,&boundType_tag,&changesetType_tag,&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
218
219 /*+ The xmlDeclaration type tag. +*/
220 static xmltag xmlDeclaration_tag=
221 {"xml",
222 2, {"version","encoding"},
223 NULL,
224 {NULL}};
225
226
227 /*+ The complete set of tags at the top level for OSM. +*/
228 static xmltag *xml_osm_toplevel_tags[]={&xmlDeclaration_tag,&osmType_tag,NULL};
229
230 /*+ The complete set of tags at the top level for OSC. +*/
231 static xmltag *xml_osc_toplevel_tags[]={&xmlDeclaration_tag,&osmChangeType_tag,NULL};
232
233
234 /* The XML tag processing functions */
235
236
237 /*++++++++++++++++++++++++++++++++++++++
238 The function that is called when the boundsType XSD type is seen
239
240 int boundsType_function Returns 0 if no error occured or something else otherwise.
241
242 const char *_tag_ Set to the name of the element tag that triggered this function call.
243
244 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
245 ++++++++++++++++++++++++++++++++++++++*/
246
247 //static int boundsType_function(const char *_tag_,int _type_)
248 //{
249 // return(0);
250 //}
251
252
253 /*++++++++++++++++++++++++++++++++++++++
254 The function that is called when the boundType XSD type is seen
255
256 int boundType_function Returns 0 if no error occured or something else otherwise.
257
258 const char *_tag_ Set to the name of the element tag that triggered this function call.
259
260 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
261 ++++++++++++++++++++++++++++++++++++++*/
262
263 //static int boundType_function(const char *_tag_,int _type_)
264 //{
265 // return(0);
266 //}
267
268
269 /*++++++++++++++++++++++++++++++++++++++
270 The function that is called when the tagType XSD type is seen
271
272 int tagType_function Returns 0 if no error occured or something else otherwise.
273
274 const char *_tag_ Set to the name of the element tag that triggered this function call.
275
276 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
277
278 const char *k The contents of the 'k' attribute (or NULL if not defined).
279
280 const char *v The contents of the 'v' attribute (or NULL if not defined).
281 ++++++++++++++++++++++++++++++++++++++*/
282
283 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v)
284 {
285 if(_type_&XMLPARSE_TAG_START && current_tags)
286 {
287 XMLPARSE_ASSERT_STRING(_tag_,k);
288 XMLPARSE_ASSERT_STRING(_tag_,v);
289
290 AppendTag(current_tags,k,v);
291 }
292
293 return(0);
294 }
295
296
297 /*++++++++++++++++++++++++++++++++++++++
298 The function that is called when the changesetType XSD type is seen
299
300 int changesetType_function Returns 0 if no error occured or something else otherwise.
301
302 const char *_tag_ Set to the name of the element tag that triggered this function call.
303
304 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
305 ++++++++++++++++++++++++++++++++++++++*/
306
307 static int changesetType_function(const char *_tag_,int _type_)
308 {
309 current_tags=NULL;
310
311 return(0);
312 }
313
314
315 /*++++++++++++++++++++++++++++++++++++++
316 The function that is called when the nodeType XSD type is seen
317
318 int nodeType_function Returns 0 if no error occured or something else otherwise.
319
320 const char *_tag_ Set to the name of the element tag that triggered this function call.
321
322 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
323
324 const char *id The contents of the 'id' attribute (or NULL if not defined).
325
326 const char *lat The contents of the 'lat' attribute (or NULL if not defined).
327
328 const char *lon The contents of the 'lon' attribute (or NULL if not defined).
329 ++++++++++++++++++++++++++++++++++++++*/
330
331 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon)
332 {
333 static node_t node_id;
334 static double latitude,longitude;
335
336 if(_type_&XMLPARSE_TAG_START)
337 {
338 long long llid;
339
340 nnodes++;
341
342 if(!(nnodes%10000))
343 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
344
345 current_tags=NewTagList();
346
347 /* Handle the node information */
348
349 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
350 node_id=(node_t)llid;
351 assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
352
353 if(mode!=MODE_DELETE)
354 {
355 XMLPARSE_ASSERT_FLOATING(_tag_,lat); latitude =atof(lat);
356 XMLPARSE_ASSERT_FLOATING(_tag_,lon); longitude=atof(lon);
357 }
358 }
359
360 if(_type_&XMLPARSE_TAG_END)
361 {
362 TagList *result=ApplyTaggingRules(&NodeRules,current_tags,node_id);
363
364 process_node_tags(result,node_id,latitude,longitude);
365
366 DeleteTagList(current_tags); current_tags=NULL;
367 DeleteTagList(result);
368 }
369
370 return(0);
371 }
372
373
374 /*++++++++++++++++++++++++++++++++++++++
375 The function that is called when the ndType XSD type is seen
376
377 int ndType_function Returns 0 if no error occured or something else otherwise.
378
379 const char *_tag_ Set to the name of the element tag that triggered this function call.
380
381 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
382
383 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
384 ++++++++++++++++++++++++++++++++++++++*/
385
386 static int ndType_function(const char *_tag_,int _type_,const char *ref)
387 {
388 if(_type_&XMLPARSE_TAG_START)
389 {
390 long long llid;
391 node_t node_id;
392
393 XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */
394 node_id=(node_t)llid;
395 assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
396
397 if(way_nnodes && (way_nnodes%256)==0)
398 way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t));
399
400 way_nodes[way_nnodes++]=node_id;
401 }
402
403 return(0);
404 }
405
406
407 /*++++++++++++++++++++++++++++++++++++++
408 The function that is called when the memberType XSD type is seen
409
410 int memberType_function Returns 0 if no error occured or something else otherwise.
411
412 const char *_tag_ Set to the name of the element tag that triggered this function call.
413
414 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
415
416 const char *type The contents of the 'type' attribute (or NULL if not defined).
417
418 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
419
420 const char *role The contents of the 'role' attribute (or NULL if not defined).
421 ++++++++++++++++++++++++++++++++++++++*/
422
423 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role)
424 {
425 if(_type_&XMLPARSE_TAG_START)
426 {
427 long long llid;
428
429 XMLPARSE_ASSERT_STRING(_tag_,type);
430 XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */
431
432 if(!strcmp(type,"node"))
433 {
434 node_t node_id;
435
436 node_id=(node_t)llid;
437 assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
438
439 if(relation_nnodes && (relation_nnodes%256)==0)
440 relation_nodes=(node_t*)realloc((void*)relation_nodes,(relation_nnodes+256)*sizeof(node_t));
441
442 relation_nodes[relation_nnodes++]=node_id;
443
444 if(role)
445 {
446 if(!strcmp(role,"via"))
447 relation_via=node_id;
448 }
449 }
450 else if(!strcmp(type,"way"))
451 {
452 way_t way_id;
453
454 way_id=(way_t)llid;
455 assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */
456
457 if(relation_nways && (relation_nways%256)==0)
458 relation_ways=(way_t*)realloc((void*)relation_ways,(relation_nways+256)*sizeof(way_t));
459
460 relation_ways[relation_nways++]=way_id;
461
462 if(role)
463 {
464 if(!strcmp(role,"from"))
465 relation_from=way_id;
466 if(!strcmp(role,"to"))
467 relation_to=way_id;
468 }
469 }
470 else if(!strcmp(type,"relation"))
471 {
472 relation_t relation_id;
473
474 relation_id=(relation_t)llid;
475 assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */
476
477 if(relation_nrelations && (relation_nrelations%256)==0)
478 relation_relations=(relation_t*)realloc((void*)relation_relations,(relation_nrelations+256)*sizeof(relation_t));
479
480 relation_relations[relation_nrelations++]=relation_id;
481 }
482 }
483
484 return(0);
485 }
486
487
488 /*++++++++++++++++++++++++++++++++++++++
489 The function that is called when the wayType XSD type is seen
490
491 int wayType_function Returns 0 if no error occured or something else otherwise.
492
493 const char *_tag_ Set to the name of the element tag that triggered this function call.
494
495 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
496
497 const char *id The contents of the 'id' attribute (or NULL if not defined).
498 ++++++++++++++++++++++++++++++++++++++*/
499
500 static int wayType_function(const char *_tag_,int _type_,const char *id)
501 {
502 static way_t way_id;
503
504 if(_type_&XMLPARSE_TAG_START)
505 {
506 long long llid;
507
508 nways++;
509
510 if(!(nways%1000))
511 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
512
513 current_tags=NewTagList();
514
515 way_nnodes=0;
516
517 /* Handle the way information */
518
519 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
520
521 way_id=(way_t)llid;
522 assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */
523 }
524
525 if(_type_&XMLPARSE_TAG_END)
526 {
527 TagList *result=ApplyTaggingRules(&WayRules,current_tags,way_id);
528
529 process_way_tags(result,way_id);
530
531 DeleteTagList(current_tags); current_tags=NULL;
532 DeleteTagList(result);
533 }
534
535 return(0);
536 }
537
538
539 /*++++++++++++++++++++++++++++++++++++++
540 The function that is called when the relationType XSD type is seen
541
542 int relationType_function Returns 0 if no error occured or something else otherwise.
543
544 const char *_tag_ Set to the name of the element tag that triggered this function call.
545
546 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
547
548 const char *id The contents of the 'id' attribute (or NULL if not defined).
549 ++++++++++++++++++++++++++++++++++++++*/
550
551 static int relationType_function(const char *_tag_,int _type_,const char *id)
552 {
553 static relation_t relation_id;
554
555 if(_type_&XMLPARSE_TAG_START)
556 {
557 long long llid;
558
559 nrelations++;
560
561 if(!(nrelations%1000))
562 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
563
564 current_tags=NewTagList();
565
566 relation_nnodes=relation_nways=relation_nrelations=0;
567
568 relation_from=NO_WAY_ID;
569 relation_to=NO_WAY_ID;
570 relation_via=NO_NODE_ID;
571
572 /* Handle the relation information */
573
574 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
575
576 relation_id=(relation_t)llid;
577 assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */
578 }
579
580 if(_type_&XMLPARSE_TAG_END)
581 {
582 TagList *result=ApplyTaggingRules(&RelationRules,current_tags,relation_id);
583
584 process_relation_tags(result,relation_id);
585
586 DeleteTagList(current_tags); current_tags=NULL;
587 DeleteTagList(result);
588 }
589
590 return(0);
591 }
592
593
594 /*++++++++++++++++++++++++++++++++++++++
595 The function that is called when the deleteType XSD type is seen
596
597 int deleteType_function Returns 0 if no error occured or something else otherwise.
598
599 const char *_tag_ Set to the name of the element tag that triggered this function call.
600
601 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
602 ++++++++++++++++++++++++++++++++++++++*/
603
604 static int deleteType_function(const char *_tag_,int _type_)
605 {
606 if(_type_&XMLPARSE_TAG_START)
607 mode=MODE_DELETE;
608
609 return(0);
610 }
611
612
613 /*++++++++++++++++++++++++++++++++++++++
614 The function that is called when the createType XSD type is seen
615
616 int createType_function Returns 0 if no error occured or something else otherwise.
617
618 const char *_tag_ Set to the name of the element tag that triggered this function call.
619
620 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
621 ++++++++++++++++++++++++++++++++++++++*/
622
623 static int createType_function(const char *_tag_,int _type_)
624 {
625 if(_type_&XMLPARSE_TAG_START)
626 mode=MODE_CREATE;
627
628 return(0);
629 }
630
631
632 /*++++++++++++++++++++++++++++++++++++++
633 The function that is called when the modifyType XSD type is seen
634
635 int modifyType_function Returns 0 if no error occured or something else otherwise.
636
637 const char *_tag_ Set to the name of the element tag that triggered this function call.
638
639 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
640 ++++++++++++++++++++++++++++++++++++++*/
641
642 static int modifyType_function(const char *_tag_,int _type_)
643 {
644 if(_type_&XMLPARSE_TAG_START)
645 mode=MODE_MODIFY;
646
647 return(0);
648 }
649
650
651 /*++++++++++++++++++++++++++++++++++++++
652 The function that is called when the osmChangeType XSD type is seen
653
654 int osmChangeType_function Returns 0 if no error occured or something else otherwise.
655
656 const char *_tag_ Set to the name of the element tag that triggered this function call.
657
658 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
659
660 const char *version The contents of the 'version' attribute (or NULL if not defined).
661 ++++++++++++++++++++++++++++++++++++++*/
662
663 static int osmChangeType_function(const char *_tag_,int _type_,const char *version)
664 {
665 if(_type_&XMLPARSE_TAG_START)
666 {
667 if(!version || strcmp(version,"0.6"))
668 XMLPARSE_MESSAGE(_tag_,"Invalid value for 'version' (only '0.6' accepted)");
669 }
670
671 return(0);
672 }
673
674
675 /*++++++++++++++++++++++++++++++++++++++
676 The function that is called when the osmType XSD type is seen
677
678 int osmType_function Returns 0 if no error occured or something else otherwise.
679
680 const char *_tag_ Set to the name of the element tag that triggered this function call.
681
682 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
683
684 const char *version The contents of the 'version' attribute (or NULL if not defined).
685 ++++++++++++++++++++++++++++++++++++++*/
686
687 static int osmType_function(const char *_tag_,int _type_,const char *version)
688 {
689 if(_type_&XMLPARSE_TAG_START)
690 {
691 mode=MODE_NORMAL;
692
693 if(!version || strcmp(version,"0.6"))
694 XMLPARSE_MESSAGE(_tag_,"Invalid value for 'version' (only '0.6' accepted)");
695 }
696
697 return(0);
698 }
699
700
701 /*++++++++++++++++++++++++++++++++++++++
702 The function that is called when the XML declaration is seen
703
704 int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
705
706 const char *_tag_ Set to the name of the element tag that triggered this function call.
707
708 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
709
710 const char *version The contents of the 'version' attribute (or NULL if not defined).
711
712 const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
713 ++++++++++++++++++++++++++++++++++++++*/
714
715 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
716 //{
717 // return(0);
718 //}
719
720
721 /*++++++++++++++++++++++++++++++++++++++
722 Parse an OSM XML file (from JOSM or planet download).
723
724 int ParseOSM Returns 0 if OK or something else in case of an error.
725
726 FILE *file The file to read from.
727
728 NodesX *OSMNodes The data structure of nodes to fill in.
729
730 SegmentsX *OSMSegments The data structure of segments to fill in.
731
732 WaysX *OSMWays The data structure of ways to fill in.
733
734 RelationsX *OSMRelations The data structure of relations to fill in.
735 ++++++++++++++++++++++++++++++++++++++*/
736
737 int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations)
738 {
739 int retval;
740
741 /* Copy the function parameters and initialise the variables. */
742
743 nodes=OSMNodes;
744 segments=OSMSegments;
745 ways=OSMWays;
746 relations=OSMRelations;
747
748 way_nodes=(node_t*)malloc(256*sizeof(node_t));
749
750 relation_nodes =(node_t *)malloc(256*sizeof(node_t));
751 relation_ways =(way_t *)malloc(256*sizeof(way_t));
752 relation_relations=(relation_t*)malloc(256*sizeof(relation_t));
753
754 /* Parse the file */
755
756 nnodes=0,nways=0,nrelations=0;
757
758 printf_first("Reading: Lines=0 Nodes=0 Ways=0 Relations=0");
759
760 retval=ParseXML(file,xml_osm_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE);
761
762 printf_last("Read: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
763
764 free(way_nodes);
765
766 free(relation_nodes);
767 free(relation_ways);
768 free(relation_relations);
769
770 return(retval);
771 }
772
773
774 /*++++++++++++++++++++++++++++++++++++++
775 Parse an OSC XML file (from planet download).
776
777 int ParseOSC Returns 0 if OK or something else in case of an error.
778
779 FILE *file The file to read from.
780
781 NodesX *OSMNodes The data structure of nodes to fill in.
782
783 SegmentsX *OSMSegments The data structure of segments to fill in.
784
785 WaysX *OSMWays The data structure of ways to fill in.
786
787 RelationsX *OSMRelations The data structure of relations to fill in.
788 ++++++++++++++++++++++++++++++++++++++*/
789
790 int ParseOSC(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations)
791 {
792 int retval;
793
794 /* Copy the function parameters and initialise the variables. */
795
796 nodes=OSMNodes;
797 segments=OSMSegments;
798 ways=OSMWays;
799 relations=OSMRelations;
800
801 way_nodes=(node_t*)malloc(256*sizeof(node_t));
802
803 relation_nodes =(node_t *)malloc(256*sizeof(node_t));
804 relation_ways =(way_t *)malloc(256*sizeof(way_t));
805 relation_relations=(relation_t*)malloc(256*sizeof(relation_t));
806
807 /* Parse the file */
808
809 nnodes=0,nways=0,nrelations=0;
810
811 printf_first("Reading: Lines=0 Nodes=0 Ways=0 Relations=0");
812
813 retval=ParseXML(file,xml_osc_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE);
814
815 printf_last("Read: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
816
817 free(way_nodes);
818
819 free(relation_nodes);
820 free(relation_ways);
821 free(relation_relations);
822
823 return(retval);
824 }
825
826
827 /*++++++++++++++++++++++++++++++++++++++
828 Process the tags associated with a node.
829
830 TagList *tags The list of node tags.
831
832 node_t id The id of the node.
833
834 double latitude The latitude of the node.
835
836 double longitude The longitude of the node.
837 ++++++++++++++++++++++++++++++++++++++*/
838
839 static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude)
840 {
841 transports_t allow=Transports_ALL;
842 uint16_t flags=0;
843 int i;
844
845 /* Delete */
846
847 if(mode==MODE_DELETE)
848 {
849 AppendNodeList(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,NODE_DELETED);
850
851 return;
852 }
853
854 /* Parse the tags */
855
856 for(i=0;i<tags->ntags;i++)
857 {
858 int recognised=0;
859 char *k=tags->k[i];
860 char *v=tags->v[i];
861
862 switch(*k)
863 {
864 case 'b':
865 if(!strcmp(k,"bicycle"))
866 {
867 if(ISFALSE(v))
868 allow&=~Transports_Bicycle;
869 else if(!ISTRUE(v))
870 logerror("Node %"Pnode_t" has an unrecognised tag value 'bicycle' = '%s' (after tagging rules); using 'yes'.\n",id,v);
871 recognised=1; break;
872 }
873
874 break;
875
876 case 'f':
877 if(!strcmp(k,"foot"))
878 {
879 if(ISFALSE(v))
880 allow&=~Transports_Foot;
881 else if(!ISTRUE(v))
882 logerror("Node %"Pnode_t" has an unrecognised tag value 'foot' = '%s' (after tagging rules); using 'yes'.\n",id,v);
883 recognised=1; break;
884 }
885
886 break;
887
888 case 'g':
889 if(!strcmp(k,"goods"))
890 {
891 if(ISFALSE(v))
892 allow&=~Transports_Goods;
893 else if(!ISTRUE(v))
894 logerror("Node %"Pnode_t" has an unrecognised tag value 'goods' = '%s' (after tagging rules); using 'yes'.\n",id,v);
895 recognised=1; break;
896 }
897
898 break;
899
900 case 'h':
901 if(!strcmp(k,"highway"))
902 if(!strcmp(v,"mini_roundabout"))
903 {
904 flags|=NODE_MINIRNDBT;
905 recognised=1; break;
906 }
907
908 if(!strcmp(k,"horse"))
909 {
910 if(ISFALSE(v))
911 allow&=~Transports_Horse;
912 else if(!ISTRUE(v))
913 logerror("Node %"Pnode_t" has an unrecognised tag value 'horse' = '%s' (after tagging rules); using 'yes'.\n",id,v);
914 recognised=1; break;
915 }
916
917 if(!strcmp(k,"hgv"))
918 {
919 if(ISFALSE(v))
920 allow&=~Transports_HGV;
921 else if(!ISTRUE(v))
922 logerror("Node %"Pnode_t" has an unrecognised tag value 'hgv' = '%s' (after tagging rules); using 'yes'.\n",id,v);
923 recognised=1; break;
924 }
925
926 break;
927
928 case 'm':
929 if(!strcmp(k,"moped"))
930 {
931 if(ISFALSE(v))
932 allow&=~Transports_Moped;
933 else if(!ISTRUE(v))
934 logerror("Node %"Pnode_t" has an unrecognised tag value 'moped' = '%s' (after tagging rules); using 'yes'.\n",id,v);
935 recognised=1; break;
936 }
937
938 if(!strcmp(k,"motorbike"))
939 {
940 if(ISFALSE(v))
941 allow&=~Transports_Motorbike;
942 else if(!ISTRUE(v))
943 logerror("Node %"Pnode_t" has an unrecognised tag value 'motorbike' = '%s' (after tagging rules); using 'yes'.\n",id,v);
944 recognised=1; break;
945 }
946
947 if(!strcmp(k,"motorcar"))
948 {
949 if(ISFALSE(v))
950 allow&=~Transports_Motorcar;
951 else if(!ISTRUE(v))
952 logerror("Node %"Pnode_t" has an unrecognised tag value 'motorcar' = '%s' (after tagging rules); using 'yes'.\n",id,v);
953 recognised=1; break;
954 }
955
956 break;
957
958 case 'p':
959 if(!strcmp(k,"psv"))
960 {
961 if(ISFALSE(v))
962 allow&=~Transports_PSV;
963 else if(!ISTRUE(v))
964 logerror("Node %"Pnode_t" has an unrecognised tag value 'psv' = '%s' (after tagging rules); using 'yes'.\n",id,v);
965 recognised=1; break;
966 }
967
968 break;
969
970 case 'w':
971 if(!strcmp(k,"wheelchair"))
972 {
973 if(ISFALSE(v))
974 allow&=~Transports_Wheelchair;
975 else if(!ISTRUE(v))
976 logerror("Node %"Pnode_t" has an unrecognised tag value 'wheelchair' = '%s' (after tagging rules); using 'yes'.\n",id,v);
977 recognised=1; break;
978 }
979
980 break;
981
982 default:
983 break;
984 }
985
986 if(!recognised)
987 logerror("Node %"Pnode_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
988 }
989
990 /* Create the node */
991
992 AppendNodeList(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,flags);
993 }
994
995
996 /*++++++++++++++++++++++++++++++++++++++
997 Process the tags associated with a way.
998
999 TagList *tags The list of way tags.
1000
1001 way_t id The id of the way.
1002 ++++++++++++++++++++++++++++++++++++++*/
1003
1004 static void process_way_tags(TagList *tags,way_t id)
1005 {
1006 Way way={0};
1007 segflags_t oneway=0,area=0;
1008 int roundabout=0;
1009 char *name=NULL,*ref=NULL,*refname=NULL;
1010 int i;
1011
1012 /* Delete */
1013
1014 if(mode==MODE_DELETE || mode==MODE_MODIFY)
1015 {
1016 way.type=WAY_DELETED;
1017
1018 AppendWayList(ways,id,&way,"");
1019
1020 way.type=0;
1021
1022 AppendSegmentList(segments,id,NO_NODE_ID,NO_NODE_ID,0,0);
1023 }
1024
1025 if(mode==MODE_DELETE)
1026 return;
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 AppendWayList(ways,id,&way,refname);
1362
1363 if(ref && name)
1364 free(refname);
1365
1366 for(i=1;i<way_nnodes;i++)
1367 {
1368 node_t from=way_nodes[i-1];
1369 node_t to =way_nodes[i];
1370
1371 AppendSegmentList(segments,id,from,to,0,area+oneway);
1372 }
1373 }
1374
1375
1376 /*++++++++++++++++++++++++++++++++++++++
1377 Process the tags associated with a relation.
1378
1379 TagList *tags The list of relation tags.
1380
1381 relation_t id The id of the relation.
1382 ++++++++++++++++++++++++++++++++++++++*/
1383
1384 static void process_relation_tags(TagList *tags,relation_t id)
1385 {
1386 transports_t routes=Transports_None;
1387 transports_t except=Transports_None;
1388 int relation_turn_restriction=0;
1389 TurnRestriction restriction=TurnRestrict_None;
1390 int i;
1391
1392 /* Delete */
1393
1394 if(mode==MODE_DELETE || mode==MODE_MODIFY)
1395 {
1396 AppendRouteRelationList(relations,id,RELATION_DELETED,
1397 relation_ways,relation_nways,
1398 relation_relations,relation_nrelations);
1399
1400 AppendTurnRelationList(relations,id,
1401 relation_from,relation_to,relation_via,
1402 restriction,RELATION_DELETED);
1403 }
1404
1405 if(mode==MODE_DELETE)
1406 return;
1407
1408 /* Sanity check */
1409
1410 if(relation_nnodes==0 && relation_nways==0 && relation_nrelations==0)
1411 {
1412 logerror("Relation %"Prelation_t" has no nodes, ways or relations.\n",id);
1413 return;
1414 }
1415
1416 /* Parse the tags */
1417
1418 for(i=0;i<tags->ntags;i++)
1419 {
1420 int recognised=0;
1421 char *k=tags->k[i];
1422 char *v=tags->v[i];
1423
1424 switch(*k)
1425 {
1426 case 'b':
1427 if(!strcmp(k,"bicycleroute"))
1428 {
1429 if(ISTRUE(v))
1430 routes|=Transports_Bicycle;
1431 else if(!ISFALSE(v))
1432 logerror("Relation %"Prelation_t" has an unrecognised tag value 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
1433 recognised=1; break;
1434 }
1435
1436 break;
1437
1438 case 'e':
1439 if(!strcmp(k,"except"))
1440 {
1441 for(i=1;i<Transport_Count;i++)
1442 if(strstr(v,TransportName(i)))
1443 except|=TRANSPORTS(i);
1444
1445 if(except==Transports_None)
1446 logerror("Relation %"Prelation_t" has an unrecognised tag value 'except' = '%s' (after tagging rules); ignoring it.\n",id,v);
1447
1448 recognised=1; break;
1449 }
1450
1451 break;
1452
1453 case 'f':
1454 if(!strcmp(k,"footroute"))
1455 {
1456 if(ISTRUE(v))
1457 routes|=Transports_Foot;
1458 else if(!ISFALSE(v))
1459 logerror("Relation %"Prelation_t" has an unrecognised tag value 'footroute' = '%s' (after tagging rules); using 'no'.\n",id,v);
1460 recognised=1; break;
1461 }
1462
1463 break;
1464
1465 case 'r':
1466 if(!strcmp(k,"restriction"))
1467 {
1468 if(!strcmp(v,"no_right_turn" )) restriction=TurnRestrict_no_right_turn;
1469 if(!strcmp(v,"no_left_turn" )) restriction=TurnRestrict_no_left_turn;
1470 if(!strcmp(v,"no_u_turn" )) restriction=TurnRestrict_no_u_turn;
1471 if(!strcmp(v,"no_straight_on" )) restriction=TurnRestrict_no_straight_on;
1472 if(!strcmp(v,"only_right_turn" )) restriction=TurnRestrict_only_right_turn;
1473 if(!strcmp(v,"only_left_turn" )) restriction=TurnRestrict_only_left_turn;
1474 if(!strcmp(v,"only_straight_on")) restriction=TurnRestrict_only_straight_on;
1475
1476 if(restriction==TurnRestrict_None)
1477 logerror("Relation %"Prelation_t" has an unrecognised tag value 'restriction' = '%s' (after tagging rules); ignoring it.\n",id,v);
1478
1479 recognised=1; break;
1480 }
1481
1482 break;
1483
1484 case 't':
1485 if(!strcmp(k,"type"))
1486 {
1487 if(!strcmp(v,"restriction"))
1488 relation_turn_restriction=1;
1489
1490 /* Don't log an error for relations of types that we don't handle - there are so many */
1491 recognised=1; break;
1492 }
1493
1494 break;
1495
1496 default:
1497 break;
1498 }
1499
1500 if(!recognised)
1501 logerror("Relation %"Prelation_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1502 }
1503
1504 /* Create the route relation (must store all relations that have ways or
1505 relations even if they are not routes because they might be referenced by
1506 other relations that are routes) */
1507
1508 if((relation_nways || relation_nrelations) && !relation_turn_restriction)
1509 AppendRouteRelationList(relations,id,routes,
1510 relation_ways,relation_nways,
1511 relation_relations,relation_nrelations);
1512
1513 /* Create the turn restriction relation. */
1514
1515 if(relation_turn_restriction && restriction!=TurnRestrict_None)
1516 {
1517 if(relation_from==NO_WAY_ID)
1518 logerror("Relation %"Prelation_t" is a turn restriction but has no 'from' way.\n",id);
1519 else if(relation_to==NO_WAY_ID)
1520 logerror("Relation %"Prelation_t" is a turn restriction but has no 'to' way.\n",id);
1521 else if(relation_via==NO_NODE_ID)
1522 logerror("Relation %"Prelation_t" is a turn restriction but has no 'via' node.\n",id);
1523 else
1524 AppendTurnRelationList(relations,id,
1525 relation_from,relation_to,relation_via,
1526 restriction,except);
1527 }
1528 }
1529
1530
1531 /*++++++++++++++++++++++++++++++++++++++
1532 Convert a string containing a speed into a double precision.
1533
1534 double parse_speed Returns the speed in km/h if it can be parsed.
1535
1536 way_t id The way being processed.
1537
1538 const char *k The tag key.
1539
1540 const char *v The tag value.
1541 ++++++++++++++++++++++++++++++++++++++*/
1542
1543 static double parse_speed(way_t id,const char *k,const char *v)
1544 {
1545 char *ev;
1546 double value=strtod(v,&ev);
1547
1548 if(v==ev)
1549 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1550 else
1551 {
1552 while(isspace(*ev)) ev++;
1553
1554 if(!strcmp(ev,"mph"))
1555 return(1.609*value);
1556
1557 if(*ev==0 || !strcmp(ev,"kph"))
1558 return(value);
1559
1560 logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1561 }
1562
1563 return(0);
1564 }
1565
1566
1567 /*++++++++++++++++++++++++++++++++++++++
1568 Convert a string containing a weight into a double precision.
1569
1570 double parse_weight Returns the weight in tonnes if it can be parsed.
1571
1572 way_t id The way being processed.
1573
1574 const char *k The tag key.
1575
1576 const char *v The tag value.
1577 ++++++++++++++++++++++++++++++++++++++*/
1578
1579 static double parse_weight(way_t id,const char *k,const char *v)
1580 {
1581 char *ev;
1582 double value=strtod(v,&ev);
1583
1584 if(v==ev)
1585 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1586 else
1587 {
1588 while(isspace(*ev)) ev++;
1589
1590 if(!strcmp(ev,"kg"))
1591 return(value/1000.0);
1592
1593 if(*ev==0 || !strcmp(ev,"T") || !strcmp(ev,"t")
1594 || !strcmp(ev,"ton") || !strcmp(ev,"tons")
1595 || !strcmp(ev,"tonne") || !strcmp(ev,"tonnes"))
1596 return(value);
1597
1598 logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1599 }
1600
1601 return(0);
1602 }
1603
1604
1605 /*++++++++++++++++++++++++++++++++++++++
1606 Convert a string containing a length into a double precision.
1607
1608 double parse_length Returns the length in metres if it can be parsed.
1609
1610 way_t id The way being processed.
1611
1612 const char *k The tag key.
1613
1614 const char *v The tag value.
1615 ++++++++++++++++++++++++++++++++++++++*/
1616
1617 static double parse_length(way_t id,const char *k,const char *v)
1618 {
1619 char *ev;
1620 double value=strtod(v,&ev);
1621
1622 if(v==ev)
1623 logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1624 else
1625 {
1626 int en=0;
1627 int feet=0,inches=0;
1628
1629 if(sscanf(v,"%d' %d\"%n",&feet,&inches,&en)==2 && en && !v[en])
1630 return((feet+(double)inches/12.0)*0.254);
1631
1632 if(sscanf(v,"%d'%d\"%n",&feet,&inches,&en)==2 && en && !v[en])
1633 return((feet+(double)inches/12.0)*0.254);
1634
1635 if(sscanf(v,"%d'-%d\"%n",&feet,&inches,&en)==2 && en && !v[en])
1636 return((feet+(double)inches/12.0)*0.254);
1637
1638 if(sscanf(v,"%d - %d%n",&feet,&inches,&en)==2 && en && !v[en])
1639 return((feet+(double)inches/12.0)*0.254);
1640
1641 if(sscanf(v,"%d ft %d in%n",&feet,&inches,&en)==2 && en && !v[en])
1642 return((feet+(double)inches/12.0)*0.254);
1643
1644 if(sscanf(v,"%d feet %d inches%n",&feet,&inches,&en)==2 && en && !v[en])
1645 return((feet+(double)inches/12.0)*0.254);
1646
1647 if(!strcmp(ev,"'"))
1648 return(feet*0.254);
1649
1650 while(isspace(*ev)) ev++;
1651
1652 if(!strcmp(ev,"ft") || !strcmp(ev,"feet"))
1653 return(value*0.254);
1654
1655 if(*ev==0 || !strcmp(ev,"m") || !strcmp(ev,"metre") || !strcmp(ev,"metres"))
1656 return(value);
1657
1658 logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after tagging rules); ignoring it.\n",id,k,v);
1659 }
1660
1661 return(0);
1662 }

Properties

Name Value
cvs:description OSM XML file parser.