shithub: riscv

ref: 0ab5d34be4b8b9faa96d4691de95d6ae8c691f0b
dir: /sys/src/cmd/map/libmap/perspective.c/

View raw version
#include <u.h>
#include <libc.h>
#include "map.h"

#define ORTHRAD 1000
static double viewpt;

static int
Xperspective(struct place *place, double *x, double *y)
{
	double r;
	if(viewpt<=1+FUZZ && fabs(place->nlat.s<=viewpt+.01))
		return(-1);
	r = place->nlat.c*(viewpt - 1.)/(viewpt - place->nlat.s);
	*x = - r*place->wlon.s;
	*y = - r*place->wlon.c;
	if(r>4.)
		return(-1);
	if(fabs(viewpt)>1 && place->nlat.s<1/viewpt ||
	   fabs(viewpt)<=1 && place->nlat.s<viewpt)
			return 0;
	return(1);
}

proj
perspective(double radius)
{
	viewpt = radius;
	if(viewpt >= ORTHRAD)
		return(Xorthographic);
	if(fabs(viewpt-1.)<.0001)
		return(0);
	return(Xperspective);
}

	/* called from various conformal projections,
           but not from stereographic itself */
int
Xstereographic(struct place *place, double *x, double *y)
{
	double v = viewpt;
	int retval;
	viewpt = -1;
	retval = Xperspective(place, x, y);
	viewpt = v;
	return retval;
}

proj
stereographic(void)
{
	viewpt = -1.;
	return(Xperspective);
}

proj
gnomonic(void)
{
	viewpt = 0.;
	return(Xperspective);
}

int
plimb(double *lat, double *lon, double res)
{
	static first = 1;
	if(viewpt >= ORTHRAD)
		return olimb(lat, lon, res);
	if(first) {
		first = 0;
		*lon = -180;
		if(fabs(viewpt) < .01)
			*lat = 0;
		else if(fabs(viewpt)<=1)
			*lat = asin(viewpt)/RAD;
		else
			*lat = asin(1/viewpt)/RAD;
	} else
		*lon += res;
	if(*lon <= 180)
		return 1;
	first = 1;
	return -1;
}