aboutsummaryrefslogtreecommitdiffstats
path: root/src/ru/olamedia/astronomy
diff options
context:
space:
mode:
Diffstat (limited to 'src/ru/olamedia/astronomy')
-rw-r--r--src/ru/olamedia/astronomy/BaseUtils.java89
-rw-r--r--src/ru/olamedia/astronomy/Declination.java33
-rw-r--r--src/ru/olamedia/astronomy/FullMoonChecker.java41
-rw-r--r--src/ru/olamedia/astronomy/JulianDate.java61
-rw-r--r--src/ru/olamedia/astronomy/MinuntesAndSecondsBase.java41
-rw-r--r--src/ru/olamedia/astronomy/MoonChecker.java26
-rw-r--r--src/ru/olamedia/astronomy/MoonPhaseFinder.java135
-rw-r--r--src/ru/olamedia/astronomy/MoonPosition.java185
-rw-r--r--src/ru/olamedia/astronomy/NewMoonChecker.java41
-rw-r--r--src/ru/olamedia/astronomy/README19
-rw-r--r--src/ru/olamedia/astronomy/RightAscension.java32
-rw-r--r--src/ru/olamedia/astronomy/SunCalendar.java284
-rw-r--r--src/ru/olamedia/astronomy/SunPosition.java95
13 files changed, 1082 insertions, 0 deletions
diff --git a/src/ru/olamedia/astronomy/BaseUtils.java b/src/ru/olamedia/astronomy/BaseUtils.java
new file mode 100644
index 0000000..99d351a
--- /dev/null
+++ b/src/ru/olamedia/astronomy/BaseUtils.java
@@ -0,0 +1,89 @@
+package ru.olamedia.astronomy;
+
+// package com.bradsbrain.simpleastronomy;
+/*
+ * Copyright 2011 Brad Parks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.text.DateFormat;
+import static java.text.DateFormat.SHORT;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+public final class BaseUtils {
+
+ public static double exactDaysSince(Calendar myCal, double epoch) {
+ return JulianDate.makeJulianDateUsingMyModified(myCal) - epoch;
+ }
+
+ public static Calendar getSafeLocalCopy(long millis) {
+ // safe local copy
+ Calendar myCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+ myCal.clear();
+ myCal.setTimeInMillis(millis);
+ return myCal;
+ }
+
+ public static double adjustTo360Range(double valToAdjust) {
+ double howMany = Math.floor(valToAdjust / 360);
+ double adjustedValue = valToAdjust - (howMany * 360);
+ return adjustedValue;
+ }
+
+ public static double sinDegrees(double angleInDegrees) {
+ return Math.sin(Math.toRadians(angleInDegrees));
+ }
+
+ public static double cosDegrees(double angleInDegrees) {
+ return Math.cos(Math.toRadians(angleInDegrees));
+ }
+
+ public static double useLessPrecision(double d, int precision) {
+ double digits = Math.pow(10, precision);
+ return Math.round(d * digits) / digits;
+ }
+
+ /**
+ * Useful date-to-string formatting which I found myself using a lot
+ *
+ * @param moonDate
+ * @return the date in GMT timezone
+ */
+ public static String formatDateForGMT(Date moonDate) {
+ DateFormat sdf = SimpleDateFormat.getDateInstance(SHORT);
+ ((SimpleDateFormat) sdf).applyPattern("yyyy-MM-dd");
+ ((SimpleDateFormat) sdf).setTimeZone(TimeZone.getTimeZone("GMT"));
+ return sdf.format(moonDate);
+ }
+
+ /**
+ * Useful date-to-string formatting which I found myself using a lot
+ *
+ * @param moonDate
+ * @param tz
+ * the timezone with which to format the date
+ * @return the date in whatever timezone is default
+ */
+ public static String formatDateAsShortDateLocalTime(Date moonDate,
+ TimeZone tz) {
+ DateFormat sdf = SimpleDateFormat.getDateInstance(SHORT);
+ sdf.setTimeZone(tz);
+ ((SimpleDateFormat) sdf).applyPattern("yyyy-MM-dd");
+ return sdf.format(moonDate);
+ }
+
+} \ No newline at end of file
diff --git a/src/ru/olamedia/astronomy/Declination.java b/src/ru/olamedia/astronomy/Declination.java
new file mode 100644
index 0000000..0798ffc
--- /dev/null
+++ b/src/ru/olamedia/astronomy/Declination.java
@@ -0,0 +1,33 @@
+package ru.olamedia.astronomy;
+
+/*
+ * Copyright 2011 Brad Parks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//package com.bradsbrain.simpleastronomy;
+
+public class Declination extends MinuntesAndSecondsBase {
+ private int degrees;
+
+ public Declination(int degrees, int minutes, int seconds) {
+ this.degrees = degrees;
+ setMinutes(minutes);
+ setSeconds(seconds);
+ }
+
+ public int getDegrees() {
+ return degrees;
+ }
+
+}
diff --git a/src/ru/olamedia/astronomy/FullMoonChecker.java b/src/ru/olamedia/astronomy/FullMoonChecker.java
new file mode 100644
index 0000000..84589ab
--- /dev/null
+++ b/src/ru/olamedia/astronomy/FullMoonChecker.java
@@ -0,0 +1,41 @@
+package ru.olamedia.astronomy;
+
+/*
+ * Copyright 2011 Brad Parks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//package com.bradsbrain.simpleastronomy;
+
+public class FullMoonChecker extends MoonChecker {
+
+ private static final double VERY_LARGE_ANGLE = 180.10;
+ private static final double VERY_LARGE_PERCENT = 99.999;
+
+ /**
+ * A new moon would be at a very small angle
+ */
+ @Override
+ public boolean isCorrectAngle(double d) {
+ return d > VERY_LARGE_ANGLE;
+ }
+
+ /**
+ * A new moon would be at a very small percent visible
+ */
+ @Override
+ public boolean isCorrectPercent(double d) {
+ return d > VERY_LARGE_PERCENT;
+ }
+
+}
diff --git a/src/ru/olamedia/astronomy/JulianDate.java b/src/ru/olamedia/astronomy/JulianDate.java
new file mode 100644
index 0000000..94303df
--- /dev/null
+++ b/src/ru/olamedia/astronomy/JulianDate.java
@@ -0,0 +1,61 @@
+package ru.olamedia.astronomy;
+
+/*
+ * Copyright 2011 Brad Parks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//package com.bradsbrain.simpleastronomy;
+
+import java.util.Calendar;
+
+/**
+ * Heavily based on procedures as documented in the book
+ * "Practical Astronomy with Your Calculator", 3rd Edition, by Peter
+ * Duffett-Smith, Cambridge University Press, 1988, 1990, 1992
+ *
+ * @author bradparks
+ */
+public class JulianDate {
+
+ /**
+ * This method is a simplification of formula in Section 3 of PAwyC3. We'll
+ * assume we're only talking about Gregorian Calendar dates because really,
+ * we don't care a whole lot about past dates.
+ *
+ * @param cal
+ * @return
+ */
+
+ public static double makeJulianDateUsingMyModified(Calendar cal) {
+ Calendar myCal = BaseUtils.getSafeLocalCopy(cal.getTimeInMillis());
+ // step 1
+ int year = myCal.get(Calendar.YEAR);
+ int month = myCal.get(Calendar.MONTH) + 1; // fix the January=0
+ double day = myCal.get(Calendar.DAY_OF_MONTH);
+ double hour = myCal.get(Calendar.HOUR_OF_DAY) / 24.0;
+ double minute = myCal.get(Calendar.MINUTE) / 24.0 / 60.0;
+ double second = myCal.get(Calendar.SECOND) / 24.0 / 60.0 / 60.0;
+
+ // step 2
+ if (month <= 2) {
+ year--;
+ month += 12;
+ }
+
+ // step 6
+ return 1720995.5 + Math.floor(365.243 * year)
+ + Math.floor(30.6 * ++month) + day + hour + minute + second;
+ }
+
+} \ No newline at end of file
diff --git a/src/ru/olamedia/astronomy/MinuntesAndSecondsBase.java b/src/ru/olamedia/astronomy/MinuntesAndSecondsBase.java
new file mode 100644
index 0000000..89fab6d
--- /dev/null
+++ b/src/ru/olamedia/astronomy/MinuntesAndSecondsBase.java
@@ -0,0 +1,41 @@
+package ru.olamedia.astronomy;
+
+/*
+ * Copyright 2011 Brad Parks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//package com.bradsbrain.simpleastronomy;
+
+public abstract class MinuntesAndSecondsBase {
+
+ private int minutes;
+ private int seconds;
+
+ public int getMinutes() {
+ return minutes;
+ }
+
+ protected void setMinutes(int minutes) {
+ this.minutes = minutes;
+ }
+
+ public int getSeconds() {
+ return seconds;
+ }
+
+ protected void setSeconds(int seconds) {
+ this.seconds = seconds;
+ }
+
+} \ No newline at end of file
diff --git a/src/ru/olamedia/astronomy/MoonChecker.java b/src/ru/olamedia/astronomy/MoonChecker.java
new file mode 100644
index 0000000..069e67a
--- /dev/null
+++ b/src/ru/olamedia/astronomy/MoonChecker.java
@@ -0,0 +1,26 @@
+package ru.olamedia.astronomy;
+
+/*
+ * Copyright 2011 Brad Parks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//package com.bradsbrain.simpleastronomy;
+
+public abstract class MoonChecker {
+
+ public abstract boolean isCorrectAngle(double d);
+
+ public abstract boolean isCorrectPercent(double d);
+
+}
diff --git a/src/ru/olamedia/astronomy/MoonPhaseFinder.java b/src/ru/olamedia/astronomy/MoonPhaseFinder.java
new file mode 100644
index 0000000..8e9c837
--- /dev/null
+++ b/src/ru/olamedia/astronomy/MoonPhaseFinder.java
@@ -0,0 +1,135 @@
+package ru.olamedia.astronomy;
+
+/*
+ * Copyright 2011 Brad Parks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//package com.bradsbrain.simpleastronomy;
+
+import java.util.Calendar;
+import java.util.Date;
+
+public class MoonPhaseFinder {
+
+ private static final int NUM_STEP_MINUTES = 1;
+
+ private static MoonChecker newMoonChecker = new NewMoonChecker();
+ private static MoonChecker fullMoonChecker = new FullMoonChecker();
+
+ public enum MoonPhase {
+ NEW,
+ WAXINGCRESCENT,
+ FIRSTQUARTER,
+ WAXINGGIBBOUS,
+ FULL,
+ WANINGGIBBOUS,
+ LASTQUARTER,
+ WANINGCRESCENT;
+
+
+ static MoonPhase finder(double percent) {
+ return FULL;
+ }
+
+ }
+
+ /**
+ * Someday this will return a descriptive MoonPhase enum when handed a cal/date
+ *
+ * @param cal
+ * @return
+ */
+ public static MoonPhase findMoonPhaseAt(Calendar cal) {
+ return null;
+ }
+
+ public static Date findFullMoonFollowing(Calendar cal) {
+ return findDatePassingBounds(cal, fullMoonChecker);
+ }
+
+ public static Date findNewMoonFollowing(Calendar cal) {
+ return findDatePassingBounds(cal, newMoonChecker);
+ }
+
+ public static Date findFullMoonFollowing(Date date) {
+ long time = date.getTime();
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ return findDatePassingBounds(cal, fullMoonChecker);
+ }
+
+ public static Date findNewMoonFollowing(Date date) {
+ long time = date.getTime();
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(time);
+ return findDatePassingBounds(cal, newMoonChecker);
+ }
+
+ /**
+ * TODO: This loop isn't very efficient, come up with a better implementation
+ *
+ * @param cal the calendar date for which to compute the moon position
+ * @param moonChecker the NewMoon or FullMoon checker
+ * @return the forward date which passes the given bounds provided
+ */
+ private static Date findDatePassingBounds(Calendar cal, MoonChecker moonChecker) {
+ Calendar myCal = BaseUtils.getSafeLocalCopy(cal.getTimeInMillis());
+ Calendar thirtyOneDaysLater = Calendar.getInstance();
+ thirtyOneDaysLater.setTimeInMillis(myCal.getTimeInMillis());
+ thirtyOneDaysLater.add(Calendar.DAY_OF_MONTH, 31);
+ // if we don't find a new moon after 31 days we're not going to find it. days between phases is ~29.5
+ while (myCal.before(thirtyOneDaysLater)) {
+ myCal.add(Calendar.MINUTE, NUM_STEP_MINUTES);
+ double percent = 100 * MoonPhaseFinder.getMoonVisiblePercent(myCal);
+ double angle = MoonPhaseFinder.getMoonAngle(myCal);
+ if (moonChecker.isCorrectAngle(angle) && moonChecker.isCorrectPercent(percent)) {
+ return myCal.getTime();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns a (much-too-)high-precision value for the amount of moon visible.
+ * Value will be somewhere in the range 0% to 100% (i.e. 0.00 to 1.00)
+ *
+ * @param cal
+ * @return percent of moon which is visible
+ */
+ public static double getMoonVisiblePercent(Calendar cal) {
+ double moonAngle = getMoonAngle(cal);
+ return BaseUtils.useLessPrecision(0.5 * (1 - BaseUtils.cosDegrees(moonAngle)), 3);
+ }
+
+ /**
+ * The moon angle. For that we need the sun's position and the moon's position. </br>
+ * The moon angle will be in the range 0 to 360. <br/>
+ * 0 or 360 is NEW, 180 is FULL
+ *
+ * @param cal
+ * @return the angle of the moon in relation to the earth
+ */
+ public static double getMoonAngle(Calendar cal) {
+ Calendar myCal = BaseUtils.getSafeLocalCopy(cal.getTimeInMillis());
+ SunPosition sunPos = new SunPosition(myCal);
+ MoonPosition moonPos = new MoonPosition(myCal);
+
+ double angleAge = moonPos.getTrueLongitude() - sunPos.getEclipticLongitude();
+ if (angleAge < 0) {
+ return 360 + angleAge;
+ }
+ return angleAge;
+ }
+
+}
diff --git a/src/ru/olamedia/astronomy/MoonPosition.java b/src/ru/olamedia/astronomy/MoonPosition.java
new file mode 100644
index 0000000..e20349f
--- /dev/null
+++ b/src/ru/olamedia/astronomy/MoonPosition.java
@@ -0,0 +1,185 @@
+package ru.olamedia.astronomy;
+
+/*
+ * Copyright 2011 Brad Parks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//package com.bradsbrain.simpleastronomy;
+
+import static ru.olamedia.astronomy.BaseUtils.sinDegrees;
+
+import java.util.Calendar;
+
+public class MoonPosition {
+ // some handy constants
+ private double EPOCH = 2447891.5; // 1990 January 0.0
+ private double MEAN_LONGITUDE_AT_EPOCH = 318.351648;
+ private double MEAN_LONGITUDE_OF_PERIGREE_AT_EPOCH = 36.340410;
+
+ /**
+ * The True Longitude
+ */
+ private double trueOrbitalLongitude;
+
+ /**
+ * This is from section 65, page 144
+ *
+ * @param cal
+ * the calendar date for which to compute the moon position
+ */
+ public MoonPosition(Calendar cal) {
+ Calendar myCal = BaseUtils.getSafeLocalCopy(cal.getTimeInMillis());
+ double daysSince = BaseUtils.exactDaysSince(myCal, EPOCH);
+
+ // l
+ double moonMeanLongitude = computeMeanLongitude(daysSince);
+ // M m
+ double moonMeanAnomaly = computeMeanAnomaly(daysSince,
+ moonMeanLongitude);
+
+ SunPosition sunPos = new SunPosition(myCal);
+
+ MoonCorrections corrections = new MoonCorrections(moonMeanLongitude,
+ moonMeanAnomaly, sunPos.getEclipticLongitude(),
+ sunPos.getMeanAnomaly());
+ trueOrbitalLongitude = corrections.getCorrectedLongitude()
+ - corrections.getVariationCorrection();
+ }
+
+ public double getTrueLongitude() {
+ return trueOrbitalLongitude;
+ }
+
+ /**
+ * Compute the Moon Mean Longitude l
+ *
+ * @param daysSince
+ * @return
+ */
+ private double computeMeanLongitude(double daysSince) {
+ double moonMeanLongitude = 13.1763966 * daysSince
+ + MEAN_LONGITUDE_AT_EPOCH;
+ return BaseUtils.adjustTo360Range(moonMeanLongitude);
+ }
+
+ /**
+ * Compute the Moon Mean Anomaly M m
+ *
+ * @param daysSince
+ * @param moonMeanLongitude
+ * @return
+ */
+ private double computeMeanAnomaly(double daysSince, double moonMeanLongitude) {
+ double moonMeanAnomaly = moonMeanLongitude - (0.1114041 * daysSince)
+ - MEAN_LONGITUDE_OF_PERIGREE_AT_EPOCH;
+ return BaseUtils.adjustTo360Range(moonMeanAnomaly);
+ }
+
+ /**
+ * Private internal class used for lots of computations and corrections
+ */
+ private static class MoonCorrections {
+ private double moonMeanLongitude;
+ private double moonMeanAnomaly;
+ private double sunLongitude;
+ private double sunMeanAnomaly;
+
+ MoonCorrections(double moonMeanLongitude, double moonMeanAnomaly,
+ double sunLongitude, double sunMeanAnomaly) {
+ this.moonMeanAnomaly = moonMeanAnomaly;
+ this.sunMeanAnomaly = sunMeanAnomaly;
+ this.moonMeanLongitude = moonMeanLongitude;
+ this.sunLongitude = sunLongitude;
+ }
+
+ /**
+ * V
+ *
+ * @return
+ */
+ public double getVariationCorrection() {
+ return 0.6583 * sinDegrees(2 * (getCorrectedLongitude() - sunLongitude));
+ }
+
+ /**
+ * l'
+ *
+ * @return
+ */
+ public double getCorrectedLongitude() {
+ return moonMeanLongitude + getEvictionCorrection()
+ + getCorrectionForEquationCentre()
+ - getAnnualEquationCorrection()
+ + getYetAnotherCorrectionTerm();
+ }
+
+ /**
+ * A 4
+ *
+ * @return
+ */
+ private double getYetAnotherCorrectionTerm() {
+ return 0.214 * sinDegrees(2 * getMoonCorrectedAnomaly());
+ }
+
+ /**
+ * E c
+ *
+ * @return
+ */
+ private double getCorrectionForEquationCentre() {
+ return 6.2886 * sinDegrees(getMoonCorrectedAnomaly());
+ }
+
+ /**
+ * M' m
+ *
+ * @return
+ */
+ private double getMoonCorrectedAnomaly() {
+ return moonMeanAnomaly + getEvictionCorrection()
+ - getAnnualEquationCorrection()
+ - getUnnamedThirdCorrection();
+ }
+
+ /**
+ * E v
+ *
+ * @return
+ */
+ public double getEvictionCorrection() {
+ double C = moonMeanLongitude - sunLongitude;
+ return 1.2739 * sinDegrees(2.0 * C - moonMeanAnomaly);
+ }
+
+ /**
+ * A e
+ *
+ * @return
+ */
+ public double getAnnualEquationCorrection() {
+ return 0.1858 * sinDegrees(sunMeanAnomaly);
+ }
+
+ /**
+ * A 3
+ *
+ * @return
+ */
+ public double getUnnamedThirdCorrection() {
+ return 0.37 * sinDegrees(sunMeanAnomaly);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/ru/olamedia/astronomy/NewMoonChecker.java b/src/ru/olamedia/astronomy/NewMoonChecker.java
new file mode 100644
index 0000000..d8472fd
--- /dev/null
+++ b/src/ru/olamedia/astronomy/NewMoonChecker.java
@@ -0,0 +1,41 @@
+package ru.olamedia.astronomy;
+
+/*
+ * Copyright 2011 Brad Parks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//package com.bradsbrain.simpleastronomy;
+
+public class NewMoonChecker extends MoonChecker {
+
+ private static final double VERY_SMALL_ANGLE = 0.01;
+ private static final double VERY_SMALL_PERCENT = 0.01;
+
+ /**
+ * A new moon would be at a very small angle
+ */
+ @Override
+ public boolean isCorrectAngle(double d) {
+ return d < VERY_SMALL_ANGLE;
+ }
+
+ /**
+ * A new moon would be at a very small percent visible
+ */
+ @Override
+ public boolean isCorrectPercent(double d) {
+ return d < VERY_SMALL_PERCENT;
+ }
+
+}
diff --git a/src/ru/olamedia/astronomy/README b/src/ru/olamedia/astronomy/README
new file mode 100644
index 0000000..13d2655
--- /dev/null
+++ b/src/ru/olamedia/astronomy/README
@@ -0,0 +1,19 @@
+
+simple-astronomy-lib
+A simple astronomy Java library for calculating moon phase, solar eclipses, etc.
+
+http://code.google.com/p/simple-astronomy-lib/
+
+import java.util.Calendar;
+import java.util.TimeZone;
+import com.bradsbrain.simpleastronomy.MoonPhaseFinder;
+
+public class WerewolfCheck {
+ public static void main(String[] args) {
+ Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("America/Chicago"));
+ cal.clear();
+ cal.set(2011, Calendar.JUNE, 12);
+
+ System.out.println("The next full moon is on: " + MoonPhaseFinder.findFullMoonFollowing(cal));
+ }
+} \ No newline at end of file
diff --git a/src/ru/olamedia/astronomy/RightAscension.java b/src/ru/olamedia/astronomy/RightAscension.java
new file mode 100644
index 0000000..a321eee
--- /dev/null
+++ b/src/ru/olamedia/astronomy/RightAscension.java
@@ -0,0 +1,32 @@
+package ru.olamedia.astronomy;
+
+/*
+ * Copyright 2011 Brad Parks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//package com.bradsbrain.simpleastronomy;
+
+public class RightAscension extends MinuntesAndSecondsBase {
+ private int hours;
+
+ public RightAscension(int hours, int minutes, int seconds) {
+ this.hours = hours;
+ setMinutes(minutes);
+ setSeconds(seconds);
+ }
+
+ public int getHours() {
+ return hours;
+ }
+} \ No newline at end of file
diff --git a/src/ru/olamedia/astronomy/SunCalendar.java b/src/ru/olamedia/astronomy/SunCalendar.java
new file mode 100644
index 0000000..05ec596
--- /dev/null
+++ b/src/ru/olamedia/astronomy/SunCalendar.java
@@ -0,0 +1,284 @@
+package ru.olamedia.astronomy;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+
+/**
+ * Sun position calculations
+ *
+ * @author olamedia
+ *
+ */
+@SuppressWarnings("unused")
+public class SunCalendar extends GregorianCalendar {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2708738531759361416L;
+ double jd;
+ double jcycle;
+ double meanLongitude; // L
+ private double latitude;
+ private double longitude;
+
+ public double getLongitude() { // User longitude at Earth
+ return longitude;
+ }
+
+ public void setLongitude(double longitude) {
+ this.longitude = longitude;
+ }
+
+ public double getLatitude() {
+ return latitude;
+ }
+
+ public void setLatitude(double latitude) {
+ this.latitude = latitude;
+ }
+
+ private double to360(double v) {
+ double v360 = v - Math.floor(v / 360) * 360;
+ while (v360 < 0) {
+ v360 += 360;
+ }
+ return v360;
+ }
+
+ private void computePosition() {
+ // These orbital elements are thus valid for the Sun's (apparent) orbit
+ // around the Earth.
+ // All angular values are expressed in degrees:
+ double w = 282.9404 + 4.70935E-5 * jd; // (longitude of perihelion)
+ // 282.9404_deg + 4.70935E-5_deg
+ // * jd
+ double a = 1.000000; // (mean distance, a.u.)
+ double e = 0.016709 - 1.151E-9 * jd; // (eccentricity)
+ double M = to360(356.0470 + 0.9856002585 * jd);// (mean anomaly)
+ // 356.0470_deg +
+ // 0.9856002585_deg * jd
+ double oblecl = 23.4393 - 3.563E-7 * jd; // (obliquity of the ecliptic)
+ // 23.4393_deg -
+ // 3.563E-7_deg * jd
+ double L = w + M; // Sun's mean longitude
+ meanLongitude = L;
+ // Let's go on computing an auxiliary angle, the eccentric anomaly.
+ // Since the eccentricity of the Sun's (i.e. the Earth's) orbit is so
+ // small, 0.017,
+ // a first approximation of E will be accurate enough. Below E and M are
+ // in degrees:
+ double E = M + (180 / Math.PI) * e * Math.sin(M)
+ * (1 + e * Math.cos(M)); // (eccentric anomaly)
+ // Now we compute the Sun's rectangular coordinates in the plane of the
+ // ecliptic, where the X axis points towards the perihelion:
+ double x = Math.cos(E) - e; // x = r * Math.cos(v) = Math.cos(E) - e
+ double y = Math.sin(E) * Math.sqrt(1 - e * e); // y = r * Math.sin(v) =
+ // Math.sin(E) * sqrt(1
+ // - e*e)
+
+ // Convert to distance and true anomaly:
+ double r = Math.sqrt(x * x + y * y);
+ double v = Math.atan2(y, x);
+
+ double lon = v + w;
+ }
+
+ double UT; // UT is the same as Greenwich time
+
+ public void computeSidetime() {
+ double GMST0 = to360(meanLongitude + 180) / 15;
+ double LON = 15; // Central Europe (at 15 deg east longitude = +15
+ // degrees long) on 19 april 1990 at 00:00 UT
+
+ // LON is the terrestial longitude in degrees (western longitude is
+ // negative, eastern positive).
+ // To "convert" the longitude from degrees to hours we divide it by 15
+ double SIDTIME = GMST0 + UT + LON / 15;
+ // To compute the altitude and azimuth
+ // we also need to know the Hour Angle, HA.
+
+ // The Hour Angle is zero when the clestial body
+ // is in the meridian i.e. in the south
+ // (or, from the southern heimsphere, in the north) -
+ // this is the moment when the celestial body
+ // is at its highest above the horizon.
+
+ // The Hour Angle increases with time
+ // (unless the object is moving faster than the Earth rotates;
+ // this is the case for most artificial satellites).
+ // It is computed from:
+ // RA - Right Ascension
+ // double HA = SIDTIME - RA;
+ }
+
+ /*
+ * Local Standard Time Meridian (LSTM) The Local Standard Time Meridian
+ * (LSTM) is a reference meridian used for a particular time zone and is
+ * similar to the Prime Meridian, which is used for Greenwich Mean Time.
+ */
+ public double getLocalStandardTimeMeridian() {
+ return 15 * this.getTimeZone().getOffset(this.getTimeInMillis());
+ }
+
+ /*
+ * Equation of Time (EoT)
+ *
+ * The equation of time (EoT) (in minutes) is an empirical equation that
+ * corrects for the eccentricity of the Earth's orbit and the Earth's axial
+ * tilt. where B in degrees and d is the number of days since the start of
+ * the year. The time correction EoT is plotted in the figure below.
+ */
+ public double getEquationOfTime() {
+ double B = getB();
+ return ((double) 9.87 * Math.sin(2 * B) - 7.53 * Math.cos(B) - 1.5 * Math
+ .sin(B));
+ }
+
+ /*
+ * Time Correction Factor (TC)
+ *
+ * The net Time Correction Factor (in minutes) accounts for the variation of
+ * the Local Solar Time (LST) within a given time zone due to the longitude
+ * variations within the time zone and also incorporates the EoT above.
+ *
+ * The factor of 4 minutes comes from the fact that the Earth rotates 1°
+ * every 4 minutes.
+ */
+ public double getTimeCorrectionFactor() {
+ // FIX LATER
+ return 0;// 4 * (getLocalStandardTimeMeridian() - getLongitude())
+ // + getEquationOfTime();
+ }
+
+ /*
+ * Local Solar Time (LST)
+ *
+ * The Local Solar Time (LST) can be found by using the previous two
+ * corrections to adjust the local time (LT).
+ */
+ public double getLocalSolarTime() {
+ return (double) get(Calendar.HOUR_OF_DAY) + (double) get(Calendar.MINUTE) / 60
+ + (double) get(Calendar.SECOND) / (60 * 60) + getTimeCorrectionFactor()
+ / 60;
+ }
+
+ /*
+ * Hour Angle (HRA)
+ *
+ * The Hour Angle converts the local solar time (LST) into the number of
+ * degrees which the sun moves across the sky. By definition, the Hour Angle
+ * is 0° at solar noon. Since the Earth rotates 15° per hour, each hour away
+ * from solar noon corresponds to an angular motion of the sun in the sky of
+ * 15°. In the morning the hour angle is negative, in the afternoon the hour
+ * angle is positive.
+ */
+ public double getHourAngle() {
+ return 15 * (getLocalSolarTime() - 12); // 15°(LST-12)
+ }
+
+ /*
+ * Declination
+ *
+ * The declination angle has been previously given as:
+ *
+ * Where d is the number of days since the start of the year.
+ */
+ public double getDeclination() {
+ return (double) 23.45 * Math.sin(getB());
+ }
+
+ public double getElevationAngle() {
+ // φ is the latitude of the location of interest
+ // δ is the declination angle
+ // elevation angle at solar noon:
+ // α = 90 - φ + δ (Northern Hemisphere: +90° North pole)
+ // α = 90 + φ - δ (Southern Hemisphere: -90° South pole)
+ // 90 + (getLatitude() - getDeclination())
+ // * (getLatitude() > 0 ? -1 : 1);
+ return Math.pow(
+ Math.sin(Math.sin(getDeclination()) * Math.sin(getLatitude())
+ + Math.cos(getDeclination()) * Math.cos(getLatitude())
+ * Math.cos(getHourAngle())
+
+ ), -1);
+ }
+
+ public double getZenithAngle() {
+ return 90 - getElevationAngle();
+ }
+
+ public double getSunrise() {
+ // Sunrise=12−1/150 cos−1(−sinφ sinδ cosφ cosδ)−TC/60
+ double delta = getLongitude() + radToDeg(getHourAngleSunrise());
+ double UTCsec = (720 - (4.0 * delta) - getEquationOfTime()) * 60;
+ double sec = UTCsec
+ + (this.getTimeZone().getOffset(getTimeInMillis()) / 1000);// in
+ // minutes,
+ // UTC
+ return (double) (int) sec / (60 * 60);
+ }
+
+ public double getSunset() {
+ // Sunset=12+1/150 cos−1(−sinφ sinδ cosφ cosδ)−TC/60
+ double lw = getLongitude();
+ return (getHourAngle() + lw) / 360;
+ // 2451545.009 + + jcycle
+ // + 0.0053 * Math.sin(M) - 0.0069 * Math.sin(2*lamb);
+
+ // return 12
+ // + 15
+ // * Math.pow(
+ // Math.cos(-Math.tan(getLatitude())
+ // * Math.tan(getDeclination())), -1)
+ // - getTimeCorrectionFactor() / 60;
+ }
+
+ public double radToDeg(double angleRad) {
+ return (180.0 * angleRad / Math.PI);
+ }
+
+ public double degToRad(double angleDeg) {
+ return (Math.PI * angleDeg / 180.0);
+ }
+
+ public double getHourAngleSunrise() {
+ double latRad = degToRad(getLatitude());
+ double sdRad = degToRad(getDeclination());
+ double HAarg = (Math.cos(degToRad(90.833))
+ / (Math.cos(latRad) * Math.cos(sdRad)) - Math.tan(latRad)
+ * Math.tan(sdRad));
+ double HA = Math.acos(HAarg);
+ return (HA); // in radians (for sunset, use -HA)
+ }
+
+ public double getB() {
+ return ((double) 360 / 365)
+ * (double) (this.get(Calendar.DAY_OF_YEAR) - 81);
+ }
+
+ public SunCalendar(Calendar cal, double longitude, // West-East
+ double latitude // +90° North-South -90°
+ ) {
+ super();
+ this.setTimeZone(cal.getTimeZone());
+ this.setTime(cal.getTime());
+ this.setLongitude(longitude);
+ // Arctic Circle 66° 33′ 39″ N
+ // Tropic of Cancer 23° 26′ 21″ N
+ // Tropic of Capricorn 23° 26′ 21″ S
+ // Antarctic Circle 66° 33′ 39" S
+ this.setLatitude(latitude);
+ // computePosition();
+ // computeSidetime();
+ }
+
+ public void update() {
+ jd = JulianDate.makeJulianDateUsingMyModified(this);
+ // Here lw is the longitude west (west is positive, east is negative)
+ // of the observer on the Earth;
+ jcycle = jd - 2451545.009 - getLongitude() / 360;
+ }
+
+}
diff --git a/src/ru/olamedia/astronomy/SunPosition.java b/src/ru/olamedia/astronomy/SunPosition.java
new file mode 100644
index 0000000..48209ed
--- /dev/null
+++ b/src/ru/olamedia/astronomy/SunPosition.java
@@ -0,0 +1,95 @@
+package ru.olamedia.astronomy;
+
+/*
+ * Copyright 2011 Brad Parks
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//package com.bradsbrain.simpleastronomy;
+
+import java.util.Calendar;
+
+public class SunPosition {
+ // some handy constants
+ private double EPOCH = 2447891.5; // 1990 January 0.0
+ private double ECLIPTIC_LONGITUDE_OF_PERIGREE = 282.768422;
+ private double ECLIPTIC_LONGITUDE_AT_EPOCH_1990 = 279.403303;
+ private double ECCENTRICITY_OF_ORBIT = 0.016713;
+
+ /**
+ * The geocentric ecliptic longitude. <br>
+ * Calculation is good to 3 decimal places <br>
+ * me: 337.44406603442917, book: 337.444194
+ */
+ private double geoEclipticLongitude = 0; // oft represented as a lambda with
+ // little circle+dot
+ /**
+ * The mean anomaly
+ */
+ private double meanAnomaly = 0; // oft represented as capital M with little
+ // circle+dot
+
+ public SunPosition(Calendar cal) {
+ Calendar myCal = BaseUtils.getSafeLocalCopy(cal.getTimeInMillis());
+
+ double daysSince = BaseUtils.exactDaysSince(myCal, EPOCH);
+
+ double N = (360 / 365.242191 * daysSince) % 360;
+ if (N < 0) {
+ N += 360;
+ }
+
+ meanAnomaly = computeMeanAnomaly(N);
+ geoEclipticLongitude = computeGeoEclipticLongitude(N);
+ }
+
+ private double computeGeoEclipticLongitude(double nValue) {
+ double Ec = (360.0 / Math.PI) * ECCENTRICITY_OF_ORBIT
+ * Math.sin(Math.toRadians(meanAnomaly));
+ double preliminaryLongitude = nValue + Ec
+ + ECLIPTIC_LONGITUDE_AT_EPOCH_1990;
+ if (preliminaryLongitude > 360) {
+ preliminaryLongitude -= 360;
+ }
+ return preliminaryLongitude;
+ }
+
+ private double computeMeanAnomaly(double nValue) {
+ double someMean = nValue + ECLIPTIC_LONGITUDE_AT_EPOCH_1990
+ - ECLIPTIC_LONGITUDE_OF_PERIGREE;
+ return someMean < 0 ? someMean + 360 : someMean;
+ }
+
+ /**
+ * TODO: implement this someday
+ */
+ public RightAscension getRightAscension() {
+ return null;
+ }
+
+ /**
+ * TODO: implement this someday
+ */
+ public Declination getDeclination() {
+ return null;
+ }
+
+ public double getEclipticLongitude() {
+ return geoEclipticLongitude;
+ }
+
+ public double getMeanAnomaly() {
+ return meanAnomaly;
+ }
+
+} \ No newline at end of file