From: martin-s Date: Thu, 1 Nov 2007 15:21:39 +0000 (+0000) Subject: new program osm2navit capable of processing planet.osm, improvements to binfile driver X-Git-Tag: navit-0.5.0.5194svn~4645 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bf0c6bb262c10bb4f21f276bc72a84ebce679d9e;p=profile%2Fivi%2Fnavit.git new program osm2navit capable of processing planet.osm, improvements to binfile driver git-svn-id: https://navit.svn.sourceforge.net/svnroot/navit/trunk@504 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- diff --git a/navit/src/Makefile.am b/navit/src/Makefile.am index 1736a98..93fc07d 100644 --- a/navit/src/Makefile.am +++ b/navit/src/Makefile.am @@ -22,7 +22,7 @@ navit_SOURCES = attr.c callback.c compass.c coord.c country.c cursor.c data_wind param.h phrase.h plugin.h point.h plugin_def.h projection.h popup.h route.h profile.h search.h speech.h statusbar.h \ transform.h track.h util.h vehicle.h xmlconfig.h -osm2navit_SOURCES = osm2navit.c item.c debug.c +osm2navit_SOURCES = osm2navit.c item.c debug.c zipfile.h navit_LDADD = @NAVIT_LIBS@ @GPSD_LIBS@ -Lfib-1.1 -lfib diff --git a/navit/src/attr_def.h b/navit/src/attr_def.h index beb90ea..966e48f 100644 --- a/navit/src/attr_def.h +++ b/navit/src/attr_def.h @@ -22,6 +22,7 @@ ATTR(x) ATTR(y) ATTR(flush_size) ATTR(flush_time) +ATTR(zipfile_ref) /* boolean */ ATTR(overwrite) ATTR2(0x0002ffff,type_int_end) @@ -59,3 +60,4 @@ ATTR(navigation_long) ATTR(navigation_long_exact) ATTR(navigation_speech) ATTR2(0x0003ffff,type_string_end) +ATTR(order_limit) diff --git a/navit/src/data/binfile/binfile.c b/navit/src/data/binfile/binfile.c index 3387832..653bceb 100644 --- a/navit/src/data/binfile/binfile.c +++ b/navit/src/data/binfile/binfile.c @@ -13,28 +13,41 @@ #include "coord.h" #include "transform.h" #include "file.h" +#include "zipfile.h" static int map_id; -struct map_priv { - int id; - char *filename; - struct file *f; -}; - -struct map_rect_priv { +struct tile { int *start; + int *end; int *pos; int *pos_coord_start; int *pos_coord; int *pos_attr_start; int *pos_attr; int *pos_next; + int zipfile_num; +}; + +struct map_priv { + int id; + char *filename; + struct file *fi; + struct zip_cd *index_cd; + int cde_size; + struct zip_eoc *eoc; +}; + +struct map_rect_priv { + int *start; int *end; enum attr_type attr_last; struct map_selection *sel; struct map_priv *m; struct item item; + int tile_depth; + struct tile tiles[8]; + struct tile *t; }; @@ -49,21 +62,23 @@ static void binfile_coord_rewind(void *priv_data) { struct map_rect_priv *mr=priv_data; - mr->pos_coord=mr->pos_coord_start; + struct tile *t=mr->t; + t->pos_coord=t->pos_coord_start; } static int binfile_coord_get(void *priv_data, struct coord *c, int count) { struct map_rect_priv *mr=priv_data; + struct tile *t=mr->t; int ret=0; dbg(1,"binfile_coord_get %d\n",count); while (count--) { - dbg(1,"%p vs %p\n", mr->pos_coord, mr->pos_attr_start); - if (mr->pos_coord >= mr->pos_attr_start) + dbg(1,"%p vs %p\n", t->pos_coord, t->pos_attr_start); + if (t->pos_coord >= t->pos_attr_start) break; - c->x=*(mr->pos_coord++); - c->y=*(mr->pos_coord++); + c->x=*(t->pos_coord++); + c->y=*(t->pos_coord++); c++; ret++; } @@ -74,7 +89,8 @@ static void binfile_attr_rewind(void *priv_data) { struct map_rect_priv *mr=priv_data; - mr->pos_attr=mr->pos_attr_start; + struct tile *t=mr->t; + t->pos_attr=t->pos_attr_start; } @@ -82,26 +98,27 @@ static int binfile_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) { struct map_rect_priv *mr=priv_data; + struct tile *t=mr->t; enum attr_type type; int size; if (attr_type != mr->attr_last) { - mr->pos_attr=mr->pos_attr_start; + t->pos_attr=t->pos_attr_start; mr->attr_last=attr_type; } - while (mr->pos_attr < mr->pos_next) { - size=*(mr->pos_attr++); - type=mr->pos_attr[0]; + while (t->pos_attr < t->pos_next) { + size=*(t->pos_attr++); + type=t->pos_attr[0]; if (type == attr_type || attr_type == attr_any) { if (attr_type == attr_any) { - dbg(0,"pos %p attr %s size %d\n", mr->pos_attr-1, attr_to_name(type), size); + dbg(0,"pos %p attr %s size %d\n", t->pos_attr-1, attr_to_name(type), size); } attr->type=type; - attr_data_set(attr, mr->pos_attr+1); - mr->pos_attr+=size; + attr_data_set(attr, t->pos_attr+1); + t->pos_attr+=size; return 1; } else { - mr->pos_attr+=size; + t->pos_attr+=size; } } return 0; @@ -114,6 +131,49 @@ static struct item_methods methods_binfile = { binfile_attr_get, }; +static void +push_tile(struct map_rect_priv *mr, struct tile *t) +{ + mr->t=&mr->tiles[mr->tile_depth++]; + *(mr->t)=*t; + mr->t->pos=mr->t->pos_next=mr->t->start; +} + +static int +pop_tile(struct map_rect_priv *mr) +{ + if (mr->tile_depth <= 1) + return 0; + mr->t=&mr->tiles[--mr->tile_depth-1]; + return 1; +} + + +static void +zipfile_to_tile(struct file *f, struct zip_cd *cd, struct tile *t) +{ + char buffer[1024]; + struct zip_lfh *lfh; + lfh=(struct zip_lfh *)(f->begin+cd->zipofst); + strncpy(buffer, lfh->zipname, lfh->zipfnln); + buffer[lfh->zipfnln]='\0'; + dbg(0,"0x%x '%s' %d\n", lfh->ziplocsig, buffer, sizeof(*cd)+cd->zipcfnl); + t->start=(int *)(f->begin+cd->zipofst+sizeof(struct zip_lfh)+lfh->zipfnln); + t->end=t->start+lfh->zipuncmp/4; +} + +static void +push_zipfile_tile(struct map_rect_priv *mr, int zipfile) +{ + struct map_priv *m=mr->m; + struct file *f=m->fi; + struct tile t; + struct zip_cd *cd=(struct zip_cd *)(f->begin + m->eoc->zipeofst + zipfile*m->cde_size); + t.zipfile_num=zipfile; + zipfile_to_tile(f, cd, &t); + push_tile(mr, &t); +} + static struct map_rect_priv * map_rect_new_binfile(struct map_priv *map, struct map_selection *sel) { @@ -123,10 +183,9 @@ map_rect_new_binfile(struct map_priv *map, struct map_selection *sel) mr=g_new0(struct map_rect_priv, 1); mr->m=map; mr->sel=sel; - mr->start=mr->pos=mr->pos_next=map->f->begin; - mr->end=map->f->end; mr->item.id_hi=0; mr->item.id_lo=0; + push_zipfile_tile(mr, map->eoc->zipecenn-1); mr->item.meth=&methods_binfile; mr->item.priv_data=mr; return mr; @@ -143,12 +202,33 @@ static void setup_pos(struct map_rect_priv *mr) { int size,coord_size; - size=*(mr->pos++); - mr->pos_next=mr->pos+size; - mr->item.type=*(mr->pos++); - coord_size=*(mr->pos++); - mr->pos_coord_start=mr->pos_coord=mr->pos; - mr->pos_attr_start=mr->pos_attr=mr->pos_coord+coord_size; + struct tile *t=mr->t; + size=*(t->pos++); + if (size > 1024*1024 || size < 0) { + fprintf(stderr,"size=0x%x\n", size); +#if 0 + fprintf(stderr,"offset=%d\n", (unsigned char *)(mr->pos)-mr->m->f->begin); +#endif + g_error("size error"); + } + t->pos_next=t->pos+size; + mr->item.type=*(t->pos++); + coord_size=*(t->pos++); + t->pos_coord_start=t->pos_coord=t->pos; + t->pos_attr_start=t->pos_attr=t->pos_coord+coord_size; +} + +static int +selection_contains(struct map_selection *sel, struct coord_rect *r) +{ + if (! sel) + return 1; + while (sel) { + if (coord_rect_overlap(r, &sel->rect)) + return 1; + sel=sel->next; + } + return 0; } @@ -156,19 +236,43 @@ setup_pos(struct map_rect_priv *mr) static struct item * map_rect_get_item_binfile(struct map_rect_priv *mr) { - mr->pos=mr->pos_next; - if (mr->pos >= mr->end) - return NULL; - mr->item.id_hi=0; - mr->item.id_lo=mr->pos-mr->start; - setup_pos(mr); - return &mr->item; + struct tile *t; + for (;;) { + t=mr->t; + t->pos=t->pos_next; + if (t->pos >= t->end) { + if (pop_tile(mr)) + continue; + return NULL; + } + mr->item.id_hi=t->zipfile_num; + mr->item.id_lo=t->pos-t->start; + setup_pos(mr); + if (mr->item.type == type_submap) { + struct coord_rect r; + r.lu.x=t->pos_coord[0]; + r.lu.y=t->pos_coord[3]; + r.rl.x=t->pos_coord[2]; + r.rl.y=t->pos_coord[1]; + if (!selection_contains(mr->sel, &r)) { + continue; + } + dbg(1,"0x%x\n", t->pos_attr[5]); + push_zipfile_tile(mr, t->pos_attr[5]); + continue; + + } + return &mr->item; + } } static struct item * map_rect_get_item_byid_binfile(struct map_rect_priv *mr, int id_hi, int id_lo) { - mr->pos=mr->start+id_lo; + struct tile *t; + push_zipfile_tile(mr, id_hi); + t=mr->t; + t->pos=t->start+id_lo; mr->item.id_hi=id_hi; mr->item.id_lo=id_lo; setup_pos(mr); @@ -192,6 +296,7 @@ map_new_binfile(struct map_methods *meth, struct attr **attrs) struct attr *data=attr_search(attrs, NULL, attr_data); struct file_wordexp *wexp; char **wexp_data; + int *magic,cde_index_size; if (! data) return NULL; @@ -204,8 +309,21 @@ map_new_binfile(struct map_methods *meth, struct attr **attrs) m->id=++map_id; m->filename=g_strdup(wexp_data[0]); dbg(0,"file_create %s\n", m->filename); - m->f=file_create(m->filename); + m->fi=file_create(m->filename); file_wordexp_destroy(wexp); + magic=(int *)(m->fi->begin); + if (*magic == 0x04034b50) { + cde_index_size=sizeof(struct zip_cd)+sizeof("index")-1; + m->eoc=(struct zip_eoc *)(m->fi->end-sizeof(struct zip_eoc)); + m->index_cd=(struct zip_cd *)((char *)m->eoc-cde_index_size); + printf("length %d\n", m->eoc->zipecsz); + printf("entries %d\n", m->eoc->zipecenn); + m->cde_size=(m->eoc->zipecsz-cde_index_size)/(m->eoc->zipecenn-1); + printf("cde_size %d\n", m->cde_size); + printf("length %d\n",m->cde_size*(m->eoc->zipecenn-1)+cde_index_size); + printf("0x%x\n", m->eoc->zipesig); + printf("0x%x\n", m->index_cd->zipcensig); + } return m; } diff --git a/navit/src/item_def.h b/navit/src/item_def.h index 8d4f30a..2480e4d 100644 --- a/navit/src/item_def.h +++ b/navit/src/item_def.h @@ -260,3 +260,5 @@ ITEM(military_zone) ITEM(marine_poly) ITEM(plantation) ITEM(tundra) +ITEM(tile) +ITEM(submap) diff --git a/navit/src/osm2navit.c b/navit/src/osm2navit.c new file mode 100644 index 0000000..da3710a --- /dev/null +++ b/navit/src/osm2navit.c @@ -0,0 +1,983 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "item.h" +#include "zipfile.h" + + +static char *attrmap={ + "amenity\n" + "building\n" + "highway cycleway street_nopass\n" + "highway footway street_nopass\n" + "highway steps street_nopass\n" + "highway cyclepath street_nopass\n" + "highway track street_nopass\n" + "highway service street_nopass\n" + "highway pedestrian street_nopass\n" + "highway residential street_1_city\n" + "highway unclassified street_1_city\n" + "highway tertiary street_2_city\n" + "highway secondary street_3_city\n" + "highway primary street_4_city\n" + "highway trunk street_4_city\n" + "highway trunk_link ramp\n" + "highway motorway highway_city\n" + "highway motorway_link ramp\n" + "landuse allotments wood\n" + "landuse cemetery cemetery_poly\n" + "landuse forest wood\n" + "leisure park park_poly\n" + "natural wood wood\n" + "natural water water_poly\n" + "place suburb town_poly\n" + "railway rail rail\n" + "railway subway rail\n" + "railway tram rail\n" + "waterway canal water_line\n" + "waterway river water_line\n" + "waterway weir water_line\n" + "waterway stream water_line\n" + "waterway drain water_line\n" +}; + +GHashTable *key_hash; + +static void +build_attrmap_line(char *line) +{ + char *k=NULL,*v=NULL,*i=NULL,*p; + gpointer *data; + GHashTable *value_hash; + k=line; + p=index(k,'\t'); + if (p) { + while (*p == '\t') + *p++='\0'; + v=p; + p=index(v,'\t'); + } + if (p) { + while (*p == '\t') + *p++='\0'; + i=p; + } + if (! i) + i="street_unkn"; + if (! key_hash) + key_hash=g_hash_table_new(g_str_hash, g_str_equal); + value_hash=g_hash_table_lookup(key_hash, k); + if (! value_hash) { + value_hash=g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(key_hash, g_strdup(k), value_hash); + } + if (v) { + data=(gpointer)item_from_name(i); + g_hash_table_insert(value_hash, g_strdup(v), data); + } +#if 0 + fprintf(stderr,"'%s' '%s' '%s'\n", k, v, i); +#endif +} + +static void +build_attrmap(char *map) +{ + char *p; + while (map) { + p=index(map,'\n'); + if (p) + *p++='\0'; + if (strlen(map)) + build_attrmap_line(map); + map=p; + } +} + +static int processed_nodes, processed_ways, processed_relations, processed_tiles; +static int in_way, in_node, in_relation; + +static void +sig_alrm(int sig) +{ + signal(SIGALRM, sig_alrm); + alarm(30); + fprintf(stderr,"PROGRESS: Processed %d nodes %d ways %d relations %d tiles\n", processed_nodes, processed_ways, processed_relations, processed_tiles); +} + +struct item_bin { + int len; + enum item_type type; + int clen; +} item; + +struct attr_bin { + int len; + enum attr_type type; +}; + +struct attr_bin label_attr = { + 0, attr_label +}; +char label_attr_buffer[1024]; + +struct attr_bin debug_attr = { + 0, attr_debug +}; +char debug_attr_buffer[1024]; + +static void +pad_text_attr(struct attr_bin *a, char *buffer) +{ + int l; + l=strlen(buffer); + while (l % 4) + buffer[l++]='\0'; + a->len=l/4+1; +} +static int parse_tag(char *p) +{ + char *q, *k, *v; + GHashTable *value_hash; + q=index(p, '"'); + if (! q) + return 0; + k=q+1; + q=index(k, '"'); + if (! q) + return 0; + *q++='\0'; + q=index(q, '"'); + if (! q) + return 0; + v=q+1; + q=index(v, '"'); + if (! q) + return 0; + *q++='\0'; + if (! strcmp(k,"name")) { + strcpy(label_attr_buffer, v); + pad_text_attr(&label_attr, label_attr_buffer); + return 1; + } + value_hash=g_hash_table_lookup(key_hash, k); + if (! value_hash) + return 1; + item.type=(enum item_type) g_hash_table_lookup(value_hash, v); + if (! item.type) { + item.type=type_street_unkn; + g_hash_table_insert(value_hash, v, (gpointer)item.type); + } + return 1; +} + +struct buffer { + int malloced_step; + int malloced; + unsigned char *base; + int size; +}; + +struct tile_head { + int size; + int total_size; + char *name; + struct tile_head *next; + char data[0]; +}; + + +struct coord { + int x; + int y; +} coord_buffer[65536]; + +struct rect { + struct coord l,h; +}; + +int coord_count; + +struct node_item { + int id; + char ref_node; + char ref_way; + char ref_ref; + char dummy; + struct coord c; +}; + +struct buffer node_buffer = { + 64*1024*1024, +}; + +struct buffer zipdir_buffer = { + 1024*1024, +}; + +static void +extend_buffer(struct buffer *b) +{ + b->malloced+=b->malloced_step; + b->base=realloc(b->base, b->malloced); + +} + +static int parse_node(char *p) +{ + int c; + double lat, lon; + struct node_item *ni; + + if (node_buffer.size + sizeof(struct node_item) > node_buffer.malloced) + extend_buffer(&node_buffer); + ni=(struct node_item *)(node_buffer.base+node_buffer.size); + c=sscanf(p, "id,&lat,&lon); + if (c != 3) + return 0; + ni->ref_node=0; + ni->ref_way=0; + ni->ref_ref=0; + ni->dummy=0; + ni->c.x=lon*6371000.0*M_PI/180; + ni->c.y=log(tan(M_PI_4+lat*M_PI/360))*6371000.0; + node_buffer.size+=sizeof(struct node_item); + return 1; +} + +static struct node_item * +node_item_get(int id) +{ + struct node_item *ni=(struct node_item *)(node_buffer.base); + int count=node_buffer.size/sizeof(struct node_item); + int interval=count/4; + int p=count/2; + while (ni[p].id != id) { +#if 0 + fprintf(stderr,"p=%d count=%d interval=%d id=%d ni[p].id=%d\n", p, count, interval, id, ni[p].id); +#endif + if (ni[p].id < id) { + p+=interval; + if (interval == 1) { + if (p >= count) + return NULL; + if (ni[p].id > id) + return NULL; + } else { + if (p >= count) + p=count-1; + } + } else { + p-=interval; + if (interval == 1) { + if (p < 0) + return NULL; + if (ni[p].id < id) + return NULL; + } else { + if (p < 0) + p=0; + } + } + if (interval > 1) + interval/=2; + } + + return &ni[p]; +} + +static void +node_ref_way(int id) +{ + struct node_item *ni=node_item_get(id); + if (! ni) { + fprintf(stderr,"WARNING: node id %d not found\n", id); + return; + } + ni->ref_way++; +} + +int wayid; + +static int +parse_way(char *p) +{ + int c; + item.type=type_street_unkn; + label_attr.len=0; + debug_attr.len=0; + c=sscanf(p, "len) { + fwrite(attr, sizeof(*attr), 1, out); + fwrite(buffer, (attr->len-1)*4, 1, out); + } +} + +static void +end_way(FILE *out) +{ + int alen=0; + pad_text_attr(&debug_attr, debug_attr_buffer); + if (label_attr.len) + alen+=label_attr.len+1; + if (debug_attr.len) + alen+=debug_attr.len+1; + item.clen=coord_count*2; + item.len=item.clen+2+alen; + fwrite(&item, sizeof(item), 1, out); + fwrite(coord_buffer, coord_count*sizeof(struct coord), 1, out); + write_attr(out, &label_attr, label_attr_buffer); + write_attr(out, &debug_attr, debug_attr_buffer); +} + +static int +parse_nd(char *p) +{ + int c,ndref,len; + struct node_item *ni; + c=sscanf(p, "c; + else { + len=strlen(p); + if (len > 0 && p[len-1]=='\n') + p[len-1]='\0'; + fprintf(stderr,"WARNING: way %d: node %d not found (%s)\n",wayid,ndref,p); + } + if (coord_count > 65536) { + fprintf(stderr,"ERROR: Overflow\n"); + exit(1); + } + return 1; +} + + +static int +phase1(FILE *in, FILE *out) +{ + int size=4096; + char buffer[size]; + char *p; + sig_alrm(0); + while (fgets(buffer, size, in)) { + p=index(buffer,'<'); + if (! p) { + fprintf(stderr,"WARNING: wrong line %s\n", buffer); + continue; + } + if (!strncmp(p, "",7)) { + in_node=0; + } else if (!strncmp(p, "",6)) { + in_way=0; + end_way(out); + } else if (!strncmp(p, "",11)) { + in_relation=0; + } else if (!strncmp(p, "",6)) { + } else { + fprintf(stderr,"WARNING: unknown tag in %s\n", buffer); + } + } + sig_alrm(0); + alarm(0); + return 1; +} + +static char buffer[65536]; + +int bytes_read=0; + +static struct item_bin * +read_item(FILE *in) +{ + struct item_bin *ib=(struct item_bin *) buffer; + int r,s; + r=fread(ib, sizeof(*ib), 1, in); + if (r != 1) + return NULL; + bytes_read+=r; + s=(ib->len+1)*4-sizeof(*ib); + r=fread(ib+1, s, 1, in); + if (r != 1) + return NULL; + bytes_read+=r; + return ib; +} + +static void +bbox(struct coord *c, int count, struct rect *r) +{ + if (! count) + return; + r->l=*c; + r->h=*c; + c++; + while (--count) { + if (c->x < r->l.x) + r->l.x=c->x; + if (c->y < r->l.y) + r->l.y=c->y; + if (c->x > r->h.x) + r->h.x=c->x; + if (c->y > r->h.y) + r->h.y=c->y; + } +} + +static int +contains_bbox(int xl, int yl, int xh, int yh, struct rect *r) +{ + if (r->h.x < xl || r->h.x > xh) { + return 0; + } + if (r->l.x > xh || r->l.x < xl) { + return 0; + } + if (r->h.y < yl || r->h.y > yh) { + return 0; + } + if (r->l.y > yh || r->l.y < yl) { + return 0; + } + return 1; + +} +struct rect world_bbox = { + { -20000000, -20000000}, + { 20000000, 20000000}, +}; + +static void +tile(struct rect *r, char *ret) +{ + int x0,x1,x2,x3,x4; + int y0,y1,y2,y3,y4; + int i; + x0=world_bbox.l.x; + y0=world_bbox.l.y; + x4=world_bbox.h.x; + y4=world_bbox.h.y; + for (i = 0 ; i < 14 ; i++) { + x2=(x0+x4)/2; + y2=(y0+y4)/2; + x1=(x0+x2)/2; + y1=(y0+y2)/2; + x3=(x2+x4)/2; + y3=(y2+y4)/2; + if ( contains_bbox(x0,y0,x2,y2,r)) { + strcat(ret,"d"); + x4=x2; + y4=y2; + } else if (contains_bbox(x2,y0,x4,y2,r)) { + strcat(ret,"c"); + x0=x2; + y4=y2; + } else if (contains_bbox(x0,y2,x2,y4,r)) { + strcat(ret,"b"); + x4=x2; + y0=y2; + } else if (contains_bbox(x2,y2,x4,y4,r)) { + strcat(ret,"a"); + x0=x2; + y0=y2; + } else + return; + } +} + +static void +tile_bbox(char *tile, struct rect *r) +{ + *r=world_bbox; + struct coord c; + while (*tile) { + c.x=(r->l.x+r->h.x)/2; + c.y=(r->l.y+r->h.y)/2; + switch (*tile) { + case 'a': + r->l.x=c.x; + r->l.y=c.y; + break; + case 'b': + r->h.x=c.x; + r->l.y=c.y; + break; + case 'c': + r->l.x=c.x; + r->h.y=c.y; + break; + case 'd': + r->h.x=c.x; + r->h.y=c.y; + break; + } + tile++; + } +} + +GHashTable *tile_hash; + +static void +tile_data_append(char *tile, void *data, int len) +{ + struct tile_head *th; + th=g_hash_table_lookup(tile_hash, tile); + if (! th) { + th=malloc(sizeof(*th)+len); + th->size=0; + th->total_size=0; + th->name=g_strdup(tile); + th->next=NULL; + processed_tiles++; +#if 0 + fprintf(stderr,"new %s\n", tile); +#endif + } else { + th=realloc(th, sizeof(*th)+len+th->size); + } + memcpy(th->data+th->size, data, len); + th->size+=len; + th->total_size+=len; + g_hash_table_insert(tile_hash, th->name, th); +} + +static int +tile_data_size(char *tile) +{ + struct tile_head *th; + th=g_hash_table_lookup(tile_hash, tile); + if (! th) + return 0; + return th->total_size; +} + +static void +merge_tiles(char *base, char *sub) +{ + struct tile_head *thb, *ths; + thb=g_hash_table_lookup(tile_hash, base); + ths=g_hash_table_lookup(tile_hash, sub); + if (! ths) + return; +#if 0 + fprintf(stderr,"merging %s with %s\n", base, sub); +#endif + if (! thb) { + thb=ths; + thb->name=g_strdup(base); + g_hash_table_insert(tile_hash, thb->name, thb); + } else { +#if 0 + thb=realloc(thb, sizeof(*thb)+ths->size+thb->size); + memcpy(thb->data+thb->size, ths->data, ths->size); + thb->size+=ths->size; + thb->total_size+=ths->total_size; + g_hash_table_insert(tile_hash, thb->name, thb); +#if 0 + tiles_list=g_list_remove(tiles_list,ths->name); +#endif + free(ths); +#endif + thb->total_size+=ths->total_size; + while (thb->next) + thb=thb->next; + thb->next=ths; + } + g_hash_table_remove(tile_hash, sub); +} + +static void +get_tiles_list_func(char *key, struct tile_head *th, GList **list) +{ + *list=g_list_prepend(*list, key); +} + +static GList * +get_tiles_list(void) +{ + GList *ret=NULL; + g_hash_table_foreach(tile_hash, (GHFunc)get_tiles_list_func, &ret); + return ret; +} + +static void +write_tile(char *key, struct tile_head *th, gpointer dummy) +{ + FILE *f; + char buffer[1024]; + fprintf(stderr,"DEBUG: Writing %s\n", key); + strcpy(buffer,"tiles/"); + strcat(buffer,key); +#if 0 + strcat(buffer,".bin"); +#endif + f=fopen(buffer, "w+"); + while (th) { + fwrite(th->data, th->size, 1, f); + th=th->next; + } + fclose(f); +} + +static int +phase2(FILE *in) +{ + struct item_bin *ib; + struct tile_head *th; + struct rect r; + char buffer[1024]; + char basetile[1024]; + char subtile[1024]; + GList *tiles_list_sorted,*last; + int i,i_min,len,size[5],size_all,size_min,work_done; + + + processed_nodes=processed_ways=processed_relations=processed_tiles=0; + sig_alrm(0); + tile_hash=g_hash_table_new(g_str_hash, g_str_equal); + while ((ib=read_item(in))) { + processed_ways++; + bbox((struct coord *)(ib+1), ib->clen/2, &r); + buffer[0]='\0'; + tile(&r, buffer); +#if 0 + fprintf(stderr,"%s\n", buffer); +#endif + tile_data_append(buffer, ib, ib->len*4+4); + } + fprintf(stderr,"read %d bytes\n", bytes_read); + do { + tiles_list_sorted=get_tiles_list(); + fprintf(stderr,"PROGRESS: sorting %d tiles\n", g_list_length(tiles_list_sorted)); + tiles_list_sorted=g_list_sort(tiles_list_sorted, (GCompareFunc)strcmp); + fprintf(stderr,"PROGRESS: sorting %d tiles done\n", g_list_length(tiles_list_sorted)); + last=g_list_last(tiles_list_sorted); + size_all=0; + while (last) { + th=g_hash_table_lookup(tile_hash, last->data); + size_all+=th->total_size; + last=g_list_previous(last); + } + fprintf(stderr,"DEBUG: size=%d\n", size_all); + last=g_list_last(tiles_list_sorted); + work_done=0; + while (last) { + processed_tiles++; + len=strlen(last->data); + if (len >= 1) { + strcpy(basetile,last->data); + basetile[len-1]='\0'; + strcpy(subtile,last->data); + for (i = 0 ; i < 4 ; i++) { + subtile[len-1]='a'+i; + size[i]=tile_data_size(subtile); + } + size[4]=tile_data_size(basetile); + size_all=size[0]+size[1]+size[2]+size[3]+size[4]; + if (size_all < 65536 && size_all > 0 && size_all != size[4]) { + for (i = 0 ; i < 4 ; i++) { + subtile[len-1]='a'+i; + merge_tiles(basetile, subtile); + } + work_done++; + } else { + for (;;) { + size_min=size_all; + i_min=-1; + for (i = 0 ; i < 4 ; i++) { + if (size[i] && size[i] < size_min) { + size_min=size[i]; + i_min=i; + } + } + if (i_min == -1) + break; + if (size[4]+size_min >= 65536) + break; + subtile[len-1]='a'+i_min; + merge_tiles(basetile, subtile); + size[4]+=size[i_min]; + size[i_min]=0; + } + } + } + last=g_list_previous(last); + } + g_list_free(tiles_list_sorted); + fprintf(stderr,"PROGRESS: merged %d tiles\n", work_done); + } while (work_done); + sig_alrm(0); + alarm(0); +#if 0 + g_hash_table_foreach(tile_hash, write_tile, NULL); +#endif + return 0; + +} + +int +dir_entries; + +static void +add_zipdirentry(char *name, struct zip_cd *cd) +{ + int cd_size=sizeof(struct zip_cd)+strlen(name); + struct zip_cd *cdn; + if (zipdir_buffer.size + cd_size > zipdir_buffer.malloced) + extend_buffer(&zipdir_buffer); + cdn=(struct zip_cd *)(zipdir_buffer.base+zipdir_buffer.size); + *cdn=*cd; + strcpy((char *)(cdn+1), name); + zipdir_buffer.size += cd_size; + dir_entries++; +} + +int zipoffset; + +static void +write_zipmember(FILE *out, char *name, int filelen, struct tile_head *th) +{ + struct tile_head *thc; + struct zip_lfh lfh = { + 0x04034b50, + 0x0a, + 0x0, + 0x0, + 0xbe2a, + 0x5d37, + 0x0, + 0x0, + 0x0, + filelen, + 0x0, + }; + struct zip_cd cd = { + 0x02014b50, + 0x17, + 0x00, + 0x0a, + 0x00, + 0x0000, + 0x0000, + 0xbe2a, + 0x5d37, + 0x0, + 0x0, + 0x0, + filelen, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0, + zipoffset, + }; + char filename[filelen+1]; + int size=0,crc,len; + + crc=crc32(0, NULL, 0); + thc=th; + while (thc) { + size+=thc->size; + crc=crc32(crc, (unsigned char *)(thc->data), thc->size); + thc=thc->next; + } + if (size != th->total_size) { + fprintf(stderr,"ERROR: size error %d vs %d\n", size, th->total_size); + } + lfh.zipcrc=crc; + lfh.zipsize=size; + lfh.zipuncmp=size; + cd.zipccrc=crc; + cd.zipcsiz=size; + cd.zipcunc=size; + strcpy(filename, name); + len=strlen(filename); + while (len < filelen) { + filename[len++]='_'; + } + filename[filelen]='\0'; + add_zipdirentry(filename, &cd); + fwrite(&lfh, sizeof(lfh), 1, out); + fwrite(filename, filelen, 1, out); + thc=th; + while (thc) { + fwrite(thc->data, thc->size, 1, out); + thc=thc->next; + } + zipoffset+=sizeof(lfh)+filelen+size; + +} + +struct index_item { + struct item_bin item; + struct rect r; + struct attr_bin attr_order_limit; + short min; + short max; + struct attr_bin attr_zipfile_ref; + int zipfile_ref; +}; + +static void +index_submap_add(char *tile) +{ + struct index_item ii; + int len=strlen(tile); + char index_tile[len+1]; + strcpy(index_tile, tile); + if (len > 6) + len=6; + else + len=0; + index_tile[len]=0; + tile_bbox(tile, &ii.r); + + ii.item.len=sizeof(ii)/4-1; + ii.item.type=type_submap; + ii.item.clen=4; + + ii.attr_order_limit.len=2; + ii.attr_order_limit.type=attr_order_limit; + ii.min=0; + ii.max=0; + + ii.attr_zipfile_ref.len=2; + ii.attr_zipfile_ref.type=attr_zipfile_ref; + ii.zipfile_ref=dir_entries; + tile_data_append(index_tile, &ii, sizeof(ii)); +#if 0 + unsigned int *c=(unsigned int *)ⅈ + int i; + for (i = 0 ; i < sizeof(ii)/4 ; i++) { + fprintf(stderr,"%08x ", c[i]); + } + fprintf(stderr,"\n"); +#endif +} + +static int +phase3(FILE *out) +{ + struct zip_eoc eoc = { + 0x06054b50, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0, + 0x0, + 0x0, + }; + + struct tile_head *th; + GList *tiles_list,*next; + int size=0,len,maxlen=0; + + processed_nodes=processed_ways=processed_relations=processed_tiles=0; + sig_alrm(0); + tiles_list=get_tiles_list(); + next=g_list_first(tiles_list); + while (next) { + if (strlen(next->data) > maxlen) + maxlen=strlen(next->data); + next=g_list_next(next); + } + len=maxlen; + while (len > 0) { + fprintf(stderr,"PROGRESS: collecting tiles with len=%d\n", len); + next=g_list_first(tiles_list); + while (next) { + if (strlen(next->data) == len) { + index_submap_add(next->data); + th=g_hash_table_lookup(tile_hash, next->data); + write_zipmember(out, next->data, maxlen, th); + processed_tiles++; + size+=th->total_size; + } + next=g_list_next(next); + } + len--; + } + th=g_hash_table_lookup(tile_hash, ""); + write_zipmember(out, "index", 5, th); + size+=th->total_size; + fprintf(stderr, "DEBUG: wrote %d bytes\n", size); + fwrite(zipdir_buffer.base, zipdir_buffer.size, 1, out); + eoc.zipenum=dir_entries; + eoc.zipecenn=dir_entries; + eoc.zipecsz=zipdir_buffer.size; + eoc.zipeofst=zipoffset; + fwrite(&eoc, sizeof(eoc), 1, out); + sig_alrm(0); + alarm(0); + return 0; +} + +int main(int argc, char **argv) +{ + FILE *tmp; + char *map=g_strdup(attrmap); + build_attrmap(map); + tmp=fopen("tmpfile","w+"); + fprintf(stderr,"PROGRESS: Phase 1: collecting data\n"); + phase1(stdin,tmp); + fclose(tmp); + free(node_buffer.base); + node_buffer.base=NULL; + node_buffer.malloced=0; + node_buffer.size=0; + fprintf(stderr,"PROGRESS: Phase 2: generating tiles\n"); + tmp=fopen("tmpfile","r"); + phase2(tmp); + fclose(tmp); + fprintf(stderr,"PROGRESS: Phase 3: assembling map\n"); + phase3(stdout); + return 0; +} diff --git a/navit/src/zipfile.h b/navit/src/zipfile.h new file mode 100644 index 0000000..dd3bb49 --- /dev/null +++ b/navit/src/zipfile.h @@ -0,0 +1,49 @@ +struct zip_lfh { + int ziplocsig; + short zipver; + short zipgenfld; + short zipmthd; + short ziptime; + short zipdate; + int zipcrc; + int zipsize; + int zipuncmp; + short zipfnln; + short zipxtraln; + char zipname[0]; +} __attribute__ ((packed)); + +struct zip_cd { + int zipcensig; + char zipcver; + char zipcos; + char zipcvxt; + char zipcexos; + short zipcflg; + short zipcmthd; + short ziptim; + short zipdat; + int zipccrc; + int zipcsiz; + int zipcunc; + short zipcfnl; + short zipcxtl; + short zipccml; + short zipdsk; + short zipint; + int zipext; + int zipofst; + char zipcfn[0]; +} __attribute__ ((packed)); + +struct zip_eoc { + int zipesig; + short zipedsk; + short zipecen; + short zipenum; + short zipecenn; + int zipecsz; + int zipeofst; + short zipecoml; + char zipecom[0]; +} __attribute__ ((packed));