/* Copyright 2000 Charles G. Wright * This software may be distributed under the terms of the * GNU General Public License. * * $Id: SOLlocation.java,v 1.1 2000-06-15 10:15:00-05 chuckles Exp chuckles $ */ import java.math.*; import java.util.*; /**

This class represents a location on the surface of planet Earth. * Its class variables define a position on Earth and its time zone. * Methods for this class deal with solar time and the position * of the sun in the sky at this location.

*

At this location can be defined one or more orientations, * defined by the SOLorientation object, of surfaces exposed to the sun. * These are all contained the linked list "orientations" attached to * this location object. */ public class SOLlocation implements CWmonitorable{ /** Values accessible using the getValue() method.*/ public static final String[] fields = {"Solar Altitude", "Solar Azimuth"}; public static final int[] field_types = {UnitConverter.NOTHING, UnitConverter.NOTHING}; // Constant: private static final double FEET_PER_METER = 3.2808389850; // locale /** Latitude of the surface, in degrees. */ public double latitude; /** Longitude of the surface, in degrees. */ public double longitude; /** Longitude of the standard time zone in degrees. */ public int time_zone; /** Elevation at this location, in meters. */ public double elevation; /** Name of this location. */ public String name; /** List of orientations associated with this location.*/ public Vector orientations; public TMYdata tmystuff; //-------------------- Constructor ----------------------------- /**

Create an SOLlocation object, which represents a location on the * surface of planet Earth. The parameters defining the location * are its:

*/ public SOLlocation(double latitude, double longitude, int time_zone, double elevation, String name){ this.latitude = latitude; this.longitude = longitude; this.time_zone = time_zone; this.elevation = elevation; this.name = name; orientations = new Vector(); CWmonitoredElements.addElements(this); } //------------------- Methods ------------------------------------ //---- utility methods ------ static public double toRadians(double angle){ return(angle * 0.0174532925); } static public double toDegrees(double angle){ return(angle / 0.0174532925); } //----------------------------- /** Returns the latitude of the location station. */ public double getLatitude(){ return latitude; } /** Returns the longitude of the location. */ public double getLongitude(){ return longitude; } /** Returns the time zone of the data location, in degrees * (longitude of standard meridian). */ public int getTimeZone(){ return time_zone; } /** Returns the elevation of the location. */ public double getElevation(){ return (double)elevation; } public String getName(){ return(name); } /** Returns the list of monitorable fields. Part of the CWmonitorable * interface.*/ public String[] getFields(){ return fields; } /** Returns the list of types of the monitorable fields. Part of the CWmonitorable * interface. Used for unit conversions. Types are defined in class UnitConverter.*/ public int[] getFieldTypes(){ return(field_types); } //---------------------- Solar Declination ------------------------ /** Returns solar declination, in degrees (angle between * ecliptic and equator), given a day number. */ public double getDeclination(int daynum){ return 23.45 * Math.sin(toRadians((360 * (284 + daynum))/ 365)); } //------------------ Equation of time ----------------------------- /** Returns local solar time, in seconds, given the day number (in the year) and the * local standard time (in seconds). */ public int getSolarTime(int daynum, int standard_time){ // convert daynum to radians int solar_time; double D = 2 * Math.PI * daynum / 365; double eot = -1 * ((445 * Math.sin(D)) - (15.4 * Math.cos(D)) + (554 * Math.sin(2 * D)) + (217.0 * Math.cos(2 * D))); solar_time = (int)(standard_time + (240.0 * (time_zone - longitude)) + eot); //System.out.println("[getSolarTime]: standard_time = " + standard_time + "solar_time = " + solar_time); return solar_time; } //------------------------- HMS to Sec ---------------------------- /** Returns time of day in seconds. Inputs are the hour of the day (0-23), * the minute of the hour (0-59), and second of the minute (0-59). */ public int timeInSeconds(int hour, int minute, int second){ return (((hour) * 3600) + ((minute) * 60) + (second)); } //------------------------ Hour Angle ----------------------------- /** Returns Hour Angle, in degrees. Input is the local solar time, in seconds. */ public double getHourAngle(int solar_time){ return(15.0 * ((solar_time / 3600.0) - 12.0)); } //-------------------------- Solar Altitude --------------------- /** Returns solar altitude, in degrees, given solar time and declination. */ public double getSolarAltitude(double decl, int solar_time){ double hourAngle = getHourAngle(solar_time); // Calculate sine of altitude // System.out.println("[getSolarAltitude]: decl="+decl+" hourAngle="+hourAngle); double sinAlt = (Math.cos(toRadians(latitude)) * Math.cos(toRadians(decl)) * Math.cos(toRadians(hourAngle))) + (Math.sin(toRadians(latitude)) * Math.sin(toRadians(decl))); double alt = Math.max(0.0, toDegrees(Math.asin(sinAlt))); return alt; } /** Returns solar altitude, in degrees, given solar time and day number. */ public double getSolarAltitude(int daynum, int solar_time){ double decl = getDeclination(daynum); return(getSolarAltitude(decl, solar_time)); } //---------------------------- Solar Azimuth ------------------------ /** Returns solar azimuth, in degrees, given solar time and declination. */ public double getSolarAzimuth(double decl, int solar_time){ double alt = getSolarAltitude(decl, solar_time); // Calculate cosine of solar azimuth double cosAzi = ((Math.sin(toRadians(alt)) * Math.sin(toRadians(latitude))) - Math.sin(toRadians(decl))) / (Math.cos(toRadians(alt)) * Math.cos(toRadians(latitude))); double result = toDegrees(Math.acos(cosAzi)); if (solar_time < 43200) result *= -1.0; // System.out.println("[getSolarAzimuth]: decl="+decl+" alt="+alt+" latitude="+latitude+" azi="+result+" solar_time="+solar_time); return(result); } /** Returns solar azimuth, in degrees, given solar time and day number. */ public double getSolarAzimuth(int daynum, int solar_time){ double decl = getDeclination(daynum); return(getSolarAzimuth(decl, solar_time)); } /** Provides access to this classes methods in common getValue() format. */ public double getValue(int month, int day, int hour, int fieldnum) { double result = 0.0; int daynum = TMYdata.dayOfYear(month, day); int solar_time = getSolarTime(daynum, timeInSeconds(hour-1, 0, 0)); switch (fieldnum){ case 0: result = getSolarAltitude(daynum, solar_time); break; case 1: result = getSolarAzimuth(daynum, solar_time); break; } return(result); } }