/[zanavi_public1]/navit/navit/transform.c
ZANavi

Contents of /navit/navit/transform.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki