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_osmload.c

2123 lines
63 KiB

/***************************************************************************
* map_osmload.c
*
* 2009-08-16
* Copyright 2009 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.
*/
/***************************************************
*
* read the xml file provided by OpenStreetMap
*
*/
#define _FILE_OFFSET_BITS 64
#include "osmroute.h"
#include "map.h"
#include "system.h"
#include "memoryleak.h"
#include "vector.h"
#include <locale.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <dirent.h>
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <libxml/xmlreader.h>
#include <bzlib.h>
struct osm_nodehash {
unsigned long long int id; /* node id */
long long int pos; /* position inside the node file */
};
struct osm_waynode {
unsigned long long int wid; /* way id */
unsigned short int wsubid; /* way sub id */
unsigned short int wpnr; /* point number inside the way node */
long long int next; /* position of the next way node */
};
struct osm_node {
unsigned long long int id; /* node id */
float lon; /* geo data of the node */
float lat;
unsigned short int waynodecnt; /* number of waynodes */
long long int waynode; /* position of the first waynode */
};
#define OSM_NODEDETAIL_NONE 0
#define OSM_NODEDETAIL_PLACE 1
#define OSM_NODEDETAIL_POI 2
struct osm_nodedetail {
unsigned long long int id;
int type; /* OSM_NODEDETAIL_PLACE, OSM_NODEDETAIL_POI */
int elements;
int size;
int allocsize;
char *data;
};
struct osm_way {
unsigned long long int wid;
int type;
char name[MAP_W_NAMELEN];
char ref[MAP_W_NAMELEN];
int flags;
int ncnt;
int nmax;
unsigned long long int *nid;
char data[];
};
struct s_osm_hashnodes {
short int hid; // number of the hid, -1 == unused
int hash_cnt; // current numbers inside
int hash_fd; // file descriptor
int hash_alloc;
struct osm_nodehash *hash; // memory to hash
char fnhash[LEN_FILENAME];
long long int nodes_end; // current end position inside the file
int nodes_fd; // file descriptor
char fnnodes[LEN_FILENAME];
};
struct s_osm_xmlcallback {
FILE *f;
BZFILE *bzf;
long long int filesize;
long long int filepos;
};
#define OSM_HASHNODES 16
static struct s_osm_hashnodes _hashnodes[OSM_HASHNODES];
static struct s_osm_hashnodes *hashnodes[OSM_HASHNODES];
struct s_osmmway {
int pmax;
int size;
struct map_way *mway;
};
struct s_osmmarea {
int pmax;
struct map_area *marea;
};
struct s_osmdata {
struct s_osmmarea area;
struct s_osmmway way;
struct osm_way *oway;
} osm;
static struct osm_waynode *osm_wnode = NULL;
static int osm_wnodecnt = 0;
static struct map_waynode *osm_mwnode = NULL;
static int osm_mwnodecnt = 0;
/* for statistic only */
static short int osm_hidmax = -1; // highest hid number
unsigned long long int osm_cur_wayid;
struct map_pos osm_load_from_web_cur;
struct map_pos osm_load_from_web_start;
struct map_pos osm_load_from_web_end;
unsigned long long int osm_nodes_cnt;
unsigned long long int osm_area_cnt;
unsigned long long int osm_ways_cnt;
float osm_file_pos;
void osm_delete_tmpdir ();
void osm_init ();
void osm_free ();
char *osm_getfname_hid (char *fn, int size, short int hid, char *ext);
char *osm_getfname_id (char *fn, int size, unsigned long long int id, char *ext);
#define osm_hash_getid(__id) ((short int)(__id>>21))
struct s_osm_hashnodes *osm_hashnodes_load (short int hid, int loadhash);
void osm_hashnodes_free (struct s_osm_hashnodes *hnode);
#define osm_node_save(_node) _osm_node_save (_node, 0)
#define osm_node_append(_node) _osm_node_save (_node, 1)
int _osm_node_save (struct osm_node node, int append);
int osm_node_load (struct osm_node *node, unsigned long long int id);
int osm_hash_read (struct s_osm_hashnodes *hnodes, struct osm_nodehash *hash, int pos);
struct s_osm_hashnodes *osm_hash_get (unsigned long long int id, struct osm_nodehash *ret);
int osm_linehashsplit (struct map_pos p1, struct map_pos p2, struct map_pos *np);
struct osm_way *osm_way_alloc (int wmax);
void osm_way_copy (struct osm_way *d, struct osm_way *s);
void osm_way_save (struct osm_way *oway, struct s_osmmway *mway);
void osm_mway_new (int max); /* realloc temp osm_way struct */
void osm_waynode_add (struct osm_node *node, long long int nodepos,
unsigned long long int id, unsigned short int subid, unsigned short int pnr);
void osm_waynodes_check ();
void osm_waynodes_checknode (struct s_osm_hashnodes *nhash, struct osm_node *node);
void osm_marea_new (struct s_osmmarea *a, int max);
void osm_area_save (struct osm_way *oway, struct s_osmmarea *marea);
int osm_area_split_add (struct s_osmmarea *marea);
void osm_nodedetail_save (struct osm_nodedetail *onoded, struct osm_node *node);
/**************************************************************************
* create a filename out of the node id..
*/
char *osm_getfname_id (char *fn, int size, unsigned long long int id, char *ext) {
if (fn == NULL) return NULL;
if (id == 0) return NULL;
snprintf (fn, size, "%s/nodes-%d%s", cfg.temppath, osm_hash_getid(id), ext);
return fn;
};
char *osm_getfname_hid (char *fn, int size, short int hid, char *ext) {
if (fn == NULL) return NULL;
if (hid == -1) return NULL;
snprintf (fn, size, "%s/nodes-%d%s", cfg.temppath, hid, ext);
return fn;
};
/**************************************************************************
* do all preparations for loading a osm file
*/
void osm_delete_tmpdir (char *path) {
DIR *dir;
struct dirent *de;
struct stat fstat;
char fn[LEN_FILENAME];
char fndir[LEN_FILENAME];
static int _osm_recursive = 0;
if (_osm_recursive > 16) { // max number of calls..
d_printf ("%s:%d too many subdirs abort deleting (%s).\n", __FILE__, __LINE__, path);
return;
}
_osm_recursive++;
/* read the directory */
dir = opendir(path);
while (dir != NULL && (de = readdir(dir)) != NULL) {
snprintf (fndir, LEN_FILENAME, "%s/%s", path, de->d_name);
/* directory? delete this dir */
sprintf (fn, "%s/%s", path, de->d_name);
stat (fn, &fstat);
if (S_ISDIR (fstat.st_mode) && strcmp (de->d_name, ".") && strcmp (de->d_name, "..")) {
osm_delete_tmpdir (fndir);
rmdir (fndir);
}
/* file? delete file */
else if (S_ISREG (fstat.st_mode)) {
unlink (fndir);
}
}
closedir (dir);
_osm_recursive--;
};
void osm_init () {
int i;
osm_delete_tmpdir (cfg.temppath);
/* take care of the hash */
for (i = 0; i < OSM_HASHNODES; i++) {
_hashnodes[i].hid = -1;
_hashnodes[i].hash = NULL;
_hashnodes[i].hash_alloc = 0;
_hashnodes[i].hash_cnt = 0;
_hashnodes[i].hash_fd = 0;
_hashnodes[i].nodes_end = 0;
_hashnodes[i].nodes_fd = 0;
hashnodes[i] = &_hashnodes[i];
}
/* prepare osm_td data */
if (osm.way.mway) ml_free (osm.way.mway);
osm.way.mway = NULL;
osm.way.pmax = 0;
osm.way.size = 0;
if (osm.area.marea) ml_free (osm.area.marea);
osm.area.marea = NULL;
osm.area.pmax = 0;
if (osm.oway) ml_free (osm.oway);
osm.oway = osm_way_alloc (32);
osm_nodes_cnt = 0;
osm_area_cnt = 0;
osm_ways_cnt = 0;
osm_hidmax = -1;
#ifdef _LINUX_
mkdir (cfg.temppath, 0755);
#else
mkdir (cfg.temppath);
#endif
};
void osm_free () {
int i;
/* take care of the hash files */
do {
for (i = 0; i < OSM_HASHNODES; i++) if (hashnodes[i]->hid != -1) {
osm_hashnodes_free (hashnodes[i]);
break;
}
}
while (i < OSM_HASHNODES);
if (osm.way.mway) ml_free (osm.way.mway);
osm.way.mway = NULL;
osm.way.pmax = 0;
osm.way.size = 0;
if (osm.area.marea) ml_free (osm.area.marea);
osm.area.marea = NULL;
osm.area.pmax = 0;
if (osm.oway) ml_free (osm.oway);
osm.oway = NULL;
if (osm_wnode != NULL) ml_free (osm_wnode);
osm_wnode = NULL;
osm_wnodecnt = 0;
if (osm_mwnode != NULL) ml_free (osm_mwnode);
osm_mwnode = NULL;
osm_mwnodecnt = 0;
// osm_delete_tmpdir (TMPDIR);
};
/***********************************************************************
* nodehash filemanagment
*/
/*
* load the needed nodes and nodehash file into the memory
* free unused memory if needed
*/
struct s_osm_hashnodes *osm_hashnodes_load (short int hid, int loadhash) {
struct stat fstathash, fstatnodes;
struct s_osm_hashnodes *hnodes = NULL;
int i, j, t;
/* searching for the current hash inside the memory,
* when finished: j - first free entry, t - last unused */
for (j = -1, t = -1, i = 0 ; i < OSM_HASHNODES; i++) {
if (hashnodes[i]->hid == hid) {
/* found hashnodes, select it and put it to the first entry */
hnodes = hashnodes[i];
if (i > 0) for(j = i; j > 0; j--) hashnodes[j] = hashnodes[j-1];
hashnodes[0] = hnodes;
break;
}
else if (j == -1 && hashnodes[i]->hid == -1) j = i;
else if (hashnodes[i]->hid != -1)
t = i;
}
if (hnodes == NULL) {
/* give us the first entry */
if (t+1 == OSM_HASHNODES) osm_hashnodes_free (hashnodes[t]); // delete last one
hnodes = hashnodes[OSM_HASHNODES-1];
for(i = OSM_HASHNODES-1; i > 0; i--) hashnodes[i] = hashnodes[i-1];
hashnodes[0] = hnodes;
/* create the filenames for the files */
osm_getfname_hid (hnodes->fnhash, LEN_FILENAME, hid, ".hashnode");
osm_getfname_hid (hnodes->fnnodes, LEN_FILENAME, hid, ".nodes");
/* check how much memory we will need to laod the data */
if (stat (hnodes->fnhash, &fstathash) != 0)
fstathash.st_size = 0;
if (stat (hnodes->fnnodes, &fstatnodes) != 0)
fstatnodes.st_size = 0;
/* load the needed data */
hnodes->hid = hid;
hnodes->hash = NULL;
if ((hnodes->hash_fd = open (hnodes->fnhash, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR)) < 0)
d_printf ("%s:%d open file '%s' failed. error:%s", __FILE__, __LINE__, hnodes->fnhash, strerror (errno));
hnodes->hash_cnt = fstathash.st_size / sizeof (struct osm_nodehash);
if ((hnodes->nodes_fd = open (hnodes->fnnodes, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR)) < 0)
d_printf ("%s:%d open file '%s' failed. error:%s", __FILE__, __LINE__, hnodes->fnnodes, strerror (errno));
hnodes->nodes_end = fstatnodes.st_size;
}
/*
* do we need to load the full hash data?
*/
if (loadhash && hnodes->hash == NULL) {
hnodes->hash_alloc = 5000 + hnodes->hash_cnt;
hnodes->hash = (struct osm_nodehash*) ml_malloc (hnodes->hash_alloc * sizeof (struct osm_nodehash));
lseek (hnodes->hash_fd, 0, SEEK_SET);
if (read (hnodes->hash_fd, hnodes->hash, hnodes->hash_cnt * sizeof (struct osm_nodehash)) < sizeof (struct osm_nodehash) * hnodes->hash_cnt) {
d_printf ("%s:%d could not read data from file:%s", __FILE__, __LINE__, hnodes->fnhash);
errorexit (-1);
}
}
if (hid > osm_hidmax) osm_hidmax = hid;
return hnodes;
};
/*
* all data will be saved immediately so we need only to close the file
*/
void osm_hashnodes_free (struct s_osm_hashnodes *hnode) {
if (hnode->hid == -1) return;
if ((hnode - _hashnodes) >= OSM_HASHNODES || (hnode - _hashnodes) < 0) {
d_printf ("%s:%d something went very wrong: %d, max (OSM_HASHNODES): %d\n", __FILE__, __LINE__,
(hnode - _hashnodes), OSM_HASHNODES);
errorexit (-1);
}
/* free all data */
if (hnode->hash && hnode->hash_alloc > 0) {
lseek (hnode->hash_fd, 0, SEEK_SET);
if (write (hnode->hash_fd, hnode->hash,
hnode->hash_cnt*sizeof(struct osm_nodehash)) < hnode->hash_cnt*sizeof(struct osm_nodehash)) {
d_printf ("%s:%d could not save all needed data.", __FILE__, __LINE__);
}
ml_free (hnode->hash);
hnode->hash_alloc = 0;
hnode->hash = NULL;
}
else if (hnode->hash) {
ml_free (hnode->hash);
hnode->hash_alloc = 0;
hnode->hash = NULL;
}
hnode->hash_cnt = 0;
if (hnode->hash_fd > 0) {
close (hnode->hash_fd);
hnode->hash_fd = 0;
}
hnode->nodes_end = 0;
if (hnode->nodes_fd > 0) {
close (hnode->nodes_fd);
hnode->nodes_fd = 0;
}
hnode->hid = -1;
};
/*
* read hash node from position
*/
int osm_hash_read (struct s_osm_hashnodes *hnodes, struct osm_nodehash *hash, int pos) {
if (hnodes->hash_alloc > 0 && hnodes->hash) {
memcpy (hash, hnodes->hash+pos, sizeof(struct osm_nodehash));
}
else {
lseek (hnodes->hash_fd, pos * sizeof (struct osm_nodehash), SEEK_SET);
if (read (hnodes->hash_fd, hash, sizeof (struct osm_nodehash)) < sizeof (struct osm_nodehash)) {
d_printf ("%s:%d could not read data from file:%s pos:%d", __FILE__, __LINE__, hnodes->fnhash, pos);
return 0;
}
}
return 1;
};
/*
* returns the nodehash entry to the givin node
*/
struct s_osm_hashnodes *osm_hash_get (unsigned long long int id, struct osm_nodehash *ret) {
short int hid = osm_hash_getid (id);
struct s_osm_hashnodes *hnodes = NULL;
struct osm_nodehash hash;
long long int left, pos, lpos1, lpos2;
int i;
unsigned long long int lid;
ret->id = 0;
ret->pos = 0;
/* prepare for looking inside the hash */
hnodes = osm_hashnodes_load (hid, 0);
left = hnodes->hash_cnt/2;
pos = left;
lpos2 = -2;
lpos1 = -1;
while (left > 0 && lpos1 != pos && lpos2 != pos && lpos1 != lpos2) {
lpos1 = lpos2;
lpos2 = pos;
if (!osm_hash_read (hnodes, &hash, pos)) {
d_printf ("%s:%d osm_hash_get id:%lld hnodes.hid:%d hnodes.cnt:%d hnodes.fnnode:%s", __FILE__, __LINE__, id, hnodes->hid, hnodes->hash_cnt, hnodes->fnnodes);
return NULL;
}
if (hash.id == id) {
*ret = hash;
return hnodes;
}
else if (hash.id < id) {
/* hid is larger than half.hid */
left = left / 2 + left % 2;
pos = pos+left;
if (pos >= hnodes->hash_cnt) pos = hnodes->hash_cnt-1;
}
else {
/* hid is smaler than half.hid */
left = left / 2 + left % 2;
pos = pos-left;
if (pos < 0) pos = 0;
}
}
if (!osm_hash_read (hnodes, &hash, pos)) {
d_printf ("%s:%d osm_hash_get id:%lld hnodes.hid:%d hnodes.cnt:%d hnodes.fnnode:%s", __FILE__, __LINE__, id, hnodes->hid, hnodes->hash_cnt, hnodes->fnnodes);
return NULL;
}
if (hash.id == id) {
*ret = hash;
return hnodes;
}
else for (lpos1 = 0; lpos1 < left+1; lpos1++) {
if (pos-lpos1 >= 0) {
if (!osm_hash_read (hnodes, &hash, pos-lpos1)) {
d_printf ("%s:%d osm_hash_get id:%lld hnodes.hid:%d hnodes.cnt:%d hnodes.fnnode:%s", __FILE__, __LINE__, id, hnodes->hid, hnodes->hash_cnt, hnodes->fnnodes);
return NULL;
}
if (hash.id == id) {
*ret = hash;
return hnodes;
}
}
if (pos+lpos1 < hnodes->hash_cnt) {
if (!osm_hash_read (hnodes, &hash, pos+lpos1)) {
d_printf ("%s:%d osm_hash_get id:%lld hnodes.hid:%d hnodes.cnt:%d hnodes.fnnode:%s", __FILE__, __LINE__, id, hnodes->hid, hnodes->hash_cnt, hnodes->fnnodes);
return NULL;
}
if (hash.id == id) {
*ret = hash;
return hnodes;
}
}
}
d_printf ("node %lld not found over fast way. hid:%d", id, hnodes->hid);
for (i = 0; i < OSM_HASHNODES; i++) {
d_printf ("%s hid:%d hash_alloc:%d hash_cnt:%d", __FUNCTION__, hashnodes[i]->hid, hashnodes[i]->hash_alloc, hashnodes[i]->hash_cnt);
}
for (lid = 0, left = 0, pos = 1; (left < hnodes->hash_cnt); left++) {
osm_hash_read (hnodes, &hash, left);
if (hash.id == id) {
d_printf (" node found over slow way: %lld nr:%d", id, left);
*ret = hash;
return hnodes;
}
if (left>0 && pos) if (hash.id <= lid && hnodes->hash) {
d_printf ("nodes are not sorted %lld <= %lld. hid:%d", hnodes->hash[left].id, hnodes->hash[left-1].id, hnodes->hid);
pos = 0;
}
lid = hash.id;
}
return NULL;
};
/*
* add the new hash entry to the hash table, we will not check for double
* entrys, this have to be done by the caller.
*/
int osm_hash_add (struct s_osm_hashnodes *hnodes, struct osm_nodehash hash) {
int i;
struct osm_nodehash thash;
if (hnodes->hash == NULL || hnodes->hash_alloc == 0)
hnodes = osm_hashnodes_load (hnodes->hid, 1);
if (hnodes->hash_alloc <= hnodes->hash_cnt) {
hnodes->hash_alloc += 5000;
hnodes->hash = ml_realloc (hnodes->hash, hnodes->hash_alloc * sizeof (struct osm_nodehash));
}
/* check for the right place */
i = hnodes->hash_cnt;
if (i > 0) thash = hnodes->hash[i-1];
while (i > 0 && thash.id > hash.id) {
hnodes->hash[i] = thash;
i--;
if (i > 0) thash = hnodes->hash[i-1];
}
hnodes->hash[i] = hash;
hnodes->hash_cnt++;
return 1;
};
/***********************************************************************
* loading / saving of a node also adding the new pos to the hash file
*/
int _osm_node_save (struct osm_node node, int append) {
struct s_osm_hashnodes *hnodes = NULL;
struct osm_nodehash hash;
/* search if we have to update the node */
hash.id = -1;
hash.pos = -1;
if (!append) /* update --> hash and hnodes == set */
hnodes = osm_hash_get (node.id, &hash);
/* append? check if we have enought memory also setup the hash entry */
if (hnodes == NULL) { /* append */
hnodes = osm_hashnodes_load (osm_hash_getid (node.id), 1);
hash.pos = hnodes->nodes_end;
hash.id = node.id;
hnodes->nodes_end += sizeof (struct osm_node);
osm_hash_add (hnodes, hash);
}
lseek (hnodes->nodes_fd, hash.pos, SEEK_SET);
if (write (hnodes->nodes_fd, &node, sizeof (struct osm_node)) < sizeof (struct osm_node)) {
d_printf ("%s:%d could not write data to file:%s pos:%d", __FILE__, __LINE__, hnodes->fnnodes, hash.pos);
errorexit (-1);
}
return 1;
};
int osm_node_load (struct osm_node *node, unsigned long long int id) {
struct s_osm_hashnodes *hnodes = NULL;
struct osm_nodehash hash;
hnodes = osm_hash_get (id, &hash);
if (hnodes == NULL) return -1;
if (lseek (hnodes->nodes_fd, hash.pos, SEEK_SET) < 0)
d_printf ("%s:%d lseek failed. fd:%d error:%s", __FILE__, __LINE__, hnodes->nodes_fd, strerror (errno));
if (read (hnodes->nodes_fd, node, sizeof (struct osm_node)) < sizeof (struct osm_node)) {
d_printf ("%s:%d could not read data from file:%s pos:%d", __FILE__, __LINE__, hnodes->fnnodes, hash.pos);
errorexit (-1);
}
return hash.pos;
};
/******************************************************************************
* waynodes handling
*/
/*
* save the waynode data inside the hash file to read all needed data later on
* and check the waynodes inside the map files.
*/
void osm_waynode_add (struct osm_node *node, long long int nodepos, unsigned long long int id,
unsigned short int subid, unsigned short int pnr) {
struct s_osm_hashnodes *hnodes = NULL;
struct osm_nodehash hash;
struct osm_waynode wn;
long long int pos, wpos;
if (node == NULL) return;
hnodes = osm_hash_get (node->id, &hash);
if (hnodes == NULL) return;
pos = hnodes->nodes_end;
hnodes->nodes_end += sizeof (struct osm_waynode);
/* save waynode at the end of the file */
wn.wid = id;
wn.wsubid = subid;
wn.wpnr = pnr;
wn.next = 0;
// d_printf ("wn id:%lld subid:%d pnr: %hd",wn.wid, wn.wsubid, wn.wpnr);
lseek (hnodes->nodes_fd, pos, SEEK_SET);
if (write (hnodes->nodes_fd, &wn, sizeof (struct osm_waynode)) < sizeof (struct osm_waynode)) {
d_printf ("%s:%d could not write waynode data to file:%s pos:%d", __FILE__, __LINE__, hnodes->fnnodes, pos);
errorexit (-1);
}
if (node->waynode == 0) {
/* save node with new waypos */
node->waynode = pos;
}
else {
/* search for the last waynode entry */
wpos = node->waynode;
do {
lseek (hnodes->nodes_fd, wpos, SEEK_SET);
if (read (hnodes->nodes_fd, &wn, sizeof (struct osm_waynode)) < sizeof (struct osm_waynode)) {
d_printf ("%s:%d could not read data from file:%s pos:%d", __FILE__, __LINE__,
hnodes->fnnodes, hash.pos);
errorexit (-1);
}
wpos = wn.next;
}
while (wn.next != 0);
wn.next = pos;
pos = 0 - (long long int)sizeof (struct osm_waynode);
lseek (hnodes->nodes_fd, pos, SEEK_CUR);
if (write (hnodes->nodes_fd, &wn, sizeof (struct osm_waynode)) < sizeof (struct osm_waynode)) {
d_printf ("%s:%d could not write data to file:%s pos:%d", __FILE__, __LINE__,
hnodes->fnnodes, hash.pos);
errorexit (-1);
}
}
/* write node data */
node->waynodecnt++;
lseek (hnodes->nodes_fd, nodepos, SEEK_SET);
if (write (hnodes->nodes_fd, node, sizeof (struct osm_node)) < sizeof (struct osm_node)) {
d_printf ("%s:%d could not read data from file:%s pos:%d", __FILE__, __LINE__, hnodes->fnnodes, hash.pos);
errorexit (-1);
}
return;
};
void osm_waynodes_check () {
int hid, i;
struct s_osm_hashnodes *ohash;
struct osm_node node;
char text[256];
d_printf ("osm_waynodes_check started");
for (hid = 0; hid < osm_hidmax; hid++) {
sprintf (text, _("checking for waynodes in hid %d"), hid);
app_status (-1, text, 0.0);
ohash = osm_hashnodes_load (hid, 1);
for (i = 0; i < ohash->hash_cnt; i++) {
if ((i%1024) == 0) main_wnd_loop (i, ohash->hash_cnt);
/* read node */
lseek (ohash->nodes_fd, ohash->hash[i].pos, SEEK_SET);
if (read (ohash->nodes_fd, &node, sizeof (struct osm_node)) < sizeof (struct osm_node)) {
d_printf ("%s:%d could not read data from file:%s pos:%d", __FILE__, __LINE__,
ohash->fnnodes, ohash->hash[i].pos);
errorexit (-1);
}
osm_waynodes_checknode (ohash, &node);
}
}
d_printf ("osm_waynodes_check finished");
};
void osm_waynodes_checknode (struct s_osm_hashnodes *ohash, struct osm_node *node) {
struct map_way *way;
struct map_hash *mh;
int wncnt, ncur, nto, i, waysize;
/* check and allocate enought memory */
if (osm_wnodecnt < node->waynodecnt || osm_wnode == NULL) {
osm_wnodecnt = node->waynodecnt + 4;
if (osm_wnode) osm_wnode = ml_realloc (osm_wnode, sizeof (struct osm_waynode) * osm_wnodecnt);
else osm_wnode = ml_malloc (sizeof (struct osm_waynode) * osm_wnodecnt);
}
if (node->waynode == 0 && node->waynodecnt == 0) return;
else if (node->waynode == 0 || node->waynodecnt == 0) {
d_printf ("%s:%d osm_waynodes_checknode error something isn't right waynode:%lld waynodecnt:%d", __FILE__, __LINE__, node->waynode, node->waynodecnt);
return;
}
if (node->waynodecnt == 1) return;
/* read all waynodes */
lseek (ohash->nodes_fd, node->waynode, SEEK_SET);
wncnt = 0;
do {
/* read waynode */
if (read (ohash->nodes_fd, &osm_wnode[wncnt], sizeof (struct osm_waynode)) < sizeof (struct osm_waynode)) {
d_printf ("%s:%d could not read data from file:%s pos:%d",
__FILE__, __LINE__, ohash->fnnodes, osm_wnode[wncnt].next);
errorexit (-1);
}
lseek (ohash->nodes_fd, osm_wnode[wncnt].next, SEEK_SET);
wncnt++;
} while (osm_wnode[wncnt-1].next != 0 && wncnt < node->waynodecnt);
/*
* walk trough all waynodes
*/
for (ncur = 0; ncur < wncnt; ncur++) {
/*
* prepare current way
*/
if ((mh = map_hash_get (node->lon, node->lat, MHLOAD_RELOAD)) == NULL) continue;
if ((way = map_way_find (mh, osm_wnode[ncur].wid, osm_wnode[ncur].wsubid)) == NULL) continue;
waysize = map_way_getsize (way) + POINTERALIGNMENT;
/* check for enought memory */
if (osm_mwnodecnt < way->n_cnt+wncnt) {
osm_mwnodecnt = way->n_cnt+wncnt + 4;
if (osm_mwnode) osm_mwnode = ml_realloc (osm_mwnode, sizeof (struct map_waynode) * osm_mwnodecnt);
else osm_mwnode = ml_malloc (sizeof (struct map_waynode) * osm_mwnodecnt);
}
if (osm.way.size < waysize) {
osm.way.size = waysize + 256;
if (osm.way.mway) osm.way.mway = ml_realloc (osm.way.mway, osm.way.size);
else osm.way.mway = ml_malloc (osm.way.size);
}
/* copy way to osm_mway and reset pointer to the nodes*/
map_way_copy (osm.way.mway, way);
osm.way.mway->next = NULL;
osm.way.mway->n = osm_mwnode;
osm.way.mway->n_cnt = way->n_cnt;
/* copy nodes */
for (i = 0; i < way->n_cnt; i++)
osm.way.mway->n[i] = way->n[i];
/*
* now update or add the new nodes
*/
for (nto = 0; nto < wncnt; nto++) {
if (nto == ncur) continue; /* from and to identical. */
for (i = 0; i < osm.way.mway->n_cnt; i++) {
/* check if we know this node already */
if (osm.way.mway->n[i].d_id == osm_wnode[nto].wid &&
osm.way.mway->n[i].d_subid == osm_wnode[nto].wsubid &&
osm.way.mway->n[i].d_pnr == osm_wnode[nto].wpnr) break;
}
if (i == osm.way.mway->n_cnt && i < osm_mwnodecnt) {
/* unknown waynode add */
osm.way.mway->n[i].d_pnr = osm_wnode[nto].wpnr;
osm.way.mway->n[i].d_id = osm_wnode[nto].wid;
osm.way.mway->n[i].d_subid = osm_wnode[nto].wsubid;
osm.way.mway->n[i].d.lon = node->lon;
osm.way.mway->n[i].d.lat = node->lat;
osm.way.mway->n[i].pnr = osm_wnode[ncur].wpnr;
osm.way.mway->n[i].flags = 0;
osm.way.mway->n_cnt++;
}
else if (i == osm.way.mway->n_cnt && i >= osm_mwnodecnt) {
d_printf ("%s:%d osm_waynodes_checknode: something went very wrong. (i == osm_mway->n_cnt && i >= osm_mwnodecnt)", __FILE__, __LINE__);
errorexit (1);
}
}
/* replace current node */
if (way->n_cnt != osm.way.mway->n_cnt) {
map_way_add (osm.way.mway, MHLOAD_RELOAD);
}
}
};
/****************************************************************************
* split the line into peaces, is the line intersects with more then one
* hash segment the function will return 2 as indicator of another
* intersection.
*/
int osm_linehashsplit (struct map_pos p1, struct map_pos p2, struct map_pos *np) {
return 0; // for now just return 0 and get the other stuff running first.
};
/***************************************************************************
* osm_way handling .. allocating memory and converting it into map_way
*/
struct osm_way *osm_way_alloc (int wmax) {
struct osm_way *w = NULL;
w = (struct osm_way*) ml_malloc (sizeof (struct osm_way) + wmax * sizeof (unsigned long long int));
w->nmax = wmax;
w->ncnt = 0;
w->nid = (unsigned long long int*) &w->data[0];
w->name[0] = 0;
w->ref[0] = 0;
w->type = MWAY_unknown;
w->flags = 0;
return w;
};
void osm_way_copy (struct osm_way *d, struct osm_way *s) {
int i;
if (d == NULL || s == NULL) {
d_printf ("%s:%d d or s is NULL \n", __FILE__, __LINE__);
errorexit (-1);
}
d->wid = s->wid;
d->type = s->type;
strncpy (d->name, s->name, MAP_W_NAMELEN);
strncpy (d->ref, s->ref, MAP_W_NAMELEN);
for (i = 0; i < s->ncnt; i++)
if (i < d->nmax) d->nid[i] = s->nid[i];
d->ncnt = s->ncnt;
d->flags = s->flags;
};
void osm_mway_pmax_new (struct s_osmmway *w, int max) {
int newsize = sizeof (struct map_way) + 2 * sizeof (struct map_waynode) + max * sizeof (struct map_pos);
if (w->mway == NULL || newsize > w->size) {
w->mway = ml_realloc (w->mway, newsize);
w->size = newsize;
}
w->pmax = max;
w->mway->name[0] = 0;
w->mway->ref[0] = 0;
w->mway->n_cnt = 0;
w->mway->p_cnt = 0;
w->mway->n = (struct map_waynode*) &w->mway->data[0];
w->mway->p = (struct map_pos*) &w->mway->data[2 * sizeof (struct map_waynode)];
w->mway->id = 0;
w->mway->subid = 0;
w->mway->next = 0;
w->mway->flags = 0;
};
/********************************************************************
* convert the osm way into the map_way type and save it into the
* hash data block. I case the way goes over more hash segments the
* way will be slit into peaces */
void osm_way_save (struct osm_way *oway, struct s_osmmway *way) {
int p;
long long int nodepos;
unsigned long long int id;
struct osm_node node;
struct map_pos curpos, lastpos;
osm_mway_pmax_new (way, oway->ncnt);
way->mway->id = oway->wid;
way->mway->type = oway->type;
way->mway->flags = oway->flags;
strncpy (way->mway->name, oway->name, MAP_W_NAMELEN);
strncpy (way->mway->ref, oway->ref, MAP_W_NAMELEN);
for (p = 0; p < oway->ncnt; p++) {
/* find the node */
id = oway->nid[p];
if ((nodepos = osm_node_load (&node, id)) == -1) return;
/* check if we are still in the same AREA.. */
curpos.lon = node.lon;
curpos.lat = node.lat;
if (p > 0 &&
(map_geo2igeo (lastpos.lon) != map_geo2igeo (curpos.lon) || map_geo2igeo (lastpos.lat) != map_geo2igeo (curpos.lat))) {
/*
* save the known part of the way..
* and create a new part of the way
*/
way->mway->n[way->mway->n_cnt].d_id = way->mway->id;
way->mway->n[way->mway->n_cnt].d_subid = way->mway->subid+1;
way->mway->n[way->mway->n_cnt].d_pnr = 0;
way->mway->n[way->mway->n_cnt].pnr = way->mway->p_cnt-1;
way->mway->n[way->mway->n_cnt].d = curpos;
way->mway->n[way->mway->n_cnt].flags = 0;
way->mway->n_cnt++;
map_way_add (way->mway, MHLOAD_RELOAD);
/* prepare a new way with subid + 1 */
way->mway->n_cnt = 1;
way->mway->n[0].d_subid = way->mway->subid;
way->mway->n[0].d_id = way->mway->id;
way->mway->n[0].d = lastpos;
way->mway->n[0].d_pnr = way->mway->p_cnt-1;
way->mway->n[0].pnr = 0;
way->mway->n[0].flags = 0;
way->mway->p_cnt = 0;
way->mway->subid++;
}
/*
* add the new node to the way.. also add the way to the nodehash..
*/
way->mway->p[way->mway->p_cnt].lon = node.lon;
way->mway->p[way->mway->p_cnt].lat = node.lat;
if (way->mway->type < MWAY_MAX)
osm_waynode_add (&node, nodepos, way->mway->id, way->mway->subid, way->mway->p_cnt);
else {
d_printf ("%s:%d osm_way_save: osm_mway->type >= MWAY_MAX which should not happen, since it should call osm_area_save", __FILE__, __LINE__);
exit (1);
}
way->mway->p_cnt++;
/* save last position */
lastpos = curpos;
osm_cur_wayid = oway->wid;
main_wnd_loop(p, -2);
}
map_way_add (way->mway, MHLOAD_RELOAD);
return;
};
/******************************************************************************
* all code to save an area
*/
void osm_marea_new (struct s_osmmarea *a, int max) {
if (a->marea == NULL || max > a->pmax) {
a->marea = ml_realloc (a->marea, sizeof (struct map_area) + max * sizeof (struct map_pos));
a->pmax = max;
}
a->marea->id = 0;
a->marea->subid = 0;
a->marea->type = MAREA_unknown;
a->marea->p = (struct map_pos*) a->marea->data;
a->marea->p_cnt = 0;
};
/********************************************************************
* convert the osm "way" into the map_area type and save it into the
* hash data block. I case the way goes over more hash segments the
* way will be slit into peaces
*
* splitting into peaces does not work yet, also taking care of the
* polygons, no angles over 180°.
*
* CALL with NULL will free all unneeded memory
*/
void osm_area_save (struct osm_way *oway, struct s_osmmarea *area ) {
int ndfirst, nd; // first node, current node
int outfirstnd; // first outside node, current outside node
static char *nodestat = NULL; // array to save all some node data
static int nodestat_alloc = 0; // size of the struct
struct map_pos pos, p1; // current hash, pos
struct osm_node curnode, node; // current node, node
int sid = 0;
/* check if we just need to free all data */
if (oway == NULL) {
if (nodestat != NULL) free (nodestat);
nodestat = NULL;
nodestat_alloc = 0;
return;
}
/* basic check and allocate enought memory (if needed) */
if (oway->type == MAREA_ignore) return;
else if (oway->type == MAREA_campsite) {
struct map_poi poi;
poi.lon = 0.0;
poi.lat = 0.0;
poi.name = oway->name;
poi.additional = NULL;
poi.type = MAP_POI_campsite;
poi.next = NULL;
poi.id = 1;
for (nd = 0; nd < oway->ncnt; nd++) {
if (osm_node_load (&node, oway->nid[nd]) == -1) {
d_printf ("%s:%d osm_area_save count not find node number: %lld", __FILE__, __LINE__, oway->nid[nd]);
return;
}
poi.lon += node.lon;
poi.lat += node.lat;
}
poi.lon = poi.lon / (float) nd;
poi.lat = poi.lat / (float) nd;
map_poi_add (&poi, MHLOAD_RELOAD);
return;
}
if (oway->ncnt < 2) {
return; // a polygon needs at last 3 nodes
}
osm_marea_new (area, oway->ncnt);
/* allocate data for nodestat, and reset data */
if (nodestat_alloc < oway->ncnt) {
nodestat = ml_malloc (oway->ncnt);
nodestat_alloc = oway->ncnt;
}
memset (nodestat, 0x0, nodestat_alloc);
/*
* find the first complete hash segment and it's end
*/
do {
/* find first unused node, also the center of the area */
for (ndfirst = 0; ndfirst < oway->ncnt && nodestat[ndfirst] != 0; ndfirst++);
/*
* found an unused node so save this segment
*/
if (ndfirst < oway->ncnt) {
if (osm_node_load (&curnode, oway->nid[ndfirst]) == -1) {
d_printf ("%s:%d osm_area_save count not find node number: %lld", __FILE__, __LINE__, oway->nid[ndfirst]);
return;
}
nodestat[ndfirst] = 1;
/* save first node */
area->marea->id = oway->wid;
area->marea->subid = sid;
area->marea->type = oway->type;
area->marea->p_cnt = 1;
area->marea->p = (struct map_pos *) area->marea->data;
area->marea->p[0].lon = curnode.lon;
area->marea->p[0].lat = curnode.lat;
/* find all nodes which are inside this segment
* do preparations after this save the area */
nd = ndfirst;
outfirstnd = -1;
pos.lon = curnode.lon;
pos.lat = curnode.lat;
if (++nd >= oway->ncnt) nd = 0; /* count +1, check for overrun */
while (nd != ndfirst) {
if (osm_node_load (&node, oway->nid[nd]) == -1) {
d_printf ("%s:%d osm_area_save count not find node number: %lld",
__FILE__, __LINE__, oway->nid[nd]);
return;
}
pos.lon = node.lon;
pos.lat = node.lat;
if (outfirstnd >= 0) {
/* we are still outside, find the next inside pos */
d_printf ("%s:%d FIX ME", __FILE__, __LINE__);
exit (-1);
}
else {
/* we are inside the current node
* check and split in two if needed */
if (osm_linehashsplit (area->marea->p[area->marea->p_cnt-1], pos, &p1) > 0) {
/* node is outside the area, the border is saved at p1 */
area->marea->p_cnt++;
outfirstnd = nd;
}
else {
/* node is inside the area */
area->marea->p[area->marea->p_cnt].lon = node.lon;
area->marea->p[area->marea->p_cnt].lat = node.lat;
area->marea->p_cnt++;
nodestat[nd] = 1;
}
}
if (++nd >= oway->ncnt) nd = 0; /* count +1, check for overrun */
}
osm_area_split_add (area);
}
} while (ndfirst < oway->ncnt);
return;
};
/*
* convert area into a polygon without angles above 180°
* it saves time late in drawing on slow devices.
* only needed because of GL_TRIANGLE_STRIP and return
* last subid saved.
*/
struct s_osmareapnt {
int pnr;
fPoint km;
float angle;
float sel_dist;
float sel_angle;
};
#define MAX_SUBID 250
int osm_area_split_add (struct s_osmmarea *marea) {
/* allocate enought memory */
struct map_area *a = NULL;
struct s_osmareapnt *pt = ml_malloc (sizeof (struct s_osmareapnt) * marea->marea->p_cnt);
int i, st, pt_c, c;
int _debug = 0, rotated = 0;
float angle_sum;
// if (marea->marea->id == 22963835) _debug = 1;
// else return 1;
// d_printf ("marea: %lld cnt:%d", marea->marea->id, marea->marea->p_cnt);
// map_area_add (marea->marea, MHLOAD_RELOAD);
// return 1;
if (_debug) d_printf ("area:%lld:%d", marea->marea->id, marea->marea->subid);
a = ml_malloc (map_area_getsize (marea->marea));
map_area_copy (a, marea->marea);
/* calculate all klon, klat and prepare start struct, also
* ignore double entrys */
for (pt_c = 0, i = 0; i < marea->marea->p_cnt; i++) {
if (i == 0) st = marea->marea->p_cnt-1;
else st = i-1;
if (marea->marea->p[i].lon == marea->marea->p[st].lon
&& marea->marea->p[i].lat == marea->marea->p[st].lat) continue;
pt[pt_c].pnr = i;
pt[pt_c].angle = -1.0;
pt[pt_c].km.x = map_lon2km (marea->marea->p[i].lon, marea->marea->p[i].lat);
pt[pt_c].km.y = map_lat2km (marea->marea->p[i].lat);
if (_debug) d_printf ("pt[%-3d].pnr:%d km.x:%f km.y:%f", pt_c, pt[pt_c].pnr, pt[pt_c].km.x, pt[pt_c].km.y);
pt_c++;
}
while (pt[0].pnr >= 0 && pt_c > 2 && a->subid < MAX_SUBID) {
/* st - will keep first pt to start checking polygon
* c - count how many angles are above 180° */
if (_debug) d_printf ("**************** subid:%d pt_c:%d", a->subid, pt_c);
for (angle_sum = 0.0, st = -1, c = 0, i = 0; i < pt_c; i++) {
if (i == pt_c-1) pt[i].angle = point_angle (pt[i-1].km, pt[i].km, pt[0].km);
else if (i == 0) pt[i].angle = point_angle (pt[pt_c-1].km, pt[i].km, pt[i+1].km);
else pt[i].angle = point_angle (pt[i-1].km, pt[i].km, pt[i+1].km);
if (pt[i].angle > M_PI) { /* only select first pt */
if (st == -1) st = i;
else if (pt[st].angle < pt[i].angle) st = i;
c++;
}
angle_sum += pt[i].angle;
if (_debug) d_printf ("i:%-2d pnr:%-2d angle:%f",i, pt[i].pnr, pt[i].angle);
}
angle_sum /= (float)pt_c;
if (_debug) d_printf ("c:%d pt_c:%d st:%d angle_sum:%f",c, pt_c, st, angle_sum);
/* make sure we going counterclock direction, only first area */
if (rotated == 0 && angle_sum > M_PI && a->subid == marea->marea->subid) {
struct s_osmareapnt *pt_ = ml_malloc (sizeof (struct s_osmareapnt) * pt_c);
if (_debug) d_printf ("change rotation ...");
for (i = 0; i < pt_c; i++) pt_[pt_c - i - 1] = pt[i];
ml_free (pt);
pt = pt_;
rotated = 1;
continue;
}
/* if c==0 save last areapart */
else if (c == 0) {
a->p_cnt = 0;
for (i = 0; i < pt_c; i++) {
if (_debug) d_printf ("0: added %d pnr:%d", a->p_cnt, pt[i].pnr);
a->p[a->p_cnt++] = marea->marea->p[pt[i].pnr];
pt[i].pnr = -1;
}
map_area_add (a, MHLOAD_RELOAD);
a->subid++;
}
/* if c==1 select j as 0 then quit, if GL_TRIANGLE_STRIP gets kicked out of
* openGL we need to change this */
else if (c == 1) {
for (a->p_cnt = 0, i = st; a->p_cnt < pt_c;) {
if (_debug) d_printf ("1: added %d pnr:%d", a->p_cnt, pt[i].pnr);
a->p[a->p_cnt++] = marea->marea->p[pt[i].pnr];
pt[i].pnr = -1;
if (i < pt_c-1) i++;
else i = 0;
}
map_area_add (a, MHLOAD_RELOAD);
a->subid++;
}
/* check again for the part to split the area. */
else {
int j, sel, s, i_old, c;
float dist;
float angle;
/* check if selected start is working for us */
sel = st;
i_old = -1;
do {
/* fill up all sel_angles and sel_dists */
if (sel < pt_c-1) s = sel + 1;
else s = 0;
if (_debug) d_printf ("select %d [pnr:%d] second:%d", sel, pt[sel].pnr, s);
for (i = 0; i < pt_c; i++) {
if (i != sel) {
pt[i].sel_angle = point_angle (pt[i].km, pt[sel].km, pt[s].km);
pt[i].sel_dist = vec_len (vec_sub (pt[i].km, pt[sel].km));
}
else {
pt[i].sel_angle = -2.0;
pt[i].sel_dist = -2.0;
}
if (_debug) d_printf (" %-2d pnr:%-2d angle:%f dist:%f", i, pt[i].pnr, pt[i].sel_angle, pt[i].sel_dist);
}
a->p_cnt = 0;
a->p[a->p_cnt++] = marea->marea->p[pt[sel].pnr];
angle = 0.0;
if (_debug) d_printf (" check for possible loop: i:%d s:%d st:%d sel:%d angle:%f pt[i].sel_angle:%f", i, s, st, sel, angle, pt[i].sel_angle);
for (i_old = -1, i = s, angle = 0.0; i != sel && angle <= pt[i].sel_angle;) {
if (_debug) d_printf (" i:%d sel:%d angle:%f pt[i].sel_angle:%f", i, st, angle, pt[i].sel_angle);
for (j = i; j != sel;) {
if (_debug) d_printf (" j:%d (pnr:%d, angle:%f, dist:%f) i:%d (pnr:%d, angle:%f, dist:%f) ", j, pt[j].pnr, pt[j].sel_angle, pt[j].sel_dist, i, pt[i].pnr, pt[i].sel_angle, pt[i].sel_dist);
if (pt[i].sel_angle > pt[j].sel_angle && pt[i].sel_dist > pt[j].sel_dist) {
if (_debug) d_printf (" break 1");
break;
}
j++; if (j >= pt_c) j = 0;
}
if (j != sel) {
/* something is in the way */
if (_debug) d_printf (" break 2");
break;
}
else {
/* found something */
if (i_old >= 0) pt[i_old].pnr = -1; /* already second pass */
a->p[a->p_cnt++] = marea->marea->p[pt[i].pnr];
if (_debug) d_printf ("add nr:%d pnr:%d", a->p_cnt-1, pt[i].pnr);
angle = pt[i].sel_angle;
}
i_old = i;
i++; if (i >= pt_c) i = 0;
}
if (a->p_cnt < 3) {
/* found nothing try next one */
sel++; if (sel >= pt_c) sel = 0;
}
} while (sel != st && a->p_cnt < 3);
/* add element */
if (a->p_cnt >= 3) {
map_area_add (a, MHLOAD_RELOAD);
a->subid++;
}
}
/* recreate pall list, delete unneeded elements (pnr == -1) */
for (c = 0, i = 0; i < pt_c; i++) if (pt[i].pnr != -1) pt[c++] = pt[i];
if (pt_c == c) {
d_printf ("%s:%d pt_c == c : nothing deleted.. something went wrong.", __FILE__, __LINE__);
d_printf (" rotated:%d", rotated);
break;
}
pt_c = c;
}
if (a->subid >= MAX_SUBID) {
d_printf ("%s:%d max subid reached. area id:%lld", __FILE__, __LINE__, a->id);
}
if (pt[0].pnr >= 0 && pt_c > 2) {
d_printf ("%s:%d osm_area_split_add: something went very wrong", __FILE__, __LINE__);
d_printf (" marea->id: %lld:%d", a->id, a->subid);
d_printf (" pt[0].pnr:%d pt[1].pnr:%d pall_cnt: %d", pt[0].pnr, pt[1].pnr, pt_c);
}
/* free unneeded memory and return to caller */
ml_free (a);
ml_free (pt);
return a->subid;
};
/********************************************************************
* save detail information of the node. This will also create the
* search index.
*/
void osm_nodedetail_save (struct osm_nodedetail *onoded, struct osm_node *node) {
int i, j;
char *data;
char *var;
char *val;
data = onoded->data;
if (onoded->type == OSM_NODEDETAIL_PLACE) {
struct map_place place;
place.lon = node->lon;
place.lat = node->lat;
place.id = node->id;
place.name = NULL;
place.country = NULL;
place.state = NULL;
place.district = NULL;
place.postalcode = NULL;
place.next = NULL;
place.population = 0;
place.type = MAP_PLACE_unknown;
for (i = 0; i < onoded->elements; i++) {
var = data;
val = var + strlen (var) + 1;
data = val + strlen (val) + 1;
// d_printf ("variable:%s value:%s", var, val);
if (strcmp (var, "name") == 0) {
place.name = val;
}
else if (strcmp (var, "place") == 0) {
for (j = 0; val[j] != 0; j++)
val[j] = tolower (val[j]);
if (strcmp (val, "city") == 0) {
place.type = MAP_PLACE_city;
}
else if (strcmp (val, "suburb") == 0) {
place.type = MAP_PLACE_suburb;
}
else if (strcmp (val, "village") == 0) {
place.type = MAP_PLACE_village;
}
else if (strcmp (val, "hamlet") == 0) {
place.type = MAP_PLACE_hamlet;
}
else if (strcmp (val, "town") == 0) {
place.type = MAP_PLACE_town;
}
else {
// d_printf ("unknown place:'%s' for '%s'", val, place.name);
place.type = MAP_PLACE_unknown;
}
}
}
// d_printf ("NAME: id:%lld name:'%s' type:%d", place.id, place.name, place.type);
if (place.type != MAP_PLACE_unknown) {
map_place_add (&place, MHLOAD_RELOAD);
map_search_add (place.country, place.name, place.id, place.lon, place.lat);
}
}
else if (onoded->type == OSM_NODEDETAIL_POI) {
struct map_poi poi;
poi.lon = node->lon;
poi.lat = node->lat;
poi.id = node->id;
poi.name = NULL;
poi.additional = NULL;
poi.type = MAP_POI_unknown;
for (i = 0; i < onoded->elements; i++) {
var = data;
val = var + strlen (var) + 1;
data = val + strlen (val) + 1;
if (strcmp (var, "name") == 0) {
poi.name = val;
}
else if (strcmp (var, "highway") == 0) {
for (j = 0; val[j] != 0; j++)
val[j] = tolower (val[j]);
if (strcmp (val, "bus_stop") == 0) {
poi.type = MAP_POI_busstop;
}
}
else if (strcmp (var, "amenity") == 0) {
for (j = 0; val[j] != 0; j++)
val[j] = tolower (val[j]);
if (strcmp (val, "restaurant") == 0) {
poi.type = MAP_POI_restaurant;
}
else if (strcmp (val, "fuel") == 0) {
poi.type = MAP_POI_gasstation;
}
}
else if (strcmp (var, "tourism") == 0) {
for (j = 0; val[j] != 0; j++)
val[j] = tolower (val[j]);
if (strcmp (val, "hotel") == 0) {
poi.type = MAP_POI_hotel;
}
}
}
if (poi.type != MAP_POI_unknown && poi.name != NULL)
if (strlen (poi.name) > 0) map_poi_add (&poi, MHLOAD_RELOAD);
}
};
/*
* append to the onoded another data, this will also check the size of the allocated data
*/
void osm_nodedetail_append (struct osm_nodedetail *onoded, char *variable, char *value) {
char *data, *var, *val;
int i,j;
/* allocated memory for the data is too small */
if (onoded->allocsize == 0 || onoded->data == NULL) {
onoded->allocsize = strlen (variable) + strlen (value) + 2 + 4096;
onoded->size = 0;
onoded->data = ml_malloc (onoded->allocsize);
}
else if ((strlen (variable) + strlen (value) + 2 + onoded->size) >= onoded->allocsize) {
char *olddata;
int oldsize;
olddata = onoded->data;
oldsize = onoded->allocsize;
onoded->allocsize += (strlen (variable) + strlen (value) + 2 + 4096);
onoded->data = ml_malloc (onoded->allocsize);
memcpy (onoded->data, olddata, oldsize);
ml_free (olddata);
}
/* go to the last element and save data */
data = onoded->data + onoded->size;
var = data;
for (i = 0; i < strlen (variable); i++)
data[i] = tolower (variable[i]);
data[i] = '\0';
data = data + i + 1;
val = data;
for (j = 0; j < strlen (value); j++)
data[j] = value[j];
data[j] = '\0';
onoded->size = onoded->size + j + i + 2;
if (strncmp (var, "place", 6) == 0) {
onoded->type = OSM_NODEDETAIL_PLACE;
}
if (strncmp (var, "highway", 8) == 0 && strncmp (val, "bus_stop", 9) == 0) {
onoded->type = OSM_NODEDETAIL_POI;
}
if (strncmp (var, "amenity", 8) == 0) {
onoded->type = OSM_NODEDETAIL_POI;
}
if (strncmp (var, "tourism", 8) == 0) {
onoded->type = OSM_NODEDETAIL_POI;
}
onoded->elements++;
};
/***************************************************************************
* read a osmxml file,
*/
#define XML_TEXTLEN 256
void osm_processdata (xmlTextReaderPtr reader) {
const xmlChar *name, *attr, *k, *v;
static int xmlolddepth = -1;
int xmldepth;
char *cid;
unsigned long long int id;
static struct osm_node onode;
static struct osm_nodedetail onoded;
struct osm_way *tmpoway = NULL;
static void *last = NULL;
if (xmlolddepth == -1) {
onode.id = 0;
onoded.data = NULL;
onoded.allocsize = 0;
onoded.size = 0;
onoded.elements = 0;
onoded.type = OSM_NODEDETAIL_NONE;
if (osm.oway != NULL) {
osm.oway->type = MWAY_unknown;
osm.oway->wid = 0;
osm.oway->ncnt = 0;
}
else {
osm.oway = osm_way_alloc (32);
}
last = NULL;
}
name = xmlTextReaderConstName(reader);
if (name == NULL)
name = BAD_CAST "--";
/* check if we need to save the data.. */
cid = (char*) xmlTextReaderGetAttribute (reader, (xmlChar*)"id");
if (cid) {
id = atoll (cid);
free (cid);
}
else id = 0;
xmldepth = xmlTextReaderDepth (reader);
if (xmldepth == 1 && (strncmp ((char*) name, "#text", 6) == 0)) {
/*
* save data
*/
if (last == (void*) osm.oway) {
if (osm.oway->type >= MWAY_MAX) {
osm.oway->type -= MWAY_MAX;
osm_area_cnt++;
if (osm.oway->type != MAREA_ignore) osm_area_save (osm.oway, &osm.area);
}
else {
osm_ways_cnt++;
osm_way_save (osm.oway, &osm.way);
}
}
else if (last == (void*) &onode) {
/* add the current node */
osm_nodes_cnt++;
osm_node_append (onode);
if (onoded.type != OSM_NODEDETAIL_NONE)
osm_nodedetail_save (&onoded, &onode);
}
onode.id = 0;
onode.waynode = 0;
onoded.type = OSM_NODEDETAIL_NONE;
onoded.size = 0;
onoded.elements = 0;
osm.oway->wid = 0;
osm.oway->type = MWAY_MAX + MAREA_ignore;
osm.oway->ncnt = 0;
osm.oway->name[0] = 0;
osm.oway->ref[0] = 0;
osm.oway->flags = 0;
last = NULL;
}
/*
* check and process date for a node
*/
if (strncmp ((char*) name, (char*) "node",5) == 0) { // it's a node
if (id == 0) return;
onode.id = id;
// d_printf ("xml.. node: %lld\n", onode.id);
attr = xmlTextReaderGetAttribute (reader, (xmlChar*)"lat"); // lat
if (attr == NULL) return;
sscanf ((char*)attr , "%g", &onode.lat);
free ((void *)attr);
attr = xmlTextReaderGetAttribute (reader, (xmlChar*)"lon"); // lon
if (attr == NULL) return;
sscanf ((char*)attr, "%g", &onode.lon);
free ((void *)attr);
xmlolddepth = xmldepth;
last = (void*)&onode;
}
else if ((strncmp ((char*) name, (char*) "tag", 3) == 0) && last == (void*)&onode) { // tag to a node?
k = xmlTextReaderGetAttribute (reader, (xmlChar*)"k");
if (k == NULL) return;
v = xmlTextReaderGetAttribute (reader, (xmlChar*)"v");
if (v == NULL) {
free ((void *)k);
return;
}
onoded.id = onode.id;
osm_nodedetail_append (&onoded, (char*)k, (char*)v);
free ((void *)k);
free ((void *)v);
}
/*
* check and process data for way or an area
*/
else if (strncmp ((char*) name, (char*) "way",4) == 0) { // it's a way
if (id == 0) return;
osm.oway->wid = id;
xmlolddepth = xmldepth;
last = (void*)osm.oway;
}
else if ((strncmp ((char*) name, (char*) "tag", 3) == 0) && last == (void*)osm.oway) { // tag to a way?
k = xmlTextReaderGetAttribute (reader, (xmlChar*)"k");
if (k == NULL) return;
v = xmlTextReaderGetAttribute (reader, (xmlChar*)"v");
if (v == NULL) {
free ((void *)k);
return;
}
if (strncmp ((char*) k, (char*) "highway", 8) == 0) {
if (strcmp ((char*) v, (char*) "primary") == 0) osm.oway->type = MWAY_tertiary;
else if (strcmp ((char*) v, (char*) "primary_link") == 0) {
osm.oway->type = MWAY_tertiary;
osm.oway->flags |= MWAY_F_junction;
}
else if (strcmp ((char*) v, (char*) "tertiary") == 0) osm.oway->type = MWAY_tertiary;
else if (strcmp ((char*) v, (char*) "secondary") == 0) osm.oway->type = MWAY_tertiary;
else if (strcmp ((char*) v, (char*) "motorway") == 0) osm.oway->type = MWAY_highway;
else if (strcmp ((char*) v, (char*) "motorway_link") == 0) {
osm.oway->type = MWAY_highway;
osm.oway->flags |= MWAY_F_junction;
}
else if (strcmp ((char*) v, (char*) "trunk") == 0) osm.oway->type = MWAY_highway;
else if (strcmp ((char*) v, (char*) "trunk_link") == 0) {
osm.oway->type = MWAY_highway;
osm.oway->flags |= MWAY_F_junction;
}
else if (strcmp ((char*) v, (char*) "residential") == 0) osm.oway->type = MWAY_residential;
else if (strcmp ((char*) v, (char*) "living_street") == 0) osm.oway->type = MWAY_residential;
else if (strcmp ((char*) v, (char*) "road") == 0) osm.oway->type = MWAY_residential;
else if (strcmp ((char*) v, (char*) "unclassified") == 0) osm.oway->type = MWAY_residential;
else if (strcmp ((char*) v, (char*) "path") == 0) osm.oway->type = MWAY_residential;
else if (strcmp ((char*) v, (char*) "construction") == 0) osm.oway->type = MWAY_residential;
else if (strcmp ((char*) v, (char*) "cycleway") == 0) osm.oway->type = MWAY_cycleway;
else if (strcmp ((char*) v, (char*) "track") == 0) osm.oway->type = MWAY_railway;
else if (strcmp ((char*) v, (char*) "service") == 0) osm.oway->type = MWAY_service;
else if (strcmp ((char*) v, (char*) "platform") == 0) osm.oway->type = MWAY_footway;
else if (strcmp ((char*) v, (char*) "footway") == 0) osm.oway->type = MWAY_footway;
else if (strcmp ((char*) v, (char*) "pedestrian") == 0) osm.oway->type = MWAY_footway;
else if (strcmp ((char*) v, (char*) "steps") == 0) osm.oway->type = MWAY_footway;
else {
osm.oway->type = MWAY_unknown_way;
printf ("unknown highway:'%s'\n", v);
}
}
/*
* check if it is a railway
*/
else if (strncmp ((char*) k, (char*) "railway", 8) == 0) {
if (strcmp ((char*) v, (char*) "rail") == 0) {
osm.oway->flags = osm.oway->flags | MWAY_F_railway;
if (osm.oway->type == MWAY_unknown || osm.oway->type == MWAY_unknown_railway)
osm.oway->type = MWAY_railway;
}
else if (strcmp ((char*) v, (char*) "abandoned") == 0) {
osm.oway->flags = osm.oway->flags | MWAY_F_railway;
if (osm.oway->type == MWAY_unknown || osm.oway->type == MWAY_unknown_railway) osm.oway->type = MWAY_unknown_railway;
}
else {
osm.oway->flags = osm.oway->flags | MWAY_F_railway;
// d_printf ("unknown railway:'%s' name:%s type:%d id:%lld", v, osm.oway->name, osm.oway->type, osm.oway->wid);
if (osm.oway->type == MWAY_unknown || osm.oway->type == MWAY_unknown_railway)
osm.oway->type = MWAY_unknown_railway;
}
}
/*
* name ?
*/
else if (strncmp ((char*) k, (char*) "name", 5) == 0) {
strncpy (osm.oway->name, (char*)v, MAP_W_NAMELEN);
}
/*
* ref ?
*/
else if (strncmp ((char*) k, (char*) "ref", 4) == 0) {
strncpy (osm.oway->ref, (char*)v, MAP_W_NAMELEN);
}
/*
* one way ?
*/
else if (strncmp ((char*) k, (char*) "oneway", 7) == 0) {
if (strcmp ((char*) v, (char*) "yes") == 0)
osm.oway->flags = osm.oway->flags | MWAY_F_oneway;
}
/*
* junction ?
*/
else if (strncmp ((char*) k, (char*) "junction", 9) == 0) {
if (strcmp ((char*) v, (char*) "roundabout") == 0)
osm.oway->flags |= MWAY_F_roundabout;
}
/*
* construction ?
*/
else if (strncmp ((char*) k, (char*) "construction", 13) == 0) {
osm.oway->flags |= MWAY_F_planed;
}
/*
* check if we have an area
*/
else if (strncmp ((char*) k, (char*) "natural", 8) == 0 || strncmp ((char*) k, (char*) "landuse", 8) == 0) {
if (strcmp ((char*) v, (char*) "water") == 0) osm.oway->type = MAREA_water;
else if (strcmp ((char*) v, (char*) "industrial") == 0) osm.oway->type = MAREA_industrial;
else if (strcmp ((char*) v, (char*) "heath") == 0) osm.oway->type = MAREA_industrial;
else if (strcmp ((char*) v, (char*) "construction") == 0) osm.oway->type = MAREA_industrial;
else if (strcmp ((char*) v, (char*) "commercial") == 0) osm.oway->type = MAREA_commercial;
else if (strcmp ((char*) v, (char*) "retail") == 0) osm.oway->type = MAREA_commercial;
else if (strcmp ((char*) v, (char*) "cemetery") == 0) osm.oway->type = MAREA_commercial;
else if (strcmp ((char*) v, (char*) "farm") == 0) osm.oway->type = MAREA_farm;
else if (strcmp ((char*) v, (char*) "field") == 0) osm.oway->type = MAREA_farm;
else if (strcmp ((char*) v, (char*) "farmland") == 0) osm.oway->type = MAREA_farm;
else if (strcmp ((char*) v, (char*) "farmyard") == 0) osm.oway->type = MAREA_farm;
else if (strcmp ((char*) v, (char*) "village_green") == 0) osm.oway->type = MAREA_greenfield;
else if (strcmp ((char*) v, (char*) "greenfield") == 0) osm.oway->type = MAREA_greenfield;
else if (strcmp ((char*) v, (char*) "grass") == 0) osm.oway->type = MAREA_greenfield;
else if (strcmp ((char*) v, (char*) "residential") == 0) osm.oway->type = MAREA_residential;
else if (strcmp ((char*) v, (char*) "allotments") == 0) osm.oway->type = MAREA_residential;
else if (strcmp ((char*) v, (char*) "forest") == 0) osm.oway->type = MAREA_wood;
else if (strcmp ((char*) v, (char*) "meadow") == 0) osm.oway->type = MAREA_wood;
else if (strcmp ((char*) v, (char*) "wood") == 0) osm.oway->type = MAREA_wood;
else if (strcmp ((char*) v, (char*) "land") == 0) osm.oway->type = MAREA_land;
else if (strcmp ((char*) v, (char*) "military") == 0) osm.oway->type = MAREA_military;
else if (strcmp ((char*) v, (char*) "basin") == 0) osm.oway->type = MAREA_water;
else if (strcmp ((char*) v, (char*) "reservoir") == 0) osm.oway->type = MAREA_water;
else if (strcmp ((char*) v, (char*) "-----") == 0) osm.oway->type = MAREA_ignore;
else {
osm.oway->type = MAREA_ignore;
// d_printf ("unknown natural+landuse:'%s'", v);
}
osm.oway->type += MWAY_MAX;
}
else if (strncmp ((char*) k, (char*) "boundary", 8) == 0 && strcmp ((char *) v, (char *) "yes") == 0) {
osm.oway->type = MAREA_ignore + MWAY_MAX;
}
else if (strncmp ((char*) k, (char*) "man made", 8) == 0 && strcmp ((char *) v, (char *) "pipeline") == 0) {
osm.oway->type = MAREA_ignore + MWAY_MAX;
}
else if (strncmp ((char*) k, (char*) "building", 8) == 0 && strcmp ((char *) v, (char *) "yes") == 0) {
osm.oway->type = MAREA_ignore + MWAY_MAX;
}
else if (strncmp ((char*) k, (char*) "tourism", 8) == 0 && strcmp ((char *) v, (char *) "camp_site") == 0) {
osm.oway->type = MAREA_campsite + MWAY_MAX;
}
free ((void *)k);
free ((void *)v);
}
else if ((strncmp ((char*) name, (char*) "nd", 3) == 0) && last == (void*)osm.oway) { // node to a way?
attr = xmlTextReaderGetAttribute (reader, (xmlChar*)"ref");
if (attr == NULL) return;
id = atoll ((char*)attr);
free ((void *)attr);
if (osm.oway->ncnt+1 > osm.oway->nmax) {
tmpoway = osm_way_alloc (osm.oway->nmax+16);
osm_way_copy (tmpoway, osm.oway);
ml_free (osm.oway);
osm.oway = tmpoway;
}
osm.oway->nid[osm.oway->ncnt] = id;
osm.oway->ncnt++;
last = osm.oway;
}
else if (xmldepth == 1) {
xmlolddepth = xmldepth;
last = NULL;
}
};
int osm_loadfile_readcallback (void *context, char *buffer, int len) {
int bzerr, bzlen;
struct s_osm_xmlcallback *xmlcb = (struct s_osm_xmlcallback*) context;
static int loopcnt;
if (++loopcnt > 100) {
xmlcb->filepos = ftell (xmlcb->f) / 1000;
osm_file_pos = (100.0 * (float)(xmlcb->filepos) / (float)(xmlcb->filesize));
loopcnt = 0;
}
bzlen = BZ2_bzRead (&bzerr, xmlcb->bzf, buffer, len);
if (bzerr == BZ_STREAM_END && !feof(xmlcb->f)) {
/* next data stream */
unsigned char unused[BZ_MAX_UNUSED];
unsigned char *unusedTmp;
int nUnused = 0;
BZ2_bzReadGetUnused (&bzerr, xmlcb->bzf, (void**) &unusedTmp, &nUnused);
if (nUnused > 0) memcpy (unused, unusedTmp, nUnused);
BZ2_bzReadClose (&bzerr, xmlcb->bzf);
xmlcb->bzf = BZ2_bzReadOpen(&bzerr, xmlcb->f, 0, 0, unused, nUnused);
}
if (bzerr != BZ_OK) d_printf ("%s:%d bzread: should:%d is:%d filepos:%d error:%d", __FILE__, __LINE__, bzlen, len, xmlcb->filepos, bzerr);
if (bzerr == BZ_CONFIG_ERROR) d_printf ("BZ_CONFIG_ERROR");
else if (bzerr == BZ_PARAM_ERROR) d_printf ("BZ_PARAM_ERROR");
else if (bzerr == BZ_IO_ERROR) d_printf ("BZ_IO_ERROR");
else if (bzerr == BZ_MEM_ERROR) d_printf ("BZ_MEM_ERROR");
else if (bzerr == BZ_SEQUENCE_ERROR) d_printf ("BZ_SEQUENCE_ERROR");
else if (bzerr == BZ_DATA_ERROR) d_printf ("BZ_DATA_ERROR");
else if (bzerr == BZ_DATA_ERROR_MAGIC) d_printf ("BZ_DATA_ERROR_MAGIC");
else if (bzerr == BZ_UNEXPECTED_EOF) d_printf ("BZ_UNEXPECTED_EOF");
else if (bzerr != BZ_OK) d_printf ("any other bz error is there:%d", bzerr);
return bzlen;
};
int osm_loadfile_closecallback(void *context) {
int bzerr;
BZ2_bzReadClose(&bzerr, ((struct s_osm_xmlcallback *)context)->bzf);
return bzerr == BZ_OK;
};
void osm_loadfile (char *fn) {
xmlTextReaderPtr reader;
struct s_osm_xmlcallback xmlcb;
int ret, compressed, i, timeout_cnt = 0, bzerr;
time_t timeout;
char ext[16];
osm_init ();
if (fn == NULL) return;
app_status (-1, _("converting file"), 0.0);
d_printf ("osm_loadfile (%s)", fn);
/* check the extension of the osm file */
for (i = 0; i < 15 && fn[i+strlen(fn)-4] != 0; i++)
ext[i] = tolower (fn[i+strlen(fn)-4]);
ext[i] = 0;
if (strncmp (ext, ".bz2", 5) == 0) compressed = 1;
else compressed = 0;
/* set the locale to POSIX, needed for decimal numbers. */
setlocale(LC_ALL, "C");
if (compressed) {
xmlcb.f = fopen (fn, "r");
if (!xmlcb.f) {
d_printf ("%s:%d could not open file '%s' for reading. Error:%s", __FILE__, __LINE__, fn, strerror (errno));
return;
}
fseek (xmlcb.f, 0, SEEK_END);
xmlcb.filesize = ftell (xmlcb.f) / 1000;
fseek (xmlcb.f, 0, SEEK_SET);
xmlcb.bzf = BZ2_bzReadOpen(&bzerr, xmlcb.f, 0, 0, NULL, 0);
if (xmlcb.bzf == NULL || bzerr != BZ_OK) {
d_printf ("%s:%d osm_loadfile could not open source file.", __FILE__, __LINE__);
exit (0);
}
reader = xmlReaderForIO(osm_loadfile_readcallback, osm_loadfile_closecallback, &xmlcb, "", NULL, 0);
}
else reader = xmlReaderForFile(fn, NULL, 0);
/*
* read the whole file...
*/
if (reader != NULL) {
ret = xmlTextReaderRead(reader);
while (ret == 1) {
osm_processdata(reader);
ret = xmlTextReaderRead(reader);
if (++timeout_cnt > 1000 || timeout < time(NULL)) {
if (compressed)
main_wnd_loop(xmlcb.filepos, xmlcb.filesize);
else
main_wnd_loop(xmlTextReaderGetParserLineNumber (reader), -1);
timeout = time(NULL);
timeout_cnt = 0;
}
}
xmlFreeTextReader(reader);
}
if (compressed) {
fclose (xmlcb.f);
}
/* check data inside the hash for waynodes */
osm_waynodes_check ();
/* reset the locale setting back to the environment setting */
setlocale (LC_ALL, NULL);
osm_free ();
app_status (-1, _(""), 0.0);
};
#define MLWEBMAX 10
void map_load_web (struct map_pos hs, struct map_pos he) {
char parm1[128];
char parm2[128];
char cmd[255];
char url[128];
char *args[13];
int ret, i;
float x1, y1;
struct stat sb;
struct map_pos h;
struct {
struct s_execcall p;
char fcache[LEN_FILENAME];
} wl[MLWEBMAX];
d_printf ("map_load_web: (%f , %f) --> (%f , %f)", hs.lon, hs.lat, he.lon, he.lat);
/* check for cache directory */
if (stat(cfg.cachepath, &sb) == -1) {
char fn[LEN_FILENAME];
strncpy (fn, cfg.cachepath, LEN_FILENAME);
fn[strlen(fn)-1] = 0;
d_printf ("create cache dir:%s", fn);
#if !defined(__MINGW32CE__) && !defined(_WIN32_WCE) && !defined(__MINGW32__)
mkdir (fn, 0755);
#else
mkdir (fn);
#endif
}
app.status = APPSTATUS_loadfromweb;
#if defined (_LINUX_)
osm_load_from_web_end = he;
osm_load_from_web_start = hs;
app_status (-1, _("refresh from OpenStreetMap.org"), 0.0);
for (ret = 0; ret < MLWEBMAX; ret++) wl[ret].p.used = 0;
for (ret = 0; ret < 13; ret++) args[ret] = NULL;
for (h.lon = hs.lon; h.lon < he.lon || cmpf(h.lon, he.lon); h.lon = h.lon + MAP_OSMWEB_DELTA)
for (h.lat = hs.lat; h.lat < he.lat || cmpf(h.lat, he.lat); h.lat = h.lat + MAP_OSMWEB_DELTA) {
do {
main_wnd_loop (-1,-1);
/* check for any finished forked processes
* if so, call osm_loadfile */
for (i = 0; i < MLWEBMAX; i++) {
if (wl[i].p.used) {
ret = execwait (&wl[i].p);
if (ret == 1) {
osm_loadfile (wl[i].fcache);
app_status (-1, _("refresh from OpenStreetMap.org"), 0.0);
main_wnd_update ();
}
}
}
for (i = 0; i < MLWEBMAX && wl[i].p.used == 1; i++);
}
while (i >= MLWEBMAX); /* exit if we can fork another process */
y1 = CALC_START (h.lon, MAP_OSMWEB_DELTA);
x1 = CALC_START (h.lat, MAP_OSMWEB_DELTA);
setlocale(LC_ALL, "C");
sprintf (wl[i].fcache, "%s/c%.4f-%.4f-%.4f-%.4f.osm", cfg.cachepath, y1-MAP_OSMWEB_DELTA, x1-MAP_OSMWEB_DELTA, y1+MAP_OSMWEB_DELTA, x1+MAP_OSMWEB_DELTA);
if (stat(wl[i].fcache, &sb) == -1) {
setlocale(LC_ALL, "C");
sprintf (cmd, "/usr/bin/wget");
args[0] = cmd;
sprintf (parm1, "-O");
args[1] = parm1;
sprintf (parm2, "%s", wl[i].fcache);
args[2] = parm2;
sprintf (url, "http://api.openstreetmap.org/api/0.6/map?bbox=%.5f,%.5f,%.5f,%.5f", y1-MAP_OSMWEB_DELTA, x1-MAP_OSMWEB_DELTA, y1+MAP_OSMWEB_DELTA, x1+MAP_OSMWEB_DELTA);
args[3] = url;
setlocale(LC_ALL, NULL);
ret = execcall(&wl[i].p, cmd, args);
}
else {
osm_loadfile (wl[i].fcache);
main_wnd_update ();
}
}
do {
main_wnd_loop (-1,-1);
for (i = 0; i < MLWEBMAX; i++) {
if (wl[i].p.used) {
ret = execwait (&wl[i].p);
if (ret == 1) {
osm_loadfile (wl[i].fcache);
main_wnd_update ();
}
}
}
for (ret = 0, i = 0; i < MLWEBMAX; i++)
if (wl[i].p.used == 1) ret = 1;
}
while (ret);
#endif
app.status = APPSTATUS_nothing;
};
/***************************************************
* displaying some informations on the screen
*/
#ifdef HAVE_NCURSES
#include <curses.h>
void osm_convert_info () {
int i;
attrset(A_BOLD | COLOR_PAIR(3));
mvprintw(6,10, "OSM HashNodes Information");
attrset(COLOR_PAIR(3));
for (i = 0; i < 16; i++)
mvprintw(7+i,1, "hid: hash: nodes: kb");
attrset(A_BOLD | COLOR_PAIR(2));
for (i = 0; i < 16 && i < OSM_HASHNODES; i++) {
if (hashnodes[i] == NULL) continue;
mvprintw(7+i,5, "%d", hashnodes[i]->hid);
mvprintw(7+i,15, "%d", hashnodes[i]->hash_cnt);
mvprintw(7+i,31, "%d", hashnodes[i]->nodes_end/1024);
if (hashnodes[i]->hash) mvprintw(7+i, 0, "*");
else mvprintw(7+i, 0, " ");
}
}
#endif