swe4r 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/swe4r/extconf.rb +3 -0
- data/ext/swe4r/src/swemptab.c +10642 -0
- data/ext/swe4r/swe4r.c +129 -0
- data/ext/swe4r/swecl.c +4948 -0
- data/ext/swe4r/swedate.c +590 -0
- data/ext/swe4r/swedate.h +82 -0
- data/ext/swe4r/swehel.c +3445 -0
- data/ext/swe4r/swehouse.c +1727 -0
- data/ext/swe4r/swehouse.h +85 -0
- data/ext/swe4r/swejpl.c +937 -0
- data/ext/swe4r/swejpl.h +105 -0
- data/ext/swe4r/swemmoon.c +1824 -0
- data/ext/swe4r/swemplan.c +959 -0
- data/ext/swe4r/swenut2000a.h +2820 -0
- data/ext/swe4r/sweodef.h +325 -0
- data/ext/swe4r/sweph.c +6241 -0
- data/ext/swe4r/sweph.h +556 -0
- data/ext/swe4r/swephexp.h +749 -0
- data/ext/swe4r/swephlib.c +2581 -0
- data/ext/swe4r/swephlib.h +177 -0
- data/lib/swe4r.rb +2 -0
- metadata +66 -0
@@ -0,0 +1,1727 @@
|
|
1
|
+
|
2
|
+
/*******************************************************
|
3
|
+
$Header: /home/dieter/sweph/RCS/swehouse.c,v 1.74 2008/06/16 10:07:20 dieter Exp $
|
4
|
+
module swehouse.c
|
5
|
+
house and (simple) aspect calculation
|
6
|
+
|
7
|
+
************************************************************/
|
8
|
+
/* Copyright (C) 1997 - 2008 Astrodienst AG, Switzerland. All rights reserved.
|
9
|
+
|
10
|
+
License conditions
|
11
|
+
------------------
|
12
|
+
|
13
|
+
This file is part of Swiss Ephemeris.
|
14
|
+
|
15
|
+
Swiss Ephemeris is distributed with NO WARRANTY OF ANY KIND. No author
|
16
|
+
or distributor accepts any responsibility for the consequences of using it,
|
17
|
+
or for whether it serves any particular purpose or works at all, unless he
|
18
|
+
or she says so in writing.
|
19
|
+
|
20
|
+
Swiss Ephemeris is made available by its authors under a dual licensing
|
21
|
+
system. The software developer, who uses any part of Swiss Ephemeris
|
22
|
+
in his or her software, must choose between one of the two license models,
|
23
|
+
which are
|
24
|
+
a) GNU public license version 2 or later
|
25
|
+
b) Swiss Ephemeris Professional License
|
26
|
+
|
27
|
+
The choice must be made before the software developer distributes software
|
28
|
+
containing parts of Swiss Ephemeris to others, and before any public
|
29
|
+
service using the developed software is activated.
|
30
|
+
|
31
|
+
If the developer choses the GNU GPL software license, he or she must fulfill
|
32
|
+
the conditions of that license, which includes the obligation to place his
|
33
|
+
or her whole software project under the GNU GPL or a compatible license.
|
34
|
+
See http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
35
|
+
|
36
|
+
If the developer choses the Swiss Ephemeris Professional license,
|
37
|
+
he must follow the instructions as found in http://www.astro.com/swisseph/
|
38
|
+
and purchase the Swiss Ephemeris Professional Edition from Astrodienst
|
39
|
+
and sign the corresponding license contract.
|
40
|
+
|
41
|
+
The License grants you the right to use, copy, modify and redistribute
|
42
|
+
Swiss Ephemeris, but only under certain conditions described in the License.
|
43
|
+
Among other things, the License requires that the copyright notices and
|
44
|
+
this notice be preserved on all copies.
|
45
|
+
|
46
|
+
Authors of the Swiss Ephemeris: Dieter Koch and Alois Treindl
|
47
|
+
|
48
|
+
The authors of Swiss Ephemeris have no control or influence over any of
|
49
|
+
the derived works, i.e. over software or services created by other
|
50
|
+
programmers which use Swiss Ephemeris functions.
|
51
|
+
|
52
|
+
The names of the authors or of the copyright holder (Astrodienst) must not
|
53
|
+
be used for promoting any software, product or service which uses or contains
|
54
|
+
the Swiss Ephemeris. This copyright notice is the ONLY place where the
|
55
|
+
names of the authors can legally appear, except in cases where they have
|
56
|
+
given special permission in writing.
|
57
|
+
|
58
|
+
The trademarks 'Swiss Ephemeris' and 'Swiss Ephemeris inside' may be used
|
59
|
+
for promoting such software, products or services.
|
60
|
+
*/
|
61
|
+
|
62
|
+
#include "sweodef.h"
|
63
|
+
#include "swephexp.h"
|
64
|
+
#include "sweph.h"
|
65
|
+
#include "swephlib.h"
|
66
|
+
#include "swehouse.h"
|
67
|
+
#include <string.h>
|
68
|
+
|
69
|
+
#define MILLIARCSEC (1.0 / 3600000.0)
|
70
|
+
|
71
|
+
static double Asc1(double, double, double, double);
|
72
|
+
static double Asc2(double, double, double, double);
|
73
|
+
static int CalcH(
|
74
|
+
double th, double fi, double ekl, char hsy,
|
75
|
+
int iteration_count, struct houses *hsp );
|
76
|
+
static int sidereal_houses_ecl_t0(double tjde,
|
77
|
+
double armc,
|
78
|
+
double eps,
|
79
|
+
double *nutlo,
|
80
|
+
double lat,
|
81
|
+
int hsys,
|
82
|
+
double *cusp,
|
83
|
+
double *ascmc);
|
84
|
+
static int sidereal_houses_trad(double tjde,
|
85
|
+
double armc,
|
86
|
+
double eps,
|
87
|
+
double nutl,
|
88
|
+
double lat,
|
89
|
+
int hsys,
|
90
|
+
double *cusp,
|
91
|
+
double *ascmc);
|
92
|
+
static int sidereal_houses_ssypl(double tjde,
|
93
|
+
double armc,
|
94
|
+
double eps,
|
95
|
+
double *nutlo,
|
96
|
+
double lat,
|
97
|
+
int hsys,
|
98
|
+
double *cusp,
|
99
|
+
double *ascmc);
|
100
|
+
|
101
|
+
/* housasp.c
|
102
|
+
* cusps are returned in double cusp[13],
|
103
|
+
* or cusp[37] with house system 'G'.
|
104
|
+
* cusp[1...12] houses 1 - 12
|
105
|
+
* additional points are returned in ascmc[10].
|
106
|
+
* ascmc[0] = ascendant
|
107
|
+
* ascmc[1] = mc
|
108
|
+
* ascmc[2] = armc
|
109
|
+
* ascmc[3] = vertex
|
110
|
+
* ascmc[4] = equasc * "equatorial ascendant" *
|
111
|
+
* ascmc[5] = coasc1 * "co-ascendant" (W. Koch) *
|
112
|
+
* ascmc[6] = coasc2 * "co-ascendant" (M. Munkasey) *
|
113
|
+
* ascmc[7] = polasc * "polar ascendant" (M. Munkasey) *
|
114
|
+
*/
|
115
|
+
int FAR PASCAL_CONV swe_houses(double tjd_ut,
|
116
|
+
double geolat,
|
117
|
+
double geolon,
|
118
|
+
int hsys,
|
119
|
+
double *cusp,
|
120
|
+
double *ascmc)
|
121
|
+
{
|
122
|
+
int i, retc = 0;
|
123
|
+
double armc, eps, nutlo[2];
|
124
|
+
double tjde = tjd_ut + swe_deltat(tjd_ut);
|
125
|
+
eps = swi_epsiln(tjde) * RADTODEG;
|
126
|
+
swi_nutation(tjde, nutlo);
|
127
|
+
for (i = 0; i < 2; i++)
|
128
|
+
nutlo[i] *= RADTODEG;
|
129
|
+
armc = swe_degnorm(swe_sidtime0(tjd_ut, eps + nutlo[1], nutlo[0]) * 15 + geolon);
|
130
|
+
#ifdef TRACE
|
131
|
+
swi_open_trace(NULL);
|
132
|
+
if (swi_trace_count <= TRACE_COUNT_MAX) {
|
133
|
+
if (swi_fp_trace_c != NULL) {
|
134
|
+
fputs("\n/*SWE_HOUSES*/\n", swi_fp_trace_c);
|
135
|
+
fprintf(swi_fp_trace_c, "#if 0\n");
|
136
|
+
fprintf(swi_fp_trace_c, " tjd = %.9f;", tjd_ut);
|
137
|
+
fprintf(swi_fp_trace_c, " geolon = %.9f;", geolon);
|
138
|
+
fprintf(swi_fp_trace_c, " geolat = %.9f;", geolat);
|
139
|
+
fprintf(swi_fp_trace_c, " hsys = %d;\n", hsys);
|
140
|
+
fprintf(swi_fp_trace_c, " retc = swe_houses(tjd, geolat, geolon, hsys, cusp, ascmc);\n");
|
141
|
+
fprintf(swi_fp_trace_c, " /* swe_houses calls swe_houses_armc as follows: */\n");
|
142
|
+
fprintf(swi_fp_trace_c, "#endif\n");
|
143
|
+
fflush(swi_fp_trace_c);
|
144
|
+
}
|
145
|
+
}
|
146
|
+
#endif
|
147
|
+
retc = swe_houses_armc(armc, geolat, eps + nutlo[1], hsys, cusp, ascmc);
|
148
|
+
return retc;
|
149
|
+
}
|
150
|
+
|
151
|
+
/* housasp.c
|
152
|
+
* cusps are returned in double cusp[13],
|
153
|
+
* or cusp[37] with house system 'G'.
|
154
|
+
* cusp[1...12] houses 1 - 12
|
155
|
+
* additional points are returned in ascmc[10].
|
156
|
+
* ascmc[0] = ascendant
|
157
|
+
* ascmc[1] = mc
|
158
|
+
* ascmc[2] = armc
|
159
|
+
* ascmc[3] = vertex
|
160
|
+
* ascmc[4] = equasc * "equatorial ascendant" *
|
161
|
+
* ascmc[5] = coasc1 * "co-ascendant" (W. Koch) *
|
162
|
+
* ascmc[6] = coasc2 * "co-ascendant" (M. Munkasey) *
|
163
|
+
* ascmc[7] = polasc * "polar ascendant" (M. Munkasey) *
|
164
|
+
*/
|
165
|
+
int FAR PASCAL_CONV swe_houses_ex(double tjd_ut,
|
166
|
+
int32 iflag,
|
167
|
+
double geolat,
|
168
|
+
double geolon,
|
169
|
+
int hsys,
|
170
|
+
double *cusp,
|
171
|
+
double *ascmc)
|
172
|
+
{
|
173
|
+
int i, retc = 0;
|
174
|
+
double armc, eps_mean, nutlo[2];
|
175
|
+
double tjde = tjd_ut + swe_deltat(tjd_ut);
|
176
|
+
struct sid_data *sip = &swed.sidd;
|
177
|
+
int ito;
|
178
|
+
if (toupper(hsys) == 'G')
|
179
|
+
ito = 36;
|
180
|
+
else
|
181
|
+
ito = 12;
|
182
|
+
if ((iflag & SEFLG_SIDEREAL) && !swed.ayana_is_set)
|
183
|
+
swe_set_sid_mode(SE_SIDM_FAGAN_BRADLEY, 0, 0);
|
184
|
+
eps_mean = swi_epsiln(tjde) * RADTODEG;
|
185
|
+
swi_nutation(tjde, nutlo);
|
186
|
+
for (i = 0; i < 2; i++)
|
187
|
+
nutlo[i] *= RADTODEG;
|
188
|
+
#ifdef TRACE
|
189
|
+
swi_open_trace(NULL);
|
190
|
+
if (swi_trace_count <= TRACE_COUNT_MAX) {
|
191
|
+
if (swi_fp_trace_c != NULL) {
|
192
|
+
fputs("\n/*SWE_HOUSES_EX*/\n", swi_fp_trace_c);
|
193
|
+
fprintf(swi_fp_trace_c, "#if 0\n");
|
194
|
+
fprintf(swi_fp_trace_c, " tjd = %.9f;", tjd_ut);
|
195
|
+
fprintf(swi_fp_trace_c, " iflag = %d;\n", iflag);
|
196
|
+
fprintf(swi_fp_trace_c, " geolon = %.9f;", geolon);
|
197
|
+
fprintf(swi_fp_trace_c, " geolat = %.9f;", geolat);
|
198
|
+
fprintf(swi_fp_trace_c, " hsys = %d;\n", hsys);
|
199
|
+
fprintf(swi_fp_trace_c, " retc = swe_houses_ex(tjd, iflag, geolat, geolon, hsys, cusp, ascmc);\n");
|
200
|
+
fprintf(swi_fp_trace_c, " /* swe_houses calls swe_houses_armc as follows: */\n");
|
201
|
+
fprintf(swi_fp_trace_c, "#endif\n");
|
202
|
+
fflush(swi_fp_trace_c);
|
203
|
+
}
|
204
|
+
}
|
205
|
+
#endif
|
206
|
+
/*houses_to_sidereal(tjde, geolat, hsys, eps, cusp, ascmc, iflag);*/
|
207
|
+
armc = swe_degnorm(swe_sidtime0(tjd_ut, eps_mean + nutlo[1], nutlo[0]) * 15 + geolon);
|
208
|
+
if (iflag & SEFLG_SIDEREAL) {
|
209
|
+
if (sip->sid_mode & SE_SIDBIT_ECL_T0)
|
210
|
+
retc = sidereal_houses_ecl_t0(tjde, armc, eps_mean + nutlo[1], nutlo, geolat, hsys, cusp, ascmc);
|
211
|
+
else if (sip->sid_mode & SE_SIDBIT_SSY_PLANE)
|
212
|
+
retc = sidereal_houses_ssypl(tjde, armc, eps_mean + nutlo[1], nutlo, geolat, hsys, cusp, ascmc);
|
213
|
+
else
|
214
|
+
retc = sidereal_houses_trad(tjde, armc, eps_mean + nutlo[1], nutlo[0], geolat, hsys, cusp, ascmc);
|
215
|
+
} else {
|
216
|
+
retc = swe_houses_armc(armc, geolat, eps_mean + nutlo[1], hsys, cusp, ascmc);
|
217
|
+
}
|
218
|
+
if (iflag & SEFLG_RADIANS) {
|
219
|
+
for (i = 1; i <= ito; i++)
|
220
|
+
cusp[i] *= DEGTORAD;
|
221
|
+
for (i = 0; i < SE_NASCMC; i++)
|
222
|
+
ascmc[i] *= DEGTORAD;
|
223
|
+
}
|
224
|
+
return retc;
|
225
|
+
}
|
226
|
+
|
227
|
+
/*
|
228
|
+
* houses to sidereal
|
229
|
+
* ------------------
|
230
|
+
* there are two methods:
|
231
|
+
* a) the traditional one
|
232
|
+
* houses are computed tropically, then nutation and the ayanamsa
|
233
|
+
* are subtracted.
|
234
|
+
* b) the projection on the ecliptic of t0
|
235
|
+
* The house computation is then as follows:
|
236
|
+
*
|
237
|
+
* Be t the birth date and t0 the epoch at which ayanamsa = 0.
|
238
|
+
* 1. Compute the angle between the mean ecliptic at t0 and
|
239
|
+
* the true equator at t.
|
240
|
+
* The intersection point of these two circles we call the
|
241
|
+
* "auxiliary vernal point", and the angle between them the
|
242
|
+
* "auxiliary obliquity".
|
243
|
+
* 2. Compute the distance of the auxiliary vernal point from the
|
244
|
+
* vernal point at t. (this is a section on the equator)
|
245
|
+
* 3. subtract this value from the armc of t = aux. armc.
|
246
|
+
* 4. Compute the axes and houses for this aux. armc and aux. obliquity.
|
247
|
+
* 5. Compute the distance between the auxiliary vernal point and the
|
248
|
+
* vernal point at t0 (this is the ayanamsa at t, measured on the
|
249
|
+
* ecliptic of t0)
|
250
|
+
* 6. subtract this distance from all house cusps.
|
251
|
+
* 7. subtract ayanamsa_t0 from all house cusps.
|
252
|
+
*/
|
253
|
+
static int sidereal_houses_ecl_t0(double tjde,
|
254
|
+
double armc,
|
255
|
+
double eps,
|
256
|
+
double *nutlo,
|
257
|
+
double lat,
|
258
|
+
int hsys,
|
259
|
+
double *cusp,
|
260
|
+
double *ascmc)
|
261
|
+
{
|
262
|
+
int i, j, retc = OK;
|
263
|
+
double x[6], xvpx[6], x2[6], epst0, xnorm[6];
|
264
|
+
double rxy, rxyz, c2, epsx, sgn, fac, dvpx, dvpxe;
|
265
|
+
double armcx;
|
266
|
+
struct sid_data *sip = &swed.sidd;
|
267
|
+
int ito;
|
268
|
+
if (toupper(hsys) == 'G')
|
269
|
+
ito = 36;
|
270
|
+
else
|
271
|
+
ito = 12;
|
272
|
+
/* epsilon at t0 */
|
273
|
+
epst0 = swi_epsiln(sip->t0);
|
274
|
+
/* cartesian coordinates of an imaginary moving body on the
|
275
|
+
* the mean ecliptic of t0; we take the vernal point: */
|
276
|
+
x[0] = x[4] = 1;
|
277
|
+
x[1] = x[2] = x[3] = x[5] = 0;
|
278
|
+
/* to equator */
|
279
|
+
swi_coortrf(x, x, -epst0);
|
280
|
+
swi_coortrf(x+3, x+3, -epst0);
|
281
|
+
/* to tjd_et */
|
282
|
+
swi_precess(x, sip->t0, J_TO_J2000);
|
283
|
+
swi_precess(x, tjde, J2000_TO_J);
|
284
|
+
swi_precess(x+3, sip->t0, J_TO_J2000);
|
285
|
+
swi_precess(x+3, tjde, J2000_TO_J);
|
286
|
+
/* to true equator of tjd_et */
|
287
|
+
swi_coortrf(x, x, (eps - nutlo[1]) * DEGTORAD);
|
288
|
+
swi_coortrf(x+3, x+3, (eps - nutlo[1]) * DEGTORAD);
|
289
|
+
swi_cartpol_sp(x, x);
|
290
|
+
x[0] += nutlo[0] * DEGTORAD;
|
291
|
+
swi_polcart_sp(x, x);
|
292
|
+
swi_coortrf(x, x, -eps * DEGTORAD);
|
293
|
+
swi_coortrf(x+3, x+3, -eps * DEGTORAD);
|
294
|
+
/* now, we have the moving point precessed to tjd_et.
|
295
|
+
* next, we compute the auxiliary epsilon: */
|
296
|
+
swi_cross_prod(x, x+3, xnorm);
|
297
|
+
rxy = xnorm[0] * xnorm[0] + xnorm[1] * xnorm[1];
|
298
|
+
c2 = (rxy + xnorm[2] * xnorm[2]);
|
299
|
+
rxyz = sqrt(c2);
|
300
|
+
rxy = sqrt(rxy);
|
301
|
+
epsx = asin(rxy / rxyz) * RADTODEG; /* 1a */
|
302
|
+
/* auxiliary vernal point */
|
303
|
+
if (fabs(x[5]) < 1e-15)
|
304
|
+
x[5] = 1e-15;
|
305
|
+
fac = x[2] / x[5];
|
306
|
+
sgn = x[5] / fabs(x[5]);
|
307
|
+
for (j = 0; j <= 2; j++)
|
308
|
+
xvpx[j] = (x[j] - fac * x[j+3]) * sgn; /* 1b */
|
309
|
+
/* distance of the auxiliary vernal point from
|
310
|
+
* the zero point at tjd_et (a section on the equator): */
|
311
|
+
swi_cartpol(xvpx, x2);
|
312
|
+
dvpx = x2[0] * RADTODEG; /* 2 */
|
313
|
+
/* auxiliary armc */
|
314
|
+
armcx = swe_degnorm(armc - dvpx); /* 3 */
|
315
|
+
/* compute axes and houses: */
|
316
|
+
retc = swe_houses_armc(armcx, lat, epsx, hsys, cusp, ascmc); /* 4 */
|
317
|
+
/* distance between auxiliary vernal point and
|
318
|
+
* vernal point of t0 (a section on the sidereal plane) */
|
319
|
+
dvpxe = acos(swi_dot_prod_unit(x, xvpx)) * RADTODEG; /* 5 */
|
320
|
+
if (tjde < sip->t0)
|
321
|
+
dvpxe = -dvpxe;
|
322
|
+
for (i = 1; i <= ito; i++) /* 6, 7 */
|
323
|
+
cusp[i] = swe_degnorm(cusp[i] - dvpxe - sip->ayan_t0);
|
324
|
+
for (i = 0; i <= SE_NASCMC; i++)
|
325
|
+
ascmc[i] = swe_degnorm(ascmc[i] - dvpxe - sip->ayan_t0);
|
326
|
+
return retc;
|
327
|
+
}
|
328
|
+
|
329
|
+
/*
|
330
|
+
* Be t the birth date and t0 the epoch at which ayanamsa = 0.
|
331
|
+
* 1. Compute the angle between the solar system rotation plane and
|
332
|
+
* the true equator at t.
|
333
|
+
* The intersection point of these two circles we call the
|
334
|
+
* "auxiliary vernal point", and the angle between them the
|
335
|
+
* "auxiliary obliquity".
|
336
|
+
* 2. Compute the distance of the auxiliary vernal point from the
|
337
|
+
* zero point at t. (this is a section on the equator)
|
338
|
+
* 3. subtract this value from the armc of t = aux. armc.
|
339
|
+
* 4. Compute the axes and houses for this aux. armc and aux. obliquity.
|
340
|
+
* 5. Compute the distance between the auxiliary vernal point at t
|
341
|
+
* and the zero point of the solar system plane J2000
|
342
|
+
* (a section measured on the solar system plane)
|
343
|
+
* 6. subtract this distance from all house cusps.
|
344
|
+
* 7. compute the ayanamsa of J2000 on the solar system plane,
|
345
|
+
* referred to t0
|
346
|
+
* 8. subtract ayanamsa_t0 from all house cusps.
|
347
|
+
* 9. subtract ayanamsa_2000 from all house cusps.
|
348
|
+
*/
|
349
|
+
static int sidereal_houses_ssypl(double tjde,
|
350
|
+
double armc,
|
351
|
+
double eps,
|
352
|
+
double *nutlo,
|
353
|
+
double lat,
|
354
|
+
int hsys,
|
355
|
+
double *cusp,
|
356
|
+
double *ascmc)
|
357
|
+
{
|
358
|
+
int i, j, retc = OK;
|
359
|
+
double x[6], x0[6], xvpx[6], x2[6], epst0, xnorm[6];
|
360
|
+
double rxy, rxyz, c2, epsx, eps2000, sgn, fac, dvpx, dvpxe, x00;
|
361
|
+
double armcx;
|
362
|
+
struct sid_data *sip = &swed.sidd;
|
363
|
+
int ito;
|
364
|
+
if (toupper(hsys) == 'G')
|
365
|
+
ito = 36;
|
366
|
+
else
|
367
|
+
ito = 12;
|
368
|
+
/* epsilon at t0 */
|
369
|
+
epst0 = swi_epsiln(sip->t0);
|
370
|
+
eps2000 = swi_epsiln(J2000);
|
371
|
+
/* cartesian coordinates of the zero point on the
|
372
|
+
* the solar system rotation plane */
|
373
|
+
x[0] = x[4] = 1;
|
374
|
+
x[1] = x[2] = x[3] = x[5] = 0;
|
375
|
+
/* to ecliptic 2000 */
|
376
|
+
swi_coortrf(x, x, -SSY_PLANE_INCL);
|
377
|
+
swi_coortrf(x+3, x+3, -SSY_PLANE_INCL);
|
378
|
+
swi_cartpol_sp(x, x);
|
379
|
+
x[0] += SSY_PLANE_NODE_E2000;
|
380
|
+
swi_polcart_sp(x, x);
|
381
|
+
/* to equator 2000 */
|
382
|
+
swi_coortrf(x, x, -eps2000);
|
383
|
+
swi_coortrf(x+3, x+3, -eps2000);
|
384
|
+
/* to mean equator of t */
|
385
|
+
swi_precess(x, tjde, J2000_TO_J);
|
386
|
+
swi_precess(x+3, tjde, J2000_TO_J);
|
387
|
+
/* to true equator of t */
|
388
|
+
swi_coortrf(x, x, (eps - nutlo[1]) * DEGTORAD);
|
389
|
+
swi_coortrf(x+3, x+3, (eps - nutlo[1]) * DEGTORAD);
|
390
|
+
swi_cartpol_sp(x, x);
|
391
|
+
x[0] += nutlo[0] * DEGTORAD;
|
392
|
+
swi_polcart_sp(x, x);
|
393
|
+
swi_coortrf(x, x, -eps * DEGTORAD);
|
394
|
+
swi_coortrf(x+3, x+3, -eps * DEGTORAD);
|
395
|
+
/* now, we have the moving point precessed to tjd_et.
|
396
|
+
* next, we compute the auxiliary epsilon: */
|
397
|
+
swi_cross_prod(x, x+3, xnorm);
|
398
|
+
rxy = xnorm[0] * xnorm[0] + xnorm[1] * xnorm[1];
|
399
|
+
c2 = (rxy + xnorm[2] * xnorm[2]);
|
400
|
+
rxyz = sqrt(c2);
|
401
|
+
rxy = sqrt(rxy);
|
402
|
+
epsx = asin(rxy / rxyz) * RADTODEG; /* 1a */
|
403
|
+
/* auxiliary vernal point */
|
404
|
+
if (fabs(x[5]) < 1e-15)
|
405
|
+
x[5] = 1e-15;
|
406
|
+
fac = x[2] / x[5];
|
407
|
+
sgn = x[5] / fabs(x[5]);
|
408
|
+
for (j = 0; j <= 2; j++)
|
409
|
+
xvpx[j] = (x[j] - fac * x[j+3]) * sgn; /* 1b */
|
410
|
+
/* distance of the auxiliary vernal point from
|
411
|
+
* mean vernal point at tjd_et (a section on the equator): */
|
412
|
+
swi_cartpol(xvpx, x2);
|
413
|
+
dvpx = x2[0] * RADTODEG; /* 2 */
|
414
|
+
/* auxiliary armc */
|
415
|
+
armcx = swe_degnorm(armc - dvpx); /* 3 */
|
416
|
+
/* compute axes and houses: */
|
417
|
+
retc = swe_houses_armc(armcx, lat, epsx, hsys, cusp, ascmc); /* 4 */
|
418
|
+
/* distance between the auxiliary vernal point at t and
|
419
|
+
* the sidereal zero point of 2000 at t
|
420
|
+
* (a section on the sidereal plane).
|
421
|
+
*/
|
422
|
+
dvpxe = acos(swi_dot_prod_unit(x, xvpx)) * RADTODEG; /* 5 */
|
423
|
+
/* (always positive for dates after 5400 bc) */
|
424
|
+
dvpxe -= SSY_PLANE_NODE * RADTODEG;
|
425
|
+
/* ayanamsa between t0 and J2000, measured on solar system plane: */
|
426
|
+
/* position of zero point of t0 */
|
427
|
+
x0[0] = 1;
|
428
|
+
x0[1] = x0[2] = 0;
|
429
|
+
/* zero point of t0 in J2000 system */
|
430
|
+
if (sip->t0 != J2000)
|
431
|
+
swi_precess(x0, sip->t0, J_TO_J2000);
|
432
|
+
/* zero point to ecliptic 2000 */
|
433
|
+
swi_coortrf(x0, x0, eps2000);
|
434
|
+
/* to solar system plane */
|
435
|
+
swi_cartpol(x0, x0);
|
436
|
+
x0[0] -= SSY_PLANE_NODE_E2000;
|
437
|
+
swi_polcart(x0, x0);
|
438
|
+
swi_coortrf(x0, x0, SSY_PLANE_INCL);
|
439
|
+
swi_cartpol(x0, x0);
|
440
|
+
x0[0] += SSY_PLANE_NODE;
|
441
|
+
x00 = x0[0] * RADTODEG; /* 7 */
|
442
|
+
for (i = 1; i <= ito; i++) /* 6, 8, 9 */
|
443
|
+
cusp[i] = swe_degnorm(cusp[i] - dvpxe - sip->ayan_t0 - x00);
|
444
|
+
for (i = 0; i <= SE_NASCMC; i++)
|
445
|
+
ascmc[i] = swe_degnorm(ascmc[i] - dvpxe - sip->ayan_t0 - x00);
|
446
|
+
return retc;
|
447
|
+
}
|
448
|
+
|
449
|
+
/* common simplified procedure */
|
450
|
+
static int sidereal_houses_trad(double tjde,
|
451
|
+
double armc,
|
452
|
+
double eps,
|
453
|
+
double nutl,
|
454
|
+
double lat,
|
455
|
+
int hsys,
|
456
|
+
double *cusp,
|
457
|
+
double *ascmc)
|
458
|
+
{
|
459
|
+
int i, retc = OK;
|
460
|
+
double ay;
|
461
|
+
int ito;
|
462
|
+
int ihs = toupper(hsys);
|
463
|
+
int ihs2 = ihs;
|
464
|
+
ay = swe_get_ayanamsa(tjde);
|
465
|
+
if (ihs == 'G')
|
466
|
+
ito = 36;
|
467
|
+
else
|
468
|
+
ito = 12;
|
469
|
+
if (ihs == 'W') /* whole sign houses: treat as 'E' and fix later */
|
470
|
+
ihs2 = 'E';
|
471
|
+
retc = swe_houses_armc(armc, lat, eps, ihs2, cusp, ascmc);
|
472
|
+
for (i = 1; i <= ito; i++) {
|
473
|
+
cusp[i] = swe_degnorm(cusp[i] - ay - nutl);
|
474
|
+
if (ihs == 'W') /* whole sign houses */
|
475
|
+
cusp[i] -= fmod(cusp[i], 30);
|
476
|
+
}
|
477
|
+
for (i = 0; i < SE_NASCMC; i++) {
|
478
|
+
if (i == 2) /* armc */
|
479
|
+
continue;
|
480
|
+
ascmc[i] = swe_degnorm(ascmc[i] - ay - nutl);
|
481
|
+
}
|
482
|
+
return retc;
|
483
|
+
}
|
484
|
+
|
485
|
+
/*
|
486
|
+
* this function is required for very special computations
|
487
|
+
* where no date is given for house calculation,
|
488
|
+
* e.g. for composite charts or progressive charts.
|
489
|
+
* cusps are returned in double cusp[13],
|
490
|
+
* or cusp[37] with house system 'G'.
|
491
|
+
* cusp[1...12] houses 1 - 12
|
492
|
+
* additional points are returned in ascmc[10].
|
493
|
+
* ascmc[0] = ascendant
|
494
|
+
* ascmc[1] = mc
|
495
|
+
* ascmc[2] = armc
|
496
|
+
* ascmc[3] = vertex
|
497
|
+
* ascmc[4] = equasc * "equatorial ascendant" *
|
498
|
+
* ascmc[5] = coasc1 * "co-ascendant" (W. Koch) *
|
499
|
+
* ascmc[6] = coasc2 * "co-ascendant" (M. Munkasey) *
|
500
|
+
* ascmc[7] = polasc * "polar ascendant" (M. Munkasey) *
|
501
|
+
*/
|
502
|
+
int FAR PASCAL_CONV swe_houses_armc(
|
503
|
+
double armc,
|
504
|
+
double geolat,
|
505
|
+
double eps,
|
506
|
+
int hsys,
|
507
|
+
double *cusp,
|
508
|
+
double *ascmc)
|
509
|
+
{
|
510
|
+
struct houses h;
|
511
|
+
int i, retc = 0;
|
512
|
+
int ito;
|
513
|
+
if (toupper(hsys) == 'G')
|
514
|
+
ito = 36;
|
515
|
+
else
|
516
|
+
ito = 12;
|
517
|
+
armc = swe_degnorm(armc);
|
518
|
+
retc = CalcH(armc,
|
519
|
+
geolat,
|
520
|
+
eps,
|
521
|
+
(char)hsys, 2, &h);
|
522
|
+
cusp[0] = 0;
|
523
|
+
for (i = 1; i <= ito; i++) {
|
524
|
+
cusp[i] = h.cusp[i];
|
525
|
+
}
|
526
|
+
ascmc[0] = h.ac; /* Asc */
|
527
|
+
ascmc[1] = h.mc; /* Mid */
|
528
|
+
ascmc[2] = armc;
|
529
|
+
ascmc[3] = h.vertex;
|
530
|
+
ascmc[4] = h.equasc;
|
531
|
+
ascmc[5] = h.coasc1; /* "co-ascendant" (W. Koch) */
|
532
|
+
ascmc[6] = h.coasc2; /* "co-ascendant" (M. Munkasey) */
|
533
|
+
ascmc[7] = h.polasc; /* "polar ascendant" (M. Munkasey) */
|
534
|
+
for (i = SE_NASCMC; i < 10; i++)
|
535
|
+
ascmc[i] = 0;
|
536
|
+
#ifdef TRACE
|
537
|
+
swi_open_trace(NULL);
|
538
|
+
if (swi_trace_count <= TRACE_COUNT_MAX) {
|
539
|
+
if (swi_fp_trace_c != NULL) {
|
540
|
+
fputs("\n/*SWE_HOUSES_ARMC*/\n", swi_fp_trace_c);
|
541
|
+
fprintf(swi_fp_trace_c, " armc = %.9f;", armc);
|
542
|
+
fprintf(swi_fp_trace_c, " geolat = %.9f;", geolat);
|
543
|
+
fprintf(swi_fp_trace_c, " eps = %.9f;", eps);
|
544
|
+
fprintf(swi_fp_trace_c, " hsys = %d;\n", hsys);
|
545
|
+
fprintf(swi_fp_trace_c, " retc = swe_houses_armc(armc, geolat, eps, hsys, cusp, ascmc);\n");
|
546
|
+
fputs(" printf(\"swe_houses_armc: %f\\t%f\\t%f\\t%c\\t\\n\", ", swi_fp_trace_c);
|
547
|
+
fputs(" armc, geolat, eps, hsys);\n", swi_fp_trace_c);
|
548
|
+
fputs(" printf(\"retc = %d\\n\", retc);\n", swi_fp_trace_c);
|
549
|
+
fputs(" printf(\"cusp:\\n\");\n", swi_fp_trace_c);
|
550
|
+
fputs(" for (i = 0; i < 12; i++)\n", swi_fp_trace_c);
|
551
|
+
fputs(" printf(\" %d\\t%f\\n\", i, cusp[i]);\n", swi_fp_trace_c);
|
552
|
+
fputs(" printf(\"ascmc:\\n\");\n", swi_fp_trace_c);
|
553
|
+
fputs(" for (i = 0; i < 10; i++)\n", swi_fp_trace_c);
|
554
|
+
fputs(" printf(\" %d\\t%f\\n\", i, ascmc[i]);\n", swi_fp_trace_c);
|
555
|
+
fflush(swi_fp_trace_c);
|
556
|
+
}
|
557
|
+
if (swi_fp_trace_out != NULL) {
|
558
|
+
fprintf(swi_fp_trace_out, "swe_houses_armc: %f\t%f\t%f\t%c\t\n", armc, geolat, eps, hsys);
|
559
|
+
fprintf(swi_fp_trace_out, "retc = %d\n", retc);
|
560
|
+
fputs("cusp:\n", swi_fp_trace_out);
|
561
|
+
for (i = 0; i < 12; i++)
|
562
|
+
fprintf(swi_fp_trace_out, " %d\t%f\n", i, cusp[i]);
|
563
|
+
fputs("ascmc:\n", swi_fp_trace_out);
|
564
|
+
for (i = 0; i < 10; i++)
|
565
|
+
fprintf(swi_fp_trace_out, " %d\t%f\n", i, ascmc[i]);
|
566
|
+
fflush(swi_fp_trace_out);
|
567
|
+
}
|
568
|
+
}
|
569
|
+
#endif
|
570
|
+
#if 0
|
571
|
+
/* for test of swe_house_pos().
|
572
|
+
* 1st house will be 0, second 30, etc. */
|
573
|
+
for (i = 1; i <=12; i++) {
|
574
|
+
double x[6];
|
575
|
+
x[0] = cusp[i]; x[1] = 0; x[2] = 1;
|
576
|
+
cusp[i] = (swe_house_pos(armc, geolat, eps, hsys, x, NULL) - 1) * 30;
|
577
|
+
}
|
578
|
+
#endif
|
579
|
+
return retc;
|
580
|
+
}
|
581
|
+
|
582
|
+
static int CalcH(
|
583
|
+
double th, double fi, double ekl, char hsy,
|
584
|
+
int iteration_count, struct houses *hsp )
|
585
|
+
/* *********************************************************
|
586
|
+
* Arguments: th = sidereal time (angle 0..360 degrees
|
587
|
+
* hsy = letter code for house system;
|
588
|
+
* A equal
|
589
|
+
* E equal
|
590
|
+
* B Alcabitius
|
591
|
+
* C Campanus
|
592
|
+
* H horizon / azimut
|
593
|
+
* K Koch
|
594
|
+
* O Porphyry
|
595
|
+
* P Placidus
|
596
|
+
* R Regiomontanus
|
597
|
+
* V equal Vehlow
|
598
|
+
* W equal, whole sign
|
599
|
+
* X axial rotation system/ Meridian houses
|
600
|
+
* G 36 Gauquelin sectors
|
601
|
+
* U Krusinski-Pisa
|
602
|
+
* fi = geographic latitude
|
603
|
+
* ekl = obliquity of the ecliptic
|
604
|
+
* iteration_count = number of iterations in
|
605
|
+
* Placidus calculation; can be 1 or 2.
|
606
|
+
* *********************************************************
|
607
|
+
* Koch and Placidus don't work in the polar circle.
|
608
|
+
* We swap MC/IC so that MC is always before AC in the zodiac
|
609
|
+
* We than divide the quadrants into 3 equal parts.
|
610
|
+
* *********************************************************
|
611
|
+
* All angles are expressed in degrees.
|
612
|
+
* Special trigonometric functions sind, cosd etc. are
|
613
|
+
* implemented for arguments in degrees.
|
614
|
+
***********************************************************/
|
615
|
+
{
|
616
|
+
double tane, tanfi, cosfi, tant, sina, cosa, th2;
|
617
|
+
double a, c, f, fh1, fh2, xh1, xh2, rectasc, ad3, acmc, vemc;
|
618
|
+
int i, ih, ih2, retc = OK;
|
619
|
+
double sine, cose;
|
620
|
+
double x[3], krHorizonLon; /* BK 14.02.2006 */
|
621
|
+
cose = cosd(ekl);
|
622
|
+
sine = sind(ekl);
|
623
|
+
tane = tand(ekl);
|
624
|
+
/* north and south poles */
|
625
|
+
if (fabs(fabs(fi) - 90) < VERY_SMALL) {
|
626
|
+
if (fi < 0)
|
627
|
+
fi = -90 + VERY_SMALL;
|
628
|
+
else
|
629
|
+
fi = 90 - VERY_SMALL;
|
630
|
+
}
|
631
|
+
tanfi = tand(fi);
|
632
|
+
/* mc */
|
633
|
+
if (fabs(th - 90) > VERY_SMALL
|
634
|
+
&& fabs(th - 270) > VERY_SMALL) {
|
635
|
+
tant = tand(th);
|
636
|
+
hsp->mc = atand(tant / cose);
|
637
|
+
if (th > 90 && th <= 270)
|
638
|
+
hsp->mc = swe_degnorm(hsp->mc + 180);
|
639
|
+
} else {
|
640
|
+
if (fabs(th - 90) <= VERY_SMALL)
|
641
|
+
hsp->mc = 90;
|
642
|
+
else
|
643
|
+
hsp->mc = 270;
|
644
|
+
} /* if */
|
645
|
+
hsp->mc = swe_degnorm(hsp->mc);
|
646
|
+
/* ascendant */
|
647
|
+
hsp->ac = Asc1 (th + 90, fi, sine, cose);
|
648
|
+
hsp->cusp[1] = hsp->ac;
|
649
|
+
hsp->cusp[10] = hsp->mc;
|
650
|
+
if (hsy > 95) hsy = (char) (hsy - 32);/* translate into capital letter */
|
651
|
+
switch (hsy) {
|
652
|
+
case 'A': /* equal houses */
|
653
|
+
case 'E':
|
654
|
+
/*
|
655
|
+
* within polar circle we swap AC/DC if AC is on wrong side
|
656
|
+
*/
|
657
|
+
acmc = swe_difdeg2n(hsp->ac, hsp->mc);
|
658
|
+
if (acmc < 0) {
|
659
|
+
hsp->ac = swe_degnorm(hsp->ac + 180);
|
660
|
+
hsp->cusp[1] = hsp->ac;
|
661
|
+
}
|
662
|
+
for (i = 2; i <=12; i++)
|
663
|
+
hsp->cusp [i] = swe_degnorm(hsp->cusp [1] + (i-1) * 30);
|
664
|
+
break;
|
665
|
+
case 'C': /* Campanus houses and Horizon or Azimut system */
|
666
|
+
case 'H':
|
667
|
+
if (hsy == 'H') {
|
668
|
+
if (fi > 0)
|
669
|
+
fi = 90 - fi;
|
670
|
+
else
|
671
|
+
fi = -90 - fi;
|
672
|
+
/* equator */
|
673
|
+
if (fabs(fabs(fi) - 90) < VERY_SMALL) {
|
674
|
+
if (fi < 0)
|
675
|
+
fi = -90 + VERY_SMALL;
|
676
|
+
else
|
677
|
+
fi = 90 - VERY_SMALL;
|
678
|
+
}
|
679
|
+
th = swe_degnorm(th + 180);
|
680
|
+
}
|
681
|
+
fh1 = asind(sind (fi) / 2);
|
682
|
+
fh2 = asind(sqrt (3.0) / 2 * sind(fi));
|
683
|
+
cosfi = cosd(fi);
|
684
|
+
if (fabs(cosfi) == 0) { /* '==' should be save! */
|
685
|
+
if (fi > 0)
|
686
|
+
xh1 = xh2 = 90; /* cosfi = VERY_SMALL; */
|
687
|
+
else
|
688
|
+
xh1 = xh2 = 270; /* cosfi = -VERY_SMALL; */
|
689
|
+
} else {
|
690
|
+
xh1 = atand(sqrt (3.0) / cosfi);
|
691
|
+
xh2 = atand(1 / sqrt (3.0) / cosfi);
|
692
|
+
}
|
693
|
+
hsp->cusp [11] = Asc1 (th + 90 - xh1, fh1, sine, cose);
|
694
|
+
hsp->cusp [12] = Asc1 (th + 90 - xh2, fh2, sine, cose);
|
695
|
+
if (hsy == 'H')
|
696
|
+
hsp->cusp [1] = Asc1 (th + 90, fi, sine, cose);
|
697
|
+
hsp->cusp [2] = Asc1 (th + 90 + xh2, fh2, sine, cose);
|
698
|
+
hsp->cusp [3] = Asc1 (th + 90 + xh1, fh1, sine, cose);
|
699
|
+
/* within polar circle, when mc sinks below horizon and
|
700
|
+
* ascendant changes to western hemisphere, all cusps
|
701
|
+
* must be added 180 degrees.
|
702
|
+
* houses will be in clockwise direction */
|
703
|
+
if (fabs(fi) >= 90 - ekl) { /* within polar circle */
|
704
|
+
acmc = swe_difdeg2n(hsp->ac, hsp->mc);
|
705
|
+
if (acmc < 0) {
|
706
|
+
hsp->ac = swe_degnorm(hsp->ac + 180);
|
707
|
+
hsp->mc = swe_degnorm(hsp->mc + 180);
|
708
|
+
for (i = 1; i <= 12; i++)
|
709
|
+
hsp->cusp[i] = swe_degnorm(hsp->cusp[i] + 180);
|
710
|
+
}
|
711
|
+
}
|
712
|
+
if (hsy == 'H') {
|
713
|
+
for (i = 1; i <= 3; i++)
|
714
|
+
hsp->cusp[i] = swe_degnorm(hsp->cusp[i] + 180);
|
715
|
+
for (i = 11; i <= 12; i++)
|
716
|
+
hsp->cusp[i] = swe_degnorm(hsp->cusp[i] + 180);
|
717
|
+
/* restore fi and th */
|
718
|
+
if (fi > 0)
|
719
|
+
fi = 90 - fi;
|
720
|
+
else
|
721
|
+
fi = -90 - fi;
|
722
|
+
th = swe_degnorm(th + 180);
|
723
|
+
}
|
724
|
+
break;
|
725
|
+
case 'K': /* Koch houses */
|
726
|
+
if (fabs(fi) >= 90 - ekl) { /* within polar circle */
|
727
|
+
retc = ERR;
|
728
|
+
goto porphyry;
|
729
|
+
}
|
730
|
+
sina = sind(hsp->mc) * sine / cosd(fi);
|
731
|
+
if (sina > 1) sina = 1;
|
732
|
+
if (sina < -1) sina = -1;
|
733
|
+
cosa = sqrt(1 - sina * sina); /* always >> 0 */
|
734
|
+
c = atand(tanfi / cosa);
|
735
|
+
ad3 = asind(sind(c) * sina) / 3.0;
|
736
|
+
hsp->cusp [11] = Asc1 (th + 30 - 2 * ad3, fi, sine, cose);
|
737
|
+
hsp->cusp [12] = Asc1 (th + 60 - ad3, fi, sine, cose);
|
738
|
+
hsp->cusp [2] = Asc1 (th + 120 + ad3, fi, sine, cose);
|
739
|
+
hsp->cusp [3] = Asc1 (th + 150 + 2 * ad3, fi, sine, cose);
|
740
|
+
break;
|
741
|
+
case 'O': /* Porphyry houses */
|
742
|
+
porphyry:
|
743
|
+
/*
|
744
|
+
* within polar circle we swap AC/DC if AC is on wrong side
|
745
|
+
*/
|
746
|
+
acmc = swe_difdeg2n(hsp->ac, hsp->mc);
|
747
|
+
if (acmc < 0) {
|
748
|
+
hsp->ac = swe_degnorm(hsp->ac + 180);
|
749
|
+
hsp->cusp[1] = hsp->ac;
|
750
|
+
acmc = swe_difdeg2n(hsp->ac, hsp->mc);
|
751
|
+
}
|
752
|
+
hsp->cusp [2] = swe_degnorm(hsp->ac + (180 - acmc) / 3);
|
753
|
+
hsp->cusp [3] = swe_degnorm(hsp->ac + (180 - acmc) / 3 * 2);
|
754
|
+
hsp->cusp [11] = swe_degnorm(hsp->mc + acmc / 3);
|
755
|
+
hsp->cusp [12] = swe_degnorm(hsp->mc + acmc / 3 * 2);
|
756
|
+
break;
|
757
|
+
case 'R': /* Regiomontanus houses */
|
758
|
+
fh1 = atand (tanfi * 0.5);
|
759
|
+
fh2 = atand (tanfi * cosd(30));
|
760
|
+
hsp->cusp [11] = Asc1 (30 + th, fh1, sine, cose);
|
761
|
+
hsp->cusp [12] = Asc1 (60 + th, fh2, sine, cose);
|
762
|
+
hsp->cusp [2] = Asc1 (120 + th, fh2, sine, cose);
|
763
|
+
hsp->cusp [3] = Asc1 (150 + th, fh1, sine, cose);
|
764
|
+
/* within polar circle, when mc sinks below horizon and
|
765
|
+
* ascendant changes to western hemisphere, all cusps
|
766
|
+
* must be added 180 degrees.
|
767
|
+
* houses will be in clockwise direction */
|
768
|
+
if (fabs(fi) >= 90 - ekl) { /* within polar circle */
|
769
|
+
acmc = swe_difdeg2n(hsp->ac, hsp->mc);
|
770
|
+
if (acmc < 0) {
|
771
|
+
hsp->ac = swe_degnorm(hsp->ac + 180);
|
772
|
+
hsp->mc = swe_degnorm(hsp->mc + 180);
|
773
|
+
for (i = 1; i <= 12; i++)
|
774
|
+
hsp->cusp[i] = swe_degnorm(hsp->cusp[i] + 180);
|
775
|
+
}
|
776
|
+
}
|
777
|
+
break;
|
778
|
+
case 'T': /* 'topocentric' houses */
|
779
|
+
fh1 = atand (tanfi / 3.0);
|
780
|
+
fh2 = atand (tanfi * 2.0 / 3.0);
|
781
|
+
hsp->cusp [11] = Asc1 (30 + th, fh1, sine, cose);
|
782
|
+
hsp->cusp [12] = Asc1 (60 + th, fh2, sine, cose);
|
783
|
+
hsp->cusp [2] = Asc1 (120 + th, fh2, sine, cose);
|
784
|
+
hsp->cusp [3] = Asc1 (150 + th, fh1, sine, cose);
|
785
|
+
/* within polar circle, when mc sinks below horizon and
|
786
|
+
* ascendant changes to western hemisphere, all cusps
|
787
|
+
* must be added 180 degrees.
|
788
|
+
* houses will be in clockwise direction */
|
789
|
+
if (fabs(fi) >= 90 - ekl) { /* within polar circle */
|
790
|
+
acmc = swe_difdeg2n(hsp->ac, hsp->mc);
|
791
|
+
if (acmc < 0) {
|
792
|
+
hsp->ac = swe_degnorm(hsp->ac + 180);
|
793
|
+
hsp->mc = swe_degnorm(hsp->mc + 180);
|
794
|
+
for (i = 1; i <= 12; i++)
|
795
|
+
hsp->cusp[i] = swe_degnorm(hsp->cusp[i] + 180);
|
796
|
+
}
|
797
|
+
}
|
798
|
+
break;
|
799
|
+
case 'V': /* equal houses after Vehlow */
|
800
|
+
/*
|
801
|
+
* within polar circle we swap AC/DC if AC is on wrong side
|
802
|
+
*/
|
803
|
+
acmc = swe_difdeg2n(hsp->ac, hsp->mc);
|
804
|
+
if (acmc < 0) {
|
805
|
+
hsp->ac = swe_degnorm(hsp->ac + 180);
|
806
|
+
hsp->cusp[1] = hsp->ac;
|
807
|
+
}
|
808
|
+
hsp->cusp [1] = swe_degnorm(hsp->ac - 15);
|
809
|
+
for (i = 2; i <=12; i++)
|
810
|
+
hsp->cusp [i] = swe_degnorm(hsp->cusp [1] + (i-1) * 30);
|
811
|
+
break;
|
812
|
+
case 'W': /* equal, whole-sign houses */
|
813
|
+
/*
|
814
|
+
* within polar circle we swap AC/DC if AC is on wrong side
|
815
|
+
*/
|
816
|
+
acmc = swe_difdeg2n(hsp->ac, hsp->mc);
|
817
|
+
if (acmc < 0) {
|
818
|
+
hsp->ac = swe_degnorm(hsp->ac + 180);
|
819
|
+
hsp->cusp[1] = hsp->ac;
|
820
|
+
}
|
821
|
+
hsp->cusp [1] = hsp->ac - fmod(hsp->ac, 30);
|
822
|
+
for (i = 2; i <=12; i++)
|
823
|
+
hsp->cusp [i] = swe_degnorm(hsp->cusp [1] + (i-1) * 30);
|
824
|
+
break;
|
825
|
+
case 'X': {
|
826
|
+
/*
|
827
|
+
* Meridian or axial rotation system:
|
828
|
+
* ecliptic points whose rectascensions
|
829
|
+
* are armc + n * 30
|
830
|
+
*/
|
831
|
+
int j;
|
832
|
+
double a = th;
|
833
|
+
for (i = 1; i <= 12; i++) {
|
834
|
+
j = i + 10;
|
835
|
+
if (j > 12) j -= 12;
|
836
|
+
a = swe_degnorm(a + 30);
|
837
|
+
if (fabs(a - 90) > VERY_SMALL
|
838
|
+
&& fabs(a - 270) > VERY_SMALL) {
|
839
|
+
tant = tand(a);
|
840
|
+
hsp->cusp[j] = atand(tant / cose);
|
841
|
+
if (a > 90 && a <= 270)
|
842
|
+
hsp->cusp[j] = swe_degnorm(hsp->cusp[j] + 180);
|
843
|
+
} else {
|
844
|
+
if (fabs(a - 90) <= VERY_SMALL)
|
845
|
+
hsp->cusp[j] = 90;
|
846
|
+
else
|
847
|
+
hsp->cusp[j] = 270;
|
848
|
+
} /* if */
|
849
|
+
hsp->cusp[j] = swe_degnorm(hsp->cusp[j]);
|
850
|
+
}
|
851
|
+
break; }
|
852
|
+
case 'M': {
|
853
|
+
/*
|
854
|
+
* Morinus
|
855
|
+
* points of the equator (armc + n * 30) are transformed
|
856
|
+
* into the ecliptic coordinate system
|
857
|
+
*/
|
858
|
+
int j;
|
859
|
+
double a = th;
|
860
|
+
double x[3];
|
861
|
+
for (i = 1; i <= 12; i++) {
|
862
|
+
j = i + 10;
|
863
|
+
if (j > 12) j -= 12;
|
864
|
+
a = swe_degnorm(a + 30);
|
865
|
+
x[0] = a;
|
866
|
+
x[1] = 0;
|
867
|
+
swe_cotrans(x, x, ekl);
|
868
|
+
hsp->cusp[j] = x[0];
|
869
|
+
}
|
870
|
+
break; }
|
871
|
+
case 'B': { /* Alcabitius */
|
872
|
+
/* created by Alois 17-sep-2000, followed example in Matrix
|
873
|
+
electrical library. The code reproduces the example!
|
874
|
+
See http://www.astro.com/cgi/adict.cgi query: alcabitius
|
875
|
+
in the resuotl page, see program code example.
|
876
|
+
I think the Alcabitius code in Walter Pullen's Astrolog 5.40
|
877
|
+
is wrong, because he remains in RA and forgets the transform to
|
878
|
+
the ecliptic. */
|
879
|
+
double dek, r, sna, sda, sn3, sd3;
|
880
|
+
#if FALSE
|
881
|
+
if (fabs(fi) >= 90 - ekl) { /* within polar circle */
|
882
|
+
retc = ERR;
|
883
|
+
goto porphyry;
|
884
|
+
}
|
885
|
+
#endif
|
886
|
+
acmc = swe_difdeg2n(hsp->ac, hsp->mc);
|
887
|
+
if (acmc < 0) {
|
888
|
+
hsp->ac = swe_degnorm(hsp->ac + 180);
|
889
|
+
hsp->cusp[1] = hsp->ac;
|
890
|
+
acmc = swe_difdeg2n(hsp->ac, hsp->mc);
|
891
|
+
}
|
892
|
+
dek = asind(sind(hsp->ac) * sine); /* declination of Ascendant */
|
893
|
+
/* must treat the case fi == 90 or -90 */
|
894
|
+
r = -tanfi * tand(dek);
|
895
|
+
/* must treat the case of abs(r) > 1; probably does not happen
|
896
|
+
* because dek becomes smaller when fi is large, as ac is close to
|
897
|
+
* zero Aries/Libra in that case.
|
898
|
+
*/
|
899
|
+
sda = acos(r) * RADTODEG; /* semidiurnal arc, measured on equator */
|
900
|
+
sna = 180 - sda; /* complement, seminocturnal arc */
|
901
|
+
sd3 = sda / 3;
|
902
|
+
sn3 = sna / 3;
|
903
|
+
rectasc = swe_degnorm(th + sd3); /* cusp 11 */
|
904
|
+
/* project rectasc onto eclipitic with pole height 0, i.e. along the
|
905
|
+
declination circle */
|
906
|
+
hsp->cusp [11] = Asc1 (rectasc, 0, sine, cose);
|
907
|
+
rectasc = swe_degnorm(th + 2 * sd3); /* cusp 12 */
|
908
|
+
hsp->cusp [12] = Asc1 (rectasc, 0, sine, cose);
|
909
|
+
rectasc = swe_degnorm(th + 180 - 2 * sn3); /* cusp 2 */
|
910
|
+
hsp->cusp [2] = Asc1 (rectasc, 0, sine, cose);
|
911
|
+
rectasc = swe_degnorm(th + 180 - sn3); /* cusp 3 */
|
912
|
+
hsp->cusp [3] = Asc1 (rectasc, 0, sine, cose);
|
913
|
+
}
|
914
|
+
break;
|
915
|
+
case 'G': /* 36 Gauquelin sectors */
|
916
|
+
for (i = 1; i <= 36; i++) {
|
917
|
+
hsp->cusp[i] = 0;
|
918
|
+
}
|
919
|
+
if (fabs(fi) >= 90 - ekl) { /* within polar circle */
|
920
|
+
retc = ERR;
|
921
|
+
goto porphyry;
|
922
|
+
}
|
923
|
+
/*************** forth/second quarter ***************/
|
924
|
+
/* note: Gauquelin sectors are counted in clockwise direction */
|
925
|
+
a = asind(tand(fi) * tane);
|
926
|
+
for (ih = 2; ih <= 9; ih++) {
|
927
|
+
ih2 = 10 - ih;
|
928
|
+
fh1 = atand(sind(a * ih2 / 9) / tane);
|
929
|
+
rectasc = swe_degnorm((90 / 9) * ih2 + th);
|
930
|
+
tant = tand(asind(sine * sind(Asc1 (rectasc, fh1, sine, cose))));
|
931
|
+
if (fabs(tant) < VERY_SMALL) {
|
932
|
+
hsp->cusp[ih] = rectasc;
|
933
|
+
} else {
|
934
|
+
/* pole height */
|
935
|
+
f = atand(sind(asind(tanfi * tant) * ih2 / 9) /tant);
|
936
|
+
hsp->cusp [ih] = Asc1 (rectasc, f, sine, cose);
|
937
|
+
for (i = 1; i <= iteration_count; i++) {
|
938
|
+
tant = tand(asind(sine * sind(hsp->cusp[ih])));
|
939
|
+
if (fabs(tant) < VERY_SMALL) {
|
940
|
+
hsp->cusp[ih] = rectasc;
|
941
|
+
break;
|
942
|
+
}
|
943
|
+
/* pole height */
|
944
|
+
f = atand(sind(asind(tanfi * tant) * ih2 / 9) / tant);
|
945
|
+
hsp->cusp[ih] = Asc1 (rectasc, f, sine, cose);
|
946
|
+
}
|
947
|
+
}
|
948
|
+
hsp->cusp[ih+18] = swe_degnorm(hsp->cusp[ih] + 180);
|
949
|
+
}
|
950
|
+
/*************** first/third quarter ***************/
|
951
|
+
for (ih = 29; ih <= 36; ih++) {
|
952
|
+
ih2 = ih - 28;
|
953
|
+
fh1 = atand(sind(a * ih2 / 9) / tane);
|
954
|
+
rectasc = swe_degnorm(180 - ih2 * 90 / 9 + th);
|
955
|
+
tant = tand(asind(sine * sind(Asc1 (rectasc, fh1, sine, cose))));
|
956
|
+
if (fabs(tant) < VERY_SMALL) {
|
957
|
+
hsp->cusp[ih] = rectasc;
|
958
|
+
} else {
|
959
|
+
f = atand(sind(asind(tanfi * tant) * ih2 / 9) / tant);
|
960
|
+
/* pole height */
|
961
|
+
hsp->cusp[ih] = Asc1 (rectasc, f, sine, cose);
|
962
|
+
for (i = 1; i <= iteration_count; i++) {
|
963
|
+
tant = tand(asind(sine * sind(hsp->cusp[ih])));
|
964
|
+
if (fabs(tant) < VERY_SMALL) {
|
965
|
+
hsp->cusp[ih] = rectasc;
|
966
|
+
break;
|
967
|
+
}
|
968
|
+
f = atand(sind(asind(tanfi * tant) * ih2 / 9) / tant);
|
969
|
+
/* pole height */
|
970
|
+
hsp->cusp[ih] = Asc1 (rectasc, f, sine, cose);
|
971
|
+
}
|
972
|
+
}
|
973
|
+
hsp->cusp[ih-18] = swe_degnorm(hsp->cusp[ih] + 180);
|
974
|
+
}
|
975
|
+
hsp->cusp[1] = hsp->ac;
|
976
|
+
hsp->cusp[10] = hsp->mc;
|
977
|
+
hsp->cusp[19] = swe_degnorm(hsp->ac + 180);
|
978
|
+
hsp->cusp[28] = swe_degnorm(hsp->mc + 180);
|
979
|
+
break;
|
980
|
+
case 'U': /* Krusinski-Pisa */
|
981
|
+
/*
|
982
|
+
* The following code was written by Bogdan Krusinski in 2006.
|
983
|
+
* bogdan@astrologia.pl
|
984
|
+
*
|
985
|
+
* Definition:
|
986
|
+
* "Krusinski - house system based on the great circle passing through
|
987
|
+
* ascendant and zenith. This circle is divided into 12 equal parts
|
988
|
+
* (1st cusp is ascendent, 10th cusp is zenith), then the resulting
|
989
|
+
* points are projected onto the ecliptic through meridian circles.
|
990
|
+
* The house cusps in space are half-circles perpendicular to the equator
|
991
|
+
* and running from the north to the south celestial pole through the
|
992
|
+
* resulting cusp points on the house circle. The points where they
|
993
|
+
* cross the ecliptic mark the ecliptic house cusps."
|
994
|
+
*
|
995
|
+
* Description of the algorithm:
|
996
|
+
* Transform into great circle running through Asc and zenit (where arc
|
997
|
+
* between Asc and zenith is always 90 deg), and then return with
|
998
|
+
* house cusps into ecliptic. Eg. solve trigonometrical triangle
|
999
|
+
* with three transformations and two rotations starting from ecliptic.
|
1000
|
+
* House cusps in space are meridian circles.
|
1001
|
+
*
|
1002
|
+
* Notes:
|
1003
|
+
* 1. In this definition we assume MC on ecliptic as point where
|
1004
|
+
* half-meridian (from north to south pole) cuts ecliptic,
|
1005
|
+
* so MC may be below horizon in arctic regions.
|
1006
|
+
* 2. Houses could be calculated in all latitudes except the poles
|
1007
|
+
* themselves (-90,90) and points on arctic circle in cases where
|
1008
|
+
* ecliptic is equal to horizon and then ascendant is undefined.
|
1009
|
+
* But ascendant when 'horizon=ecliptic' could be deduced as limes
|
1010
|
+
* from both sides of that point and houses with that provision can
|
1011
|
+
* be computed also there.
|
1012
|
+
*
|
1013
|
+
* Starting values for calculations:
|
1014
|
+
* - Asc ecliptic longitude
|
1015
|
+
* - right ascension of MC (RAMC)
|
1016
|
+
* - geographic latitude.
|
1017
|
+
*/
|
1018
|
+
/*
|
1019
|
+
* within polar circle we swap AC/DC if AC is on wrong side
|
1020
|
+
*/
|
1021
|
+
acmc = swe_difdeg2n(hsp->ac, hsp->mc);
|
1022
|
+
if (acmc < 0) {
|
1023
|
+
hsp->ac = swe_degnorm(hsp->ac + 180);
|
1024
|
+
}
|
1025
|
+
/* A0. Start point - ecliptic coords of ascendant */
|
1026
|
+
x[0] = hsp->ac; /* Asc longitude */
|
1027
|
+
x[1] = 0.0; /* Asc declination */
|
1028
|
+
x[2] = 1.0; /* Radius to test validity of subsequent transformations. */
|
1029
|
+
swe_cotrans(x, x, -ekl); /* A1. Transform into equatorial coords */
|
1030
|
+
x[0] = x[0] - (th-90); /* A2. Rotate */
|
1031
|
+
swe_cotrans(x, x, -(90-fi)); /* A3. Transform into horizontal coords */
|
1032
|
+
krHorizonLon = x[0]; /* ...save asc lon on horizon to get back later with house cusp */
|
1033
|
+
x[0] = x[0] - x[0]; /* A4. Rotate */
|
1034
|
+
swe_cotrans(x, x, -90); /* A5. Transform into this house system great circle (asc-zenith) */
|
1035
|
+
/* As it is house circle now, simple add 30 deg increments... */
|
1036
|
+
for(i = 0; i < 6; i++) {
|
1037
|
+
/* B0. Set 'n-th' house cusp.
|
1038
|
+
* Note that IC/MC are also calculated here to check
|
1039
|
+
* if really this is the asc-zenith great circle. */
|
1040
|
+
x[0] = 30.0*i;
|
1041
|
+
x[1] = 0.0;
|
1042
|
+
swe_cotrans(x, x, 90); /* B1. Transform back into horizontal coords */
|
1043
|
+
x[0] = x[0] + krHorizonLon; /* B2. Rotate back. */
|
1044
|
+
swe_cotrans(x, x, 90-fi); /* B3. Transform back into equatorial coords */
|
1045
|
+
x[0] = swe_degnorm(x[0] + (th-90)); /* B4. Rotate back -> RA of house cusp as result. */
|
1046
|
+
/* B5. Where's this house cusp on ecliptic? */
|
1047
|
+
/* ... so last but not least - get ecliptic longitude of house cusp: */
|
1048
|
+
hsp->cusp[i+1] = atand(tand(x[0])/cosd(ekl));
|
1049
|
+
if (x[0] > 90 && x[0] <= 270)
|
1050
|
+
hsp->cusp[i+1] = swe_degnorm(hsp->cusp[i+1] + 180);
|
1051
|
+
hsp->cusp[i+1] = swe_degnorm(hsp->cusp[i+1]);
|
1052
|
+
hsp->cusp[i+7] = swe_degnorm(hsp->cusp[i+1]+180);
|
1053
|
+
}
|
1054
|
+
break;
|
1055
|
+
default: /* Placidus houses */
|
1056
|
+
#ifndef _WINDOWS
|
1057
|
+
if (hsy != 'P')
|
1058
|
+
fprintf (stderr, "swe_houses: make Placidus, unknown key %c\n", hsy);
|
1059
|
+
#endif
|
1060
|
+
if (fabs(fi) >= 90 - ekl) { /* within polar circle */
|
1061
|
+
retc = ERR;
|
1062
|
+
goto porphyry;
|
1063
|
+
}
|
1064
|
+
a = asind(tand(fi) * tane);
|
1065
|
+
fh1 = atand(sind(a / 3) / tane);
|
1066
|
+
fh2 = atand(sind(a * 2 / 3) / tane);
|
1067
|
+
/* ************ house 11 ******************** */
|
1068
|
+
rectasc = swe_degnorm(30 + th);
|
1069
|
+
tant = tand(asind(sine * sind(Asc1 (rectasc, fh1, sine, cose))));
|
1070
|
+
if (fabs(tant) < VERY_SMALL) {
|
1071
|
+
hsp->cusp [11] = rectasc;
|
1072
|
+
} else {
|
1073
|
+
/* pole height */
|
1074
|
+
f = atand(sind(asind(tanfi * tant) / 3) /tant);
|
1075
|
+
hsp->cusp [11] = Asc1 (rectasc, f, sine, cose);
|
1076
|
+
for (i = 1; i <= iteration_count; i++) {
|
1077
|
+
tant = tand(asind(sine * sind(hsp->cusp [11])));
|
1078
|
+
if (fabs(tant) < VERY_SMALL) {
|
1079
|
+
hsp->cusp [11] = rectasc;
|
1080
|
+
break;
|
1081
|
+
}
|
1082
|
+
/* pole height */
|
1083
|
+
f = atand(sind(asind(tanfi * tant) / 3) / tant);
|
1084
|
+
hsp->cusp [11] = Asc1 (rectasc, f, sine, cose);
|
1085
|
+
}
|
1086
|
+
}
|
1087
|
+
/* ************ house 12 ******************** */
|
1088
|
+
rectasc = swe_degnorm(60 + th);
|
1089
|
+
tant = tand(asind(sine*sind(Asc1 (rectasc, fh2, sine, cose))));
|
1090
|
+
if (fabs(tant) < VERY_SMALL) {
|
1091
|
+
hsp->cusp [12] = rectasc;
|
1092
|
+
} else {
|
1093
|
+
f = atand(sind(asind(tanfi * tant) / 1.5) / tant);
|
1094
|
+
/* pole height */
|
1095
|
+
hsp->cusp [12] = Asc1 (rectasc, f, sine, cose);
|
1096
|
+
for (i = 1; i <= iteration_count; i++) {
|
1097
|
+
tant = tand(asind(sine * sind(hsp->cusp [12])));
|
1098
|
+
if (fabs(tant) < VERY_SMALL) {
|
1099
|
+
hsp->cusp [12] = rectasc;
|
1100
|
+
break;
|
1101
|
+
}
|
1102
|
+
f = atand(sind(asind(tanfi * tant) / 1.5) / tant);
|
1103
|
+
/* pole height */
|
1104
|
+
hsp->cusp [12] = Asc1 (rectasc, f, sine, cose);
|
1105
|
+
}
|
1106
|
+
}
|
1107
|
+
/* ************ house 2 ******************** */
|
1108
|
+
rectasc = swe_degnorm(120 + th);
|
1109
|
+
tant = tand(asind(sine * sind(Asc1 (rectasc, fh2, sine, cose))));
|
1110
|
+
if (fabs(tant) < VERY_SMALL) {
|
1111
|
+
hsp->cusp [2] = rectasc;
|
1112
|
+
} else {
|
1113
|
+
f = atand(sind(asind(tanfi * tant) / 1.5) / tant);
|
1114
|
+
/* pole height */
|
1115
|
+
hsp->cusp [2] = Asc1 (rectasc, f, sine, cose);
|
1116
|
+
for (i = 1; i <= iteration_count; i++) {
|
1117
|
+
tant = tand(asind(sine * sind(hsp->cusp [2])));
|
1118
|
+
if (fabs(tant) < VERY_SMALL) {
|
1119
|
+
hsp->cusp [2] = rectasc;
|
1120
|
+
break;
|
1121
|
+
}
|
1122
|
+
f = atand(sind(asind(tanfi * tant) / 1.5) / tant);
|
1123
|
+
/* pole height */
|
1124
|
+
hsp->cusp [2] = Asc1 (rectasc, f, sine, cose);
|
1125
|
+
}
|
1126
|
+
}
|
1127
|
+
/* ************ house 3 ******************** */
|
1128
|
+
rectasc = swe_degnorm(150 + th);
|
1129
|
+
tant = tand(asind(sine * sind(Asc1 (rectasc, fh1, sine, cose))));
|
1130
|
+
if (fabs(tant) < VERY_SMALL) {
|
1131
|
+
hsp->cusp [3] = rectasc;
|
1132
|
+
} else {
|
1133
|
+
f = atand(sind(asind(tanfi * tant) / 3) / tant);
|
1134
|
+
/* pole height */
|
1135
|
+
hsp->cusp [3] = Asc1(rectasc, f, sine, cose);
|
1136
|
+
for (i = 1; i <= iteration_count; i++) {
|
1137
|
+
tant = tand(asind(sine * sind(hsp->cusp [3])));
|
1138
|
+
if (fabs(tant) < VERY_SMALL) {
|
1139
|
+
hsp->cusp [3] = rectasc;
|
1140
|
+
break;
|
1141
|
+
}
|
1142
|
+
f = atand(sind(asind(tanfi * tant) / 3) / tant);
|
1143
|
+
/* pole height */
|
1144
|
+
hsp->cusp [3] = Asc1 (rectasc, f, sine, cose);
|
1145
|
+
}
|
1146
|
+
}
|
1147
|
+
break;
|
1148
|
+
} /* end switch */
|
1149
|
+
if (hsy != 'G') {
|
1150
|
+
hsp->cusp [4] = swe_degnorm(hsp->cusp [10] + 180);
|
1151
|
+
hsp->cusp [5] = swe_degnorm(hsp->cusp [11] + 180);
|
1152
|
+
hsp->cusp [6] = swe_degnorm(hsp->cusp [12] + 180);
|
1153
|
+
hsp->cusp [7] = swe_degnorm(hsp->cusp [1] + 180);
|
1154
|
+
hsp->cusp [8] = swe_degnorm(hsp->cusp [2] + 180);
|
1155
|
+
hsp->cusp [9] = swe_degnorm(hsp->cusp [3] + 180);
|
1156
|
+
}
|
1157
|
+
/* vertex */
|
1158
|
+
if (fi >= 0)
|
1159
|
+
f = 90 - fi;
|
1160
|
+
else
|
1161
|
+
f = -90 - fi;
|
1162
|
+
hsp->vertex = Asc1 (th - 90, f, sine, cose);
|
1163
|
+
/* with tropical latitudes, the vertex behaves strange,
|
1164
|
+
* in a similar way as the ascendant within the polar
|
1165
|
+
* circle. we keep it always on the western hemisphere.*/
|
1166
|
+
if (fabs(fi) <= ekl) {
|
1167
|
+
vemc = swe_difdeg2n(hsp->vertex, hsp->mc);
|
1168
|
+
if (vemc > 0)
|
1169
|
+
hsp->vertex = swe_degnorm(hsp->vertex + 180);
|
1170
|
+
}
|
1171
|
+
/*
|
1172
|
+
* some strange points:
|
1173
|
+
*/
|
1174
|
+
/* equasc (equatorial ascendant) */
|
1175
|
+
th2 = swe_degnorm(th + 90);
|
1176
|
+
if (fabs(th2 - 90) > VERY_SMALL
|
1177
|
+
&& fabs(th2 - 270) > VERY_SMALL) {
|
1178
|
+
tant = tand(th2);
|
1179
|
+
hsp->equasc = atand(tant / cose);
|
1180
|
+
if (th2 > 90 && th2 <= 270)
|
1181
|
+
hsp->equasc = swe_degnorm(hsp->equasc + 180);
|
1182
|
+
} else {
|
1183
|
+
if (fabs(th2 - 90) <= VERY_SMALL)
|
1184
|
+
hsp->equasc = 90;
|
1185
|
+
else
|
1186
|
+
hsp->equasc = 270;
|
1187
|
+
} /* if */
|
1188
|
+
hsp->equasc = swe_degnorm(hsp->equasc);
|
1189
|
+
/* "co-ascendant" W. Koch */
|
1190
|
+
hsp->coasc1 = swe_degnorm(Asc1 (th - 90, fi, sine, cose) + 180);
|
1191
|
+
/* "co-ascendant" M. Munkasey */
|
1192
|
+
if (fi >= 0)
|
1193
|
+
hsp->coasc2 = Asc1 (th + 90, 90 - fi, sine, cose);
|
1194
|
+
else /* southern hemisphere */
|
1195
|
+
hsp->coasc2 = Asc1 (th + 90, -90 - fi, sine, cose);
|
1196
|
+
/* "polar ascendant" M. Munkasey */
|
1197
|
+
hsp->polasc = Asc1 (th - 90, fi, sine, cose);
|
1198
|
+
return retc;
|
1199
|
+
} /* procedure houses */
|
1200
|
+
|
1201
|
+
/******************************/
|
1202
|
+
static double Asc1 (double x1, double f, double sine, double cose)
|
1203
|
+
{
|
1204
|
+
int n;
|
1205
|
+
double ass;
|
1206
|
+
x1 = swe_degnorm(x1);
|
1207
|
+
n = (int) ((x1 / 90) + 1);
|
1208
|
+
if (n == 1)
|
1209
|
+
ass = ( Asc2 (x1, f, sine, cose));
|
1210
|
+
else if (n == 2)
|
1211
|
+
ass = (180 - Asc2 (180 - x1, - f, sine, cose));
|
1212
|
+
else if (n == 3)
|
1213
|
+
ass = (180 + Asc2 (x1 - 180, - f, sine, cose));
|
1214
|
+
else
|
1215
|
+
ass = (360 - Asc2 (360- x1, f, sine, cose));
|
1216
|
+
ass = swe_degnorm(ass);
|
1217
|
+
if (fabs(ass - 90) < VERY_SMALL) /* rounding, e.g.: if */
|
1218
|
+
ass = 90; /* fi = 0 & st = 0, ac = 89.999... */
|
1219
|
+
if (fabs(ass - 180) < VERY_SMALL)
|
1220
|
+
ass = 180;
|
1221
|
+
if (fabs(ass - 270) < VERY_SMALL) /* rounding, e.g.: if */
|
1222
|
+
ass = 270; /* fi = 0 & st = 0, ac = 89.999... */
|
1223
|
+
if (fabs(ass - 360) < VERY_SMALL)
|
1224
|
+
ass = 0;
|
1225
|
+
return ass;
|
1226
|
+
} /* Asc1 */
|
1227
|
+
|
1228
|
+
static double Asc2 (double x, double f, double sine, double cose)
|
1229
|
+
{
|
1230
|
+
double ass, sinx;
|
1231
|
+
ass = - tand(f) * sine + cose * cosd(x);
|
1232
|
+
if (fabs(ass) < VERY_SMALL)
|
1233
|
+
ass = 0;
|
1234
|
+
sinx = sind(x);
|
1235
|
+
if (fabs(sinx) < VERY_SMALL)
|
1236
|
+
sinx = 0;
|
1237
|
+
if (sinx == 0) {
|
1238
|
+
if (ass < 0)
|
1239
|
+
ass = -VERY_SMALL;
|
1240
|
+
else
|
1241
|
+
ass = VERY_SMALL;
|
1242
|
+
} else if (ass == 0) {
|
1243
|
+
if (sinx < 0)
|
1244
|
+
ass = -90;
|
1245
|
+
else
|
1246
|
+
ass = 90;
|
1247
|
+
} else {
|
1248
|
+
ass = atand(sinx / ass);
|
1249
|
+
}
|
1250
|
+
if (ass < 0)
|
1251
|
+
ass = 180 + ass;
|
1252
|
+
return (ass);
|
1253
|
+
} /* Asc2 */
|
1254
|
+
|
1255
|
+
|
1256
|
+
/* Computes the house position of a planet or another point,
|
1257
|
+
* in degrees: 0 - 30 = 1st house, 30 - 60 = 2nd house, etc.
|
1258
|
+
* armc sidereal time in degrees
|
1259
|
+
* geolat geographic latitude
|
1260
|
+
* eps true ecliptic obliquity
|
1261
|
+
* hsys house system character
|
1262
|
+
* xpin array of 6 doubles:
|
1263
|
+
* only the first two of them are used: ecl. long., lat.
|
1264
|
+
* serr error message area
|
1265
|
+
*
|
1266
|
+
* House position is returned by function.
|
1267
|
+
*
|
1268
|
+
* IMPORTANT: This function should NOT be used for sidereal astrology.
|
1269
|
+
* If you cannot avoid doing so, please note:
|
1270
|
+
* - The input longitudes (xpin) MUST always be tropical, even if you
|
1271
|
+
* are a siderealist.
|
1272
|
+
* - Sidereal and tropical house positions are identical for most house
|
1273
|
+
* systems, if a traditional definition of the sidereal zodiac is used
|
1274
|
+
* (sid = trop - ayanamsa).
|
1275
|
+
* - The function does NOT provide correct positions for Whole Sign houses.
|
1276
|
+
* - The function does NOT provide correct positions, if you use a
|
1277
|
+
* non-traditional sidereal method (where the sidereal plane is not
|
1278
|
+
* identical to the ecliptic of date) with a house system whose definition
|
1279
|
+
* is dependent on the ecliptic, such as:
|
1280
|
+
* equal, Porphyry, Alcabitius, Koch, Krusinski (all others should work).
|
1281
|
+
* The Swiss Ephemeris currently does not handle these cases.
|
1282
|
+
*/
|
1283
|
+
double FAR PASCAL_CONV swe_house_pos(
|
1284
|
+
double armc, double geolat, double eps, int hsys, double *xpin, char *serr)
|
1285
|
+
{
|
1286
|
+
double xp[6], xeq[6], ra, de, mdd, mdn, sad, san;
|
1287
|
+
double hpos, sinad, ad, a, admc, adp, samc, demc, asc, mc, acmc, tant;
|
1288
|
+
double fh, ra0, tanfi, fac, dfac;
|
1289
|
+
double x[3], xasc[3], raep, raaz, oblaz, xtemp; /* BK 21.02.2006 */
|
1290
|
+
double sine = sind(eps);
|
1291
|
+
double cose = cosd(eps);
|
1292
|
+
AS_BOOL is_above_hor = FALSE;
|
1293
|
+
AS_BOOL is_invalid = FALSE;
|
1294
|
+
AS_BOOL is_circumpolar = FALSE;
|
1295
|
+
if (serr != NULL)
|
1296
|
+
*serr = '\0';
|
1297
|
+
hsys = toupper(hsys);
|
1298
|
+
xeq[0] = xpin[0];
|
1299
|
+
xeq[1] = xpin[1];
|
1300
|
+
xeq[2] = 1;
|
1301
|
+
swe_cotrans(xpin, xeq, -eps);
|
1302
|
+
ra = xeq[0];
|
1303
|
+
de = xeq[1];
|
1304
|
+
mdd = swe_degnorm(ra - armc);
|
1305
|
+
mdn = swe_degnorm(mdd + 180);
|
1306
|
+
if (mdd >= 180)
|
1307
|
+
mdd -= 360;
|
1308
|
+
if (mdn >= 180)
|
1309
|
+
mdn -= 360;
|
1310
|
+
/* xp[0] will contain the house position, a value between 0 and 360 */
|
1311
|
+
switch(hsys) {
|
1312
|
+
case 'A':
|
1313
|
+
case 'E':
|
1314
|
+
case 'V':
|
1315
|
+
case 'W':
|
1316
|
+
asc = Asc1 (swe_degnorm(armc + 90), geolat, sine, cose);
|
1317
|
+
demc = atand(sind(armc) * tand(eps));
|
1318
|
+
if (geolat >= 0 && 90 - geolat + demc < 0)
|
1319
|
+
asc = swe_degnorm(asc + 180);
|
1320
|
+
if (geolat < 0 && -90 - geolat + demc > 0)
|
1321
|
+
asc = swe_degnorm(asc + 180);
|
1322
|
+
xp[0] = swe_degnorm(xpin[0] - asc);
|
1323
|
+
if (hsys == 'V')
|
1324
|
+
xp[0] = swe_degnorm(xp[0] + 15);
|
1325
|
+
if (hsys == 'W')
|
1326
|
+
xp[0] = swe_degnorm(xp[0] + fmod(asc, 30));
|
1327
|
+
/* to make sure that a call with a house cusp position returns
|
1328
|
+
* a value within the house, 0.001" is added */
|
1329
|
+
xp[0] = swe_degnorm(xp[0] + MILLIARCSEC);
|
1330
|
+
hpos = xp[0] / 30.0 + 1;
|
1331
|
+
break;
|
1332
|
+
case 'O': /* Porphyry */
|
1333
|
+
case 'B': /* Alcabitius */
|
1334
|
+
asc = Asc1 (swe_degnorm(armc + 90), geolat, sine, cose);
|
1335
|
+
demc = atand(sind(armc) * tand(eps));
|
1336
|
+
/* mc */
|
1337
|
+
if (fabs(armc - 90) > VERY_SMALL
|
1338
|
+
&& fabs(armc - 270) > VERY_SMALL) {
|
1339
|
+
tant = tand(armc);
|
1340
|
+
mc = swe_degnorm(atand(tant / cose));
|
1341
|
+
if (armc > 90 && armc <= 270)
|
1342
|
+
mc = swe_degnorm(mc + 180);
|
1343
|
+
} else {
|
1344
|
+
if (fabs(armc - 90) <= VERY_SMALL)
|
1345
|
+
mc = 90;
|
1346
|
+
else
|
1347
|
+
mc = 270;
|
1348
|
+
}
|
1349
|
+
/* while MC is always south,
|
1350
|
+
* Asc must always be in eastern hemisphere */
|
1351
|
+
if (geolat >= 0 && 90 - geolat + demc < 0) {
|
1352
|
+
asc = swe_degnorm(asc + 180);
|
1353
|
+
}
|
1354
|
+
if (geolat < 0 && -90 - geolat + demc > 0) {
|
1355
|
+
asc = swe_degnorm(asc + 180);
|
1356
|
+
}
|
1357
|
+
if (hsys == 'O') {
|
1358
|
+
xp[0] = swe_degnorm(xpin[0] - asc);
|
1359
|
+
/* to make sure that a call with a house cusp position returns
|
1360
|
+
* a value within the house, 0.001" is added */
|
1361
|
+
xp[0] = swe_degnorm(xp[0] + MILLIARCSEC);
|
1362
|
+
if (xp[0] < 180)
|
1363
|
+
hpos = 1;
|
1364
|
+
else {
|
1365
|
+
hpos = 7;
|
1366
|
+
xp[0] -= 180;
|
1367
|
+
}
|
1368
|
+
acmc = swe_difdeg2n(asc, mc);
|
1369
|
+
if (xp[0] < 180 - acmc)
|
1370
|
+
hpos += xp[0] * 3 / (180 - acmc);
|
1371
|
+
else
|
1372
|
+
hpos += 3 + (xp[0] - 180 + acmc) * 3 / acmc;
|
1373
|
+
} else { /* Alcabitius */
|
1374
|
+
double dek, r, sna, sda;
|
1375
|
+
dek = asind(sind(asc) * sine); /* declination of Ascendant */
|
1376
|
+
/* must treat the case fi == 90 or -90 */
|
1377
|
+
tanfi = tand(geolat);
|
1378
|
+
r = -tanfi * tand(dek);
|
1379
|
+
/* must treat the case of abs(r) > 1; probably does not happen
|
1380
|
+
* because dek becomes smaller when fi is large, as ac is close to
|
1381
|
+
* zero Aries/Libra in that case.
|
1382
|
+
*/
|
1383
|
+
sda = acos(r) * RADTODEG; /* semidiurnal arc, measured on equator */
|
1384
|
+
sna = 180 - sda; /* complement, seminocturnal arc */
|
1385
|
+
if (mdd > 0) {
|
1386
|
+
if (mdd < sda)
|
1387
|
+
hpos = mdd * 90 / sda;
|
1388
|
+
else
|
1389
|
+
hpos = 90 + (mdd - sda) * 90 / sna;
|
1390
|
+
} else {
|
1391
|
+
if (mdd > -sna)
|
1392
|
+
hpos = 360 + mdd * 90 / sna;
|
1393
|
+
else
|
1394
|
+
hpos = 270 + (mdd + sna) * 90 / sda;
|
1395
|
+
}
|
1396
|
+
hpos = swe_degnorm(hpos - 90) / 30.0 + 1.0;
|
1397
|
+
if (hpos >= 13.0) hpos -= 12;
|
1398
|
+
}
|
1399
|
+
break;
|
1400
|
+
case 'X': /* Merdidian or axial rotation system */
|
1401
|
+
hpos = swe_degnorm(mdd - 90) / 30.0 + 1.0;
|
1402
|
+
break;
|
1403
|
+
case 'M': { /* Morinus */
|
1404
|
+
double a = xpin[0];
|
1405
|
+
if (fabs(a - 90) > VERY_SMALL
|
1406
|
+
&& fabs(a - 270) > VERY_SMALL) {
|
1407
|
+
tant = tand(a);
|
1408
|
+
hpos = atand(tant / cose);
|
1409
|
+
if (a > 90 && a <= 270)
|
1410
|
+
hpos = swe_degnorm(hpos + 180);
|
1411
|
+
} else {
|
1412
|
+
if (fabs(a - 90) <= VERY_SMALL)
|
1413
|
+
hpos = 90;
|
1414
|
+
else
|
1415
|
+
hpos = 270;
|
1416
|
+
} /* if */
|
1417
|
+
hpos = swe_degnorm(hpos - armc - 90);
|
1418
|
+
hpos = hpos / 30.0 + 1;
|
1419
|
+
}
|
1420
|
+
break;
|
1421
|
+
#if 0
|
1422
|
+
/* old version of Koch method */
|
1423
|
+
case 'K':
|
1424
|
+
demc = atand(sind(armc) * tand(eps));
|
1425
|
+
/* if body is within circumpolar region, error */
|
1426
|
+
if (90 - fabs(geolat) <= fabs(de)) {
|
1427
|
+
if (serr != NULL)
|
1428
|
+
strcpy(serr, "no Koch house position, because planet is circumpolar.");
|
1429
|
+
xp[0] = 0;
|
1430
|
+
hpos = 0; /* Error */
|
1431
|
+
} else if (90 - fabs(geolat) <= fabs(demc)) {
|
1432
|
+
if (serr != NULL)
|
1433
|
+
strcpy(serr, "no Koch house position, because mc is circumpolar.");
|
1434
|
+
xp[0] = 0;
|
1435
|
+
hpos = 0; /* Error */
|
1436
|
+
} else {
|
1437
|
+
admc = asind(tand(eps) * tand(geolat) * sind(armc));
|
1438
|
+
adp = asind(tand(geolat) * tand(de));
|
1439
|
+
samc = 90 + admc;
|
1440
|
+
if (mdd >= 0) { /* east */
|
1441
|
+
xp[0] = swe_degnorm(((mdd - adp + admc) / samc - 1) * 90);
|
1442
|
+
} else {
|
1443
|
+
xp[0] = swe_degnorm(((mdd + 180 + adp + admc) / samc + 1) * 90);
|
1444
|
+
}
|
1445
|
+
/* to make sure that a call with a house cusp position returns
|
1446
|
+
* a value within the house, 0.001" is added */
|
1447
|
+
xp[0] = swe_degnorm(xp[0] + MILLIARCSEC);
|
1448
|
+
hpos = xp[0] / 30.0 + 1;
|
1449
|
+
}
|
1450
|
+
break;
|
1451
|
+
#endif
|
1452
|
+
/* version of Koch method: do calculations within circumpolar circle,
|
1453
|
+
* if possible; make sure house positions 4 - 9 only appear on western
|
1454
|
+
* hemisphere */
|
1455
|
+
case 'K':
|
1456
|
+
demc = atand(sind(armc) * tand(eps));
|
1457
|
+
is_invalid = FALSE;
|
1458
|
+
is_circumpolar = FALSE;
|
1459
|
+
/* object is within a circumpolar circle */
|
1460
|
+
if (90 - geolat < de || -90 - geolat > de) {
|
1461
|
+
adp = 90;
|
1462
|
+
is_circumpolar = TRUE;
|
1463
|
+
}
|
1464
|
+
/* object is within a circumpolar circle, southern hemisphere */
|
1465
|
+
else if (geolat - 90 > de || geolat + 90 < de) {
|
1466
|
+
adp = -90;
|
1467
|
+
is_circumpolar = TRUE;
|
1468
|
+
}
|
1469
|
+
/* object does rise and set */
|
1470
|
+
else {
|
1471
|
+
adp = asind(tand(geolat) * tand(de));
|
1472
|
+
}
|
1473
|
+
#if 0
|
1474
|
+
if (fabs(adp) == 90)
|
1475
|
+
is_invalid = TRUE; /* omit this to use the above values */
|
1476
|
+
#endif
|
1477
|
+
admc = tand(eps) * tand(geolat) * sind(armc);
|
1478
|
+
/* midheaven is circumpolar */
|
1479
|
+
if (fabs(admc) > 1) {
|
1480
|
+
#if 0
|
1481
|
+
is_invalid = TRUE; /* omit this line to use the below values */
|
1482
|
+
#endif
|
1483
|
+
if (admc > 1)
|
1484
|
+
admc = 1;
|
1485
|
+
else
|
1486
|
+
admc = -1;
|
1487
|
+
is_circumpolar = TRUE;
|
1488
|
+
}
|
1489
|
+
admc = asind(admc);
|
1490
|
+
samc = 90 + admc;
|
1491
|
+
if (samc == 0)
|
1492
|
+
is_invalid = TRUE;
|
1493
|
+
if (fabs(samc) > 0) {
|
1494
|
+
if (mdd >= 0) { /* east */
|
1495
|
+
dfac = (mdd - adp + admc) / samc;
|
1496
|
+
xp[0] = swe_degnorm((dfac - 1) * 90);
|
1497
|
+
xp[0] = swe_degnorm(xp[0] + MILLIARCSEC);
|
1498
|
+
/* eastern object has longer SA than midheaven */
|
1499
|
+
if (dfac > 2 || dfac < 0)
|
1500
|
+
is_invalid = TRUE; /* if this is omitted, funny things happen */
|
1501
|
+
} else {
|
1502
|
+
dfac = (mdd + 180 + adp + admc) / samc;
|
1503
|
+
xp[0] = swe_degnorm((dfac + 1) * 90);
|
1504
|
+
xp[0] = swe_degnorm(xp[0] + MILLIARCSEC);
|
1505
|
+
/* western object has longer SA than midheaven */
|
1506
|
+
if (dfac > 2 || dfac < 0)
|
1507
|
+
is_invalid = TRUE; /* if this is omitted, funny things happen */
|
1508
|
+
}
|
1509
|
+
}
|
1510
|
+
if (is_invalid) {
|
1511
|
+
xp[0] = 0;
|
1512
|
+
hpos = 0;
|
1513
|
+
if (serr != NULL)
|
1514
|
+
strcpy(serr, "Koch house position failed in circumpolar area");
|
1515
|
+
break;
|
1516
|
+
}
|
1517
|
+
if (is_circumpolar) {
|
1518
|
+
if (serr != NULL)
|
1519
|
+
strcpy(serr, "Koch house position, doubtful result in circumpolar area");
|
1520
|
+
}
|
1521
|
+
/* to make sure that a call with a house cusp position returns
|
1522
|
+
* a value within the house, 0.001" is added */
|
1523
|
+
hpos = xp[0] / 30.0 + 1;
|
1524
|
+
break;
|
1525
|
+
case 'C':
|
1526
|
+
xeq[0] = swe_degnorm(mdd - 90);
|
1527
|
+
swe_cotrans(xeq, xp, -geolat);
|
1528
|
+
/* to make sure that a call with a house cusp position returns
|
1529
|
+
* a value within the house, 0.001" is added */
|
1530
|
+
xp[0] = swe_degnorm(xp[0] + MILLIARCSEC);
|
1531
|
+
hpos = xp[0] / 30.0 + 1;
|
1532
|
+
break;
|
1533
|
+
case 'U': /* Krusinski-Pisa */
|
1534
|
+
/* Purpose: find point where planet's house circle (meridian)
|
1535
|
+
* cuts house plane, giving exact planet's house position.
|
1536
|
+
* Input data: ramc, geolat, asc.
|
1537
|
+
*/
|
1538
|
+
asc = Asc1 (swe_degnorm(armc + 90), geolat, sine, cose);
|
1539
|
+
demc = atand(sind(armc) * tand(eps));
|
1540
|
+
/* while MC is always south,
|
1541
|
+
* Asc must always be in eastern hemisphere */
|
1542
|
+
if (geolat >= 0 && 90 - geolat + demc < 0) {
|
1543
|
+
asc = swe_degnorm(asc + 180);
|
1544
|
+
}
|
1545
|
+
if (geolat < 0 && -90 - geolat + demc > 0) {
|
1546
|
+
asc = swe_degnorm(asc + 180);
|
1547
|
+
}
|
1548
|
+
/*
|
1549
|
+
* Descr: find the house plane 'asc-zenith' - where it intersects
|
1550
|
+
* with equator and at what angle, and then simple find arc
|
1551
|
+
* from asc on that plane to planet's meridian intersection
|
1552
|
+
* with this plane.
|
1553
|
+
*/
|
1554
|
+
/* I. find plane of 'asc-zenith' great circle relative to equator:
|
1555
|
+
* solve spherical triangle 'EP-asc-intersection of house circle with equator' */
|
1556
|
+
/* Ia. Find intersection of house plane with equator: */
|
1557
|
+
x[0] = asc; x[1] = 0.0; x[2] = 1.0; /* 1. Start with ascendent on ecliptic */
|
1558
|
+
swe_cotrans(x, x, -eps); /* 2. Transform asc into equatorial coords */
|
1559
|
+
raep = swe_degnorm(armc + 90); /* 3. RA of east point */
|
1560
|
+
x[0] = swe_degnorm(raep - x[0]); /* 4. Rotation - found arc raas-raep */
|
1561
|
+
swe_cotrans(x, x, -(90-geolat)); /* 5. Transform into horizontal coords - arc EP-asc on horizon */
|
1562
|
+
xtemp = atand(tand(x[0])/cosd((90-geolat))); /* 6. Rotation from horizon on circle perpendicular to equator */
|
1563
|
+
if (x[0] > 90 && x[0] <= 270)
|
1564
|
+
xtemp = swe_degnorm(xtemp + 180);
|
1565
|
+
x[0] = swe_degnorm(xtemp);
|
1566
|
+
raaz = swe_degnorm(raep - x[0]); /* result: RA of intersection 'asc-zenith' great circle with equator */
|
1567
|
+
/* Ib. Find obliquity to equator of 'asc-zenith' house plane: */
|
1568
|
+
x[0] = raaz; x[1] = 0.0;
|
1569
|
+
x[0] = swe_degnorm(raep - x[0]); /* 1. Rotate start point relative to EP */
|
1570
|
+
swe_cotrans(x, x, -(90-geolat)); /* 2. Transform into horizontal coords */
|
1571
|
+
x[1] = x[1] + 90; /* 3. Add 90 deg do decl - so get the point on house plane most distant from equ. */
|
1572
|
+
swe_cotrans(x, x, 90-geolat); /* 4. Rotate back to equator */
|
1573
|
+
oblaz = x[1]; /* 5. Obliquity of house plane to equator */
|
1574
|
+
/* II. Next find asc and planet position on house plane,
|
1575
|
+
* so to find relative distance of planet from
|
1576
|
+
* coords beginning. */
|
1577
|
+
/* IIa. Asc on house plane relative to intersection
|
1578
|
+
* of equator with 'asc-zenith' plane. */
|
1579
|
+
xasc[0] = asc; xasc[1] = 0.0; xasc[2] = 1.0;
|
1580
|
+
swe_cotrans(xasc, xasc, -eps);
|
1581
|
+
xasc[0] = swe_degnorm(xasc[0] - raaz);
|
1582
|
+
xtemp = atand(tand(xasc[0])/cosd(oblaz));
|
1583
|
+
if (xasc[0] > 90 && xasc[0] <= 270)
|
1584
|
+
xtemp = swe_degnorm(xtemp + 180);
|
1585
|
+
xasc[0] = swe_degnorm(xtemp);
|
1586
|
+
/* IIb. Planet on house plane relative to intersection
|
1587
|
+
* of equator with 'asc-zenith' plane */
|
1588
|
+
xp[0] = swe_degnorm(xeq[0] - raaz); /* Rotate on equator */
|
1589
|
+
xtemp = atand(tand(xp[0])/cosd(oblaz)); /* Find arc on house plane from equator */
|
1590
|
+
if (xp[0] > 90 && xp[0] <= 270)
|
1591
|
+
xtemp = swe_degnorm(xtemp + 180);
|
1592
|
+
xp[0] = swe_degnorm(xtemp);
|
1593
|
+
xp[0] = swe_degnorm(xp[0]-xasc[0]); /* find arc between asc and planet, and get planet house position */
|
1594
|
+
/* IIc. Distance from planet to house plane on declination circle: */
|
1595
|
+
x[0] = xeq[0];
|
1596
|
+
x[1] = xeq[1];
|
1597
|
+
swe_cotrans(x, x, oblaz);
|
1598
|
+
xp[1] = xeq[1] - x[1]; /* How many degrees is the point on declination circle from house circle */
|
1599
|
+
/* to make sure that a call with a house cusp position returns
|
1600
|
+
* a value within the house, 0.001" is added */
|
1601
|
+
xp[0] = swe_degnorm(xp[0] + MILLIARCSEC);
|
1602
|
+
hpos = xp[0] / 30.0 + 1;
|
1603
|
+
break;
|
1604
|
+
case 'H':
|
1605
|
+
xeq[0] = swe_degnorm(mdd - 90);
|
1606
|
+
swe_cotrans(xeq, xp, 90 - geolat);
|
1607
|
+
/* to make sure that a call with a house cusp position returns
|
1608
|
+
* a value within the house, 0.001" is added */
|
1609
|
+
xp[0] = swe_degnorm(xp[0] + MILLIARCSEC);
|
1610
|
+
hpos = xp[0] / 30.0 + 1;
|
1611
|
+
break;
|
1612
|
+
case 'R':
|
1613
|
+
if (fabs(mdd) < VERY_SMALL)
|
1614
|
+
xp[0] = 270;
|
1615
|
+
else if (180 - fabs(mdd) < VERY_SMALL)
|
1616
|
+
xp[0] = 90;
|
1617
|
+
else {
|
1618
|
+
if (90 - fabs(geolat) < VERY_SMALL) {
|
1619
|
+
if (geolat > 0)
|
1620
|
+
geolat = 90 - VERY_SMALL;
|
1621
|
+
else
|
1622
|
+
geolat = -90 + VERY_SMALL;
|
1623
|
+
}
|
1624
|
+
if (90 - fabs(de) < VERY_SMALL) {
|
1625
|
+
if (de > 0)
|
1626
|
+
de = 90 - VERY_SMALL;
|
1627
|
+
else
|
1628
|
+
de = -90 + VERY_SMALL;
|
1629
|
+
}
|
1630
|
+
a = tand(geolat) * tand(de) + cosd(mdd);
|
1631
|
+
xp[0] = swe_degnorm(atand(-a / sind(mdd)));
|
1632
|
+
if (mdd < 0)
|
1633
|
+
xp[0] += 180;
|
1634
|
+
xp[0] = swe_degnorm(xp[0]);
|
1635
|
+
/* to make sure that a call with a house cusp position returns
|
1636
|
+
* a value within the house, 0.001" is added */
|
1637
|
+
xp[0] = swe_degnorm(xp[0] + MILLIARCSEC);
|
1638
|
+
}
|
1639
|
+
hpos = xp[0] / 30.0 + 1;
|
1640
|
+
break;
|
1641
|
+
case 'T':
|
1642
|
+
mdd = swe_degnorm(mdd);
|
1643
|
+
if (de > 90 - VERY_SMALL)
|
1644
|
+
de = 90 - VERY_SMALL;
|
1645
|
+
if (de < -90 + VERY_SMALL)
|
1646
|
+
de = -90 + VERY_SMALL;
|
1647
|
+
sinad = tand(de) * tand(geolat);
|
1648
|
+
ad = asind(sinad);
|
1649
|
+
a = sinad + cosd(mdd);
|
1650
|
+
if (a >= 0)
|
1651
|
+
is_above_hor = TRUE;
|
1652
|
+
/* mirror everything below the horizon to the opposite point
|
1653
|
+
* above the horizon */
|
1654
|
+
if (!is_above_hor) {
|
1655
|
+
ra = swe_degnorm(ra + 180);
|
1656
|
+
de = -de;
|
1657
|
+
mdd = swe_degnorm(mdd + 180);
|
1658
|
+
}
|
1659
|
+
/* mirror everything on western hemisphere to eastern hemisphere */
|
1660
|
+
if (mdd > 180) {
|
1661
|
+
ra = swe_degnorm(armc - mdd);
|
1662
|
+
}
|
1663
|
+
/* binary search for "topocentric" position line of body */
|
1664
|
+
tanfi = tand(geolat);
|
1665
|
+
fh = geolat;
|
1666
|
+
ra0 = swe_degnorm(armc + 90);
|
1667
|
+
xp[1] = 1;
|
1668
|
+
xeq[1] = de;
|
1669
|
+
fac = 2;
|
1670
|
+
while (fabs(xp[1]) > 0.000001) {
|
1671
|
+
if (xp[1] > 0) {
|
1672
|
+
fh = atand(tand(fh) - tanfi / fac);
|
1673
|
+
ra0 -= 90 / fac;
|
1674
|
+
} else {
|
1675
|
+
fh = atand(tand(fh) + tanfi / fac);
|
1676
|
+
ra0 += 90 / fac;
|
1677
|
+
}
|
1678
|
+
xeq[0] = swe_degnorm(ra - ra0);
|
1679
|
+
swe_cotrans(xeq, xp, 90 - fh);
|
1680
|
+
fac *= 2;
|
1681
|
+
}
|
1682
|
+
hpos = swe_degnorm(ra0 - armc);
|
1683
|
+
/* mirror back to west */
|
1684
|
+
if (mdd > 180)
|
1685
|
+
hpos = swe_degnorm(-hpos);
|
1686
|
+
/* mirror back to below horizon */
|
1687
|
+
if (!is_above_hor)
|
1688
|
+
hpos = swe_degnorm(hpos + 180);
|
1689
|
+
hpos = swe_degnorm(hpos - 90) / 30 + 1;
|
1690
|
+
break;
|
1691
|
+
case 'P':
|
1692
|
+
case 'G':
|
1693
|
+
default:
|
1694
|
+
/* circumpolar region */
|
1695
|
+
if (90 - fabs(de) <= fabs(geolat)) {
|
1696
|
+
if (de * geolat < 0)
|
1697
|
+
xp[0] = swe_degnorm(90 + mdn / 2);
|
1698
|
+
else
|
1699
|
+
xp[0] = swe_degnorm(270 + mdd / 2);
|
1700
|
+
if (serr != NULL)
|
1701
|
+
strcpy(serr, "Otto Ludwig procedure within circumpolar regions.");
|
1702
|
+
} else {
|
1703
|
+
sinad = tand(de) * tand(geolat);
|
1704
|
+
ad = asind(sinad);
|
1705
|
+
a = sinad + cosd(mdd);
|
1706
|
+
if (a >= 0)
|
1707
|
+
is_above_hor = TRUE;
|
1708
|
+
sad = 90 + ad;
|
1709
|
+
san = 90 - ad;
|
1710
|
+
if (is_above_hor)
|
1711
|
+
xp[0] = (mdd / sad + 3) * 90;
|
1712
|
+
else
|
1713
|
+
xp[0] = (mdn / san + 1) * 90;
|
1714
|
+
/* to make sure that a call with a house cusp position returns
|
1715
|
+
* a value within the house, 0.001" is added */
|
1716
|
+
xp[0] = swe_degnorm(xp[0] + MILLIARCSEC);
|
1717
|
+
}
|
1718
|
+
if (hsys == 'G') {
|
1719
|
+
xp[0] = 360 - xp[0]; /* Gauquelin sectors are in clockwise direction */
|
1720
|
+
hpos = xp[0] / 10.0 + 1;
|
1721
|
+
} else {
|
1722
|
+
hpos = xp[0] / 30.0 + 1;
|
1723
|
+
}
|
1724
|
+
break;
|
1725
|
+
}
|
1726
|
+
return hpos;
|
1727
|
+
}
|