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"
36 struct street_data *street;
45 struct tracking_line *next;
54 struct transformation t;
56 struct coord last_updated;
57 struct tracking_line *lines;
59 struct tracking_line **last_ptr;
61 struct tracking_line *curr_line;
63 struct coord curr[2], curr_in, curr_out;
65 struct coord last[2], last_in, last_out;
70 int connected_pref=-10;
72 int offroad_limit_pref=5000;
76 tracking_get_pos(struct tracking *tr)
82 tracking_get_segment_pos(struct tracking *tr)
88 tracking_get_street_data(struct tracking *tr)
90 return tr->curr_line->street;
94 tracking_get_current_attr(struct tracking *_this, enum attr_type type, struct attr *attr)
99 if (! _this->curr_line || ! _this->curr_line->street)
101 item=&_this->curr_line->street->item;
102 mr=map_rect_new(item->map,NULL);
103 item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
104 if (item_attr_get(item, type, attr))
106 map_rect_destroy(mr);
111 tracking_get_current_item(struct tracking *_this)
113 if (! _this->curr_line || ! _this->curr_line->street)
115 return &_this->curr_line->street->item;
119 tracking_get_angles(struct tracking_line *tl)
122 struct street_data *sd=tl->street;
123 for (i = 0 ; i < sd->count-1 ; i++)
124 tl->angle[i]=transform_get_angle_delta(&sd->c[i], &sd->c[i+1], 0);
128 tracking_doupdate_lines(struct tracking *tr, struct coord *cc)
131 struct map_selection *sel=route_rect(18, cc, cc, 0, max_dist);
132 struct mapset_handle *h;
136 struct street_data *street;
137 struct tracking_line *tl;
143 h=mapset_open(tr->ms);
144 while ((m=mapset_next(h,1))) {
145 mr=map_rect_new(m, sel);
148 while ((item=map_rect_get_item(mr))) {
149 if (item->type >= type_street_0 && item->type <= type_ferry) {
150 street=street_get_data(item);
151 tl=g_malloc(sizeof(struct tracking_line)+(street->count-1)*sizeof(int));
153 tracking_get_angles(tl);
158 map_rect_destroy(mr);
161 map_selection_destroy(sel);
165 struct transformation t;
167 tr->last_ptr=&tr->lines;
168 transform_setup_source_rect_limit(&t,c,1000);
169 transform_setup_source_rect_limit(&tr->t,c,1000);
173 street_get_block(tr->ma,&t,tst_callback,tr);
174 profile_timer("end");
180 tracking_free_lines(struct tracking *tr)
182 struct tracking_line *tl=tr->lines,*next;
183 dbg(1,"enter(tr=%p)\n", tr);
187 street_data_free(tl->street);
195 tracking_angle_abs_diff(int a1, int a2, int full)
209 tracking_angle_delta(int vehicle_angle, int street_angle, int flags)
216 street_angle=(street_angle+180)%360;
221 ret=tracking_angle_abs_diff(vehicle_angle, street_angle, full);
227 tracking_is_connected(struct coord *c1, struct coord *c2)
229 if (c1[0].x == c2[0].x && c1[0].y == c2[0].y)
231 if (c1[0].x == c2[1].x && c1[0].y == c2[1].y)
233 if (c1[1].x == c2[0].x && c1[1].y == c2[0].y)
235 if (c1[1].x == c2[1].x && c1[1].y == c2[1].y)
241 tracking_value(struct tracking *tr, struct tracking_line *t, int offset, struct coord *lpnt, int flags)
244 struct street_data *sd=t->street;
245 dbg(2, "%d: (0x%x,0x%x)-(0x%x,0x%x)\n", offset, sd->c[offset].x, sd->c[offset].y, sd->c[offset+1].x, sd->c[offset+1].y);
247 value+=transform_distance_line_sq(&sd->c[offset], &sd->c[offset+1], &tr->curr_in, lpnt);
248 if (value >= INT_MAX/2)
252 value += tracking_angle_delta(tr->curr_angle, t->angle[offset], sd->flags)*angle_factor>>4;
254 if (tracking_is_connected(tr->last, &sd->c[offset]))
255 value += connected_pref;
258 if (lpnt->x == tr->last_out.x && lpnt->y == tr->last_out.y)
259 value += nostop_pref;
267 tracking_update(struct tracking *tr, struct coord *c, int angle)
269 struct tracking_line *t;
276 dbg(1,"enter(%p,%p,%d)\n", tr, c, angle);
277 dbg(1,"c=0x%x,0x%x\n", c->x, c->y);
279 if (c->x == tr->curr_in.x && c->y == tr->curr_in.y) {
280 if (tr->curr_out.x && tr->curr_out.y)
284 tr->last_in=tr->curr_in;
285 tr->last_out=tr->curr_out;
286 tr->last[0]=tr->curr[0];
287 tr->last[1]=tr->curr[1];
289 tr->curr_angle=angle;
290 if (!tr->lines || transform_distance_sq(&tr->last_updated, c) > 250000) {
292 tracking_free_lines(tr);
293 tracking_doupdate_lines(tr, c);
295 dbg(1,"update end\n");
303 struct street_data *sd=t->street;
304 if ((sd->flags & 3) == 3) {
308 for (i = 0; i < sd->count-1 ; i++) {
309 value=tracking_value(tr,t,i,&lpnt,-1);
310 if (value < INT_MAX/2 && (! tr->curr_line || value < min)) {
313 tr->curr[0]=sd->c[i];
314 tr->curr[1]=sd->c[i+1];
315 dbg(1,"lpnt.x=0x%x,lpnt.y=0x%x pos=%d %d+%d+%d+%d=%d\n", lpnt.x, lpnt.y, i,
316 transform_distance_line_sq(&sd->c[i], &sd->c[i+1], c, &lpnt),
317 tracking_angle_delta(angle, t->angle[i], 0)*angle_factor,
318 tracking_is_connected(tr->last, &sd->c[i]) ? connected_pref : 0,
319 lpnt.x == tr->last_out.x && lpnt.y == tr->last_out.y ? nostop_pref : 0,
328 dbg(0,"tr->curr_line=%p min=%d\n", tr->curr_line, min);
329 if (!tr->curr_line || min > offroad_limit_pref)
331 dbg(0,"found 0x%x,0x%x\n", tr->curr_out.x, tr->curr_out.y);
337 tracking_new(struct mapset *ms)
339 struct tracking *this=g_new0(struct tracking, 1);
346 tracking_set_mapset(struct tracking *this, struct mapset *ms)
352 tracking_destroy(struct tracking *tr)
354 tracking_free_lines(tr);
359 tracking_get_map(struct tracking *this_)
362 this_->map=map_new((struct attr*[]){
363 &(struct attr){attr_type,{"tracking"}},
364 &(struct attr){attr_trackingo,.u.tracking=this_},
365 &(struct attr){attr_data,{""}},
366 &(struct attr){attr_description,{"Tracking"}},
373 struct tracking *tracking;
376 struct map_rect_priv {
377 struct tracking *tracking;
379 struct tracking_line *curr,*next;
381 enum attr_type attr_next;
388 tracking_map_item_coord_get(void *priv_data, struct coord *c, int count)
390 struct map_rect_priv *this=priv_data;
393 while (this->ccount < 2 && count > 0) {
394 *c=this->curr->street->c[this->ccount+this->coord];
395 dbg(1,"coord %d 0x%x,0x%x\n",this->ccount,c->x,c->y);
405 tracking_map_item_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
407 struct map_rect_priv *this_=priv_data;
408 attr->type=attr_type;
409 struct coord lpnt,*c;
410 struct tracking *tr=this_->tracking;
420 switch(this_->debug_idx) {
423 this_->str=attr->u.str=g_strdup_printf("overall: %d",tracking_value(tr, this_->curr, this_->coord, &lpnt, -1));
427 c=&this_->curr->street->c[this_->coord];
428 value=tracking_value(tr, this_->curr, this_->coord, &lpnt, 1);
429 this_->str=attr->u.str=g_strdup_printf("distance: (0x%x,0x%x) from (0x%x,0x%x)-(0x%x,0x%x) at (0x%x,0x%x) %d",
430 tr->curr_in.x, tr->curr_in.y,
431 c[0].x, c[0].y, c[1].x, c[1].y,
432 lpnt.x, lpnt.y, value);
436 this_->str=attr->u.str=g_strdup_printf("angle: %d to %d (flags %d) %d",
437 tr->curr_angle, this_->curr->angle[this_->coord], this_->curr->street->flags & 3,
438 tracking_value(tr, this_->curr, this_->coord, &lpnt, 2));
442 this_->str=attr->u.str=g_strdup_printf("line %p", this_->curr);
445 this_->attr_next=attr_none;
449 while (this_->attr_next != attr_none) {
450 if (tracking_map_item_attr_get(priv_data, this_->attr_next, attr))
455 attr->type=attr_none;
460 static struct item_methods tracking_map_item_methods = {
462 tracking_map_item_coord_get,
464 tracking_map_item_attr_get,
469 tracking_map_destroy(struct map_priv *priv)
475 tracking_map_rect_init(struct map_rect_priv *priv)
477 priv->next=priv->tracking->lines;
484 static struct map_rect_priv *
485 tracking_map_rect_new(struct map_priv *priv, struct map_selection *sel)
487 struct tracking *tracking=priv->tracking;
488 struct map_rect_priv *ret=g_new0(struct map_rect_priv, 1);
489 ret->tracking=tracking;
490 tracking_map_rect_init(ret);
491 ret->item.meth=&tracking_map_item_methods;
492 ret->item.priv_data=ret;
493 ret->item.type=type_tracking_100;
498 tracking_map_rect_destroy(struct map_rect_priv *priv)
504 tracking_map_get_item(struct map_rect_priv *priv)
506 struct item *ret=&priv->item;
512 if (! priv->curr || priv->coord + 2 >= priv->curr->street->count) {
513 priv->curr=priv->next;
514 priv->next=priv->curr->next;
522 value=tracking_value(priv->tracking, priv->curr, priv->coord, &lpnt, -1);
524 priv->item.type=type_tracking_100;
525 else if (value < 128)
526 priv->item.type=type_tracking_90;
527 else if (value < 256)
528 priv->item.type=type_tracking_80;
529 else if (value < 512)
530 priv->item.type=type_tracking_70;
531 else if (value < 1024)
532 priv->item.type=type_tracking_60;
533 else if (value < 2048)
534 priv->item.type=type_tracking_50;
535 else if (value < 4096)
536 priv->item.type=type_tracking_40;
537 else if (value < 8192)
538 priv->item.type=type_tracking_30;
539 else if (value < 16384)
540 priv->item.type=type_tracking_20;
541 else if (value < 32768)
542 priv->item.type=type_tracking_10;
544 priv->item.type=type_tracking_0;
545 dbg(1,"item %d %d points\n", priv->coord, priv->curr->street->count);
547 priv->attr_next=attr_debug;
553 tracking_map_get_item_byid(struct map_rect_priv *priv, int id_hi, int id_lo)
556 tracking_map_rect_init(priv);
557 while ((ret=tracking_map_get_item(priv))) {
558 if (ret->id_hi == id_hi && ret->id_lo == id_lo)
564 static struct map_methods tracking_map_meth = {
567 tracking_map_destroy,
568 tracking_map_rect_new,
569 tracking_map_rect_destroy,
570 tracking_map_get_item,
571 tracking_map_get_item_byid,
577 static struct map_priv *
578 tracking_map_new(struct map_methods *meth, struct attr **attrs)
580 struct map_priv *ret;
581 struct attr *tracking_attr;
583 tracking_attr=attr_search(attrs, NULL, attr_trackingo);
586 ret=g_new0(struct map_priv, 1);
587 *meth=tracking_map_meth;
588 ret->tracking=tracking_attr->u.tracking;
597 plugin_register_map_type("tracking", tracking_map_new);