2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
26 #include "transform.h"
29 #include "projection.h"
35 struct street_data *street;
44 struct tracking_line *next;
52 struct transformation t;
54 struct coord last_updated;
55 struct tracking_line *lines;
57 struct tracking_line **last_ptr;
59 struct tracking_line *curr_line;
63 struct coord last_out;
68 int connected_pref=-10;
70 int offroad_limit_pref=5000;
74 tracking_get_pos(struct tracking *tr)
80 tracking_get_segment_pos(struct tracking *tr)
86 tracking_get_street_data(struct tracking *tr)
88 return tr->curr_line->street;
92 tracking_get_current_attr(struct tracking *_this, enum attr_type type, struct attr *attr)
97 if (! _this->curr_line || ! _this->curr_line->street)
99 item=&_this->curr_line->street->item;
100 mr=map_rect_new(item->map,NULL);
101 item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
102 if (item_attr_get(item, type, attr))
104 map_rect_destroy(mr);
109 tracking_get_current_item(struct tracking *_this)
111 if (! _this->curr_line || ! _this->curr_line->street)
113 return &_this->curr_line->street->item;
117 tracking_get_angles(struct tracking_line *tl)
120 struct street_data *sd=tl->street;
121 for (i = 0 ; i < sd->count-1 ; i++)
122 tl->angle[i]=transform_get_angle_delta(&sd->c[i], &sd->c[i+1], 0);
126 tracking_doupdate_lines(struct tracking *tr, struct coord *cc)
129 struct map_selection *sel=route_rect(18, cc, cc, 0, max_dist);
130 struct mapset_handle *h;
134 struct street_data *street;
135 struct tracking_line *tl;
141 h=mapset_open(tr->ms);
142 while ((m=mapset_next(h,1))) {
143 mr=map_rect_new(m, sel);
146 while ((item=map_rect_get_item(mr))) {
147 if (item->type >= type_street_0 && item->type <= type_ferry) {
148 street=street_get_data(item);
149 tl=g_malloc(sizeof(struct tracking_line)+(street->count-1)*sizeof(int));
151 tracking_get_angles(tl);
156 map_rect_destroy(mr);
159 map_selection_destroy(sel);
163 struct transformation t;
165 tr->last_ptr=&tr->lines;
166 transform_setup_source_rect_limit(&t,c,1000);
167 transform_setup_source_rect_limit(&tr->t,c,1000);
171 street_get_block(tr->ma,&t,tst_callback,tr);
172 profile_timer("end");
178 tracking_free_lines(struct tracking *tr)
180 struct tracking_line *tl=tr->lines,*next;
181 dbg(1,"enter(tr=%p)\n", tr);
185 street_data_free(tl->street);
193 tracking_angle_abs_diff(int a1, int a2, int full)
207 tracking_angle_delta(int vehicle_angle, int street_angle, int dir)
214 street_angle=(street_angle+180)%360;
216 ret=tracking_angle_abs_diff(vehicle_angle, street_angle, full);
222 tracking_is_connected(struct coord *c1, struct coord *c2)
224 if (c1[0].x == c2[0].x && c1[0].y == c2[0].y)
226 if (c1[0].x == c2[1].x && c1[0].y == c2[1].y)
228 if (c1[1].x == c2[0].x && c1[1].y == c2[0].y)
230 if (c1[1].x == c2[1].x && c1[1].y == c2[1].y)
236 tracking_update(struct tracking *tr, struct coord *c, int angle)
238 struct tracking_line *t;
245 dbg(1,"enter(%p,%p,%d)\n", tr, c, angle);
246 dbg(1,"c=0x%x,0x%x\n", c->x, c->y);
248 if (c->x == tr->last_in.x && c->y == tr->last_in.y) {
249 if (tr->last_out.x && tr->last_out.y)
254 if (!tr->lines || transform_distance_sq(&tr->last_updated, c) > 250000) {
256 tracking_free_lines(tr);
257 tracking_doupdate_lines(tr, c);
259 dbg(1,"update end\n");
267 struct street_data *sd=t->street;
269 switch(sd->flags & AF_ONEWAYMASK) {
283 for (i = 0; i < sd->count-1 ; i++) {
284 dbg(2, "%d: (0x%x,0x%x)-(0x%x,0x%x)\n", i, sd->c[i].x, sd->c[i].y, sd->c[i+1].x, sd->c[i+1].y);
285 value=transform_distance_line_sq(&sd->c[i], &sd->c[i+1], c, &lpnt);
286 if (value < INT_MAX/2) {
287 value += tracking_angle_delta(angle, t->angle[i], dir)*angle_factor>>4;
288 if (tracking_is_connected(tr->curr, &sd->c[i]))
289 value += connected_pref;
290 if (lpnt.x == tr->last_out.x && lpnt.y == tr->last_out.y)
291 value += nostop_pref;
292 if (! tr->curr_line || value < min) {
295 tr->curr[0]=sd->c[i];
296 tr->curr[1]=sd->c[i+1];
297 dbg(1,"lpnt.x=0x%x,lpnt.y=0x%x pos=%d %d+%d+%d+%d=%d\n", lpnt.x, lpnt.y, i,
298 transform_distance_line_sq(&sd->c[i], &sd->c[i+1], c, &lpnt),
299 tracking_angle_delta(angle, t->angle[i], 0)*angle_factor,
300 tracking_is_connected(tr->curr, &sd->c[i]) ? connected_pref : 0,
301 lpnt.x == tr->last_out.x && lpnt.y == tr->last_out.y ? nostop_pref : 0,
312 dbg(1,"tr->curr_line=%p min=%d\n", tr->curr_line, min);
313 if (!tr->curr_line || min > offroad_limit_pref)
315 dbg(1,"found 0x%x,0x%x\n", tr->last_out.x, tr->last_out.y);
321 tracking_new(struct mapset *ms)
323 struct tracking *this=g_new0(struct tracking, 1);
330 tracking_set_mapset(struct tracking *this, struct mapset *ms)
336 tracking_destroy(struct tracking *tr)
338 tracking_free_lines(tr);