Add:Core:Added autozoom support
authortinloaf <tinloaf@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Tue, 3 Feb 2009 17:11:09 +0000 (17:11 +0000)
committertinloaf <tinloaf@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Tue, 3 Feb 2009 17:11:09 +0000 (17:11 +0000)
git-svn-id: https://navit.svn.sourceforge.net/svnroot/navit/trunk/navit@1998 ffa7fe5e-494d-0410-b361-a75ebd5db220

navit/attr_def.h
navit/navit.c
navit/route.c
navit/route.h
navit/transform.c
navit/transform.h

index 13b632b..b090565 100644 (file)
@@ -98,6 +98,7 @@ ATTR(sat_prn)
 ATTR(sat_elevation)
 ATTR(sat_azimuth)
 ATTR(sat_snr)
+ATTR(autozoom)
 ATTR2(0x00028000,type_boolean_begin)
 /* boolean */
 ATTR(overwrite)
index a709a73..383c234 100644 (file)
@@ -119,6 +119,7 @@ struct navit {
        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;
@@ -473,6 +474,49 @@ navit_scale(struct navit *this_, long scale, struct point *p)
 }
 
 /**
+ * @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
@@ -562,6 +606,7 @@ navit_new(struct attr *parent, struct attr **attrs)
        this_->last_moved = 0;
        this_->center_timeout = 10;
        this_->use_mousewheel = 1;
+       this_->autozoom_secs = 0;
 
        for (;*attrs; attrs++) {
                switch((*attrs)->type) {
@@ -595,6 +640,8 @@ navit_new(struct attr *parent, struct attr **attrs)
                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;
@@ -1655,6 +1702,9 @@ navit_add_attr(struct navit *this_, struct attr *attr)
        case attr_timeout:
                this_->center_timeout = attr->u.num;
                break;
+       case attr_autozoom:
+               this_->autozoom_secs = attr->u.num;
+               break;
        default:
                return 0;
        }
@@ -1819,6 +1869,7 @@ navit_vehicle_update(struct navit *this_, struct navit_vehicle *nv)
        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_);
index 6ea0fce..b02f9a9 100644 (file)
@@ -1541,6 +1541,61 @@ route_path_new_trivial(struct route_graph *this, struct route_info *pos, struct
 }
 
 /**
+ * @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
index 686e163..787bc2b 100644 (file)
@@ -114,6 +114,7 @@ void route_add_callback(struct route *this_, struct callback *cb);
 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 */
 
index 44d499e..91176e6 100644 (file)
@@ -853,6 +853,42 @@ transform_distance_line_sq(struct coord *l0, struct coord *l1, struct coord *ref
        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)
 {
index 44e0d2e..62ce3ff 100644 (file)
@@ -86,6 +86,7 @@ int transform_within_dist_polyline(struct coord *ref, struct coord *c, int count
 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
 }