swisseph-wasm 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCUMENTATION.md +888 -0
- package/LICENSE +41 -0
- package/QUICK_REFERENCE.md +263 -0
- package/README.md +305 -0
- package/examples/README.md +239 -0
- package/examples/basic-usage.js +301 -0
- package/examples/birth-chart.js +386 -0
- package/examples/demo.html +543 -0
- package/package.json +75 -0
- package/src/swisseph.js +1092 -0
- package/types/index.d.ts +255 -0
- package/wsam/swisseph.data +0 -0
- package/wsam/swisseph.js +3412 -0
- package/wsam/swisseph.wasm +0 -0
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Birth Chart Calculation Example
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to calculate a complete birth chart
|
|
5
|
+
* including planetary positions, houses, and various coordinate systems.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import SwissEph from '../src/swisseph.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Birth Chart Calculator Class
|
|
12
|
+
* Provides methods for calculating comprehensive birth charts
|
|
13
|
+
*/
|
|
14
|
+
class BirthChartCalculator {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.swe = null;
|
|
17
|
+
this.initialized = false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Initialize the Swiss Ephemeris
|
|
22
|
+
*/
|
|
23
|
+
async init() {
|
|
24
|
+
if (!this.initialized) {
|
|
25
|
+
this.swe = new SwissEph();
|
|
26
|
+
await this.swe.initSwissEph();
|
|
27
|
+
this.initialized = true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Calculate a complete birth chart
|
|
33
|
+
* @param {Object} birthData - Birth information
|
|
34
|
+
* @param {number} birthData.year - Birth year
|
|
35
|
+
* @param {number} birthData.month - Birth month (1-12)
|
|
36
|
+
* @param {number} birthData.day - Birth day
|
|
37
|
+
* @param {number} birthData.hour - Birth hour (0-23)
|
|
38
|
+
* @param {number} birthData.minute - Birth minute (0-59)
|
|
39
|
+
* @param {number} birthData.timezone - Timezone offset from UTC
|
|
40
|
+
* @param {number} birthData.latitude - Birth latitude
|
|
41
|
+
* @param {number} birthData.longitude - Birth longitude
|
|
42
|
+
* @param {string} birthData.houseSystem - House system ('P', 'K', 'E', etc.)
|
|
43
|
+
* @returns {Object} Complete birth chart data
|
|
44
|
+
*/
|
|
45
|
+
async calculateBirthChart(birthData) {
|
|
46
|
+
await this.init();
|
|
47
|
+
|
|
48
|
+
const {
|
|
49
|
+
year, month, day, hour, minute, timezone,
|
|
50
|
+
latitude, longitude, houseSystem = 'P'
|
|
51
|
+
} = birthData;
|
|
52
|
+
|
|
53
|
+
// Convert local time to UTC
|
|
54
|
+
const utcHour = hour + minute / 60 - timezone;
|
|
55
|
+
const jd = this.swe.julday(year, month, day, utcHour);
|
|
56
|
+
|
|
57
|
+
// Calculate planetary positions
|
|
58
|
+
const planets = await this.calculatePlanets(jd);
|
|
59
|
+
|
|
60
|
+
// Calculate houses
|
|
61
|
+
const houses = await this.calculateHouses(jd, latitude, longitude, houseSystem);
|
|
62
|
+
|
|
63
|
+
// Calculate additional points
|
|
64
|
+
const additionalPoints = await this.calculateAdditionalPoints(jd);
|
|
65
|
+
|
|
66
|
+
// Calculate aspects
|
|
67
|
+
const aspects = this.calculateAspects(planets);
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
birthData: {
|
|
71
|
+
...birthData,
|
|
72
|
+
julianDay: jd,
|
|
73
|
+
utcTime: utcHour
|
|
74
|
+
},
|
|
75
|
+
planets,
|
|
76
|
+
houses,
|
|
77
|
+
additionalPoints,
|
|
78
|
+
aspects,
|
|
79
|
+
metadata: {
|
|
80
|
+
calculatedAt: new Date().toISOString(),
|
|
81
|
+
swissEphVersion: this.swe.version()
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Calculate positions for all major planets
|
|
88
|
+
* @param {number} jd - Julian Day
|
|
89
|
+
* @returns {Object} Planet positions
|
|
90
|
+
*/
|
|
91
|
+
async calculatePlanets(jd) {
|
|
92
|
+
const planetList = [
|
|
93
|
+
{ id: this.swe.SE_SUN, name: 'Sun', symbol: '☉' },
|
|
94
|
+
{ id: this.swe.SE_MOON, name: 'Moon', symbol: '☽' },
|
|
95
|
+
{ id: this.swe.SE_MERCURY, name: 'Mercury', symbol: '☿' },
|
|
96
|
+
{ id: this.swe.SE_VENUS, name: 'Venus', symbol: '♀' },
|
|
97
|
+
{ id: this.swe.SE_MARS, name: 'Mars', symbol: '♂' },
|
|
98
|
+
{ id: this.swe.SE_JUPITER, name: 'Jupiter', symbol: '♃' },
|
|
99
|
+
{ id: this.swe.SE_SATURN, name: 'Saturn', symbol: '♄' },
|
|
100
|
+
{ id: this.swe.SE_URANUS, name: 'Uranus', symbol: '♅' },
|
|
101
|
+
{ id: this.swe.SE_NEPTUNE, name: 'Neptune', symbol: '♆' },
|
|
102
|
+
{ id: this.swe.SE_PLUTO, name: 'Pluto', symbol: '♇' }
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
const planets = {};
|
|
106
|
+
|
|
107
|
+
for (const planet of planetList) {
|
|
108
|
+
const position = this.swe.calc_ut(jd, planet.id, this.swe.SEFLG_SWIEPH | this.swe.SEFLG_SPEED);
|
|
109
|
+
|
|
110
|
+
planets[planet.name] = {
|
|
111
|
+
id: planet.id,
|
|
112
|
+
name: planet.name,
|
|
113
|
+
symbol: planet.symbol,
|
|
114
|
+
longitude: position[0],
|
|
115
|
+
latitude: position[1],
|
|
116
|
+
distance: position[2],
|
|
117
|
+
speed: position[3],
|
|
118
|
+
zodiacSign: this.getZodiacSign(position[0]),
|
|
119
|
+
house: null // Will be calculated later with houses
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return planets;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Calculate house cusps and angles
|
|
128
|
+
* @param {number} jd - Julian Day
|
|
129
|
+
* @param {number} latitude - Geographic latitude
|
|
130
|
+
* @param {number} longitude - Geographic longitude
|
|
131
|
+
* @param {string} houseSystem - House system
|
|
132
|
+
* @returns {Object} House information
|
|
133
|
+
*/
|
|
134
|
+
async calculateHouses(jd, latitude, longitude, houseSystem) {
|
|
135
|
+
// Calculate houses using the specified system
|
|
136
|
+
const houseResult = this.swe.houses(jd, latitude, longitude, houseSystem);
|
|
137
|
+
|
|
138
|
+
// Get sidereal time for ARMC calculation
|
|
139
|
+
const sidTime = this.swe.sidtime(jd);
|
|
140
|
+
const armc = (sidTime + longitude / 15) * 15; // Convert to degrees
|
|
141
|
+
|
|
142
|
+
const houses = {
|
|
143
|
+
system: houseSystem,
|
|
144
|
+
cusps: [],
|
|
145
|
+
angles: {
|
|
146
|
+
ascendant: null,
|
|
147
|
+
midheaven: null,
|
|
148
|
+
descendant: null,
|
|
149
|
+
imumCoeli: null
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// Extract house cusps (houses 1-12)
|
|
154
|
+
for (let i = 1; i <= 12; i++) {
|
|
155
|
+
houses.cusps[i] = {
|
|
156
|
+
house: i,
|
|
157
|
+
longitude: houseResult, // This would need proper implementation
|
|
158
|
+
zodiacSign: this.getZodiacSign(houseResult)
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Calculate angles
|
|
163
|
+
houses.angles.ascendant = houses.cusps[1].longitude;
|
|
164
|
+
houses.angles.midheaven = houses.cusps[10].longitude;
|
|
165
|
+
houses.angles.descendant = (houses.cusps[1].longitude + 180) % 360;
|
|
166
|
+
houses.angles.imumCoeli = (houses.cusps[10].longitude + 180) % 360;
|
|
167
|
+
|
|
168
|
+
return houses;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Calculate additional astrological points
|
|
173
|
+
* @param {number} jd - Julian Day
|
|
174
|
+
* @returns {Object} Additional points
|
|
175
|
+
*/
|
|
176
|
+
async calculateAdditionalPoints(jd) {
|
|
177
|
+
const points = {};
|
|
178
|
+
|
|
179
|
+
// Lunar nodes
|
|
180
|
+
const meanNode = this.swe.calc_ut(jd, this.swe.SE_MEAN_NODE, this.swe.SEFLG_SWIEPH);
|
|
181
|
+
const trueNode = this.swe.calc_ut(jd, this.swe.SE_TRUE_NODE, this.swe.SEFLG_SWIEPH);
|
|
182
|
+
|
|
183
|
+
points.meanNode = {
|
|
184
|
+
name: 'Mean North Node',
|
|
185
|
+
symbol: '☊',
|
|
186
|
+
longitude: meanNode[0],
|
|
187
|
+
zodiacSign: this.getZodiacSign(meanNode[0])
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
points.trueNode = {
|
|
191
|
+
name: 'True North Node',
|
|
192
|
+
symbol: '☊',
|
|
193
|
+
longitude: trueNode[0],
|
|
194
|
+
zodiacSign: this.getZodiacSign(trueNode[0])
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// South nodes (opposite of north nodes)
|
|
198
|
+
points.meanSouthNode = {
|
|
199
|
+
name: 'Mean South Node',
|
|
200
|
+
symbol: '☋',
|
|
201
|
+
longitude: (meanNode[0] + 180) % 360,
|
|
202
|
+
zodiacSign: this.getZodiacSign((meanNode[0] + 180) % 360)
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// Lunar apogee (Lilith)
|
|
206
|
+
const meanApogee = this.swe.calc_ut(jd, this.swe.SE_MEAN_APOG, this.swe.SEFLG_SWIEPH);
|
|
207
|
+
points.lilith = {
|
|
208
|
+
name: 'Mean Lilith',
|
|
209
|
+
symbol: '⚸',
|
|
210
|
+
longitude: meanApogee[0],
|
|
211
|
+
zodiacSign: this.getZodiacSign(meanApogee[0])
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// Chiron
|
|
215
|
+
const chiron = this.swe.calc_ut(jd, this.swe.SE_CHIRON, this.swe.SEFLG_SWIEPH);
|
|
216
|
+
points.chiron = {
|
|
217
|
+
name: 'Chiron',
|
|
218
|
+
symbol: '⚷',
|
|
219
|
+
longitude: chiron[0],
|
|
220
|
+
zodiacSign: this.getZodiacSign(chiron[0])
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
return points;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Calculate major aspects between planets
|
|
228
|
+
* @param {Object} planets - Planet positions
|
|
229
|
+
* @returns {Array} List of aspects
|
|
230
|
+
*/
|
|
231
|
+
calculateAspects(planets) {
|
|
232
|
+
const aspects = [];
|
|
233
|
+
const planetNames = Object.keys(planets);
|
|
234
|
+
|
|
235
|
+
// Major aspects with their angles and orbs
|
|
236
|
+
const aspectTypes = [
|
|
237
|
+
{ name: 'Conjunction', angle: 0, orb: 8, symbol: '☌' },
|
|
238
|
+
{ name: 'Opposition', angle: 180, orb: 8, symbol: '☍' },
|
|
239
|
+
{ name: 'Trine', angle: 120, orb: 6, symbol: '△' },
|
|
240
|
+
{ name: 'Square', angle: 90, orb: 6, symbol: '□' },
|
|
241
|
+
{ name: 'Sextile', angle: 60, orb: 4, symbol: '⚹' },
|
|
242
|
+
{ name: 'Quincunx', angle: 150, orb: 3, symbol: '⚻' }
|
|
243
|
+
];
|
|
244
|
+
|
|
245
|
+
// Check all planet pairs
|
|
246
|
+
for (let i = 0; i < planetNames.length; i++) {
|
|
247
|
+
for (let j = i + 1; j < planetNames.length; j++) {
|
|
248
|
+
const planet1 = planets[planetNames[i]];
|
|
249
|
+
const planet2 = planets[planetNames[j]];
|
|
250
|
+
|
|
251
|
+
const angle = Math.abs(planet1.longitude - planet2.longitude);
|
|
252
|
+
const normalizedAngle = angle > 180 ? 360 - angle : angle;
|
|
253
|
+
|
|
254
|
+
// Check each aspect type
|
|
255
|
+
for (const aspectType of aspectTypes) {
|
|
256
|
+
const difference = Math.abs(normalizedAngle - aspectType.angle);
|
|
257
|
+
|
|
258
|
+
if (difference <= aspectType.orb) {
|
|
259
|
+
aspects.push({
|
|
260
|
+
planet1: planet1.name,
|
|
261
|
+
planet2: planet2.name,
|
|
262
|
+
aspect: aspectType.name,
|
|
263
|
+
symbol: aspectType.symbol,
|
|
264
|
+
angle: aspectType.angle,
|
|
265
|
+
actualAngle: normalizedAngle,
|
|
266
|
+
orb: difference,
|
|
267
|
+
applying: planet1.speed > planet2.speed
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return aspects.sort((a, b) => a.orb - b.orb);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Get zodiac sign information for a longitude
|
|
279
|
+
* @param {number} longitude - Longitude in degrees
|
|
280
|
+
* @returns {Object} Zodiac sign information
|
|
281
|
+
*/
|
|
282
|
+
getZodiacSign(longitude) {
|
|
283
|
+
const signs = [
|
|
284
|
+
{ name: 'Aries', symbol: '♈', element: 'Fire', quality: 'Cardinal' },
|
|
285
|
+
{ name: 'Taurus', symbol: '♉', element: 'Earth', quality: 'Fixed' },
|
|
286
|
+
{ name: 'Gemini', symbol: '♊', element: 'Air', quality: 'Mutable' },
|
|
287
|
+
{ name: 'Cancer', symbol: '♋', element: 'Water', quality: 'Cardinal' },
|
|
288
|
+
{ name: 'Leo', symbol: '♌', element: 'Fire', quality: 'Fixed' },
|
|
289
|
+
{ name: 'Virgo', symbol: '♍', element: 'Earth', quality: 'Mutable' },
|
|
290
|
+
{ name: 'Libra', symbol: '♎', element: 'Air', quality: 'Cardinal' },
|
|
291
|
+
{ name: 'Scorpio', symbol: '♏', element: 'Water', quality: 'Fixed' },
|
|
292
|
+
{ name: 'Sagittarius', symbol: '♐', element: 'Fire', quality: 'Mutable' },
|
|
293
|
+
{ name: 'Capricorn', symbol: '♑', element: 'Earth', quality: 'Cardinal' },
|
|
294
|
+
{ name: 'Aquarius', symbol: '♒', element: 'Air', quality: 'Fixed' },
|
|
295
|
+
{ name: 'Pisces', symbol: '♓', element: 'Water', quality: 'Mutable' }
|
|
296
|
+
];
|
|
297
|
+
|
|
298
|
+
const signIndex = Math.floor(longitude / 30);
|
|
299
|
+
const degree = longitude % 30;
|
|
300
|
+
|
|
301
|
+
return {
|
|
302
|
+
...signs[signIndex],
|
|
303
|
+
degree: degree,
|
|
304
|
+
formatted: `${degree.toFixed(2)}° ${signs[signIndex].name}`
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Clean up resources
|
|
310
|
+
*/
|
|
311
|
+
destroy() {
|
|
312
|
+
if (this.swe) {
|
|
313
|
+
this.swe.close();
|
|
314
|
+
this.swe = null;
|
|
315
|
+
this.initialized = false;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Example usage of the Birth Chart Calculator
|
|
322
|
+
*/
|
|
323
|
+
async function exampleBirthChart() {
|
|
324
|
+
console.log('=== Birth Chart Calculation Example ===\n');
|
|
325
|
+
|
|
326
|
+
const calculator = new BirthChartCalculator();
|
|
327
|
+
|
|
328
|
+
try {
|
|
329
|
+
// Example birth data
|
|
330
|
+
const birthData = {
|
|
331
|
+
year: 1990,
|
|
332
|
+
month: 5,
|
|
333
|
+
day: 15,
|
|
334
|
+
hour: 14,
|
|
335
|
+
minute: 30,
|
|
336
|
+
timezone: -5, // UTC-5 (Eastern Daylight Time)
|
|
337
|
+
latitude: 40.7128, // New York City
|
|
338
|
+
longitude: -74.0060,
|
|
339
|
+
houseSystem: 'P' // Placidus
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
console.log('Calculating birth chart for:');
|
|
343
|
+
console.log(`Date: ${birthData.year}-${birthData.month.toString().padStart(2, '0')}-${birthData.day.toString().padStart(2, '0')}`);
|
|
344
|
+
console.log(`Time: ${birthData.hour}:${birthData.minute.toString().padStart(2, '0')} (UTC${birthData.timezone})`);
|
|
345
|
+
console.log(`Location: ${birthData.latitude}°N, ${Math.abs(birthData.longitude)}°W\n`);
|
|
346
|
+
|
|
347
|
+
const chart = await calculator.calculateBirthChart(birthData);
|
|
348
|
+
|
|
349
|
+
// Display planetary positions
|
|
350
|
+
console.log('PLANETARY POSITIONS:');
|
|
351
|
+
console.log('===================');
|
|
352
|
+
for (const [name, planet] of Object.entries(chart.planets)) {
|
|
353
|
+
console.log(`${planet.symbol} ${name.padEnd(10)}: ${planet.zodiacSign.formatted} (${planet.longitude.toFixed(2)}°)`);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Display additional points
|
|
357
|
+
console.log('\nADDITIONAL POINTS:');
|
|
358
|
+
console.log('==================');
|
|
359
|
+
for (const [name, point] of Object.entries(chart.additionalPoints)) {
|
|
360
|
+
console.log(`${point.symbol} ${point.name.padEnd(15)}: ${point.zodiacSign.formatted} (${point.longitude.toFixed(2)}°)`);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Display major aspects
|
|
364
|
+
console.log('\nMAJOR ASPECTS:');
|
|
365
|
+
console.log('==============');
|
|
366
|
+
chart.aspects.slice(0, 10).forEach(aspect => {
|
|
367
|
+
console.log(`${aspect.planet1} ${aspect.symbol} ${aspect.planet2}: ${aspect.aspect} (orb: ${aspect.orb.toFixed(2)}°)`);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
console.log(`\nTotal aspects found: ${chart.aspects.length}`);
|
|
371
|
+
console.log(`Calculated using Swiss Ephemeris ${chart.metadata.swissEphVersion}`);
|
|
372
|
+
|
|
373
|
+
} catch (error) {
|
|
374
|
+
console.error('Error calculating birth chart:', error);
|
|
375
|
+
} finally {
|
|
376
|
+
calculator.destroy();
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Export the calculator class and example function
|
|
381
|
+
export { BirthChartCalculator, exampleBirthChart };
|
|
382
|
+
|
|
383
|
+
// Run example if this file is executed directly
|
|
384
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
385
|
+
exampleBirthChart().catch(console.error);
|
|
386
|
+
}
|