/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include "map.h" static struct coord p0; /* standard parallel */ int first; static doubletrigclamp(double x){ return x>1? 1: x<-1? -1: x;} static struct coord az; /* azimuth of p0 seen from place */static struct coord rad; /* angular dist from place to p0 */ static intazimuth(struct place *place){ if(place->nlat.c < FUZZ) { az.l = PI/2 + place->nlat.l - place->wlon.l; sincos(&az); rad.l = fabs(place->nlat.l - p0.l); if(rad.l > PI) rad.l = 2*PI - rad.l; sincos(&rad); return 1; } rad.c = trigclamp(p0.s*place->nlat.s + /* law of cosines */ p0.c*place->nlat.c*place->wlon.c); rad.s = sqrt(1 - rad.c*rad.c); if(fabs(rad.s) < .001) { az.s = 0; az.c = 1; } else { az.s = trigclamp(p0.c*place->wlon.s/rad.s); /* sines */ az.c = trigclamp((p0.s - rad.c*place->nlat.s) /(rad.s*place->nlat.c)); } rad.l = atan2(rad.s, rad.c); return 1;} static intXmecca(struct place *place, double *x, double *y){ if(!azimuth(place)) return 0; *x = -place->wlon.l; *y = fabs(az.s)<.02? -az.c*rad.s/p0.c: *x*az.c/az.s; return fabs(*y)>2? -1: rad.c<0? 0: 1;} projmecca(double par){ first = 1; if(fabs(par)>80.) return(0); deg2rad(par,&p0); return(Xmecca);} static intXhoming(struct place *place, double *x, double *y){ if(!azimuth(place)) return 0; *x = -rad.l*az.s; *y = -rad.l*az.c; return place->wlon.c<0? 0: 1;} projhoming(double par){ first = 1; if(fabs(par)>80.) return(0); deg2rad(par,&p0); return(Xhoming);} inthlimb(double *lat, double *lon, double res){ if(first) { *lon = -90; *lat = -90; first = 0; return 0; } *lat += res; if(*lat <= 90) return 1; if(*lon == 90) return -1; *lon = 90; *lat = -90; return 0;} intmlimb(double *lat, double *lon, double res){ int ret = !first; if(fabs(p0.s) < .01) return -1; if(first) { *lon = -180; first = 0; } else *lon += res; if(*lon > 180) return -1; *lat = atan(-cos(*lon*RAD)/p0.s*p0.c)/RAD; return ret;}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#include <u.h>
#include <libc.h>
#include "map.h"
static struct coord p0; /* standard parallel */
int first;
static double
trigclamp(double x)
{
return x>1? 1: x<-1? -1: x;
}
static struct coord az; /* azimuth of p0 seen from place */
static struct coord rad; /* angular dist from place to p0 */
static int
azimuth(struct place *place)
{
if(place->nlat.c < FUZZ) {
az.l = PI/2 + place->nlat.l - place->wlon.l;
sincos(&az);
rad.l = fabs(place->nlat.l - p0.l);
if(rad.l > PI)
rad.l = 2*PI - rad.l;
sincos(&rad);
return 1;
}
rad.c = trigclamp(p0.s*place->nlat.s + /* law of cosines */
p0.c*place->nlat.c*place->wlon.c);
rad.s = sqrt(1 - rad.c*rad.c);
if(fabs(rad.s) < .001) {
az.s = 0;
az.c = 1;
} else {
az.s = trigclamp(p0.c*place->wlon.s/rad.s); /* sines */
az.c = trigclamp((p0.s - rad.c*place->nlat.s)
/(rad.s*place->nlat.c));
}
rad.l = atan2(rad.s, rad.c);
return 1;
}
static int
Xmecca(struct place *place, double *x, double *y)
{
if(!azimuth(place))
return 0;
*x = -place->wlon.l;
*y = fabs(az.s)<.02? -az.c*rad.s/p0.c: *x*az.c/az.s;
return fabs(*y)>2? -1:
rad.c<0? 0:
1;
}
proj
mecca(double par)
{
first = 1;
if(fabs(par)>80.)
return(0);
deg2rad(par,&p0);
return(Xmecca);
}
static int
Xhoming(struct place *place, double *x, double *y)
{
if(!azimuth(place))
return 0;
*x = -rad.l*az.s;
*y = -rad.l*az.c;
return place->wlon.c<0? 0: 1;
}
proj
homing(double par)
{
first = 1;
if(fabs(par)>80.)
return(0);
deg2rad(par,&p0);
return(Xhoming);
}
int
hlimb(double *lat, double *lon, double res)
{
if(first) {
*lon = -90;
*lat = -90;
first = 0;
return 0;
}
*lat += res;
if(*lat <= 90)
return 1;
if(*lon == 90)
return -1;
*lon = 90;
*lat = -90;
return 0;
}
int
mlimb(double *lat, double *lon, double res)
{
int ret = !first;
if(fabs(p0.s) < .01)
return -1;
if(first) {
*lon = -180;
first = 0;
} else
*lon += res;
if(*lon > 180)
return -1;
*lat = atan(-cos(*lon*RAD)/p0.s*p0.c)/RAD;
return ret;
}