Example #1
0
void AstroClock::convert(uint32_t timestamp, float ra, float dec, float* alt,
		float* az) {
	float lstd = getLSTd(convertJ2000(timestamp));
	float ha = lstd - ra;
	while (ha < 0)
		ha += 360.0;

	float sinAlt = SIN(dec) * SIN(lat) + COS(dec) * COS(lat) * COS(ha);
	*alt = ASIN(sinAlt);

	float cosA = //
			(SIN(dec) - SIN(*alt) * SIN(lat)) //
			/ (COS(*alt) * COS(lat));

	float a = ACOS(cosA);

	if (SIN(ha) < 0)
		*az = a;
	else
		*az = 360.0 - a;
}
Example #2
0
void divarc(real x1, real y1, real z1,
            real x2, real y2, real z2,
            int div1, int div2, real *xr, real *yr, real *zr)
{

    real xd, yd, zd, dd, d1, d2, s, x, y, z;
    real phi, sphi, cphi;

    xd = y1*z2-y2*z1;
    yd = z1*x2-z2*x1;
    zd = x1*y2-x2*y1;
    dd = sqrt(xd*xd+yd*yd+zd*zd);
    if (dd < DP_TOL)
    {
        ERROR("divarc: rotation axis of length %f", dd);
    }

    d1 = x1*x1+y1*y1+z1*z1;
    if (d1 < 0.5)
    {
        ERROR("divarc: vector 1 of sq.length %f", d1);
    }
    d2 = x2*x2+y2*y2+z2*z2;
    if (d2 < 0.5)
    {
        ERROR("divarc: vector 2 of sq.length %f", d2);
    }

    phi  = ASIN(dd/sqrt(d1*d2));
    phi  = phi*((real)div1)/((real)div2);
    sphi = sin(phi); cphi = cos(phi);
    s    = (x1*xd+y1*yd+z1*zd)/dd;

    x   = xd*s*(1.-cphi)/dd + x1 * cphi + (yd*z1-y1*zd)*sphi/dd;
    y   = yd*s*(1.-cphi)/dd + y1 * cphi + (zd*x1-z1*xd)*sphi/dd;
    z   = zd*s*(1.-cphi)/dd + z1 * cphi + (xd*y1-x1*yd)*sphi/dd;
    dd  = sqrt(x*x+y*y+z*z);
    *xr = x/dd; *yr = y/dd; *zr = z/dd;
}
Example #3
0
static void
sunpos(int inYY, int inMM, int inDD, double UTCOFFSET, int inHOUR, int inMIN,
    int inSEC, double eastlongitude, double latitude, double *L, double *DEC)
{
	int Y;
	double ZJ, D, T, M, epsilon, lambda, alpha, HA, UTHM;

	ZJ = ZJtable[inMM];
	if (inMM <= 2 && isleap(inYY))
		ZJ -= 1.0;

	UTHM = inHOUR + inMIN / FMINSPERHOUR + inSEC / FSECSPERHOUR - UTCOFFSET;
	Y = inYY - 1900;						/*  1 */
	D = floor(365.25 * Y) + ZJ + inDD + UTHM / FHOURSPERDAY;	/*  3 */
	T = D / 36525.0;						/*  4 */
	*L = 279.697 + 36000.769 * T;					/*  5 */
	fixup(L);
	M = 358.476 + 35999.050 * T;					/*  6 */
	fixup(&M);
	epsilon = 23.452 - 0.013 * T;					/*  7 */
	fixup(&epsilon);

	lambda = *L + (1.919 - 0.005 * T) * SIN(M) + 0.020 * SIN(2 * M);/*  8 */
	fixup(&lambda);
	alpha = ATAN(TAN(lambda) * COS(epsilon));			/*  9 */

	/* Alpha should be in the same quadrant as lamba */
	{
		int lssign = sin(D2R(lambda)) < 0 ? -1 : 1;
		int lcsign = cos(D2R(lambda)) < 0 ? -1 : 1;
		while (((sin(D2R(alpha)) < 0) ? -1 : 1) != lssign
		    || ((cos(D2R(alpha)) < 0) ? -1 : 1) != lcsign)
			alpha += 90.0;
	}
	fixup(&alpha);

	*DEC = ASIN(SIN(lambda) * SIN(epsilon));			/* 10 */
	fixup(DEC);
	fixup(&eastlongitude);
	HA = *L - alpha + 180 + 15 * UTHM + eastlongitude;		/* 12 */
	fixup(&HA);
	fixup(&latitude);
#ifdef NOTDEF
	printf("%02d/%02d %02d:%02d:%02d l:%g d:%g h:%g\n",
	    inMM, inDD, inHOUR, inMIN, inSEC, latitude, *DEC, HA);
#endif
	return;

	/*
	 * The following calculations are not used, so to save time
	 * they are not calculated.
	 */
#ifdef NOTDEF
	*ALT = ASIN(SIN(latitude) * SIN(*DEC) +
	    COS(latitude) * COS(*DEC) * COS(HA));			/* 13 */
	fixup(ALT);
	*AZ = ATAN(SIN(HA) /
	    (COS(HA) * SIN(latitude) - TAN(*DEC) * COS(latitude)));	/* 14 */

	if (*ALT > 180)
		*ALT -= 360;
	if (*ALT < -180)
		*ALT += 360;
	printf("a:%g a:%g\n", *ALT, *AZ);
#endif

#ifdef NOTDEF
	printf("Y:\t\t\t     %d\t\t     %d\t\t      %d\n", Y, expY, Y - expY);
	comp("ZJ", ZJ, expZJ);
	comp("UTHM", UTHM, expUTHM);
	comp("D", D, expD);
	comp("T", T, expT);
	comp("L", L, fixup(&expL));
	comp("M", M, fixup(&expM));
	comp("epsilon", epsilon, fixup(&expepsilon));
	comp("lambda", lambda, fixup(&explambda));
	comp("alpha", alpha, fixup(&expalpha));
	comp("DEC", DEC, fixup(&expDEC));
	comp("eastlongitude", eastlongitude, fixup(&expeastlongitude));
	comp("latitude", latitude, fixup(&explatitude));
	comp("HA", HA, fixup(&expHA));
	comp("ALT", ALT, fixup(&expALT));
	comp("AZ", AZ, fixup(&expAZ));
#endif
}
Example #4
0
        DBstatus GE706(
        DBAny  *pstr1,
        DBAny  *pstr2,
        short  *noint,
        DBfloat u1[],
        DBfloat u2[])

/*      Compute intersect between line and arc/circle in 2D.
 *
 *      In: pstr1  => First entity
 *          pstr2  => Second entity
 *          noint  => Requested solution +/-
 *
 *      Out: *noint => Number of solutions
 *           *u1    => Parametric values related to the line
 *           *u2    => Parameteric values related to the arc
 *
 *      (C)microform ab  5/8/85 R. Svedin efter IVAR
 *
 *       12/8/85  Anpassning till v3, J.Kjellander
 *       3/1/86   Tangering, J. Kjellander
 *       15/1/86  Bug lodrät linje, J. Kjellander
 *       13/4/86  Bytt TOL1 mot TOL2, J. Kjellander
 *       19/4/86  Horisontell linje, J. Kjellander
 *       26/11/89 Neg intnr, J. Kjellander
 *       1999-05-10 Rewritten, J.Kjellander
 *
 ******************************************************************!*/

  {
   DBLine *linpek;
   DBArc  *arcpek;
   DBfloat k,k2,p,q,dx,dy;
   DBfloat x1,y1,x2,y2,tt,tmp;
   DBfloat t1[2],t2[2];
   short   i;

/*
***Which is which ?
*/
   if ( pstr1->hed_un.type == LINTYP )
      {
      linpek = (GMLIN *)pstr1;
      arcpek = (GMARC *)pstr2;
      }
   else
      {
      linpek = (GMLIN *)pstr2;
      arcpek = (GMARC *)pstr1;
      }
/*
***Some init.
*/
   dx = linpek->crd2_l.x_gm - linpek->crd1_l.x_gm;
   dy = linpek->crd2_l.y_gm - linpek->crd1_l.y_gm;
/*
***Vertical, horisontal or sloping line ?
*
***Horisontal.
*/
   if ( ABS(dx) > 1000.0*ABS(dy) )
      {
      if ( ABS(linpek->crd1_l.y_gm-arcpek->y_a)-arcpek->r_a  > TOL2 )
         {
         *noint = 0;
         return(0);
         }

      y1 = y2 = linpek->crd1_l.y_gm;

      if ( arcpek->r_a > ABS(linpek->crd1_l.y_gm-arcpek->y_a) )
        {
        x1 = arcpek->x_a + arcpek->r_a*COS(ASIN((linpek->
             crd1_l.y_gm-arcpek->y_a)/arcpek->r_a));
        x2 = 2.0*arcpek->x_a - x1;
        }
      else
        {
        x1 = x2 = arcpek->x_a;
        }

      t1[0] = 1.0 + (x1 - linpek->crd1_l.x_gm) / dx;
      t1[1] = 1.0 + (x2 - linpek->crd1_l.x_gm) / dx;
      }
/*
***Vertical.
*/
   else if ( ABS(dy) > 1000.0*ABS(dx) )
      {
      if ( ABS(linpek->crd1_l.x_gm-arcpek->x_a)-arcpek->r_a  > TOL2 )
         {
         *noint = 0;
         return(0);
         }

      x1 = x2 = linpek->crd1_l.x_gm;

      if ( arcpek->r_a > ABS(linpek->crd1_l.x_gm-arcpek->x_a) )
        {
        y1 = arcpek->y_a + arcpek->r_a*SIN(ACOS((linpek->
             crd1_l.x_gm-arcpek->x_a)/arcpek->r_a));
        y2 = 2.0*arcpek->y_a - y1;
        }
      else
        {
        y1 = y2 = arcpek->y_a;
        }

      t1[0] = 1.0 + (y1 - linpek->crd1_l.y_gm) / dy;
      t1[1] = 1.0 + (y2 - linpek->crd1_l.y_gm) / dy;
      }
/*
***Sloping.
*/
   else
      {
      k  = dy/dx;
      k2 = k*k;

      p = (arcpek->x_a + k2 * linpek->crd1_l.x_gm - k *
          (linpek->crd1_l.y_gm - arcpek->y_a)) / (1.0 + k2);

      q = (arcpek->x_a * arcpek->x_a + k2 * linpek->crd1_l.x_gm *
          linpek->crd1_l.x_gm + 2.0 * k * linpek->crd1_l.x_gm * 
          (arcpek->y_a - linpek->crd1_l.y_gm) + (linpek->crd1_l.y_gm - 
          arcpek->y_a) * (linpek->crd1_l.y_gm - arcpek->y_a) - 
          arcpek->r_a * arcpek->r_a) / (1.0 + k2);
/*
***Do they intersect ?
*/
      if ( (tt=p*p-q) < 0.0 && tt > -TOL2 ) tt = 0.0;
      if ( tt >= 0.0 )
        {
/*
***Yes, analytical solution.
*/
        x1 = p+SQRT(tt);
        y1 = k*(x1-linpek->crd1_l.x_gm) + linpek->crd1_l.y_gm;
        x2 = p-SQRT(tt);     
        y2 = k*(x2-linpek->crd1_l.x_gm) + linpek->crd1_l.y_gm;
        }
/*
***No intersect.
*/
      else
        {
        *noint = 0;
        return(0);
        }
/*
***Compute line parametric values.
*/
      t1[0] = 1.0 + (x1 - linpek->crd1_l.x_gm) / dx;
      t1[1] = 1.0 + (x2 - linpek->crd1_l.x_gm) / dx;
      }
/*
***Compute arc parametric values.
*/
   dx = x1 - arcpek->x_a;
   dy = y1 - arcpek->y_a;
   GE315(arcpek,dx,dy,&t2[0]);

   dx = x2 - arcpek->x_a;
   dy = y2 - arcpek->y_a;
   GE315(arcpek,dx,dy,&t2[1]);
/*
***If *noint > 0, remove intersects outside actual length of entity.
*/
   if ( *noint > 0 )
     {
     *noint = 2;
     if ( t1[0] < 1.0-TOL4 || t1[0] > 2.0+TOL4 ||
          t2[0] < 1.0-TOL4 || t2[0] > 2.0+TOL4 )
       {
       t1[0] = t1[1];
       t2[0] = t2[1];
       *noint = 1;
       }

     if ( t1[1] < 1.0-TOL4 || t1[1] > 2.0+TOL4 ||
          t2[1] < 1.0-TOL4 || t2[1] > 2.0+TOL4 )
       {
       *noint = *noint - 1;
       }
     }
   else *noint = 2;
/*
***Copy remaining solutions to u1 and u2.
*/
   for ( i=0; i<*noint; ++i )
      {
      if ( pstr1->hed_un.type == LINTYP ) 
         {
         u1[i] = t1[i];
         u2[i] = t2[i];
         }
      else
         {
         u1[i] = t2[i];
         u2[i] = t1[i];
         }
      }
/*
***If more than one solution left sort in increasing order
***with respect of the first entity.
*/
   if ( *noint > 1 && u1[0] > u1[1] )
      {
      tmp = u1[0];
      u1[0] = u1[1];
      u1[1] = tmp;

      tmp = u2[0];
      u2[0] = u2[1];
      u2[1] = tmp;
      }

   return(0);
  }
Example #5
0
/* Sun rise-set calculation algorithm.
 * Algorithm description:   http://williams.best.vwh.net/sunrise_sunset_algorithm.htm
 *
 *	Almanac for Computers, 1990
 *	published by Nautical Almanac Office
 *	United States Naval Observatory
 *	Washington, DC 20392
 *
 * Parameters:
 *  yd					- day of the year (1..365)
 *  latitude, longitude	- Sample: 32.27, 34.85 for Netania israel
 *  riseset				- ESUNRISE or ESUNSET
 *
 * Returns: UTC hour of the event (a real number).
*/
double sunriseset( int yd, double latitude, double longitude, ERiseSet riseset )
{
	// 96 degrees    - Calculate Civil twilight time. Used as indication if
	//   it is (usually) bright enough for outdoor activities without additional lighting.
	// 90 degrees 5' - Calculate true Sunrise/Sunset time. Used to check if
	//   the Sun itself is visible above the horizont in ideal conditions.
	const double zenith = 96;

	double sinDec, cosDec, cosH;
	double H, T, UT;

	// Rise / Set
	int op = (riseset==ESUNRISE ? 1:-1);

	// Convert the longitude to hour value and calculate an approximate time
	double lngHour = longitude / 15;

	// if rising time is desired:
	double t = yd + ((12 - (6*op) - lngHour) / 24);

	// Calculate the Sun's mean anomaly
	double M = (0.9856 * t) - 3.289;

	// Calculate the Sun's true longitude
	double L = M + (1.916 * SIN(M)) + (0.020 * SIN(2 * M)) + 282.634;

	// Calculate the Sun's right ascension
	double RA = ATAN(0.91764 * TAN(L));

	// Right ascension value needs to be in the same quadrant as L
	double Lquadrant  = (floor( L/90)) * 90;
	double RAquadrant = (floor(RA/90)) * 90;

	RA = RA + (Lquadrant - RAquadrant);

	// Right ascension value needs to be converted into hours
	RA = RA / 15;

	// Calculate the Sun's declination
	sinDec = 0.39782 * SIN(L);
	cosDec = COS(ASIN(sinDec));

	// Calculate the Sun's local hour angle
	cosH = (COS(zenith) - (sinDec * SIN(latitude))) / (cosDec * COS(latitude));
	if( cosH < -1 || cosH > 1 )
		// The sun never rises or sets on this location (on the specified date)
		return -1;

	// Finish calculating H and convert into hours
	H = 180 + (180 - ACOS(cosH))*op;
	H = H / 15;

	// Calculate local mean time of rising/setting
	T = H + RA - (0.06571 * t) - 6.622;

	// Adjust back to UTC
	UT = T - lngHour;

	// UT potentially needs to be adjusted into the range [0,24) by adding/subtracting 24
	if (UT < 0)   UT += 24;
	if (UT >= 24) UT -= 24;

	return UT;
}