From 1c148c52797038ad65854edea41b9979ff6281c1 Mon Sep 17 00:00:00 2001 From: olamedia Date: Tue, 2 Oct 2012 15:27:32 +0600 Subject: night --- src/ru/olamedia/astronomy/BaseUtils.java | 89 +++++++ src/ru/olamedia/astronomy/Declination.java | 33 +++ src/ru/olamedia/astronomy/FullMoonChecker.java | 41 +++ src/ru/olamedia/astronomy/JulianDate.java | 61 +++++ .../olamedia/astronomy/MinuntesAndSecondsBase.java | 41 +++ src/ru/olamedia/astronomy/MoonChecker.java | 26 ++ src/ru/olamedia/astronomy/MoonPhaseFinder.java | 135 ++++++++++ src/ru/olamedia/astronomy/MoonPosition.java | 185 ++++++++++++++ src/ru/olamedia/astronomy/NewMoonChecker.java | 41 +++ src/ru/olamedia/astronomy/README | 19 ++ src/ru/olamedia/astronomy/RightAscension.java | 32 +++ src/ru/olamedia/astronomy/SunCalendar.java | 284 +++++++++++++++++++++ src/ru/olamedia/astronomy/SunPosition.java | 95 +++++++ src/ru/olamedia/game/GameTime.java | 145 +++++++++++ .../olamedia/olacraft/picker/joglBlockPicker.java | 6 +- src/ru/olamedia/olacraft/scene/GameScene.java | 13 +- .../olacraft/world/blockTypes/GrassBlockType.java | 6 +- 17 files changed, 1241 insertions(+), 11 deletions(-) create mode 100644 src/ru/olamedia/astronomy/BaseUtils.java create mode 100644 src/ru/olamedia/astronomy/Declination.java create mode 100644 src/ru/olamedia/astronomy/FullMoonChecker.java create mode 100644 src/ru/olamedia/astronomy/JulianDate.java create mode 100644 src/ru/olamedia/astronomy/MinuntesAndSecondsBase.java create mode 100644 src/ru/olamedia/astronomy/MoonChecker.java create mode 100644 src/ru/olamedia/astronomy/MoonPhaseFinder.java create mode 100644 src/ru/olamedia/astronomy/MoonPosition.java create mode 100644 src/ru/olamedia/astronomy/NewMoonChecker.java create mode 100644 src/ru/olamedia/astronomy/README create mode 100644 src/ru/olamedia/astronomy/RightAscension.java create mode 100644 src/ru/olamedia/astronomy/SunCalendar.java create mode 100644 src/ru/olamedia/astronomy/SunPosition.java create mode 100644 src/ru/olamedia/game/GameTime.java (limited to 'src/ru/olamedia') 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.
+ * The moon angle will be in the range 0 to 360.
+ * 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.
+ * Calculation is good to 3 decimal places
+ * 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 diff --git a/src/ru/olamedia/game/GameTime.java b/src/ru/olamedia/game/GameTime.java new file mode 100644 index 0000000..9c2348a --- /dev/null +++ b/src/ru/olamedia/game/GameTime.java @@ -0,0 +1,145 @@ +package ru.olamedia.game; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +import ru.olamedia.astronomy.SunCalendar; + +public class GameTime { + public double longitude = 56.803698; + public double latitude = 60.635262; + public double gameSpeed = 60;// 1 real second is 60 seconds at game + private static double daysInYear = 365.242; + private static double minute = 60; + @SuppressWarnings("unused") + private static double hour = 3600; + private static double day = 24 * 3600; + @SuppressWarnings("unused") + private static double month = (daysInYear / 12) * 24 * 3600; + + public GregorianCalendar earthCalendar; + public SunCalendar sunCalendar; + public double gameStart; + public double yearStart; + public double gameTime; + public double gameYearTime; + public double sunlightFactor = 0f; + public int lastSunLight = 0; + public float[] clearColors = new float[] { 0.0f, 0.0f, 0.0f }; + public boolean spaceLightIsInvalid = true; + public boolean receivedLightIsInvalid = true; + public double sunrise; + public double sunset; // + public double sunHA; // + public double sunEA; // + public double sunTC; // + + public static double getSystemTime() { + return System.currentTimeMillis() / (double) (1000); + } + + public void init() { + earthCalendar = new GregorianCalendar(); + earthCalendar.setTimeZone(TimeZone.getTimeZone("Asia/Yekaterinburg")); // FIX + // Timezone + // for + // latlon + sunCalendar = new SunCalendar(earthCalendar, longitude, latitude); + gameSpeed = day / (1 * minute); + + gameStart = getTime(); + + yearStart = gameStart - (gameStart % daysInYear); + updateGameTime(); + } + + public double getTime() { + return getSystemTime() / gameSpeed; + } + + public Date getGameDate() { + return new Date((long) gameTime); + } + + public void updateGameTime() { + gameTime = (getTime() - gameStart) * gameSpeed * gameSpeed; + } + + public String getDateTimeString() { + return new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date((long) (gameTime * 1000))); + } + + private static float addComponent(float a, float b) { + return a + b; + } + + private static float mulComponent(float a, float b) { + return a * b; + } + + public float[] getClearColor() { + float sunAngularDiameter = 32; + float sunRenderDistance = 700; + @SuppressWarnings("unused") + float sunRenderDiameter = (float) ((float) 2 * sunRenderDistance * Math.tan(sunAngularDiameter / 2)); + + sunRenderDiameter /= 15; + + float[] spaceColors = new float[] { 0.03f, 0.03f, 0.05f }; // a little + // blue + + clearColors = new float[] { 0.0f, 0.0f, 0.0f }; + + double crossAngle = sunCalendar.getHourAngle(); + @SuppressWarnings("unused") + int elevationAngle = (int) sunCalendar.radToDeg(sunCalendar.getElevationAngle()); + + sunlightFactor = 0f; + if ((crossAngle > -120 && crossAngle < -70) || (crossAngle > 70 && crossAngle < 120)) { + sunlightFactor = (float) 1f - (Math.abs(crossAngle) - 70) / 50; + } + if (crossAngle >= -70 && crossAngle <= 70) { + sunlightFactor = (float) 1f; + } + int sunlight = (int) Math.round(15 * sunlightFactor); + if (sunlight != lastSunLight) { + spaceLightIsInvalid = true; + receivedLightIsInvalid = true; + } + float[] sunSkyColors = new float[] { 0.5f, 0.7f, 1f }; + for (int i = 0; i < 3; i++) { + clearColors[i] = addComponent(sunSkyColors[i] * (float) sunlightFactor, spaceColors[i]); + } + float lightness = clearColors[0] + clearColors[1] + clearColors[2]; + float[] sunRedColorsAdd = new float[] { 0.3f, 0.1f, 0.0f }; + for (int i = 0; i < 3; i++) { + if (sunlightFactor < 0.5f && sunlightFactor > 0.0f) { + float redFactor = (float) (1 - Math.abs(1 - sunlightFactor * 4)); + clearColors[i] = addComponent(clearColors[i], (float) sunRedColorsAdd[i] * redFactor); + } + clearColors[i] = mulComponent(clearColors[i], (float) sunlightFactor); + } + // fix lightness + float newLightness = clearColors[0] + clearColors[1] + clearColors[2]; + for (int i = 0; i < 3; i++) { + clearColors[i] = clearColors[i] * lightness / newLightness; + } + return clearColors; + } + + public void tick() { + updateGameTime(); + // earthCalendar.setTimeInMillis((long) gameTime * 1000); + if (sunCalendar != null) { + sunCalendar.setTimeInMillis((long) gameTime * 1000); + sunCalendar.update(); + sunrise = Math.floor(sunCalendar.getSunrise() * 1000) / 1000; + sunset = Math.floor(sunCalendar.getSunset() * 1000) / 1000; + sunHA = sunCalendar.getHourAngle(); + sunEA = Math.floor(sunCalendar.getElevationAngle() * 1000) / 1000; + sunTC = Math.floor(sunCalendar.getTimeCorrectionFactor() * 1000) / 1000; + } + } +} diff --git a/src/ru/olamedia/olacraft/picker/joglBlockPicker.java b/src/ru/olamedia/olacraft/picker/joglBlockPicker.java index 6eb279c..b12e1ea 100644 --- a/src/ru/olamedia/olacraft/picker/joglBlockPicker.java +++ b/src/ru/olamedia/olacraft/picker/joglBlockPicker.java @@ -6,12 +6,12 @@ import javax.media.opengl.GL2; import javax.media.opengl.GLAutoDrawable; import ru.olamedia.olacraft.world.block.Block; -import ru.olamedia.olacraft.world.provider.ChunkProvider; +import ru.olamedia.olacraft.world.provider.WorldProvider; public class joglBlockPicker { - ChunkProvider provider; + WorldProvider provider; - public void setChunkProvider(ChunkProvider provider) { + public joglBlockPicker(WorldProvider provider) { this.provider = provider; } diff --git a/src/ru/olamedia/olacraft/scene/GameScene.java b/src/ru/olamedia/olacraft/scene/GameScene.java index 7f2e1fa..37a5098 100644 --- a/src/ru/olamedia/olacraft/scene/GameScene.java +++ b/src/ru/olamedia/olacraft/scene/GameScene.java @@ -14,6 +14,7 @@ import org.ode4j.ode.DBody; import com.jogamp.opengl.util.PMVMatrix; import ru.olamedia.Options; +import ru.olamedia.game.GameTime; import ru.olamedia.liveEntity.LiveEntity; import ru.olamedia.olacraft.game.Game; import ru.olamedia.olacraft.physics.GamePhysicsWorld; @@ -45,6 +46,7 @@ public class GameScene { private boolean isInitialized = false; BlockSlice viewSlice; + public GameTime time = new GameTime(); public GameScene(WorldProvider provider) { this.provider = provider; @@ -74,6 +76,7 @@ public class GameScene { return; } isInitialized = true; + time.init(); registerTextures(); viewport = new joglViewport(drawable); testObject = new VBO(drawable); @@ -132,6 +135,7 @@ public class GameScene { } public void tick() { + time.tick(); Game.instance.tick(); float aspect = Game.Display.getAspect(); Game.instance.camera.setAspect(aspect); @@ -148,9 +152,11 @@ public class GameScene { return; } init(drawable); + float[] clearColor = time.getClearColor(); GL2 gl = drawable.getGL().getGL2(); gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); - gl.glClearColor(49f / 255f, 119f / 255f, 243f / 255f, 1); + gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], 1); + // gl.glClearColor(49f / 255f, 119f / 255f, 243f / 255f, 1); // GOING 3D gl.glPushMatrix(); gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS); @@ -252,10 +258,7 @@ public class GameScene { viewport.drawText("slice x: " + cs.getX() + ".." + (cs.getX() + cs.getWidth() - 1) + " y: " + cs.getY() + ".." + (cs.getY() + cs.getHeight() - 1) + " z: " + cs.getZ() + ".." + (cs.getZ() + cs.getDepth() - 1), width - msz * 2 - 10, height - msz - 170); - // viewport.drawText("slice x: " + (cs.getX() + cs.getWidth() - 1) + - // " y: " + (cs.getY() + cs.getHeight() - 1) - // + " z: " + (cs.getY() + cs.getDepth() - 1), width - msz * 2 - 10, - // height - msz - 185); + viewport.drawText("time: " + time.getDateTimeString(), width - msz * 2 - 10, height - msz - 185); gl.glPopAttrib(); gl.glPopMatrix(); diff --git a/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java index 816b283..d863139 100644 --- a/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java +++ b/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java @@ -13,16 +13,16 @@ public class GrassBlockType extends AbstractBlockType { @Override public String getStackTextureFile() { - return "texture/terrain-grassdarkgreen.png"; + return "texture/terrain-grassolive.png"; } @Override public String getTopTextureFile() { - return "texture/terrain-grassdarkgreen.png"; + return "texture/terrain-grassolive.png"; } @Override public String getFrontTextureFile() { - return "texture/terrain-glong-darkgreen-dirt.png"; + return "texture/terrain-ledgeolive.png"; } } -- cgit v1.2.3