Fix:Core:Changed view frustrum calculation
[navit-package] / navit / transform.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
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.
8  *
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.
13  *
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.
18  */
19
20 #include <assert.h>
21 #include <stdio.h>
22 #include <math.h>
23 #include <limits.h>
24 #include <glib.h>
25 #include <string.h>
26 #include "config.h"
27 #include "coord.h"
28 #include "debug.h"
29 #include "item.h"
30 #include "map.h"
31 #include "transform.h"
32 #include "projection.h"
33 #include "point.h"
34
35 #define POST_SHIFT 8
36
37 struct transformation {
38         int yaw;                /* Rotation angle */
39         int pitch;
40         int ddd;
41         int m00,m01,m10,m11;    /* 2d transformation matrix */
42         int xscale,yscale,wscale;
43         int m20,m21;            /* additional 3d parameters */
44 #ifdef ENABLE_ROLL
45         int roll;
46         int m02,m12,m22; 
47         int hog;
48         navit_float im02,im12,im20,im21,im22;
49 #endif
50         navit_float im00,im01,im10,im11;        /* inverse 2d transformation matrix */
51         struct map_selection *map_sel;
52         struct map_selection *screen_sel;
53         struct point screen_center;
54         int screen_dist;
55         int offx,offy,offz;
56         int znear,zfar;
57         struct coord map_center;        /* Center of source rectangle */
58         enum projection pro;
59         navit_float scale;              /* Scale factor */
60         int scale_shift;
61         int order;
62         int order_base;
63 };
64
65
66
67 static void
68 transform_setup_matrix(struct transformation *t)
69 {
70         navit_float det;
71         navit_float fac;
72 #if 0 /* FIXME */
73 #if 0
74         t->roll=0;
75         t->pitch=90;
76         t->yaw=0;
77 #endif
78 #if 0
79         t->scale=1;
80 #endif
81         t->hog=2;
82         t->ddd=1;
83 #endif
84         navit_float yawc=navit_cos(-M_PI*t->yaw/180);
85         navit_float yaws=navit_sin(-M_PI*t->yaw/180);
86         navit_float pitchc=navit_cos(-M_PI*t->pitch/180);
87         navit_float pitchs=navit_sin(-M_PI*t->pitch/180);
88 #ifdef ENABLE_ROLL      
89         navit_float rollc=navit_cos(M_PI*t->roll/180);
90         navit_float rolls=navit_sin(M_PI*t->roll/180);
91 #endif
92
93         int scale=t->scale;
94         int order_dir=-1;
95
96         dbg(1,"yaw=%d pitch=%d center=0x%x,0x%x\n", t->yaw, t->pitch, t->map_center.x, t->map_center.y);
97         t->znear=1 << POST_SHIFT;
98         t->zfar=1000*t->znear;
99         t->scale_shift=0;
100         t->order=t->order_base;
101         if (t->scale >= 1) {
102                 scale=t->scale;
103         } else {
104                 scale=1.0/t->scale;
105                 order_dir=1;
106         }
107         while (scale > 1) {
108                 if (order_dir < 0)
109                         t->scale_shift++;
110                 t->order+=order_dir;
111                 scale >>= 1;
112         }
113         fac=(1 << POST_SHIFT) * (1 << t->scale_shift) / t->scale;
114         dbg(1,"scale_shift=%d order=%d scale=%f fac=%f\n", t->scale_shift, t->order,t->scale,fac);
115         
116 #ifdef ENABLE_ROLL
117         t->m00=rollc*yawc*fac;
118         t->m01=rollc*yaws*fac;
119         t->m02=-rolls*fac;
120         t->m10=(pitchs*rolls*yawc-pitchc*yaws)*(-fac);
121         t->m11=(pitchs*rolls*yaws+pitchc*yawc)*(-fac);
122         t->m12=pitchs*rollc*(-fac);
123         t->m20=(pitchc*rolls*yawc+pitchs*yaws)*fac;
124         t->m21=(pitchc*rolls*yaws-pitchs*yawc)*fac;
125         t->m22=pitchc*rollc*fac;
126 #else
127         t->m00=yawc*fac;
128         t->m01=yaws*fac;
129         t->m10=(-pitchc*yaws)*(-fac);
130         t->m11=pitchc*yawc*(-fac);
131         t->m20=pitchs*yaws*fac;
132         t->m21=(-pitchs*yawc)*fac;
133 #endif
134         t->offz=0;
135         t->xscale=1;
136         t->yscale=1;
137         t->wscale=1;
138         t->ddd=0;
139         t->offx=t->screen_center.x;
140         t->offy=t->screen_center.y;
141         if (t->pitch) {
142                 t->ddd=1;
143                 t->offz=t->screen_dist;
144                 t->xscale=t->offz;
145                 t->yscale=t->offz;
146                 t->wscale=t->offz << POST_SHIFT;
147         }
148 #if 0 /* FIXME */
149         t->offz=0;
150         t->xscale=750;
151         t->yscale=620;
152         t->wscale=32 << POST_SHIFT;
153 #endif
154 #ifdef ENABLE_ROLL
155         det=(navit_float)t->m00*(navit_float)t->m11*(navit_float)t->m22+
156             (navit_float)t->m01*(navit_float)t->m12*(navit_float)t->m20+
157             (navit_float)t->m02*(navit_float)t->m10*(navit_float)t->m21-
158             (navit_float)t->m02*(navit_float)t->m11*(navit_float)t->m20-
159             (navit_float)t->m01*(navit_float)t->m10*(navit_float)t->m22-
160             (navit_float)t->m00*(navit_float)t->m12*(navit_float)t->m21;
161
162         t->im00=(t->m11*t->m22-t->m12*t->m21)/det;
163         t->im01=(t->m02*t->m21-t->m01*t->m22)/det;
164         t->im02=(t->m01*t->m12-t->m02*t->m11)/det;
165         t->im10=(t->m12*t->m20-t->m10*t->m22)/det;
166         t->im11=(t->m00*t->m22-t->m02*t->m20)/det;
167         t->im12=(t->m02*t->m10-t->m00*t->m12)/det;
168         t->im20=(t->m10*t->m21-t->m11*t->m20)/det;
169         t->im21=(t->m01*t->m20-t->m00*t->m21)/det;
170         t->im22=(t->m00*t->m11-t->m01*t->m10)/det;
171 #else
172         det=((navit_float)t->m00*(navit_float)t->m11-(navit_float)t->m01*(navit_float)t->m10);
173         t->im00=t->m11/det;
174         t->im01=-t->m01/det;
175         t->im10=-t->m10/det;
176         t->im11=t->m00/det;
177 #endif
178 }
179
180 struct transformation *
181 transform_new(void)
182 {
183         struct transformation *this_;
184
185         this_=g_new0(struct transformation, 1);
186         this_->screen_dist=100;
187         this_->order_base=14;
188 #if 0
189         this_->pitch=20;
190 #endif
191 #if 0
192         this_->roll=30;
193         this_->hog=1000;
194 #endif
195         transform_setup_matrix(this_);
196         return this_;
197 }
198
199 #ifdef ENABLE_ROLL
200
201 int
202 transform_get_hog(struct transformation *this_)
203 {
204         return this_->hog;
205 }
206
207 void
208 transform_set_hog(struct transformation *this_, int hog)
209 {
210         this_->hog=hog;
211 }
212
213 #else
214
215 int
216 transform_get_hog(struct transformation *this_)
217 {
218         return 0;
219 }
220
221 void
222 transform_set_hog(struct transformation *this_, int hog)
223 {
224         dbg(0,"not supported\n");
225 }
226
227 #endif
228
229 int
230 transformation_get_order_base(struct transformation *this_)
231 {
232         return this_->order_base;
233 }
234
235 void
236 transform_set_order_base(struct transformation *this_, int order_base)
237 {
238         this_->order_base=order_base;
239 }
240
241
242 struct transformation *
243 transform_dup(struct transformation *t)
244 {
245         struct transformation *ret=g_new0(struct transformation, 1);
246         *ret=*t;
247         return ret;
248 }
249
250 static const navit_float gar2geo_units = 360.0/(1<<24);
251 static const navit_float geo2gar_units = 1/(360.0/(1<<24));
252
253 void
254 transform_to_geo(enum projection pro, struct coord *c, struct coord_geo *g)
255 {
256         int x,y,northern,zone;
257         switch (pro) {
258         case projection_mg:
259                 g->lng=c->x/6371000.0/M_PI*180;
260                 g->lat=navit_atan(exp(c->y/6371000.0))/M_PI*360-90;
261                 break;
262         case projection_garmin:
263                 g->lng=c->x*gar2geo_units;
264                 g->lat=c->y*gar2geo_units;
265                 break;
266         case projection_utm:
267                 x=c->x;
268                 y=c->y;
269                 northern=y >= 0;
270                 if (!northern) {
271                         y+=10000000;
272                 }
273                 zone=(x/1000000);
274                 x=x%1000000;
275                 transform_utm_to_geo(x, y, zone, northern, g);
276                 break;  
277         default:
278                 break;
279         }
280 }
281
282 void
283 transform_from_geo(enum projection pro, struct coord_geo *g, struct coord *c)
284 {
285         switch (pro) {
286         case projection_mg:
287                 c->x=g->lng*6371000.0*M_PI/180;
288                 c->y=log(navit_tan(M_PI_4+g->lat*M_PI/360))*6371000.0;
289                 break;
290         case projection_garmin:
291                 c->x=g->lng*geo2gar_units;
292                 c->y=g->lat*geo2gar_units;
293                 break;
294         default:
295                 break;
296         }
297 }
298
299 void
300 transform_from_to(struct coord *cfrom, enum projection from, struct coord *cto, enum projection to)
301 {
302         struct coord_geo g;
303         transform_to_geo(from, cfrom, &g);
304         transform_from_geo(to, &g, cto);
305 }
306
307 void
308 transform_geo_to_cart(struct coord_geo *geo, navit_float a, navit_float b, struct coord_geo_cart *cart)
309 {
310         navit_float n,ee=1-b*b/(a*a);
311         n = a/sqrtf(1-ee*navit_sin(geo->lat)*navit_sin(geo->lat));
312         cart->x=n*navit_cos(geo->lat)*navit_cos(geo->lng);
313         cart->y=n*navit_cos(geo->lat)*navit_sin(geo->lng);
314         cart->z=n*(1-ee)*navit_sin(geo->lat);
315 }
316
317 void
318 transform_cart_to_geo(struct coord_geo_cart *cart, navit_float a, navit_float b, struct coord_geo *geo)
319 {
320         navit_float lat,lati,n,ee=1-b*b/(a*a), lng = navit_tan(cart->y/cart->x);
321
322         lat = navit_tan(cart->z / navit_sqrt((cart->x * cart->x) + (cart->y * cart->y)));
323         do
324         {
325                 lati = lat;
326
327                 n = a / navit_sqrt(1-ee*navit_sin(lat)*navit_sin(lat));
328                 lat = navit_atan((cart->z + ee * n * navit_sin(lat)) / navit_sqrt(cart->x * cart->x + cart->y * cart->y));
329         }
330         while (fabs(lat - lati) >= 0.000000000000001);
331
332         geo->lng=lng/M_PI*180;
333         geo->lat=lat/M_PI*180;
334 }
335
336
337 void
338 transform_utm_to_geo(const double UTMEasting, const double UTMNorthing, int ZoneNumber, int NorthernHemisphere, struct coord_geo *geo)
339 {
340 //converts UTM coords to lat/long.  Equations from USGS Bulletin 1532 
341 //East Longitudes are positive, West longitudes are negative. 
342 //North latitudes are positive, South latitudes are negative
343 //Lat and Long are in decimal degrees. 
344         //Written by Chuck Gantz- chuck.gantz@globalstar.com
345
346         double Lat, Long;
347         double k0 = 0.99960000000000004;
348         double a = 6378137;
349         double eccSquared = 0.0066943799999999998;
350         double eccPrimeSquared;
351         double e1 = (1-sqrt(1-eccSquared))/(1+sqrt(1-eccSquared));
352         double N1, T1, C1, R1, D, M;
353         double LongOrigin;
354         double mu, phi1, phi1Rad;
355         double x, y;
356         double rad2deg = 180/M_PI;
357
358         x = UTMEasting - 500000.0; //remove 500,000 meter offset for longitude
359         y = UTMNorthing;
360
361         if (!NorthernHemisphere) {
362                 y -= 10000000.0;//remove 10,000,000 meter offset used for southern hemisphere
363         }
364
365         LongOrigin = (ZoneNumber - 1)*6 - 180 + 3;  //+3 puts origin in middle of zone
366
367         eccPrimeSquared = (eccSquared)/(1-eccSquared);
368
369         M = y / k0;
370         mu = M/(a*(1-eccSquared/4-3*eccSquared*eccSquared/64-5*eccSquared*eccSquared*eccSquared/256));
371         phi1Rad = mu    + (3*e1/2-27*e1*e1*e1/32)*sin(2*mu) 
372                                 + (21*e1*e1/16-55*e1*e1*e1*e1/32)*sin(4*mu)
373                                 +(151*e1*e1*e1/96)*sin(6*mu);
374         phi1 = phi1Rad*rad2deg;
375
376         N1 = a/sqrt(1-eccSquared*sin(phi1Rad)*sin(phi1Rad));
377         T1 = tan(phi1Rad)*tan(phi1Rad);
378         C1 = eccPrimeSquared*cos(phi1Rad)*cos(phi1Rad);
379         R1 = a*(1-eccSquared)/pow(1-eccSquared*sin(phi1Rad)*sin(phi1Rad), 1.5);
380         D = x/(N1*k0);
381
382         Lat = phi1Rad - (N1*tan(phi1Rad)/R1)*(D*D/2-(5+3*T1+10*C1-4*C1*C1-9*eccPrimeSquared)*D*D*D*D/24
383                                         +(61+90*T1+298*C1+45*T1*T1-252*eccPrimeSquared-3*C1*C1)*D*D*D*D*D*D/720);
384         Lat = Lat * rad2deg;
385
386         Long = (D-(1+2*T1+C1)*D*D*D/6+(5-2*C1+28*T1-3*C1*C1+8*eccPrimeSquared+24*T1*T1)
387                                         *D*D*D*D*D/120)/cos(phi1Rad);
388         Long = LongOrigin + Long * rad2deg;
389
390         geo->lat=Lat;
391         geo->lng=Long;
392 }
393
394 void
395 transform_datum(struct coord_geo *from, enum map_datum from_datum, struct coord_geo *to, enum map_datum to_datum)
396 {
397 }
398
399 int
400 transform(struct transformation *t, enum projection pro, struct coord *c, struct point *p, int count, int mindist, int width, int *width_return)
401 {
402         struct coord c1;
403         int xcn, ycn; 
404         struct coord_geo g;
405         int xc, yc, zc=0, xco=0, yco=0, zco=0;
406         int xm,ym,zct;
407         int zlimit=t->znear;
408         int visible, visibleo=-1;
409         int i,j = 0,k=0;
410         dbg(1,"count=%d\n", count);
411         for (i=0; i < count; i++) {
412                 if (pro == t->pro) {
413                         xc=c[i].x;
414                         yc=c[i].y;
415                 } else {
416                         transform_to_geo(pro, &c[i], &g);
417                         transform_from_geo(t->pro, &g, &c1);
418                         xc=c1.x;
419                         yc=c1.y;
420                 }
421                 if (i != 0 && i != count-1 && mindist) {
422                         if (xc > c[k].x-mindist && xc < c[k].x+mindist && yc > c[k].y-mindist && yc < c[k].y+mindist) 
423                                 continue;
424                         k=i;
425                 }
426                 xm=xc;
427                 ym=yc;
428 //              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);
429 //              ret=coord_rect_contains(&t->r, c);
430                 xc-=t->map_center.x;
431                 yc-=t->map_center.y;
432                 xc >>= t->scale_shift;
433                 yc >>= t->scale_shift;
434                 xm=xc;
435                 ym=yc;
436 #ifdef ENABLE_ROLL              
437                 xcn=xc*t->m00+yc*t->m01+t->hog*t->m02;
438                 ycn=xc*t->m10+yc*t->m11+t->hog*t->m12;
439 #else
440                 xcn=xc*t->m00+yc*t->m01;
441                 ycn=xc*t->m10+yc*t->m11;
442 #endif
443
444                 if (t->ddd) {
445 #ifdef ENABLE_ROLL              
446                         zc=(xc*t->m20+yc*t->m21+t->hog*t->m22);
447 #else
448                         zc=(xc*t->m20+yc*t->m21);
449 #endif
450                         zct=zc;
451                         zc+=t->offz << POST_SHIFT;
452                         dbg(1,"zc=%d\n", zc);
453                         dbg(1,"zc(%d)=xc(%d)*m20(%d)+yc(%d)*m21(%d)\n", (xc*t->m20+yc*t->m21), xc, t->m20, yc, t->m21);
454                         /* visibility */
455                         visible=(zc < zlimit ? 0:1);
456                         dbg(1,"visible=%d old %d\n", visible, visibleo);
457                         if (visible != visibleo && visibleo != -1) { 
458                                 dbg(1,"clipping (%d,%d,%d)-(%d,%d,%d) (%d,%d,%d)\n", xcn, ycn, zc, xco, yco, zco, xco-xcn, yco-ycn, zco-zc);
459                                 if (zco != zc) {
460                                         xcn=xcn+(long long)(xco-xcn)*(zlimit-zc)/(zco-zc);
461                                         ycn=ycn+(long long)(yco-ycn)*(zlimit-zc)/(zco-zc);
462                                 }
463                                 dbg(1,"result (%d,%d,%d) * %d / %d\n", xcn,ycn,zc,zlimit-zc,zco-zc);
464                                 zc=zlimit;
465                                 xco=xcn;
466                                 yco=ycn;
467                                 zco=zc;
468                                 if (visible)
469                                         i--;
470                                 visibleo=visible;
471                         } else {
472                                 xco=xcn;
473                                 yco=ycn;
474                                 zco=zc;
475                                 visibleo=visible;
476                                 if (! visible)
477                                         continue;
478                         }
479                         dbg(1,"zc=%d\n", zc);
480                         dbg(1,"xcn %d ycn %d\n", xcn, ycn);
481                         dbg(1,"%d,%d %d\n",xc,yc,zc);
482 #if 0
483                         dbg(0,"%d/%d=%d %d/%d=%d\n",xcn,xc,xcn/xc,ycn,yc,ycn/yc);
484 #endif
485 #if 1
486                         xc=(long long)xcn*t->xscale/zc;
487                         yc=(long long)ycn*t->yscale/zc;
488 #else
489                         xc=xcn/(1000+zc);
490                         yc=ycn/(1000+zc);
491 #endif
492 #if 0
493                         dbg(1,"%d,%d %d\n",xc,yc,zc);
494 #endif
495                 } else {
496                         xc=xcn;
497                         yc=ycn;
498                         xc>>=POST_SHIFT;
499                         yc>>=POST_SHIFT;
500                 }
501                 xc+=t->offx;
502                 yc+=t->offy;
503                 p[j].x=xc;
504                 p[j].y=yc;
505                 if (width_return) {
506                         if (t->ddd) 
507                                 width_return[j]=width*t->wscale/zc;
508                         else 
509                                 width_return[j]=width;
510                 }
511                 j++;
512         }
513         return j;
514 }
515
516 static void
517 transform_apply_inverse_matrix(struct transformation *t, struct coord_geo_cart *in, struct coord_geo_cart *out)
518 {
519         out->x=in->x*t->im00+in->y*t->im01+in->z*t->im02;
520         out->y=in->x*t->im10+in->y*t->im11+in->z*t->im12;
521         out->z=in->x*t->im20+in->y*t->im21+in->z*t->im22;
522 }
523
524 static int
525 transform_zplane_intersection(struct coord_geo_cart *p1, struct coord_geo_cart *p2, navit_float z, struct coord_geo_cart *result)
526 {
527         navit_float dividend=z-p1->z;
528         navit_float divisor=p2->z-p1->z;
529         navit_float q;
530         if (!divisor) {
531                 if (dividend) 
532                         return 0;       /* no intersection */
533                 else
534                         return 3;       /* identical planes */
535         }
536         q=dividend/divisor;
537         result->x=p1->x+q*(p2->x-p1->x);
538         result->y=p1->y+q*(p2->y-p1->y);
539         result->z=z;
540         if (q >= 0 && q <= 1)
541                 return 1;       /* intersection within [p1,p2] */
542         return 2; /* intersection without [p1,p2] */
543 }
544
545 static void
546 transform_screen_to_3d(struct transformation *t, struct point *p, navit_float z, struct coord_geo_cart *cg)
547 {
548         double xc,yc;
549         double offz=t->offz << POST_SHIFT;
550         xc=p->x - t->offx;
551         yc=p->y - t->offy;
552         z+=offz;
553         cg->x=xc*z/t->xscale;
554         cg->y=yc*z/t->yscale;
555         cg->z=z-offz;
556 }
557
558 static int
559 transform_reverse_near_far(struct transformation *t, struct point *p, struct coord *c, int near, int far)
560 {
561         double xc,yc;
562         dbg(1,"%d,%d\n",p->x,p->y);
563         if (t->ddd) {
564                 struct coord_geo_cart nearc,farc,nears,fars,intersection;
565                 transform_screen_to_3d(t, p, near, &nearc);     
566                 transform_screen_to_3d(t, p, far, &farc);
567                 transform_apply_inverse_matrix(t, &nearc, &nears);
568                 transform_apply_inverse_matrix(t, &farc, &fars);
569                 if (transform_zplane_intersection(&nears, &fars, t->hog, &intersection) != 1)
570                         return 0;
571                 xc=intersection.x;
572                 yc=intersection.y;
573         } else {
574                 double xcn,ycn;
575                 xcn=p->x - t->offx;
576                 ycn=p->y - t->offy;
577                 xc=(xcn*t->im00+ycn*t->im01)*(1 << POST_SHIFT);
578                 yc=(xcn*t->im10+ycn*t->im11)*(1 << POST_SHIFT);
579         }
580         c->x=xc*(1 << t->scale_shift)+t->map_center.x;
581         c->y=yc*(1 << t->scale_shift)+t->map_center.y;
582         return 1;
583 }
584
585 int
586 transform_reverse(struct transformation *t, struct point *p, struct coord *c)
587 {
588         return transform_reverse_near_far(t, p, c, t->znear, t->zfar);
589 }
590
591 enum projection
592 transform_get_projection(struct transformation *this_)
593 {
594         return this_->pro;
595 }
596
597 void
598 transform_set_projection(struct transformation *this_, enum projection pro)
599 {
600         this_->pro=pro;
601 }
602
603 static int
604 min4(int v1,int v2, int v3, int v4)
605 {
606         int res=v1;
607         if (v2 < res)
608                 res=v2;
609         if (v3 < res)
610                 res=v3;
611         if (v4 < res)
612                 res=v4;
613         return res;
614 }
615
616 static int
617 max4(int v1,int v2, int v3, int v4)
618 {
619         int res=v1;
620         if (v2 > res)
621                 res=v2;
622         if (v3 > res)
623                 res=v3;
624         if (v4 > res)
625                 res=v4;
626         return res;
627 }
628
629 struct map_selection *
630 transform_get_selection(struct transformation *this_, enum projection pro, int order)
631 {
632
633         struct map_selection *ret,*curri,*curro;
634         struct coord_geo g;
635         
636         ret=map_selection_dup(this_->map_sel);
637         curri=this_->map_sel;
638         curro=ret;
639         while (curri) {
640                 if (this_->pro != pro) {
641                         transform_to_geo(this_->pro, &curri->u.c_rect.lu, &g);
642                         transform_from_geo(pro, &g, &curro->u.c_rect.lu);
643                         dbg(1,"%f,%f", g.lat, g.lng);
644                         transform_to_geo(this_->pro, &curri->u.c_rect.rl, &g);
645                         transform_from_geo(pro, &g, &curro->u.c_rect.rl);
646                         dbg(1,": - %f,%f\n", g.lat, g.lng);
647                 }
648                 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);
649                 curro->order+=order;
650                 curro->u.c_rect.lu.x-=500;
651                 curro->u.c_rect.lu.y+=500;
652                 curro->u.c_rect.rl.x+=500;
653                 curro->u.c_rect.rl.y-=500;
654                 curro->range=item_range_all;
655                 curri=curri->next;
656                 curro=curro->next;
657         }
658         return ret;
659 }
660
661 struct coord *
662 transform_center(struct transformation *this_)
663 {
664         return &this_->map_center;
665 }
666
667 struct coord *
668 transform_get_center(struct transformation *this_)
669 {
670         return &this_->map_center;
671 }
672
673 void
674 transform_set_center(struct transformation *this_, struct coord *c)
675 {
676         this_->map_center=*c;
677 }
678
679
680 void
681 transform_set_yaw(struct transformation *t,int yaw)
682 {
683         t->yaw=yaw;
684         transform_setup_matrix(t);
685 }
686
687 int
688 transform_get_yaw(struct transformation *this_)
689 {
690         return this_->yaw;
691 }
692
693 void
694 transform_set_pitch(struct transformation *this_,int pitch)
695 {
696         this_->pitch=pitch;
697         transform_setup_matrix(this_);
698 }
699 int
700 transform_get_pitch(struct transformation *this_)
701 {
702         return this_->pitch;
703 }
704
705 #ifdef ENABLE_ROLL
706 void
707 transform_set_roll(struct transformation *this_,int roll)
708 {
709         this_->roll=roll;
710         transform_setup_matrix(this_);
711 }
712
713 int
714 transform_get_roll(struct transformation *this_)
715 {
716         return this_->roll;
717 }
718
719 #else
720
721 void
722 transform_set_roll(struct transformation *this_,int roll)
723 {
724         dbg(0,"not supported\n");
725 }
726
727 int
728 transform_get_roll(struct transformation *this_)
729 {
730         return 0;
731 }
732
733 #endif
734
735 void
736 transform_set_distance(struct transformation *this_,int distance)
737 {
738         this_->screen_dist=distance;
739         transform_setup_matrix(this_);
740 }
741
742 int
743 transform_get_distance(struct transformation *this_)
744 {
745         return this_->screen_dist;
746 }
747
748 void
749 transform_set_screen_selection(struct transformation *t, struct map_selection *sel)
750 {
751         map_selection_destroy(t->screen_sel);
752         t->screen_sel=map_selection_dup(sel);
753         if (sel) {
754                 t->screen_center.x=(sel->u.p_rect.rl.x-sel->u.p_rect.lu.x)/2;
755                 t->screen_center.y=(sel->u.p_rect.rl.y-sel->u.p_rect.lu.y)/2;
756                 transform_setup_matrix(t);
757         }
758 }
759
760 void
761 transform_set_screen_center(struct transformation *t, struct point *p)
762 {
763         t->screen_center=*p;
764 }
765
766 #if 0
767 void
768 transform_set_size(struct transformation *t, int width, int height)
769 {
770         t->width=width;
771         t->height=height;
772 }
773 #endif
774
775 void
776 transform_get_size(struct transformation *t, int *width, int *height)
777 {
778         struct point_rect *r;
779         if (t->screen_sel) {
780                 r=&t->screen_sel->u.p_rect;
781                 *width=r->rl.x-r->lu.x;
782                 *height=r->rl.y-r->lu.y;
783         }
784 }
785
786 void
787 transform_setup(struct transformation *t, struct pcoord *c, int scale, int yaw)
788 {
789         t->pro=c->pro;
790         t->map_center.x=c->x;
791         t->map_center.y=c->y;
792         t->scale=scale/16.0;
793         transform_set_yaw(t, yaw);
794 }
795
796 #if 0
797
798 void
799 transform_setup_source_rect_limit(struct transformation *t, struct coord *center, int limit)
800 {
801         t->center=*center;
802         t->scale=1;
803         t->angle=0;
804         t->r.lu.x=center->x-limit;
805         t->r.rl.x=center->x+limit;
806         t->r.rl.y=center->y-limit;
807         t->r.lu.y=center->y+limit;
808 }
809 #endif
810
811 void
812 transform_setup_source_rect(struct transformation *t)
813 {
814         int i;
815         struct coord screen[4];
816         struct point screen_pnt[4];
817         struct point_rect *pr;
818         struct map_selection *ms,*msm,*next,**msm_last;
819         ms=t->map_sel;
820         while (ms) {
821                 next=ms->next;
822                 g_free(ms);
823                 ms=next;
824         }
825         t->map_sel=NULL;
826         msm_last=&t->map_sel;
827         ms=t->screen_sel;
828         while (ms) {
829                 int valid=0;
830                 msm=g_new0(struct map_selection, 1);
831                 *msm=*ms;
832                 pr=&ms->u.p_rect;
833                 screen_pnt[0].x=pr->lu.x;       /* left upper */
834                 screen_pnt[0].y=pr->lu.y;
835                 screen_pnt[1].x=pr->rl.x;       /* right upper */
836                 screen_pnt[1].y=pr->lu.y;
837                 screen_pnt[2].x=pr->rl.x;       /* right lower */
838                 screen_pnt[2].y=pr->rl.y;
839                 screen_pnt[3].x=pr->lu.x;       /* left lower */
840                 screen_pnt[3].y=pr->rl.y;
841                 if (t->ddd) {
842                         struct coord_geo_cart tmp,cg[8];
843                         struct coord c;
844                         int valid=0;
845                         int hog=t->hog;
846                         char edgenodes[]={
847                                 0,1,
848                                 1,2,
849                                 2,3,
850                                 3,0,
851                                 4,5,
852                                 5,6,
853                                 6,7,
854                                 7,4,
855                                 0,4,
856                                 1,5,
857                                 2,6,
858                                 3,7};   
859                         for (i = 0 ; i < 8 ; i++) {
860                                 transform_screen_to_3d(t, &screen_pnt[i%4], (i >= 4 ? t->zfar:t->znear), &tmp);
861                                 transform_apply_inverse_matrix(t, &tmp, &cg[i]);
862                         }
863                         msm->u.c_rect.lu.x=0;
864                         msm->u.c_rect.lu.y=0;
865                         msm->u.c_rect.rl.x=0;
866                         msm->u.c_rect.rl.y=0;
867                         for (i = 0 ; i < 12 ; i++) {
868                                 if (transform_zplane_intersection(&cg[edgenodes[i*2]], &cg[edgenodes[i*2+1]], hog, &tmp) == 1) {
869                                         c.x=tmp.x*(1 << t->scale_shift)+t->map_center.x;
870                                         c.y=tmp.y*(1 << t->scale_shift)+t->map_center.y;
871                                         dbg(0,"intersection with edge %d at 0x%x,0x%x\n",i,c.x,c.y);
872                                         if (valid)
873                                                 coord_rect_extend(&msm->u.c_rect, &c);
874                                         else {
875                                                 msm->u.c_rect.lu=c;
876                                                 msm->u.c_rect.rl=c;
877                                                 valid=1;
878                                         }
879                                         dbg(0,"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);
880                                 }
881                         }
882                 } else {
883                         for (i = 0 ; i < 4 ; i++) {
884                                 transform_reverse(t, &screen_pnt[i], &screen[i]);
885                                 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);
886                         }
887                         msm->u.c_rect.lu.x=min4(screen[0].x,screen[1].x,screen[2].x,screen[3].x);
888                         msm->u.c_rect.rl.x=max4(screen[0].x,screen[1].x,screen[2].x,screen[3].x);
889                         msm->u.c_rect.rl.y=min4(screen[0].y,screen[1].y,screen[2].y,screen[3].y);
890                         msm->u.c_rect.lu.y=max4(screen[0].y,screen[1].y,screen[2].y,screen[3].y);
891                 }
892                 dbg(1,"%dx%d\n", msm->u.c_rect.rl.x-msm->u.c_rect.lu.x,
893                                  msm->u.c_rect.lu.y-msm->u.c_rect.rl.y);
894                 *msm_last=msm;
895                 msm_last=&msm->next;
896                 ms=ms->next;
897         }
898 }
899
900 long
901 transform_get_scale(struct transformation *t)
902 {
903         return (int)(t->scale*16);
904 }
905
906 void
907 transform_set_scale(struct transformation *t, long scale)
908 {
909         t->scale=scale/16.0;
910         transform_setup_matrix(t);
911 }
912
913
914 int
915 transform_get_order(struct transformation *t)
916 {
917         dbg(1,"order %d\n", t->order);
918         return t->order;
919 }
920
921
922
923 #define TWOPI (M_PI*2)
924 #define GC2RAD(c) ((c) * TWOPI/(1<<24))
925 #define minf(a,b) ((a) < (b) ? (a) : (b))
926
927 static double
928 transform_distance_garmin(struct coord *c1, struct coord *c2)
929 {
930 #ifdef USE_HALVESINE
931         static const int earth_radius = 6371*1000; //m change accordingly
932 // static const int earth_radius  = 3960; //miles
933  
934 //Point 1 cords
935         navit_float lat1  = GC2RAD(c1->y);
936         navit_float long1 = GC2RAD(c1->x);
937
938 //Point 2 cords
939         navit_float lat2  = GC2RAD(c2->y);
940         navit_float long2 = GC2RAD(c2->x);
941
942 //Haversine Formula
943         navit_float dlong = long2-long1;
944         navit_float dlat  = lat2-lat1;
945
946         navit_float sinlat  = navit_sin(dlat/2);
947         navit_float sinlong = navit_sin(dlong/2);
948  
949         navit_float a=(sinlat*sinlat)+navit_cos(lat1)*navit_cos(lat2)*(sinlong*sinlong);
950         navit_float c=2*navit_asin(minf(1,navit_sqrt(a)));
951 #ifdef AVOID_FLOAT
952         return round(earth_radius*c);
953 #else
954         return earth_radius*c;
955 #endif
956 #else
957 #define GMETER 2.3887499999999999
958         navit_float dx,dy;
959         dx=c1->x-c2->x;
960         dy=c1->y-c2->y;
961         return navit_sqrt(dx*dx+dy*dy)*GMETER;
962 #undef GMETER
963 #endif
964 }
965
966 double
967 transform_scale(int y)
968 {
969         struct coord c;
970         struct coord_geo g;
971         c.x=0;
972         c.y=y;
973         transform_to_geo(projection_mg, &c, &g);
974         return 1/navit_cos(g.lat/180*M_PI);
975 }
976
977 #ifdef AVOID_FLOAT
978 static int
979 tab_sqrt[]={14142,13379,12806,12364,12018,11741,11517,11333,11180,11051,10943,10850,10770,10701,10640,10587,10540,10499,10462,10429,10400,10373,10349,10327,10307,10289,10273,10257,10243,10231,10219,10208};
980
981 static int tab_int_step = 0x20000;
982 static int tab_int_scale[]={10000,10002,10008,10019,10033,10052,10076,10103,10135,10171,10212,10257,10306,10359,10417,10479,10546,10617,10693,10773,10858,10947,11041,11140,11243,11352,11465,11582,11705,11833,11965,12103,12246,12394,12547,12706,12870,13039,13214,13395,13581,13773,13971,14174,14384,14600,14822,15050,15285,15526,15774,16028,16289,16557,16832,17114,17404,17700,18005,18316,18636,18964,19299,19643,19995,20355,20724,21102,21489,21885,22290,22705,23129,23563,24007,24461,24926,25401,25886,26383,26891};
983
984 int transform_int_scale(int y)
985 {
986         int a=tab_int_step,i,size = sizeof(tab_int_scale)/sizeof(int);
987         if (y < 0)
988                 y=-y;
989         i=y/tab_int_step;
990         if (i < size-1) 
991                 return tab_int_scale[i]+((tab_int_scale[i+1]-tab_int_scale[i])*(y-i*tab_int_step))/tab_int_step;
992         return tab_int_scale[size-1];
993 }
994 #endif
995
996 double
997 transform_distance(enum projection pro, struct coord *c1, struct coord *c2)
998 {
999         if (pro == projection_mg) {
1000 #ifndef AVOID_FLOAT 
1001         double dx,dy,scale=transform_scale((c1->y+c2->y)/2);
1002         dx=c1->x-c2->x;
1003         dy=c1->y-c2->y;
1004         return sqrt(dx*dx+dy*dy)/scale;
1005 #else
1006         int dx,dy,f,scale=transform_int_scale((c1->y+c2->y)/2);
1007         dx=c1->x-c2->x;
1008         dy=c1->y-c2->y;
1009         if (dx < 0)
1010                 dx=-dx;
1011         if (dy < 0)
1012                 dy=-dy;
1013         while (dx > 20000 || dy > 20000) {
1014                 dx/=10;
1015                 dy/=10;
1016                 scale/=10;
1017         }
1018         if (! dy)
1019                 return dx*10000/scale;
1020         if (! dx)
1021                 return dy*10000/scale;
1022         if (dx > dy) {
1023                 f=dx*8/dy-8;
1024                 if (f >= 32)
1025                         return dx*10000/scale;
1026                 return dx*tab_sqrt[f]/scale;
1027         } else {
1028                 f=dy*8/dx-8;
1029                 if (f >= 32)
1030                         return dy*10000/scale;
1031                 return dy*tab_sqrt[f]/scale;
1032         }
1033 #endif
1034         } else if (pro == projection_garmin) {
1035                 return transform_distance_garmin(c1, c2);
1036         } else {
1037                 dbg(0,"Unknown projection: %d\n", pro);
1038                 return 0;
1039         }
1040 }
1041
1042 void
1043 transform_project(enum projection pro, struct coord *c, int distance, int angle, struct coord *res)
1044 {
1045         double scale;
1046         switch (pro) {
1047         case projection_mg:
1048                 scale=transform_scale(c->y);
1049                 res->x=c->x+distance*sin(angle*M_PI/180)*scale;
1050                 res->y=c->y+distance*cos(angle*M_PI/180)*scale;
1051                 break;
1052         default:
1053                 dbg(0,"Unsupported projection: %d\n", pro);
1054                 return;
1055         }
1056         
1057 }
1058
1059
1060 double
1061 transform_polyline_length(enum projection pro, struct coord *c, int count)
1062 {
1063         double ret=0;
1064         int i;
1065
1066         for (i = 0 ; i < count-1 ; i++) 
1067                 ret+=transform_distance(pro, &c[i], &c[i+1]);
1068         return ret;
1069 }
1070
1071 int
1072 transform_distance_sq(struct coord *c1, struct coord *c2)
1073 {
1074         int dx=c1->x-c2->x;
1075         int dy=c1->y-c2->y;
1076
1077         if (dx > 32767 || dy > 32767 || dx < -32767 || dy < -32767)
1078                 return INT_MAX;
1079         else
1080                 return dx*dx+dy*dy;
1081 }
1082
1083 int
1084 transform_distance_sq_pc(struct pcoord *c1, struct pcoord *c2)
1085 {
1086         struct coord p1,p2;
1087         p1.x = c1->x; p1.y = c1->y;
1088         p2.x = c2->x; p2.y = c2->y;
1089         return transform_distance_sq(&p1, &p2);
1090 }
1091
1092 int
1093 transform_distance_line_sq(struct coord *l0, struct coord *l1, struct coord *ref, struct coord *lpnt)
1094 {
1095         int vx,vy,wx,wy;
1096         int c1,c2;
1097         int climit=1000000;
1098         struct coord l;
1099
1100         vx=l1->x-l0->x;
1101         vy=l1->y-l0->y;
1102         wx=ref->x-l0->x;
1103         wy=ref->y-l0->y;
1104
1105         c1=vx*wx+vy*wy;
1106         if ( c1 <= 0 ) {
1107                 if (lpnt)
1108                         *lpnt=*l0;
1109                 return transform_distance_sq(l0, ref);
1110         }
1111         c2=vx*vx+vy*vy;
1112         if ( c2 <= c1 ) {
1113                 if (lpnt)
1114                         *lpnt=*l1;
1115                 return transform_distance_sq(l1, ref);
1116         }
1117         while (c1 > climit || c2 > climit) {
1118                 c1/=256;
1119                 c2/=256;
1120         }
1121         l.x=l0->x+vx*c1/c2;
1122         l.y=l0->y+vy*c1/c2;
1123         if (lpnt)
1124                 *lpnt=l;
1125         return transform_distance_sq(&l, ref);
1126 }
1127
1128 int
1129 transform_distance_polyline_sq(struct coord *c, int count, struct coord *ref, struct coord *lpnt, int *pos)
1130 {
1131         int i,dist,distn;
1132         struct coord lp;
1133         if (count < 2)
1134                 return INT_MAX;
1135         if (pos)
1136                 *pos=0;
1137         dist=transform_distance_line_sq(&c[0], &c[1], ref, lpnt);
1138         for (i=2 ; i < count ; i++) {
1139                 distn=transform_distance_line_sq(&c[i-1], &c[i], ref, &lp);
1140                 if (distn < dist) {
1141                         dist=distn;
1142                         if (lpnt)
1143                                 *lpnt=lp;
1144                         if (pos)
1145                                 *pos=i-1;
1146                 }
1147         }
1148         return dist;
1149 }
1150
1151 int
1152 transform_douglas_peucker(struct coord *in, int count, int dist_sq, struct coord *out)
1153 {
1154         int ret=0;
1155         int i,d,dmax=0, idx=0;
1156         for (i = 1; i < count-1 ; i++) {
1157                 d=transform_distance_line_sq(&in[0], &in[count-1], &in[i], NULL);
1158                 if (d > dmax) {
1159                         idx=i;
1160                         dmax=d;
1161                 }
1162         }
1163         if (dmax > dist_sq) {
1164                 ret=transform_douglas_peucker(in, idx+1, dist_sq, out)-1;
1165                 ret+=transform_douglas_peucker(in+idx, count-idx, dist_sq, out+ret);
1166         } else {
1167                 if (count > 0)
1168                         out[ret++]=in[0];
1169                 if (count > 1)
1170                         out[ret++]=in[count-1];
1171         }
1172         return ret;
1173 }
1174
1175
1176 void
1177 transform_print_deg(double deg)
1178 {
1179         printf("%2.0f:%2.0f:%2.4f", floor(deg), fmod(deg*60,60), fmod(deg*3600,60));
1180 }
1181
1182 #ifdef AVOID_FLOAT
1183 static int tab_atan[]={0,262,524,787,1051,1317,1584,1853,2126,2401,2679,2962,3249,3541,3839,4142,4452,4770,5095,5430,5774,6128,6494,6873,7265,7673,8098,8541,9004,9490,10000,10538};
1184
1185 static int
1186 atan2_int_lookup(int val)
1187 {
1188         int len=sizeof(tab_atan)/sizeof(int);
1189         int i=len/2;
1190         int p=i-1;
1191         for (;;) {
1192                 i>>=1;
1193                 if (val < tab_atan[p])
1194                         p-=i;
1195                 else
1196                         if (val < tab_atan[p+1])
1197                                 return p+(p>>1);
1198                         else
1199                                 p+=i;
1200         }
1201 }
1202
1203 static int
1204 atan2_int(int dx, int dy)
1205 {
1206         int f,mul=1,add=0,ret;
1207         if (! dx) {
1208                 return dy < 0 ? 180 : 0;
1209         }
1210         if (! dy) {
1211                 return dx < 0 ? -90 : 90;
1212         }
1213         if (dx < 0) {
1214                 dx=-dx;
1215                 mul=-1;
1216         }
1217         if (dy < 0) {
1218                 dy=-dy;
1219                 add=180*mul;
1220                 mul*=-1;
1221         }
1222         while (dx > 20000 || dy > 20000) {
1223                 dx/=10;
1224                 dy/=10;
1225         }
1226         if (dx > dy) {
1227                 ret=90-atan2_int_lookup(dy*10000/dx);
1228         } else {
1229                 ret=atan2_int_lookup(dx*10000/dy);
1230         }
1231         return ret*mul+add;
1232 }
1233 #endif
1234
1235 int
1236 transform_get_angle_delta(struct coord *c1, struct coord *c2, int dir)
1237 {
1238         int dx=c2->x-c1->x;
1239         int dy=c2->y-c1->y;
1240 #ifndef AVOID_FLOAT 
1241         double angle;
1242         angle=atan2(dx,dy);
1243         angle*=180/M_PI;
1244 #else
1245         int angle;
1246         angle=atan2_int(dx,dy);
1247 #endif
1248         if (dir == -1)
1249                 angle=angle-180;
1250         if (angle < 0)
1251                 angle+=360;
1252         return angle;
1253 }
1254
1255 int
1256 transform_within_border(struct transformation *this_, struct point *p, int border)
1257 {
1258         struct map_selection *ms=this_->screen_sel;
1259         while (ms) {
1260                 struct point_rect *r=&ms->u.p_rect;
1261                 if (p->x >= r->lu.x+border && p->x <= r->rl.x-border &&
1262                     p->y >= r->lu.y+border && p->y <= r->rl.y-border)
1263                         return 1;
1264                 ms=ms->next;
1265         }
1266         return 0;
1267 }
1268
1269 int
1270 transform_within_dist_point(struct coord *ref, struct coord *c, int dist)
1271 {
1272         if (c->x-dist > ref->x)
1273                 return 0;
1274         if (c->x+dist < ref->x)
1275                 return 0;
1276         if (c->y-dist > ref->y)
1277                 return 0;
1278         if (c->y+dist < ref->y)
1279                 return 0;
1280         if ((c->x-ref->x)*(c->x-ref->x) + (c->y-ref->y)*(c->y-ref->y) <= dist*dist) 
1281                 return 1;
1282         return 0;
1283 }
1284
1285 int
1286 transform_within_dist_line(struct coord *ref, struct coord *c0, struct coord *c1, int dist)
1287 {
1288         int vx,vy,wx,wy;
1289         int n1,n2;
1290         struct coord lc;
1291
1292         if (c0->x < c1->x) {
1293                 if (c0->x-dist > ref->x)
1294                         return 0;
1295                 if (c1->x+dist < ref->x)
1296                         return 0;
1297         } else {
1298                 if (c1->x-dist > ref->x)
1299                         return 0;
1300                 if (c0->x+dist < ref->x)
1301                         return 0;
1302         }
1303         if (c0->y < c1->y) {
1304                 if (c0->y-dist > ref->y)
1305                         return 0;
1306                 if (c1->y+dist < ref->y)
1307                         return 0;
1308         } else {
1309                 if (c1->y-dist > ref->y)
1310                         return 0;
1311                 if (c0->y+dist < ref->y)
1312                         return 0;
1313         }
1314         vx=c1->x-c0->x;
1315         vy=c1->y-c0->y;
1316         wx=ref->x-c0->x;
1317         wy=ref->y-c0->y;
1318
1319         n1=vx*wx+vy*wy;
1320         if ( n1 <= 0 )
1321                 return transform_within_dist_point(ref, c0, dist);
1322         n2=vx*vx+vy*vy;
1323         if ( n2 <= n1 )
1324                 return transform_within_dist_point(ref, c1, dist);
1325
1326         lc.x=c0->x+vx*n1/n2;
1327         lc.y=c0->y+vy*n1/n2;
1328         return transform_within_dist_point(ref, &lc, dist);
1329 }
1330
1331 int
1332 transform_within_dist_polyline(struct coord *ref, struct coord *c, int count, int close, int dist)
1333 {
1334         int i;
1335         for (i = 0 ; i < count-1 ; i++) {
1336                 if (transform_within_dist_line(ref,c+i,c+i+1,dist)) {
1337                         return 1;
1338                 }
1339         }
1340         if (close)
1341                 return (transform_within_dist_line(ref,c,c+count-1,dist));
1342         return 0;
1343 }
1344
1345 int
1346 transform_within_dist_polygon(struct coord *ref, struct coord *c, int count, int dist)
1347 {
1348         int i, j, ci = 0;
1349         for (i = 0, j = count-1; i < count; j = i++) {
1350                 if ((((c[i].y <= ref->y) && ( ref->y < c[j].y )) ||
1351                 ((c[j].y <= ref->y) && ( ref->y < c[i].y))) &&
1352                 (ref->x < (c[j].x - c[i].x) * (ref->y - c[i].y) / (c[j].y - c[i].y) + c[i].x))
1353                         ci = !ci;
1354         }
1355         if (! ci) {
1356                 if (dist)
1357                         return transform_within_dist_polyline(ref, c, count, dist, 1);
1358                 else
1359                         return 0;
1360         }
1361         return 1;
1362 }
1363
1364 int
1365 transform_within_dist_item(struct coord *ref, enum item_type type, struct coord *c, int count, int dist)
1366 {
1367         if (type < type_line)
1368                 return transform_within_dist_point(ref, c, dist);
1369         if (type < type_area)
1370                 return transform_within_dist_polyline(ref, c, count, 0, dist);
1371         return transform_within_dist_polygon(ref, c, count, dist);
1372 }
1373
1374 void
1375 transform_destroy(struct transformation *t)
1376 {
1377         g_free(t);
1378 }
1379
1380
1381 /*
1382 Note: there are many mathematically equivalent ways to express these formulas. As usual, not all of them are computationally equivalent.
1383
1384 L = latitude in radians (positive north)
1385 Lo = longitude in radians (positive east)
1386 E = easting (meters)
1387 N = northing (meters)
1388
1389 For the sphere
1390
1391 E = r Lo
1392 N = r ln [ tan (pi/4 + L/2) ]
1393
1394 where 
1395
1396 r = radius of the sphere (meters)
1397 ln() is the natural logarithm
1398
1399 For the ellipsoid
1400
1401 E = a Lo
1402 N = a * ln ( tan (pi/4 + L/2) * ( (1 - e * sin (L)) / (1 + e * sin (L))) ** (e/2)  )
1403
1404
1405                                                e
1406                                                -
1407                    pi     L     1 - e sin(L)   2
1408     =  a ln( tan( ---- + ---) (--------------)   )
1409                    4      2     1 + e sin(L) 
1410
1411
1412 where
1413
1414 a = the length of the semi-major axis of the ellipsoid (meters)
1415 e = the first eccentricity of the ellipsoid
1416
1417
1418 */
1419
1420