Iterate the Placidus cusps
Equal houses needed one starting direction and repeated addition. Placidus needs a direction that agrees with a calculation involving that same direction. We will follow the engine’s repeated estimates for four cusps, then convert and assemble a twelve-boundary list.
Before this lesson
Read “Choose a simple house convention.” We reuse the local meridian right ascension α, latitude φ and true obliquity ε from the orientation lessons. Right ascension measures an equatorial direction; a house cusp is an ecliptic longitude. Toy ε = 30° simplifies the arithmetic and is not a real-date obliquity.
What you will learn
Apply the four parameter sets, distinguish convergence from failure, convert right ascensions to longitudes, and place the solutions in house order.
Dotted-underlined terms open a definition beside the text. Select one to read more, then close it to continue.
Each step has its own check. Pass every step to complete the lesson. Your answers and checked steps are saved in this browser, so you can continue after leaving or reloading.
1. Find an estimate that agrees with its next update
Some calculations cannot be completed by evaluating a formula once, because the unknown appears inside the formula used to find it. Start with a guess, calculate an improved value, and use that value for another update. If successive values become sufficiently close, the engine accepts the latest estimate. This is a fixed-point iteration: it seeks a value that the update leaves unchanged.
For this update, sine and tangent use radians as usual. The inverse cosine, acos, asks which angle has a specified cosine. It returns a real angle only when the argument is between −1 and 1. Thus acos(0) = 90° and acos(0.5) = 60° after conversion from radians. Its argument is a dimensionless product, not a longitude.
q = s × sin(r × π/180) × tan(φ × π/180) × tan(ε × π/180)
r_next = b + t × f × acos(q) × 180/π
Here r is the current right ascension in degrees, b is a base angle in degrees, f is a fraction, and s and t are separate signs. The four source parameter sets are: cusp 11 has (b, f, t, s, seed) = (α, 1/3, +1, −1, α + 30°); cusp 12 has (α, 2/3, +1, −1, α + 60°); cusp 2 has (α + 180°, 2/3, −1, +1, α + 120°); cusp 3 has (α + 180°, 1/3, −1, +1, α + 150°). The sign inside acos and the sign multiplying its result do different jobs.
Begin with invented α = 0°, φ = 30° and ε = 30° for cusp 11. The seed is 30°. Since tan 30° × tan 30° = 1/3, q = −sin 30° / 3 = −1/6. The next value is acos(−1/6) / 3 ≈ 33.198022742°. Substituting that value back gives about 33.505359634°. The first update is not yet the answer: it changes the estimate by roughly 3.198°, far above the stopping threshold.
The implementation accepts next when |next − r| < 10⁻¹² degrees. It compares ordinary subtraction, not wrapped angular distance, and does not normalize intermediate right ascensions. It rejects |q| > 1 before acos; exact q = ±1 is allowed. If no accepted update occurs in 200 attempts, it returns None. A small change is the solver’s stopping condition, not proof of independent astronomical accuracy.
For an especially transparent example, set φ = 0°. Then tan φ = 0 and every q is zero. With α = 0°, the four accepted right ascensions are 30°, 60°, 120° and 150° for cusps 11, 12, 2 and 3 respectively. Their seeds already equal their updates, so each succeeds on its first attempt.
Why the system bears a person’s name
Swiss Ephemeris identifies Placidus de Titis (1590–1668), an Italian monk, as the namesake and describes division of day and night arcs. A semidiurnal arc is the part of a direction’s daily path from rising to its upper meridian passage. The name does not establish him as the inventor of this code or its stopping rules. This lesson reproduces the current update rather than deriving a general house theory.
See the teaching TypeScript
type Iteration = { base: number; fraction: number; term: number; argSign: number; seed: number };
const cuspRightAscension = (it: Iteration, latitude: number, obliquity: number): number | undefined => {
const d = Math.PI / 180;
const scale = Math.tan(latitude * d) * Math.tan(obliquity * d);
const update = (ra: number, remaining: number): number | undefined => {
if (remaining === 0) return undefined;
const arg = it.argSign * Math.sin(ra * d) * scale;
if (Math.abs(arg) > 1) return undefined;
const next = it.base + it.term * it.fraction * Math.acos(arg) / d;
return Math.abs(next - ra) < 1e-12 ? next : update(next, remaining - 1);
};
return update(it.seed, 200);
};Finite, correctly labeled inputs are assumed. This demonstrates the arithmetic; it does not fetch data or replace the engine.
Connect this step to the source
src/astro/houses.rs
placidus_cusp_ra; placidus_cusps
Paths refer to the astrology-engine repository. Examples use invented inputs; a successful exercise is not an astronomical-accuracy test.
Sources for this section
Apply this step
Answer every part, then check. You can retry as often as you like.
2. Convert four equatorial directions into twelve boundaries
The four solved directions are measured along the equator. The cusp list is measured along the ecliptic. Because these circles are tilted, a 30° right ascension need not be a 30° longitude. Conversion must happen before the opposite longitudes are constructed.
λ = wrap(atan2(sin(r × π/180) / cos(ε × π/180), cos(r × π/180)) × 180/π)
In the equatorial toy example α = 0°, φ = 0°, ε = 30°, the accepted r11 is 30°. The atan2 components are y = 0.5 / 0.866025404 ≈ 0.577350269 and x = 0.866025404. The longitude is therefore λ11 ≈ 33.690067526°. For r12 = 60°, y = 1 and x = 0.5, giving λ12 ≈ 63.434948823°. The other solutions convert to λ2 ≈ 116.565051177° and λ3 ≈ 146.309932474°.
For the same toy orientation, compute_angles gives Asc = 90° and MC = 0°. These supply cusps 1 and 10. The engine uses their half-turn opposites for cusps 7 and 4. The other opposite pairs are built from the converted cusp longitudes, so cusp 5 is wrap(λ11 + 180°) ≈ 213.690067526°, rather than r11 + 180° = 210°.
[Asc, λ2, λ3, wrap(MC + 180°), wrap(λ11 + 180°), wrap(λ12 + 180°), wrap(Asc + 180°), wrap(λ2 + 180°), wrap(λ3 + 180°), MC, λ11, λ12]
The complete toy list, rounded to six decimal places, is [90, 116.565051, 146.309932, 180, 213.690068, 243.434949, 270, 296.565051, 326.309932, 0, 33.690068, 63.434949] degrees. Array position zero is house 1; array position nine is house 10. The internal solve order 11, 12, 2, 3 is not the final house order.
See the teaching TypeScript
const wrap = (x: number): number => { const r = x % 360; return r < 0 ? r + 360 : r; };
const toLongitude = (rightAscension: number, obliquity: number): number => {
const d = Math.PI / 180;
return wrap(Math.atan2(Math.sin(rightAscension * d) / Math.cos(obliquity * d), Math.cos(rightAscension * d)) / d);
};
const assembleCusps = (asc: number, mc: number, c11: number, c12: number, c2: number, c3: number): number[] =>
[asc, c2, c3, wrap(mc + 180), wrap(c11 + 180), wrap(c12 + 180), wrap(asc + 180), wrap(c2 + 180), wrap(c3 + 180), mc, c11, c12];Finite, correctly labeled inputs are assumed. This demonstrates the arithmetic; it does not fetch data or replace the engine.
Connect this step to the source
src/astro/houses.rs
right_ascension_to_longitude; placidus_cusps
Paths refer to the astrology-engine repository. Examples use invented inputs; a successful exercise is not an astronomical-accuracy test.
Sources for this section
Apply this step
Answer every part, then check. You can retry as often as you like.
Your lesson checks
0 of 2 steps passed.
Use the feedback beside each check to retry any unfinished step.