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.
839 lines
25 KiB
839 lines
25 KiB
/* draw.c
|
|
* Copyright (C) Steffen Pohle 2010 <steffen@gulpe.de>
|
|
*
|
|
* main.c 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 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* main.c 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <sys/time.h>
|
|
#include <math.h>
|
|
|
|
#include "osmroute.h"
|
|
#include "draw.h"
|
|
#include "map.h"
|
|
#include "system.h"
|
|
#include "gui.h"
|
|
#include "vector.h"
|
|
#include "memoryleak.h"
|
|
|
|
|
|
/**************************************************************************
|
|
* color definitions, hopfully this can go out soon, need to find a way to
|
|
* specify only the rgb values like it is in HTML and thats it.
|
|
* i.e. color = 0xFF0000; for red.
|
|
*/
|
|
struct line_style draw_linestyle[MWAY_MAX];
|
|
struct color color_polygon[MAREA_MAX];
|
|
struct color color_bg;
|
|
struct color color_fg;
|
|
struct color color[COLOR_MAX][COLOR_steps];
|
|
|
|
|
|
/**************************************************************************
|
|
* current screen data, center of the screen? where we look at the scale,
|
|
* and the drawing flags. All these values start with view_*
|
|
*/
|
|
float view_scale = 0.001;
|
|
float view_lon = 11.183;
|
|
float view_lat = 48.736;
|
|
int view_flags = DRAW_GPSFOLLOW;
|
|
|
|
|
|
/**************************************************************************
|
|
* internal variables set by some functions within the drawing stuff and
|
|
* from withing the *_gfx sources.. Some drawing functon will have vriables
|
|
* declared on top of the first function. (i.E. drawing lines, polygones.
|
|
*/
|
|
int draw_type[MAREA_MAX+MWAY_MAX];
|
|
|
|
/*
|
|
* selection variables
|
|
*/
|
|
struct map_pos select_pos;
|
|
int select_enabled = 0;
|
|
|
|
char statusline_text[255] = "";
|
|
int statusline_progress = 0;
|
|
|
|
void draw_line (struct image *img, int x1, int y1, int x2, int y2, struct line_style style);
|
|
void draw_lineway (struct image *img, int x1, int y1, int x2, int y2, struct line_style style);
|
|
void draw_rectangle (struct image *img, int x1, int y1, int x2, int y2, struct line_style style);
|
|
|
|
|
|
/*************************************************************************
|
|
* to prevent the flickering screen, we create two images inside the
|
|
* memory. One which keeps a larger area of the map (so we only draw
|
|
* the map once in a while) and a second map with the on screen data.
|
|
* img_map: keeps the current map screen values.
|
|
* img_screen: is the final data with the on screen data to copy on
|
|
* the screen.
|
|
*/
|
|
struct image *img_map = NULL; // image data of the current map
|
|
struct map_pos img_map_pos; // position of the current map
|
|
float img_map_scale; // scale of the current map
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* functions to convert between geo data and screen data
|
|
*
|
|
*/
|
|
iPoint draw_geo2screen (float center_lon, float center_lat, float lon, float lat) {
|
|
iPoint r;
|
|
|
|
r.x = - (map_lon2km (center_lon - lon, lat) / view_scale);
|
|
r.y = (map_lat2km (center_lat - lat) / view_scale);
|
|
|
|
return r;
|
|
};
|
|
|
|
|
|
void draw_screen2geo (int x, int y, float *lon, float *lat) {
|
|
y = y - gfx_screensize.y/2;
|
|
x = x - gfx_screensize.x/2;
|
|
|
|
*lat = -map_km2lat(((float)y) * view_scale);
|
|
*lon = map_km2lon(((float)x) * view_scale, view_lat + *lat);
|
|
*lat = view_lat + *lat;
|
|
*lon = view_lon + *lon;
|
|
};
|
|
|
|
|
|
/******************************************************************************
|
|
* set the new scale, and check what will have to be shown
|
|
*/
|
|
void draw_setscale (int newscale) {
|
|
float scale = view_scale;
|
|
|
|
if (newscale < 0) {
|
|
scale = scale / 1.5;
|
|
}
|
|
else {
|
|
scale = scale * 1.5;
|
|
}
|
|
d_printf ("scale: %f -> %f (i:%d)", view_scale, scale, newscale);
|
|
draw_setscalef (scale);
|
|
};
|
|
|
|
|
|
void draw_setscalef (float newscale) {
|
|
int i;
|
|
|
|
view_scale = newscale;
|
|
if (view_scale < 0.001) view_scale = 0.001;
|
|
else if (view_scale > 0.5) view_scale = 0.5;
|
|
|
|
/* change display settings */
|
|
if (view_scale < 0.01) {
|
|
for (i = 0; i < MWAY_MAX+MAREA_MAX; i++)
|
|
draw_type [i] = TRUE;
|
|
}
|
|
else if (view_scale < 0.1) {
|
|
for (i = 0; i < MWAY_MAX+MAREA_MAX; i++) {
|
|
switch (i) {
|
|
case (MWAY_tertiary):
|
|
case (MWAY_highway):
|
|
case (MWAY_MAX + MAREA_greenfield):
|
|
case (MWAY_MAX + MAREA_water):
|
|
case (MWAY_MAX + MAREA_industrial):
|
|
case (MWAY_MAX + MAREA_residential):
|
|
draw_type [i] = TRUE;
|
|
break;
|
|
default:
|
|
draw_type [i] = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (i = 0; i < MWAY_MAX+MAREA_MAX; i++) {
|
|
switch (i) {
|
|
case (MWAY_highway):
|
|
case (MWAY_MAX + MAREA_greenfield):
|
|
case (MWAY_MAX + MAREA_wood):
|
|
case (MWAY_MAX + MAREA_water):
|
|
case (MWAY_MAX + MAREA_residential):
|
|
draw_type [i] = TRUE;
|
|
break;
|
|
default:
|
|
draw_type [i] = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
main_wnd_update();
|
|
};
|
|
|
|
|
|
void draw_set_flag (int flag) {
|
|
view_flags |= flag;
|
|
};
|
|
|
|
|
|
void draw_del_flag (int flag) {
|
|
view_flags &= (0xFFFF - flag);
|
|
};
|
|
|
|
|
|
/**************************************************************************+
|
|
* drawing initial functions
|
|
*/
|
|
void draw_init () {
|
|
int n;
|
|
|
|
d_printf ("draw_init");
|
|
draw_init_color ();
|
|
for (n = 0; n < MAREA_MAX; n++) draw_type[n] = 1;
|
|
|
|
view_lon = cfg.last_lon;
|
|
view_lat = cfg.last_lat;
|
|
draw_setscalef (cfg.last_scale);
|
|
};
|
|
|
|
void draw_init_color () {
|
|
int n, i, r,g,b;
|
|
|
|
d_printf ("draw_init_color");
|
|
|
|
for (n = 0; n < COLOR_MAX; n++) for (i = COLOR_steps-1; i >= 0; i--) {
|
|
if (i == COLOR_steps-1) {
|
|
if (n == COLOR_white) gfx_color_alloc (&color[n][i], 0xFFFF, 0xFFFF, 0xFFFF);
|
|
else if (n == COLOR_red) gfx_color_alloc (&color[n][i], 0xFFFF, 0x0, 0x0);
|
|
else if (n == COLOR_redgray) gfx_color_alloc (&color[n][i], 0xFFFF, 0xA000, 0xA000);
|
|
else if (n == COLOR_blue) gfx_color_alloc (&color[n][i], 0x0, 0x0, 0xFFFF);
|
|
else if (n == COLOR_bluegray) gfx_color_alloc (&color[n][i], 0xA000, 0xA000, 0xFFFF);
|
|
else if (n == COLOR_green) gfx_color_alloc (&color[n][i], 0x0, 0xFFFF, 0x0);
|
|
else if (n == COLOR_greengray) gfx_color_alloc (&color[n][i], 0xA000, 0xFFFF, 0xA000);
|
|
else if (n == COLOR_brown) gfx_color_alloc (&color[n][i], 0xFFFF, 0x8000, 0x0);
|
|
else if (n == COLOR_pink) gfx_color_alloc (&color[n][i], 0xFFFF, 0x0, 0xFFFF);
|
|
else if (n == COLOR_yellow) gfx_color_alloc (&color[n][i], 0xFFFF, 0xFFFF, 0x0000);
|
|
else {
|
|
d_printf ("%s:%d not all colors have been defined..", __FILE__, __LINE__);
|
|
exit (1);
|
|
}
|
|
}
|
|
else {
|
|
r = color[n][COLOR_steps-1].r;
|
|
g = color[n][COLOR_steps-1].g;
|
|
b = color[n][COLOR_steps-1].b;
|
|
if (n == COLOR_white) {
|
|
if (i == 0) {
|
|
r = g = b = 0;
|
|
}
|
|
else {
|
|
r = r*(i)/COLOR_steps-1;
|
|
g = g*(i)/COLOR_steps-1;
|
|
b = b*(i)/COLOR_steps-1;
|
|
}
|
|
}
|
|
else {
|
|
r = r*(i+1)/COLOR_steps;
|
|
g = g*(i+1)/COLOR_steps;
|
|
b = b*(i+1)/COLOR_steps;
|
|
}
|
|
gfx_color_alloc (&color[n][i], r, g, b);
|
|
}
|
|
|
|
gfx_color_alloc (&color_bg, 0,0,0); // background
|
|
gfx_color_alloc (&color_fg, 0x8000,0x8000,0x8000); // foreground
|
|
}
|
|
|
|
for (n = 0; n < MWAY_MAX; n++) {
|
|
draw_linestyle[n].width = 0.0;
|
|
gfx_color_alloc (&draw_linestyle[n].borderc, 0x8000, 0x8000,0x8000);
|
|
|
|
switch (n) {
|
|
case (MWAY_highway):
|
|
draw_linestyle[n].width = 4.0;
|
|
gfx_color_alloc (&draw_linestyle[n].c, 0xFFFF,0xFFFF,0x8000);
|
|
break;
|
|
case (MWAY_tertiary):
|
|
draw_linestyle[n].width = 3.0;
|
|
gfx_color_alloc (&draw_linestyle[n].c, 0xA000,0xA000,0x0000);
|
|
break;
|
|
case (MWAY_residential):
|
|
draw_linestyle[n].width = 2.0;
|
|
gfx_color_alloc (&draw_linestyle[n].c, 0xA000,0xA000,0xA000);
|
|
break;
|
|
case (MWAY_cycleway):
|
|
gfx_color_alloc (&draw_linestyle[n].c, 0x4000,0xA000,0x4000);
|
|
break;
|
|
case (MWAY_footway):
|
|
gfx_color_alloc (&draw_linestyle[n].c, 0x4000,0x4000,0xA000);
|
|
break;
|
|
case (MWAY_railway):
|
|
gfx_color_alloc (&draw_linestyle[n].c, 0x8000,0x8000,0x8000);
|
|
break;
|
|
case (MWAY_unknown_railway):
|
|
gfx_color_alloc (&draw_linestyle[n].c, 0x6000,0x6000,0x6000);
|
|
break;
|
|
case (MWAY_service):
|
|
gfx_color_alloc (&draw_linestyle[n].c, 0x6000,0x6000,0x6000);
|
|
break;
|
|
case (MWAY_unknown):
|
|
case (MWAY_unknown_way):
|
|
default:
|
|
gfx_color_alloc (&draw_linestyle[n].c, 0xA000,0x5000,0x5000);
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (n = 0; n < MAREA_MAX; n++) switch (n) {
|
|
case (MAREA_water):
|
|
gfx_color_alloc (&color_polygon[n], 0x4000,0x4000,0xFFFF);
|
|
break;
|
|
case (MAREA_greenfield):
|
|
gfx_color_alloc (&color_polygon[n], 0x2000,0x8000,0x2000);
|
|
break;
|
|
case (MAREA_wood):
|
|
gfx_color_alloc (&color_polygon[n], 0x0000,0x6000,0x0000);
|
|
break;
|
|
case (MAREA_land):
|
|
gfx_color_alloc (&color_polygon[n], 0x6000,0x6000,0x0000);
|
|
break;
|
|
case (MAREA_residential):
|
|
gfx_color_alloc (&color_polygon[n], 0x2000,0x2000,0x2000);
|
|
break;
|
|
case (MAREA_farm):
|
|
gfx_color_alloc (&color_polygon[n], 0x8000,0x4000,0x2000);
|
|
break;
|
|
case (MAREA_industrial):
|
|
gfx_color_alloc (&color_polygon[n], 0x8000,0x6000,0x8000);
|
|
break;
|
|
case (MAREA_commercial):
|
|
gfx_color_alloc (&color_polygon[n], 0x8000,0x0000,0x8000);
|
|
break;
|
|
case (MAREA_military):
|
|
gfx_color_alloc (&color_polygon[n], 0x2000,0x2000,0x2000);
|
|
break;
|
|
case (MAREA_building):
|
|
gfx_color_alloc (&color_polygon[n], 0x6000,0x6000,0x6000);
|
|
break;
|
|
default:
|
|
gfx_color_alloc (&color_polygon[n],0xFFFF,0x0000,0x0000);
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**************************************************************************+
|
|
* drawing subfunctions
|
|
*/
|
|
|
|
/*
|
|
* rectangle
|
|
*/
|
|
void draw_rectangle (struct image *dimg, int x1, int y1, int x2, int y2, struct line_style style) {
|
|
gfx_draw_line (dimg, x1, y1, x2, y1, style);
|
|
gfx_draw_line (dimg, x2, y1, x2, y2, style);
|
|
gfx_draw_line (dimg, x2, y2, x1, y2, style);
|
|
gfx_draw_line (dimg, x1, y2, x1, y1, style);
|
|
};
|
|
|
|
|
|
void draw_fillrectangle (struct image *dimg, int x1, int y1, int x2, int y2, struct color *c) {
|
|
struct line_style ls;
|
|
|
|
ls.c = *c;
|
|
ls.borderc = *c;
|
|
ls.width = 1.0;
|
|
|
|
iPoint points[4] = { {x1, y1},
|
|
{x2, y1},
|
|
{x2, y2},
|
|
{x1, y2} };
|
|
|
|
gfx_draw_polygon (dimg, points, 4, ls, c);
|
|
};
|
|
|
|
|
|
/*
|
|
* lines
|
|
*/
|
|
void draw_line (struct image *dimg, int x1, int y1, int x2, int y2, struct line_style style) {
|
|
int width, height;
|
|
|
|
if (dimg == NULL) {
|
|
width = gfx_screensize.x;
|
|
height = gfx_screensize.y;
|
|
}
|
|
else {
|
|
width = dimg->width;
|
|
height = dimg->height;
|
|
}
|
|
|
|
if ((x1 >= 0 && x1 <= width && y1 >= 0 && y1 <= height) ||
|
|
(x2 >= 0 && x2 <= width && y2 >= 0 && y2 <= height) ||
|
|
(x1 <= 0 && x2 >= width) || (x2 <= 0 && x1 >= width) ||
|
|
(y1 <= 0 && y2 >= height) || (y2 <= 0 && y1 >= height))
|
|
gfx_draw_line (dimg, x1, y1, x2, y2, style);
|
|
};
|
|
|
|
|
|
/*
|
|
* draw a polygon..
|
|
*/
|
|
static iPoint _polypoints[POLYGON_MAX_POINTS];
|
|
static int _polycnt;
|
|
|
|
void draw_polygonstart () {
|
|
_polycnt = 0;
|
|
};
|
|
|
|
void draw_polygonadd (int x, int y) {
|
|
if (_polycnt >= POLYGON_MAX_POINTS) {
|
|
printf ("%s:%d draw_polygonadd: too many points.\n", __FILE__, __LINE__);
|
|
return;
|
|
}
|
|
_polypoints[_polycnt].x = x;
|
|
_polypoints[_polycnt].y = y;
|
|
_polycnt++;
|
|
};
|
|
|
|
|
|
void draw_polygonfinish (struct image *dimg, struct line_style ls, struct color *c, int border) {
|
|
int i;
|
|
|
|
gfx_draw_polygon (dimg, _polypoints, _polycnt, ls, c);
|
|
|
|
if (border) {
|
|
for (i = 1; i < _polycnt; i++) {
|
|
gfx_draw_line (dimg, _polypoints[i-1].x, _polypoints[i-1].y, _polypoints[i].x, _polypoints[i].y, ls);
|
|
}
|
|
gfx_draw_line (dimg, _polypoints[_polycnt-1].x, _polypoints[_polycnt-1].y, _polypoints[0].x, _polypoints[0].y, ls);
|
|
}
|
|
_polycnt = 0;
|
|
};
|
|
|
|
|
|
void draw_lineway (struct image *dimg, int x1, int y1, int x2, int y2, struct line_style style) {
|
|
struct line_style tmplinestyle = style;
|
|
|
|
if (view_scale < 0.01)
|
|
tmplinestyle.width = tmplinestyle.width * (0.005/view_scale);
|
|
|
|
draw_line (dimg, x1, y1, x2, y2, tmplinestyle);
|
|
};
|
|
|
|
|
|
/************************************************************************
|
|
* the drawing stuff itself.
|
|
* before drawing everything on the screen, check if we need to redraw
|
|
* the map or just copy a part of it into the gui image.
|
|
* After copying the map into the gui screen draw the gui, afterwards
|
|
* copy the gui screen onto the display.
|
|
*/
|
|
void draw_map () {
|
|
struct map_hash *mh;
|
|
struct map_way *cway;
|
|
struct map_area *carea;
|
|
struct map_place *cplace;
|
|
struct map_poi *cpoi;
|
|
int w, n, i;
|
|
struct map_hashpos h, hs, he;
|
|
iPoint p1, p2;
|
|
fPoint nd, v1, v2, v3;
|
|
struct line_style tmplinestyle;
|
|
iPoint center;
|
|
struct map_pos hashstart, hashend;
|
|
struct color *c;
|
|
char text[255];
|
|
|
|
d_printf ("view_lon: %f view_lat:%f", view_lon, view_lat);
|
|
|
|
gfx_clear (img_map, &color_bg);
|
|
center.x = img_map->width / 2;
|
|
center.y = img_map->height / 2;
|
|
|
|
tmplinestyle.width = 1.0;
|
|
tmplinestyle.c = tmplinestyle.borderc = color[COLOR_red][2];
|
|
|
|
hashstart.lat = view_lat - map_km2lat(view_scale * ((float)img_map->width));
|
|
hashstart.lon = view_lon - map_km2lon(view_scale * ((float)img_map->height), hashstart.lat);
|
|
hashend.lat = view_lat + map_km2lat(view_scale * ((float)img_map->height));
|
|
hashend.lon = view_lon + map_km2lon(view_scale * ((float)img_map->width), hashend.lat);
|
|
|
|
hs.ilon = map_geo2igeo (hashstart.lon);
|
|
hs.ilat = map_geo2igeo (hashstart.lat);
|
|
he.ilon = map_geo2igeo (hashend.lon);
|
|
he.ilat = map_geo2igeo (hashend.lat);
|
|
|
|
/*
|
|
* draw areas
|
|
*/
|
|
for (h.ilon = hs.ilon; h.ilon <= he.ilon; h.ilon++)
|
|
for (h.ilat = hs.ilat; h.ilat <= he.ilat; h.ilat++) {
|
|
if (app.status == APPSTATUS_nothing) mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_RELOAD);
|
|
else mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_NONE);
|
|
if (mh) {
|
|
carea = mh->areas;
|
|
while (carea) {
|
|
if (draw_type[carea->type + MWAY_MAX]) {
|
|
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);
|
|
}
|
|
carea = carea->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* draw ways
|
|
*/
|
|
/* draw outside */
|
|
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..
|
|
*/
|
|
if (app.status == APPSTATUS_nothing) mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_RELOAD);
|
|
else mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_NONE);
|
|
if (mh) {
|
|
/*
|
|
* ways
|
|
*/
|
|
cway = mh->ways;
|
|
while (cway) {
|
|
if (cway->id != 0 && draw_type[cway->type]) {
|
|
/* go through all the nodes */
|
|
tmplinestyle.width = draw_linestyle[cway->type].width * (0.005/view_scale) + 2;
|
|
tmplinestyle.c = tmplinestyle.borderc = color[COLOR_white][1];
|
|
if (view_scale < 0.01) {
|
|
for (n = 0; n < cway->p_cnt; n++) {
|
|
p2 = p1;
|
|
nd.x = map_lon2km (view_lon - cway->p[n].lon, cway->p[n].lat);
|
|
nd.y = map_lat2km (view_lat - cway->p[n].lat);
|
|
p1.x = center.x - (nd.x / view_scale);
|
|
p1.y = center.y + (nd.y / view_scale);
|
|
|
|
if (n > 0)
|
|
draw_line (img_map, p1.x, p1.y, p2.x, p2.y, tmplinestyle);
|
|
}
|
|
}
|
|
else {
|
|
for (n = -1; n < cway->n_cnt;) {
|
|
/* find next node */
|
|
if (n == -1) {
|
|
i = 0;
|
|
n++;
|
|
}
|
|
else {
|
|
for (n = 0, w = cway->p_cnt; n < cway->n_cnt; n++) {
|
|
if (cway->n[n].pnr > i && cway->n[n].pnr < w) w = cway->n[n].pnr;
|
|
}
|
|
if (w == cway->p_cnt) i = cway->p_cnt - 1;
|
|
else {
|
|
i = w;
|
|
n = 1;
|
|
}
|
|
}
|
|
p2 = p1;
|
|
nd.x = map_lon2km (view_lon - cway->p[i].lon, cway->p[i].lat);
|
|
nd.y = map_lat2km (view_lat - cway->p[i].lat);
|
|
p1.x = center.x - (nd.x / view_scale);
|
|
p1.y = center.y + (nd.y / view_scale);
|
|
|
|
if (n > 0)
|
|
draw_line (img_map, p1.x, p1.y, p2.x, p2.y, tmplinestyle);
|
|
}
|
|
}
|
|
|
|
/* draw the waynodes */
|
|
for (n = 0; n < cway->n_cnt; n++) if (cway->n[n].pnr < cway->p_cnt) {
|
|
p1 = draw_geo2screen (view_lon, view_lat, cway->n[n].d.lon, cway->n[n].d.lat);
|
|
p2 = draw_geo2screen (view_lon, view_lat, cway->p[cway->n[n].pnr].lon, cway->p[cway->n[n].pnr].lat);
|
|
p1.x += center.x;
|
|
p1.y += center.y;
|
|
p2.x += center.x;
|
|
p2.y += center.y;
|
|
draw_line (img_map, p1.x, p1.y, p2.x, p2.y, tmplinestyle);
|
|
}
|
|
}
|
|
cway = cway->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ways inside */
|
|
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..
|
|
*/
|
|
if (app.status == APPSTATUS_nothing) mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_RELOAD);
|
|
else mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_NONE);
|
|
if (mh) {
|
|
/*
|
|
* ways
|
|
*/
|
|
cway = mh->ways;
|
|
while (cway) {
|
|
if (cway->id != 0 && draw_type[cway->type] && (cway->flags & MWAY_F_planed) == 0) {
|
|
/* go through all the nodes */
|
|
if (view_scale < 0.01) {
|
|
for (n = 0; n < cway->p_cnt; n++) {
|
|
p2 = p1;
|
|
nd.x = map_lon2km (view_lon - cway->p[n].lon, cway->p[n].lat);
|
|
nd.y = map_lat2km (view_lat - cway->p[n].lat);
|
|
p1.x = center.x - (nd.x / view_scale);
|
|
p1.y = center.y + (nd.y / view_scale);
|
|
if (n > 0) {
|
|
if (cway->type >= MWAY_MAX)
|
|
draw_lineway (img_map, p1.x, p1.y, p2.x, p2.y, draw_linestyle[MWAY_unknown]);
|
|
else
|
|
draw_lineway (img_map, p1.x, p1.y, p2.x, p2.y, draw_linestyle[cway->type]);
|
|
|
|
/* one way arrow */
|
|
if (cway->flags & MWAY_F_oneway && view_scale < 0.004) {
|
|
tmplinestyle.width = 1;
|
|
tmplinestyle.c = tmplinestyle.borderc = color[COLOR_white][0];
|
|
nd.x = (p1.x+p2.x)/2;
|
|
nd.y = (p1.y+p2.y)/2;
|
|
v1.x = p1.x-p2.x;
|
|
v1.y = p1.y-p2.y;
|
|
v1 = vec_one (v1);
|
|
v2 = vec_turn90 (v1);
|
|
v3 = vec_mirror (v2);
|
|
v1 = vec_mul (v1, 3.0);
|
|
v2 = vec_mul (v2, 3.0);
|
|
v3 = vec_mul (v3, 3.0);
|
|
v1 = vec_add (v1, nd);
|
|
v2 = vec_add (v2, nd);
|
|
v3 = vec_add (v3, nd);
|
|
draw_line (img_map, v1.x, v1.y, v2.x, v2.y, tmplinestyle);
|
|
draw_line (img_map, v1.x, v1.y, v3.x, v3.y, tmplinestyle);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (n = -1; n < cway->n_cnt;) {
|
|
// d_printf ("LINE: %lld n_cnt:%d p_cnt:%d", cway->id, cway->n_cnt, cway->p_cnt);
|
|
/* find next node */
|
|
if (n == -1) {
|
|
i = 0;
|
|
n++;
|
|
}
|
|
else {
|
|
for (n = 0, w = cway->p_cnt; n < cway->n_cnt; n++) {
|
|
if (cway->n[n].pnr > i && cway->n[n].pnr < w) w = cway->n[n].pnr;
|
|
}
|
|
if (w == cway->p_cnt) i = cway->p_cnt - 1;
|
|
else {
|
|
i = w;
|
|
n = 1;
|
|
}
|
|
}
|
|
// d_printf (" i:%d n:%d", i, n);
|
|
p2 = p1;
|
|
nd.x = map_lon2km (view_lon - cway->p[i].lon, cway->p[i].lat);
|
|
nd.y = map_lat2km (view_lat - cway->p[i].lat);
|
|
p1.x = center.x - (nd.x / view_scale);
|
|
p1.y = center.y + (nd.y / view_scale);
|
|
|
|
if (n > 0) {
|
|
if (cway->type >= MWAY_MAX)
|
|
draw_lineway (img_map, p1.x, p1.y, p2.x, p2.y, draw_linestyle[MWAY_unknown]);
|
|
else
|
|
draw_lineway (img_map, p1.x, p1.y, p2.x, p2.y, draw_linestyle[cway->type]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* draw the waynodes */
|
|
for (n = 0; n < cway->n_cnt; n++) if (cway->n[n].pnr < cway->p_cnt) {
|
|
p1 = draw_geo2screen (view_lon, view_lat, cway->n[n].d.lon, cway->n[n].d.lat);
|
|
p2 = draw_geo2screen (view_lon, view_lat, cway->p[cway->n[n].pnr].lon, cway->p[cway->n[n].pnr].lat);
|
|
p1.x += center.x;
|
|
p1.y += center.y;
|
|
p2.x += center.x;
|
|
p2.y += center.y;
|
|
if (cway->type >= MWAY_MAX)
|
|
draw_lineway (img_map, p1.x, p1.y, p2.x, p2.y, draw_linestyle[MWAY_unknown]);
|
|
else
|
|
draw_lineway (img_map, p1.x, p1.y, p2.x, p2.y, draw_linestyle[cway->type]);
|
|
}
|
|
else d_printf ("%s:%d wayid:%lld cway->n[n].pnr(%d) < cway->p_cnt(%d) doesn't match", __FILE__, __LINE__, cway->id, cway->n[n].pnr, cway->p_cnt);
|
|
|
|
}
|
|
cway = cway->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* draw places, pois just on top layers
|
|
*/
|
|
for (h.ilon = hs.ilon; h.ilon <= he.ilon; h.ilon++)
|
|
for (h.ilat = hs.ilat; h.ilat <= he.ilat; h.ilat++) {
|
|
|
|
if (app.status == APPSTATUS_nothing) mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_RELOAD);
|
|
else mh = map_hash_geti (h.ilon, h.ilat, MHLOAD_NONE);
|
|
if (mh) {
|
|
/*
|
|
* places
|
|
*/
|
|
cplace = mh->places;
|
|
i = 0;
|
|
while (cplace) {
|
|
if (view_scale < 0.01
|
|
|| cplace->type == MAP_PLACE_city
|
|
|| cplace->type == MAP_PLACE_town
|
|
|| (cplace->type == MAP_PLACE_village && view_scale < 0.05)) {
|
|
i++;
|
|
p1 = draw_geo2screen(view_lon, view_lat, cplace->lon, cplace->lat);
|
|
p1.x += center.x;
|
|
p1.y += center.y;
|
|
switch (cplace->type) {
|
|
case (MAP_PLACE_city):
|
|
case (MAP_PLACE_town):
|
|
case (MAP_PLACE_village):
|
|
gfx_draw_text (img_map, p1.x,p1.y, cplace->name, &color[COLOR_white][3]);
|
|
break;
|
|
case (MAP_PLACE_hamlet):
|
|
case (MAP_PLACE_suburb):
|
|
gfx_draw_text (img_map, p1.x,p1.y, cplace->name, &color[COLOR_bluegray][2]);
|
|
break;
|
|
default:
|
|
gfx_draw_text (img_map, p1.x,p1.y, cplace->name, &color[COLOR_bluegray][2]);
|
|
break;
|
|
}
|
|
}
|
|
cplace = cplace->next;
|
|
}
|
|
|
|
|
|
/*
|
|
* poi
|
|
*/
|
|
cpoi = mh->pois;
|
|
i = 0;
|
|
if (view_scale < 0.01) while (cpoi) {
|
|
p1 = draw_geo2screen(view_lon, view_lat, cpoi->lon, cpoi->lat);
|
|
p1.x += center.x;
|
|
p1.y += center.y;
|
|
if (cpoi->type != MAP_POI_unknown &&
|
|
((view_scale < 0.01 && cpoi->type == MAP_POI_gasstation)
|
|
|| (view_scale < 0.0015))) {
|
|
switch (cpoi->type) {
|
|
case (MAP_POI_campsite):
|
|
sprintf (text, "C");
|
|
c = &color[COLOR_greengray][3];
|
|
break;
|
|
default:
|
|
sprintf (text, "?");
|
|
c = &color[COLOR_red][3];
|
|
break;
|
|
}
|
|
gfx_draw_text (img_map, p1.x-4, p1.y-4, text, c);
|
|
gfx_draw_text (img_map, p1.x-strlen(cpoi->name)*2, p1.y+8, cpoi->name, c);
|
|
}
|
|
cpoi = cpoi->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
// tmplinestyle.width = 4.0;
|
|
// tmplinestyle.c = tmplinestyle.borderc = color_red1;
|
|
// draw_line (img_map, center.x-100, center.y, center.x+100, center.y, tmplinestyle);
|
|
// draw_line (img_map, center.x, center.y-100, center.x, center.y+100, tmplinestyle);
|
|
// draw_lines (img_map);
|
|
// sprintf (text, "%f,%f", view_lon, view_lat);
|
|
// gfx_img_draw_text (img_map, center.x,center.y, text, &color_blue1);
|
|
|
|
/*
|
|
* save data of the map drawed
|
|
*/
|
|
img_map_pos.lon = view_lon;
|
|
img_map_pos.lat = view_lat;
|
|
img_map_scale = view_scale;
|
|
};
|
|
|
|
|
|
int draw_mapcopy () {
|
|
iPoint p1, p2;
|
|
|
|
p2 = draw_geo2screen (img_map_pos.lon, img_map_pos.lat, view_lon, view_lat);
|
|
p1.x = img_map->width/2 + p2.x - gfx_screensize.x/2;
|
|
p1.y = img_map->height/2 + p2.y - gfx_screensize.y/2;
|
|
|
|
if (p1.x < 0 || p1.y < 0
|
|
|| p1.x > (img_map->width - gfx_screensize.x)
|
|
|| p1.y > (img_map->height - gfx_screensize.y)) return 0;
|
|
|
|
gfx_draw_img (NULL, 0, 0, gfx_screensize.x, gfx_screensize.y, img_map, p1.x, p1.y);
|
|
|
|
return 1;
|
|
};
|
|
|
|
|
|
|
|
|
|
void draw () {
|
|
static int still_drawing = 0;
|
|
|
|
/* only run once at the time.. */
|
|
if (still_drawing) return;
|
|
still_drawing = 1;
|
|
|
|
while (view_lon > 180.0) view_lon -= 360.0;
|
|
while (view_lon < -180.0) view_lon += 360.0;
|
|
while (view_lat > 180.0) view_lat -= 360.0;
|
|
while (view_lat < -180.0) view_lat += 360.0;
|
|
|
|
/* do we need to alloc the screens */
|
|
if (img_map != NULL && (img_map->width != gfx_screensize.x * 2 || img_map->height != gfx_screensize.y * 2)) {
|
|
gfx_img_free (img_map);
|
|
img_map = NULL;
|
|
}
|
|
if (img_map == NULL) {
|
|
// img_map = gfx_img_alloc (400 * 2, 400 * 2);
|
|
img_map = gfx_img_alloc (gfx_screensize.x * 2, gfx_screensize.y * 2);
|
|
img_map_scale = -1.0;
|
|
}
|
|
|
|
/* draw the map, if needed */
|
|
if (img_map_scale < 0.0 || img_map_scale != view_scale) {
|
|
draw_map ();
|
|
}
|
|
gfx_clear (NULL, &color[COLOR_white][0]);
|
|
if (draw_mapcopy () == 0) {
|
|
draw_map ();
|
|
draw_mapcopy ();
|
|
}
|
|
|
|
draw_gui ();
|
|
gfx_flip ();
|
|
still_drawing = 0;
|
|
};
|
|
|
|
|
|
void draw_redrawmap () {
|
|
img_map_scale = -1;
|
|
draw ();
|
|
};
|