Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /branches/2.4.1-dev/src/osmparser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1215 - (show annotations) (download) (as text)
Mon Dec 17 10:56:11 2012 UTC (12 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 49133 byte(s)
Merge the remaining trunk changes into the 2.4.1 dev branch.

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

Properties

Name Value
cvs:description OSM XML file parser.