001/* 002 * Shredzone Commons - suncalc 003 * 004 * Copyright (C) 2017 Richard "Shred" Körber 005 * http://commons.shredzone.org 006 * 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 013 */ 014package org.shredzone.commons.suncalc; 015 016import static java.lang.Math.toDegrees; 017import static java.lang.Math.toRadians; 018import static org.shredzone.commons.suncalc.util.ExtendedMath.equatorialToHorizontal; 019import static org.shredzone.commons.suncalc.util.ExtendedMath.refraction; 020 021import org.shredzone.commons.suncalc.param.Builder; 022import org.shredzone.commons.suncalc.param.GenericParameter; 023import org.shredzone.commons.suncalc.param.LocationParameter; 024import org.shredzone.commons.suncalc.param.TimeParameter; 025import org.shredzone.commons.suncalc.util.BaseBuilder; 026import org.shredzone.commons.suncalc.util.JulianDate; 027import org.shredzone.commons.suncalc.util.Sun; 028import org.shredzone.commons.suncalc.util.Vector; 029 030/** 031 * Calculates the position of the sun. 032 */ 033public class SunPosition { 034 035 private final double azimuth; 036 private final double altitude; 037 private final double trueAltitude; 038 private final double distance; 039 040 private SunPosition(double azimuth, double altitude, double trueAltitude, double distance) { 041 this.azimuth = (toDegrees(azimuth) + 180.0) % 360.0; 042 this.altitude = toDegrees(altitude); 043 this.trueAltitude = toDegrees(trueAltitude); 044 this.distance = distance; 045 } 046 047 /** 048 * Starts the computation of {@link SunPosition}. 049 * 050 * @return {@link Parameters} to set. 051 */ 052 public static Parameters compute() { 053 return new SunPositionBuilder(); 054 } 055 056 /** 057 * Collects all parameters for {@link SunPosition}. 058 */ 059 public interface Parameters extends 060 GenericParameter<Parameters>, 061 LocationParameter<Parameters>, 062 TimeParameter<Parameters>, 063 Builder<SunPosition> { 064 } 065 066 /** 067 * Builder for {@link SunPosition}. Performs the computations based on the parameters, 068 * and creates a {@link SunPosition} object that holds the result. 069 */ 070 private static class SunPositionBuilder extends BaseBuilder<Parameters> implements Parameters { 071 @Override 072 public SunPosition execute() { 073 JulianDate t = getJulianDate(); 074 075 double lw = toRadians(-getLongitude()); 076 double phi = toRadians(getLatitude()); 077 Vector c = Sun.position(t); 078 double h = t.getGreenwichMeanSiderealTime() - lw - c.getPhi(); 079 Vector horizontal = equatorialToHorizontal(h, c.getTheta(), c.getR(), phi); 080 double hRef = refraction(horizontal.getTheta()); 081 082 return new SunPosition(horizontal.getPhi(), 083 horizontal.getTheta() + hRef, 084 horizontal.getTheta(), 085 horizontal.getR()); 086 } 087 } 088 089 /** 090 * The visible sun altitude above the horizon, in degrees. 091 * <p> 092 * {@code 0.0} means the sun's center is at the horizon, {@code 90.0} at the zenith 093 * (straight over your head). Atmospheric refraction is taken into account. 094 * 095 * @see #getTrueAltitude() 096 */ 097 public double getAltitude() { 098 return altitude; 099 } 100 101 /** 102 * The true sun altitude above the horizon, in degrees. 103 * <p> 104 * {@code 0.0} means the sun's center is at the horizon, {@code 90.0} at the zenith 105 * (straight over your head). 106 * 107 * @see #getAltitude() 108 * @since 2.3 109 */ 110 public double getTrueAltitude() { 111 return trueAltitude; 112 } 113 114 /** 115 * Sun azimuth, in degrees, north-based. 116 * <p> 117 * This is the direction along the horizon, measured from north to east. For example, 118 * {@code 0.0} means north, {@code 135.0} means southeast, {@code 270.0} means west. 119 */ 120 public double getAzimuth() { 121 return azimuth; 122 } 123 124 /** 125 * Sun's distance, in kilometers. 126 */ 127 public double getDistance() { 128 return distance; 129 } 130 131 @Override 132 public String toString() { 133 StringBuilder sb = new StringBuilder(); 134 sb.append("SunPosition[azimuth=").append(azimuth); 135 sb.append("°, altitude=").append(altitude); 136 sb.append("°, true altitude=").append(trueAltitude); 137 sb.append("°, distance=").append(distance).append(" km]"); 138 return sb.toString(); 139 } 140 141}