From 1d1796c97867ada2211a39b313ef6398297c7b8f Mon Sep 17 00:00:00 2001 From: hybrid Date: Sat, 8 Aug 2026 08:10:17 +0300 Subject: upd: tmp --- .gitignore | 1 + Makefile | 8 +- example/example.c | 9 +++ include/ballistics.h | 17 +++++ include/constants.h | 4 + include/context.h | 1 + include/misc.h | 19 +++++ include/vector.h | 43 +++++++++-- src/atragmx.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++---- src/misc.c | 23 ++++++ src/vector.c | 27 ------- 11 files changed, 305 insertions(+), 51 deletions(-) create mode 100644 example/example.c create mode 100644 include/misc.h create mode 100644 src/misc.c delete mode 100644 src/vector.c diff --git a/.gitignore b/.gitignore index a753d23..bf73b04 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,4 @@ bin/** # emacs files .#.* compile_commands.json +.cache/clangd/index diff --git a/Makefile b/Makefile index ba28c77..c7c7777 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC := /usr/bin/gcc -CFLAGS = -Wall -Wpedantic -I$(INC_DIR) -O2 +CFLAGS = -Wall -Wpedantic -I$(INC_DIR) -O2 -fPIC LDLIBS := -lm # DIRS @@ -7,12 +7,14 @@ BASE_DIR = $(pwd) SRC_DIR = src BIN_DIR = bin OBJ_DIR = obj -#LIB_DIR := lib +LIB_DIR := lib BUILD_DIR = build INC_DIR = include +EXAMPLE_DIR = example # TARGETS -TARGET := $(BIN_DIR)/catragmx +LIBBALLISTIC := $(LIB_DIR)/libballistic.so +EXAMPLE := $(BIN_DIR)/example SOURCES := $(wildcard $(SRC_DIR)/*.c) OBJECTS := $(SOURCES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o) diff --git a/example/example.c b/example/example.c new file mode 100644 index 0000000..15615df --- /dev/null +++ b/example/example.c @@ -0,0 +1,9 @@ +#include +#include + +#include "atragmx.h" + +int main(int argc, char** argv) { + printf("Hello, %s\n", argv[0]); + exit(EXIT_SUCCESS); +} diff --git a/include/ballistics.h b/include/ballistics.h index ab68c3f..7ba4248 100644 --- a/include/ballistics.h +++ b/include/ballistics.h @@ -19,4 +19,21 @@ double retard(DragFunction drag_function, double velocity, double temperature); +typedef struct RangeCardRecord RangeCardRecord; +struct RangeCardRecord { + size_t n; + double range; + double elevation; + Windage windage; + double lead; + double time_of_flight; + double bullet_speed; + double kinetic_energy; +}; +typedef struct RangeCard RangeCard; +struct RangeCard { + RangeCardRecord *card; + size_t records; +}; + #endif diff --git a/include/constants.h b/include/constants.h index 026ff7b..f367e4b 100644 --- a/include/constants.h +++ b/include/constants.h @@ -11,4 +11,8 @@ static const double STD_AIR_DENSITY_ICAO = 1.22498; static const double STD_AIR_DENSITY_ASM = 1.20886; static const double BC_CONVERSION_FACTOR = 0.00068418; +static const double rangeCardStartRange = 200; +static const double rangeCardIncrement = 50; +static const double rangeCardEndRange = 2000; + #endif diff --git a/include/context.h b/include/context.h index 5dfad31..dd207bb 100644 --- a/include/context.h +++ b/include/context.h @@ -21,6 +21,7 @@ typedef struct { double ballistic_coef; DragFunction drag_model; double twist_dir; + double air_friction; } GunConfig; typedef struct { diff --git a/include/misc.h b/include/misc.h new file mode 100644 index 0000000..a0b235c --- /dev/null +++ b/include/misc.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include "misc.h" +#include "vector.h" + +#define MRAD_IN_DEG 17.45329252 + +double linearConversion(double min_from, + double max_from, + double value, + double min_to, + double max_to, + bool clip); + +static inline double MRAD_TO_DEG(double d) { + return d / MRAD_IN_DEG; +} diff --git a/include/vector.h b/include/vector.h index 72e6523..07d44cd 100644 --- a/include/vector.h +++ b/include/vector.h @@ -1,9 +1,42 @@ #pragma once -#include "vector.h" + +#include typedef struct { double x, y, z; } Vec3; -static inline double vec3_magnitude(Vec3 v); -static inline Vec3 vec3_diff(Vec3 a, Vec3 b); -static inline Vec3 vec3_normalize(Vec3 v); -static inline Vec3 vec3_mul(Vec3 v, double n); +static inline double vec3_magnitude(Vec3 v) { + return hypot(v.x, hypot(v.y, v.z)); +} + +static inline Vec3 vec3_diff(Vec3 a, Vec3 b) { + return (Vec3){.x = a.x - b.x, + .y = a.y - b.y, + .z = a.z - b.z}; +} + +static inline Vec3 vec3_normalize(Vec3 v) { + if (v.x == 0.0 || v.y == 0.0 || v.z == 0.0) + return (Vec3){.x = 0.0, + .y = 0.0, + .z = 0.0}; + + double len = sqrt(v.x * v.x + + v.y * v.y + + v.z * v.z); + return (Vec3){.x = v.x / len, + .y = v.y / len, + .z = v.z / len}; +} + +static inline Vec3 vec3_mul(Vec3 v, double n) { + return (Vec3) {.x = v.x * n, + .y = v.y * n, + .z = v.z * n}; +} + +static inline Vec3 vec3_add(Vec3 a, Vec3 b) { + return (Vec3) {.x = a.x + b.x, + .y = a.y + b.y, + .z = a.z + b.z}; +} + diff --git a/src/atragmx.c b/src/atragmx.c index 07cd580..c797505 100644 --- a/src/atragmx.c +++ b/src/atragmx.c @@ -8,6 +8,7 @@ #include "atragmx.h" #include "ace.h" #include "vector.h" +#include "misc.h" ATragMXSolution *ATragMXCalcSolution(ATragMXContext *ctx, ace_config *ace) { @@ -24,14 +25,6 @@ ATragMXSolution *ATragMXCalcSolution(ATragMXContext *ctx, ace_config *ace) { // local data - struct { - double speed1; - double speed2; - } wind = { - .speed1 = ctx->atmosphere.wind_speed[0], - .speed2 = ctx->atmosphere.wind_speed[1], - }; - struct { double tx; double tz; @@ -69,14 +62,19 @@ ATragMXSolution *ATragMXCalcSolution(ATragMXContext *ctx, ace_config *ace) { } local_solution = {0}; struct { + size_t n; double range; double true_range; double range_factor; - double *range_card; + RangeCard range_card; } ctx_range = { + .n = 0, .range_factor = ctx->store_range_card ? 1.0936133 : 1, - .range_card = NULL, + .range_card.records = (size_t) (rangeCardEndRange / rangeCardIncrement), + .range_card.card = calloc(ctx_range.range_card.records, + sizeof(RangeCardRecord)), }; + Vec3 wind1 = { .x = cos(270 - ctx->atmosphere.wind_dir * 30) @@ -122,6 +120,7 @@ ATragMXSolution *ATragMXCalcSolution(ATragMXContext *ctx, ace_config *ace) { while (local_solution.time_of_flight < 15 && bullet.pos.y < ctx->target.range) { + // calculate magnitude of bullet.velocity bullet.speed = vec3_magnitude(bullet.velocity); local_solution.true_velocity = vec3_diff(bullet.velocity, wind1); @@ -133,13 +132,186 @@ ATragMXSolution *ATragMXCalcSolution(ATragMXContext *ctx, ace_config *ace) { ctx->gun.ballistic_coef, ctx->gun.muzzle_velocity, ctx->atmosphere.temperature); - /* memcpy(bullet.accel, */ - /* (double[3]){bullet.accel[0] != 0 ? -data : 0, */ - /* bullet.accel[1] != 0 ? -data : 0, */ - /* bullet.accel[2] != 0 ? -data : 0}, */ - /* ); */ + + bullet.accel = vec3_mul(local_solution.true_velocity, + (-1.0 * data)); + } else { + bullet.accel = vec3_mul(local_solution.true_velocity, + local_solution.true_speed + * ctx->gun.air_friction); } + + bullet.accel = vec3_add(bullet.accel, bullet.gravity); + + bullet.last_pos = bullet.pos; + + bullet.pos = vec3_add(bullet.pos, + vec3_mul(bullet.velocity, bullet.deltaT * 0.5)); + + bullet.velocity = vec3_add(bullet.velocity, + vec3_mul(bullet.accel, bullet.deltaT)); + + bullet.pos = vec3_add(bullet.pos, + vec3_mul(bullet.velocity, bullet.deltaT * 0.5)); + + sln->time_of_flight = sln->time_of_flight + bullet.deltaT; + + // continue here + if (ctx->store_range_card) { + ctx_range.range = rangeCardStartRange + + ctx_range.n + * rangeCardIncrement; + + if (bullet.pos.x * ctx_range.range_factor >= ctx_range.range + && ctx_range.range <= rangeCardEndRange) { + + ctx_range.true_range = ctx_range.range / ctx_range.range_factor; + + if (ctx_range.true_range != 0) { + bullet.tx = linearConversion(bullet.last_pos.y, + bullet.pos.y, + ctx_range.true_range, + bullet.last_pos.x, + bullet.pos.x, false); + + bullet.tz = linearConversion(bullet.last_pos.y, + bullet.pos.y, + ctx_range.true_range, + bullet.last_pos.z, + bullet.pos.z, false); + + local_solution.elevation = - atan(bullet.tz + / ctx_range.true_range); + + local_solution.windage.w1 = - atan(bullet.tx + / ctx_range.true_range); + + wind_drift = wind2.x * (sln->time_of_flight + - ctx_range.true_range + / ctx->gun.muzzle_velocity); + + local_solution.windage.w2 = - atan(wind_drift + / ctx_range.true_range); + + sln->lead = (ctx->target.speed * sln->time_of_flight) + / (tan(MRAD_TO_DEG(1)) + * bullet.speed * bullet.speed); + } + double kinetic_energy = 0.5 * (ctx->gun.bullet_mass / 1000.0 + * (bullet.speed * bullet.speed)); + + kinetic_energy *= 0.737562149; + + if (ace->ballistics->enabled && bullet.pos.y > 0) { + // Coriolis + local_solution.h_coriolis_deflection = + 0.0000729 * bullet.pos.y * local_solution.time_of_flight + * sin(ctx->target.latitude); + + local_solution.h_coriolis = + - atan(local_solution.h_coriolis_deflection + / bullet.pos.y); + + local_solution.windage.w1 += local_solution.h_coriolis; + local_solution.windage.w2 += local_solution.h_coriolis; + + // Eoetvoes + local_solution.v_coriolis_deflection = + bullet.pos.z * eoetvoes_multiplier; + + local_solution.v_coriolis = + - atan(local_solution.v_coriolis_deflection + / bullet.pos.y); + + local_solution.elevation += local_solution.v_coriolis; + + // Spin drift + local_solution.spin_deflection = + ctx->gun.twist_dir * 0.0254 * 1.25 + * (ctx->stability_factor + 1.2) + * pow(local_solution.time_of_flight, 1.83); + + local_solution.spin_drift = + - atan(local_solution.spin_deflection / bullet.pos.y); + + local_solution.windage.w1 += local_solution.spin_drift; + local_solution.windage.w2 += local_solution.spin_drift; + } + + if (ctx_range.n < ctx_range.range_card.records) { + + ctx_range.range_card.card->n = ctx_range.n; + ctx_range.range_card.card->range = ctx_range.range; + + ctx_range.range_card.card->elevation + = local_solution.elevation; + + ctx_range.range_card.card->windage.w1 + = local_solution.windage.w1 * 60.0; + + ctx_range.range_card.card->windage.w2 + = local_solution.windage.w2 * 60.0; + + ctx_range.range_card.card->lead = sln->lead; + + ctx_range.range_card.card->time_of_flight + = local_solution.time_of_flight; + + ctx_range.range_card.card->bullet_speed = bullet.speed; + ctx_range.range_card.card->kinetic_energy = kinetic_energy; + } + ctx_range.n++; + } + } } + + double kinetic_energy = 0.5 * (ctx->gun.bullet_mass / 1000.0 * + (bullet.speed * bullet.speed)); + kinetic_energy *= 0.737562149; + + if (ace->ballistics->enabled && bullet.pos.y > 0) { + // Coriolis + local_solution.h_coriolis_deflection = 0.0000729 * bullet.pos.y * + local_solution.time_of_flight * + sin(ctx->target.latitude); + + local_solution.h_coriolis = + -atan(local_solution.h_coriolis_deflection / bullet.pos.y); + + local_solution.windage.w1 += local_solution.h_coriolis; + local_solution.windage.w2 += local_solution.h_coriolis; + + // Eoetvoes + local_solution.v_coriolis_deflection = + bullet.pos.z * eoetvoes_multiplier; + + local_solution.v_coriolis = + -atan(local_solution.v_coriolis_deflection / bullet.pos.y); + + local_solution.elevation += local_solution.v_coriolis; + + // Spin drift + local_solution.spin_deflection = + ctx->gun.twist_dir * 0.0254 * 1.25 * (ctx->stability_factor + 1.2) * + pow(local_solution.time_of_flight, 1.83); + + local_solution.spin_drift = + -atan(local_solution.spin_deflection / bullet.pos.y); + + local_solution.windage.w1 += local_solution.spin_drift; + local_solution.windage.w2 += local_solution.spin_drift; + } + + sln->elev = local_solution.elevation * 60.0; + sln->windage.w1 = local_solution.windage.w1 * 60.0; + sln->windage.w2 = local_solution.windage.w2 * 60.0; + sln->lead = local_solution.lead; + sln->time_of_flight = local_solution.time_of_flight; + sln->remaining_velocity = bullet.speed; + sln->remaining_energy = kinetic_energy; + sln->coriolis_vdrift = local_solution.v_coriolis * 60.0; + sln->coriolis_hdrift = local_solution.h_coriolis * 60.0; + sln->spin_drift = local_solution.spin_drift * 60.0; - return sln; + return sln; } diff --git a/src/misc.c b/src/misc.c new file mode 100644 index 0000000..a01a70d --- /dev/null +++ b/src/misc.c @@ -0,0 +1,23 @@ +#include "misc.h" + +double linearConversion(double min_from, double max_from, double value, + double min_to, double max_to, bool clip) { + // prevent division by zero + if (max_from == min_from) { + return min_to; + } + + // main formula + double result = min_to + (value - min_from) * (max_to - min_to) / (max_from - min_from); + + // check clipping + if (clip) { + if (result < min_to) { + result = min_to; + } else if (result > max_to) { + result = max_to; + } + } + + return result; +} diff --git a/src/vector.c b/src/vector.c deleted file mode 100644 index 7274cbb..0000000 --- a/src/vector.c +++ /dev/null @@ -1,27 +0,0 @@ -#include - -#include "vector.h" - -static inline double vec3_magnitude(Vec3 v) { - return hypot(v.x, hypot(v.y, v.z)); -} - -static inline Vec3 vec3_diff(Vec3 a, Vec3 b) { - return (Vec3){.x = a.x - b.x, - .y = a.y - b.y, - .z = a.z - b.z}; -} - -static inline Vec3 vec3_normalize(Vec3 v) { - double len = sqrt(v.x * v.x - + v.y * v.y - + v.z * v.z); - if (len != 0.0) - return (Vec3){.x = v.x / len, - .y = v.y / len, - .z = v.z / len}; -} - -static inline Vec3 vec3_mul(Vec3 v, double n) { - -} -- cgit v1.3.1