summaryrefslogtreecommitdiffstats
path: root/kstars/kstars/ksmoon.cpp
blob: c8e1e5c73ae69ebb996f7bc5248f4241b1d42cd0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/***************************************************************************
                          ksmoon.cpp  -  Trinity Desktop Planetarium
                             -------------------
    begin                : Sun Aug 26 2001
    copyright            : (C) 2001 by Jason Harris
    email                : kstars@30doradus.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdlib.h>
#include <math.h>

#include <tqfile.h>

#include "ksnumbers.h"
#include "ksutils.h"
#include "kssun.h"
#include "ksmoon.h"
#include "kstarsdata.h"

KSMoon::KSMoon(KStarsData *kd)
 : KSPlanetBase( kd, I18N_NOOP("Moon"), "", 3474.8 /*diameter in km*/ ) {
	BData.setAutoDelete(true);
	LRData.setAutoDelete(true);
}

KSMoon::~KSMoon() {
}

bool KSMoon::data_loaded = false;
TQPtrList<KSMoon::MoonLRData> KSMoon::LRData;
TQPtrList<KSMoon::MoonBData> KSMoon::BData;

bool KSMoon::loadData() {
	if (data_loaded) return true;

	TQString line;
	TQFile f;
	int nd, nm, nm1, nf;
	double Li, Ri, Bi; //coefficients of the sums

	if ( KSUtils::openDataFile( f, "moonLR.dat" ) ) {
		TQTextStream stream( &f );
		while ( !stream.eof() ) {
			line = stream.readLine();
			TQTextIStream instream( &line );
			instream >> nd >> nm >> nm1 >> nf >> Li >> Ri;
			LRData.append(new MoonLRData(nd, nm, nm1, nf, Li, Ri));
		}
		f.close();
	} else
		return false;


	if ( KSUtils::openDataFile( f, "moonB.dat" ) ) {
		TQTextStream stream( &f );
		while ( !stream.eof() ) {
			line = stream.readLine();
			TQTextIStream instream( &line );
			instream >> nd >> nm >> nm1 >> nf >> Bi;
			BData.append(new MoonBData(nd, nm, nm1, nf, Bi));
		}
		f.close();
	}

	data_loaded = true;
	return true;
}

bool KSMoon::findGeocentricPosition( const KSNumbers *num, const KSPlanetBase* ) {
	//Algorithms in this subroutine are taken from Chapter 45 of "Astronomical Algorithms"
  //by Jean Meeus (1991, Willmann-Bell, Inc. ISBN 0-943396-35-2.  http://www.willbell.com/math/mc1.htm)
	TQString fname, snum, line;
	TQFile f;
	double DegtoRad;
	double T, L, D, M, M1, F, E, A1, A2, A3;
	double sumL, sumR, sumB;

	DegtoRad = acos( -1.0 )/180.0;

	//Julian centuries since J2000
	T = num->julianCenturies();

	double Et = 1.0 - 0.002516*T - 0.0000074*T*T;

	//Moon's mean longitude
	L = 218.3164591 + 481267.88134236*T - 0.0013268*T*T + T*T*T/538841.0 - T*T*T*T/65194000.0;
	while ( L > 360.0 ) L -= 360.0;
	while ( L < 0.0 ) L += 360.0;
	L *= DegtoRad;
	//Moon's mean elongation
	D = 297.8502042 + 445267.1115168*T - 0.0016300*T*T + T*T*T/545868.0 - T*T*T*T/113065000.0;
	while ( D > 360.0 ) D -= 360.0;
	while ( D < 0.0 ) D += 360.0;
	D *= DegtoRad;
	//Sun's mean anomaly
  M = 357.5291092 + 35999.0502909*T - 0.0001536*T*T + T*T*T/24490000.0;
	while ( M > 360.0 ) M -= 360.0;
	while ( M < 0.0 ) M += 360.0;
	M *= DegtoRad;
	//Moon's mean anomaly
	M1= 134.9634114 + 477198.8676313*T + 0.0089970*T*T + T*T*T/69699.0 - T*T*T*T/14712000.0;
	while ( M1 > 360.0 ) M1 -= 360.0;
	while ( M1 < 0.0 ) M1 += 360.0;
	M1 *= DegtoRad;
  //Moon's argument of latitude (angle from ascending node)
	F = 93.2720993 + 483202.0175273*T - 0.0034029*T*T - T*T*T/3526000.0 + T*T*T*T/863310000.0;
	while ( F > 360.0 ) F -= 360.0;
	while ( F < 0.0 ) F += 360.0;
	F *= DegtoRad;

	A1 = 119.75 +    131.849*T;
	A2 =  53.09 + 479264.290*T;
	A3 = 313.45 + 481226.484*T;
	while ( A1 > 360.0 ) A1 -= 360.0;
	while ( A1 < 0.0 ) A1 += 360.0;
	while ( A2 > 360.0 ) A2 -= 360.0;
	while ( A2 < 0.0 ) A2 += 360.0;
	while ( A3 > 360.0 ) A3 -= 360.0;
	while ( A3 < 0.0 ) A3 += 360.0;
	A1 *= DegtoRad;
	A2 *= DegtoRad;
	A3 *= DegtoRad;

	//Calculate the series expansions stored in moonLR.txt and moonB.txt.
	//
	sumL = 0.0;
	sumR = 0.0;

	if (!loadData()) return false;

	for (MoonLRData *mlrd = LRData.first(); mlrd != 0; mlrd = LRData.next()) {

		E = 1.0;
		if ( mlrd->nm ) { //if M != 0, include changing eccentricity of Earth's orbit
			E = Et;
			if ( abs( mlrd->nm )==2 ) E = E*E; //use E^2
		}
		sumL += E*mlrd->Li*sin( mlrd->nd*D + mlrd->nm*M + mlrd->nm1*M1 + mlrd->nf*F );
		sumR += E*mlrd->Ri*cos( mlrd->nd*D + mlrd->nm*M + mlrd->nm1*M1 + mlrd->nf*F );
	}

	sumB = 0.0;
	for (MoonBData *mbd = BData.first(); mbd != 0; mbd = BData.next()) {

		E = 1.0;
		if ( mbd->nm ) { //if M != 0, include changing eccentricity of Earth's orbit
			E = Et;
			if ( abs( mbd->nm )==2 ) E = E*E; //use E^2
		}
		sumB += E*mbd->Bi*sin( mbd->nd*D + mbd->nm*M + mbd->nm1*M1 + mbd->nf*F );
	}

	//Additive terms for sumL and sumB
	sumL += ( 3958.0*sin( A1 ) + 1962.0*sin( L-F ) + 318.0*sin( A2 ) );
	sumB += ( -2235.0*sin( L ) + 382.0*sin( A3 ) + 175.0*sin( A1-F ) + 175.0*sin( A1+F ) + 127.0*sin( L-M1 ) - 115.0*sin( L+M1 ) );

	//Geocentric coordinates
	setEcLong( ( L + DegtoRad*sumL/1000000.0 ) * 180./dms::PI );  //convert radians to degrees
	setEcLat( ( DegtoRad*sumB/1000000.0 ) * 180./dms::PI );
	Rearth = ( 385000.56 + sumR/1000.0 )/AU_KM; //distance from Earth, in AU
	setAngularSize( asin(physicalSize()/Rearth/AU_KM)*60.*180./dms::PI ); //angular size in arcmin

	EclipticToEquatorial( num->obliquity() );

	//Determine position angle
	findPA( num );

	return true;
}

void KSMoon::findPhase( const KSSun *Sun ) {
	Phase.setD( ecLong()->Degrees() - Sun->ecLong()->Degrees() );
	Phase.setD( Phase.reduce().Degrees() );
	int iPhase = int( 0.1*Phase.Degrees()+0.5 );
	if (iPhase==36) iPhase = 0;
	TQString sPhase;
	sPhase = sPhase.sprintf( "%02d", iPhase );
	TQString imName = "moon" + sPhase + ".png";

	TQFile imFile;
	if ( KSUtils::openDataFile( imFile, imName ) ) {
		imFile.close();
		image0()->load( imFile.name() );
		image()->load( imFile.name() );

	}
}

TQString KSMoon::phaseName() const {
	double f = illum();
	double p = phase().Degrees();
	
	//First, handle the major phases
	if ( f > 0.99 ) return i18n( "moon phase, 100 percent illuminated", "Full moon" );
	if ( f < 0.01 ) return i18n( "moon phase, 0 percent illuminated", "New moon" );
	if ( fabs( f - 0.50 ) < 0.01 ) {
		if ( p < 180.0 ) return i18n( "moon phase, half-illuminated and growing", "First quarter" );
		else return i18n( "moon phase, half-illuminated and shrinking", "Third quarter" );
	}

	//Next, handle the more general cases
	if ( p < 90.0 ) return i18n( "moon phase between new moon and 1st quarter", "Waxing crescent" );
	else if ( p < 180.0 ) return i18n( "moon phase between 1st quarter and full moon", "Waxing gibbous" );
	else if ( p < 270.0 ) return i18n( "moon phase between full moon and 3rd quarter", "Waning gibbous" );
	else if ( p < 360.0 ) return i18n( "moon phase between 3rd quarter and new moon", "Waning crescent" );

	else return i18n( "unknown" );
}