summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhybrid <hybrid@hybridlabs.pro>2026-08-08 08:10:17 +0300
committerhybrid <hybrid@hybridlabs.pro>2026-08-08 08:10:17 +0300
commit1d1796c97867ada2211a39b313ef6398297c7b8f (patch)
tree927e9c477d7a974fb219ed9963fced6ea8109b5c
parent884bac2a767bf5bf77413c055a6484a7ea87700c (diff)
downloada3catragmx-1d1796c97867ada2211a39b313ef6398297c7b8f.tar.gz
a3catragmx-1d1796c97867ada2211a39b313ef6398297c7b8f.tar.bz2
a3catragmx-1d1796c97867ada2211a39b313ef6398297c7b8f.zip
upd: tmp
-rw-r--r--.gitignore1
-rw-r--r--Makefile8
-rw-r--r--example/example.c9
-rw-r--r--include/ballistics.h17
-rw-r--r--include/constants.h4
-rw-r--r--include/context.h1
-rw-r--r--include/misc.h19
-rw-r--r--include/vector.h43
-rw-r--r--src/atragmx.c204
-rw-r--r--src/misc.c23
-rw-r--r--src/vector.c27
11 files changed, 305 insertions, 51 deletions
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 <stdio.h>
+#include <stdlib.h>
+
+#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 <stdbool.h>
+
+#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 <math.h>
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 <math.h>
-
-#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) {
-
-}