From a260d24d36656fad1e5f3c18129dcccbf60d0ea4 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Fri, 16 Jan 2026 14:20:59 -0500 Subject: [PATCH] Simplify find_dominant_body based on parent type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement much simpler SOI transition logic: If parent is not root (parent_idx != 0): - Only two options: stay with parent or go to Sun - If within parent's SOI: stay with current parent - If outside parent's SOI: switch to Sun (index 0) If parent is root (parent_idx == 0): - Check all bodies for SOI containment - Find closest body whose SOI contains us - If no SOI contains us: stay with Sun Benefits: - Eliminates unnecessary N-body comparisons when inside parent's SOI - Prevents unphysical transitions (Moon→Mars while in Earth's SOI) - Much simpler and more maintainable logic - Enables proper patched conics: Earth→Sun→Mars→Sun→Earth Test results: - SOI transition test now passes (2 parent changes: Sun→Mars→Sun) - All 24 tests passing - Net change: +18/-21 lines --- src/simulation.cpp | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/simulation.cpp b/src/simulation.cpp index 5000393..7bad5af 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -60,28 +60,33 @@ int add_body_to_simulation(SimulationState* sim, CelestialBody* body) { return new_idx; } -// Find which body is gravitationally dominant for the given body int find_dominant_body(SimulationState* sim, int body_index) { if (body_index < 0 || body_index >= sim->body_count) { return -1; } CelestialBody* body = &sim->bodies[body_index]; - int dominant = body->parent_index; + int parent_idx = body->parent_index; - // If within current parent's SOI → stay with current parent - if (dominant >= 0 && dominant < sim->body_count) { - CelestialBody* parent = &sim->bodies[dominant]; + // If parent is not root (not Sun): only check if still within parent's SOI + if (parent_idx != 0) { + if (parent_idx < 0 || parent_idx >= sim->body_count) { + return -1; + } + + CelestialBody* parent = &sim->bodies[parent_idx]; double distance = vec3_distance(body->position, parent->position); + // Stay with parent if within SOI, otherwise go to Sun if (distance < parent->soi_radius) { - return dominant; + return parent_idx; + } else { + return 0; } } - // Outside current parent's SOI (or has no parent) - // Find new parent: body we're within SOI of and closest to - int new_parent = -1; + // Parent is root (Sun): check all bodies for SOI containment + int new_parent = 0; double min_distance = INFINITY; for (int i = 0; i < sim->body_count; i++) { @@ -90,23 +95,15 @@ int find_dominant_body(SimulationState* sim, int body_index) { CelestialBody* potential = &sim->bodies[i]; double distance = vec3_distance(body->position, potential->position); - // Only consider bodies we're within SOI of - if (distance < potential->soi_radius) { - if (distance < min_distance) { - min_distance = distance; - new_parent = i; - } + // If within SOI and closer than current, switch to this body + if (distance < potential->soi_radius && distance < min_distance) { + min_distance = distance; + new_parent = i; } } - // If no body's SOI contains us, fall back to root (Sun) - if (new_parent == -1) { - new_parent = 0; - } - return new_parent; } - // Update sphere of influence radius using Hill sphere approximation // r_soi = a * (m/M)^(2/5) where a = semi-major axis, m = body mass, M = parent mass void update_soi(CelestialBody* body, CelestialBody* parent, double semi_major_axis) {