int transform_distance_polyline_sq(struct coord *c, int count, struct coord *ref, struct coord *lpnt, int *pos) { int i,dist,distn; struct coord lp; if (count < 2) return INT_MAX; if (pos) *pos=0; dist=transform_distance_line_sq(&c[0], &c[1], ref, lpnt); for (i=2 ; i < count ; i++) { distn=transform_distance_line_sq(&c[i-1], &c[i], ref, &lp); if (distn < dist) { dist=distn; if (lpnt) *lpnt=lp; if (pos) *pos=i-1; } } return dist; }
int transform_douglas_peucker(struct coord *in, int count, int dist_sq, struct coord *out) { int ret=0; int i,d,dmax=0, idx=0; for (i = 1; i < count-2 ; i++) { d=transform_distance_line_sq(&in[0], &in[count-1], &in[i], NULL); if (d > dmax) { idx=i; dmax=d; } } if (dmax > dist_sq) { ret=transform_douglas_peucker(in, idx, dist_sq, out)-1; ret+=transform_douglas_peucker(in+idx, count-idx, dist_sq, out+ret); } else { if (count > 0) out[ret++]=in[0]; if (count > 1) out[ret++]=in[count-1]; } return ret; }
int tracking_update(struct tracking *tr, struct coord *c, int angle) { struct tracking_line *t; int i,value,min=0; struct coord lpnt; #if 0 int min,dist; int debug=0; #endif dbg(1,"enter(%p,%p,%d)\n", tr, c, angle); dbg(1,"c=0x%x,0x%x\n", c->x, c->y); if (c->x == tr->last_in.x && c->y == tr->last_in.y) { *c=tr->last_out; return 0; } tr->last_in=*c; if (!tr->lines || transform_distance_sq(&tr->last_updated, c) > 250000) { dbg(1, "update\n"); tracking_free_lines(tr); tracking_doupdate_lines(tr, c); tr->last_updated=*c; dbg(1,"update end\n"); } t=tr->lines; if (! t) return 0; tr->curr_line=NULL; while (t) { struct street_data *sd=t->street; int dir = 0; switch(sd->flags & AF_ONEWAYMASK) { case 0: dir=0; break; case 1: dir=1; break; case 2: dir=-1; break; case 3: t=t->next; continue; } for (i = 0; i < sd->count-1 ; i++) { 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); value=transform_distance_line_sq(&sd->c[i], &sd->c[i+1], c, &lpnt); if (value < INT_MAX/2) value += tracking_angle_delta(angle, t->angle[i], dir)*angle_factor; if (tracking_is_connected(tr->curr, &sd->c[i])) value += connected_pref; if (lpnt.x == tr->last_out.x && lpnt.y == tr->last_out.y) value += nostop_pref; if (! tr->curr_line || value < min) { tr->curr_line=t; tr->pos=i; tr->curr[0]=sd->c[i]; tr->curr[1]=sd->c[i+1]; dbg(1,"lpnt.x=0x%x,lpnt.y=0x%x pos=%d %d+%d+%d+%d=%d\n", lpnt.x, lpnt.y, i, transform_distance_line_sq(&sd->c[i], &sd->c[i+1], c, &lpnt), tracking_angle_delta(angle, t->angle[i], 0)*angle_factor, tracking_is_connected(tr->curr, &sd->c[i]) ? connected_pref : 0, lpnt.x == tr->last_out.x && lpnt.y == tr->last_out.y ? nostop_pref : 0, value ); tr->last_out=lpnt; min=value; } } t=t->next; } dbg(1,"tr->curr_line=%p\n", tr->curr_line); if (!tr->curr_line) return 0; dbg(1,"found 0x%x,0x%x\n", tr->last_out.x, tr->last_out.y); *c=tr->last_out; return 1; }