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.
324 lines
8.4 KiB
324 lines
8.4 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;
|
|
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))-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));
|
|
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]);
|
|
}
|
|
};
|