home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.parl.clemson.edu
/
2015-02-07.ftp.parl.clemson.edu.tar
/
ftp.parl.clemson.edu
/
pub
/
portedOneB.tar
/
OneB
/
SolarTools.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-07-13
|
10KB
|
370 lines
#include "RAConeb.h"
const LDOUBLE
e_Re = 6378149.196,
e_ecc_sq = 6.694378665e-3;
//------------------------------------------------------------------------------
//
// Solar Zenith Angle Computation Program
//
// coded by C. Hoisington SSAI
// 19 Feb 98 version 1.0
//
// modified by Scott Mitchell
// 20 Feb 98 version 1.1
//
// This contains the procedures and a test main program to compute
// Solar Zenith Angles
//
//------------------------------------------------------------------------------
/*
CC -g SolarAngleProgram.c -I../mystuff2 ../mystuff2/mylib.a myorbit.a \
/usr/lib/libm.a -lm -o SolarAngleProgram
*/
LDOUBLE PrincipleAngleDeg (LDOUBLE angle);
LDOUBLE JulianDate (time_t unixTimeSec);
LDOUBLE chGreenwichHourAngle (LDOUBLE t1970);
//------------------------------------------------------------------------------
//
// PrincipleAngleDeg
//
// Convert angle to principle positive angle. (degrees)
//
//------------------------------------------------------------------------------
LDOUBLE PrincipleAngleDeg (LDOUBLE angle)
{
LDOUBLE base;
base = fmod (angle, 360L);
if (base < 0.L) base += 360L;
return base;
}
//------------------------------------------------------------------------------
//
// AngleBetweenVectors
//
// Compute angle between to vectors in rectangular coordinates.
// (returns angle in radians)
//
//------------------------------------------------------------------------------
LDOUBLE AngleBetweenVectors
(
LDOUBLE x1,
LDOUBLE y1,
LDOUBLE z1,
LDOUBLE x2,
LDOUBLE y2,
LDOUBLE z2
)
{
LDOUBLE dotProduct, absV1, absV2, aTemp;
dotProduct = x1*x2 + y1*y2 + z1*z2;
absV1 = sqrt (x1*x1 + y1*y1 + z1*z1);
absV2 = sqrt (x2*x2 + y2*y2 + z2*z2);
/* Perform an FINIT if defined in platform.h as needed */
FINIT
aTemp = acos ( dotProduct / (absV1*absV2) );
return aTemp;
}
//------------------------------------------------------------------------------
//
// chGreenwichHourAngle
//
// - compute Greenwich Hour Angle from time in seconds from 0 Jan 1970.
//
//
//------------------------------------------------------------------------------
LDOUBLE chGreenwichHourAngle (LDOUBLE t1970)
{
const LDOUBLE
DEL= +.22737064e0; // correct GHA to 91/10/02
// 01:13:18.030
const LDOUBLE
G0 = 0.1746647027e+1, // GHA on 01 Jan 1950 (Rad)
G1 = 0.1720279100e-1, // GHA revolutions/Day (Rad/Day)
RE = 0.7292115850e-4, // Earth rotation rate (Rad/Sec)
CA = 0.7671432057e-4, // Nutation amplitude (Rad)
A1 = 0.2114043493e+0, // Nutation component 01 Jan 50
A2 = 0.9242186639e-3, // Nutation rate (Rad/Day)
CB = 0.5662286171e-5, // Earth orbit rev comp. (Rad)
B1 = 0.3493493163e+1, // Earth rev comp. 01 Jan (Rad)
B2 = 0.3440558258e-1; // Earth rev rate (Rad/day)
LDOUBLE SEC,SD,RAD;
long DY;
SEC = t1970 + 631152000;
DY = SEC/86400e0; // days since 1950
SD = SEC-DY*86400 + DEL; // second of day
RAD = G0 + G1 * DY + RE * SD // Earth Rotation
- CA * sin (A1 - DY*A2) // Nutation component
- CB * sin (B1 + DY*B2); // revolution component
RAD = fmod (RAD,m_twoPi); // convert to principle angle
return RAD;
}
//------------------------------------------------------------------------------
//
// RectInertialToFixed
//
// Convert Geocentric Rectangular Inertial coordinates to Earth Fixed
// Coordinates
//
//------------------------------------------------------------------------------
void RectInertialToFixed
(
LDOUBLE greenwichHourAngle,
LDOUBLE inertxp, // inertial coordinates input
LDOUBLE inertyp,
LDOUBLE inertzp,
LDOUBLE *fixedxp, // earth fixed coordinates output
LDOUBLE *fixedyp,
LDOUBLE *fixedzp
)
{
LDOUBLE sinGha,cosGha;
sinGha = sin (greenwichHourAngle);
cosGha = cos (greenwichHourAngle);
*fixedxp = inertxp * cosGha + inertyp * sinGha; // position
*fixedyp = -inertxp * sinGha + inertyp * cosGha;
*fixedzp = inertzp;
}
//------------------------------------------------------------------------------
//
// GeodeticToFixedRect
//
// Convert Geodetic (latitude and longitude) coordinates to earth fixed
// rectangular coordinates
//
//------------------------------------------------------------------------------
void GeodeticToFixedRect
(
LDOUBLE phi,
LDOUBLE lambda,
LDOUBLE *xp,
LDOUBLE *yp,
LDOUBLE *zp
)
{
LDOUBLE sinPhi,cosPhi,sinLambda,cosLambda,Rs;
sinPhi = sin (phi); // Sine phi
cosPhi = cos (phi); // Cos phi
sinLambda = sin (lambda); // Sine lambda
cosLambda = cos (lambda); // Cosine lambda
Rs = e_Re / sqrt (1. - e_ecc_sq * sinPhi*sinPhi);
// rectangular coordinates
*xp = (Rs) * cosPhi * cosLambda;
*yp = (Rs) * cosPhi * sinLambda;
*zp = (Rs * (1.-e_ecc_sq)) * sinPhi;
}
//------------------------------------------------------------------------------
//
// GeoInertialSunLocation
//
// Compute sun location in geocentric inertial rectangular coordinates
//
// Note: See "The Astronomical Almanac for the Year 1996", U.S. Government
// Printing Office, page C24
//
//------------------------------------------------------------------------------
void GeoInertialSunLocation
(
LDOUBLE JulianDate,
LDOUBLE *xp,
LDOUBLE *yp,
LDOUBLE *zp
)
{
LDOUBLE au = 149598845.0L; // astronomical unit in kilometers
LDOUBLE n, L, g, gr, eta, etar, lambda, lambdar, R, x, y, z;
n = JulianDate - 2451545.0L; // days from J2000.0
L = 280.461L + 0.9856474L * n; // mean longitude of sun
L = PrincipleAngleDeg(L);
g = 357.528L + 0.9856003L * n; // mean anomaly (deg)
g = PrincipleAngleDeg(g);
gr= g*m_dToR;
eta = 23.439L - 0.0000004L * n; // Obliquity of ecliptic
etar= eta * m_dToR;
lambda = L + 1.915L * sin(gr) + 0.020 * sin (2*gr); // Ecliptic longitude
lambdar= lambda *m_dToR;
R = 1.00014L - 0.01671L * cos(gr) - 0.00014L * cos(2*gr); // distance of sun from earth in a.u
x = R * cos(lambdar);
y = R * cos(etar ) * sin(lambdar);
z = R * sin(etar ) * sin(lambdar);
*xp = x * au;
*yp = y * au;
*zp = z * au;
}
//------------------------------------------------------------------------------
//
// GeoFixedSunLocation
//
// Compute sun location in geocentric fixed rectangular coordinates
//
//------------------------------------------------------------------------------
void GeoFixedSunLocation
(
LDOUBLE unixSec,
LDOUBLE *sunXfixed,
LDOUBLE *sunYfixed,
LDOUBLE *sunZfixed
)
{
LDOUBLE sunXinertial, sunYinertial, sunZinertial;
LDOUBLE julianDays, greenwichHourAngle;
julianDays = JulianDate (unixSec);
GeoInertialSunLocation
(
julianDays,
&sunXinertial, &sunYinertial, &sunZinertial
);
greenwichHourAngle = chGreenwichHourAngle ( (LDOUBLE)unixSec );
RectInertialToFixed
(
greenwichHourAngle,
sunXinertial, sunYinertial, sunZinertial,
sunXfixed, sunYfixed, sunZfixed
);
}
//------------------------------------------------------------------------------
//
// JulianDate
//
//------------------------------------------------------------------------------
LDOUBLE JulianDate (time_t unixTimeSec)
{
return 2440587.5L + (LDOUBLE)unixTimeSec / 86400.L;
}
//------------------------------------------------------------------------------
//
// SolarZenithAngle
//
// Compute the solar zenith angle at a given time for the specified
// latitude and longitude.
//
// (angle is returned in degrees.)
//
//------------------------------------------------------------------------------
LDOUBLE SolarZenithAngle
(
char *buffer, int fourDigitYear, int dayOfYear, long milliSecondOfDay, time_t unixTime,
LDOUBLE latitudeDeg, LDOUBLE longitudeDeg
)
//------------------------------------------------------------------------
// procedure body
//
//------------------------------------------------------------------------
{
LDOUBLE sunXfixed, sunYfixed, sunZfixed;
LDOUBLE pixelXfixed, pixelYfixed, pixelZfixed;
time_t unixSec;
LDOUBLE aTemp;
unixSec = unixTime;
//--------------------------------------------------------------------
// compute Sun location
//--------------------------------------------------------------------
GeoFixedSunLocation
(
(LDOUBLE)unixSec,
&sunXfixed, &sunYfixed, &sunZfixed
);
//--------------------------------------------------------------------
// compute pixel location
//--------------------------------------------------------------------
GeodeticToFixedRect
(
latitudeDeg*m_dToR, longitudeDeg*m_dToR,
&pixelXfixed, &pixelYfixed, &pixelZfixed
);
//--------------------------------------------------------------------
// compute angle between pixel and sun
//--------------------------------------------------------------------
// printf("sunXfixed = %f, sunYfixed = %f, sunZfixed = %f\n", sunXfixed, sunYfixed, sunZfixed);
// printf("pixelXfixed = %f, pixelYfixed = %f, pixelZfixed = %f\n", pixelXfixed, pixelYfixed, pixelZfixed);
aTemp = (AngleBetweenVectors
(
sunXfixed, sunYfixed, sunZfixed,
pixelXfixed, pixelYfixed, pixelZfixed
) * m_rToD);
aTemp *= 2.0;
// printf("(uchar)aTemp = %c\n", (uchar)aTemp);
buffer[0] = (uchar)aTemp;
// printf("buffer[0] = %c\n", buffer[0]);
// printf("aTemp = %Lf\n", aTemp);
return aTemp;
}