summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/atragmx.c204
-rw-r--r--src/misc.c23
-rw-r--r--src/vector.c27
3 files changed, 211 insertions, 43 deletions
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) {
-
-}