You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
spOSMroute/mapsys/map.c

322 lines
8.3 KiB

/***************************************************************************
* 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 <math.h>
#include "map.h"
#include "memoryleak.h"
#include "system.h"
struct map_hash **mhash = NULL;
int mhash_max = 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))-1] == DIR_SEP) fn[i] = '\0';
else {
d_printf (" append '%c' to mappath.", DIR_SEP);
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));
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]);
}
};