Browse Source

Refactor config loader to extract orbit parsing into helper function

main
cinnaboot 5 months ago
parent
commit
840623d34d
  1. 173
      src/config_loader.cpp

173
src/config_loader.cpp

@ -29,43 +29,14 @@ static bool extract_color_from_table(toml_datum_t table, float* color) {
return true;
}
static bool parse_toml_body(toml_datum_t body_table, CelestialBody* body) {
// Extract string fields
toml_datum_t name = toml_get(body_table, "name");
if (name.type != TOML_STRING) {
return false;
}
strncpy(body->name, name.u.s, 63);
body->name[63] = '\0';
// Extract numeric fields
toml_datum_t mass = toml_get(body_table, "mass");
toml_datum_t radius = toml_get(body_table, "radius");
toml_datum_t parent_idx = toml_get(body_table, "parent_index");
if (mass.type != TOML_FP64 || radius.type != TOML_FP64 ||
parent_idx.type != TOML_INT64) {
return false;
}
body->mass = mass.u.fp64;
body->radius = radius.u.fp64;
body->parent_index = (int)(parent_idx.type == TOML_INT64 ? parent_idx.u.int64 : (int)parent_idx.u.fp64);
// Parse orbit table
toml_datum_t orbit_table = toml_get(body_table, "orbit");
if (orbit_table.type != TOML_TABLE) {
printf("Error: Body '%s' missing required 'orbit' table\n", body->name);
return false;
}
static bool parse_toml_orbit(toml_datum_t orbit_table, OrbitalElements* orbit, const char* object_name) {
// Initialize orbital elements with defaults
body->orbit.semi_major_axis = 0.0;
body->orbit.eccentricity = 0.0;
body->orbit.inclination = 0.0;
body->orbit.longitude_of_ascending_node = 0.0;
body->orbit.argument_of_periapsis = 0.0;
body->orbit.true_anomaly = 0.0;
orbit->semi_major_axis = 0.0;
orbit->eccentricity = 0.0;
orbit->inclination = 0.0;
orbit->longitude_of_ascending_node = 0.0;
orbit->argument_of_periapsis = 0.0;
orbit->true_anomaly = 0.0;
// Parse semi_major_axis (for elliptical/hyperbolic) or semi_latus_rectum (for parabolic)
toml_datum_t semi_major = toml_get(orbit_table, "semi_major_axis");
@ -74,58 +45,95 @@ static bool parse_toml_body(toml_datum_t body_table, CelestialBody* body) {
// Parse eccentricity first to determine which parameter is required
toml_datum_t eccentricity = toml_get(orbit_table, "eccentricity");
if (eccentricity.type != TOML_FP64) {
printf("Error: Body '%s' missing required 'eccentricity' in orbit table\n", body->name);
printf("Error: Object '%s' missing required 'eccentricity' in orbit table\n", object_name);
return false;
}
body->orbit.eccentricity = eccentricity.u.fp64;
orbit->eccentricity = eccentricity.u.fp64;
bool is_parabolic = (fabs(body->orbit.eccentricity - 1.0) < 0.005);
bool is_parabolic = (fabs(orbit->eccentricity - 1.0) < 0.005);
if (is_parabolic) {
// Parabolic orbit - requires semi_latus_rectum
if (semi_latus.type != TOML_FP64) {
printf("Error: Parabolic orbit for body '%s' requires 'semi_latus_rectum' (not 'semi_major_axis')\n", body->name);
printf("Error: Parabolic orbit for object '%s' requires 'semi_latus_rectum' (not 'semi_major_axis')\n", object_name);
return false;
}
body->orbit.semi_latus_rectum = semi_latus.u.fp64;
orbit->semi_latus_rectum = semi_latus.u.fp64;
if (semi_major.type == TOML_FP64) {
printf("Warning: Body '%s' has parabolic eccentricity, 'semi_latus_rectum' used instead of 'semi_major_axis'\n", body->name);
printf("Warning: Object '%s' has parabolic eccentricity, 'semi_latus_rectum' used instead of 'semi_major_axis'\n", object_name);
}
} else {
// Elliptical or hyperbolic - requires semi_major_axis
if (semi_major.type == TOML_FP64) {
body->orbit.semi_major_axis = semi_major.u.fp64;
orbit->semi_major_axis = semi_major.u.fp64;
} else {
printf("Error: Body '%s' must have 'semi_major_axis' in orbit table (non-parabolic orbits)\n", body->name);
printf("Error: Object '%s' must have 'semi_major_axis' in orbit table (non-parabolic orbits)\n", object_name);
return false;
}
if (semi_latus.type == TOML_FP64) {
printf("Warning: Body '%s' has non-parabolic eccentricity, 'semi_latus_rectum' ignored\n", body->name);
printf("Warning: Object '%s' has non-parabolic eccentricity, 'semi_latus_rectum' ignored\n", object_name);
}
}
// Parse true_anomaly (optional, default 0.0)
toml_datum_t true_anomaly = toml_get(orbit_table, "true_anomaly");
if (true_anomaly.type == TOML_FP64) {
body->orbit.true_anomaly = true_anomaly.u.fp64;
orbit->true_anomaly = true_anomaly.u.fp64;
}
// Parse inclination (optional, default 0.0)
toml_datum_t inclination = toml_get(orbit_table, "inclination");
if (inclination.type == TOML_FP64) {
body->orbit.inclination = inclination.u.fp64;
orbit->inclination = inclination.u.fp64;
}
// Parse longitude_of_ascending_node (optional, default 0.0)
toml_datum_t raan = toml_get(orbit_table, "longitude_of_ascending_node");
if (raan.type == TOML_FP64) {
body->orbit.longitude_of_ascending_node = raan.u.fp64;
orbit->longitude_of_ascending_node = raan.u.fp64;
}
// Parse argument_of_periapsis (optional, default 0.0)
toml_datum_t aop = toml_get(orbit_table, "argument_of_periapsis");
if (aop.type == TOML_FP64) {
body->orbit.argument_of_periapsis = aop.u.fp64;
orbit->argument_of_periapsis = aop.u.fp64;
}
return true;
}
static bool parse_toml_body(toml_datum_t body_table, CelestialBody* body) {
// Extract string fields
toml_datum_t name = toml_get(body_table, "name");
if (name.type != TOML_STRING) {
return false;
}
strncpy(body->name, name.u.s, 63);
body->name[63] = '\0';
// Extract numeric fields
toml_datum_t mass = toml_get(body_table, "mass");
toml_datum_t radius = toml_get(body_table, "radius");
toml_datum_t parent_idx = toml_get(body_table, "parent_index");
if (mass.type != TOML_FP64 || radius.type != TOML_FP64 ||
parent_idx.type != TOML_INT64) {
return false;
}
body->mass = mass.u.fp64;
body->radius = radius.u.fp64;
body->parent_index = (int)(parent_idx.type == TOML_INT64 ? parent_idx.u.int64 : (int)parent_idx.u.fp64);
// Parse orbit table
toml_datum_t orbit_table = toml_get(body_table, "orbit");
if (orbit_table.type != TOML_TABLE) {
printf("Error: Body '%s' missing required 'orbit' table\n", body->name);
return false;
}
if (!parse_toml_orbit(orbit_table, &body->orbit, body->name)) {
return false;
}
// Extract color
@ -275,74 +283,9 @@ static bool parse_toml_spacecraft(toml_datum_t craft_table, Spacecraft* craft) {
return false;
}
// Initialize orbital elements with defaults
craft->orbit.semi_major_axis = 0.0;
craft->orbit.eccentricity = 0.0;
craft->orbit.inclination = 0.0;
craft->orbit.longitude_of_ascending_node = 0.0;
craft->orbit.argument_of_periapsis = 0.0;
craft->orbit.true_anomaly = 0.0;
// Parse semi_major_axis (for elliptical/hyperbolic) or semi_latus_rectum (for parabolic)
toml_datum_t semi_major = toml_get(orbit_table, "semi_major_axis");
toml_datum_t semi_latus = toml_get(orbit_table, "semi_latus_rectum");
// Parse eccentricity first to determine which parameter is required
toml_datum_t eccentricity = toml_get(orbit_table, "eccentricity");
if (eccentricity.type != TOML_FP64) {
printf("Error: Spacecraft '%s' missing required 'eccentricity' in orbit table\n", craft->name);
if (!parse_toml_orbit(orbit_table, &craft->orbit, craft->name)) {
return false;
}
craft->orbit.eccentricity = eccentricity.u.fp64;
bool is_parabolic = (fabs(craft->orbit.eccentricity - 1.0) < 0.005);
if (is_parabolic) {
// Parabolic orbit - requires semi_latus_rectum
if (semi_latus.type != TOML_FP64) {
printf("Error: Parabolic orbit for spacecraft '%s' requires 'semi_latus_rectum' (not 'semi_major_axis')\n", craft->name);
return false;
}
craft->orbit.semi_latus_rectum = semi_latus.u.fp64;
if (semi_major.type == TOML_FP64) {
printf("Warning: Spacecraft '%s' has parabolic eccentricity, 'semi_latus_rectum' used instead of 'semi_major_axis'\n", craft->name);
}
} else {
// Elliptical or hyperbolic - requires semi_major_axis
if (semi_major.type == TOML_FP64) {
craft->orbit.semi_major_axis = semi_major.u.fp64;
} else {
printf("Error: Spacecraft '%s' must have 'semi_major_axis' in orbit table (non-parabolic orbits)\n", craft->name);
return false;
}
if (semi_latus.type == TOML_FP64) {
printf("Warning: Spacecraft '%s' has non-parabolic eccentricity, 'semi_latus_rectum' ignored\n", craft->name);
}
}
// Parse true_anomaly (optional, default 0.0)
toml_datum_t true_anomaly = toml_get(orbit_table, "true_anomaly");
if (true_anomaly.type == TOML_FP64) {
craft->orbit.true_anomaly = true_anomaly.u.fp64;
}
// Parse inclination (optional, default 0.0)
toml_datum_t inclination = toml_get(orbit_table, "inclination");
if (inclination.type == TOML_FP64) {
craft->orbit.inclination = inclination.u.fp64;
}
// Parse longitude_of_ascending_node (optional, default 0.0)
toml_datum_t raan = toml_get(orbit_table, "longitude_of_ascending_node");
if (raan.type == TOML_FP64) {
craft->orbit.longitude_of_ascending_node = raan.u.fp64;
}
// Parse argument_of_periapsis (optional, default 0.0)
toml_datum_t aop = toml_get(orbit_table, "argument_of_periapsis");
if (aop.type == TOML_FP64) {
craft->orbit.argument_of_periapsis = aop.u.fp64;
}
// Initialize position and velocity (will be calculated later from orbital elements)
craft->global_position = {0.0, 0.0, 0.0};

Loading…
Cancel
Save