int dihf(float x, float y, float z, float *d, float *i, float *h, float *f) { float h2; float sn, hpx; sn = (float)1e-4; h2 = x * x + y * y; *h = sqrt(h2); *f = sqrt(h2 + z * z); if (*f < sn) { *d = (float)999.; *i = (float)999.; } else { *i = atan2d(z,*h); if (*h < sn) { *d = (float)999.; } else { hpx = *h + x; if (hpx < sn) { *d = (float) 180.; } else { *d = atan2d(y,hpx) * (float)2.; } } } return 0; }
static void astro_sunpos(double d, double *lon, double *r) { double M, /* Mean anomaly of the Sun */ w, /* Mean longitude of perihelion */ /* Note: Sun's mean longitude = M + w */ e, /* Eccentricity of Earth's orbit */ E, /* Eccentric anomaly */ x, y, /* x, y coordinates in orbit */ v; /* True anomaly */ /* Compute mean elements */ M = astro_revolution(356.0470 + 0.9856002585 * d); w = 282.9404 + 4.70935E-5 * d; e = 0.016709 - 1.151E-9 * d; /* Compute true longitude and radius vector */ E = M + e * RADEG * sind(M) * (1.0 + e * cosd(M)); x = cosd(E) - e; y = sqrt(1.0 - e*e) * sind(E); *r = sqrt(x*x + y*y); /* Solar distance */ v = atan2d(y, x); /* True anomaly */ *lon = v + w; /* True solar longitude */ if (*lon >= 360.0) { *lon -= 360.0; /* Make it 0..360 degrees */ } }
void sunpos( double d, double *lon, double *r ) /******************************************************/ /* Computes the Sun's ecliptic longitude and distance */ /* at an instant given in d, number of days since */ /* 2000 Jan 0.0. The Sun's ecliptic latitude is not */ /* computed, since it's always very near 0. */ /******************************************************/ { double M, /* Mean anomaly of the Sun */ w, /* Mean longitude of perihelion */ /* Note: Sun's mean longitude = M + w */ e, /* Eccentricity of Earth's orbit */ E, /* Eccentric anomaly */ x, y, /* x, y coordinates in orbit */ v; /* True anomaly */ /* Compute mean elements */ M = revolution( 356.0470 + 0.9856002585 * d ); w = 282.9404 + 4.70935E-5 * d; e = 0.016709 - 1.151E-9 * d; /* Compute true longitude and radius vector */ E = M + e * RADEG * sind(M) * ( 1.0 + e * cosd(M) ); x = cosd(E) - e; y = sqrt( 1.0 - e*e ) * sind(E); *r = sqrt( x*x + y*y ); /* Solar distance */ v = atan2d( y, x ); /* True anomaly */ *lon = v + w; /* True solar longitude */ if ( *lon >= 360.0 ) *lon -= 360.0; /* Make it 0..360 degrees */ }
void fldpnt(double rrho,double rlat,double rlon,double ral, double rel,double r,double *frho,double *flat, double *flon) { double rx,ry,rz,sx,sy,sz,tx,ty,tz; double sinteta; /* convert from global spherical to global cartesian*/ sinteta=sind(90.0-rlat); rx=rrho*sinteta*cosd(rlon); ry=rrho*sinteta*sind(rlon); rz=rrho*cosd(90.0-rlat); sx=-r*cosd(rel)*cosd(ral); sy=r*cosd(rel)*sind(ral); sz=r*sind(rel); tx = cosd(90.0-rlat)*sx + sind(90.0-rlat)*sz; ty = sy; tz = -sind(90.0-rlat)*sx + cosd(90.0-rlat)*sz; sx = cosd(rlon)*tx - sind(rlon)*ty; sy = sind(rlon)*tx + cosd(rlon)*ty; sz = tz; tx=rx+sx; ty=ry+sy; tz=rz+sz; /* convert from cartesian back to global spherical*/ *frho=sqrt((tx*tx)+(ty*ty)+(tz*tz)); *flat=90.0-acosd(tz/(*frho)); if ((tx==0) && (ty==0)) *flon=0; else *flon=atan2d(ty,tx); }
int RPosRngBmAzmElv(int bm,int rn,int year, struct RadarSite *hdw,double frang, double rsep,double rx,double height, double *azm,double *elv) { double flat,flon,frho; double fx,fy,fz; double gx,gy,gz; double glat,glon; double gdlat,gdlon,gdrho; double gbx,gby,gbz; double ghx,ghy,ghz; double bx,by,bz,b; double dummy; int s; gdlat=hdw->geolat; gdlon=hdw->geolon; if (rx==0) rx=hdw->recrise; RPosGeo(1,bm,rn,hdw,frang,rsep,rx, height,&frho,&flat,&flon); sphtocar(frho,flat,flon,&fx,&fy,&fz); geodtgc(1,&gdlat,&gdlon,&gdrho,&glat,&glon,&dummy); sphtocar(gdrho,glat,glon,&gbx,&gby,&gbz); gx=fx-gbx; gy=fy-gby; gz=fz-gbz; norm_vec(&gx,&gy,&gz); glbthor(1,flat,flon,&gx,&gy,&gz,&ghx,&ghy,&ghz); norm_vec(&ghx,&ghy,&ghz); s=IGRFMagCmp(year,frho,flat,flon,&bx,&by,&bz,&b); if (s==-1) return -1; norm_vec(&bx,&by,&bz); ghz=-(bx*ghx+by*ghy)/bz; norm_vec(&ghx,&ghy,&ghz); *elv=atan2d(ghz,sqrt(ghx*ghx+ghy*ghy)); *azm=atan2d(ghy,-ghx); return 0; }
/***********************************************************************//** * @brief Cartesian-to-spherical deprojection * * @param[in] nx X vector length. * @param[in] ny Y vector length (0=no replication). * @param[in] sxy Input vector step. * @param[in] spt Output vector step. * @param[in] x Vector of projected x coordinates. * @param[in] y Vector of projected y coordinates. * @param[out] phi Longitude of the projected point in native spherical * coordinates [deg]. * @param[out] theta Latitude of the projected point in native spherical * coordinates [deg]. * @param[out] stat Status return value for each vector element (always 0) * * Deproject Cartesian (x,y) coordinates in the plane of projection to native * spherical coordinates (phi,theta). * * This method has been adapted from the wcslib function prj.c::carx2s(). * The interface follows very closely that of wcslib. In contrast to the * wcslib routine, however, the method assumes that the projection has been * setup previsouly (as this will be done by the constructor). ***************************************************************************/ void GWcsSTG::prj_x2s(int nx, int ny, int sxy, int spt, const double* x, const double* y, double* phi, double* theta, int* stat) const { // Initialize projection if required if (!m_prjset) prj_set(); // Set value replication length mx,my int mx; int my; if (ny > 0) { mx = nx; my = ny; } else { mx = 1; my = 1; ny = nx; } // Do x dependence const double* xp = x; int rowoff = 0; int rowlen = nx * spt; for (int ix = 0; ix < nx; ++ix, rowoff += spt, xp += sxy) { double xj = *xp + m_x0; double* phip = phi + rowoff; for (int iy = 0; iy < my; ++iy, phip += rowlen) *phip = xj; } // Do y dependence const double* yp = y; double* phip = phi; double* thetap = theta; int* statp = stat; for (int iy = 0; iy < ny; ++iy, yp += sxy) { double yj = *yp + m_y0; double yj2 = yj*yj; for (int ix = 0; ix < mx; ++ix, phip += spt, thetap += spt) { double xj = *phip; double r = sqrt(xj*xj + yj2); if (r == 0.0) *phip = 0.0; else *phip = atan2d(xj, -yj); *thetap = 90.0 - 2.0*atand(r*m_w[1]); *(statp++) = 0; } } // Return return; }
/* ** The GSM to SM transformation is given by the matrix ** T4 = <- mu,Y> ** ** where the rotation angle mu is the dipole tilt. This transformation ** is a rotation in the GSM XZ plane from the GSM Z axis to the ** geomagnetic dipole axis. */ void mat_T4(const double et, Mat mat) { Vec Qe; double mu; vec_Qe(et, Qe); mu = atan2d(Qe[0], sqrt(Qe[1]*Qe[1] + Qe[2]*Qe[2])); hapgood_matrix(-mu, Y, mat); }
/* ** The GSE to GSM transformation is given by the matrix ** ** T3 = <-psi,X> ** ** where the rotation angle psi is the the GSE-GSM angle. This ** transformation is a rotation in the GSE YZ plane from the GSE Z axis ** to the GSM Z axis. */ void mat_T3(const double et, Mat mat) { Vec Qe; double psi; vec_Qe(et, Qe); psi = atan2d(Qe[1], Qe[2]); hapgood_matrix(-psi, X, mat); }
static void astro_sun_RA_dec(double d, double *RA, double *dec, double *r) { double lon, obl_ecl, x, y, z; /* Compute Sun's ecliptical coordinates */ astro_sunpos(d, &lon, r); /* Compute ecliptic rectangular coordinates (z=0) */ x = *r * cosd(lon); y = *r * sind(lon); /* Compute obliquity of ecliptic (inclination of Earth's axis) */ obl_ecl = 23.4393 - 3.563E-7 * d; /* Convert to equatorial rectangular coordinates - x is unchanged */ z = y * sind(obl_ecl); y = y * cosd(obl_ecl); /* Convert to spherical coordinates */ *RA = atan2d(y, x); *dec = atan2d(z, sqrt(x*x + y*y)); }
void geocnvrt(double gdlat,double gdlon, double xal,double xel,double *ral,double *rel) { double kxg,kyg,kzg,kxr,kyr,kzr; double rrad,rlat,rlon,del; kxg=cosd(xel)*sind(xal); kyg=cosd(xel)*cosd(xal); kzg=sind(xel); geodtgc(1,&gdlat,&gdlon,&rrad,&rlat,&rlon,&del); kxr=kxg; kyr=kyg*cosd(del)+kzg*sind(del); kzr=-kyg*sind(del)+kzg*cosd(del); *ral=atan2d(kxr,kyr); *rel=atand(kzr/sqrt((kxr*kxr)+(kyr*kyr))); }
int RPosInvMag(int bm,int rn,int year,struct RadarSite *hdw,double frang, double rsep,double rx,double height, double *mlat,double *mlon,double *azm) { double flat,flon,frho; double fx,fy,fz; double gx,gy,gz; double glat,glon; double gdlat,gdlon,gdrho; double gbx,gby,gbz; double ghx,ghy,ghz; double bx,by,bz,b; double dummy,elv,azc; double tmp_ht; double xlat,xlon,nlat,nlon; int s; gdlat=hdw->geolat; gdlon=hdw->geolon; if (rx==0) rx=hdw->recrise; RPosGeo(1,bm,rn,hdw,frang,rsep,rx, height,&frho,&flat,&flon); sphtocar(frho,flat,flon,&fx,&fy,&fz); geodtgc(1,&gdlat,&gdlon,&gdrho,&glat,&glon,&dummy); sphtocar(gdrho,glat,glon,&gbx,&gby,&gbz); gx=fx-gbx; gy=fy-gby; gz=fz-gbz; norm_vec(&gx,&gy,&gz); glbthor(1,flat,flon,&gx,&gy,&gz,&ghx,&ghy,&ghz); norm_vec(&ghx,&ghy,&ghz); s=IGRFMagCmp(year,frho,flat,flon,&bx,&by,&bz,&b); if (s==-1) return -1; norm_vec(&bx,&by,&bz); ghz=-(bx*ghx+by*ghy)/bz; norm_vec(&ghx,&ghy,&ghz); elv=atan2d(ghz,sqrt(ghx*ghx+ghy*ghy)); azc=atan2d(ghy,-ghx); geodtgc(-1,&gdlat,&gdlon,&gdrho,&flat,&flon,&dummy); tmp_ht=frho-gdrho; AACGMConvert(flat,flon,tmp_ht,mlat,mlon,&dummy,0); fldpnt_sph(frho,flat,flon,azc,rsep,&xlat,&xlon); s=AACGMConvert(xlat,xlon,tmp_ht,&nlat,&nlon,&dummy,0); if (s==-1) return -1; if ((nlon-*mlon) > 180) nlon=nlon-360; if ((nlon-*mlon) < -180) nlon=nlon+360; fldpnt_azm(*mlat,*mlon,nlat,nlon,azm); return 0; }
int sphx2s( const double eul[5], int nphi, int ntheta, int spt, int sll, const double phi[], const double theta[], double lng[], double lat[]) { int mphi, mtheta, rowlen, rowoff; double cosphi, costhe, costhe3, costhe4, dlng, dphi, sinphi, sinthe, sinthe3, sinthe4, x, y, z; register int iphi, itheta; register const double *phip, *thetap; register double *latp, *lngp; if (ntheta > 0) { mphi = nphi; mtheta = ntheta; } else { mphi = 1; mtheta = 1; ntheta = nphi; } /* Check for a simple change in origin of longitude. */ if (eul[4] == 0.0) { if (eul[1] == 0.0) { dlng = fmod(eul[0] + 180.0 - eul[2], 360.0); lngp = lng; latp = lat; phip = phi; thetap = theta; for (itheta = 0; itheta < ntheta; itheta++) { for (iphi = 0; iphi < mphi; iphi++) { *lngp = *phip + dlng; *latp = *thetap; /* Normalize the celestial longitude. */ if (eul[0] >= 0.0) { if (*lngp < 0.0) *lngp += 360.0; } else { if (*lngp > 0.0) *lngp -= 360.0; } if (*lngp > 360.0) { *lngp -= 360.0; } else if (*lngp < -360.0) { *lngp += 360.0; } lngp += sll; latp += sll; phip += spt; thetap += spt; } } } else { dlng = fmod(eul[0] + eul[2], 360.0); lngp = lng; latp = lat; phip = phi; thetap = theta; for (itheta = 0; itheta < ntheta; itheta++) { for (iphi = 0; iphi < mphi; iphi++) { *lngp = dlng - *phip; *latp = -(*thetap); /* Normalize the celestial longitude. */ if (eul[0] >= 0.0) { if (*lngp < 0.0) *lngp += 360.0; } else { if (*lngp > 0.0) *lngp -= 360.0; } if (*lngp > 360.0) { *lngp -= 360.0; } else if (*lngp < -360.0) { *lngp += 360.0; } lngp += sll; latp += sll; phip += spt; thetap += spt; } } } return 0; } /* Do phi dependency. */ phip = phi; rowoff = 0; rowlen = nphi*sll; for (iphi = 0; iphi < nphi; iphi++, rowoff += sll, phip += spt) { dphi = *phip - eul[2]; lngp = lng + rowoff; for (itheta = 0; itheta < mtheta; itheta++) { *lngp = dphi; lngp += rowlen; } } /* Do theta dependency. */ thetap = theta; lngp = lng; latp = lat; for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) { sincosd(*thetap, &sinthe, &costhe); costhe3 = costhe*eul[3]; costhe4 = costhe*eul[4]; sinthe3 = sinthe*eul[3]; sinthe4 = sinthe*eul[4]; for (iphi = 0; iphi < mphi; iphi++, lngp += sll, latp += sll) { dphi = *lngp; sincosd(dphi, &sinphi, &cosphi); /* Compute the celestial longitude. */ x = sinthe4 - costhe3*cosphi; if (fabs(x) < tol) { /* Rearrange formula to reduce roundoff errors. */ x = -cosd(*thetap + eul[1]) + costhe3*(1.0 - cosphi); } y = -costhe*sinphi; if (x != 0.0 || y != 0.0) { dlng = atan2d(y, x); } else { /* Change of origin of longitude. */ if (eul[1] < 90.0) { dlng = dphi + 180.0; } else { dlng = -dphi; } } *lngp = eul[0] + dlng; /* Normalize the celestial longitude. */ if (eul[0] >= 0.0) { if (*lngp < 0.0) *lngp += 360.0; } else { if (*lngp > 0.0) *lngp -= 360.0; } if (*lngp > 360.0) { *lngp -= 360.0; } else if (*lngp < -360.0) { *lngp += 360.0; } /* Compute the celestial latitude. */ if (fmod(dphi,180.0) == 0.0) { *latp = *thetap + cosphi*eul[1]; if (*latp > 90.0) *latp = 180.0 - *latp; if (*latp < -90.0) *latp = -180.0 - *latp; } else { z = sinthe3 + costhe4*cosphi; if (fabs(z) > 0.99) { /* Use an alternative formula for greater accuracy. */ *latp = copysign(acosd(sqrt(x*x+y*y)), z); } else { *latp = asind(z); } } } } return 0; }
int sphs2x( const double eul[5], int nlng, int nlat, int sll, int spt, const double lng[], const double lat[], double phi[], double theta[]) { int mlat, mlng, rowlen, rowoff; double coslat, coslat3, coslat4, coslng, dlng, dphi, sinlat, sinlat3, sinlat4, sinlng, x, y, z; register int ilat, ilng; register const double *latp, *lngp; register double *phip, *thetap; if (nlat > 0) { mlng = nlng; mlat = nlat; } else { mlng = 1; mlat = 1; nlat = nlng; } /* Check for a simple change in origin of longitude. */ if (eul[4] == 0.0) { if (eul[1] == 0.0) { dphi = fmod(eul[2] - 180.0 - eul[0], 360.0); lngp = lng; latp = lat; phip = phi; thetap = theta; for (ilat = 0; ilat < nlat; ilat++) { for (ilng = 0; ilng < mlng; ilng++) { *phip = fmod(*lngp + dphi, 360.0); *thetap = *latp; /* Normalize the native longitude. */ if (*phip > 180.0) { *phip -= 360.0; } else if (*phip < -180.0) { *phip += 360.0; } phip += spt; thetap += spt; lngp += sll; latp += sll; } } } else { dphi = fmod(eul[2] + eul[0], 360.0); lngp = lng; latp = lat; phip = phi; thetap = theta; for (ilat = 0; ilat < nlat; ilat++) { for (ilng = 0; ilng < mlng; ilng++) { *phip = fmod(dphi - *lngp, 360.0); *thetap = -(*latp); /* Normalize the native longitude. */ if (*phip > 180.0) { *phip -= 360.0; } else if (*phip < -180.0) { *phip += 360.0; } phip += spt; thetap += spt; lngp += sll; latp += sll; } } } return 0; } /* Do lng dependency. */ lngp = lng; rowoff = 0; rowlen = nlng*spt; for (ilng = 0; ilng < nlng; ilng++, rowoff += spt, lngp += sll) { dlng = *lngp - eul[0]; phip = phi + rowoff; thetap = theta; for (ilat = 0; ilat < mlat; ilat++) { *phip = dlng; phip += rowlen; } } /* Do lat dependency. */ latp = lat; phip = phi; thetap = theta; for (ilat = 0; ilat < nlat; ilat++, latp += sll) { sincosd(*latp, &sinlat, &coslat); coslat3 = coslat*eul[3]; coslat4 = coslat*eul[4]; sinlat3 = sinlat*eul[3]; sinlat4 = sinlat*eul[4]; for (ilng = 0; ilng < mlng; ilng++, phip += spt, thetap += spt) { dlng = *phip; sincosd(dlng, &sinlng, &coslng); /* Compute the native longitude. */ x = sinlat4 - coslat3*coslng; if (fabs(x) < tol) { /* Rearrange formula to reduce roundoff errors. */ x = -cosd(*latp+eul[1]) + coslat3*(1.0 - coslng); } y = -coslat*sinlng; if (x != 0.0 || y != 0.0) { dphi = atan2d(y, x); } else { /* Change of origin of longitude. */ if (eul[1] < 90.0) { dphi = dlng - 180.0; } else { dphi = -dlng; } } *phip = fmod(eul[2] + dphi, 360.0); /* Normalize the native longitude. */ if (*phip > 180.0) { *phip -= 360.0; } else if (*phip < -180.0) { *phip += 360.0; } /* Compute the native latitude. */ if (fmod(dlng,180.0) == 0.0) { *thetap = *latp + coslng*eul[1]; if (*thetap > 90.0) *thetap = 180.0 - *thetap; if (*thetap < -90.0) *thetap = -180.0 - *thetap; } else { z = sinlat3 + coslat4*coslng; if (fabs(z) > 0.99) { /* Use an alternative formula for greater accuracy. */ *thetap = copysign(acosd(sqrt(x*x+y*y)), z); } else { *thetap = asind(z); } } } } return 0; }