// sattool - visual satellite tracking and prediction tool.
// Copyright 2000 Tom Rothamel <tom-idbg@onegeek.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  

#include "sattool.h"

Encounter::Encounter() {
	obj = NULL;
	site = NULL;
	
	objp = new Position;
	sitep = new Position;
	relp = new Position;
	rotp = new Position;
}

// This creates a new Encounter object, and then it calls calc
// on the parameters, combining the two steps.
Encounter::Encounter(Object *nobj, Object *nsite, double nt) {
	obj = NULL;
	site = NULL;

	objp = new Position;
	sitep = new Position;
	relp = new Position;
	rotp = new Position;

	calc(nobj, nsite, nt);
}

Encounter::~Encounter() {
	delete objp;
	delete sitep;
	delete relp;
	delete rotp;

	if (obj) unlock(obj);
	if (obj) unlock(site);
}
	

// Rotates a vector around the y axis.
static void yrot(double *x, double sint, double cost) {
        double tempz;

        tempz = x[0] * sint + x[2] * cost;
        x[0] = x[0] * cost - x[2] * sint;
        x[2] = tempz;
}

// Rotates a vector around the z axis.
static void zrot(double *x, double sint, double cost) {
        double tempx;

        tempx = x[0] * sint + x[1] * cost;
        x[0] = x[0] * cost - x[1] * sint;
        x[1] = tempx;
}

// Calculates the elevation of an object, as well as the various
// position vectors.
double Encounter::calc(Object *nobj, Object *nsite, double nt) {
	int i;

	if (obj) unlock(obj);
	if (site) unlock(site);
	
	obj = nobj;
	site = nsite;

	_object = obj;		
	_time = nt;
	_sat = getSat(_object);
	
	lock(obj);
	lock(site);
	
	t = nt;

	obj->calcpos(t, objp);
	site->calcpos(t, sitep);

	for (i = 0; i < 3; i++) {
		relp->x[i] = objp->x[i] - sitep->x[i];
		rotp->x[i] = relp->x[i];
	}
	
	zrot(rotp->x, sitep->sintheta, sitep->costheta);
	yrot(rotp->x, sitep->sinlat, sitep->coslat);

	// At this point, relp contains the object's eci coordinates as
	// an offset of the observers, and rotp contains the coordinites
	// in a new system where the x-axis is the zenith and the z-axis
	// points in the azimuth reference direction. (usually north.)
	
	elevation = RADEG * atan2(rotp->x[0], hypot(rotp->x[1], rotp->x[2]));
	return elevation;
}

// This calculates a few more things about this encounter. (Actually,
// everything that isn't the elevation.)
void Encounter::calcmore() {
	azimuth = RADEG * atan2(rotp->x[1], rotp->x[2]);	
	range = hypot(rotp->x[0], hypot(rotp->x[1], rotp->x[2]));

	if (azimuth < 0) azimuth += 360;
	
	ra = M_PI - atan2(-relp->x[0], relp->x[1]);
	dec = atan2(relp->x[2], hypot(relp->x[1], relp->x[0]));	
}
