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 394 - (show annotations) (download) (as text)
Tue May 18 18:38:32 2010 UTC (14 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 20442 byte(s)
Almost completely re-written OSM parser using tagging transformations.

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/osmparser.c,v 1.65 2010-05-18 18:38:15 amb Exp $
3
4 OSM XML file parser (either JOSM or planet)
5
6 Part of the Routino routing software.
7 ******************/ /******************
8 This file Copyright 2008-2010 Andrew M. Bishop
9
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU Affero General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Affero General Public License for more details.
19
20 You should have received a copy of the GNU Affero General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 ***************************************/
23
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <ctype.h>
29
30 #include "typesx.h"
31 #include "functionsx.h"
32 #include "nodesx.h"
33 #include "segmentsx.h"
34 #include "waysx.h"
35 #include "xmlparse.h"
36 #include "tagging.h"
37
38
39 /* Macros */
40
41 #define ISTRUE(xx) (!strcmp(xx,"true") || !strcmp(xx,"yes") || !strcmp(xx,"1"))
42
43
44 /* Local variables */
45
46 static long nnodes=0,nways=0,nrelations=0;
47 static TagList current_tags={0,NULL,NULL};
48
49 static node_t *way_nodes=NULL;
50 static int way_nnodes=0;
51
52 static NodesX *nodes;
53 static SegmentsX *segments;
54 static WaysX *ways;
55 static Profile *profile;
56
57
58 /* Local functions */
59
60 static void process_way_tags(TagList *tags,way_t id);
61
62
63 /* The XML tag processing function prototypes */
64
65 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding);
66 //static int osmType_function(const char *_tag_,int _type_);
67 static int relationType_function(const char *_tag_,int _type_,const char *id);
68 static int wayType_function(const char *_tag_,int _type_,const char *id);
69 //static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role);
70 static int ndType_function(const char *_tag_,int _type_,const char *ref);
71 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon);
72 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v);
73 //static int boundsType_function(const char *_tag_,int _type_);
74
75
76 /* The XML tag definitions */
77
78 /*+ The boundsType type tag. +*/
79 static xmltag boundsType_tag=
80 {"bounds",
81 0, {NULL},
82 NULL,
83 {NULL}};
84
85 /*+ The tagType type tag. +*/
86 static xmltag tagType_tag=
87 {"tag",
88 2, {"k","v"},
89 tagType_function,
90 {NULL}};
91
92 /*+ The nodeType type tag. +*/
93 static xmltag nodeType_tag=
94 {"node",
95 3, {"id","lat","lon"},
96 nodeType_function,
97 {&tagType_tag,NULL}};
98
99 /*+ The ndType type tag. +*/
100 static xmltag ndType_tag=
101 {"nd",
102 1, {"ref"},
103 ndType_function,
104 {NULL}};
105
106 /*+ The memberType type tag. +*/
107 static xmltag memberType_tag=
108 {"member",
109 3, {"type","ref","role"},
110 NULL,
111 {NULL}};
112
113 /*+ The wayType type tag. +*/
114 static xmltag wayType_tag=
115 {"way",
116 1, {"id"},
117 wayType_function,
118 {&ndType_tag,&tagType_tag,NULL}};
119
120 /*+ The relationType type tag. +*/
121 static xmltag relationType_tag=
122 {"relation",
123 1, {"id"},
124 relationType_function,
125 {&memberType_tag,&tagType_tag,NULL}};
126
127 /*+ The osmType type tag. +*/
128 static xmltag osmType_tag=
129 {"osm",
130 0, {NULL},
131 NULL,
132 {&boundsType_tag,&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
133
134 /*+ The xmlDeclaration type tag. +*/
135 static xmltag xmlDeclaration_tag=
136 {"xml",
137 2, {"version","encoding"},
138 NULL,
139 {NULL}};
140
141
142 /*+ The complete set of tags at the top level. +*/
143 static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&osmType_tag,NULL};
144
145
146 /* The XML tag processing functions */
147
148
149 /*++++++++++++++++++++++++++++++++++++++
150 The function that is called when the boundsType XSD type is seen
151
152 int boundsType_function Returns 0 if no error occured or something else otherwise.
153
154 const char *_tag_ Set to the name of the element tag that triggered this function call.
155
156 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
157 ++++++++++++++++++++++++++++++++++++++*/
158
159 //static int boundsType_function(const char *_tag_,int _type_)
160 //{
161 // return(0);
162 //}
163
164
165 /*++++++++++++++++++++++++++++++++++++++
166 The function that is called when the tagType XSD type is seen
167
168 int tagType_function Returns 0 if no error occured or something else otherwise.
169
170 const char *_tag_ Set to the name of the element tag that triggered this function call.
171
172 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
173
174 const char *k The contents of the 'k' attribute (or NULL if not defined).
175
176 const char *v The contents of the 'v' attribute (or NULL if not defined).
177 ++++++++++++++++++++++++++++++++++++++*/
178
179 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v)
180 {
181 if(_type_&XMLPARSE_TAG_START)
182 {
183 XMLPARSE_ASSERT_STRING(_tag_,k);
184 XMLPARSE_ASSERT_STRING(_tag_,v);
185
186 AppendTag(&current_tags,k,v);
187 }
188
189 return(0);
190 }
191
192
193 /*++++++++++++++++++++++++++++++++++++++
194 The function that is called when the nodeType XSD type is seen
195
196 int nodeType_function Returns 0 if no error occured or something else otherwise.
197
198 const char *_tag_ Set to the name of the element tag that triggered this function call.
199
200 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
201
202 const char *id The contents of the 'id' attribute (or NULL if not defined).
203
204 const char *lat The contents of the 'lat' attribute (or NULL if not defined).
205
206 const char *lon The contents of the 'lon' attribute (or NULL if not defined).
207 ++++++++++++++++++++++++++++++++++++++*/
208
209 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon)
210 {
211 if(_type_&XMLPARSE_TAG_START)
212 {
213 node_t node_id;
214 double latitude,longitude;
215
216 nnodes++;
217
218 if(!(nnodes%1000))
219 {
220 printf("\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
221 fflush(stdout);
222 }
223
224 /* Handle the node information */
225
226 XMLPARSE_ASSERT_STRING(_tag_,id); node_id=atoll(id); /* need long long conversion */
227 XMLPARSE_ASSERT_FLOATING(_tag_,lat,latitude);
228 XMLPARSE_ASSERT_FLOATING(_tag_,lon,longitude);
229
230 AppendNode(nodes,node_id,degrees_to_radians(latitude),degrees_to_radians(longitude));
231
232 current_tags.ntags=0;
233 }
234
235 // if(_type_&XMLPARSE_TAG_END)
236 // {
237 // TagList *result=ApplyTaggingRules(&NodeRules,&current_tags);
238 //
239 // DeleteTagList(result);
240 // }
241
242 return(0);
243 }
244
245
246 /*++++++++++++++++++++++++++++++++++++++
247 The function that is called when the ndType XSD type is seen
248
249 int ndType_function Returns 0 if no error occured or something else otherwise.
250
251 const char *_tag_ Set to the name of the element tag that triggered this function call.
252
253 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
254
255 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
256 ++++++++++++++++++++++++++++++++++++++*/
257
258 static int ndType_function(const char *_tag_,int _type_,const char *ref)
259 {
260 if(_type_&XMLPARSE_TAG_START)
261 {
262 node_t node_id;
263
264 XMLPARSE_ASSERT_STRING(_tag_,ref); node_id=atoll(ref); /* need long long conversion */
265
266 if((way_nnodes%256)==0)
267 way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t));
268
269 way_nodes[way_nnodes++]=node_id;
270 }
271
272 return(0);
273 }
274
275
276 /*++++++++++++++++++++++++++++++++++++++
277 The function that is called when the memberType XSD type is seen
278
279 int memberType_function Returns 0 if no error occured or something else otherwise.
280
281 const char *_tag_ Set to the name of the element tag that triggered this function call.
282
283 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
284
285 const char *type The contents of the 'type' attribute (or NULL if not defined).
286
287 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
288
289 const char *role The contents of the 'role' attribute (or NULL if not defined).
290 ++++++++++++++++++++++++++++++++++++++*/
291
292 //static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role)
293 //{
294 // return(0);
295 //}
296
297
298 /*++++++++++++++++++++++++++++++++++++++
299 The function that is called when the wayType XSD type is seen
300
301 int wayType_function Returns 0 if no error occured or something else otherwise.
302
303 const char *_tag_ Set to the name of the element tag that triggered this function call.
304
305 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
306
307 const char *id The contents of the 'id' attribute (or NULL if not defined).
308 ++++++++++++++++++++++++++++++++++++++*/
309
310 static int wayType_function(const char *_tag_,int _type_,const char *id)
311 {
312 static way_t way_id;
313
314 if(_type_&XMLPARSE_TAG_START)
315 {
316 nways++;
317
318 if(!(nways%1000))
319 {
320 printf("\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
321 fflush(stdout);
322 }
323
324 current_tags.ntags=0;
325 way_nnodes=0;
326
327 /* Handle the way information */
328
329 XMLPARSE_ASSERT_STRING(_tag_,id); way_id=atoll(id); /* need long long conversion */
330 }
331
332 if(_type_&XMLPARSE_TAG_END)
333 {
334 TagList *result=ApplyTaggingRules(&WayRules,&current_tags);
335
336 process_way_tags(result,way_id);
337
338 DeleteTagList(result);
339 }
340
341 return(0);
342 }
343
344
345 /*++++++++++++++++++++++++++++++++++++++
346 The function that is called when the relationType XSD type is seen
347
348 int relationType_function Returns 0 if no error occured or something else otherwise.
349
350 const char *_tag_ Set to the name of the element tag that triggered this function call.
351
352 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
353
354 const char *id The contents of the 'id' attribute (or NULL if not defined).
355 ++++++++++++++++++++++++++++++++++++++*/
356
357 static int relationType_function(const char *_tag_,int _type_,const char *id)
358 {
359 if(_type_&XMLPARSE_TAG_START)
360 {
361 nrelations++;
362
363 if(!(nrelations%1000))
364 {
365 printf("\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
366 fflush(stdout);
367 }
368
369 current_tags.ntags=0;
370 }
371
372 if(_type_&XMLPARSE_TAG_END)
373 {
374 TagList *result=ApplyTaggingRules(&RelationRules,&current_tags);
375
376 DeleteTagList(result);
377 }
378
379 return(0);
380 }
381
382
383 /*++++++++++++++++++++++++++++++++++++++
384 The function that is called when the osmType XSD type is seen
385
386 int osmType_function Returns 0 if no error occured or something else otherwise.
387
388 const char *_tag_ Set to the name of the element tag that triggered this function call.
389
390 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
391 ++++++++++++++++++++++++++++++++++++++*/
392
393 //static int osmType_function(const char *_tag_,int _type_)
394 //{
395 // return(0);
396 //}
397
398
399 /*++++++++++++++++++++++++++++++++++++++
400 The function that is called when the XML declaration is seen
401
402 int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
403
404 const char *_tag_ Set to the name of the element tag that triggered this function call.
405
406 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
407
408 const char *version The contents of the 'version' attribute (or NULL if not defined).
409
410 const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
411 ++++++++++++++++++++++++++++++++++++++*/
412
413 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
414 //{
415 // return(0);
416 //}
417
418
419 /*++++++++++++++++++++++++++++++++++++++
420 Parse an OSM XML file (from JOSM or planet download).
421
422 int ParseOSM Returns 0 if OK or something else in case of an error.
423
424 FILE *file The file to read from.
425
426 NodesX *OSMNodes The array of nodes to fill in.
427
428 SegmentsX *OSMSegments The array of segments to fill in.
429
430 WaysX *OSMWays The arrray of ways to fill in.
431
432 Profile *allowprofile A profile of the allowed transport types and included/excluded highway types.
433 ++++++++++++++++++++++++++++++++++++++*/
434
435 int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,Profile *allowprofile)
436 {
437 int retval;
438
439 /* Parse the file */
440
441 nodes=OSMNodes;
442 segments=OSMSegments;
443 ways=OSMWays;
444 profile=allowprofile;
445
446 nnodes=0,nways=0,nrelations=0;
447
448 printf("\rReading: Lines=0 Nodes=0 Ways=0 Relations=0");
449 fflush(stdout);
450
451 retval=ParseXML(file,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE);
452
453 printf("\rRead: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld \n",ParseXML_LineNumber(),nnodes,nways,nrelations);
454 fflush(stdout);
455
456 return(retval);
457 }
458
459
460 /*++++++++++++++++++++++++++++++++++++++
461 Process the tags associated with a way.
462
463 TagList *tags The list of way tags.
464
465 way_t id The id of the way.
466 ++++++++++++++++++++++++++++++++++++++*/
467
468 static void process_way_tags(TagList *tags,way_t id)
469 {
470 Way way={0};
471 int oneway=0,roundabout=0;
472 char *highway=NULL,*name=NULL,*ref=NULL;
473
474 int i;
475
476 /* Parse the tags */
477
478 for(i=0;i<tags->ntags;i++)
479 {
480 char *k=tags->k[i];
481 char *v=tags->v[i];
482
483 switch(*k)
484 {
485 case 'b':
486 if(!strcmp(k,"bicycle"))
487 if(ISTRUE(v))
488 way.allow|= Allow_Bicycle;
489
490 if(!strcmp(k,"bridge"))
491 if(ISTRUE(v))
492 way.props|=Properties_Bridge;
493
494 break;
495
496 case 'f':
497 if(!strcmp(k,"foot"))
498 if(ISTRUE(v))
499 way.allow|= Allow_Foot;
500
501 break;
502
503 case 'g':
504 if(!strcmp(k,"goods"))
505 if(ISTRUE(v))
506 way.allow|=Allow_Goods;
507
508 break;
509
510 case 'h':
511 if(!strcmp(k,"highway"))
512 {
513 highway=v;
514 way.type=HighwayType(v);
515 }
516
517 if(!strcmp(k,"horse"))
518 if(ISTRUE(v))
519 way.allow|=Allow_Horse;
520
521 if(!strcmp(k,"hgv"))
522 if(ISTRUE(v))
523 way.allow|=Allow_HGV;
524
525 break;
526
527 case 'j':
528 if(!strcmp(k,"junction") && !strcmp(v,"roundabout"))
529 roundabout=1;
530
531 break;
532
533 case 'm':
534 if(!strcmp(k,"maxspeed"))
535 {
536 if(strstr(v,"mph"))
537 way.speed=kph_to_speed(1.609*atof(v));
538 else
539 way.speed=kph_to_speed(atof(v));
540 }
541
542 if(!strcmp(k,"maxweight"))
543 {
544 if(strstr(v,"kg"))
545 way.weight=tonnes_to_weight(atof(v)/1000);
546 else
547 way.weight=tonnes_to_weight(atof(v));
548 }
549
550 if(!strcmp(k,"maxheight"))
551 {
552 if(strchr(v,'\''))
553 {
554 int feet,inches;
555
556 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
557 way.height=metres_to_height((feet+(double)inches/12.0)*0.254);
558 else if(sscanf(v,"%d'",&feet)==1)
559 way.height=metres_to_height((feet+(double)inches/12.0)*0.254);
560 }
561 else if(strstr(v,"ft") || strstr(v,"feet"))
562 way.height=metres_to_height(atof(v)*0.254);
563 else
564 way.height=metres_to_height(atof(v));
565 }
566
567 if(!strcmp(k,"maxwidth"))
568 {
569 if(strchr(v,'\''))
570 {
571 int feet,inches;
572
573 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
574 way.width=metres_to_height((feet+(double)inches/12.0)*0.254);
575 else if(sscanf(v,"%d'",&feet)==1)
576 way.width=metres_to_height((feet+(double)inches/12.0)*0.254);
577 }
578 else if(strstr(v,"ft") || strstr(v,"feet"))
579 way.width=metres_to_width(atof(v)*0.254);
580 else
581 way.width=metres_to_width(atof(v));
582 }
583
584 if(!strcmp(k,"maxlength"))
585 {
586 if(strchr(v,'\''))
587 {
588 int feet,inches;
589
590 if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
591 way.length=metres_to_height((feet+(double)inches/12.0)*0.254);
592 else if(sscanf(v,"%d'",&feet)==1)
593 way.length=metres_to_height((feet+(double)inches/12.0)*0.254);
594 }
595 else if(strstr(v,"ft") || strstr(v,"feet"))
596 way.length=metres_to_length(atof(v)*0.254);
597 else
598 way.length=metres_to_length(atof(v));
599 }
600
601 if(!strcmp(k,"moped"))
602 if(ISTRUE(v))
603 way.allow|=Allow_Moped;
604
605 if(!strcmp(k,"motorbike"))
606 if(ISTRUE(v))
607 way.allow|=Allow_Motorbike;
608
609 if(!strcmp(k,"motorcar"))
610 if(ISTRUE(v))
611 way.allow|=Allow_Motorcar;
612
613 if(!strcmp(k,"multilane"))
614 if(ISTRUE(v))
615 way.props|=Properties_Multilane;
616
617 break;
618
619 case 'n':
620 if(!strcmp(k,"name"))
621 name=v;
622
623 break;
624
625 case 'o':
626 if(!strcmp(k,"oneway"))
627 {
628 if(ISTRUE(v))
629 oneway=1;
630 else if(!strcmp(v,"-1"))
631 oneway=-1;
632 }
633
634 break;
635
636 case 'p':
637 if(!strcmp(k,"paved"))
638 if(ISTRUE(v))
639 way.props|=Properties_Paved;
640
641 if(!strcmp(k,"psv"))
642 if(ISTRUE(v))
643 way.allow|=Allow_PSV;
644
645 break;
646
647 case 'r':
648 if(!strcmp(k,"ref"))
649 ref=v;
650
651 break;
652
653 case 't':
654 if(!strcmp(k,"tunnel"))
655 if(ISTRUE(v))
656 way.props|=Properties_Tunnel;
657
658 break;
659
660 case 'w':
661 if(!strcmp(k,"wheelchair"))
662 if(ISTRUE(v))
663 way.allow|=Allow_Wheelchair;
664
665 break;
666
667 default:
668 ;
669 }
670 }
671
672 /* Create the way */
673
674 if(way.type>0 && way.type<Way_Count && profile->highway[way.type])
675 {
676 if(way.allow & profile->allow)
677 {
678 char *refname;
679
680 if(oneway)
681 way.type|=Way_OneWay;
682
683 if(roundabout)
684 way.type|=Way_Roundabout;
685
686 if(!profile->props_yes[Property_Paved])
687 way.props&=~Properties_Paved;
688
689 if(!profile->props_yes[Property_Multilane])
690 way.props&=~Properties_Multilane;
691
692 if(!profile->props_yes[Property_Bridge])
693 way.props&=~Properties_Bridge;
694
695 if(!profile->props_yes[Property_Tunnel])
696 way.props&=~Properties_Tunnel;
697
698 if(ref && name)
699 {
700 refname=(char*)malloc(strlen(ref)+strlen(name)+4);
701 sprintf(refname,"%s (%s)",name,ref);
702 }
703 else if(ref && !name && roundabout)
704 {
705 refname=(char*)malloc(strlen(ref)+14);
706 sprintf(refname,"%s (roundabout)",ref);
707 }
708 else if(ref && !name)
709 refname=ref;
710 else if(!ref && name)
711 refname=name;
712 else if(roundabout)
713 {
714 refname=(char*)malloc(strlen(highway)+14);
715 sprintf(refname,"%s (roundabout)",highway);
716 }
717 else /* if(!ref && !name && !roundabout) */
718 refname=highway;
719
720 AppendWay(ways,id,&way,refname);
721
722 if(refname!=ref && refname!=name && refname!=highway)
723 free(refname);
724
725 for(i=1;i<way_nnodes;i++)
726 {
727 node_t from=way_nodes[i-1];
728 node_t to =way_nodes[i];
729
730 if(oneway>0)
731 {
732 AppendSegment(segments,id,from,to,ONEWAY_1TO2);
733 AppendSegment(segments,id,to,from,ONEWAY_2TO1);
734 }
735 else if(oneway<0)
736 {
737 AppendSegment(segments,id,from,to,ONEWAY_2TO1);
738 AppendSegment(segments,id,to,from,ONEWAY_1TO2);
739 }
740 else
741 {
742 AppendSegment(segments,id,from,to,0);
743 AppendSegment(segments,id,to,from,0);
744 }
745 }
746 }
747 }
748 }

Properties

Name Value
cvs:description OSM XML file parser.