vibe coding an orbital mechanics simulation to try out claude code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

268 lines
9.3 KiB

#include "config_validator.h"
#include <cstdio>
#include <cmath>
#include <cstring>
bool validate_parent_index_ordering(SimulationState* sim) {
for (int i = 0; i < sim->body_count; i++) {
if (sim->bodies[i].parent_index != -1 && sim->bodies[i].parent_index >= i) {
printf("Error: Body '%s' (index %d) has invalid parent_index %d - must be < %d or -1\n",
sim->bodies[i].name, i, sim->bodies[i].parent_index, i);
return false;
}
}
for (int i = 0; i < sim->craft_count; i++) {
Spacecraft* craft = &sim->spacecraft[i];
if (craft->parent_index < 0 || craft->parent_index >= sim->body_count) {
printf("Error: Spacecraft '%s' has invalid parent_index %d (valid: 0-%d)\n",
craft->name, craft->parent_index, sim->body_count - 1);
return false;
}
}
return true;
}
bool validate_orbital_elements(SimulationState* sim) {
for (int i = 0; i < sim->body_count; i++) {
CelestialBody* body = &sim->bodies[i];
if (body->parent_index < 0) {
continue;
}
bool is_parabolic = (fabs(body->orbit.eccentricity - 1.0) < 0.005);
if (body->orbit.eccentricity < 0.0) {
printf("Error: Body '%s' has invalid eccentricity: %.2e (must be >= 0)\n",
body->name, body->orbit.eccentricity);
return false;
}
if (is_parabolic) {
if (body->orbit.semi_latus_rectum <= 0.0) {
printf("Error: Body '%s' has parabolic orbit but non-positive semi_latus_rectum: %.2e\n",
body->name, body->orbit.semi_latus_rectum);
return false;
}
} else {
if (body->orbit.semi_major_axis == 0.0) {
printf("Error: Body '%s' has invalid semi_major_axis: %.2e (must not be zero)\n",
body->name, body->orbit.semi_major_axis);
return false;
}
if (body->orbit.eccentricity < 1.0 && body->orbit.semi_major_axis <= 0.0) {
printf("Error: Body '%s' has elliptical orbit but non-positive semi_major_axis: %.2e\n",
body->name, body->orbit.semi_major_axis);
return false;
}
}
}
for (int i = 0; i < sim->craft_count; i++) {
Spacecraft* craft = &sim->spacecraft[i];
bool is_parabolic = (fabs(craft->orbit.eccentricity - 1.0) < 0.005);
if (is_parabolic) {
if (craft->orbit.semi_latus_rectum <= 0.0) {
printf("Error: Spacecraft '%s' has parabolic orbit but non-positive semi_latus_rectum: %.2e\n",
craft->name, craft->orbit.semi_latus_rectum);
return false;
}
} else {
if (fabs(craft->orbit.semi_major_axis) < 1e-10) {
printf("Error: Spacecraft '%s' has invalid semi_major_axis: %.2e (must not be zero)\n",
craft->name, craft->orbit.semi_major_axis);
return false;
}
if (craft->orbit.eccentricity < 1.0 && craft->orbit.semi_major_axis <= 0.0) {
printf("Error: Spacecraft '%s' has elliptical orbit but non-positive semi_major_axis: %.2e\n",
craft->name, craft->orbit.semi_major_axis);
return false;
}
}
if (craft->orbit.eccentricity < 0.0) {
printf("Error: Spacecraft '%s' has invalid eccentricity: %.3f (must be >= 0)\n",
craft->name, craft->orbit.eccentricity);
return false;
}
}
return true;
}
bool validate_mass_ratios(SimulationState* sim) {
for (int i = 0; i < sim->body_count; i++) {
CelestialBody* body = &sim->bodies[i];
if (body->parent_index < 0 || body->parent_index >= sim->body_count) {
continue;
}
CelestialBody* parent = &sim->bodies[body->parent_index];
double mass_ratio = parent->mass / body->mass;
double radius_ratio = body->radius / parent->radius;
if (parent->parent_index < 0 && radius_ratio > 0.5 && mass_ratio < MIN_MASS_RATIO) {
printf("Error: Body '%s' (mass=%.2e kg, radius=%.2e m) has insufficient mass ratio with root parent '%s' (mass=%.2e kg, radius=%.2e m)\n",
body->name, body->mass, body->radius, parent->name, parent->mass, parent->radius);
printf(" Mass ratio: %.2f (minimum required: %.2f)\n", mass_ratio, MIN_MASS_RATIO);
printf(" Radius ratio: %.2f (triggers validation for radius > 50%% of parent)\n", radius_ratio);
return false;
}
}
return true;
}
bool validate_soi_overlap(SimulationState* sim) {
for (int i = 0; i < sim->body_count; i++) {
CelestialBody* body_i = &sim->bodies[i];
if (body_i->parent_index < 0) {
continue;
}
for (int j = i + 1; j < sim->body_count; j++) {
CelestialBody* body_j = &sim->bodies[j];
if (body_j->parent_index != body_i->parent_index) {
continue;
}
double distance = vec3_distance(body_i->global_position, body_j->global_position);
double combined_soi = body_i->soi_radius + body_j->soi_radius;
if (distance < combined_soi) {
printf("Error: Bodies '%s' and '%s' have overlapping SOIs while sharing same parent '%s'\n",
body_i->name, body_j->name, sim->bodies[body_i->parent_index].name);
printf(" Separation: %.2e m\n", distance);
printf(" Combined SOI: %.2e m (%.2e + %.2e)\n",
combined_soi, body_i->soi_radius, body_j->soi_radius);
printf(" SOI overlap: %.2e m\n", combined_soi - distance);
return false;
}
}
}
return true;
}
bool validate_nested_orbits(SimulationState* sim) {
for (int i = 0; i < sim->body_count; i++) {
CelestialBody* body = &sim->bodies[i];
if (body->parent_index < 0 || body->parent_index >= sim->body_count) {
continue;
}
CelestialBody* parent = &sim->bodies[body->parent_index];
if (parent->parent_index < 0) {
continue;
}
double radius_ratio = body->radius / parent->radius;
if (radius_ratio > 0.3) {
continue;
}
if (body->orbit.eccentricity > 0.5) {
continue;
}
if (body->mass < 1e20) {
continue;
}
double child_orbit_radius = body->orbit.semi_major_axis;
double parent_soi = parent->soi_radius;
double max_allowed = NESTED_ORBIT_FRACTION * parent_soi;
if (child_orbit_radius > max_allowed) {
printf("Error: Body '%s' orbit extends too far from parent '%s'\n",
body->name, parent->name);
printf(" Child orbit radius: %.2e m\n", child_orbit_radius);
printf(" Parent SOI radius: %.2e m\n", parent_soi);
printf(" Maximum allowed: %.2e m (%.2f%% of parent SOI)\n",
max_allowed, NESTED_ORBIT_FRACTION * 100.0);
return false;
}
}
return true;
}
bool validate_initial_positions(SimulationState* sim) {
for (int i = 0; i < sim->body_count; i++) {
CelestialBody* body = &sim->bodies[i];
if (body->parent_index >= 0 && body->parent_index < sim->body_count) {
CelestialBody* parent = &sim->bodies[body->parent_index];
double distance = vec3_magnitude(vec3_sub(body->global_position, parent->global_position));
double min_distance = parent->radius + body->radius;
if (distance < min_distance) {
printf("Error: Body '%s' (index %d) too close to parent '%s' (index %d)\n",
body->name, i, parent->name, body->parent_index);
printf(" Distance: %.2e m\n", distance);
printf(" Minimum required: %.2e m (parent radius + body radius)\n", min_distance);
return false;
}
}
}
for (int i = 0; i < sim->craft_count; i++) {
Spacecraft* craft = &sim->spacecraft[i];
if (craft->parent_index >= 0 && craft->parent_index < sim->body_count) {
CelestialBody* parent = &sim->bodies[craft->parent_index];
double distance = vec3_magnitude(vec3_sub(craft->global_position, parent->global_position));
double min_distance = parent->radius;
if (distance < min_distance) {
printf("Error: Spacecraft '%s' too close to parent '%s'\n",
craft->name, parent->name);
printf(" Distance: %.2e m\n", distance);
printf(" Minimum required: %.2e m (parent radius)\n", min_distance);
return false;
}
}
}
return true;
}
bool run_all_config_validations(SimulationState* sim) {
if (!validate_parent_index_ordering(sim)) {
return false;
}
if (!validate_orbital_elements(sim)) {
return false;
}
if (!validate_mass_ratios(sim)) {
return false;
}
if (!validate_soi_overlap(sim)) {
return false;
}
if (!validate_nested_orbits(sim)) {
return false;
}
if (!validate_initial_positions(sim)) {
return false;
}
return true;
}