Add:maptool:Experimental o5m support
authormartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Sun, 3 Jul 2011 11:17:23 +0000 (11:17 +0000)
committermartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Sun, 3 Jul 2011 11:17:23 +0000 (11:17 +0000)
git-svn-id: https://navit.svn.sourceforge.net/svnroot/navit/trunk@4572 ffa7fe5e-494d-0410-b361-a75ebd5db220

navit/navit/maptool/CMakeLists.txt
navit/navit/maptool/Makefile.am
navit/navit/maptool/maptool.c
navit/navit/maptool/maptool.h
navit/navit/maptool/osm_o5m.c [new file with mode: 0644]

index f9541f1..6bee654 100644 (file)
@@ -2,7 +2,7 @@
 if(BUILD_MAPTOOL)
    add_definitions( -DMODULE=maptool ${NAVIT_COMPILE_FLAGS})
    include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-   SET(MAPTOOL_SOURCE boundaries.c buffer.c ch.c coastline.c geom.c itembin.c itembin_buffer.c misc.c osm.c sourcesink.c tempfile.c tile.c zip.c osm_xml.c)
+   SET(MAPTOOL_SOURCE boundaries.c buffer.c ch.c coastline.c geom.c itembin.c itembin_buffer.c misc.c osm.c osm_o5m.c sourcesink.c tempfile.c tile.c zip.c osm_xml.c)
    if(NOT MSVC)
        SET(MAPTOOL_SOURCE ${MAPTOOL_SOURCE} osm_protobuf.c osm_protobufdb.c generated-code/fileformat.pb-c.c generated-code/osmformat.pb-c.c google/protobuf-c/protobuf-c.c)
    endif(NOT MSVC)
index fb11510..ca70bba 100644 (file)
@@ -5,6 +5,6 @@ if !SUPPORT_ANDROID
 endif
 
 AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/navit @ZLIB_CFLAGS@ @POSTGRESQL_CFLAGS@ -DMODULE=maptool
-libmaptool_la_SOURCES = boundaries.c buffer.c ch.c coastline.c geom.c itembin.c itembin_buffer.c misc.c osm.c osm_psql.c osm_protobuf.c osm_protobufdb.c osm_xml.c sourcesink.c tempfile.c tile.c zip.c maptool.h generated-code/fileformat.pb-c.c generated-code/fileformat.pb-c.h generated-code/osmformat.pb-c.c generated-code/osmformat.pb-c.h google/protobuf-c/protobuf-c.c google/protobuf-c/protobuf-c.h google/protobuf-c/protobuf-c-private.h
+libmaptool_la_SOURCES = boundaries.c buffer.c ch.c coastline.c geom.c itembin.c itembin_buffer.c misc.c osm.c osm_o5m.c osm_psql.c osm_protobuf.c osm_protobufdb.c osm_xml.c sourcesink.c tempfile.c tile.c zip.c maptool.h generated-code/fileformat.pb-c.c generated-code/fileformat.pb-c.h generated-code/osmformat.pb-c.c generated-code/osmformat.pb-c.h google/protobuf-c/protobuf-c.c google/protobuf-c/protobuf-c.h google/protobuf-c/protobuf-c-private.h
 maptool_SOURCES = maptool.c
 maptool_LDADD = libmaptool.la ../libnavit.la @NAVIT_LIBS@ @WORDEXP_LIBS@ @ZLIB_LIBS@ @POSTGRESQL_LIBS@ @CRYPTO_LIBS@ @INTLLIBS@ @LIBC_LIBS@
index 9a80664..6794c83 100644 (file)
@@ -122,6 +122,7 @@ usage(FILE *f)
        fprintf(f,"-e (--end)               : end at specified phase\n");
        fprintf(f,"-i (--input-file)        : specify the input file name (OSM), overrules default stdin\n");
        fprintf(f,"-k (--keep-tmpfiles)     : do not delete tmp files after processing. useful to reuse them\n\n");
+       fprintf(f,"-M (--o5m)               : input file os o5m\n");
        fprintf(f,"-N (--nodes-only)        : process only nodes\n");
        fprintf(f,"-o (--coverage)          : map every street to item coverage\n");
        fprintf(f,"-P (--protobuf)          : input file is protobuf\n");
@@ -157,6 +158,7 @@ int main(int argc, char **argv)
        int output=0;
        int input=0;
        int protobuf=0;
+       int o5m;
        int f,pos;
        char *result,*optarg_cp,*attr_name,*attr_value;
        char *protobufdb=NULL,*protobufdb_operation=NULL,*md5file=NULL;
@@ -213,6 +215,7 @@ int main(int argc, char **argv)
                        {"keep-tmpfiles", 0, 0, 'k'},
                        {"nodes-only", 0, 0, 'N'},
                        {"map", 1, 0, 'm'},
+                       {"o5m", 0, 0, 'M'},
                        {"plugin", 1, 0, 'p'},
                        {"protobuf", 0, 0, 'P'},
                        {"start", 1, 0, 's'},
@@ -225,7 +228,7 @@ int main(int argc, char **argv)
                        {"unknown-country", 0, 0, 'U'},
                        {0, 0, 0, 0}
                };
-               c = getopt_long (argc, argv, "5:6B:DNO:PWS:a:bc"
+               c = getopt_long (argc, argv, "5:6B:DMNO:PWS:a:bc"
 #ifdef HAVE_POSTGRESQL
                                              "d:"
 #endif
@@ -245,6 +248,9 @@ int main(int argc, char **argv)
                case 'D':
                        output=1;
                        break;
+               case 'M':
+                       o5m=1;
+                       break;  
                case 'N':
                        process_ways=0;
                        break;
@@ -402,6 +408,8 @@ int main(int argc, char **argv)
                }
                else if (protobuf)
                        map_collect_data_osm_protobuf(input_file,ways,nodes,turn_restrictions,boundaries);
+               else if (o5m)
+                       map_collect_data_osm_o5m(input_file,ways,nodes,turn_restrictions,boundaries);
                else
                        map_collect_data_osm(input_file,ways,nodes,turn_restrictions,boundaries);
                if (slices) {
index f048363..d5b3c0d 100644 (file)
@@ -248,6 +248,9 @@ void write_countrydir(struct zip_info *zip_info);
 void remove_countryfiles(void);
 void osm_init(FILE*);
 
+/* osm_o5m.c */
+int map_collect_data_osm_o5m(FILE *in, FILE *out_ways, FILE *out_nodes, FILE *out_turn_restrictions, FILE *out_boundaries);
+
 /* osm_psql.c */
 int map_collect_data_osm_db(char *dbstr, FILE *out_ways, FILE *out_nodes, FILE *out_turn_restrictions, FILE *out_boundaries);
 
diff --git a/navit/navit/maptool/osm_o5m.c b/navit/navit/maptool/osm_o5m.c
new file mode 100644 (file)
index 0000000..c90f509
--- /dev/null
@@ -0,0 +1,342 @@
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "maptool.h"
+
+static int print;
+
+static char *types[]={"node","way","relation"};
+
+struct o5m {
+       unsigned char buffer[65536];
+       int buffer_size;
+       unsigned char *buffer_start;
+       unsigned char *buffer_end;
+       FILE *in;
+       int error;
+
+       int lat, lon, uid, version;
+       long long id, rid[3], changeset;
+       time_t timestamp;
+       char *user;
+};
+
+static struct string_table {
+       char strings[15000][256];
+       int pos;
+} st;
+
+static double latlon_scale=10000000.0;
+
+#define buffer_end(o,x) ((o)->buffer_start+(x) > (o)->buffer_end && !fill_buffer((o), (x)))
+
+static int
+fill_buffer(struct o5m *o, int min)
+{
+       int count;
+
+       memmove(o->buffer, o->buffer_start, o->buffer_end-o->buffer_start);
+       o->buffer_end-=o->buffer_start-o->buffer;
+       o->buffer_start=o->buffer;
+       count=fread(o->buffer_end, 1, o->buffer+o->buffer_size-o->buffer_end, o->in);
+       if (!count)
+               return 0;
+       o->buffer_end+=count;
+       return (min <= o->buffer_end - o->buffer);
+}
+
+static unsigned long long
+get_uval(unsigned char **p)
+{
+       unsigned char c;
+       long long ret=0;
+       int shift=0;
+
+       for (;;) {
+               c=*((*p)++);
+               ret+=((long long)c & 0x7f) << shift;
+               if (!(c & 0x80)) 
+                       return ret;
+               shift+=7;
+       }
+}
+
+static unsigned long long
+get_sval(unsigned char **p)
+{
+       long long ret=get_uval(p);
+       if (ret & 1) {
+               return -((ret >> 1)+1);
+       } else {
+               return ret >> 1;
+       }
+}
+
+static void
+get_strings(struct string_table *st, unsigned char **p, char **s1, char **s2)
+{
+       int len,xlen=0;
+       *s1=(char *)*p;
+       len=strlen(*s1);
+       xlen=1;
+       if (s2) {
+               *s2=*s1+len+1;
+               len+=strlen(*s2);
+               xlen++;
+       }
+       (*p)+=len+xlen;
+       if (len <= 250) {
+               memcpy(st->strings[st->pos++], *s1, len+xlen);
+               if (st->pos >= 15000)
+                       st->pos=0;
+       }
+}
+
+static void
+get_strings_ref(struct string_table *st, int ref, char **s1, char **s2)
+{
+       int pos=st->pos-ref;
+       
+       if (pos < 0)
+               pos+=15000;
+       *s1=st->strings[pos];
+       if (s2) 
+               *s2=*s1+strlen(*s1)+1;
+}
+
+static void
+print_escaped(char *s)
+{
+       for (;;) {
+               switch (*s) {
+               case 0:
+                       return;
+               case 9:
+               case 13:
+               case 34:
+               case 38:
+               case 39:
+               case 60:
+               case 62:
+                       printf("&#%d;",*s);
+                       break;
+               default:
+                       putc(*s,stdout);
+                       break;
+               }
+               s++;
+       }
+}
+
+static void
+o5m_reset(struct o5m *o)
+{
+       o->lat=0;
+       o->lon=0;
+       o->id=0;
+       o->rid[0]=0;
+       o->rid[1]=0;
+       o->rid[2]=0;
+       o->changeset=0;
+       o->timestamp=0;
+}
+
+static void
+o5m_print_start(struct o5m *o, int c)
+{
+       printf("\t<%s id=\"%Ld\"",types[c-0x10],o->id);
+}
+
+static void
+o5m_print_version(struct o5m *o, int tags)
+{
+       char timestamp_str[64];
+       if (o->version) {
+               strftime(timestamp_str, sizeof(timestamp_str), "%Y-%m-%dT%H:%M:%SZ", gmtime(&o->timestamp));
+               printf(" version=\"%d\" timestamp=\"%s\" changeset=\"%Ld\"",o->version,timestamp_str,o->changeset);
+               if (o->uid) {
+                       printf(" uid=\"%d\" user=\"",o->uid);
+                       print_escaped(o->user);
+                       printf("\"");
+               }
+       }
+       printf("%s\n",tags?">":"/>");
+}
+
+static void
+o5m_print_end(char c)
+{      
+       printf("\t</%s>\n",types[c-0x10]);
+}
+
+int
+map_collect_data_osm_o5m(FILE *in, FILE *out_ways, FILE *out_nodes, FILE *out_turn_restrictions, FILE *out_boundaries)
+{
+       struct o5m o;
+       unsigned char c, *end, *rend;
+       int len, rlen, ref, tags;
+       char *uidstr, *role;
+
+       if (print) {
+               printf("<?xml version='1.0' encoding='UTF-8'?>\n");
+               printf("<osm version=\"0.6\" generator=\"osmconvert 0.1X6\">\n");
+       }
+
+
+       o5m_reset(&o);
+       o.buffer_size=sizeof(o.buffer);
+       o.buffer_start=o.buffer;
+       o.buffer_end=o.buffer;
+       o.error=0;
+       o.in=in;
+       
+       fill_buffer(&o,1);
+       for (;;) {
+               if (buffer_end(&o, 1)) {
+                       fprintf(stderr,"unexpected eof\n");
+                       return 1;
+               }
+               c=*(o.buffer_start++);
+               switch (c) {
+               case 0x10:
+               case 0x11:
+               case 0x12:
+                       (void)buffer_end(&o, 4);
+                       len=get_uval(&o.buffer_start);
+                       if (o.buffer_start > o.buffer_end) {
+                               fprintf(stderr,"unexpected eof\n");
+                               return 0;
+                       }
+                       if (buffer_end(&o, len)) {
+                               fprintf(stderr,"unexpected eof or buffer too small\n");
+                               return 0;
+                       }
+                       end=o.buffer_start+len;
+                       o.id+=get_sval(&o.buffer_start);
+                       o.version=get_uval(&o.buffer_start);
+                       if (o.version) {
+                               o.timestamp+=get_sval(&o.buffer_start);
+                               if (o.timestamp) {
+                                       o.changeset+=get_sval(&o.buffer_start);
+                                       ref=get_uval(&o.buffer_start);
+                                       if (ref) 
+                                               get_strings_ref(&st, ref, &uidstr, &o.user);
+                                       else
+                                               get_strings(&st, &o.buffer_start, &uidstr, &o.user);
+                                       o.uid=get_uval((unsigned char **)&uidstr);
+                               }
+                       }
+                       if (print)
+                               o5m_print_start(&o, c);
+                       switch (c) {
+                       case 0x10:
+                               o.lon+=get_sval(&o.buffer_start);
+                               o.lat+=get_sval(&o.buffer_start);
+                               osm_add_node(o.id, o.lat/latlon_scale,o.lon/latlon_scale);
+                               tags=end > o.buffer_start;
+                               if (print) {
+                                       printf(" lat=\"%.7f\" lon=\"%.7f\"",o.lat/10000000.0,o.lon/10000000.0);
+                                       o5m_print_version(&o, tags);
+                               }
+                               break;
+                       case 0x11:
+                               osm_add_way(o.id);
+                               rlen=get_uval(&o.buffer_start); 
+                               tags=end > o.buffer_start;
+                               rend=o.buffer_start+rlen;
+                               if (print)
+                                       o5m_print_version(&o, tags);
+                               while (o.buffer_start < rend) {
+                                       o.rid[0]+=get_sval(&o.buffer_start);
+                                       osm_add_nd(o.rid[0]);
+                                       if (print) 
+                                               printf("\t\t<nd ref=\"%Ld\"/>\n",o.rid[0]);
+                               }
+                               break;
+                       case 0x12:
+                               osm_add_relation(o.id);
+                               rlen=get_uval(&o.buffer_start); 
+                               tags=end > o.buffer_start;
+                               rend=o.buffer_start+rlen;
+                               if (print)
+                                       o5m_print_version(&o, tags);
+                               while (o.buffer_start < rend) {
+                                       long long delta=get_sval(&o.buffer_start);
+                                       int r;
+                                       ref=get_uval(&o.buffer_start);
+                                       if (ref) 
+                                               get_strings_ref(&st, ref, &role, NULL);
+                                       else
+                                               get_strings(&st, &o.buffer_start, &role, NULL);
+                                       r=role[0]-'0';
+                                       if (r < 0)
+                                               r=0;
+                                       if (r > 2)
+                                               r=2;
+                                       o.rid[r]+=delta;
+                                       osm_add_member(r+1, o.rid[r], role+1);
+                                       if (print)
+                                               printf("\t\t<member type=\"%s\" ref=\"%Ld\" role=\"%s\"/>\n",types[r], o.rid[r], role+1);
+                               }
+                               break;
+                       }
+                       while (end > o.buffer_start) {
+                               char *k, *v;
+                               ref=get_uval(&o.buffer_start);
+                               if (ref) 
+                                       get_strings_ref(&st, ref, &k, &v);
+                               else
+                                       get_strings(&st, &o.buffer_start, &k, &v);
+                               osm_add_tag(k, v);
+                               if (print) {
+                                       printf("\t\t<tag k=\"");
+                                       print_escaped(k);
+                                       printf("\" v=\"");
+                                       print_escaped(v);
+                                       printf("\"/>\n");
+                               }
+                       }
+                       if (print && tags) {
+                               o5m_print_end(c);
+                       }
+                       switch (c) {
+                       case 0x10:
+                               osm_end_node(out_nodes);
+                               break;
+                       case 0x11:
+                               osm_end_way(out_ways);
+                               break;
+                       case 0x12:
+                               osm_end_relation(out_turn_restrictions, out_boundaries);
+                               break;
+                       }
+                       break;
+               case 0xdb:
+                       if (print)
+                               printf("\t<bounds minlat=\"-180.0000000\" minlon=\"-90.0000000\" maxlat=\"180.0000000\" maxlon=\"90.0000000\"/>\n");
+                       len=get_uval(&o.buffer_start);
+                       if (o.buffer_start > o.buffer_end) {
+                               return 0;
+                       }
+                       if (buffer_end(&o, len)) {
+                               return 0;
+                       }
+                       o.buffer_start+=len;
+                       break;
+               case 0xe0:
+                       if (buffer_end(&o, 5))
+                               return 0;
+                       o.buffer_start+=5;
+                       break;
+               case 0xfe:
+                       return 1;
+               case 0xff:
+                       o5m_reset(&o);
+                       break;
+               default:
+                       fprintf(stderr,"Unknown tag 0x%x\n",c);
+                       return 0;
+               }
+       }
+       return 0;
+}