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;
55 struct transformation t;
57 struct pcoord last_updated;
58 struct tracking_line *lines;
60 struct tracking_line **last_ptr;
62 struct tracking_line *curr_line;
65 struct pcoord curr_in, curr_out;
68 struct pcoord last_in, last_out;
73 int connected_pref=10;
75 int offroad_limit_pref=5000;
80 tracking_get_pos(struct tracking *tr)
86 tracking_get_segment_pos(struct tracking *tr)
92 tracking_get_street_data(struct tracking *tr)
95 return tr->curr_line->street;
100 tracking_get_current_attr(struct tracking *_this, enum attr_type type, struct attr *attr)
105 if (! _this->curr_line || ! _this->curr_line->street)
107 item=&_this->curr_line->street->item;
108 mr=map_rect_new(item->map,NULL);
109 item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
110 if (item_attr_get(item, type, attr))
112 map_rect_destroy(mr);
117 tracking_get_current_item(struct tracking *_this)
119 if (! _this->curr_line || ! _this->curr_line->street)
121 return &_this->curr_line->street->item;
125 tracking_get_angles(struct tracking_line *tl)
128 struct street_data *sd=tl->street;
129 for (i = 0 ; i < sd->count-1 ; i++)
130 tl->angle[i]=transform_get_angle_delta(&sd->c[i], &sd->c[i+1], 0);
134 street_data_within_selection(struct street_data *sd, struct map_selection *sel)
137 struct map_selection *curr;
144 for (i = 1 ; i < sd->count ; i++) {
145 if (r.lu.x > sd->c[i].x)
147 if (r.rl.x < sd->c[i].x)
149 if (r.rl.y > sd->c[i].y)
151 if (r.lu.y < sd->c[i].y)
156 struct coord_rect *sr=&curr->u.c_rect;
157 if (r.lu.x <= sr->rl.x && r.rl.x >= sr->lu.x &&
158 r.lu.y >= sr->rl.y && r.rl.y <= sr->lu.y)
167 tracking_doupdate_lines(struct tracking *tr, struct pcoord *pc)
170 struct map_selection *sel;
171 struct mapset_handle *h;
175 struct street_data *street;
176 struct tracking_line *tl;
181 h=mapset_open(tr->ms);
182 while ((m=mapset_next(h,1))) {
185 if (map_projection(m) != pc->pro) {
186 transform_to_geo(pc->pro, &cc, &g);
187 transform_from_geo(map_projection(m), &g, &cc);
189 sel = route_rect(18, &cc, &cc, 0, max_dist);
190 mr=map_rect_new(m, sel);
193 while ((item=map_rect_get_item(mr))) {
194 if (item->type >= type_street_0 && item->type <= type_ferry) {
195 street=street_get_data(item);
196 if (street_data_within_selection(street, sel)) {
197 tl=g_malloc(sizeof(struct tracking_line)+(street->count-1)*sizeof(int));
199 tracking_get_angles(tl);
203 street_data_free(street);
206 map_selection_destroy(sel);
207 map_rect_destroy(mr);
213 struct transformation t;
215 tr->last_ptr=&tr->lines;
216 transform_setup_source_rect_limit(&t,c,1000);
217 transform_setup_source_rect_limit(&tr->t,c,1000);
221 street_get_block(tr->ma,&t,tst_callback,tr);
222 profile_timer("end");
228 tracking_free_lines(struct tracking *tr)
230 struct tracking_line *tl=tr->lines,*next;
231 dbg(1,"enter(tr=%p)\n", tr);
235 street_data_free(tl->street);
243 tracking_angle_abs_diff(int a1, int a2, int full)
257 tracking_angle_delta(int vehicle_angle, int street_angle, int flags)
264 street_angle=(street_angle+180)%360;
269 ret=tracking_angle_abs_diff(vehicle_angle, street_angle, full);
275 tracking_is_connected(struct coord *c1, struct coord *c2)
277 if (c1[0].x == c2[0].x && c1[0].y == c2[0].y)
279 if (c1[0].x == c2[1].x && c1[0].y == c2[1].y)
281 if (c1[1].x == c2[0].x && c1[1].y == c2[0].y)
283 if (c1[1].x == c2[1].x && c1[1].y == c2[1].y)
285 return connected_pref;
289 tracking_is_no_stop(struct coord *c1, struct pcoord *c2)
291 if (c1->x == c2->x && c1->y == c2->y)
297 tracking_is_on_route(struct route *rt, struct item *item)
301 if (route_pos_contains(rt, item))
303 if (route_contains(rt, item))
309 tracking_value(struct tracking *tr, struct tracking_line *t, int offset, struct coord *lpnt, int min, int flags)
312 struct street_data *sd=t->street;
313 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);
315 struct coord c1, c2, cp;
316 c1.x = sd->c[offset].x;
317 c1.y = sd->c[offset].y;
318 c2.x = sd->c[offset+1].x;
319 c2.y = sd->c[offset+1].y;
320 cp.x = tr->curr_in.x;
321 cp.y = tr->curr_in.y;
322 value+=transform_distance_line_sq(&c1, &c2, &cp, lpnt);
327 value += tracking_angle_delta(tr->curr_angle, t->angle[offset], sd->flags)*angle_factor>>4;
331 value += tracking_is_connected(tr->last, &sd->c[offset]);
333 value += tracking_is_no_stop(lpnt, &tr->last_out);
337 value += tracking_is_on_route(tr->rt, &sd->item);
343 tracking_update(struct tracking *tr, struct pcoord *pc, int angle)
345 struct tracking_line *t;
353 dbg(1,"enter(%p,%p,%d)\n", tr, pc, angle);
354 dbg(1,"c=%d:0x%x,0x%x\n", pc->pro, pc->x, pc->y);
356 if (pc->x == tr->curr_in.x && pc->y == tr->curr_in.y) {
357 if (tr->curr_out.x && tr->curr_out.y)
361 tr->last_in=tr->curr_in;
362 tr->last_out=tr->curr_out;
363 tr->last[0]=tr->curr[0];
364 tr->last[1]=tr->curr[1];
366 tr->curr_angle=angle;
369 if (!tr->lines || transform_distance_sq_pc(&tr->last_updated, pc) > 250000) {
371 tracking_free_lines(tr);
372 tracking_doupdate_lines(tr, pc);
373 tr->last_updated=*pc;
374 dbg(1,"update end\n");
383 struct street_data *sd=t->street;
384 if ((sd->flags & 3) == 3) {
388 for (i = 0; i < sd->count-1 ; i++) {
389 value=tracking_value(tr,t,i,&lpnt,min,-1);
393 tr->curr[0]=sd->c[i];
394 tr->curr[1]=sd->c[i+1];
395 dbg(1,"lpnt.x=0x%x,lpnt.y=0x%x pos=%d %d+%d+%d+%d=%d\n", lpnt.x, lpnt.y, i,
396 transform_distance_line_sq(&sd->c[i], &sd->c[i+1], &cin, &lpnt),
397 tracking_angle_delta(angle, t->angle[i], 0)*angle_factor,
398 tracking_is_connected(tr->last, &sd->c[i]) ? connected_pref : 0,
399 lpnt.x == tr->last_out.x && lpnt.y == tr->last_out.y ? nostop_pref : 0,
402 tr->curr_out.x=lpnt.x;
403 tr->curr_out.y=lpnt.y;
404 tr->curr_out.pro = pc->pro;
410 dbg(1,"tr->curr_line=%p min=%d\n", tr->curr_line, min);
411 if (!tr->curr_line || min > offroad_limit_pref)
413 dbg(1,"found 0x%x,0x%x\n", tr->curr_out.x, tr->curr_out.y);
419 tracking_new(struct attr *parent, struct attr **attrs)
421 struct tracking *this=g_new0(struct tracking, 1);
427 tracking_set_mapset(struct tracking *this, struct mapset *ms)
433 tracking_set_route(struct tracking *this, struct route *rt)
439 tracking_destroy(struct tracking *tr)
441 tracking_free_lines(tr);
446 tracking_get_map(struct tracking *this_)
449 this_->map=map_new(NULL, (struct attr*[]){
450 &(struct attr){attr_type,{"tracking"}},
451 &(struct attr){attr_trackingo,.u.tracking=this_},
452 &(struct attr){attr_data,{""}},
453 &(struct attr){attr_description,{"Tracking"}},
460 struct tracking *tracking;
463 struct map_rect_priv {
464 struct tracking *tracking;
466 struct tracking_line *curr,*next;
468 enum attr_type attr_next;
475 tracking_map_item_coord_get(void *priv_data, struct coord *c, int count)
477 struct map_rect_priv *this=priv_data;
481 while (this->ccount < 2 && count > 0) {
482 pro = map_projection(this->curr->street->item.map);
483 if (projection_mg != pro) {
484 transform_from_to(&this->curr->street->c[this->ccount+this->coord],
488 *c=this->curr->street->c[this->ccount+this->coord];
489 dbg(1,"coord %d 0x%x,0x%x\n",this->ccount,c->x,c->y);
499 tracking_map_item_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
501 struct map_rect_priv *this_=priv_data;
502 attr->type=attr_type;
503 struct coord lpnt,*c;
504 struct tracking *tr=this_->tracking;
514 switch(this_->debug_idx) {
517 this_->str=attr->u.str=g_strdup_printf("overall: %d",tracking_value(tr, this_->curr, this_->coord, &lpnt, INT_MAX/2, -1));
521 c=&this_->curr->street->c[this_->coord];
522 value=tracking_value(tr, this_->curr, this_->coord, &lpnt, INT_MAX/2, 1);
523 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",
524 tr->curr_in.x, tr->curr_in.y,
525 c[0].x, c[0].y, c[1].x, c[1].y,
526 lpnt.x, lpnt.y, value);
530 this_->str=attr->u.str=g_strdup_printf("angle: %d to %d (flags %d) %d",
531 tr->curr_angle, this_->curr->angle[this_->coord], this_->curr->street->flags & 3,
532 tracking_value(tr, this_->curr, this_->coord, &lpnt, INT_MAX/2, 2));
536 this_->str=attr->u.str=g_strdup_printf("connected: %d", tracking_value(tr, this_->curr, this_->coord, &lpnt, INT_MAX/2, 4));
540 this_->str=attr->u.str=g_strdup_printf("no_stop: %d", tracking_value(tr, this_->curr, this_->coord, &lpnt, INT_MAX/2, 8));
544 this_->str=attr->u.str=g_strdup_printf("route: %d", tracking_value(tr, this_->curr, this_->coord, &lpnt, INT_MAX/2, 16));
548 this_->str=attr->u.str=g_strdup_printf("line %p", this_->curr);
551 this_->attr_next=attr_none;
555 while (this_->attr_next != attr_none) {
556 if (tracking_map_item_attr_get(priv_data, this_->attr_next, attr))
561 attr->type=attr_none;
566 static struct item_methods tracking_map_item_methods = {
568 tracking_map_item_coord_get,
570 tracking_map_item_attr_get,
575 tracking_map_destroy(struct map_priv *priv)
581 tracking_map_rect_init(struct map_rect_priv *priv)
583 priv->next=priv->tracking->lines;
590 static struct map_rect_priv *
591 tracking_map_rect_new(struct map_priv *priv, struct map_selection *sel)
593 struct tracking *tracking=priv->tracking;
594 struct map_rect_priv *ret=g_new0(struct map_rect_priv, 1);
595 ret->tracking=tracking;
596 tracking_map_rect_init(ret);
597 ret->item.meth=&tracking_map_item_methods;
598 ret->item.priv_data=ret;
599 ret->item.type=type_tracking_100;
604 tracking_map_rect_destroy(struct map_rect_priv *priv)
610 tracking_map_get_item(struct map_rect_priv *priv)
612 struct item *ret=&priv->item;
618 if (! priv->curr || priv->coord + 2 >= priv->curr->street->count) {
619 priv->curr=priv->next;
620 priv->next=priv->curr->next;
628 value=tracking_value(priv->tracking, priv->curr, priv->coord, &lpnt, INT_MAX/2, -1);
630 priv->item.type=type_tracking_100;
631 else if (value < 128)
632 priv->item.type=type_tracking_90;
633 else if (value < 256)
634 priv->item.type=type_tracking_80;
635 else if (value < 512)
636 priv->item.type=type_tracking_70;
637 else if (value < 1024)
638 priv->item.type=type_tracking_60;
639 else if (value < 2048)
640 priv->item.type=type_tracking_50;
641 else if (value < 4096)
642 priv->item.type=type_tracking_40;
643 else if (value < 8192)
644 priv->item.type=type_tracking_30;
645 else if (value < 16384)
646 priv->item.type=type_tracking_20;
647 else if (value < 32768)
648 priv->item.type=type_tracking_10;
650 priv->item.type=type_tracking_0;
651 dbg(1,"item %d %d points\n", priv->coord, priv->curr->street->count);
653 priv->attr_next=attr_debug;
659 tracking_map_get_item_byid(struct map_rect_priv *priv, int id_hi, int id_lo)
662 tracking_map_rect_init(priv);
663 while ((ret=tracking_map_get_item(priv))) {
664 if (ret->id_hi == id_hi && ret->id_lo == id_lo)
670 static struct map_methods tracking_map_meth = {
673 tracking_map_destroy,
674 tracking_map_rect_new,
675 tracking_map_rect_destroy,
676 tracking_map_get_item,
677 tracking_map_get_item_byid,
683 static struct map_priv *
684 tracking_map_new(struct map_methods *meth, struct attr **attrs)
686 struct map_priv *ret;
687 struct attr *tracking_attr;
689 tracking_attr=attr_search(attrs, NULL, attr_trackingo);
692 ret=g_new0(struct map_priv, 1);
693 *meth=tracking_map_meth;
694 ret->tracking=tracking_attr->u.tracking;
703 plugin_register_map_type("tracking", tracking_map_new);