diff --git a/ChangeLog b/ChangeLog index 7f40215..63a497a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,17 @@ Version 0.0.2: name changed to spOSMroute, since on there had been another OSMroute already. ============================================================================= +(2013-05-02): +- fixed: areas haven't been updated right. + +- added: areas have subid now. + +- changed: saving subid within the id by shifting bits to the left. + saving 2 bytes each way. + +- fixed: areas get split into different parts on each inside angle above 180° + should fix displaying issues on opengl and opengles devices. + (2013-03-11): - rewrote most parts of the gui handling. diff --git a/base/vector.c b/base/vector.c index 75510cd..a59c1bc 100644 --- a/base/vector.c +++ b/base/vector.c @@ -21,6 +21,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include "osmroute.h" #include "vector.h" @@ -108,3 +109,23 @@ fPoint vec_mul (fPoint v, float f) { a.y = f * v.y; return a; }; + + +/* calc angle of three points assuming v2 is the center.. */ +float point_angle (fPoint v1, fPoint v2, fPoint v3) { + float a1; + float a3; + float delta; + + v1 = vec_sub (v1, v2); + v3 = vec_sub (v3, v2); + a1 = atan2f (v1.y, v1.x); + a3 = atan2f (v3.y, v3.x); + + if (a1 < 0.0) a1 += 2.0*M_PI; + if (a3 < 0.0) a3 += 2.0*M_PI; + if ((delta = a1-a3) < 0.0) delta += 2.0*M_PI; + + return delta; +}; + diff --git a/base/vector.h b/base/vector.h index 45c423e..0c5e357 100644 --- a/base/vector.h +++ b/base/vector.h @@ -35,4 +35,6 @@ extern fPoint vec_mirror (fPoint veca); extern float vec_len (fPoint veca); extern fPoint vec_mul (fPoint v, float f); +extern float point_angle (fPoint v1, fPoint v2, fPoint v3); + #endif diff --git a/doc/TechDoc.odt b/doc/TechDoc.odt index 6d6f97f..a07eacf 100644 Binary files a/doc/TechDoc.odt and b/doc/TechDoc.odt differ diff --git a/draw/draw.c b/draw/draw.c index 9c43a65..1d479fc 100644 --- a/draw/draw.c +++ b/draw/draw.c @@ -479,12 +479,19 @@ void draw_map () { carea = mh->areas; while (carea) { if (draw_type[carea->type + MWAY_MAX]) { - draw_polygonstart (); + draw_polygonstart (); for (n = 0; n < carea->p_cnt; n++) if (n == 0 || n == carea->p_cnt-1 || view_scale < 0.01 || ((view_scale < 0.1 && (n % 2) == 0) || carea->p_cnt < 5) || ((view_scale < 0.1 && (n % 4) == 0) || carea->p_cnt < 10)) { p1 = draw_geo2screen (view_lon, view_lat, carea->p[n].lon, carea->p[n].lat); + // if (n == 0) { + // draw_line (img_map, p1.x + center.x - 5, p1.y + center.y - 5, p1.x + center.x + 5, p1.y + center.y + 5, tmplinestyle); + // draw_line (img_map, p1.x + center.x + 5, p1.y + center.y - 5, p1.x + center.x - 5, p1.y + center.y + 5, tmplinestyle); + // } + // if (n == 0) sprintf (text, "%d:%d", n, carea->subid); + // else sprintf (text, "%d", n); + // gfx_draw_text (img_map, p1.x + center.x - 20, p1.y + center.y - 10, text, &color[COLOR_white][3]); draw_polygonadd (p1.x + center.x, p1.y + center.y); } draw_polygonfinish (img_map, tmplinestyle, &color_polygon[carea->type], 0); @@ -494,12 +501,11 @@ void draw_map () { } } - /* * draw ways */ /* draw outside */ - for (h.ilon = hs.ilon; h.ilon <= he.ilon; h.ilon++) + for (h.ilon = hs.ilon; h.ilon <= he.ilon; h.ilon++) for (h.ilat = hs.ilat; h.ilat <= he.ilat; h.ilat++) { /* * draw the hash.. @@ -573,7 +579,7 @@ void draw_map () { } /* ways inside */ - for (h.ilon = hs.ilon; h.ilon <= he.ilon; h.ilon++) + for (h.ilon = hs.ilon; h.ilon <= he.ilon; h.ilon++) for (h.ilat = hs.ilat; h.ilat <= he.ilat; h.ilat++) { /* * draw the hash.. @@ -679,7 +685,6 @@ void draw_map () { } } - /* * draw places, pois just on top layers */ diff --git a/mapsys/map.h b/mapsys/map.h index 6f1007c..5a15783 100644 --- a/mapsys/map.h +++ b/mapsys/map.h @@ -44,7 +44,7 @@ #define MAP_LSSTAT_MAX 128 #endif #define MAP_LSSIZE_HASH 28 -#define MAP_LSSIZE_WAY 16 +#define MAP_LSSIZE_WAY 14 #define MAP_LSSIZE_WAYNODE 23 #define MAP_LSSIZE_POS 8 #define MAP_LSSIZE_AREA 12 @@ -176,6 +176,7 @@ struct map_way { struct map_area { char status; unsigned long long int id; + unsigned short int subid; unsigned char type; unsigned char flags; diff --git a/mapsys/map_area.c b/mapsys/map_area.c index 15409bd..66a865d 100644 --- a/mapsys/map_area.c +++ b/mapsys/map_area.c @@ -39,11 +39,18 @@ int map_area_add_to_hash (struct map_hash *mh, struct map_area *ma) { int size; struct map_area *a; + /* check if the first element is already the one we want to update */ + if (mh->areas && mh->areas->id == ma->id && mh->areas->subid == ma->subid) { + mh->areas = mh->areas->next; + mh->areascnt--; + } + + /* find possible update and go to the end */ if (mh->areas) { /* find last way */ a = mh->areas; while (a && a->next) { - if (a->next->id == ma->id) { + if (a->next->id == ma->id && a->next->subid == a->subid) { /* found old way.. just delete .. */ a->next = a->next->next; mh->areascnt--; @@ -85,6 +92,8 @@ int map_area_add (struct map_area *area, int loadflags) { int size; if (area->p == NULL || area->p_cnt == 0) return 0; +// area->type = area->subid % MAREA_campsite + 1; +// d_printf ("subid:%d type:%d cnt:%d", area->subid, area->type, area->p_cnt); size = map_area_getsize (area); mh = map_hash_get (area->p[0].lon, area->p[0].lat, loadflags); @@ -110,6 +119,7 @@ void map_area_copy (struct map_area *dest, struct map_area *src) { int i; dest->id = src->id; + dest->subid = src->subid; dest->type = src->type; dest->p_cnt = src->p_cnt; dest->p = (struct map_pos*) (dest->data); diff --git a/mapsys/map_loadsave.c b/mapsys/map_loadsave.c index 52cdeab..f55ea5c 100644 --- a/mapsys/map_loadsave.c +++ b/mapsys/map_loadsave.c @@ -38,6 +38,8 @@ #include "memoryleak.h" #include "osmroute.h" +#define MAP_BITS_SUBID 5 + char *lsrw_data = NULL; int lsrw_data_size = 0; char *lshash_data = NULL; @@ -576,9 +578,8 @@ char *map_ls_hash2data (struct map_hash *mh, int *size) { /* save the basic data */ ui64 = mw->id; /* id */ + ui64 = (ui64 << MAP_BITS_SUBID) | mw->subid; woutpos = mempush (woutpos, &ui64, 8); - ui16 = mw->subid; /* subid */ - woutpos = mempush (woutpos, &ui16, 2); ui8 = mw->type; /* type */ woutpos = mempush (woutpos, &ui8, 1); ui8 = mw->flags; /* flags */ @@ -644,7 +645,7 @@ char *map_ls_hash2data (struct map_hash *mh, int *size) { map_ls_hashdatacheckpos (*size, &woutpos); /* save the basic data */ - ui64 = ma->id; /* id */ + ui64 = (ma->id << MAP_BITS_SUBID) | ma->subid; /* id */ woutpos = mempush (woutpos, &ui64, 8); ui8 = ma->type; /* type */ woutpos = mempush (woutpos, &ui8, 1); @@ -839,9 +840,8 @@ struct map_hash *map_ls_data2hash (char *data, int size) { for (cnt = 0; cnt < lsh.ways; cnt++) { /* load basic data */ inpos = mempop (inpos, &ui64, 8); - way->id = ui64; - inpos = mempop (inpos, &ui16, 2); - way->subid = ui16; + way->subid = ui64 % (1<id = (ui64 >> MAP_BITS_SUBID); inpos = mempop (inpos, &ui8, 1); way->type = ui8; inpos = mempop (inpos, &ui8, 1); @@ -914,6 +914,7 @@ struct map_hash *map_ls_data2hash (char *data, int size) { area->next = NULL; inpos = mempop (inpos, &ui64, 8); + area->subid = ui64 % (1<id = ui64; inpos = mempop (inpos, &ui8, 1); area->type = ui8; diff --git a/mapsys/map_osmload.c b/mapsys/map_osmload.c index 1c28f56..7c1f97c 100644 --- a/mapsys/map_osmload.c +++ b/mapsys/map_osmload.c @@ -34,6 +34,7 @@ #include "map.h" #include "system.h" #include "memoryleak.h" +#include "vector.h" #include #include @@ -190,6 +191,7 @@ void osm_waynodes_checknode (struct s_osm_hashnodes *nhash, struct osm_node *nod 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); @@ -696,7 +698,8 @@ void osm_waynode_add (struct osm_node *node, long long int nodepos, unsigned lon 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); + d_printf ("%s:%d could not read data from file:%s pos:%d", __FILE__, __LINE__, + hnodes->fnnodes, hash.pos); errorexit (-1); } wpos = wn.next; @@ -707,7 +710,8 @@ void osm_waynode_add (struct osm_node *node, long long int nodepos, unsigned lon 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); + d_printf ("%s:%d could not write data to file:%s pos:%d", __FILE__, __LINE__, + hnodes->fnnodes, hash.pos); errorexit (-1); } } @@ -719,7 +723,6 @@ void osm_waynode_add (struct osm_node *node, long long int nodepos, unsigned lon d_printf ("%s:%d could not read data from file:%s pos:%d", __FILE__, __LINE__, hnodes->fnnodes, hash.pos); errorexit (-1); } - return; }; @@ -741,7 +744,8 @@ void osm_waynodes_check () { /* 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); + 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); @@ -777,7 +781,8 @@ void osm_waynodes_checknode (struct s_osm_hashnodes *ohash, struct osm_node *nod 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); + 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); @@ -1036,6 +1041,7 @@ void osm_area_save (struct osm_way *oway, struct s_osmmarea *area ) { 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) { @@ -1105,6 +1111,7 @@ void osm_area_save (struct osm_way *oway, struct s_osmmarea *area ) { /* 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; @@ -1120,7 +1127,8 @@ void osm_area_save (struct osm_way *oway, struct s_osmmarea *area ) { 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]); + d_printf ("%s:%d osm_area_save count not find node number: %lld", + __FILE__, __LINE__, oway->nid[nd]); return; } pos.lon = node.lon; @@ -1150,7 +1158,7 @@ void osm_area_save (struct osm_way *oway, struct s_osmmarea *area ) { } if (++nd >= oway->ncnt) nd = 0; /* count +1, check for overrun */ } - map_area_add (area->marea, MHLOAD_RELOAD); + osm_area_split_add (area); } } while (ndfirst < oway->ncnt); @@ -1158,6 +1166,196 @@ void osm_area_save (struct osm_way *oway, struct s_osmmarea *area ) { }; +/* + * 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; +}; + + +int osm_area_split_add (struct s_osmmarea *marea) { + /* allocate enought memory */ + struct map_area *a = NULL; + struct s_osmareapnt *pall = ml_malloc (sizeof (struct s_osmareapnt) * marea->marea->p_cnt); + int pall_cnt = marea->marea->p_cnt; + int i, j, c, k, smaller; + int _debug = 0; + +// if (marea->marea->id == 29225778) _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 (c = 0, i = 0; i < marea->marea->p_cnt; i++) { + if (i == 0) j = marea->marea->p_cnt-1; + else j = i-1; + + if (marea->marea->p[i].lon == marea->marea->p[j].lon + && marea->marea->p[i].lat == marea->marea->p[j].lat) continue; + + pall[c].pnr = i; + pall[c].km.x = map_lon2km (marea->marea->p[i].lon, marea->marea->p[i].lat); + pall[c].km.y = map_lat2km (marea->marea->p[i].lat); + c++; + } + pall_cnt = c; + + while (pall[0].pnr >= 0 && pall_cnt > 2) { + /* j - will keep first ptr to start checking polygon + * c - counter how many angles > 180° */ +// d_printf ("**************** subid:%d pallcnt:%d", a->subid, pall_cnt); + for (smaller = 0, j = -1, c = 0, i = 0; i < pall_cnt; i++) { + if (i == pall_cnt-1) pall[i].angle = point_angle (pall[i-1].km, pall[i].km, pall[0].km); + else if (i == 0) pall[i].angle = point_angle (pall[pall_cnt-1].km, pall[i].km, pall[i+1].km); + else pall[i].angle = point_angle (pall[i-1].km, pall[i].km, pall[i+1].km); + if (pall[i].angle > M_PI) { + if (j == -1 ||j+1 == i) j = i; + c++; + } + else smaller = 1; +// if (_debug) d_printf ("i:%-2d pnr:%-2d angle:%f",i, pall[i].pnr, pall[i].angle); + } +// if (_debug) d_printf ("c:%d pall_cnt:%d j:%d",c, pall_cnt, j); + + /* if all angles are abover 180° turn rotation around */ + if (smaller == 0) { + struct s_osmareapnt *pall_ = ml_malloc (sizeof (struct s_osmareapnt) * pall_cnt); + +// if (_debug) d_printf ("change rotation ..."); + for (i = 0; i < pall_cnt; i++) pall_[pall_cnt - i - 1] = pall[i]; + ml_free (pall); + pall = pall_; + } + + /* if c==0 save last areapart */ + else if (c == 0) { + for (i = 0; i < pall_cnt; i++) { +// if (_debug) d_printf ("0: added %d pnr:%d", k, pall[i].pnr); + a->p[i] = marea->marea->p[pall[i].pnr]; + pall[i].pnr = -1; + } + a->p_cnt = pall_cnt; + 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 (k = 0, i = j; k < pall_cnt;) { +// if (_debug) d_printf ("1: added %d pnr:%d", k, pall[i].pnr); + a->p[k++] = marea->marea->p[pall[i].pnr]; + pall[i].pnr = -1; + + if (i < pall_cnt-1) i++; + else i = 0; + } + a->p_cnt = pall_cnt; + map_area_add (a, MHLOAD_RELOAD); + a->subid++; + } + + /* check again for the part to split the area. */ + else { + float angle; + int s; /* second point */ + float angle_old; /* old value */ + int i_old; + int pnr_old; + + k = 0; + i = j; + +// if (_debug) d_printf ("added %d pnr:%d", k, pall[i].pnr); + a->p[k++] = marea->marea->p[pall[i].pnr]; /* copy first point */ + if (i < pall_cnt-1) i++; /* increase */ + else i = 0; + + i_old = s = i; + angle_old = angle = 0.0; + if (_debug) d_printf ("pall_cnt:%d c:%d s:%d j:%d", pall_cnt, c, s, j); + + /* loop as long as angle is increasing and below 180° */ + for (; i != j && angle_old <= angle && angle <= M_PI;) { + angle_old = angle; /* save old values */ + i_old = i; + pnr_old = pall[i].pnr; +// if (_debug) d_printf ("added %d pnr:%d", k, pall[i].pnr); + a->p[k++] = marea->marea->p[pall[i].pnr]; /* copy point */ + pall[i].pnr = -1; + + if (i < pall_cnt-1) i++; /* increase */ + else i = 0; + angle = point_angle (pall[i].km, pall[j].km, pall[s].km); +// if (_debug) d_printf ("k:%d next angle:%f angle_old:%f pall[%d].angle:%f nr:%d", k, angle, angle_old, i, pall[i].angle, pall[i].pnr); + } + +// if (_debug) d_printf ("j:%d i:%d s:%d k:%d angle:%f angle_old:%f pall[i].angle:%f", +// j, i, s, k, angle, angle_old, pall[i].angle); + +// /* last visible point */ +// if (pall[i].angle > M_PI) { +// if (_debug) d_printf ("added %d pnr:%d", k, pall[i].pnr); +// a->p[k++] = marea->marea->p[pall[i].pnr]; /* copy point */ +// } +// else + if (angle_old > angle) { + pall[i_old].pnr = pnr_old; + } + else if (angle > M_PI) { + pall[i_old].pnr = pnr_old; + } + else if (i == j) { + d_printf ("%s:%d i(%d) == j(%d) finished?", __FILE__, __LINE__, i, j); + } + +// if (_debug) d_printf ("j:%d i:%d s:%d k:%d angle:%f angle_old:%f pall[i].angle:%f", +// j, i, s, k, angle, angle_old, pall[i].angle); + + /* add element */ + a->p_cnt = k; + map_area_add (a, MHLOAD_RELOAD); + a->subid++; + } + + /* recreate pall list, delete unneeded elements (pnr == -1) */ + for (k = 0, i = 0; i < pall_cnt; i++) + if (pall[i].pnr != -1) { + pall[k++] = pall[i]; +// if (_debug) d_printf (" old:%-2d new:%-2d pnr:%d", i, k, pall[i].pnr); + } + pall_cnt = k; + } + +// if (_debug) d_printf ("j:%d c:%d", j, c); + if (pall[0].pnr >= 0 && pall_cnt > 0) { + d_printf ("%s:%d osm_area_split_add: something went very wrong", __FILE__, __LINE__); + d_printf (" marea->id: %lld:%d", marea->marea->id, marea->marea->subid); + d_printf (" pall[0].pnr:%d pall_cnt: %d", pall[0].pnr, pall_cnt); + + } + + /* free unneeded memory and return to caller */ + ml_free (a); + ml_free (pall); + + return a->subid; +}; + + /******************************************************************** * save detail information of the node. This will also create the