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/draw/draw_route.c

326 lines
11 KiB

/*
* draw_route.c
* Copyright (C) Steffen Pohle 2011 <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 "routing.h"
#include "gps.h"
#include "system.h"
void draw_routelist (struct rtwaylist *rtlist, struct line_style linestyle, int cnt);
/****************************************************************************
* drawing routing information on the screen
*/
void draw_gui_route () {
struct map_hash *mh;
struct map_way *mw;
struct line_style tmplinestyle;
iPoint p1, p2, center = {gfx_screensize.x/2, gfx_screensize.y/2};
fPoint nd;
float angle, f;
int j, n, i;
char text[256];
struct rtwaylist *rtlist = NULL;
if (route == NULL) return;
/*
* draw the destination route thick
*/
mh = map_hash_get (route->dest.lon, route->dest.lat, MHLOAD_RELOAD);
mw = map_way_find (mh, route->dest_way_id, route->dest_way_sid);
if (mw) {
/* go through all the nodes */
tmplinestyle.width = 5;
tmplinestyle.c = color[COLOR_white][3];
for (n = 0; n < mw->p_cnt; n++) {
p2 = p1;
nd.x = map_lon2km (view_lon - mw->p[n].lon, mw->p[n].lat);
nd.y = map_lat2km (view_lat - mw->p[n].lat);
p1.x = center.x - (nd.x / view_scale);
p1.y = center.y + (nd.y / view_scale);
if (n > 0) {
draw_lineway (NULL, p1.x, p1.y, p2.x, p2.y, tmplinestyle);
}
}
}
/*
* draw the destination cross
*/
tmplinestyle.width = 2.0;
tmplinestyle.c = tmplinestyle.borderc = color[COLOR_greengray][3];
p1 = draw_geo2screen (view_lon, view_lat, route->dest.lon, route->dest.lat);
p1.x += center.x;
p1.y += center.y;
draw_line (NULL, p1.x-5, p1.y-5, p1.x+5, p1.y+5, tmplinestyle);
draw_line (NULL, p1.x+5, p1.y-5, p1.x-5, p1.y+5, tmplinestyle);
if (view_flags & DRAW_DEBUG && route->state > ROUTING_INIT) {
p1 = draw_geo2screen (view_lon, view_lat, route->pos.lon, route->pos.lat);
p1.x += center.x;
p1.y += center.y;
p2 = draw_geo2screen (view_lon, view_lat, route->dest.lon, route->dest.lat);
p2.x += center.x;
p2.y += center.y;
draw_line (NULL, p1.x, p1.y, p2.x, p2.y, tmplinestyle);
}
/*
* display some information
*/
if (route->state == ROUTING_CALC) {
sprintf (text, _("calculating: %5.2g%% %g/%g"), 100.0-(100.0*route->closest_distance/route->distance), route->closest_distance, route->distance);
}
else if (route->state == ROUTING_OPTIMIZE) {
sprintf (text, _("optimizing:"));
}
else if (route->state == ROUTING_ONWAY) {
sprintf (text, _("onway dist: %3.1fkm"), route->distance);
}
else if (route->state == ROUTING_INIT) {
sprintf (text, _("init"));
}
else if (route->state == ROUTING_ABORT) {
sprintf (text, _("abort"));
}
else {
sprintf (text, _("unknown state: %d"), route->state);
}
gfx_draw_text (NULL, 0, gfx_screensize.y-32, text, &color[COLOR_greengray][3]);
/*
* draw compass
*/
tmplinestyle.width = 1.0;
tmplinestyle.c = tmplinestyle.borderc = color[COLOR_white][3];
draw_line (NULL, center.x-100, 40, center.x+100, 40, tmplinestyle);
for (angle = 0.0; angle < 360.0; angle = angle + 45.0) {
f = angle - drawgps_data.direction;
if (f > 180.0) f = f - 360.0;
if (f < -180.0) f = f + 360.0;
if (f >= -100.0 && f <= 100.0) {
draw_line (NULL, center.x+f, 40, center.x+f, 37, tmplinestyle);
if (angle == 0.0) {
sprintf (text, _("N"));
gfx_draw_text (NULL, center.x+f-4, 41, text, &color[COLOR_white][3]);
}
else if (angle == 90.0) {
sprintf (text, _("E"));
gfx_draw_text (NULL, center.x+f-4, 41, text, &color[COLOR_white][3]);
}
else if (angle == 180.0) {
sprintf (text, _("S"));
gfx_draw_text (NULL, center.x+f-4, 41, text, &color[COLOR_white][3]);
}
else if (angle == 270.0) {
sprintf (text, _("W"));
gfx_draw_text (NULL, center.x+f-4, 41, text, &color[COLOR_white][3]);
}
}
}
f = route->angle - drawgps_data.direction;
if (f > 180.0) f = f - 360.0;
if (f < -180.0) f = f + 360.0;
if (f < -100.0) f = -100.0;
else if (f > 100.0) f = 100.0;
else {
tmplinestyle.width = 2.0;
tmplinestyle.c = tmplinestyle.borderc = color[COLOR_greengray][3];
draw_line (NULL, center.x+f, 45, center.x+f, 35, tmplinestyle);
gfx_draw_text (NULL, center.x+f-4, 41, "*", &color[COLOR_greengray][3]);
}
/*
* debug information
*/
if (view_flags & DRAW_DEBUG) {
for (j = 0; j < 4; j++) {
if (j == 0) {
rtlist = &route->stack1;
tmplinestyle.width = 2;
tmplinestyle.c = color[COLOR_blue][3];
draw_routelist (rtlist, tmplinestyle, 64);
}
else if (j == 1) {
rtlist = &route->stack2;
tmplinestyle.width = 2;
tmplinestyle.c = color[COLOR_blue][3];
draw_routelist (rtlist, tmplinestyle, 64);
}
else if (j == 2) {
rtlist = &route->stack3;
tmplinestyle.width = 2;
tmplinestyle.c = color[COLOR_blue][3];
draw_routelist (rtlist, tmplinestyle, 64);
}
else if (j == 3) {
rtlist = &route->ways;
tmplinestyle.width = 3;
tmplinestyle.c = color[COLOR_red][2];
draw_routelist (rtlist, tmplinestyle, -1);
}
}
/*
* draw information about the way
*/
rtlist = NULL;
/* check route->ways */
for (i = 0; i < route->ways.cnt; i++) {
if (mouse_over_way_id == route->ways.array[i].way.id && mouse_over_way_sid == route->ways.array[i].way.sid) {
rtlist = &route->ways;
break;
}
}
/* check route->stacks */
if (rtlist == NULL) for (i = 0; i < route->stack1.cnt; i++) {
if (mouse_over_way_id == route->stack1.array[i].way.id && mouse_over_way_sid == route->stack1.array[i].way.sid) {
rtlist = &route->stack1;
break;
}
}
if (rtlist == NULL) for (i = 0; i < route->stack2.cnt; i++) {
if (mouse_over_way_id == route->stack2.array[i].way.id && mouse_over_way_sid == route->stack2.array[i].way.sid) {
rtlist = &route->stack2;
break;
}
}
if (rtlist == NULL) for (i = 0; i < route->stack3.cnt; i++) {
if (mouse_over_way_id == route->stack3.array[i].way.id && mouse_over_way_sid == route->stack3.array[i].way.sid) {
rtlist = &route->stack3;
break;
}
}
if (rtlist && i >= 0) {
sprintf (text, "dist2pos:%g dist2dest:%g step:%d", rtlist->array[i].dist2pos, rtlist->array[i].dist2dest, rtlist->array[i].step);
gfx_draw_text (NULL, 200, gfx_screensize.y-16, text, &color[COLOR_yellow][3]);
sprintf (text, "prio:%g deltadistr:%g", rtlist->array[i].priority, rtlist->array[i].deltadist);
gfx_draw_text (NULL, 200, gfx_screensize.y-28, text, &color[COLOR_yellow][3]);
sprintf (text, "%lld:%d (pnr:%d)", rtlist->array[i].way.id, rtlist->array[i].way.sid, rtlist->array[i].pnr);
gfx_draw_text (NULL, 200, gfx_screensize.y-40, text, &color[COLOR_yellow][3]);
sprintf (text, "way:%g cycle:%d:%d", rtlist->array[i].dist2dest, rtlist->array[i].cycle1, rtlist->array[i].cycle2);
gfx_draw_text (NULL, 200, gfx_screensize.y-52, text, &color[COLOR_yellow][3]);
}
/* display additional information */
sprintf (text, "r->stack1: %d prio:%g", route->stack1.cnt, (route->stack1.cnt == 0) ? 0.0 : route->stack1.array[route->stack1.cnt-1].priority);
gfx_draw_text (NULL, 80, 80, text, &color[COLOR_yellow][3]);
sprintf (text, "r->stack2: %d prio:%g", route->stack2.cnt, (route->stack2.cnt == 0) ? 0.0 : route->stack2.array[route->stack2.cnt-1].priority);
gfx_draw_text (NULL, 80, 96, text, &color[COLOR_yellow][3]);
sprintf (text, "r->stack3: %d prio:%g", route->stack3.cnt, (route->stack3.cnt == 0) ? 0.0 : route->stack3.array[route->stack3.cnt-1].priority);
gfx_draw_text (NULL, 80, 112, text, &color[COLOR_yellow][3]);
sprintf (text, "r->ways: %d", route->ways.cnt);
gfx_draw_text (NULL, 80, 128, text, &color[COLOR_yellow][2]);
sprintf (text, "r->route: %d", route->route.cnt);
gfx_draw_text (NULL, 80, 144, text, &color[COLOR_yellow][3]);
}
/*
* draw the calculated route..
*/
rtlist = &route->route;
tmplinestyle.width = 3;
tmplinestyle.c = color[COLOR_redgray][3];
draw_routelist (rtlist, tmplinestyle, -1);
};
void draw_routelist (struct rtwaylist *rtlist, struct line_style linestyle, int cnt) {
struct map_hash *mh;
struct map_way *mw;
iPoint p1, p2, center = {gfx_screensize.x/2, gfx_screensize.y/2};
fPoint nd;
int n, i, ps, pe;
struct rtway* rtw = NULL;
if (rtlist) for (i = 0; i < rtlist->cnt && (i < cnt || cnt == -1); i++) {
rtw = &rtlist->array[i];
mh = map_hash_get (rtw->pos.lon, rtw->pos.lat, MHLOAD_RELOAD);
mw = map_way_find (mh, rtw->way.id, rtw->way.sid);
// d_printf ("draw route %d: mw:%p id:%lld subid:%d pos:(%g,%g)", i, mw, route->ways.array[i].way.id, route->ways.array[i].way.sid,
// route->ways.array[i].pos.lon, route->ways.array[i].pos.lat );
if (mw) {
/* go through all the nodes */
if (rtlist == &route->route && i < rtlist->cnt-1) {
ps = rtlist->array[i].pnr;
for (n = 0, pe = mw->p_cnt; n < mw->n_cnt; n++)
if (mw->n[n].d_id == rtlist->array[i+1].way.id && mw->n[n].d_subid == rtlist->array[i+1].way.sid) {
pe = mw->n[n].pnr;
}
if (pe < ps) {
n = pe;
pe = ps;
ps = n;
}
pe++;
if (pe >= mw->p_cnt) pe = mw->p_cnt;
//d_printf ("%d %lld:%d ps:%d pe:%d", i, rtlist->array[i].way.id, rtlist->array[i].way.sid, ps, pe);
}
else {
ps = 0;
pe = mw->p_cnt;
}
for (n = ps; n < pe; n++) {
p2 = p1;
nd.x = map_lon2km (view_lon - mw->p[n].lon, mw->p[n].lat);
nd.y = map_lat2km (view_lat - mw->p[n].lat);
p1.x = center.x - (nd.x / view_scale);
p1.y = center.y + (nd.y / view_scale);
if ((p1.x >= 0 && p1.x < gfx_screensize.x && p1.y >= 0 && p1.y < gfx_screensize.y) ||
(p2.x >= 0 && p2.x < gfx_screensize.x && p2.y >= 0 && p2.y < gfx_screensize.y)) {
if (n > ps) {
draw_lineway (NULL, p1.x, p1.y, p2.x, p2.y, linestyle);
}
}
}
for (n = 0; n < mw->n_cnt; n++) {
nd.x = map_lon2km (view_lon - mw->n[n].d.lon, mw->n[n].d.lat);
nd.y = map_lat2km (view_lat - mw->n[n].d.lat);
p1.x = center.x - (nd.x / view_scale);
p1.y = center.y + (nd.y / view_scale);
nd.x = map_lon2km (view_lon - mw->p[mw->n[n].pnr].lon, mw->p[mw->n[n].pnr].lat);
nd.y = map_lat2km (view_lat - mw->p[mw->n[n].pnr].lat);
p2.x = center.x - (nd.x / view_scale);
p2.y = center.y + (nd.y / view_scale);
if ((p1.x >= 0 && p1.x < gfx_screensize.x && p1.y >= 0 && p1.y < gfx_screensize.y) ||
(p2.x >= 0 && p2.x < gfx_screensize.x && p2.y >= 0 && p2.y < gfx_screensize.y)) {
draw_lineway (NULL, p1.x, p1.y, p2.x, p2.y, linestyle);
}
}
}
}
};