2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 #define _FILE_OFFSET_BITS 64
22 #define _LARGEFILE_SOURCE
23 #define _LARGEFILE64_SOURCE
42 #include "linguistics.h"
44 #ifdef HAVE_POSTGRESQL
51 struct tile_head *tile_head_root;
52 GHashTable *strings_hash,*tile_hash,*tile_hash2;
54 static char* string_hash_lookup( const char* key )
58 if ( strings_hash == NULL ) {
59 strings_hash = g_hash_table_new(g_str_hash, g_str_equal);
62 if ( ( key_ptr = g_hash_table_lookup(strings_hash, key )) == NULL ) {
63 key_ptr = g_strdup( key );
64 g_hash_table_insert(strings_hash, key_ptr, (gpointer)key_ptr );
70 static char** th_get_subtile( const struct tile_head* th, int idx )
72 char* subtile_ptr = NULL;
73 subtile_ptr = (char*)th + sizeof( struct tile_head ) + idx * sizeof( char *);
74 return (char**)subtile_ptr;
78 tile(struct rect *r, char *suffix, char *ret, int max, int overlap, struct rect *tr)
88 for (i = 0 ; i < max ; i++) {
91 xo=(x4-x0)*overlap/100;
92 yo=(y4-y0)*overlap/100;
93 if ( contains_bbox(x0,y0,x2+xo,y2+yo,r)) {
97 } else if (contains_bbox(x2-xo,y0,x4,y2+yo,r)) {
101 } else if (contains_bbox(x0,y2-yo,x2+xo,y4,r)) {
105 } else if (contains_bbox(x2-xo,y2-yo,x4,y4,r)) {
124 tile_bbox(char *tile, struct rect *r, int overlap)
130 c.x=(r->l.x+r->h.x)/2;
131 c.y=(r->l.y+r->h.y)/2;
132 xo=(r->h.x-r->l.x)*overlap/100;
133 yo=(r->h.y-r->l.y)*overlap/100;
160 while (tile[0] >= 'a' && tile[0] <= 'd') {
168 tile_extend(char *tile, struct item_bin *ib, GList **tiles_list)
170 struct tile_head *th=NULL;
171 if (debug_tile(tile))
172 fprintf(stderr,"Tile:Writing %d bytes to '%s' (%p,%p) 0x%x %Ld\n", (ib->len+1)*4, tile, g_hash_table_lookup(tile_hash, tile), tile_hash2 ? g_hash_table_lookup(tile_hash2, tile) : NULL, ib->type, item_bin_get_id(ib));
174 th=g_hash_table_lookup(tile_hash2, tile);
176 th=g_hash_table_lookup(tile_hash, tile);
178 th=malloc(sizeof(struct tile_head)+ sizeof( char* ) );
180 // strcpy(th->subtiles, tile);
183 th->total_size_used=0;
186 th->name=string_hash_lookup(tile);
187 *th_get_subtile( th, 0 ) = th->name;
190 g_hash_table_insert(tile_hash2, string_hash_lookup( th->name ), th);
192 *tiles_list=g_list_append(*tiles_list, string_hash_lookup( th->name ) );
194 if (debug_tile(tile))
195 fprintf(stderr,"new '%s'\n", tile);
197 th->total_size+=ib->len*4+4;
198 if (debug_tile(tile))
199 fprintf(stderr,"New total size of %s(%p):%d\n", th->name, th, th->total_size);
200 g_hash_table_insert(tile_hash, string_hash_lookup( th->name ), th);
204 tile_data_size(char *tile)
206 struct tile_head *th;
207 th=g_hash_table_lookup(tile_hash, tile);
210 return th->total_size;
214 merge_tile(char *base, char *sub)
216 struct tile_head *thb, *ths;
217 thb=g_hash_table_lookup(tile_hash, base);
218 ths=g_hash_table_lookup(tile_hash, sub);
221 if (debug_tile(base) || debug_tile(sub))
222 fprintf(stderr,"merging '%s'(%p) (%d) with '%s'(%p) (%d)\n", base, thb, thb ? thb->total_size : 0, sub, ths, ths->total_size);
225 g_hash_table_remove(tile_hash, sub);
226 thb->name=string_hash_lookup(base);
227 g_hash_table_insert(tile_hash, string_hash_lookup( thb->name ), thb);
230 thb=realloc(thb, sizeof(struct tile_head)+( ths->num_subtiles+thb->num_subtiles ) * sizeof( char*) );
232 memcpy( th_get_subtile( thb, thb->num_subtiles ), th_get_subtile( ths, 0 ), ths->num_subtiles * sizeof( char*) );
233 thb->num_subtiles+=ths->num_subtiles;
234 thb->total_size+=ths->total_size;
235 g_hash_table_insert(tile_hash, string_hash_lookup( thb->name ), thb);
236 g_hash_table_remove(tile_hash, sub);
244 get_tiles_list_func(char *key, struct tile_head *th, GList **list)
246 *list=g_list_prepend(*list, key);
253 g_hash_table_foreach(tile_hash, (GHFunc)get_tiles_list_func, &ret);
259 write_tile(char *key, struct tile_head *th, gpointer dummy)
263 fprintf(stderr,"DEBUG: Writing %s\n", key);
264 strcpy(buffer,"tiles/");
267 strcat(buffer,".bin");
269 f=fopen(buffer, "wb+");
271 fwrite(th->data, th->size, 1, f);
279 write_item(char *tile, struct item_bin *ib, FILE *reference)
281 struct tile_head *th;
284 th=g_hash_table_lookup(tile_hash2, tile);
285 if (debug_itembin(ib)) {
286 fprintf(stderr,"tile head %p\n",th);
289 th=g_hash_table_lookup(tile_hash, tile);
291 if (debug_itembin(ib)) {
292 fprintf(stderr,"Match %s %d %s\n",tile,th->process,th->name);
295 if (th->process != 0 && th->process != 1) {
296 fprintf(stderr,"error with tile '%s' of length %d\n", tile, (int)strlen(tile));
301 fseek(reference, 8, SEEK_CUR);
304 if (debug_tile(tile))
305 fprintf(stderr,"Data:Writing %d bytes to '%s' (%p,%p) 0x%x\n", (ib->len+1)*4, tile, g_hash_table_lookup(tile_hash, tile), tile_hash2 ? g_hash_table_lookup(tile_hash2, tile) : NULL, ib->type);
307 if (th->total_size_used+size > th->total_size) {
308 fprintf(stderr,"Overflow in tile %s (used %d max %d item %d)\n", tile, th->total_size_used, th->total_size, size);
313 int offset=th->total_size_used/4;
314 fwrite(&th->zipnum, sizeof(th->zipnum), 1, reference);
315 fwrite(&offset, sizeof(th->total_size_used), 1, reference);
318 memcpy(th->zip_data+th->total_size_used, ib, size);
319 th->total_size_used+=size;
321 fprintf(stderr,"no tile hash found for %s\n", tile);
327 tile_write_item_to_tile(struct tile_info *info, struct item_bin *ib, FILE *reference, char *name)
330 write_item(name, ib, reference);
332 tile_extend(name, ib, info->tiles_list);
336 tile_write_item_minmax(struct tile_info *info, struct item_bin *ib, FILE *reference, int min, int max)
340 bbox((struct coord *)(ib+1), ib->clen/2, &r);
342 tile(&r, info->suffix, buffer, max, overlap, NULL);
343 tile_write_item_to_tile(info, ib, reference, buffer);
347 add_aux_tile(struct zip_info *zip_info, char *name, char *filename, int size)
354 if (!strcmp(at->name, name)) {
355 fprintf(stderr,"exists %s vs %s\n",at->name, name);
360 at=g_new0(struct aux_tile, 1);
361 at->name=g_strdup(name);
362 at->filename=g_strdup(filename);
364 aux_tile_list=g_list_append(aux_tile_list, at);
365 return zip_info->zipnum++;
369 write_aux_tiles(struct zip_info *zip_info)
371 GList *l=aux_tile_list;
379 buffer=malloc(at->size);
380 assert(buffer != NULL);
381 f=fopen(at->filename,"rb");
383 fread(buffer, at->size, 1, f);
385 write_zipmember(zip_info, at->name, zip_info->maxnamelen, buffer, at->size);
395 add_tile_hash(struct tile_head *th)
397 int idx,len,maxnamelen=0;
401 g_hash_table_insert(tile_hash2, string_hash_lookup( th->name ), th);
403 for( idx = 0; idx < th->num_subtiles; idx++ ) {
405 data = th_get_subtile( th, idx );
407 if (debug_tile(((char *)data)) || debug_tile(th->name)) {
408 fprintf(stderr,"Parent for '%s' is '%s'\n", *data, th->name);
411 g_hash_table_insert(tile_hash2, *data, th);
413 len = strlen( *data );
415 if (len > maxnamelen) {
424 create_tile_hash(void)
426 struct tile_head *th;
427 int len,maxnamelen=0;
429 tile_hash2=g_hash_table_new(g_str_hash, g_str_equal);
432 len=add_tile_hash(th);
433 if (len > maxnamelen)
441 create_tile_hash_list(GList *list)
444 struct tile_head *th;
446 tile_hash2=g_hash_table_new(g_str_hash, g_str_equal);
448 next=g_list_first(list);
450 th=g_hash_table_lookup(tile_hash, next->data);
452 fprintf(stderr,"No tile found for '%s'\n", (char *)(next->data));
455 next=g_list_next(next);
460 write_tilesdir(struct tile_info *info, struct zip_info *zip_info, FILE *out)
463 GList *next,*tiles_list;
465 struct tile_head *th,**last=NULL;
467 tiles_list=get_tiles_list();
468 info->tiles_list=&tiles_list;
470 create_tile_hash_list(tiles_list);
471 next=g_list_first(tiles_list);
472 last=&tile_head_root;
476 if (strlen(next->data) > maxlen)
477 maxlen=strlen(next->data);
478 next=g_list_next(next);
484 fprintf(stderr,"PROGRESS: collecting tiles with len=%d\n", len);
486 next=g_list_first(tiles_list);
488 if (strlen(next->data) == len) {
489 th=g_hash_table_lookup(tile_hash, next->data);
494 th->zipnum=zip_info->zipnum;
495 fprintf(out,"%s:%d",(char *)next->data,th->total_size);
497 for ( idx = 0; idx< th->num_subtiles; idx++ ){
498 data= th_get_subtile( th, idx );
499 fprintf(out,":%s", *data);
504 if (th->name[strlen(info->suffix)])
505 index_submap_add(info, th);
509 next=g_list_next(next);
513 if (info->suffix[0] && info->write) {
514 item_bin_init(item_bin, type_submap);
515 item_bin_add_coord_rect(item_bin, &world_bbox);
516 item_bin_add_attr_range(item_bin, attr_order, 0, 255);
517 item_bin_add_attr_int(item_bin, attr_zipfile_ref, zip_info->zipnum-1);
518 item_bin_write(item_bin, zip_info->index);
523 merge_tiles(struct tile_info *info)
525 struct tile_head *th;
528 GList *tiles_list_sorted,*last;
529 int i,i_min,len,size_all,size[5],size_min,work_done;
533 tiles_list_sorted=get_tiles_list();
534 fprintf(stderr,"PROGRESS: sorting %d tiles\n", g_list_length(tiles_list_sorted));
535 tiles_list_sorted=g_list_sort(tiles_list_sorted, (GCompareFunc)strcmp);
536 fprintf(stderr,"PROGRESS: sorting %d tiles done\n", g_list_length(tiles_list_sorted));
537 last=g_list_last(tiles_list_sorted);
540 th=g_hash_table_lookup(tile_hash, last->data);
541 zip_size+=th->total_size;
542 last=g_list_previous(last);
544 last=g_list_last(tiles_list_sorted);
548 len=tile_len(last->data);
550 strcpy(basetile,last->data);
551 basetile[len-1]='\0';
552 strcat(basetile, info->suffix);
553 strcpy(subtile,last->data);
554 for (i = 0 ; i < 4 ; i++) {
555 subtile[len-1]='a'+i;
556 size[i]=tile_data_size(subtile);
558 size[4]=tile_data_size(basetile);
559 size_all=size[0]+size[1]+size[2]+size[3]+size[4];
560 if (size_all < 65536 && size_all > 0 && size_all != size[4]) {
561 for (i = 0 ; i < 4 ; i++) {
562 subtile[len-1]='a'+i;
563 work_done+=merge_tile(basetile, subtile);
569 for (i = 0 ; i < 4 ; i++) {
570 if (size[i] && size[i] < size_min) {
577 if (size[4]+size_min >= 65536)
579 subtile[len-1]='a'+i_min;
580 work_done+=merge_tile(basetile, subtile);
581 size[4]+=size[i_min];
586 last=g_list_previous(last);
588 g_list_free(tiles_list_sorted);
589 fprintf(stderr,"PROGRESS: merged %d tiles\n", work_done);
594 index_init(struct zip_info *info, int version)
596 item_bin_init(item_bin, type_map_information);
597 item_bin_add_attr_int(item_bin, attr_version, version);
598 item_bin_write(item_bin, info->index);
602 index_submap_add(struct tile_info *info, struct tile_head *th)
604 int tlen=tile_len(th->name);
606 char index_tile[len+1+strlen(info->suffix)];
609 strcpy(index_tile, th->name);
615 strcat(index_tile, info->suffix);
616 tile_bbox(th->name, &r, overlap);
618 item_bin_init(item_bin, type_submap);
619 item_bin_add_coord_rect(item_bin, &r);
620 item_bin_add_attr_range(item_bin, attr_order, (tlen > 4)?tlen-4 : 0, 255);
621 item_bin_add_attr_int(item_bin, attr_zipfile_ref, th->zipnum);
622 tile_write_item_to_tile(info, item_bin, NULL, index_tile);