skia / external / github.com / unicode-org / icu / refs/tags/icu-release-3-6-d02 / . / source / i18n / astro.h

/************************************************************************ | |

* Copyright (C) 1996-2006, International Business Machines Corporation * | |

* and others. All Rights Reserved. * | |

************************************************************************ | |

* 2003-nov-07 srl Port from Java | |

*/ | |

#ifndef ASTRO_H | |

#define ASTRO_H | |

#include "unicode/utypes.h" | |

#if !UCONFIG_NO_FORMATTING | |

#include "gregoimp.h" // for Math | |

#include "unicode/unistr.h" | |

U_NAMESPACE_BEGIN | |

/** | |

* <code>CalendarAstronomer</code> is a class that can perform the calculations to | |

* determine the positions of the sun and moon, the time of sunrise and | |

* sunset, and other astronomy-related data. The calculations it performs | |

* are in some cases quite complicated, and this utility class saves you | |

* the trouble of worrying about them. | |

* <p> | |

* The measurement of time is a very important part of astronomy. Because | |

* astronomical bodies are constantly in motion, observations are only valid | |

* at a given moment in time. Accordingly, each <code>CalendarAstronomer</code> | |

* object has a <code>time</code> property that determines the date | |

* and time for which its calculations are performed. You can set and | |

* retrieve this property with {@link #setDate setDate}, {@link #getDate getDate} | |

* and related methods. | |

* <p> | |

* Almost all of the calculations performed by this class, or by any | |

* astronomer, are approximations to various degrees of accuracy. The | |

* calculations in this class are mostly modelled after those described | |

* in the book | |

* <a href="http://www.amazon.com/exec/obidos/ISBN=0521356997" target="_top"> | |

* Practical Astronomy With Your Calculator</a>, by Peter J. | |

* Duffett-Smith, Cambridge University Press, 1990. This is an excellent | |

* book, and if you want a greater understanding of how these calculations | |

* are performed it a very good, readable starting point. | |

* <p> | |

* <strong>WARNING:</strong> This class is very early in its development, and | |

* it is highly likely that its API will change to some degree in the future. | |

* At the moment, it basically does just enough to support {@link IslamicCalendar} | |

* and {@link ChineseCalendar}. | |

* | |

* @author Laura Werner | |

* @author Alan Liu | |

* @internal | |

*/ | |

class U_I18N_API CalendarAstronomer : public UMemory { | |

public: | |

// some classes | |

public: | |

/** | |

* Represents the position of an object in the sky relative to the ecliptic, | |

* the plane of the earth's orbit around the Sun. | |

* This is a spherical coordinate system in which the latitude | |

* specifies the position north or south of the plane of the ecliptic. | |

* The longitude specifies the position along the ecliptic plane | |

* relative to the "First Point of Aries", which is the Sun's position in the sky | |

* at the Vernal Equinox. | |

* <p> | |

* Note that Ecliptic objects are immutable and cannot be modified | |

* once they are constructed. This allows them to be passed and returned by | |

* value without worrying about whether other code will modify them. | |

* | |

* @see CalendarAstronomer.Equatorial | |

* @see CalendarAstronomer.Horizon | |

* @internal | |

*/ | |

class U_I18N_API Ecliptic : public UMemory { | |

public: | |

/** | |

* Constructs an Ecliptic coordinate object. | |

* <p> | |

* @param lat The ecliptic latitude, measured in radians. | |

* @param lon The ecliptic longitude, measured in radians. | |

* @internal | |

*/ | |

Ecliptic(double lat = 0, double lon = 0) { | |

latitude = lat; | |

longitude = lon; | |

} | |

/** | |

* Setter for Ecliptic Coordinate object | |

* @param lat The ecliptic latitude, measured in radians. | |

* @param lon The ecliptic longitude, measured in radians. | |

* @internal | |

*/ | |

void set(double lat, double lon) { | |

latitude = lat; | |

longitude = lon; | |

} | |

/** | |

* Return a string representation of this object | |

* @internal | |

*/ | |

UnicodeString toString() const; | |

/** | |

* The ecliptic latitude, in radians. This specifies an object's | |

* position north or south of the plane of the ecliptic, | |

* with positive angles representing north. | |

* @internal | |

*/ | |

double latitude; | |

/** | |

* The ecliptic longitude, in radians. | |

* This specifies an object's position along the ecliptic plane | |

* relative to the "First Point of Aries", which is the Sun's position | |

* in the sky at the Vernal Equinox, | |

* with positive angles representing east. | |

* <p> | |

* A bit of trivia: the first point of Aries is currently in the | |

* constellation Pisces, due to the precession of the earth's axis. | |

* @internal | |

*/ | |

double longitude; | |

}; | |

/** | |

* Represents the position of an | |

* object in the sky relative to the plane of the earth's equator. | |

* The <i>Right Ascension</i> specifies the position east or west | |

* along the equator, relative to the sun's position at the vernal | |

* equinox. The <i>Declination</i> is the position north or south | |

* of the equatorial plane. | |

* <p> | |

* Note that Equatorial objects are immutable and cannot be modified | |

* once they are constructed. This allows them to be passed and returned by | |

* value without worrying about whether other code will modify them. | |

* | |

* @see CalendarAstronomer.Ecliptic | |

* @see CalendarAstronomer.Horizon | |

* @internal | |

*/ | |

class U_I18N_API Equatorial : public UMemory { | |

public: | |

/** | |

* Constructs an Equatorial coordinate object. | |

* <p> | |

* @param asc The right ascension, measured in radians. | |

* @param dec The declination, measured in radians. | |

* @internal | |

*/ | |

Equatorial(double asc = 0, double dec = 0) | |

: ascension(asc), declination(dec) { } | |

/** | |

* Setter | |

* @param asc The right ascension, measured in radians. | |

* @param dec The declination, measured in radians. | |

* @internal | |

*/ | |

void set(double asc, double dec) { | |

ascension = asc; | |

declination = dec; | |

} | |

/** | |

* Return a string representation of this object, with the | |

* angles measured in degrees. | |

* @internal | |

*/ | |

UnicodeString toString() const; | |

/** | |

* Return a string representation of this object with the right ascension | |

* measured in hours, minutes, and seconds. | |

* @internal | |

*/ | |

//String toHmsString() { | |

//return radToHms(ascension) + "," + radToDms(declination); | |

//} | |

/** | |

* The right ascension, in radians. | |

* This is the position east or west along the equator | |

* relative to the sun's position at the vernal equinox, | |

* with positive angles representing East. | |

* @internal | |

*/ | |

double ascension; | |

/** | |

* The declination, in radians. | |

* This is the position north or south of the equatorial plane, | |

* with positive angles representing north. | |

* @internal | |

*/ | |

double declination; | |

}; | |

/** | |

* Represents the position of an object in the sky relative to | |

* the local horizon. | |

* The <i>Altitude</i> represents the object's elevation above the horizon, | |

* with objects below the horizon having a negative altitude. | |

* The <i>Azimuth</i> is the geographic direction of the object from the | |

* observer's position, with 0 representing north. The azimuth increases | |

* clockwise from north. | |

* <p> | |

* Note that Horizon objects are immutable and cannot be modified | |

* once they are constructed. This allows them to be passed and returned by | |

* value without worrying about whether other code will modify them. | |

* | |

* @see CalendarAstronomer.Ecliptic | |

* @see CalendarAstronomer.Equatorial | |

* @internal | |

*/ | |

class U_I18N_API Horizon : public UMemory { | |

public: | |

/** | |

* Constructs a Horizon coordinate object. | |

* <p> | |

* @param alt The altitude, measured in radians above the horizon. | |

* @param azim The azimuth, measured in radians clockwise from north. | |

* @internal | |

*/ | |

Horizon(double alt=0, double azim=0) | |

: altitude(alt), azimuth(azim) { } | |

/** | |

* Setter for Ecliptic Coordinate object | |

* @param alt The altitude, measured in radians above the horizon. | |

* @param azim The azimuth, measured in radians clockwise from north. | |

* @internal | |

*/ | |

void set(double alt, double azim) { | |

altitude = alt; | |

azimuth = azim; | |

} | |

/** | |

* Return a string representation of this object, with the | |

* angles measured in degrees. | |

* @internal | |

*/ | |

UnicodeString toString() const; | |

/** | |

* The object's altitude above the horizon, in radians. | |

* @internal | |

*/ | |

double altitude; | |

/** | |

* The object's direction, in radians clockwise from north. | |

* @internal | |

*/ | |

double azimuth; | |

}; | |

public: | |

//------------------------------------------------------------------------- | |

// Assorted private data used for conversions | |

//------------------------------------------------------------------------- | |

// My own copies of these so compilers are more likely to optimize them away | |

static const double PI; | |

/** | |

* The average number of solar days from one new moon to the next. This is the time | |

* it takes for the moon to return the same ecliptic longitude as the sun. | |

* It is longer than the sidereal month because the sun's longitude increases | |

* during the year due to the revolution of the earth around the sun. | |

* Approximately 29.53. | |

* | |

* @see #SIDEREAL_MONTH | |

* @internal | |

* @deprecated ICU 2.4. This class may be removed or modified. | |

*/ | |

static const double SYNODIC_MONTH; | |

//------------------------------------------------------------------------- | |

// Constructors | |

//------------------------------------------------------------------------- | |

/** | |

* Construct a new <code>CalendarAstronomer</code> object that is initialized to | |

* the current date and time. | |

* @internal | |

*/ | |

CalendarAstronomer(); | |

/** | |

* Construct a new <code>CalendarAstronomer</code> object that is initialized to | |

* the specified date and time. | |

* @internal | |

*/ | |

CalendarAstronomer(UDate d); | |

/** | |

* Construct a new <code>CalendarAstronomer</code> object with the given | |

* latitude and longitude. The object's time is set to the current | |

* date and time. | |

* <p> | |

* @param longitude The desired longitude, in <em>degrees</em> east of | |

* the Greenwich meridian. | |

* | |

* @param latitude The desired latitude, in <em>degrees</em>. Positive | |

* values signify North, negative South. | |

* | |

* @see java.util.Date#getTime() | |

* @internal | |

*/ | |

CalendarAstronomer(double longitude, double latitude); | |

/** | |

* Destructor | |

* @internal | |

*/ | |

~CalendarAstronomer(); | |

//------------------------------------------------------------------------- | |

// Time and date getters and setters | |

//------------------------------------------------------------------------- | |

/** | |

* Set the current date and time of this <code>CalendarAstronomer</code> object. All | |

* astronomical calculations are performed based on this time setting. | |

* | |

* @param aTime the date and time, expressed as the number of milliseconds since | |

* 1/1/1970 0:00 GMT (Gregorian). | |

* | |

* @see #setDate | |

* @see #getTime | |

* @internal | |

*/ | |

void setTime(UDate aTime); | |

/** | |

* Set the current date and time of this <code>CalendarAstronomer</code> object. All | |

* astronomical calculations are performed based on this time setting. | |

* | |

* @param aTime the date and time, expressed as the number of milliseconds since | |

* 1/1/1970 0:00 GMT (Gregorian). | |

* | |

* @see #getTime | |

* @internal | |

*/ | |

void setDate(UDate aDate) { setTime(aDate); } | |

/** | |

* Set the current date and time of this <code>CalendarAstronomer</code> object. All | |

* astronomical calculations are performed based on this time setting. | |

* | |

* @param jdn the desired time, expressed as a "julian day number", | |

* which is the number of elapsed days since | |

* 1/1/4713 BC (Julian), 12:00 GMT. Note that julian day | |

* numbers start at <em>noon</em>. To get the jdn for | |

* the corresponding midnight, subtract 0.5. | |

* | |

* @see #getJulianDay | |

* @see #JULIAN_EPOCH_MS | |

* @internal | |

*/ | |

void setJulianDay(double jdn); | |

/** | |

* Get the current time of this <code>CalendarAstronomer</code> object, | |

* represented as the number of milliseconds since | |

* 1/1/1970 AD 0:00 GMT (Gregorian). | |

* | |

* @see #setTime | |

* @see #getDate | |

* @internal | |

*/ | |

UDate getTime(); | |

/** | |

* Get the current time of this <code>CalendarAstronomer</code> object, | |

* expressed as a "julian day number", which is the number of elapsed | |

* days since 1/1/4713 BC (Julian), 12:00 GMT. | |

* | |

* @see #setJulianDay | |

* @see #JULIAN_EPOCH_MS | |

* @internal | |

*/ | |

double getJulianDay(); | |

/** | |

* Return this object's time expressed in julian centuries: | |

* the number of centuries after 1/1/1900 AD, 12:00 GMT | |

* | |

* @see #getJulianDay | |

* @internal | |

*/ | |

double getJulianCentury(); | |

/** | |

* Returns the current Greenwich sidereal time, measured in hours | |

* @internal | |

*/ | |

double getGreenwichSidereal(); | |

private: | |

double getSiderealOffset(); | |

public: | |

/** | |

* Returns the current local sidereal time, measured in hours | |

* @internal | |

*/ | |

double getLocalSidereal(); | |

/** | |

* Converts local sidereal time to Universal Time. | |

* | |

* @param lst The Local Sidereal Time, in hours since sidereal midnight | |

* on this object's current date. | |

* | |

* @return The corresponding Universal Time, in milliseconds since | |

* 1 Jan 1970, GMT. | |

*/ | |

//private: | |

double lstToUT(double lst); | |

/** | |

* | |

* Convert from ecliptic to equatorial coordinates. | |

* | |

* @param ecliptic The ecliptic | |

* @param result Fillin result | |

* @return reference to result | |

*/ | |

Equatorial& eclipticToEquatorial(Equatorial& result, const Ecliptic& ecliptic); | |

/** | |

* Convert from ecliptic to equatorial coordinates. | |

* | |

* @param eclipLong The ecliptic longitude | |

* @param eclipLat The ecliptic latitude | |

* | |

* @return The corresponding point in equatorial coordinates. | |

* @internal | |

*/ | |

Equatorial& eclipticToEquatorial(Equatorial& result, double eclipLong, double eclipLat); | |

/** | |

* Convert from ecliptic longitude to equatorial coordinates. | |

* | |

* @param eclipLong The ecliptic longitude | |

* | |

* @return The corresponding point in equatorial coordinates. | |

* @internal | |

*/ | |

Equatorial& eclipticToEquatorial(Equatorial& result, double eclipLong) ; | |

/** | |

* @internal | |

*/ | |

Horizon& eclipticToHorizon(Horizon& result, double eclipLong) ; | |

//------------------------------------------------------------------------- | |

// The Sun | |

//------------------------------------------------------------------------- | |

/** | |

* The longitude of the sun at the time specified by this object. | |

* The longitude is measured in radians along the ecliptic | |

* from the "first point of Aries," the point at which the ecliptic | |

* crosses the earth's equatorial plane at the vernal equinox. | |

* <p> | |

* Currently, this method uses an approximation of the two-body Kepler's | |

* equation for the earth and the sun. It does not take into account the | |

* perturbations caused by the other planets, the moon, etc. | |

* @internal | |

*/ | |

double getSunLongitude(); | |

/** | |

* TODO Make this public when the entire class is package-private. | |

*/ | |

/*public*/ void getSunLongitude(double julianDay, double &longitude, double &meanAnomaly); | |

/** | |

* The position of the sun at this object's current date and time, | |

* in equatorial coordinates. | |

* @param result fillin for the result | |

* @internal | |

*/ | |

Equatorial& getSunPosition(Equatorial& result); | |

public: | |

/** | |

* Constant representing the vernal equinox. | |

* For use with {@link #getSunTime getSunTime}. | |

* Note: In this case, "vernal" refers to the northern hemisphere's seasons. | |

* @internal | |

*/ | |

// static double VERNAL_EQUINOX(); | |

/** | |

* Constant representing the summer solstice. | |

* For use with {@link #getSunTime getSunTime}. | |

* Note: In this case, "summer" refers to the northern hemisphere's seasons. | |

* @internal | |

*/ | |

static double SUMMER_SOLSTICE(); | |

/** | |

* Constant representing the autumnal equinox. | |

* For use with {@link #getSunTime getSunTime}. | |

* Note: In this case, "autumn" refers to the northern hemisphere's seasons. | |

* @internal | |

*/ | |

// static double AUTUMN_EQUINOX(); | |

/** | |

* Constant representing the winter solstice. | |

* For use with {@link #getSunTime getSunTime}. | |

* Note: In this case, "winter" refers to the northern hemisphere's seasons. | |

* @internal | |

*/ | |

// static double WINTER_SOLSTICE(); | |

/** | |

* Find the next time at which the sun's ecliptic longitude will have | |

* the desired value. | |

* @internal | |

*/ | |

UDate getSunTime(double desired, UBool next); | |

/** | |

* Returns the time (GMT) of sunrise or sunset on the local date to which | |

* this calendar is currently set. | |

* | |

* NOTE: This method only works well if this object is set to a | |

* time near local noon. Because of variations between the local | |

* official time zone and the geographic longitude, the | |

* computation can flop over into an adjacent day if this object | |

* is set to a time near local midnight. | |

* | |

* @internal | |

*/ | |

UDate getSunRiseSet(UBool rise); | |

//------------------------------------------------------------------------- | |

// The Moon | |

//------------------------------------------------------------------------- | |

/** | |

* The position of the moon at the time set on this | |

* object, in equatorial coordinates. | |

* @internal | |

* @return const reference to internal field of calendar astronomer. Do not use outside of the lifetime of this astronomer. | |

*/ | |

const Equatorial& getMoonPosition(); | |

/** | |

* The "age" of the moon at the time specified in this object. | |

* This is really the angle between the | |

* current ecliptic longitudes of the sun and the moon, | |

* measured in radians. | |

* | |

* @see #getMoonPhase | |

* @internal | |

*/ | |

double getMoonAge(); | |

/** | |

* Calculate the phase of the moon at the time set in this object. | |

* The returned phase is a <code>double</code> in the range | |

* <code>0 <= phase < 1</code>, interpreted as follows: | |

* <ul> | |

* <li>0.00: New moon | |

* <li>0.25: First quarter | |

* <li>0.50: Full moon | |

* <li>0.75: Last quarter | |

* </ul> | |

* | |

* @see #getMoonAge | |

* @internal | |

*/ | |

double getMoonPhase(); | |

class U_I18N_API MoonAge : public UMemory { | |

public: | |

MoonAge(double l) | |

: value(l) { } | |

void set(double l) { value = l; } | |

double value; | |

}; | |

/** | |

* Constant representing a new moon. | |

* For use with {@link #getMoonTime getMoonTime} | |

* @internal | |

*/ | |

// static const MoonAge NEW_MOON(); | |

/** | |

* Constant representing the moon's first quarter. | |

* For use with {@link #getMoonTime getMoonTime} | |

* @internal | |

*/ | |

// static const MoonAge FIRST_QUARTER(); | |

/** | |

* Constant representing a full moon. | |

* For use with {@link #getMoonTime getMoonTime} | |

* @internal | |

*/ | |

static const MoonAge FULL_MOON(); | |

/** | |

* Constant representing the moon's last quarter. | |

* For use with {@link #getMoonTime getMoonTime} | |

* @internal | |

*/ | |

// static const MoonAge LAST_QUARTER(); | |

/** | |

* Find the next or previous time at which the Moon's ecliptic | |

* longitude will have the desired value. | |

* <p> | |

* @param desired The desired longitude. | |

* @param next <tt>true</tt> if the next occurrance of the phase | |

* is desired, <tt>false</tt> for the previous occurrance. | |

* @internal | |

*/ | |

UDate getMoonTime(double desired, UBool next); | |

UDate getMoonTime(const MoonAge& desired, UBool next); | |

/** | |

* Returns the time (GMT) of sunrise or sunset on the local date to which | |

* this calendar is currently set. | |

* @internal | |

*/ | |

UDate getMoonRiseSet(UBool rise); | |

//------------------------------------------------------------------------- | |

// Interpolation methods for finding the time at which a given event occurs | |

//------------------------------------------------------------------------- | |

// private | |

class AngleFunc : public UMemory { | |

public: | |

virtual double eval(CalendarAstronomer&) = 0; | |

virtual ~AngleFunc(); | |

}; | |

friend class AngleFunc; | |

UDate timeOfAngle(AngleFunc& func, double desired, | |

double periodDays, double epsilon, UBool next); | |

class CoordFunc : public UMemory { | |

public: | |

virtual void eval(Equatorial& result, CalendarAstronomer&) = 0; | |

virtual ~CoordFunc(); | |

}; | |

friend class CoordFunc; | |

double riseOrSet(CoordFunc& func, UBool rise, | |

double diameter, double refraction, | |

double epsilon); | |

//------------------------------------------------------------------------- | |

// Other utility methods | |

//------------------------------------------------------------------------- | |

private: | |

/*** | |

* Given 'value', add or subtract 'range' until 0 <= 'value' < range. | |

* The modulus operator. | |

*/ | |

inline static double normalize(double value, double range) { | |

return value - range * Math::floorDivide(value, range); | |

} | |

/** | |

* Normalize an angle so that it's in the range 0 - 2pi. | |

* For positive angles this is just (angle % 2pi), but the Java | |

* mod operator doesn't work that way for negative numbers.... | |

*/ | |

inline static double norm2PI(double angle) { | |

return normalize(angle, CalendarAstronomer::PI * 2.0); | |

} | |

/** | |

* Normalize an angle into the range -PI - PI | |

*/ | |

inline static double normPI(double angle) { | |

return normalize(angle + PI, CalendarAstronomer::PI * 2.0) - PI; | |

} | |

/** | |

* Find the "true anomaly" (longitude) of an object from | |

* its mean anomaly and the eccentricity of its orbit. This uses | |

* an iterative solution to Kepler's equation. | |

* | |

* @param meanAnomaly The object's longitude calculated as if it were in | |

* a regular, circular orbit, measured in radians | |

* from the point of perigee. | |

* | |

* @param eccentricity The eccentricity of the orbit | |

* | |

* @return The true anomaly (longitude) measured in radians | |

*/ | |

double trueAnomaly(double meanAnomaly, double eccentricity); | |

/** | |

* Return the obliquity of the ecliptic (the angle between the ecliptic | |

* and the earth's equator) at the current time. This varies due to | |

* the precession of the earth's axis. | |

* | |

* @return the obliquity of the ecliptic relative to the equator, | |

* measured in radians. | |

*/ | |

double eclipticObliquity(); | |

//------------------------------------------------------------------------- | |

// Private data | |

//------------------------------------------------------------------------- | |

private: | |

/** | |

* Current time in milliseconds since 1/1/1970 AD | |

* @see java.util.Date#getTime | |

*/ | |

UDate fTime; | |

/* These aren't used yet, but they'll be needed for sunset calculations | |

* and equatorial to horizon coordinate conversions | |

*/ | |

double fLongitude; | |

double fLatitude; | |

double fGmtOffset; | |

// | |

// The following fields are used to cache calculated results for improved | |

// performance. These values all depend on the current time setting | |

// of this object, so the clearCache method is provided. | |

// | |

double julianDay ; | |

double julianCentury ; | |

double sunLongitude ; | |

double meanAnomalySun ; | |

double moonLongitude ; | |

double moonEclipLong ; | |

double meanAnomalyMoon ; | |

double eclipObliquity ; | |

double siderealT0 ; | |

double siderealTime ; | |

void clearCache(); | |

Equatorial moonPosition; | |

UBool moonPositionSet; | |

/** | |

* @internal | |

*/ | |

// UDate local(UDate localMillis); | |

}; | |

U_NAMESPACE_END | |

struct UHashtable; | |

U_NAMESPACE_BEGIN | |

/** | |

* Cache of month -> julian day | |

* @internal | |

*/ | |

class U_I18N_API CalendarCache : public UMemory { | |

public: | |

static int32_t get(CalendarCache** cache, int32_t key, UErrorCode &status); | |

static void put(CalendarCache** cache, int32_t key, int32_t value, UErrorCode &status); | |

virtual ~CalendarCache(); | |

private: | |

CalendarCache(int32_t size, UErrorCode& status); | |

static void createCache(CalendarCache** cache, UErrorCode& status); | |

/** | |

* not implemented | |

*/ | |

CalendarCache(); | |

UHashtable *fTable; | |

}; | |

U_NAMESPACE_END | |

#endif | |

#endif |