/*************************************************************************** * map.c * * Thu Jul 19 19:00:10 2007 * Copyright 2007 Steffen Pohle * steffen@gulpe.de ****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "map.h" #include "memoryleak.h" #include "system.h" struct map_hash **mhash = NULL; int mhash_max = 0; int mhash_pos = 0; struct map_lsstat *mlsstat = NULL; int map_busy = 0; extern int map_search_fd; /****************************************************** * Initialize the map data, allocate memory and * increase the memory. */ void map_init () { int i, j; char fn[LEN_FILENAME]; d_printf ("map_init"); d_printf (" MAP_HASH_DEGFACTOR:%f", MAP_HASH_DEGFACTOR); d_printf (" MAP_OSMWEB_DELTA:%f", MAP_OSMWEB_DELTA); d_printf (" MAP_LSHASHFACTOR:%d", MAP_LSHASHFACTOR); d_printf (" MAP_LSSTAT_MAX:%d", MAP_LSSTAT_MAX); d_printf (" Directory: %s", cfg.mappath); strncpy (fn, cfg.mappath, LEN_FILENAME); if (fn[(i=strlen(fn))] == DIR_SEP) fn[i] = '\0'; else { cfg.mappath[strlen(cfg.mappath)+1] = '\0'; cfg.mappath[strlen(cfg.mappath)] = DIR_SEP; } if (!dir_exist (fn)) { d_printf ("***************** dir does not exist **************************"); } if (mlsstat == NULL) mlsstat = (struct map_lsstat*) ml_malloc (MAP_LSSTAT_MAX*sizeof (struct map_lsstat)); for (i = 0; i < MAP_LSSTAT_MAX; i++) { mlsstat[i].fname[0] = '\0'; mlsstat[i].fnametmp[0] = '\0'; for (j = 0; j < MAP_LSHASHFACTOR*MAP_LSHASHFACTOR; j++) { mlsstat[i].r_lshpos[j].pos = 0; mlsstat[i].r_lshpos[j].size = 0; mlsstat[i].w_lshpos[j].pos = 0; mlsstat[i].w_lshpos[j].size = 0; if (j < MAP_LSFREECNT) { mlsstat[i].w_free[j].pos = 0; mlsstat[i].w_free[j].size = 0; } } mlsstat[i].w_fd = 0; mlsstat[i].r_fd = 0; } mhash_max = MAP_HASH_MAX; mhash = (struct map_hash**) ml_malloc (sizeof (void*) * (mhash_max)); mhash_pos = mhash_max/2; for (i = 0; i < mhash_max; i++) mhash[i] = NULL; }; void map_clear () { int i; d_printf ("map_clean"); if (mhash != NULL) { d_printf ("map_clean mhash reset"); for (i = 0; i < mhash_max; i++) if (mhash[i]) { ml_free (mhash[i]); mhash[i] = NULL; } ml_free (mhash); mhash = NULL; mhash_max = 0; } if (mlsstat) { d_printf ("map_clean mlsstat reset"); for (i = 0; i < MAP_LSSTAT_MAX; i++) { if (mlsstat[i].w_fd != 0 || mlsstat[i].r_fd != 0) map_ls_statclose (&mlsstat[i]); } ml_free (mlsstat); mlsstat = NULL; } if (map_search_fd) { close (map_search_fd); map_search_fd = 0; } map_init (); d_printf ("map_clean left"); }; /********************************************************************************* * * convert input text to geo-data needed for the programm * RETURN 1 on success, 0 on error */ int map_text2geo (char *text, float *dest) { int i; int type = 0; // 0 = grad, 1=min, 2=sec char ctab[3][32]; int itab[3] = { 0, 0, 0}; float ftab[3] = {0.0, 0.0, 0.0 }; memset (ctab, 0x0, sizeof (ctab)); if (text == NULL || dest == NULL) return 0; for (i = 0; itab[type] < 32 && i < 63; i++) { if (text[i] == '\0') break; else if (text[i] == '"') type = 1; else if (text[i] == '\'') type = 2; else ctab[type][itab[type]++] = text[i]; } for (i = 0; i < 3; i++) ftab[i] = atof(ctab[i]); *dest = ftab[0] + ftab[1]/60.0 + ftab[2]/3600.0; return 1; }; /********************************************************************************* * * convert between stretched km/map and geographial coordinates * */ float map_lon2km (float lon, float lat) { return (lon * cosf(M_PI * lat/180.0) * M_PI * MAP_EARTHRADIUS/180.0); }; float map_lat2km (float lat) { return (lat * M_PI * MAP_EARTHRADIUS/180.0); }; float map_km2lon (float km, float lat) { return (180.0 * km / (cosf(M_PI * lat/180.0) * M_PI * MAP_EARTHRADIUS)); }; float map_km2lat (float km) { return (180.0 * km / (M_PI * MAP_EARTHRADIUS)); }; /********************************************************************************* * * convert between integer lon and lat and the float lon lat values * needed for handling with the hash tables * */ int map_geo2igeo (float f) { if (f < -720.0 || f > 720.0) { d_printf ("map_geo2igeo f out of range. f:%f", f); d_print_backtrace (); f = 0.0; } f = f + 180.0; while (f < 0.0) f = f + 360.0; while (f >= 360.0) f = f - 360.0; return ((int)(f*MAP_HASH_DEGFACTOR)); }; float map_igeo2geo (int i) { return ((((float)i)/MAP_HASH_DEGFACTOR)-180.0); }; struct map_hashpos map_pos2ipos (struct map_pos pos) { struct map_hashpos hpos; hpos.ilon = map_geo2igeo(pos.lon); hpos.ilat = map_geo2igeo(pos.lat); return hpos; }; float map_getdistance (struct map_pos p1, struct map_pos p2) { fPoint v; v.x = map_lon2km (p1.lon - p2.lon, p2.lat); v.y = map_lat2km (p1.lat - p2.lat); return sqrtf (v.x*v.x + v.y*v.y); }; /****************************************************************************** * * Debugging Functions.. * */ void map_way_print (struct map_way *mw) { int i; d_printf (""); d_printf ("DEBUG WAY: %lld:%d name:%s", mw->id, mw->subid, mw->name); d_printf ("| Points: %d @ %p Nodes:%d @ %p", mw->p_cnt, mw->p, mw->n_cnt, mw->n); for (i = 0; i < mw->p_cnt; i++) d_printf ("| %3d: %g , %g", i, mw->p[i].lon, mw->p[i].lat); for (i = 0; i < mw->n_cnt; i++) d_printf ("| %3d to %lld:%d pnr:%d %g , %g", i, mw->n[i].d_id, mw->n[i].d_subid, mw->n[i].d_pnr, mw->n[i].d.lon, mw->n[i].d.lat); }; /* * refresh the map by downloading from internet */ void map_refresh (float lon, float lat) { char fn[LEN_FILENAME]; char rfn[LEN_FILENAME]; map_ls_get_filename_only (fn, LEN_FILENAME, map_geo2igeo (lon), map_geo2igeo (lat)); map_ls_get_filename (rfn, LEN_FILENAME, map_geo2igeo (lon), map_geo2igeo (lat)); #if defined(SPOSMROUTE) map_webload (fn, rfn, NULL); #endif }; /* * load all needed blocks from the server * start, end rectangle to download * delta, how many km addition to the left, right, up and down. */ void map_refreshblock (struct map_pos start, struct map_pos end, float delta) { char fn[LEN_FILENAME]; char rfn[LEN_FILENAME]; int ilon, ilon_s, ilon_e, ilat, ilat_s, ilat_e; fPoint p1, p2; char text[255]; /* check that we download the data from top/left to bottom/right */ p1.x = map_lon2km (start.lon, start.lat); p1.y = map_lat2km (start.lat); p2.x = map_lon2km (end.lon, end.lat); p2.y = map_lat2km (end.lat); if (p1.x > p2.x) { memswap (&p1.x, &p2.x, sizeof (float)); } if (p1.y < p2.y) { memswap (&p1.y, &p2.y, sizeof (float)); } p1.x -= delta; p1.y += delta; p2.x += delta; p2.y -= delta; d_printf (" km %g,%g --> %g,%g", p1.x, p1.y, p2.x, p2.y); /* latitude loop */ ilat_s = map_geo2igeo (map_km2lat(p2.y)) / MAP_LSHASHFACTOR; ilat_e = map_geo2igeo (map_km2lat(p1.y)) / MAP_LSHASHFACTOR; for (ilat = ilat_s; ilat <= ilat_e; ilat++) { /* longitude loop */ ilon_s = map_geo2igeo (map_km2lon (p1.x, map_igeo2geo (ilat * MAP_LSHASHFACTOR))) / MAP_LSHASHFACTOR; ilon_e = map_geo2igeo (map_km2lon (p2.x, map_igeo2geo (ilat * MAP_LSHASHFACTOR))) / MAP_LSHASHFACTOR; for (ilon = ilon_s; ilon <= ilon_e; ilon++) { /* download data */ map_ls_get_filename_only (fn, LEN_FILENAME, MAP_LSHASHFACTOR*ilon, MAP_LSHASHFACTOR*ilat); map_ls_get_filename (rfn, LEN_FILENAME, MAP_LSHASHFACTOR*ilon, MAP_LSHASHFACTOR*ilat); snprintf (text, 255, _("%d,%d "), ilat, ilon); #if defined(SPOSMROUTE) map_webload (fn, rfn, text); #endif } } }; /* * Display Map Informations */ void map_debug () { int i; d_printf ("**** Mapinformation"); d_printf ("Hash Information:"); for (i = 0; i < mhash_max; i++) if (mhash[i]) { d_printf (" mhash[%d] : prt:%p", i, mhash[i]); } };