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; }
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; }
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 }
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); }
/* 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; }