]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/astro.h
ICU-57166.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / astro.h
CommitLineData
374ca955 1/************************************************************************
57a6839d 2 * Copyright (C) 1996-2008,2014 International Business Machines Corporation *
374ca955
A
3 * and others. All Rights Reserved. *
4 ************************************************************************
5 * 2003-nov-07 srl Port from Java
6 */
7
8#ifndef ASTRO_H
9#define ASTRO_H
10
11#include "unicode/utypes.h"
12
13#if !UCONFIG_NO_FORMATTING
14
15#include "gregoimp.h" // for Math
16#include "unicode/unistr.h"
17
18U_NAMESPACE_BEGIN
19
20/**
21 * <code>CalendarAstronomer</code> is a class that can perform the calculations to
22 * determine the positions of the sun and moon, the time of sunrise and
23 * sunset, and other astronomy-related data. The calculations it performs
24 * are in some cases quite complicated, and this utility class saves you
25 * the trouble of worrying about them.
26 * <p>
27 * The measurement of time is a very important part of astronomy. Because
28 * astronomical bodies are constantly in motion, observations are only valid
29 * at a given moment in time. Accordingly, each <code>CalendarAstronomer</code>
30 * object has a <code>time</code> property that determines the date
31 * and time for which its calculations are performed. You can set and
32 * retrieve this property with {@link #setDate setDate}, {@link #getDate getDate}
33 * and related methods.
34 * <p>
35 * Almost all of the calculations performed by this class, or by any
36 * astronomer, are approximations to various degrees of accuracy. The
37 * calculations in this class are mostly modelled after those described
38 * in the book
39 * <a href="http://www.amazon.com/exec/obidos/ISBN=0521356997" target="_top">
40 * Practical Astronomy With Your Calculator</a>, by Peter J.
41 * Duffett-Smith, Cambridge University Press, 1990. This is an excellent
42 * book, and if you want a greater understanding of how these calculations
43 * are performed it a very good, readable starting point.
44 * <p>
45 * <strong>WARNING:</strong> This class is very early in its development, and
46 * it is highly likely that its API will change to some degree in the future.
47 * At the moment, it basically does just enough to support {@link IslamicCalendar}
48 * and {@link ChineseCalendar}.
49 *
50 * @author Laura Werner
51 * @author Alan Liu
52 * @internal
53 */
54class U_I18N_API CalendarAstronomer : public UMemory {
55public:
56 // some classes
57
58public:
59 /**
60 * Represents the position of an object in the sky relative to the ecliptic,
61 * the plane of the earth's orbit around the Sun.
62 * This is a spherical coordinate system in which the latitude
63 * specifies the position north or south of the plane of the ecliptic.
64 * The longitude specifies the position along the ecliptic plane
65 * relative to the "First Point of Aries", which is the Sun's position in the sky
66 * at the Vernal Equinox.
67 * <p>
68 * Note that Ecliptic objects are immutable and cannot be modified
69 * once they are constructed. This allows them to be passed and returned by
70 * value without worrying about whether other code will modify them.
71 *
72 * @see CalendarAstronomer.Equatorial
73 * @see CalendarAstronomer.Horizon
74 * @internal
75 */
76 class U_I18N_API Ecliptic : public UMemory {
77 public:
78 /**
79 * Constructs an Ecliptic coordinate object.
80 * <p>
81 * @param lat The ecliptic latitude, measured in radians.
82 * @param lon The ecliptic longitude, measured in radians.
83 * @internal
84 */
85 Ecliptic(double lat = 0, double lon = 0) {
86 latitude = lat;
87 longitude = lon;
88 }
89
90 /**
91 * Setter for Ecliptic Coordinate object
92 * @param lat The ecliptic latitude, measured in radians.
93 * @param lon The ecliptic longitude, measured in radians.
94 * @internal
95 */
96 void set(double lat, double lon) {
97 latitude = lat;
98 longitude = lon;
99 }
100
101 /**
102 * Return a string representation of this object
103 * @internal
104 */
105 UnicodeString toString() const;
106
107 /**
108 * The ecliptic latitude, in radians. This specifies an object's
109 * position north or south of the plane of the ecliptic,
110 * with positive angles representing north.
111 * @internal
112 */
113 double latitude;
114
115 /**
116 * The ecliptic longitude, in radians.
117 * This specifies an object's position along the ecliptic plane
118 * relative to the "First Point of Aries", which is the Sun's position
119 * in the sky at the Vernal Equinox,
120 * with positive angles representing east.
121 * <p>
122 * A bit of trivia: the first point of Aries is currently in the
123 * constellation Pisces, due to the precession of the earth's axis.
124 * @internal
125 */
126 double longitude;
127 };
128
129 /**
130 * Represents the position of an
131 * object in the sky relative to the plane of the earth's equator.
132 * The <i>Right Ascension</i> specifies the position east or west
133 * along the equator, relative to the sun's position at the vernal
134 * equinox. The <i>Declination</i> is the position north or south
135 * of the equatorial plane.
136 * <p>
137 * Note that Equatorial objects are immutable and cannot be modified
138 * once they are constructed. This allows them to be passed and returned by
139 * value without worrying about whether other code will modify them.
140 *
141 * @see CalendarAstronomer.Ecliptic
142 * @see CalendarAstronomer.Horizon
143 * @internal
144 */
145 class U_I18N_API Equatorial : public UMemory {
146 public:
147 /**
148 * Constructs an Equatorial coordinate object.
149 * <p>
150 * @param asc The right ascension, measured in radians.
151 * @param dec The declination, measured in radians.
152 * @internal
153 */
154 Equatorial(double asc = 0, double dec = 0)
155 : ascension(asc), declination(dec) { }
156
157 /**
158 * Setter
159 * @param asc The right ascension, measured in radians.
160 * @param dec The declination, measured in radians.
161 * @internal
162 */
163 void set(double asc, double dec) {
164 ascension = asc;
165 declination = dec;
166 }
167
168 /**
169 * Return a string representation of this object, with the
170 * angles measured in degrees.
171 * @internal
172 */
173 UnicodeString toString() const;
174
175 /**
176 * Return a string representation of this object with the right ascension
177 * measured in hours, minutes, and seconds.
178 * @internal
179 */
180 //String toHmsString() {
181 //return radToHms(ascension) + "," + radToDms(declination);
182 //}
183
184 /**
185 * The right ascension, in radians.
186 * This is the position east or west along the equator
187 * relative to the sun's position at the vernal equinox,
188 * with positive angles representing East.
189 * @internal
190 */
191 double ascension;
192
193 /**
194 * The declination, in radians.
195 * This is the position north or south of the equatorial plane,
196 * with positive angles representing north.
197 * @internal
198 */
199 double declination;
200 };
201
202 /**
203 * Represents the position of an object in the sky relative to
204 * the local horizon.
205 * The <i>Altitude</i> represents the object's elevation above the horizon,
206 * with objects below the horizon having a negative altitude.
207 * The <i>Azimuth</i> is the geographic direction of the object from the
208 * observer's position, with 0 representing north. The azimuth increases
209 * clockwise from north.
210 * <p>
211 * Note that Horizon objects are immutable and cannot be modified
212 * once they are constructed. This allows them to be passed and returned by
213 * value without worrying about whether other code will modify them.
214 *
215 * @see CalendarAstronomer.Ecliptic
216 * @see CalendarAstronomer.Equatorial
217 * @internal
218 */
219 class U_I18N_API Horizon : public UMemory {
220 public:
221 /**
222 * Constructs a Horizon coordinate object.
223 * <p>
224 * @param alt The altitude, measured in radians above the horizon.
225 * @param azim The azimuth, measured in radians clockwise from north.
226 * @internal
227 */
228 Horizon(double alt=0, double azim=0)
229 : altitude(alt), azimuth(azim) { }
230
231 /**
232 * Setter for Ecliptic Coordinate object
233 * @param alt The altitude, measured in radians above the horizon.
234 * @param azim The azimuth, measured in radians clockwise from north.
235 * @internal
236 */
237 void set(double alt, double azim) {
238 altitude = alt;
239 azimuth = azim;
240 }
241
242 /**
243 * Return a string representation of this object, with the
244 * angles measured in degrees.
245 * @internal
246 */
247 UnicodeString toString() const;
248
249 /**
250 * The object's altitude above the horizon, in radians.
251 * @internal
252 */
253 double altitude;
254
255 /**
256 * The object's direction, in radians clockwise from north.
257 * @internal
258 */
259 double azimuth;
260 };
261
262public:
263 //-------------------------------------------------------------------------
264 // Assorted private data used for conversions
265 //-------------------------------------------------------------------------
266
267 // My own copies of these so compilers are more likely to optimize them away
268 static const double PI;
269
270 /**
271 * The average number of solar days from one new moon to the next. This is the time
272 * it takes for the moon to return the same ecliptic longitude as the sun.
273 * It is longer than the sidereal month because the sun's longitude increases
274 * during the year due to the revolution of the earth around the sun.
275 * Approximately 29.53.
276 *
277 * @see #SIDEREAL_MONTH
278 * @internal
279 * @deprecated ICU 2.4. This class may be removed or modified.
280 */
281 static const double SYNODIC_MONTH;
282
283 //-------------------------------------------------------------------------
284 // Constructors
285 //-------------------------------------------------------------------------
286
287 /**
288 * Construct a new <code>CalendarAstronomer</code> object that is initialized to
289 * the current date and time.
290 * @internal
291 */
292 CalendarAstronomer();
293
294 /**
295 * Construct a new <code>CalendarAstronomer</code> object that is initialized to
296 * the specified date and time.
297 * @internal
298 */
299 CalendarAstronomer(UDate d);
300
301 /**
302 * Construct a new <code>CalendarAstronomer</code> object with the given
303 * latitude and longitude. The object's time is set to the current
304 * date and time.
305 * <p>
306 * @param longitude The desired longitude, in <em>degrees</em> east of
307 * the Greenwich meridian.
308 *
309 * @param latitude The desired latitude, in <em>degrees</em>. Positive
310 * values signify North, negative South.
311 *
312 * @see java.util.Date#getTime()
313 * @internal
314 */
315 CalendarAstronomer(double longitude, double latitude);
316
317 /**
318 * Destructor
319 * @internal
320 */
321 ~CalendarAstronomer();
322
323 //-------------------------------------------------------------------------
324 // Time and date getters and setters
325 //-------------------------------------------------------------------------
326
327 /**
328 * Set the current date and time of this <code>CalendarAstronomer</code> object. All
329 * astronomical calculations are performed based on this time setting.
330 *
331 * @param aTime the date and time, expressed as the number of milliseconds since
332 * 1/1/1970 0:00 GMT (Gregorian).
333 *
334 * @see #setDate
335 * @see #getTime
336 * @internal
337 */
338 void setTime(UDate aTime);
339
340
341 /**
342 * Set the current date and time of this <code>CalendarAstronomer</code> object. All
343 * astronomical calculations are performed based on this time setting.
344 *
345 * @param aTime the date and time, expressed as the number of milliseconds since
346 * 1/1/1970 0:00 GMT (Gregorian).
347 *
348 * @see #getTime
349 * @internal
350 */
351 void setDate(UDate aDate) { setTime(aDate); }
352
353 /**
354 * Set the current date and time of this <code>CalendarAstronomer</code> object. All
355 * astronomical calculations are performed based on this time setting.
356 *
357 * @param jdn the desired time, expressed as a "julian day number",
358 * which is the number of elapsed days since
359 * 1/1/4713 BC (Julian), 12:00 GMT. Note that julian day
360 * numbers start at <em>noon</em>. To get the jdn for
361 * the corresponding midnight, subtract 0.5.
362 *
363 * @see #getJulianDay
364 * @see #JULIAN_EPOCH_MS
365 * @internal
366 */
367 void setJulianDay(double jdn);
368
369 /**
370 * Get the current time of this <code>CalendarAstronomer</code> object,
371 * represented as the number of milliseconds since
372 * 1/1/1970 AD 0:00 GMT (Gregorian).
373 *
374 * @see #setTime
375 * @see #getDate
376 * @internal
377 */
378 UDate getTime();
379
380 /**
381 * Get the current time of this <code>CalendarAstronomer</code> object,
382 * expressed as a "julian day number", which is the number of elapsed
383 * days since 1/1/4713 BC (Julian), 12:00 GMT.
384 *
385 * @see #setJulianDay
386 * @see #JULIAN_EPOCH_MS
387 * @internal
388 */
389 double getJulianDay();
390
391 /**
392 * Return this object's time expressed in julian centuries:
393 * the number of centuries after 1/1/1900 AD, 12:00 GMT
394 *
395 * @see #getJulianDay
396 * @internal
397 */
398 double getJulianCentury();
399
400 /**
401 * Returns the current Greenwich sidereal time, measured in hours
402 * @internal
403 */
404 double getGreenwichSidereal();
405
406private:
407 double getSiderealOffset();
408public:
409 /**
410 * Returns the current local sidereal time, measured in hours
411 * @internal
412 */
413 double getLocalSidereal();
414
415 /**
416 * Converts local sidereal time to Universal Time.
417 *
418 * @param lst The Local Sidereal Time, in hours since sidereal midnight
419 * on this object's current date.
420 *
421 * @return The corresponding Universal Time, in milliseconds since
422 * 1 Jan 1970, GMT.
423 */
424 //private:
425 double lstToUT(double lst);
426
427 /**
428 *
429 * Convert from ecliptic to equatorial coordinates.
430 *
431 * @param ecliptic The ecliptic
432 * @param result Fillin result
433 * @return reference to result
434 */
435 Equatorial& eclipticToEquatorial(Equatorial& result, const Ecliptic& ecliptic);
436
437 /**
438 * Convert from ecliptic to equatorial coordinates.
439 *
440 * @param eclipLong The ecliptic longitude
441 * @param eclipLat The ecliptic latitude
442 *
443 * @return The corresponding point in equatorial coordinates.
444 * @internal
445 */
446 Equatorial& eclipticToEquatorial(Equatorial& result, double eclipLong, double eclipLat);
447
448 /**
449 * Convert from ecliptic longitude to equatorial coordinates.
450 *
451 * @param eclipLong The ecliptic longitude
452 *
453 * @return The corresponding point in equatorial coordinates.
454 * @internal
455 */
456 Equatorial& eclipticToEquatorial(Equatorial& result, double eclipLong) ;
457
458 /**
459 * @internal
460 */
461 Horizon& eclipticToHorizon(Horizon& result, double eclipLong) ;
462
463 //-------------------------------------------------------------------------
464 // The Sun
465 //-------------------------------------------------------------------------
466
57a6839d
A
467 /**
468 * Returns sunLongitude which may be adjusted for correctness
469 * based on the time, using a table which only has data covering
470 * gregorian years 1900-2100.
471 * <p>
472 * @param theSunLongitude the sunLongitude to be adjusted if necessary
473 * @param theTime the time for which the sunLongitude is to be adjusted
474 * @internal
475 */
476 static double adjustSunLongitude(double &theSunLongitude, UDate theTime);
477
478 /**
479 * The longitude of the sun at the time specified by theTime.
480 * This does not result in caching of any of the intermediate computations.
481 * @internal
482 */
483 static double getSunLongitudeForTime(UDate theTime);
484
374ca955
A
485 /**
486 * The longitude of the sun at the time specified by this object.
487 * The longitude is measured in radians along the ecliptic
488 * from the "first point of Aries," the point at which the ecliptic
489 * crosses the earth's equatorial plane at the vernal equinox.
490 * <p>
491 * Currently, this method uses an approximation of the two-body Kepler's
492 * equation for the earth and the sun. It does not take into account the
493 * perturbations caused by the other planets, the moon, etc.
494 * @internal
495 */
496 double getSunLongitude();
497
498 /**
499 * TODO Make this public when the entire class is package-private.
500 */
57a6839d 501 /*public*/ static void getSunLongitude(double julianDay, double &longitude, double &meanAnomaly);
374ca955
A
502
503 /**
504 * The position of the sun at this object's current date and time,
505 * in equatorial coordinates.
506 * @param result fillin for the result
507 * @internal
508 */
509 Equatorial& getSunPosition(Equatorial& result);
510
511public:
512 /**
513 * Constant representing the vernal equinox.
514 * For use with {@link #getSunTime getSunTime}.
515 * Note: In this case, "vernal" refers to the northern hemisphere's seasons.
516 * @internal
517 */
73c04bcf 518// static double VERNAL_EQUINOX();
374ca955
A
519
520 /**
521 * Constant representing the summer solstice.
522 * For use with {@link #getSunTime getSunTime}.
523 * Note: In this case, "summer" refers to the northern hemisphere's seasons.
524 * @internal
525 */
526 static double SUMMER_SOLSTICE();
527
528 /**
529 * Constant representing the autumnal equinox.
530 * For use with {@link #getSunTime getSunTime}.
531 * Note: In this case, "autumn" refers to the northern hemisphere's seasons.
532 * @internal
533 */
73c04bcf 534// static double AUTUMN_EQUINOX();
374ca955
A
535
536 /**
537 * Constant representing the winter solstice.
538 * For use with {@link #getSunTime getSunTime}.
539 * Note: In this case, "winter" refers to the northern hemisphere's seasons.
540 * @internal
541 */
46f4442e 542 static double WINTER_SOLSTICE();
374ca955
A
543
544 /**
545 * Find the next time at which the sun's ecliptic longitude will have
546 * the desired value.
547 * @internal
548 */
549 UDate getSunTime(double desired, UBool next);
550
551 /**
552 * Returns the time (GMT) of sunrise or sunset on the local date to which
553 * this calendar is currently set.
554 *
555 * NOTE: This method only works well if this object is set to a
556 * time near local noon. Because of variations between the local
557 * official time zone and the geographic longitude, the
558 * computation can flop over into an adjacent day if this object
559 * is set to a time near local midnight.
560 *
561 * @internal
562 */
563 UDate getSunRiseSet(UBool rise);
564
565 //-------------------------------------------------------------------------
566 // The Moon
567 //-------------------------------------------------------------------------
568
569 /**
570 * The position of the moon at the time set on this
571 * object, in equatorial coordinates.
572 * @internal
573 * @return const reference to internal field of calendar astronomer. Do not use outside of the lifetime of this astronomer.
574 */
575 const Equatorial& getMoonPosition();
576
577 /**
578 * The "age" of the moon at the time specified in this object.
579 * This is really the angle between the
580 * current ecliptic longitudes of the sun and the moon,
581 * measured in radians.
582 *
583 * @see #getMoonPhase
584 * @internal
585 */
586 double getMoonAge();
587
588 /**
589 * Calculate the phase of the moon at the time set in this object.
590 * The returned phase is a <code>double</code> in the range
591 * <code>0 <= phase < 1</code>, interpreted as follows:
592 * <ul>
593 * <li>0.00: New moon
594 * <li>0.25: First quarter
595 * <li>0.50: Full moon
596 * <li>0.75: Last quarter
597 * </ul>
598 *
599 * @see #getMoonAge
600 * @internal
601 */
602 double getMoonPhase();
603
604 class U_I18N_API MoonAge : public UMemory {
605 public:
606 MoonAge(double l)
607 : value(l) { }
608 void set(double l) { value = l; }
609 double value;
610 };
611
612 /**
613 * Constant representing a new moon.
614 * For use with {@link #getMoonTime getMoonTime}
615 * @internal
616 */
46f4442e 617 static const MoonAge NEW_MOON();
374ca955
A
618
619 /**
620 * Constant representing the moon's first quarter.
621 * For use with {@link #getMoonTime getMoonTime}
622 * @internal
623 */
73c04bcf 624// static const MoonAge FIRST_QUARTER();
374ca955
A
625
626 /**
627 * Constant representing a full moon.
628 * For use with {@link #getMoonTime getMoonTime}
629 * @internal
630 */
631 static const MoonAge FULL_MOON();
632
633 /**
634 * Constant representing the moon's last quarter.
635 * For use with {@link #getMoonTime getMoonTime}
636 * @internal
637 */
73c04bcf 638// static const MoonAge LAST_QUARTER();
374ca955 639
57a6839d
A
640 /**
641 * Find the next or previous time of a new moon if date is in the
642 * range handled by this function (approx gregorian 1900-2100),
643 * else return 0.
644 * <p>
645 * @param theTime the time relative to which the function should find
646 * the next or previous new moon
647 * @param next <tt>true</tt> if the next occurrance of the new moon
648 * is desired, <tt>false</tt> for the previous occurrance.
649 * @internal
650 */
651 static UDate getNewMoonTimeInRange(UDate theTime, UBool next);
652
374ca955
A
653 /**
654 * Find the next or previous time at which the Moon's ecliptic
655 * longitude will have the desired value.
656 * <p>
657 * @param desired The desired longitude.
658 * @param next <tt>true</tt> if the next occurrance of the phase
659 * is desired, <tt>false</tt> for the previous occurrance.
660 * @internal
661 */
662 UDate getMoonTime(double desired, UBool next);
663 UDate getMoonTime(const MoonAge& desired, UBool next);
664
665 /**
666 * Returns the time (GMT) of sunrise or sunset on the local date to which
667 * this calendar is currently set.
668 * @internal
669 */
670 UDate getMoonRiseSet(UBool rise);
671
672 //-------------------------------------------------------------------------
673 // Interpolation methods for finding the time at which a given event occurs
674 //-------------------------------------------------------------------------
675
676 // private
73c04bcf 677 class AngleFunc : public UMemory {
374ca955
A
678 public:
679 virtual double eval(CalendarAstronomer&) = 0;
73c04bcf 680 virtual ~AngleFunc();
374ca955
A
681 };
682 friend class AngleFunc;
683
684 UDate timeOfAngle(AngleFunc& func, double desired,
685 double periodDays, double epsilon, UBool next);
686
73c04bcf 687 class CoordFunc : public UMemory {
374ca955
A
688 public:
689 virtual void eval(Equatorial& result, CalendarAstronomer&) = 0;
73c04bcf 690 virtual ~CoordFunc();
374ca955
A
691 };
692 friend class CoordFunc;
693
694 double riseOrSet(CoordFunc& func, UBool rise,
695 double diameter, double refraction,
696 double epsilon);
697
698 //-------------------------------------------------------------------------
699 // Other utility methods
700 //-------------------------------------------------------------------------
701private:
374ca955
A
702
703 /**
704 * Return the obliquity of the ecliptic (the angle between the ecliptic
705 * and the earth's equator) at the current time. This varies due to
706 * the precession of the earth's axis.
707 *
708 * @return the obliquity of the ecliptic relative to the equator,
709 * measured in radians.
710 */
711 double eclipticObliquity();
712
713 //-------------------------------------------------------------------------
714 // Private data
715 //-------------------------------------------------------------------------
716private:
717 /**
718 * Current time in milliseconds since 1/1/1970 AD
719 * @see java.util.Date#getTime
720 */
721 UDate fTime;
722
723 /* These aren't used yet, but they'll be needed for sunset calculations
724 * and equatorial to horizon coordinate conversions
725 */
726 double fLongitude;
727 double fLatitude;
728 double fGmtOffset;
729
730 //
731 // The following fields are used to cache calculated results for improved
732 // performance. These values all depend on the current time setting
733 // of this object, so the clearCache method is provided.
734 //
735
46f4442e
A
736 double julianDay;
737 double julianCentury;
738 double sunLongitude;
739 double meanAnomalySun;
740 double moonLongitude;
741 double moonEclipLong;
742 double meanAnomalyMoon;
743 double eclipObliquity;
744 double siderealT0;
745 double siderealTime;
374ca955
A
746
747 void clearCache();
748
749 Equatorial moonPosition;
750 UBool moonPositionSet;
751
752 /**
753 * @internal
754 */
73c04bcf 755// UDate local(UDate localMillis);
374ca955
A
756};
757
758U_NAMESPACE_END
759
760struct UHashtable;
761
762U_NAMESPACE_BEGIN
763
764/**
765 * Cache of month -> julian day
766 * @internal
767 */
46f4442e 768class CalendarCache : public UMemory {
374ca955
A
769public:
770 static int32_t get(CalendarCache** cache, int32_t key, UErrorCode &status);
771 static void put(CalendarCache** cache, int32_t key, int32_t value, UErrorCode &status);
772 virtual ~CalendarCache();
773private:
774 CalendarCache(int32_t size, UErrorCode& status);
775 static void createCache(CalendarCache** cache, UErrorCode& status);
776 /**
777 * not implemented
778 */
779 CalendarCache();
780 UHashtable *fTable;
781};
782
783U_NAMESPACE_END
784
785#endif
786#endif