ATTR(sat_elevation)
ATTR(sat_azimuth)
ATTR(sat_snr)
+ATTR(autozoom)
ATTR2(0x00028000,type_boolean_begin)
/* boolean */
ATTR(overwrite)
int button_pressed,moved,popped,zoomed;
time_t last_moved;
int center_timeout;
+ int autozoom_secs;
struct event_timeout *button_timeout, *motion_timeout;
struct callback *motion_timeout_callback;
int ignore_button;
}
/**
+ * @brief Automatically adjusts zoom level
+ *
+ * This function automatically adjusts the current
+ * zoom level according to the current speed.
+ *
+ * @param this_ The navit struct
+ * @param speed The vehicles speed in meters per second
+ */
+static void
+navit_autozoom(struct navit *this_, struct coord *center, int speed)
+{
+ struct coord c;
+ struct point pc;
+ int distance;
+ long scale;
+ double factor;
+
+ if (this_->autozoom_secs <= 0) {
+ return;
+ }
+
+ distance = speed * this_->autozoom_secs;
+
+ if (route_get_path_set(this_->route)) {
+ c = route_get_coord_dist(this_->route, distance);
+ } else {
+ return;
+ }
+
+ transform(this_->trans, transform_get_projection(this_->trans), center, &pc, 1, 0, 0, NULL);
+ factor = transform_get_autozoom_factor(this_->trans, &pc, &c);
+
+ if ((factor < 1.1) && (factor > 0.9)) {
+ return;
+ }
+
+ scale = transform_get_scale(this_->trans);
+ scale = (scale * factor);
+
+ navit_scale(this_, scale, &pc);
+}
+
+/**
* Change the current zoom level, zooming closer to the ground
*
* @param navit The navit instance
this_->last_moved = 0;
this_->center_timeout = 10;
this_->use_mousewheel = 1;
+ this_->autozoom_secs = 0;
for (;*attrs; attrs++) {
switch((*attrs)->type) {
case attr_timeout:
this_->center_timeout = (*attrs)->u.num;
break;
+ case attr_autozoom:
+ this_->autozoom_secs = (*attrs)->u.num;
default:
dbg(0, "Unexpected attribute %x\n",(*attrs)->type);
break;
case attr_timeout:
this_->center_timeout = attr->u.num;
break;
+ case attr_autozoom:
+ this_->autozoom_secs = attr->u.num;
+ break;
default:
return 0;
}
if ((nv->follow_curr == 1) && (!this_->button_pressed)) {
if (this_->cursor_flag && ((time(NULL) - this_->last_moved) > this_->center_timeout) && (recenter)) {
navit_set_center_cursor(this_, &nv->coord, nv->dir, 50, 80);
+ navit_autozoom(this_, &nv->coord, nv->speed);
pnt=NULL;
} else { // We don't want to center, but redraw because otherwise the old route "lags"
navit_draw(this_);
}
/**
+ * @brief Returns a coordinate at a given distance
+ *
+ * This function returns the coordinate, where the user will be if he
+ * follows the current route for a certain distance.
+ *
+ * @param this_ The route we're driving upon
+ * @param dist The distance in meters
+ * @return The coordinate where the user will be in that distance
+ */
+struct coord
+route_get_coord_dist(struct route *this_, int dist)
+{
+ int d,l,i,len;
+ int dx,dy;
+ double frac;
+ struct route_path_segment *cur;
+ struct coord ret;
+
+ d = dist;
+
+ if (!this_->path2) {
+ return this_->pos->c;
+ }
+
+ ret = this_->pos->c;
+ cur = this_->path2->path;
+ while (cur) {
+ if (cur->length < d) {
+ d -= cur->length;
+ } else {
+ for (i=0; i < (cur->ncoords-1); i++) {
+ l = d;
+ len = (int)transform_polyline_length(route_projection(this_), (cur->c + i), 2);
+ d -= len;
+ if (d <= 0) {
+ // We interpolate a bit here...
+ frac = (double)l / len;
+
+ dx = (cur->c + i + 1)->x - (cur->c + i)->x;
+ dy = (cur->c + i + 1)->y - (cur->c + i)->y;
+
+ ret.x = (cur->c + i)->x + (frac * dx);
+ ret.y = (cur->c + i)->y + (frac * dy);
+ return ret;
+ }
+ }
+ return cur->c[(cur->ncoords-1)];
+ }
+ cur = cur->next;
+ }
+
+ return this_->dst->c;
+}
+
+/**
* @brief Creates a new route path
*
* This creates a new non-trivial route. It therefore needs the routing information created by route_graph_flood, so
void route_remove_callback(struct route *this_, struct callback *cb);
void route_init(void);
int route_pos_contains(struct route *this, struct item *item);
+struct coord route_get_coord_dist(struct route *this_, int dist);
/* end of prototypes */
return transform_distance_sq(&l, ref);
}
+double
+transform_get_autozoom_factor(struct transformation *this_, struct point *center, struct coord *c)
+{
+ struct point p;
+ struct map_selection *ms=this_->screen_sel;
+ double fx=0,fy=0,nfx,nfy;
+
+ transform(this_, transform_get_projection(this_), c, &p, 1, 0, 0, NULL);
+
+ while (ms) {
+ struct point_rect *r=&ms->u.p_rect;
+ if (p.x > center->x) {
+ nfx = (double)(p.x - center->x) / (r->rl.x - center->x);
+ } else {
+ nfx = (double)(p.x - center->x) / (r->lu.x - center->x);
+ }
+
+ if (p.y < center->y) {
+ nfy = (double)(p.y - center->y) / (double)(r->lu.y - center->y) ;
+ } else {
+ nfy = (double)(p.y - center->y) / (double)(r->rl.y - center->y);
+ }
+
+ if ((nfx < fx) || (fx == 0)) {
+ fx = nfx;
+ }
+ if ((nfy < fy) || (fy == 0)) {
+ fy = nfy;
+ }
+
+ ms=ms->next;
+ }
+
+ return (fy < fx) ? fx : fy;
+}
+
int
transform_distance_polyline_sq(struct coord *c, int count, struct coord *ref, struct coord *lpnt, int *pos)
{
int transform_within_dist_polygon(struct coord *ref, struct coord *c, int count, int dist);
int transform_within_dist_item(struct coord *ref, enum item_type type, struct coord *c, int count, int dist);
void transform_destroy(struct transformation *t);
+double transform_get_autozoom_factor(struct transformation *this_, struct point *center, struct coord *c);
/* end of prototypes */
#ifdef __cplusplus
}