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.*; 017import static org.shredzone.commons.suncalc.util.ExtendedMath.equatorialToHorizontal; 018import static org.shredzone.commons.suncalc.util.ExtendedMath.refraction; 019 020import org.shredzone.commons.suncalc.param.Builder; 021import org.shredzone.commons.suncalc.param.GenericParameter; 022import org.shredzone.commons.suncalc.param.LocationParameter; 023import org.shredzone.commons.suncalc.param.TimeParameter; 024import org.shredzone.commons.suncalc.util.BaseBuilder; 025import org.shredzone.commons.suncalc.util.JulianDate; 026import org.shredzone.commons.suncalc.util.Moon; 027import org.shredzone.commons.suncalc.util.Vector; 028 029/** 030 * Calculates the position of the moon. 031 */ 032public class MoonPosition { 033 034 private final double azimuth; 035 private final double altitude; 036 private final double trueAltitude; 037 private final double distance; 038 private final double parallacticAngle; 039 040 private MoonPosition(double azimuth, double altitude, double trueAltitude, double distance, double parallacticAngle) { 041 this.azimuth = (toDegrees(azimuth) + 180.0) % 360.0; 042 this.altitude = toDegrees(altitude); 043 this.trueAltitude = toDegrees(trueAltitude); 044 this.distance = distance; 045 this.parallacticAngle = toDegrees(parallacticAngle); 046 } 047 048 /** 049 * Starts the computation of {@link MoonPosition}. 050 * 051 * @return {@link Parameters} to set. 052 */ 053 public static Parameters compute() { 054 return new MoonPositionBuilder(); 055 } 056 057 /** 058 * Collects all parameters for {@link MoonPosition}. 059 */ 060 public interface Parameters extends 061 GenericParameter<Parameters>, 062 LocationParameter<Parameters>, 063 TimeParameter<Parameters>, 064 Builder<MoonPosition> { 065 } 066 067 /** 068 * Builder for {@link MoonPosition}. Performs the computations based on the 069 * parameters, and creates a {@link MoonPosition} object that holds the result. 070 */ 071 private static class MoonPositionBuilder extends BaseBuilder<Parameters> implements Parameters { 072 @Override 073 public MoonPosition execute() { 074 if (!hasLocation()) { 075 throw new IllegalArgumentException("Geolocation is missing."); 076 } 077 078 JulianDate t = getJulianDate(); 079 080 double phi = getLatitudeRad(); 081 double lambda = getLongitudeRad(); 082 083 Vector mc = Moon.position(t); 084 double h = t.getGreenwichMeanSiderealTime() + lambda - mc.getPhi(); 085 086 Vector horizontal = equatorialToHorizontal(h, mc.getTheta(), mc.getR(), phi); 087 088 double hRef = refraction(horizontal.getTheta()); 089 090 double pa = atan2(sin(h), tan(phi) * cos(mc.getTheta()) - sin(mc.getTheta()) * cos(h)); 091 092 return new MoonPosition( 093 horizontal.getPhi(), 094 horizontal.getTheta() + hRef, 095 horizontal.getTheta(), 096 mc.getR(), 097 pa); 098 } 099 } 100 101 /** 102 * Moon altitude above the horizon, in degrees. 103 * <p> 104 * {@code 0.0} means the moon's center is at the horizon, {@code 90.0} at the zenith 105 * (straight over your head). Atmospheric refraction is taken into account. 106 * 107 * @see #getTrueAltitude() 108 */ 109 public double getAltitude() { 110 return altitude; 111 } 112 113 /** 114 * The true moon altitude above the horizon, in degrees. 115 * <p> 116 * {@code 0.0} means the moon's center is at the horizon, {@code 90.0} at the zenith 117 * (straight over your head). 118 * 119 * @see #getAltitude() 120 * @since 3.8 121 */ 122 public double getTrueAltitude() { 123 return trueAltitude; 124 } 125 126 /** 127 * Moon azimuth, in degrees, north-based. 128 * <p> 129 * This is the direction along the horizon, measured from north to east. For example, 130 * {@code 0.0} means north, {@code 135.0} means southeast, {@code 270.0} means west. 131 */ 132 public double getAzimuth() { 133 return azimuth; 134 } 135 136 /** 137 * Distance to the moon in kilometers. 138 */ 139 public double getDistance() { 140 return distance; 141 } 142 143 /** 144 * Parallactic angle of the moon, in degrees. 145 */ 146 public double getParallacticAngle() { 147 return parallacticAngle; 148 } 149 150 @Override 151 public String toString() { 152 StringBuilder sb = new StringBuilder(); 153 sb.append("MoonPosition[azimuth=").append(azimuth); 154 sb.append("°, altitude=").append(altitude); 155 sb.append("°, true altitude=").append(trueAltitude); 156 sb.append("°, distance=").append(distance); 157 sb.append(" km, parallacticAngle=").append(parallacticAngle); 158 sb.append("°]"); 159 return sb.toString(); 160 } 161 162}