我正在写一些必要的方法来计算太阳在特定点上的路径。我已经使用两个不同的来源编写了代码,以进行计算,但都没有产生期望的结果。来源是:http://www.pveducation.org/pvcdrom/properties-of-sunlight/suns-position
http://www.esrl.noaa.gov/gmd/grad/solcalc/solareqns.PDF

注意:弧分的度数是度* 60分钟。

  • localSolartime:我将经度转换为“分钟”,从localStandardTimeMeridian方法派生的本地标准时间子午线(lstm)返回的值以“分钟”为单位,而equationOfTime也以“分钟”为单位返回。使用来自体育的方程式,我计算了时间校正,该校正考虑了给定时区内的较小时间变化。当我将此结果和localTime(以分钟为单位)应用于本地太阳时间(lst)公式时,结果为676.515(此刻),这对我来说没有任何意义。据我了解,本地的太阳时间代表相对于太阳的时间,当它在天空中的最高点时,在本地被视为太阳正午。 676.515没有任何意义。有谁知道可能是什么原因造成的。
  • HourAngle:我希望一旦修复了localSolarTime方法,就无需对此进行更正。

  • 我选择华盛顿特区作为纬度和经度。 Zenith和Azimuth读数均应为正值,并且对于我现在的区域,分别为66和201。
    public class PathOfSun {
        static LocalTime localTime = LocalTime.now();
        static double dcLat = 38.83;
        static double dcLong =  -77.02;
        static DecimalFormat df = new DecimalFormat("#.0");
    
        public static void main(String [] args) {
            int day = dayOfYear();
            double equationOfTime = equationOfTime(day);
            double lstm = localTimeMeridian();
            double lst = localSolarTime(equationOfTime, dcLong, lstm);
            double declination = declination(day);
            double hourAngle = hourAngle(lst);
    
            double zenith = zenith(dcLat, declination, hourAngle);
            double azimuth = azimuth(dcLong, declination, zenith, hourAngle);
    
        }
    
        //Longitude of timezone meridian
        public static double localTimeMeridian() {
            TimeZone gmt = TimeZone.getTimeZone("GMT");
            TimeZone est = TimeZone.getTimeZone("EST");
            int td = gmt.getRawOffset() - est.getRawOffset();
            double localStandardTimeMeridian = 15 * (td/(1000*60*60)); //convert td to hours
            //System.out.println("Local Time Meridian: " + localStandardTimeMeridian);
            return localStandardTimeMeridian;
        }
    
        //Get the number of days since Jan. 1
        public static int dayOfYear() {
            Calendar localCalendar = Calendar.getInstance(TimeZone.getDefault());
            int dayOfYear = localCalendar.get(Calendar.DAY_OF_YEAR);
            //System.out.println("Day: " + dayOfYear);
            return dayOfYear;
        }
    
        //Emperical equation to correct the eccentricity of Earth's orbit and axial tilt
        public static double equationOfTime (double day) {
            double d =(360.0/365.0)*(day - 81);
            d = Math.toRadians(d);
            double equationTime = 9.87*sin(2*d)-7.53*cos(d)-1.54*sin(d);
            //System.out.println("Equation Of Time: " + equationTime);
            return equationTime;
        }
        //The angle between the equator and a line drawn from the center of the Sun(degrees)
        public static double declination(int dayOfYear) {
            double declination = 23.5*sin((Math.toRadians(360.0/365.0))*(dayOfYear - 81));
            //System.out.println("Declination: " + df.format(declination));
            return declination;
        }
    
        //Add the number of minutes past midnight localtime//
        public static double hourAngle(double localSolarTime) {
            double hourAngle = 15 * (localSolarTime - 13);
            System.out.println("Hour Angle: " + df.format(hourAngle)); //(degrees)
            return hourAngle;
        }
    
        //Account for the variation within timezone - increases accuracy
        public static double localSolarTime(double equationOfTime, double longitude, double lstm) {
            //LocalSolarTime = 4min * (longitude + localStandardTimeMeridian) + equationOfTime
            //Time Correction is time variation within given time zone (minutes)
            //longitude = longitude/60; //convert degrees to arcminutes
            double localStandardTimeMeridian = lstm;
            double timeCorrection = (4 * (longitude + localStandardTimeMeridian) + equationOfTime);
            System.out.println("Time Correction: " + timeCorrection); //(in minutes)
            //localSolarTime represents solar time where noon represents sun's is highest position
            // in sky and the hour angle is 0 -- hour angle is negative in morning, and positive after solar noon.
            double localSolarTime = (localTime.toSecondOfDay() + (timeCorrection*60)); //(seconds)
            localSolarTime = localSolarTime/(60*60);  //convert from seconds to hours
            //Convert double to Time (HH:mm:ss) for console output
            int hours = (int) Math.floor(localSolarTime);
            int minutes = (int) ((localSolarTime - hours) * 60);
            //-1 for the daylight savings
            Time solarTime = new Time((hours-1), minutes, 0);
            System.out.println("Local Solar Time: " + solarTime); //hours
    
            return localSolarTime;
        }
    
        public static double azimuth(double lat, double declination, double zenith, double hourAngle) {
            double azimuthDegree = 0;
            double elevation = 90 - zenith;
            elevation = Math.toRadians(elevation);
            zenith = Math.toRadians(zenith);
            lat = Math.toRadians(lat);
            declination = Math.toRadians(declination);
            hourAngle = Math.round(hourAngle);
            hourAngle = Math.toRadians(hourAngle);
    
            //double azimuthRadian = -sin(hourAngle)*cos(declination) / cos(elevation);
            double azimuthRadian = ((sin(declination)*cos(lat)) - (cos(hourAngle)*cos(declination)*
                    sin(lat)))/cos(elevation);
    
            //Account for time quadrants
            Calendar cal = Calendar.getInstance();
            int hour = cal.get(Calendar.HOUR_OF_DAY);
            if(hour > 0 && hour < 6) {
            azimuthDegree =  Math.toDegrees(acos(azimuthRadian));
            }
            else if(hour >= 6 && hour < 12) {
                azimuthDegree = Math.toDegrees(acos(azimuthRadian));
                azimuthDegree = 180 - azimuthDegree;
            } else if (hour >= 12 && hour < 18) {
                azimuthDegree = Math.toDegrees(acos(azimuthRadian));
                azimuthDegree = azimuthDegree - 180;
            } else if (hour >= 18 && hour < 24) {
                azimuthDegree = Math.toDegrees(acos(azimuthRadian));
                azimuthDegree = 360 - azimuthDegree;
            }
    
            System.out.println("Azimuth: " + df.format(azimuthDegree));
            return azimuthDegree;
        }
    
        public static double zenith(double lat, double declination, double hourAngle) {
            lat = Math.toRadians(lat);
            declination = Math.toRadians(declination);
            hourAngle = Math.round(hourAngle);
            hourAngle = Math.toRadians(hourAngle);
            //Solar Zenith Angle
            double zenith = Math.toDegrees(acos(sin(lat)*sin(declination) + (cos(lat)*cos(declination)*cos(hourAngle))));
            //Solar Elevation Angle
            double elevation = Math.toDegrees(asin(sin(lat)*sin(declination) + (cos(lat)*cos(declination)*cos(hourAngle))));
            System.out.println("Elevation: " + df.format(elevation));
            System.out.println("Zenith: " + df.format(zenith));
            return zenith;
        }
    }
    

    重申一下,本地时间子午线是完全正确的,并且时间和纬度等式是准确的,但不是精确的。
    ----更新输出----


    - - -更新 - - -
    使用散点图显示全天太阳的仰角/方位角。我仍然无法确定方位角的输出。长期以来它是正确的,但随后会从增加变为减少(〜270-> 0)。最终确定正确的输出后,我将确保更新代码。

    最佳答案

    您将经度作为度数传递给localSolarTime(),然后将其除以60,并加上一条注释,声称这是为了转换为弧度分钟。这是错误的;您以后的计算需要度数,即使您需要弧度的分钟数,也要乘以60,而不是除以。

    这种错误的划分会导致经度为-1.3°,并且当您发现本地子午线与位置之间的角度时,您会得到一个大角度(大约75°)。它应该是一个小角度,通常为±7.5°。大角度会导致较大的时间校正,并且会丢掉所有内容。

    更新:在azimuth()方法的更新版本中,象限选择应基于太阳的时角或等效地基于本地的太阳时间,而不是标准的挂钟时间。并且,在所有计算中使用的小时角不应四舍五入。与其测试四个不同的象限,该方法可能看起来像这样:

    public static double azimuth(double lat, double declination, double zenith, double hourAngle)
    {
      double elevation = Math.toRadians(90 - zenith);
      lat = Math.toRadians(lat);
      declination = Math.toRadians(declination);
      hourAngle = Math.toRadians(hourAngle);
      double azimuthRadian = acos(((sin(declination) * cos(lat)) - (cos(hourAngle) * cos(declination) * sin(lat))) / cos(elevation));
      double azimuthDegree = Math.toDegrees(azimuthRadian);
      if (hourAngle > 0)
        azimuthDegree = 360 - azimuthDegree;
      System.out.println("Azimuth: " + df.format(azimuthDegree));
      return azimuthDegree;
    }
    

    最后,您将dcLong作为lat方法的azimuth()参数传入。这应该是dcLat

    我建议整个内部都使用弧度,并且仅在输入和输出之间进行度数转换。这将有助于防止错误,并减少舍入错误和不必要的困惑。

    关于java - 太阳路径的计算,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30038320/

    10-11 10:49