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)
94 return tr->curr_line->street;
98 tracking_get_current_attr(struct tracking *_this, enum attr_type type, struct attr *attr)
103 if (! _this->curr_line || ! _this->curr_line->street)
105 item=&_this->curr_line->street->item;
106 mr=map_rect_new(item->map,NULL);
107 item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
108 if (item_attr_get(item, type, attr))
110 map_rect_destroy(mr);
115 tracking_get_current_item(struct tracking *_this)
117 if (! _this->curr_line || ! _this->curr_line->street)
119 return &_this->curr_line->street->item;
123 tracking_get_angles(struct tracking_line *tl)
126 struct street_data *sd=tl->street;
127 for (i = 0 ; i < sd->count-1 ; i++)
128 tl->angle[i]=transform_get_angle_delta(&sd->c[i], &sd->c[i+1], 0);
132 tracking_doupdate_lines(struct tracking *tr, struct pcoord *pc)
135 struct map_selection *sel;
136 struct mapset_handle *h;
140 struct street_data *street;
141 struct tracking_line *tl;
146 h=mapset_open(tr->ms);
147 while ((m=mapset_next(h,1))) {
150 if (map_projection(m) != pc->pro) {
151 transform_to_geo(pc->pro, &cc, &g);
152 transform_from_geo(map_projection(m), &g, &cc);
154 sel = route_rect(18, &cc, &cc, 0, max_dist);
155 mr=map_rect_new(m, sel);
158 while ((item=map_rect_get_item(mr))) {
159 if (item->type >= type_street_0 && item->type <= type_ferry) {
160 street=street_get_data(item);
161 tl=g_malloc(sizeof(struct tracking_line)+(street->count-1)*sizeof(int));
163 tracking_get_angles(tl);
168 map_selection_destroy(sel);
169 map_rect_destroy(mr);
175 struct transformation t;
177 tr->last_ptr=&tr->lines;
178 transform_setup_source_rect_limit(&t,c,1000);
179 transform_setup_source_rect_limit(&tr->t,c,1000);
183 street_get_block(tr->ma,&t,tst_callback,tr);
184 profile_timer("end");
190 tracking_free_lines(struct tracking *tr)
192 struct tracking_line *tl=tr->lines,*next;
193 dbg(1,"enter(tr=%p)\n", tr);
197 street_data_free(tl->street);
205 tracking_angle_abs_diff(int a1, int a2, int full)
219 tracking_angle_delta(int vehicle_angle, int street_angle, int flags)
226 street_angle=(street_angle+180)%360;
231 ret=tracking_angle_abs_diff(vehicle_angle, street_angle, full);
237 tracking_is_connected(struct coord *c1, struct coord *c2)
239 if (c1[0].x == c2[0].x && c1[0].y == c2[0].y)
241 if (c1[0].x == c2[1].x && c1[0].y == c2[1].y)
243 if (c1[1].x == c2[0].x && c1[1].y == c2[0].y)
245 if (c1[1].x == c2[1].x && c1[1].y == c2[1].y)
247 return connected_pref;
251 tracking_is_no_stop(struct coord *c1, struct pcoord *c2)
253 if (c1->x == c2->x && c1->y == c2->y)
259 tracking_is_on_route(struct route *rt, struct item *item)
263 if (route_pos_contains(rt, item))
265 if (route_contains(rt, item))
271 tracking_value(struct tracking *tr, struct tracking_line *t, int offset, struct coord *lpnt, int min, int flags)
274 struct street_data *sd=t->street;
275 struct coord c, c1, c2;
276 c.x = sd->c[offset].x;
277 c.y = sd->c[offset].y;
279 c1.x = sd->c[offset].x;
280 c1.y = sd->c[offset].y;
282 c2.x = tr->curr_in.x;
283 c2.y = tr->curr_in.y;
284 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);
286 value+=transform_distance_line_sq(&c, &c1, &c2, lpnt);
290 value += tracking_angle_delta(tr->curr_angle, t->angle[offset], sd->flags)*angle_factor>>4;
294 value += tracking_is_connected(tr->last, &sd->c[offset]);
296 value += tracking_is_no_stop(lpnt, &tr->last_out);
300 value += tracking_is_on_route(tr->rt, &sd->item);
306 tracking_update(struct tracking *tr, struct pcoord *pc, int angle)
308 struct tracking_line *t;
316 dbg(1,"enter(%p,%p,%d)\n", tr, pc, angle);
317 dbg(1,"c=%d:0x%x,0x%x\n", pc->pro, pc->x, pc->y);
319 if (pc->x == tr->curr_in.x && pc->y == tr->curr_in.y) {
320 if (tr->curr_out.x && tr->curr_out.y)
324 tr->last_in=tr->curr_in;
325 tr->last_out=tr->curr_out;
326 tr->last[0]=tr->curr[0];
327 tr->last[1]=tr->curr[1];
329 tr->curr_angle=angle;
332 if (!tr->lines || transform_distance_sq_pc(&tr->last_updated, pc) > 250000) {
334 tracking_free_lines(tr);
335 tracking_doupdate_lines(tr, pc);
336 tr->last_updated=*pc;
337 dbg(1,"update end\n");
346 struct street_data *sd=t->street;
347 if ((sd->flags & 3) == 3) {
351 for (i = 0; i < sd->count-1 ; i++) {
352 value=tracking_value(tr,t,i,&lpnt,min,-1);
356 tr->curr[0]=sd->c[i];
357 tr->curr[1]=sd->c[i+1];
358 dbg(1,"lpnt.x=0x%x,lpnt.y=0x%x pos=%d %d+%d+%d+%d=%d\n", lpnt.x, lpnt.y, i,
359 transform_distance_line_sq(&sd->c[i], &sd->c[i+1], &cin, &lpnt),
360 tracking_angle_delta(angle, t->angle[i], 0)*angle_factor,
361 tracking_is_connected(tr->last, &sd->c[i]) ? connected_pref : 0,
362 lpnt.x == tr->last_out.x && lpnt.y == tr->last_out.y ? nostop_pref : 0,
365 tr->curr_out.x=lpnt.x;
366 tr->curr_out.y=lpnt.y;
367 tr->curr_out.pro = pc->pro;
373 dbg(1,"tr->curr_line=%p min=%d\n", tr->curr_line, min);
374 if (!tr->curr_line || min > offroad_limit_pref)
376 dbg(1,"found 0x%x,0x%x\n", tr->curr_out.x, tr->curr_out.y);
382 tracking_new(struct attr *parent, struct attr **attrs)
384 struct tracking *this=g_new0(struct tracking, 1);
390 tracking_set_mapset(struct tracking *this, struct mapset *ms)
396 tracking_set_route(struct tracking *this, struct route *rt)
402 tracking_destroy(struct tracking *tr)
404 tracking_free_lines(tr);
409 tracking_get_map(struct tracking *this_)
412 this_->map=map_new(NULL, (struct attr*[]){
413 &(struct attr){attr_type,{"tracking"}},
414 &(struct attr){attr_trackingo,.u.tracking=this_},
415 &(struct attr){attr_data,{""}},
416 &(struct attr){attr_description,{"Tracking"}},
423 struct tracking *tracking;
426 struct map_rect_priv {
427 struct tracking *tracking;
429 struct tracking_line *curr,*next;
431 enum attr_type attr_next;
438 tracking_map_item_coord_get(void *priv_data, struct coord *c, int count)
440 struct map_rect_priv *this=priv_data;
444 while (this->ccount < 2 && count > 0) {
445 pro = map_projection(this->curr->street->item.map);
446 if (projection_mg != pro) {
447 transform_from_to(&this->curr->street->c[this->ccount+this->coord],
451 *c=this->curr->street->c[this->ccount+this->coord];
452 dbg(1,"coord %d 0x%x,0x%x\n",this->ccount,c->x,c->y);
462 tracking_map_item_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
464 struct map_rect_priv *this_=priv_data;
465 attr->type=attr_type;
466 struct coord lpnt,*c;
467 struct tracking *tr=this_->tracking;
477 switch(this_->debug_idx) {
480 this_->str=attr->u.str=g_strdup_printf("overall: %d",tracking_value(tr, this_->curr, this_->coord, &lpnt, INT_MAX/2, -1));
484 c=&this_->curr->street->c[this_->coord];
485 value=tracking_value(tr, this_->curr, this_->coord, &lpnt, INT_MAX/2, 1);
486 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",
487 tr->curr_in.x, tr->curr_in.y,
488 c[0].x, c[0].y, c[1].x, c[1].y,
489 lpnt.x, lpnt.y, value);
493 this_->str=attr->u.str=g_strdup_printf("angle: %d to %d (flags %d) %d",
494 tr->curr_angle, this_->curr->angle[this_->coord], this_->curr->street->flags & 3,
495 tracking_value(tr, this_->curr, this_->coord, &lpnt, INT_MAX/2, 2));
499 this_->str=attr->u.str=g_strdup_printf("connected: %d", tracking_value(tr, this_->curr, this_->coord, &lpnt, INT_MAX/2, 4));
503 this_->str=attr->u.str=g_strdup_printf("no_stop: %d", tracking_value(tr, this_->curr, this_->coord, &lpnt, INT_MAX/2, 8));
507 this_->str=attr->u.str=g_strdup_printf("route: %d", tracking_value(tr, this_->curr, this_->coord, &lpnt, INT_MAX/2, 16));
511 this_->str=attr->u.str=g_strdup_printf("line %p", this_->curr);
514 this_->attr_next=attr_none;
518 while (this_->attr_next != attr_none) {
519 if (tracking_map_item_attr_get(priv_data, this_->attr_next, attr))
524 attr->type=attr_none;
529 static struct item_methods tracking_map_item_methods = {
531 tracking_map_item_coord_get,
533 tracking_map_item_attr_get,
538 tracking_map_destroy(struct map_priv *priv)
544 tracking_map_rect_init(struct map_rect_priv *priv)
546 priv->next=priv->tracking->lines;
553 static struct map_rect_priv *
554 tracking_map_rect_new(struct map_priv *priv, struct map_selection *sel)
556 struct tracking *tracking=priv->tracking;
557 struct map_rect_priv *ret=g_new0(struct map_rect_priv, 1);
558 ret->tracking=tracking;
559 tracking_map_rect_init(ret);
560 ret->item.meth=&tracking_map_item_methods;
561 ret->item.priv_data=ret;
562 ret->item.type=type_tracking_100;
567 tracking_map_rect_destroy(struct map_rect_priv *priv)
573 tracking_map_get_item(struct map_rect_priv *priv)
575 struct item *ret=&priv->item;
581 if (! priv->curr || priv->coord + 2 >= priv->curr->street->count) {
582 priv->curr=priv->next;
583 priv->next=priv->curr->next;
591 value=tracking_value(priv->tracking, priv->curr, priv->coord, &lpnt, INT_MAX/2, -1);
593 priv->item.type=type_tracking_100;
594 else if (value < 128)
595 priv->item.type=type_tracking_90;
596 else if (value < 256)
597 priv->item.type=type_tracking_80;
598 else if (value < 512)
599 priv->item.type=type_tracking_70;
600 else if (value < 1024)
601 priv->item.type=type_tracking_60;
602 else if (value < 2048)
603 priv->item.type=type_tracking_50;
604 else if (value < 4096)
605 priv->item.type=type_tracking_40;
606 else if (value < 8192)
607 priv->item.type=type_tracking_30;
608 else if (value < 16384)
609 priv->item.type=type_tracking_20;
610 else if (value < 32768)
611 priv->item.type=type_tracking_10;
613 priv->item.type=type_tracking_0;
614 dbg(1,"item %d %d points\n", priv->coord, priv->curr->street->count);
616 priv->attr_next=attr_debug;
622 tracking_map_get_item_byid(struct map_rect_priv *priv, int id_hi, int id_lo)
625 tracking_map_rect_init(priv);
626 while ((ret=tracking_map_get_item(priv))) {
627 if (ret->id_hi == id_hi && ret->id_lo == id_lo)
633 static struct map_methods tracking_map_meth = {
636 tracking_map_destroy,
637 tracking_map_rect_new,
638 tracking_map_rect_destroy,
639 tracking_map_get_item,
640 tracking_map_get_item_byid,
646 static struct map_priv *
647 tracking_map_new(struct map_methods *meth, struct attr **attrs)
649 struct map_priv *ret;
650 struct attr *tracking_attr;
652 tracking_attr=attr_search(attrs, NULL, attr_trackingo);
655 ret=g_new0(struct map_priv, 1);
656 *meth=tracking_map_meth;
657 ret->tracking=tracking_attr->u.tracking;
666 plugin_register_map_type("tracking", tracking_map_new);