001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/ogcwebservices/wpvs/utils/SunPosition.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 037 package org.deegree.ogcwebservices.wpvs.utils; 038 039 import java.util.Calendar; 040 import java.util.GregorianCalendar; 041 042 /** 043 * 044 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 045 * @author last edited by: $Author: mschneider $ 046 * @version $Revision: 18195 $ $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 047 */ 048 public class SunPosition { 049 050 private int year; 051 private int month; 052 private int day; 053 private int hour; 054 private int minute; 055 private double daysSinceVernalEquinox; 056 057 /** 058 * Constructs a sunposition at the currenttime 059 */ 060 public SunPosition(){ 061 GregorianCalendar calendar = new GregorianCalendar(); 062 this.year = calendar.get( Calendar.YEAR ); 063 this.month = calendar.get( Calendar.MONTH ) + 1; 064 this.day = calendar.get( Calendar.DAY_OF_MONTH ); 065 this.hour = calendar.get( Calendar.HOUR_OF_DAY ); 066 this.minute = calendar.get( Calendar.MINUTE ); 067 daysSinceVernalEquinox = getDaySinceVernalEquinox( ); 068 } 069 /** 070 * Constructs a sunposition with the given Calendar 071 * @param calendar a given Calendar 072 */ 073 public SunPosition( Calendar calendar ){ 074 this( calendar.get( Calendar.YEAR ), 075 calendar.get( Calendar.MONTH ) + 1, 076 calendar.get( Calendar.DAY_OF_MONTH ), 077 calendar.get( Calendar.HOUR_OF_DAY ), 078 calendar.get( Calendar.MINUTE ) ); 079 } 080 081 /** 082 * @param year 083 * @param month 084 * @param day 085 * @param hour 086 * @param minute 087 */ 088 public SunPosition( int year, int month, int day, int hour, int minute ){ 089 this.year = year; 090 this.month = month; 091 if( month <= 0 || month > 12 ) 092 this.month = 1; 093 this.day = day; 094 if( day <= 0 || day > 32 ) 095 this.day = 1; 096 this.hour = hour; 097 if( hour < 0 || hour >=24 ) 098 this.hour = 0; 099 this.minute = minute; 100 if( minute < 0 || minute >= 60 ) 101 this.minute = 0; 102 103 daysSinceVernalEquinox = getDaySinceVernalEquinox( ); 104 } 105 /** 106 * calculates the solar altitude for given latitude, year, month, date, hour 107 * and minute 108 * @param latitude latitude of the the viewers position 109 * @return the solar altitud fo given latitude 110 */ 111 public double getVerticalSunposition( double latitude ) 112 { 113 // Hour Angle (H), 114 // Solar Declination (D), 115 // Latitude (L) 116 // solar altitude (A). 117 // sin(A) = sin(D)*sin(L) + cos(D)*cos(L)*cos(H) 118 double rad23_5 = 0.41015237421866745057706; 119 //double days = getDaySinceVernalEquinox( year, month, date ); 120 double sinD = Math.sin( rad23_5 ) * Math.sin( Math.toRadians( daysSinceVernalEquinox * 360.0 / 365.0 ) ); 121 double cosD = Math.cos( Math.asin( sinD ) ); 122 // the sun hour angle is zero when the object is on the meridian 123 double h = getHorizontalSunPosition( ) - Math.toRadians(180); 124 double radL = Math.toRadians( latitude ); 125 double sinA = sinD * Math.sin(radL) + cosD * Math.cos(radL) * Math.cos(h); 126 127 return Math.asin( sinA ); 128 } 129 130 /** 131 * calculates the horizontal angle of the sun depending only on hour and minute! 132 * @return the horizontal angle 133 */ 134 public double getHorizontalSunPosition( ) 135 { 136 double d = hour + minute/60.0; 137 d = 180 + (( d - 12 ) * 15.0); 138 return Math.toRadians(d); 139 } 140 141 /** 142 * caluculates for a given date the number of days since the last vernal(spring) 143 * equinox. (leap years are considered) 144 */ 145 private double getDaySinceVernalEquinox( ) 146 { 147 //0 for january 148 GregorianCalendar calendar = new GregorianCalendar( year, 2, 21 ); 149 int vEq = calendar.get( Calendar.DAY_OF_YEAR ); 150 calendar = new GregorianCalendar( year, month-1, day-1 ); 151 int doy = calendar.get( Calendar.DAY_OF_YEAR ); 152 if ( doy < vEq ) { 153 doy = ( (calendar.isLeapYear(year)?366:365) - vEq ) + doy; 154 } 155 return doy-vEq; 156 } 157 158 }