// this is not used effectovely // it is just try to have some alternative function for calculation sun position // but it needs to be fixed, because // it calculates correct ecliptical coordinates, but when transforming // into horizontal coordinates (azimut, elevation) it will do something wrong public static GCHorizontalCoords sunPosition(int year, int month, int day, int hour, int min, int sec, double lat, double longi) { double twopi = GCMath.PI2; double deg2rad = GCMath.PI2 / 180; int[] month_days = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 }; for (int y2 = 0; y2 < month; y2++) { day += month_days[y2]; } if ((year % 4 == 0) && ((year % 400 == 0) || (year % 100 != 0)) && (day >= 60) && !(month == 2 & day == 60)) { day++; } //# Get Julian date - 2400000 double hourd = hour + min / 60.0 + sec / 3600.0; // hour plus fraction double delta = year - 1949; double leap = Math.Floor(delta / 4); // former leapyears double jd = 32916.5 + delta * 365 + leap + day + hourd / 24.0; // The input to the Atronomer's almanach is the difference between // the Julian date and JD 2451545.0 (noon, 1 January 2000) double time = jd - 51545.0; // Ecliptic coordinates // Mean longitude double mnlong = GCMath.putIn360(280.460 + .9856474 * time); // Mean anomaly double mnanom = GCMath.putIn360(357.528 + .9856003 * time); //mnanom <- mnanom * deg2rad // Ecliptic longitude and obliquity of ecliptic double eclong = mnlong + 1.915 * GCMath.sinDeg(mnanom) + 0.020 * GCMath.sinDeg(2 * mnanom); eclong = GCMath.putIn360(eclong); double oblqec = 23.439 - 0.0000004 * time; //-- eclong <- eclong * deg2rad //-- oblqec <- oblqec * deg2rad // Celestial coordinates // Right ascension and declination double num = GCMath.cosDeg(oblqec) * GCMath.sinDeg(eclong); double den = GCMath.cosDeg(eclong); double ra = GCMath.arcTan2Deg(num, den); while (ra < 0) { ra += 180; } //-- ra[den < 0] <- ra[den < 0] + pi if (den >= 0 && num < 0) { ra += 360; } double dec = GCMath.arcSinDeg(GCMath.sinDeg(oblqec) * GCMath.sinDeg(eclong)); // Local coordinates // Greenwich mean sidereal time double gmst = 6.697375 + .0657098242 * time + hourd; gmst = GCMath.putIn24(gmst); // Local mean sidereal time double lmst = gmst + longi / 15.0; lmst = GCMath.putIn24(lmst); lmst = lmst * 15.0; // Hour angle double ha = lmst - ra; ha = GCMath.putIn180(ha); // Azimuth and elevation double el = GCMath.arcSinDeg(GCMath.sinDeg(dec) * GCMath.sinDeg(lat) + GCMath.cosDeg(dec) * GCMath.cosDeg(lat) * GCMath.cosDeg(ha)); double az = GCMath.arcSinDeg(-GCMath.cosDeg(dec) * GCMath.sinDeg(ha) / GCMath.cosDeg(el)); //# ----------------------------------------------- //# New code //# Solar zenith angle double zenithAngle = GCMath.arccosDeg(GCMath.sinDeg(lat) * GCMath.sinDeg(dec) + GCMath.cosDeg(lat) * GCMath.cosDeg(dec) * GCMath.cosDeg(ha)); //# Solar azimuth az = GCMath.arccosDeg(((GCMath.sinDeg(lat) * GCMath.cosDeg(zenithAngle)) - GCMath.sinDeg(dec)) / (GCMath.cosDeg(lat) * GCMath.sinDeg(zenithAngle))); //# ----------------------------------------------- //# Azimuth and elevation el = GCMath.arcSinDeg(GCMath.sinDeg(dec) * GCMath.sinDeg(lat) + GCMath.cosDeg(dec) * GCMath.cosDeg(lat) * GCMath.cosDeg(ha)); //# ----------------------------------------------- //# New code if (ha > 0) { az += 180; } else { az = 540 - az; } az = GCMath.putIn360(az); // For logic and names, see Spencer, J.W. 1989. Solar Energy. 42(4):353 //cosAzPos <- (0 <= sin(dec) - sin(el) * sin(lat)) //sinAzNeg <- (sin(az) < 0) //az[cosAzPos & sinAzNeg] <- az[cosAzPos & sinAzNeg] + twopi //az[!cosAzPos] <- pi - az[!cosAzPos] /* * if (0 < GCMath.sinDeg(dec) - GCMath.sinDeg(el) * GCMath.sinDeg(lat)) * { * if(GCMath.sinDeg(az) < 0) * { * az = az + 360; * } * } * else * { * az = 180 - az; * } */ //el <- el / deg2rad //az <- az / deg2rad //lat <- lat / deg2rad GCHorizontalCoords coords; coords.azimut = az; coords.elevation = el; return(coords); }