Imported Upstream version 1.5
[routino] / src / osmparser.c
index 3af039d..f8b47a9 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/osmparser.c,v 1.69 2010/05/29 13:54:23 amb Exp $
+ $Header: /home/amb/routino/src/RCS/osmparser.c,v 1.72 2010/09/25 18:47:32 amb Exp $
 
  OSM XML file parser (either JOSM or planet)
 
 
 #include "typesx.h"
 #include "functionsx.h"
+
 #include "nodesx.h"
 #include "segmentsx.h"
 #include "waysx.h"
+#include "relationsx.h"
+
 #include "xmlparse.h"
 #include "tagging.h"
 
@@ -49,14 +52,24 @@ static TagList *current_tags=NULL;
 static node_t *way_nodes=NULL;
 static int     way_nnodes=0;
 
-static NodesX    *nodes;
-static SegmentsX *segments;
-static WaysX     *ways;
+static node_t     *relation_nodes=NULL;
+static int         relation_nnodes=0;
+static way_t      *relation_ways=NULL;
+static int         relation_nways=0;
+static relation_t *relation_relations=NULL;
+static int         relation_nrelations=0;
+
+static NodesX     *nodes;
+static SegmentsX  *segments;
+static WaysX      *ways;
+static RelationsX *relations;
 
 
 /* Local functions */
 
+static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude);
 static void process_way_tags(TagList *tags,way_t id);
+static void process_relation_tags(TagList *tags,relation_t id);
 
 
 /* The XML tag processing function prototypes */
@@ -65,7 +78,7 @@ static void process_way_tags(TagList *tags,way_t id);
 //static int osmType_function(const char *_tag_,int _type_);
 static int relationType_function(const char *_tag_,int _type_,const char *id);
 static int wayType_function(const char *_tag_,int _type_,const char *id);
-//static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role);
+static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role);
 static int ndType_function(const char *_tag_,int _type_,const char *ref);
 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon);
 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v);
@@ -114,7 +127,7 @@ static xmltag ndType_tag=
 static xmltag memberType_tag=
               {"member",
                3, {"type","ref","role"},
-               NULL,
+               memberType_function,
                {NULL}};
 
 /*+ The wayType type tag. +*/
@@ -231,11 +244,11 @@ static int tagType_function(const char *_tag_,int _type_,const char *k,const cha
 
 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon)
 {
+ static node_t node_id;
+ static double latitude,longitude;
+
  if(_type_&XMLPARSE_TAG_START)
    {
-    node_t node_id;
-    double latitude,longitude;
-
     nnodes++;
 
     if(!(nnodes%1000))
@@ -244,25 +257,24 @@ static int nodeType_function(const char *_tag_,int _type_,const char *id,const c
        fflush(stdout);
       }
 
+    current_tags=NewTagList();
+
     /* Handle the node information */
 
     XMLPARSE_ASSERT_STRING(_tag_,id); node_id=atoll(id); /* need long long conversion */
     XMLPARSE_ASSERT_FLOATING(_tag_,lat,latitude);
     XMLPARSE_ASSERT_FLOATING(_tag_,lon,longitude);
+   }
 
-    AppendNode(nodes,node_id,degrees_to_radians(latitude),degrees_to_radians(longitude));
+ if(_type_&XMLPARSE_TAG_END)
+   {
+    TagList *result=ApplyTaggingRules(&NodeRules,current_tags);
 
-//    current_tags=NewTagList();
-    current_tags=NULL;
-   }
+    process_node_tags(result,node_id,latitude,longitude);
 
-// if(_type_&XMLPARSE_TAG_END)
-//   {
-//    TagList *result=ApplyTaggingRules(&NodeRules,current_tags);
-//
-//    DeleteTagList(current_tags);
-//    DeleteTagList(result);
-//   }
+    DeleteTagList(current_tags);
+    DeleteTagList(result);
+   }
 
  return(0);
 }
@@ -288,7 +300,7 @@ static int ndType_function(const char *_tag_,int _type_,const char *ref)
 
     XMLPARSE_ASSERT_STRING(_tag_,ref); node_id=atoll(ref); /* need long long conversion */
 
-    if((way_nnodes%256)==0)
+    if(way_nnodes && (way_nnodes%256)==0)
        way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t));
 
     way_nodes[way_nnodes++]=node_id;
@@ -314,10 +326,44 @@ static int ndType_function(const char *_tag_,int _type_,const char *ref)
   const char *role The contents of the 'role' attribute (or NULL if not defined).
   ++++++++++++++++++++++++++++++++++++++*/
 
-//static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role)
-//{
-// return(0);
-//}
+static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role)
+{
+ if(_type_&XMLPARSE_TAG_START)
+   {
+    XMLPARSE_ASSERT_STRING(_tag_,type);
+    XMLPARSE_ASSERT_STRING(_tag_,ref);
+
+    if(!strcmp(type,"node"))
+      {
+       node_t node_id=atoll(ref); /* need long long conversion */
+
+       if(relation_nnodes && (relation_nnodes%256)==0)
+          relation_nodes=(node_t*)realloc((void*)relation_nodes,(relation_nnodes+256)*sizeof(node_t));
+
+       relation_nodes[relation_nnodes++]=node_id;
+      }
+    else if(!strcmp(type,"way"))
+      {
+       way_t way_id=atoll(ref); /* need long long conversion */
+
+       if(relation_nways && (relation_nways%256)==0)
+          relation_ways=(way_t*)realloc((void*)relation_ways,(relation_nways+256)*sizeof(way_t));
+
+       relation_ways[relation_nways++]=way_id;
+      }
+    else if(!strcmp(type,"relation"))
+      {
+       relation_t relation_id=atoll(ref); /* need long long conversion */
+
+       if(relation_nrelations && (relation_nrelations%256)==0)
+          relation_relations=(relation_t*)realloc((void*)relation_relations,(relation_nrelations+256)*sizeof(relation_t));
+
+       relation_relations[relation_nrelations++]=relation_id;
+      }
+   }
+
+ return(0);
+}
 
 
 /*++++++++++++++++++++++++++++++++++++++
@@ -347,6 +393,7 @@ static int wayType_function(const char *_tag_,int _type_,const char *id)
       }
 
     current_tags=NewTagList();
+
     way_nnodes=0;
 
     /* Handle the way information */
@@ -382,6 +429,8 @@ static int wayType_function(const char *_tag_,int _type_,const char *id)
 
 static int relationType_function(const char *_tag_,int _type_,const char *id)
 {
+ static relation_t relation_id;
+
  if(_type_&XMLPARSE_TAG_START)
    {
     nrelations++;
@@ -392,17 +441,24 @@ static int relationType_function(const char *_tag_,int _type_,const char *id)
        fflush(stdout);
       }
 
-//    current_tags=NewTagList();
-    current_tags=NULL;
+    current_tags=NewTagList();
+
+    relation_nnodes=relation_nways=relation_nrelations=0;
+
+    /* Handle the relation information */
+
+    XMLPARSE_ASSERT_STRING(_tag_,id); relation_id=atoll(id); /* need long long conversion */
    }
 
-// if(_type_&XMLPARSE_TAG_END)
-//   {
-//    TagList *result=ApplyTaggingRules(&RelationRules,current_tags);
-//
-//    DeleteTagList(current_tags);
-//    DeleteTagList(result);
-//   }
+ if(_type_&XMLPARSE_TAG_END)
+   {
+    TagList *result=ApplyTaggingRules(&RelationRules,current_tags);
+
+    process_relation_tags(result,relation_id);
+
+    DeleteTagList(current_tags);
+    DeleteTagList(result);
+   }
 
  return(0);
 }
@@ -451,22 +507,33 @@ static int relationType_function(const char *_tag_,int _type_,const char *id)
 
   FILE *file The file to read from.
 
-  NodesX *OSMNodes The array of nodes to fill in.
+  NodesX *OSMNodes The data structure of nodes to fill in.
+
+  SegmentsX *OSMSegments The data structure of segments to fill in.
 
-  SegmentsX *OSMSegments The array of segments to fill in.
+  WaysX *OSMWays The data structure of ways to fill in.
 
-  WaysX *OSMWays The arrray of ways to fill in.
+  RelationsX *OSMRelations The data structure of relations to fill in.
   ++++++++++++++++++++++++++++++++++++++*/
 
-int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays)
+int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations)
 {
  int retval;
 
- /* Parse the file */
+ /* Copy the function parameters and initialise the variables. */
 
  nodes=OSMNodes;
  segments=OSMSegments;
  ways=OSMWays;
+ relations=OSMRelations;
+
+ way_nodes=(node_t*)malloc(256*sizeof(node_t));
+
+ relation_nodes    =(node_t    *)malloc(256*sizeof(node_t));
+ relation_ways     =(way_t     *)malloc(256*sizeof(way_t));
+ relation_relations=(relation_t*)malloc(256*sizeof(relation_t));
+
+ /* Parse the file */
 
  nnodes=0,nways=0,nrelations=0;
 
@@ -483,6 +550,105 @@ int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays)
 
 
 /*++++++++++++++++++++++++++++++++++++++
+  Process the tags associated with a node.
+
+  TagList *tags The list of node tags.
+
+  node_t id The id of the node.
+
+  double latitude The latitude of the node.
+
+  double longitude The longitude of the node.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude)
+{
+ allow_t allow=Allow_ALL;
+
+ int i;
+
+ /* Parse the tags */
+
+ for(i=0;i<tags->ntags;i++)
+   {
+    char *k=tags->k[i];
+    char *v=tags->v[i];
+
+    switch(*k)
+      {
+      case 'b':
+       if(!strcmp(k,"bicycle"))
+          if(!ISTRUE(v))
+             allow&=~Allow_Bicycle;
+
+       break;
+
+      case 'f':
+       if(!strcmp(k,"foot"))
+          if(!ISTRUE(v))
+             allow&=~Allow_Foot;
+
+       break;
+
+      case 'g':
+       if(!strcmp(k,"goods"))
+          if(!ISTRUE(v))
+             allow&=~Allow_Goods;
+
+       break;
+
+      case 'h':
+       if(!strcmp(k,"horse"))
+          if(!ISTRUE(v))
+             allow&=~Allow_Horse;
+
+       if(!strcmp(k,"hgv"))
+          if(!ISTRUE(v))
+             allow&=~Allow_HGV;
+
+       break;
+
+      case 'm':
+       if(!strcmp(k,"moped"))
+          if(!ISTRUE(v))
+             allow&=~Allow_Moped;
+
+       if(!strcmp(k,"motorbike"))
+          if(!ISTRUE(v))
+             allow&=~Allow_Motorbike;
+
+       if(!strcmp(k,"motorcar"))
+          if(!ISTRUE(v))
+             allow&=~Allow_Motorcar;
+
+       break;
+
+      case 'p':
+       if(!strcmp(k,"psv"))
+          if(!ISTRUE(v))
+             allow&=~Allow_PSV;
+
+       break;
+
+      case 'w':
+       if(!strcmp(k,"wheelchair"))
+          if(!ISTRUE(v))
+             allow&=~Allow_Wheelchair;
+
+       break;
+
+      default:
+       ;
+      }
+   }
+
+ /* Create the node */
+
+ AppendNode(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
   Process the tags associated with a way.
 
   TagList *tags The list of way tags.
@@ -512,6 +678,10 @@ static void process_way_tags(TagList *tags,way_t id)
           if(ISTRUE(v))
              way.allow|= Allow_Bicycle;
 
+       if(!strcmp(k,"bicycleroute"))
+          if(ISTRUE(v))
+             way.props|=Properties_BicycleRoute;
+
        if(!strcmp(k,"bridge"))
           if(ISTRUE(v))
              way.props|=Properties_Bridge;
@@ -523,6 +693,10 @@ static void process_way_tags(TagList *tags,way_t id)
           if(ISTRUE(v))
              way.allow|= Allow_Foot;
 
+       if(!strcmp(k,"footroute"))
+          if(ISTRUE(v))
+             way.props|=Properties_FootRoute;
+
        break;
 
       case 'g':
@@ -746,3 +920,55 @@ static void process_way_tags(TagList *tags,way_t id)
       }
    }
 }
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Process the tags associated with a relation.
+
+  TagList *tags The list of relation tags.
+
+  relation_t id The id of the relation.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+static void process_relation_tags(TagList *tags,relation_t id)
+{
+ allow_t routes=Allow_None;
+ int i;
+
+ /* Parse the tags */
+
+ for(i=0;i<tags->ntags;i++)
+   {
+    char *k=tags->k[i];
+    char *v=tags->v[i];
+
+    switch(*k)
+      {
+      case 'b':
+       if(!strcmp(k,"bicycleroute"))
+          if(ISTRUE(v))
+             routes|=Allow_Bicycle;
+
+       break;
+
+      case 'f':
+       if(!strcmp(k,"footroute"))
+          if(ISTRUE(v))
+             routes|=Allow_Foot;
+
+       break;
+
+      default:
+       ;
+      }
+   }
+
+ /* Create the route relation (must store all relations that have ways or
+    relations even if they are not routes because they might be referenced by
+    other relations that are routes) */
+
+ if(relation_nways || relation_nrelations)
+    AppendRouteRelation(relations,id,routes,
+                        relation_ways,relation_nways,
+                        relation_relations,relation_nrelations);
+}