int yaw; /* Rotation angle */
int pitch;
int ddd;
- int m00,m01,m10,m11; /* 2d transformation matrix */
- int xyscale;
- int m20,m21; /* additional 3d parameters */
+ int m00,m01,m02; /* 3d transformation matrix */
+ int m10,m11,m12;
+ int m20,m21,m22;
+ int xscale,yscale,wscale;
+ int xscale3d,yscale3d,wscale3d;
#ifdef ENABLE_ROLL
int roll;
- int m02,m12,m22;
int hog;
- navit_float im02,im12,im20,im21,im22;
#endif
- navit_float im00,im01,im10,im11; /* inverse 2d transformation matrix */
+ navit_float im00,im01,im02; /* inverse 3d transformation matrix */
+ navit_float im10,im11,im12;
+ navit_float im20,im21,im22;
struct map_selection *map_sel;
struct map_selection *screen_sel;
struct point screen_center;
int screen_dist;
int offx,offy,offz;
+ int znear,zfar;
struct coord map_center; /* Center of source rectangle */
enum projection pro;
navit_float scale; /* Scale factor */
int order_base;
};
+#ifdef ENABLE_ROLL
+#define HOG(t) ((t).hog)
+#else
+#define HOG(t) 0
+#endif
+static void
+transform_set_screen_dist(struct transformation *t, int dist)
+{
+ t->screen_dist=dist;
+ t->xscale3d=dist;
+ t->yscale3d=dist;
+ t->wscale3d=dist << POST_SHIFT;
+}
static void
transform_setup_matrix(struct transformation *t)
#ifdef ENABLE_ROLL
navit_float rollc=navit_cos(M_PI*t->roll/180);
navit_float rolls=navit_sin(M_PI*t->roll/180);
+#else
+ navit_float rollc=1;
+ navit_float rolls=0;
#endif
int scale=t->scale;
int order_dir=-1;
dbg(1,"yaw=%d pitch=%d center=0x%x,0x%x\n", t->yaw, t->pitch, t->map_center.x, t->map_center.y);
+ t->znear=1 << POST_SHIFT;
+ t->zfar=300*t->znear;
t->scale_shift=0;
t->order=t->order_base;
if (t->scale >= 1) {
fac=(1 << POST_SHIFT) * (1 << t->scale_shift) / t->scale;
dbg(1,"scale_shift=%d order=%d scale=%f fac=%f\n", t->scale_shift, t->order,t->scale,fac);
-#ifdef ENABLE_ROLL
t->m00=rollc*yawc*fac;
t->m01=rollc*yaws*fac;
t->m02=-rolls*fac;
t->m20=(pitchc*rolls*yawc+pitchs*yaws)*fac;
t->m21=(pitchc*rolls*yaws-pitchs*yawc)*fac;
t->m22=pitchc*rollc*fac;
-#else
- t->m00=yawc*fac;
- t->m01=yaws*fac;
- t->m10=(-pitchc*yaws)*(-fac);
- t->m11=pitchc*yawc*(-fac);
- t->m20=pitchs*yaws*fac;
- t->m21=(-pitchs*yawc)*fac;
-#endif
- t->offz=0;
- t->xyscale=1;
- t->ddd=0;
+
t->offx=t->screen_center.x;
t->offy=t->screen_center.y;
if (t->pitch) {
t->ddd=1;
t->offz=t->screen_dist;
- t->xyscale=t->offz;
+ dbg(1,"near %d far %d\n",t->znear,t->zfar);
+ t->xscale=t->xscale3d;
+ t->yscale=t->yscale3d;
+ t->wscale=t->wscale3d;
+ } else {
+ t->ddd=0;
+ t->offz=0;
+ t->xscale=1;
+ t->yscale=1;
+ t->wscale=1;
}
-#ifdef ENABLE_ROLL
det=(navit_float)t->m00*(navit_float)t->m11*(navit_float)t->m22+
(navit_float)t->m01*(navit_float)t->m12*(navit_float)t->m20+
(navit_float)t->m02*(navit_float)t->m10*(navit_float)t->m21-
t->im20=(t->m10*t->m21-t->m11*t->m20)/det;
t->im21=(t->m01*t->m20-t->m00*t->m21)/det;
t->im22=(t->m00*t->m11-t->m01*t->m10)/det;
-#else
- det=((navit_float)t->m00*(navit_float)t->m11-(navit_float)t->m01*(navit_float)t->m10);
- t->im00=t->m11/det;
- t->im01=-t->m01/det;
- t->im10=-t->m10/det;
- t->im11=t->m00/det;
-#endif
}
struct transformation *
struct transformation *this_;
this_=g_new0(struct transformation, 1);
- this_->screen_dist=100;
+ transform_set_screen_dist(this_, 100);
this_->order_base=14;
#if 0
this_->pitch=20;
return this_;
}
-#ifdef ENABLE_ROLL
-
int
transform_get_hog(struct transformation *this_)
{
- return this_->hog;
+ return HOG(*this_);
}
void
transform_set_hog(struct transformation *this_, int hog)
{
+#ifdef ENABLE_ROLL
this_->hog=hog;
-}
-
#else
+ dbg(0,"not supported\n");
+#endif
-int
-transform_get_hog(struct transformation *this_)
-{
- return 0;
}
-void
-transform_set_hog(struct transformation *this_, int hog)
+int
+transform_get_attr(struct transformation *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
{
- dbg(0,"not supported\n");
+ switch (type) {
+#ifdef ENABLE_ROLL
+ case attr_hog:
+ attr->u.num=this_->hog;
+ break;
+#endif
+ default:
+ return 0;
+ }
+ attr->type=type;
+ return 1;
}
+int
+transform_set_attr(struct transformation *this_, struct attr *attr)
+{
+ switch (attr->type) {
+#ifdef ENABLE_ROLL
+ case attr_hog:
+ this_->hog=attr->u.num;
+ return 1;
#endif
+ default:
+ return 0;
+ }
+}
int
transformation_get_order_base(struct transformation *this_)
}
int
-transform(struct transformation *t, enum projection pro, struct coord *c, struct point *p, int count, int unique, int width, int *width_return)
+transform(struct transformation *t, enum projection pro, struct coord *c, struct point *p, int count, int mindist, int width, int *width_return)
{
struct coord c1;
int xcn, ycn;
struct coord_geo g;
int xc, yc, zc=0, xco=0, yco=0, zco=0;
int xm,ym,zct;
- int zlimit=1000;
+ int zlimit=t->znear;
int visible, visibleo=-1;
- int i,j = 0;
+ int i,j = 0,k=0;
dbg(1,"count=%d\n", count);
for (i=0; i < count; i++) {
if (pro == t->pro) {
xc=c1.x;
yc=c1.y;
}
+ if (i != 0 && i != count-1 && mindist) {
+ if (xc > c[k].x-mindist && xc < c[k].x+mindist && yc > c[k].y-mindist && yc < c[k].y+mindist &&
+ (c[i+1].x != c[0].x || c[i+1].y != c[0].y))
+ continue;
+ k=i;
+ }
xm=xc;
ym=yc;
// dbg(2,"0x%x, 0x%x - 0x%x,0x%x contains 0x%x,0x%x\n", t->r.lu.x, t->r.lu.y, t->r.rl.x, t->r.rl.y, c->x, c->y);
yc-=t->map_center.y;
xc >>= t->scale_shift;
yc >>= t->scale_shift;
-#ifdef ENABLE_ROLL
- xcn=xc*t->m00+yc*t->m01+t->hog*t->m02;
- ycn=xc*t->m10+yc*t->m11+t->hog*t->m12;
-#else
- xcn=xc*t->m00+yc*t->m01;
- ycn=xc*t->m10+yc*t->m11;
-#endif
+ xm=xc;
+ ym=yc;
+
+ xcn=xc*t->m00+yc*t->m01+HOG(*t)*t->m02;
+ ycn=xc*t->m10+yc*t->m11+HOG(*t)*t->m12;
if (t->ddd) {
-#ifdef ENABLE_ROLL
- zc=(xc*t->m20+yc*t->m21+t->hog*t->m22);
-#else
- zc=(xc*t->m20+yc*t->m21);
-#endif
+ zc=(xc*t->m20+yc*t->m21+HOG(*t)*t->m22);
zct=zc;
zc+=t->offz << POST_SHIFT;
dbg(1,"zc=%d\n", zc);
dbg(0,"%d/%d=%d %d/%d=%d\n",xcn,xc,xcn/xc,ycn,yc,ycn/yc);
#endif
#if 1
- xc=(long long)xcn*t->xyscale/zc;
- yc=(long long)ycn*t->xyscale/zc;
+ xc=(long long)xcn*t->xscale/zc;
+ yc=(long long)ycn*t->yscale/zc;
#else
xc=xcn/(1000+zc);
yc=ycn/(1000+zc);
#endif
+#if 0
dbg(1,"%d,%d %d\n",xc,yc,zc);
+#endif
} else {
xc=xcn;
yc=ycn;
}
xc+=t->offx;
yc+=t->offy;
- dbg(1,"xc=%d yc=%d\n", xc, yc);
- if (j == 0 || !unique || p[j-1].x != xc || p[j-1].y != yc) {
- p[j].x=xc;
- p[j].y=yc;
- if (width_return) {
- if (t->ddd)
- width_return[j]=width*(t->offz << POST_SHIFT)/zc;
- else
- width_return[j]=width;
- }
- j++;
+ p[j].x=xc;
+ p[j].y=yc;
+ if (width_return) {
+ if (t->ddd)
+ width_return[j]=width*t->wscale/zc;
+ else
+ width_return[j]=width;
}
+ j++;
}
return j;
}
-void
-transform_reverse(struct transformation *t, struct point *p, struct coord *c)
+static void
+transform_apply_inverse_matrix(struct transformation *t, struct coord_geo_cart *in, struct coord_geo_cart *out)
+{
+ out->x=in->x*t->im00+in->y*t->im01+in->z*t->im02;
+ out->y=in->x*t->im10+in->y*t->im11+in->z*t->im12;
+ out->z=in->x*t->im20+in->y*t->im21+in->z*t->im22;
+}
+
+static int
+transform_zplane_intersection(struct coord_geo_cart *p1, struct coord_geo_cart *p2, navit_float z, struct coord_geo_cart *result)
+{
+ navit_float dividend=z-p1->z;
+ navit_float divisor=p2->z-p1->z;
+ navit_float q;
+ if (!divisor) {
+ if (dividend)
+ return 0; /* no intersection */
+ else
+ return 3; /* identical planes */
+ }
+ q=dividend/divisor;
+ result->x=p1->x+q*(p2->x-p1->x);
+ result->y=p1->y+q*(p2->y-p1->y);
+ result->z=z;
+ if (q >= 0 && q <= 1)
+ return 1; /* intersection within [p1,p2] */
+ return 2; /* intersection without [p1,p2] */
+}
+
+static void
+transform_screen_to_3d(struct transformation *t, struct point *p, navit_float z, struct coord_geo_cart *cg)
{
- double zc,xc,yc,xcn,ycn,q;
+ double xc,yc;
double offz=t->offz << POST_SHIFT;
xc=p->x - t->offx;
yc=p->y - t->offy;
- if (t->ddd) {
- xc/=t->xyscale;
- yc/=t->xyscale;
- double f00=xc*t->im00*t->m20;
- double f01=yc*t->im01*t->m20;
- double f10=xc*t->im10*t->m21;
- double f11=yc*t->im11*t->m21;
-#ifdef ENABLE_ROLL
- q=(1-f00-f01-t->im02*t->m20-f10-f11-t->im12*t->m21);
- if (q < 0)
- q=0.15;
- zc=(offz*((f00+f01+f10+f11))+t->hog*t->m22)/q;
-#else
- q=(1-f00-f01-f10-f11);
- if (q < 0)
- q=0.15;
- zc=offz*(f00+f01+f10+f11)/q;
-#endif
- xcn=xc*(zc+offz);
- ycn=yc*(zc+offz);
-#ifdef ENABLE_ROLL
- xc=xcn*t->im00+ycn*t->im01+zc*t->im02;
- yc=xcn*t->im10+ycn*t->im11+zc*t->im12;
-#else
- xc=xcn*t->im00+ycn*t->im01;
- yc=xcn*t->im10+ycn*t->im11;
-#endif
+ cg->x=xc*z/t->xscale;
+ cg->y=yc*z/t->yscale;
+ cg->z=z-offz;
+}
+static int
+transform_reverse_near_far(struct transformation *t, struct point *p, struct coord *c, int near, int far)
+{
+ double xc,yc;
+ dbg(1,"%d,%d\n",p->x,p->y);
+ if (t->ddd) {
+ struct coord_geo_cart nearc,farc,nears,fars,intersection;
+ transform_screen_to_3d(t, p, near, &nearc);
+ transform_screen_to_3d(t, p, far, &farc);
+ transform_apply_inverse_matrix(t, &nearc, &nears);
+ transform_apply_inverse_matrix(t, &farc, &fars);
+ if (transform_zplane_intersection(&nears, &fars, HOG(*t), &intersection) != 1)
+ return 0;
+ xc=intersection.x;
+ yc=intersection.y;
} else {
- xcn=xc;
- ycn=yc;
+ double xcn,ycn;
+ xcn=p->x - t->offx;
+ ycn=p->y - t->offy;
xc=(xcn*t->im00+ycn*t->im01)*(1 << POST_SHIFT);
yc=(xcn*t->im10+ycn*t->im11)*(1 << POST_SHIFT);
}
c->x=xc*(1 << t->scale_shift)+t->map_center.x;
c->y=yc*(1 << t->scale_shift)+t->map_center.y;
+ return 1;
+}
+
+int
+transform_reverse(struct transformation *t, struct point *p, struct coord *c)
+{
+ return transform_reverse_near_far(t, p, c, t->znear, t->zfar);
}
enum projection
}
dbg(1,"transform rect for %d is %d,%d - %d,%d\n", pro, curro->u.c_rect.lu.x, curro->u.c_rect.lu.y, curro->u.c_rect.rl.x, curro->u.c_rect.rl.y);
curro->order+=order;
+ curro->u.c_rect.lu.x-=500;
+ curro->u.c_rect.lu.y+=500;
+ curro->u.c_rect.rl.x+=500;
+ curro->u.c_rect.rl.y-=500;
curro->range=item_range_all;
curri=curri->next;
curro=curro->next;
return this_->pitch;
}
-#ifdef ENABLE_ROLL
void
transform_set_roll(struct transformation *this_,int roll)
{
+#ifdef ENABLE_ROLL
this_->roll=roll;
transform_setup_matrix(this_);
-}
-
-int
-transform_get_roll(struct transformation *this_)
-{
- return this_->roll;
-}
-
#else
-
-void
-transform_set_roll(struct transformation *this_,int roll)
-{
dbg(0,"not supported\n");
+#endif
}
int
transform_get_roll(struct transformation *this_)
{
+#ifdef ENABLE_ROLL
+ return this_->roll;
+#else
return 0;
-}
-
#endif
+}
void
transform_set_distance(struct transformation *this_,int distance)
{
- this_->screen_dist=distance;
+ transform_set_screen_dist(this_, distance);
transform_setup_matrix(this_);
}
}
void
+transform_set_scales(struct transformation *this_, int xscale, int yscale, int wscale)
+{
+ this_->xscale3d=xscale;
+ this_->yscale3d=yscale;
+ this_->wscale3d=wscale;
+}
+
+void
transform_set_screen_selection(struct transformation *t, struct map_selection *sel)
{
map_selection_destroy(t->screen_sel);
msm=g_new0(struct map_selection, 1);
*msm=*ms;
pr=&ms->u.p_rect;
- screen_pnt[0].x=pr->lu.x;
+ screen_pnt[0].x=pr->lu.x; /* left upper */
screen_pnt[0].y=pr->lu.y;
- screen_pnt[1].x=pr->rl.x;
+ screen_pnt[1].x=pr->rl.x; /* right upper */
screen_pnt[1].y=pr->lu.y;
- screen_pnt[2].x=pr->lu.x;
+ screen_pnt[2].x=pr->rl.x; /* right lower */
screen_pnt[2].y=pr->rl.y;
- screen_pnt[3].x=pr->rl.x;
+ screen_pnt[3].x=pr->lu.x; /* left lower */
screen_pnt[3].y=pr->rl.y;
- for (i = 0 ; i < 4 ; i++) {
- transform_reverse(t, &screen_pnt[i], &screen[i]);
- dbg(1,"map(%d) %d,%d=0x%x,0x%x\n", i,screen_pnt[i].x, screen_pnt[i].y, screen[i].x, screen[i].y);
+ if (t->ddd) {
+ struct coord_geo_cart tmp,cg[8];
+ struct coord c;
+ int valid=0;
+ char edgenodes[]={
+ 0,1,
+ 1,2,
+ 2,3,
+ 3,0,
+ 4,5,
+ 5,6,
+ 6,7,
+ 7,4,
+ 0,4,
+ 1,5,
+ 2,6,
+ 3,7};
+ for (i = 0 ; i < 8 ; i++) {
+ transform_screen_to_3d(t, &screen_pnt[i%4], (i >= 4 ? t->zfar:t->znear), &tmp);
+ transform_apply_inverse_matrix(t, &tmp, &cg[i]);
+ }
+ msm->u.c_rect.lu.x=0;
+ msm->u.c_rect.lu.y=0;
+ msm->u.c_rect.rl.x=0;
+ msm->u.c_rect.rl.y=0;
+ for (i = 0 ; i < 12 ; i++) {
+ if (transform_zplane_intersection(&cg[edgenodes[i*2]], &cg[edgenodes[i*2+1]], HOG(*t), &tmp) == 1) {
+ c.x=tmp.x*(1 << t->scale_shift)+t->map_center.x;
+ c.y=tmp.y*(1 << t->scale_shift)+t->map_center.y;
+ dbg(1,"intersection with edge %d at 0x%x,0x%x\n",i,c.x,c.y);
+ if (valid)
+ coord_rect_extend(&msm->u.c_rect, &c);
+ else {
+ msm->u.c_rect.lu=c;
+ msm->u.c_rect.rl=c;
+ valid=1;
+ }
+ dbg(1,"rect 0x%x,0x%x - 0x%x,0x%x\n",msm->u.c_rect.lu.x,msm->u.c_rect.lu.y,msm->u.c_rect.rl.x,msm->u.c_rect.rl.y);
+ }
+ }
+ } else {
+ for (i = 0 ; i < 4 ; i++) {
+ transform_reverse(t, &screen_pnt[i], &screen[i]);
+ dbg(1,"map(%d) %d,%d=0x%x,0x%x\n", i,screen_pnt[i].x, screen_pnt[i].y, screen[i].x, screen[i].y);
+ }
+ msm->u.c_rect.lu.x=min4(screen[0].x,screen[1].x,screen[2].x,screen[3].x);
+ msm->u.c_rect.rl.x=max4(screen[0].x,screen[1].x,screen[2].x,screen[3].x);
+ msm->u.c_rect.rl.y=min4(screen[0].y,screen[1].y,screen[2].y,screen[3].y);
+ msm->u.c_rect.lu.y=max4(screen[0].y,screen[1].y,screen[2].y,screen[3].y);
}
- msm->u.c_rect.lu.x=min4(screen[0].x,screen[1].x,screen[2].x,screen[3].x);
- msm->u.c_rect.rl.x=max4(screen[0].x,screen[1].x,screen[2].x,screen[3].x);
- msm->u.c_rect.rl.y=min4(screen[0].y,screen[1].y,screen[2].y,screen[3].y);
- msm->u.c_rect.lu.y=max4(screen[0].y,screen[1].y,screen[2].y,screen[3].y);
dbg(1,"%dx%d\n", msm->u.c_rect.rl.x-msm->u.c_rect.lu.x,
msm->u.c_rect.lu.y-msm->u.c_rect.rl.y);
*msm_last=msm;
}
}
+void
+transform_project(enum projection pro, struct coord *c, int distance, int angle, struct coord *res)
+{
+ double scale;
+ switch (pro) {
+ case projection_mg:
+ scale=transform_scale(c->y);
+ res->x=c->x+distance*sin(angle*M_PI/180)*scale;
+ res->y=c->y+distance*cos(angle*M_PI/180)*scale;
+ break;
+ default:
+ dbg(0,"Unsupported projection: %d\n", pro);
+ return;
+ }
+
+}
+
+
double
transform_polyline_length(enum projection pro, struct coord *c, int count)
{
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-1 ; 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+1, 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;
+}
+
void
transform_print_deg(double deg)