Vedākṣha

Integration Guide

Transit Search

Vedākṣha includes a transit search engine that finds the exact moment of any planetary event — aspects to natal positions, solar and lunar returns, or user-defined celestial conditions — using an adaptive step and bisection algorithm.

How the Search Engine Works

Brute-force transit finding is slow: computing a full chart for every minute of a year requires ~525,000 ephemeris calls. Vedākṣha uses a two-phase approach that is both fast and accurate.

1

Adaptive Step Scan

The engine starts with a coarse step (default: 1 day) and monitors the sign of the separation between the transiting planet and the target. When the sign changes, a transit has occurred somewhere in that interval.

2

Bisection Refinement

Once a bracket is found, bisection narrows the exact crossing to within a configurable tolerance (default: 1 second of time). The algorithm converges in ~17 iterations regardless of the initial step size.

Setting Up a Transit Search

Construct a TransitSearch with the natal chart, date range, and which transiting bodies and aspect types to look for. The result is an iterator of TransitEvent values in chronological order.

transit_search.rs
use vedaksha::prelude::*;

let birth_jd = calendar_to_jd(1990, 6, 15, 6.0);
let natal    = compute_chart(birth_jd, 28.6139, 77.2090, &ChartConfig::tropical())?;

// Search window: 2024 calendar year
let start_jd = calendar_to_jd(2024, 1, 1, 0.0);
let end_jd   = calendar_to_jd(2024, 12, 31, 23.99);

let search = TransitSearch::new(&natal)
    .date_range(start_jd, end_jd)
    .bodies(&[Body::Jupiter, Body::Saturn, Body::Uranus])
    .aspects(&[AspectType::Conjunction, AspectType::Opposition, AspectType::Trine])
    .orb(1.0)
    .build();

for event in search.find()? {
    let date = jd_to_calendar(event.exact_jd);
    println!(
        "{}-{:02}-{:02}: transiting {} {} natal {}",
        date.year, date.month, date.day,
        event.transiting_body,
        event.aspect_type,
        event.natal_body,
    );
}

TransitEvent Fields

.exact_jdf64

Julian Day of the exact aspect moment, accurate to within the configured tolerance.

.transiting_bodyBody

The transiting planet — the one moving through the natal chart.

.natal_bodyBody

The natal planet being aspected.

.aspect_typeAspectType

The aspect type formed (Conjunction, Trine, etc.).

.applyingbool

True if this event represents the ingress into orb (applying); false for the exit (separating).

.transiting_longitudef64

Ecliptic longitude of the transiting planet at the exact moment.

Solar and Lunar Returns

A solar return is the moment the Sun returns to its exact natal longitude. A lunar return is the equivalent for the Moon, occurring approximately once per month. Both use the same bisection engine internally.

returns.rs
// Solar return — Sun back to natal longitude
let sr = solar_return(&natal, 2024)?;
let sr_date = jd_to_calendar(sr.exact_jd);
println!("Solar return: {}-{:02}-{:02} {:05.2}h UT",
    sr_date.year, sr_date.month, sr_date.day, sr_date.hour_ut);

// Full solar return chart at the exact moment
let sr_chart = compute_chart(
    sr.exact_jd,
    sr_location_lat,  // location at time of return, if relocating
    sr_location_lon,
    &ChartConfig::tropical()
)?;

// Lunar return — Moon back to natal longitude
// Returns the next one after start_jd
let lr = lunar_return(&natal, start_jd)?;

Synastry (Inter-Chart Aspects)

Synastry compares two natal charts and finds all aspects formed between their planets. Each aspect in the result identifies which person's planet is aspecting the other.

synastry.rs
let chart_a = compute_chart(jd_a, lat_a, lon_a, &config)?;
let chart_b = compute_chart(jd_b, lat_b, lon_b, &config)?;

let synastry = find_synastry_aspects(
    &chart_a,
    &chart_b,
    &AspectConfig::default(),
)?;

for asp in &synastry.aspects {
    println!(
        "A's {} {} B's {} (orb {:.2}°)",
        asp.body_a, asp.aspect_type, asp.body_b, asp.orb
    );
}

Composite Chart (Midpoint Method)

A composite chart is constructed by taking the midpoint of each pair of corresponding planets from two natal charts. The result is a single synthetic chart representing the relationship itself. Vedākṣha uses the near-midpoint method (selecting the midpoint that produces a coherent chart rather than its opposite).

composite.rs
let composite = compute_composite_chart(&chart_a, &chart_b)?;

// composite.planets[i].longitude is the near-midpoint
// of chart_a.planets[i] and chart_b.planets[i]

for planet in &composite.planets {
    println!("{}: {:.4}°", planet.body, planet.longitude);
}

Muhurta Search

Muhurta is the Vedic practice of selecting an auspicious moment for an activity. Vedākṣha's muhurta engine searches a date range for windows that satisfy a set of configurable criteria drawn from classical Jyotish.

muhurta.rs
let criteria = MuhurtaCriteria {
    avoid_nakshatras: vec![Nakshatra::Bharani, Nakshatra::Krittika],
    require_weekdays:  vec![Weekday::Monday, Weekday::Wednesday, Weekday::Thursday],
    avoid_tithis:      vec![Tithi::Amavasya, Tithi::Chaturdashi],
    require_moon_sign: Some(Sign::Taurus),
    min_score:         0.7,
};

let windows = find_muhurta(start_jd, end_jd, lat, lon, &criteria)?;

for window in windows.iter().take(5) {
    let start = jd_to_calendar(window.start_jd);
    let end   = jd_to_calendar(window.end_jd);
    println!(
        "{}-{:02}-{:02} {:04.1}h – {:04.1}h UT  score: {:.2}",
        start.year, start.month, start.day,
        start.hour_ut, end.hour_ut,
        window.score,
    );
}
avoid_nakshatras

Exclude specific lunar mansions.

require_weekdays

Only return results on specified weekdays.

avoid_tithis

Exclude specific lunar days (1–30).

require_moon_sign

Moon must be in a specified sign.

planetary_hora

Match a specific planetary hora (hourly ruler).

min_score

Threshold for the overall auspiciousness score.