ballistics-engine 0.13.3 → 0.13.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-APACHE +201 -0
- package/README.md +206 -526
- package/ballistics_engine.d.ts +64 -0
- package/ballistics_engine.js +247 -181
- package/ballistics_engine_bg.wasm +0 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -1,614 +1,294 @@
|
|
|
1
|
-
# Ballistics Engine
|
|
1
|
+
# Ballistics Engine (WebAssembly)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
High-performance ballistics trajectory calculations for JavaScript and TypeScript applications. This package provides WebAssembly bindings for the ballistics-engine library, delivering near-native performance in the browser.
|
|
4
4
|
|
|
5
5
|
**Project Website:** [https://ballistics.rs/](https://ballistics.rs/)
|
|
6
6
|
|
|
7
|
-
## Features
|
|
8
|
-
|
|
9
|
-
- **Full 3D Trajectory Integration** - Six-state ballistic modeling with adaptive RK45 and fixed-step RK4 integration methods
|
|
10
|
-
- **Advanced Drag Models** - Support for G1, G7, and custom drag curves with automatic transonic corrections
|
|
11
|
-
- **Automatic Zeroing** - Calculate sight adjustments and apply zero angles automatically
|
|
12
|
-
- **Unit Conversion** - Seamless switching between Imperial (default) and Metric units
|
|
13
|
-
- **BC Segmentation** - Velocity-dependent ballistic coefficient modeling with automatic estimation
|
|
14
|
-
- **Atmospheric Modeling** - Temperature, pressure, humidity, and altitude effects with ICAO standard atmosphere
|
|
15
|
-
- **Wind Effects** - 3D wind calculations with altitude-dependent wind shear modeling
|
|
16
|
-
- **Monte Carlo Simulations** - Statistical analysis with parameter uncertainties
|
|
17
|
-
- **BC Estimation** - Estimate ballistic coefficients from trajectory data
|
|
18
|
-
- **Advanced Physics**:
|
|
19
|
-
- **Spin Effects**: Magnus effect, enhanced spin drift with decay modeling
|
|
20
|
-
- **Earth Effects**: Coriolis effect with latitude-dependent calculations
|
|
21
|
-
- **Angular Motion**: Gyroscopic precession and nutation physics
|
|
22
|
-
- **Transonic Analysis**: Pitch damping coefficients and stability warnings
|
|
23
|
-
- **Trajectory Sampling**: Regular interval data collection for analysis
|
|
24
|
-
- **Form Factor Corrections**: Bullet-specific drag adjustments
|
|
25
|
-
- **Multiple Output Formats** - JSON, CSV, and formatted tables
|
|
26
|
-
|
|
27
7
|
## Installation
|
|
28
8
|
|
|
29
|
-
### From Source
|
|
30
|
-
|
|
31
9
|
```bash
|
|
32
|
-
|
|
33
|
-
cd ballistics-engine
|
|
34
|
-
cargo build --release
|
|
10
|
+
npm install ballistics-engine
|
|
35
11
|
```
|
|
36
12
|
|
|
37
|
-
The binary will be at: `target/release/ballistics`
|
|
38
|
-
|
|
39
13
|
## Quick Start
|
|
40
14
|
|
|
41
|
-
###
|
|
15
|
+
### ES Modules (Browser/Bundler)
|
|
42
16
|
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
./ballistics trajectory -v 2700 -b 0.475 -m 168 -d 0.308 --max-range 1000
|
|
17
|
+
```javascript
|
|
18
|
+
import init, { Calculator } from 'ballistics-engine';
|
|
46
19
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
```
|
|
20
|
+
// Initialize the WASM module first
|
|
21
|
+
await init();
|
|
50
22
|
|
|
51
|
-
|
|
23
|
+
// Create a calculator with default values (.308 Win, 168gr at 2700 fps)
|
|
24
|
+
const calc = new Calculator();
|
|
52
25
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
26
|
+
// Configure your load
|
|
27
|
+
calc
|
|
28
|
+
.setVelocity(2700) // fps
|
|
29
|
+
.setBC(0.475) // G1 ballistic coefficient
|
|
30
|
+
.setMass(168) // grains
|
|
31
|
+
.setDiameter(0.308) // inches
|
|
32
|
+
.setZeroRange(200) // zero at 200 yards
|
|
33
|
+
.setWind(10, 90); // 10 mph from the right
|
|
57
34
|
|
|
58
|
-
|
|
35
|
+
// Calculate trajectory at a specific range
|
|
36
|
+
const result = calc.calculateTrajectory(500);
|
|
37
|
+
console.log(result);
|
|
38
|
+
// { range_yards: 500, drop_inches: -48.2, windage_inches: 15.3, velocity_fps: 2145, energy_ftlb: 1715, time_sec: 0.62 }
|
|
59
39
|
|
|
60
|
-
|
|
40
|
+
// Get full trajectory table
|
|
41
|
+
const trajectory = calc.getFullTrajectory();
|
|
42
|
+
console.log(trajectory);
|
|
43
|
+
// Array of trajectory points from 0 to max range
|
|
61
44
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
- **Distance**: yards
|
|
66
|
-
- **Diameter**: inches
|
|
67
|
-
- **Temperature**: Fahrenheit
|
|
68
|
-
- **Pressure**: inHg
|
|
69
|
-
- **Wind**: mph
|
|
45
|
+
// Clean up when done
|
|
46
|
+
calc.free();
|
|
47
|
+
```
|
|
70
48
|
|
|
71
|
-
###
|
|
72
|
-
- **Velocity**: meters per second (m/s)
|
|
73
|
-
- **Mass**: grams
|
|
74
|
-
- **Distance**: meters
|
|
75
|
-
- **Diameter**: millimeters
|
|
76
|
-
- **Temperature**: Celsius
|
|
77
|
-
- **Pressure**: hPa (millibars)
|
|
78
|
-
- **Wind**: m/s
|
|
49
|
+
### With TypeScript
|
|
79
50
|
|
|
80
|
-
|
|
51
|
+
```typescript
|
|
52
|
+
import init, { Calculator } from 'ballistics-engine';
|
|
81
53
|
|
|
82
|
-
|
|
54
|
+
async function main() {
|
|
55
|
+
await init();
|
|
83
56
|
|
|
84
|
-
|
|
57
|
+
const calc = new Calculator()
|
|
58
|
+
.setVelocity(3000)
|
|
59
|
+
.setBC(0.620)
|
|
60
|
+
.setMass(140)
|
|
61
|
+
.setDiameter(0.264)
|
|
62
|
+
.setDragModel('g7')
|
|
63
|
+
.setZeroRange(100);
|
|
85
64
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
./ballistics trajectory \
|
|
89
|
-
-v 2700 # Velocity (fps)
|
|
90
|
-
-b 0.475 # Ballistic coefficient
|
|
91
|
-
-m 168 # Mass (grains)
|
|
92
|
-
-d 0.308 # Diameter (inches)
|
|
93
|
-
--drag-model g7 # G7 drag model
|
|
94
|
-
--angle 0 # Launch angle (degrees)
|
|
95
|
-
--max-range 1000 # Maximum range (yards)
|
|
96
|
-
--wind-speed 10 # Wind speed (mph)
|
|
97
|
-
--wind-direction 90 # Wind from right (degrees)
|
|
98
|
-
--temperature 59 # Temperature (Fahrenheit)
|
|
99
|
-
--pressure 29.92 # Pressure (inHg)
|
|
100
|
-
--humidity 50 # Relative humidity (%)
|
|
101
|
-
--altitude 0 # Altitude (feet)
|
|
102
|
-
--full # Show all trajectory points
|
|
103
|
-
```
|
|
65
|
+
const result = calc.calculateTrajectory(1000);
|
|
66
|
+
console.log(`Drop at 1000 yards: ${result.drop_inches.toFixed(1)} inches`);
|
|
104
67
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
Automatically calculate and apply the zero angle for a specific distance:
|
|
68
|
+
calc.free();
|
|
69
|
+
}
|
|
108
70
|
|
|
109
|
-
|
|
110
|
-
# Zero at 200 yards and show trajectory to 500 yards
|
|
111
|
-
./ballistics trajectory \
|
|
112
|
-
-v 2700 -b 0.475 -m 168 -d 0.308 \
|
|
113
|
-
--auto-zero 200 \ # Automatically zero at 200 yards
|
|
114
|
-
--max-range 500 \
|
|
115
|
-
--full
|
|
116
|
-
|
|
117
|
-
# Custom sight height for auto-zero
|
|
118
|
-
./ballistics trajectory \
|
|
119
|
-
-v 2700 -b 0.475 -m 168 -d 0.308 \
|
|
120
|
-
--auto-zero 100 \
|
|
121
|
-
--sight-height 0.055 # 2.2 inches in yards
|
|
71
|
+
main();
|
|
122
72
|
```
|
|
123
73
|
|
|
124
|
-
|
|
74
|
+
## API Reference
|
|
125
75
|
|
|
126
|
-
|
|
76
|
+
### Calculator Class
|
|
127
77
|
|
|
128
|
-
|
|
129
|
-
# Enable BC segmentation (velocity-based BC changes)
|
|
130
|
-
./ballistics trajectory \
|
|
131
|
-
-v 2700 -b 0.475 -m 168 -d 0.308 \
|
|
132
|
-
--use-bc-segments \
|
|
133
|
-
--auto-zero 600 \
|
|
134
|
-
--max-range 1000
|
|
135
|
-
```
|
|
78
|
+
A fluent, chainable API for trajectory calculations.
|
|
136
79
|
|
|
137
|
-
####
|
|
80
|
+
#### Constructor
|
|
138
81
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
```bash
|
|
142
|
-
# Magnus effect and spin drift calculation
|
|
143
|
-
./ballistics trajectory \
|
|
144
|
-
-v 2700 -b 0.475 -m 168 -d 0.308 \
|
|
145
|
-
--twist-rate 10 # 1:10" barrel twist
|
|
146
|
-
--twist-right # Right-hand twist
|
|
147
|
-
--enable-magnus # Enable Magnus effect
|
|
148
|
-
--enable-spin-drift # Enable enhanced spin drift
|
|
149
|
-
--wind-speed 10 \
|
|
150
|
-
--wind-direction 90 \
|
|
151
|
-
--max-range 1000
|
|
152
|
-
|
|
153
|
-
# Coriolis effect for extreme long range
|
|
154
|
-
./ballistics trajectory \
|
|
155
|
-
-v 3000 -b 0.750 -m 250 -d 0.338 \
|
|
156
|
-
--enable-coriolis \
|
|
157
|
-
--latitude 45 # Shooting latitude
|
|
158
|
-
--shooting-angle 90 # Azimuth (0=N, 90=E)
|
|
159
|
-
--max-range 2000
|
|
82
|
+
```javascript
|
|
83
|
+
const calc = new Calculator();
|
|
160
84
|
```
|
|
161
85
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
86
|
+
Creates a calculator with sensible defaults:
|
|
87
|
+
- .308 Winchester 168gr at 2700 fps
|
|
88
|
+
- G1 drag model
|
|
89
|
+
- Standard atmosphere (59°F, 29.92 inHg)
|
|
90
|
+
|
|
91
|
+
#### Configuration Methods
|
|
92
|
+
|
|
93
|
+
All methods return `this` for chaining.
|
|
94
|
+
|
|
95
|
+
| Method | Parameters | Description |
|
|
96
|
+
|--------|------------|-------------|
|
|
97
|
+
| `setVelocity(fps)` | `number` | Muzzle velocity in feet per second |
|
|
98
|
+
| `setBC(bc)` | `number` | Ballistic coefficient (G1 or G7) |
|
|
99
|
+
| `setMass(grains)` | `number` | Bullet weight in grains |
|
|
100
|
+
| `setDiameter(inches)` | `number` | Bullet diameter in inches |
|
|
101
|
+
| `setDragModel(model)` | `'g1'` \| `'g7'` | Drag model to use |
|
|
102
|
+
| `setZeroRange(yards)` | `number` | Zero distance in yards |
|
|
103
|
+
| `setSightHeight(inches)` | `number` | Scope height above bore |
|
|
104
|
+
| `setMaxRange(yards)` | `number` | Maximum calculation range |
|
|
105
|
+
| `setWind(mph, degrees)` | `number, number` | Wind speed and direction (0°=headwind, 90°=from right) |
|
|
106
|
+
| `setTemperature(fahrenheit)` | `number` | Ambient temperature |
|
|
107
|
+
| `setPressure(inHg)` | `number` | Barometric pressure |
|
|
108
|
+
| `setHumidity(percent)` | `number` | Relative humidity (0-100) |
|
|
109
|
+
| `setAltitude(feet)` | `number` | Shooting altitude |
|
|
110
|
+
| `enableSpinDrift(enabled, twistRate?)` | `boolean, number?` | Enable spin drift (twist rate in inches) |
|
|
111
|
+
| `enableCoriolis(enabled, latitude?)` | `boolean, number?` | Enable Coriolis effect |
|
|
112
|
+
|
|
113
|
+
#### Calculation Methods
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
// Calculate at specific range
|
|
117
|
+
const point = calc.calculateTrajectory(500);
|
|
118
|
+
|
|
119
|
+
// Get full trajectory table
|
|
120
|
+
const trajectory = calc.getFullTrajectory();
|
|
182
121
|
```
|
|
183
122
|
|
|
184
|
-
|
|
185
|
-
- Zero angle in degrees
|
|
186
|
-
- Adjustment in MOA (Minutes of Angle)
|
|
187
|
-
- Adjustment in mrad (milliradians)
|
|
188
|
-
- Maximum ordinate (highest point of trajectory)
|
|
189
|
-
|
|
190
|
-
### Monte Carlo Simulation
|
|
191
|
-
|
|
192
|
-
Run statistical analysis with parameter variations:
|
|
123
|
+
#### Result Object
|
|
193
124
|
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
--bc-std 0.01 # BC std dev
|
|
204
|
-
--wind-std 2 # Wind speed std dev (mph)
|
|
205
|
-
--target-distance 300 # Target distance for hit probability
|
|
125
|
+
```typescript
|
|
126
|
+
interface TrajectoryPoint {
|
|
127
|
+
range_yards: number; // Distance from muzzle
|
|
128
|
+
drop_inches: number; // Bullet drop (negative = below line of sight)
|
|
129
|
+
windage_inches: number; // Wind deflection (positive = right)
|
|
130
|
+
velocity_fps: number; // Remaining velocity
|
|
131
|
+
energy_ftlb: number; // Remaining energy
|
|
132
|
+
time_sec: number; // Time of flight
|
|
133
|
+
}
|
|
206
134
|
```
|
|
207
135
|
|
|
208
|
-
###
|
|
209
|
-
|
|
210
|
-
Estimate ballistic coefficient from observed trajectory data:
|
|
211
|
-
|
|
212
|
-
```bash
|
|
213
|
-
./ballistics estimate-bc \
|
|
214
|
-
-v 2700 -m 168 -d 0.308 \
|
|
215
|
-
--distance1 100 --drop1 0.0 # First data point
|
|
216
|
-
--distance2 200 --drop2 0.023 # Second data point
|
|
217
|
-
```
|
|
136
|
+
### WasmBallistics Class
|
|
218
137
|
|
|
219
|
-
|
|
138
|
+
A CLI-style interface for running commands as strings.
|
|
220
139
|
|
|
221
|
-
|
|
140
|
+
```javascript
|
|
141
|
+
import init, { WasmBallistics } from 'ballistics-engine';
|
|
222
142
|
|
|
223
|
-
|
|
143
|
+
await init();
|
|
224
144
|
|
|
225
|
-
|
|
226
|
-
- **RK4 (Runge-Kutta 4th Order Fixed-Step)** - Available with `--use-rk4-fixed` flag for faster computation
|
|
145
|
+
const ballistics = new WasmBallistics();
|
|
227
146
|
|
|
228
|
-
|
|
147
|
+
// Run trajectory command
|
|
148
|
+
const output = ballistics.runCommand(
|
|
149
|
+
'trajectory -v 2700 -b 0.475 -m 168 -d 0.308 --auto-zero 200 --max-range 1000 -o json'
|
|
150
|
+
);
|
|
229
151
|
|
|
230
|
-
|
|
152
|
+
console.log(JSON.parse(output));
|
|
231
153
|
|
|
232
|
-
|
|
233
|
-
./ballistics trajectory -v 2700 -b 0.475 -m 168 -d 0.308 \
|
|
234
|
-
--wind-speed 10 --wind-direction 90 \
|
|
235
|
-
--enable-wind-shear \
|
|
236
|
-
--max-range 1000
|
|
154
|
+
ballistics.free();
|
|
237
155
|
```
|
|
238
156
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
Analyze projectile stability through the transonic regime:
|
|
242
|
-
|
|
243
|
-
```bash
|
|
244
|
-
./ballistics trajectory -v 3000 -b 0.475 -m 168 -d 0.308 \
|
|
245
|
-
--enable-pitch-damping \
|
|
246
|
-
--max-range 2000
|
|
247
|
-
```
|
|
157
|
+
## Examples
|
|
248
158
|
|
|
249
|
-
|
|
159
|
+
### Long-Range Trajectory
|
|
250
160
|
|
|
251
|
-
|
|
161
|
+
```javascript
|
|
162
|
+
const calc = new Calculator()
|
|
163
|
+
.setVelocity(2850)
|
|
164
|
+
.setBC(0.690) // G7 BC
|
|
165
|
+
.setMass(230)
|
|
166
|
+
.setDiameter(0.338)
|
|
167
|
+
.setDragModel('g7')
|
|
168
|
+
.setZeroRange(100)
|
|
169
|
+
.setMaxRange(1500)
|
|
170
|
+
.setWind(10, 270) // 10 mph from left
|
|
171
|
+
.setAltitude(5000) // High altitude
|
|
172
|
+
.setTemperature(75);
|
|
252
173
|
|
|
253
|
-
|
|
174
|
+
const trajectory = calc.getFullTrajectory();
|
|
254
175
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
--sample-interval 25 # Sample every 25 yards
|
|
259
|
-
--max-range 1000 -o json
|
|
176
|
+
// Find data at 1000 yards
|
|
177
|
+
const point1000 = trajectory.find(p => p.range_yards === 1000);
|
|
178
|
+
console.log(`At 1000 yards: ${point1000.drop_inches.toFixed(1)}" drop, ${point1000.windage_inches.toFixed(1)}" wind`);
|
|
260
179
|
```
|
|
261
180
|
|
|
262
|
-
###
|
|
263
|
-
|
|
264
|
-
Model precession and nutation of spinning projectiles:
|
|
181
|
+
### Environmental Effects
|
|
265
182
|
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
183
|
+
```javascript
|
|
184
|
+
// Hot day, high altitude
|
|
185
|
+
const calc = new Calculator()
|
|
186
|
+
.setVelocity(2700)
|
|
187
|
+
.setBC(0.475)
|
|
188
|
+
.setMass(168)
|
|
189
|
+
.setDiameter(0.308)
|
|
190
|
+
.setTemperature(95) // Hot day
|
|
191
|
+
.setAltitude(8000) // Mountain shooting
|
|
192
|
+
.setPressure(24.5) // Lower pressure at altitude
|
|
193
|
+
.setHumidity(20); // Dry air
|
|
194
|
+
|
|
195
|
+
// Velocity will stay higher due to thinner air
|
|
271
196
|
```
|
|
272
197
|
|
|
273
|
-
###
|
|
274
|
-
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
--shooting-angle 45 \
|
|
289
|
-
--wind-speed 15 --wind-direction 270 \
|
|
290
|
-
--altitude 6000 \
|
|
291
|
-
--max-range 2000
|
|
198
|
+
### With Spin Drift
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
const calc = new Calculator()
|
|
202
|
+
.setVelocity(2700)
|
|
203
|
+
.setBC(0.475)
|
|
204
|
+
.setMass(168)
|
|
205
|
+
.setDiameter(0.308)
|
|
206
|
+
.enableSpinDrift(true, 10) // 1:10" twist, right-hand
|
|
207
|
+
.setZeroRange(100)
|
|
208
|
+
.setMaxRange(1000);
|
|
209
|
+
|
|
210
|
+
// Spin drift adds to windage at long range
|
|
211
|
+
const point = calc.calculateTrajectory(1000);
|
|
212
|
+
console.log(`Spin drift at 1000: ${point.windage_inches.toFixed(1)}"`);
|
|
292
213
|
```
|
|
293
214
|
|
|
294
|
-
##
|
|
295
|
-
|
|
296
|
-
The ballistics engine implements comprehensive physics modeling for accurate trajectory prediction:
|
|
215
|
+
## Browser Usage
|
|
297
216
|
|
|
298
|
-
###
|
|
299
|
-
- **Drag Modeling** - Multiple drag functions (G1-G8, JBM, custom curves) with transonic flow corrections
|
|
300
|
-
- **Form Factor** - Projectile efficiency corrections based on shape and design
|
|
301
|
-
- **Reynolds Number Effects** - Viscosity and flow regime corrections
|
|
217
|
+
### With a Bundler (Vite, Webpack, etc.)
|
|
302
218
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
- **Precession** - Gyroscopic precession of spinning projectile
|
|
306
|
-
- **Nutation** - Oscillatory motion superimposed on precession
|
|
307
|
-
- **Spin Decay** - Reduction in spin rate over time due to aerodynamic damping
|
|
308
|
-
- **Pitch Damping** - Aerodynamic moments opposing angular motion
|
|
219
|
+
```javascript
|
|
220
|
+
import init, { Calculator } from 'ballistics-engine';
|
|
309
221
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
- **Wind Shear** - Altitude-dependent wind variations
|
|
314
|
-
- **Atmospheric Stratification** - Density and sound speed variations with altitude
|
|
315
|
-
|
|
316
|
-
### Stability Modeling
|
|
317
|
-
- **Dynamic Stability** - Gyroscopic and aerodynamic stability calculations
|
|
318
|
-
- **Yaw of Repose** - Equilibrium yaw angle in crosswind
|
|
319
|
-
- **Limit Cycle Yaw** - Bounded oscillatory motion analysis
|
|
320
|
-
|
|
321
|
-
## FFI Layer
|
|
322
|
-
|
|
323
|
-
The library includes a Foreign Function Interface (FFI) layer for integration with iOS, Android, and other platforms. The FFI provides C-compatible bindings for all major functionality.
|
|
324
|
-
|
|
325
|
-
<img src="ios.png" alt="iOS Integration Example" width="35%">
|
|
326
|
-
|
|
327
|
-
### FFI Features
|
|
328
|
-
- **C-Compatible Structures** - All data structures use C-compatible layouts
|
|
329
|
-
- **Safe Memory Management** - Proper handling of memory across language boundaries
|
|
330
|
-
- **iOS/Swift Integration** - Ready for use with Swift through bridging headers
|
|
331
|
-
- **Android/JNI Support** - Compatible with Java Native Interface
|
|
332
|
-
- **Monte Carlo Simulation** - Statistical analysis with parameter variations
|
|
333
|
-
- **Error Handling** - Graceful error propagation across FFI boundary
|
|
334
|
-
|
|
335
|
-
### Example FFI Usage (C/Swift)
|
|
336
|
-
```c
|
|
337
|
-
// Create input parameters
|
|
338
|
-
FFIBallisticInputs inputs = {
|
|
339
|
-
.muzzle_velocity = 823.0, // m/s
|
|
340
|
-
.ballistic_coefficient = 0.475,
|
|
341
|
-
.mass = 0.0109, // kg
|
|
342
|
-
.diameter = 0.00782, // meters
|
|
343
|
-
.drag_model = 0, // G1
|
|
344
|
-
.sight_height = 0.05, // meters
|
|
345
|
-
.temperature = 15.0, // Celsius
|
|
346
|
-
.altitude = 0.0
|
|
347
|
-
};
|
|
348
|
-
|
|
349
|
-
// Calculate trajectory
|
|
350
|
-
FFITrajectoryResult* result = ballistics_calculate_trajectory(&inputs, NULL, NULL, 1000.0, 0.1);
|
|
351
|
-
|
|
352
|
-
// Use results
|
|
353
|
-
printf("Max range: %.2f meters\n", result->max_range);
|
|
354
|
-
|
|
355
|
-
// Clean up
|
|
356
|
-
ballistics_free_trajectory_result(result);
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
### Monte Carlo Simulation via FFI
|
|
360
|
-
```c
|
|
361
|
-
// Set up Monte Carlo parameters
|
|
362
|
-
FFIMonteCarloParams params = {
|
|
363
|
-
.num_simulations = 1000,
|
|
364
|
-
.velocity_std_dev = 10.0, // m/s variation
|
|
365
|
-
.angle_std_dev = 0.001, // radian variation (elevation)
|
|
366
|
-
.bc_std_dev = 0.01, // BC variation
|
|
367
|
-
.wind_speed_std_dev = 2.0, // m/s wind variation
|
|
368
|
-
.target_distance = 600.0, // Target at 600m
|
|
369
|
-
.azimuth_std_dev = 0.001 // radian variation (horizontal)
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
// Run simulation
|
|
373
|
-
FFIMonteCarloResults* results = ballistics_monte_carlo(&inputs, NULL, ¶ms);
|
|
374
|
-
|
|
375
|
-
// Use statistical results
|
|
376
|
-
printf("Mean range: %.2f m (σ=%.2f)\n", results->mean_range, results->std_dev_range);
|
|
377
|
-
printf("Hit probability at 600m: %.1f%%\n", results->hit_probability * 100);
|
|
378
|
-
|
|
379
|
-
// Access individual shots
|
|
380
|
-
for (int i = 0; i < results->num_results; i++) {
|
|
381
|
-
printf("Shot %d: Range %.2f m, Impact velocity %.2f m/s\n",
|
|
382
|
-
i, results->ranges[i], results->impact_velocities[i]);
|
|
222
|
+
async function setupBallistics() {
|
|
223
|
+
await init();
|
|
224
|
+
// Ready to use
|
|
383
225
|
}
|
|
384
|
-
|
|
385
|
-
// Clean up
|
|
386
|
-
ballistics_free_monte_carlo_results(results);
|
|
387
226
|
```
|
|
388
227
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
All commands support three output formats via the `-o` flag:
|
|
392
|
-
|
|
393
|
-
- **table** (default) - Formatted ASCII table for terminal display
|
|
394
|
-
- **json** - Complete data in JSON format for programmatic use
|
|
395
|
-
- **csv** - Comma-separated values for spreadsheet analysis
|
|
228
|
+
### Without a Bundler (Script Tag)
|
|
396
229
|
|
|
397
|
-
|
|
230
|
+
```html
|
|
231
|
+
<script type="module">
|
|
232
|
+
import init, { Calculator } from './node_modules/ballistics-engine/ballistics_engine.js';
|
|
398
233
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
# Calculate zero angle
|
|
405
|
-
./ballistics zero \
|
|
406
|
-
-v 2650 -b 0.460 -m 180 -d 0.308 \
|
|
407
|
-
--target-distance 200
|
|
408
|
-
|
|
409
|
-
# Verify trajectory with auto-zero
|
|
410
|
-
./ballistics trajectory \
|
|
411
|
-
-v 2650 -b 0.460 -m 180 -d 0.308 \
|
|
412
|
-
--auto-zero 200 \
|
|
413
|
-
--max-range 400 \
|
|
414
|
-
--wind-speed 15 \
|
|
415
|
-
--wind-direction 270 \
|
|
416
|
-
--temperature 32 \
|
|
417
|
-
--humidity 30 \
|
|
418
|
-
--altitude 5000 \
|
|
419
|
-
--full
|
|
234
|
+
init().then(() => {
|
|
235
|
+
const calc = new Calculator();
|
|
236
|
+
// ...
|
|
237
|
+
});
|
|
238
|
+
</script>
|
|
420
239
|
```
|
|
421
240
|
|
|
422
|
-
|
|
241
|
+
## Performance
|
|
423
242
|
|
|
424
|
-
|
|
243
|
+
WebAssembly provides near-native performance:
|
|
425
244
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
--drag-model g7 \
|
|
430
|
-
--auto-zero 100 \
|
|
431
|
-
--max-range 1100 \
|
|
432
|
-
--wind-speed 10 \
|
|
433
|
-
--wind-direction 45 \
|
|
434
|
-
--full \
|
|
435
|
-
-o json > trajectory.json
|
|
436
|
-
```
|
|
245
|
+
- Single trajectory (1000 yards): ~1ms
|
|
246
|
+
- Full trajectory table (1500 points): ~5ms
|
|
247
|
+
- Zero calculation: ~2ms
|
|
437
248
|
|
|
438
|
-
|
|
249
|
+
## TypeScript Support
|
|
439
250
|
|
|
440
|
-
|
|
251
|
+
Full TypeScript definitions are included. Import types:
|
|
441
252
|
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
./ballistics monte-carlo \
|
|
445
|
-
-v 2750 -b 0.475 -m 168 -d 0.308 \
|
|
446
|
-
-n 1000 \
|
|
447
|
-
--velocity-std 15 \
|
|
448
|
-
--target-distance 600
|
|
449
|
-
|
|
450
|
-
# Load 2: Lower velocity, more consistent
|
|
451
|
-
./ballistics monte-carlo \
|
|
452
|
-
-v 2680 -b 0.475 -m 168 -d 0.308 \
|
|
453
|
-
-n 1000 \
|
|
454
|
-
--velocity-std 8 \
|
|
455
|
-
--target-distance 600
|
|
253
|
+
```typescript
|
|
254
|
+
import type { Calculator, WasmBallistics } from 'ballistics-engine';
|
|
456
255
|
```
|
|
457
256
|
|
|
458
|
-
##
|
|
459
|
-
|
|
460
|
-
### BC Segmentation
|
|
461
|
-
|
|
462
|
-
Velocity-dependent BC modeling accounts for how ballistic coefficient changes as the bullet slows down. Enable with `--use-bc-segments`:
|
|
257
|
+
## Memory Management
|
|
463
258
|
|
|
464
|
-
|
|
465
|
-
- No external data required - uses caliber, weight, and BC
|
|
466
|
-
- Identifies bullet type (Match, Hunting, VLD, etc.) from parameters
|
|
467
|
-
- Applies physics-based BC degradation curves
|
|
259
|
+
The Calculator and WasmBallistics classes allocate memory in the WASM heap. Call `.free()` when done to prevent memory leaks:
|
|
468
260
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
261
|
+
```javascript
|
|
262
|
+
const calc = new Calculator();
|
|
263
|
+
try {
|
|
264
|
+
// Use calculator
|
|
265
|
+
const result = calc.calculateTrajectory(500);
|
|
266
|
+
} finally {
|
|
267
|
+
calc.free();
|
|
268
|
+
}
|
|
472
269
|
```
|
|
473
270
|
|
|
271
|
+
Or use the `Symbol.dispose` for automatic cleanup (when supported):
|
|
474
272
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
- **Coriolis Effect** - Earth rotation effects (with latitude input)
|
|
481
|
-
- **Transonic Drag** - Enhanced drag modeling in transonic regime
|
|
482
|
-
- **Reynolds Number Corrections** - Viscous effects at low velocities
|
|
483
|
-
|
|
484
|
-
## Building from Source
|
|
485
|
-
|
|
486
|
-
### Requirements
|
|
487
|
-
|
|
488
|
-
- Rust 1.70 or later
|
|
489
|
-
- Cargo build system
|
|
490
|
-
|
|
491
|
-
### Build Commands
|
|
492
|
-
|
|
493
|
-
```bash
|
|
494
|
-
# Debug build
|
|
495
|
-
cargo build
|
|
496
|
-
|
|
497
|
-
# Release build (optimized)
|
|
498
|
-
cargo build --release
|
|
499
|
-
|
|
500
|
-
# Run tests
|
|
501
|
-
cargo test
|
|
502
|
-
|
|
503
|
-
# Build documentation
|
|
504
|
-
cargo doc --open
|
|
273
|
+
```typescript
|
|
274
|
+
{
|
|
275
|
+
using calc = new Calculator();
|
|
276
|
+
const result = calc.calculateTrajectory(500);
|
|
277
|
+
} // Automatically freed
|
|
505
278
|
```
|
|
506
279
|
|
|
507
|
-
##
|
|
508
|
-
|
|
509
|
-
Use as a Rust library in your own projects:
|
|
510
|
-
|
|
511
|
-
```rust
|
|
512
|
-
use ballistics_engine::{
|
|
513
|
-
BallisticInputs, TrajectorySolver,
|
|
514
|
-
WindConditions, AtmosphericConditions
|
|
515
|
-
};
|
|
516
|
-
|
|
517
|
-
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
518
|
-
let inputs = BallisticInputs {
|
|
519
|
-
muzzle_velocity: 823.0, // m/s
|
|
520
|
-
launch_angle: 0.0, // radians
|
|
521
|
-
ballistic_coefficient: 0.475,
|
|
522
|
-
mass: 0.0109, // kg
|
|
523
|
-
diameter: 0.00782, // meters
|
|
524
|
-
sight_height: 0.05, // meters
|
|
525
|
-
..Default::default()
|
|
526
|
-
};
|
|
527
|
-
|
|
528
|
-
let wind = WindConditions {
|
|
529
|
-
speed: 5.0, // m/s
|
|
530
|
-
direction: 1.5708, // 90 degrees in radians
|
|
531
|
-
..Default::default()
|
|
532
|
-
};
|
|
533
|
-
|
|
534
|
-
let atmosphere = AtmosphericConditions {
|
|
535
|
-
temperature: 15.0, // Celsius
|
|
536
|
-
pressure: 1013.25, // hPa
|
|
537
|
-
humidity: 50.0, // %
|
|
538
|
-
altitude: 0.0, // meters
|
|
539
|
-
..Default::default()
|
|
540
|
-
};
|
|
541
|
-
|
|
542
|
-
let solver = TrajectorySolver::new(inputs, wind, atmosphere);
|
|
543
|
-
let result = solver.solve()?;
|
|
544
|
-
|
|
545
|
-
println!("Max range: {:.2} m", result.max_range);
|
|
546
|
-
println!("Max height: {:.2} m", result.max_height);
|
|
547
|
-
println!("Time of flight: {:.3} s", result.time_of_flight);
|
|
548
|
-
|
|
549
|
-
Ok(())
|
|
550
|
-
}
|
|
551
|
-
```
|
|
280
|
+
## Related Packages
|
|
552
281
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
- Single trajectory (1000m): ~5ms
|
|
557
|
-
- Monte Carlo (1000 runs): ~500ms
|
|
558
|
-
- BC estimation: ~50ms
|
|
559
|
-
- Zero calculation: ~10ms
|
|
560
|
-
|
|
561
|
-
## Common Ballistic Coefficients
|
|
562
|
-
|
|
563
|
-
| Caliber | Weight | BC (G1) | BC (G7) | Description |
|
|
564
|
-
|---------|--------|---------|---------|-------------|
|
|
565
|
-
| .223 | 55gr | 0.250 | - | FMJ |
|
|
566
|
-
| .223 | 77gr | 0.362 | 0.182 | Match |
|
|
567
|
-
| .308 | 168gr | 0.475 | 0.224 | Match |
|
|
568
|
-
| .308 | 175gr | 0.505 | 0.253 | Match |
|
|
569
|
-
| .308 | 180gr | 0.480 | - | Hunting |
|
|
570
|
-
| .338 | 300gr | 0.768 | 0.383 | Match |
|
|
571
|
-
| 6.5mm | 140gr | 0.620 | 0.310 | Match |
|
|
572
|
-
| .50 | 750gr | 1.050 | 0.520 | Match |
|
|
573
|
-
|
|
574
|
-
## Troubleshooting
|
|
575
|
-
|
|
576
|
-
### Trajectory hits ground early
|
|
577
|
-
- Check if you're using `--auto-zero` or setting `--angle` manually
|
|
578
|
-
- Default angle is 0° (horizontal), which will hit ground quickly
|
|
579
|
-
- Use `--auto-zero <distance>` to automatically calculate proper angle
|
|
580
|
-
|
|
581
|
-
### Units confusion
|
|
582
|
-
- Default is Imperial (fps, grains, yards)
|
|
583
|
-
- Use `--units metric` for metric system
|
|
584
|
-
- All inputs must match the selected unit system
|
|
585
|
-
|
|
586
|
-
### Unexpected BC behavior
|
|
587
|
-
- G1 and G7 models have different BC values for same bullet
|
|
588
|
-
- G7 typically better for boat-tail bullets
|
|
589
|
-
- BC segmentation automatically applied based on bullet type
|
|
590
|
-
|
|
591
|
-
## Contributing
|
|
592
|
-
|
|
593
|
-
Contributions are welcome! Please:
|
|
594
|
-
1. Fork the repository
|
|
595
|
-
2. Create a feature branch
|
|
596
|
-
3. Add tests for new features
|
|
597
|
-
4. Run `cargo test` and `cargo fmt`
|
|
598
|
-
5. Submit a pull request
|
|
282
|
+
- **Node.js package**: Use `ballistics-engine` from npm (same package, works in Node.js too)
|
|
283
|
+
- **Rust crate**: [crates.io/crates/ballistics-engine](https://crates.io/crates/ballistics-engine)
|
|
284
|
+
- **Python package**: [pypi.org/project/ballistics-engine](https://pypi.org/project/ballistics-engine/)
|
|
599
285
|
|
|
600
286
|
## License
|
|
601
287
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
## Acknowledgments
|
|
605
|
-
|
|
606
|
-
- Ballistics physics based on Robert McCoy's "Modern Exterior Ballistics"
|
|
607
|
-
- Drag tables from military ballistics research
|
|
608
|
-
- BC segmentation algorithms from Bryan Litz's research
|
|
609
|
-
- Community contributions and testing
|
|
288
|
+
MIT OR Apache-2.0
|
|
610
289
|
|
|
611
|
-
##
|
|
290
|
+
## Links
|
|
612
291
|
|
|
613
|
-
|
|
614
|
-
- GitHub
|
|
292
|
+
- [Documentation](https://docs.ballistics.rs/)
|
|
293
|
+
- [GitHub Repository](https://github.com/ajokela/ballistics-engine)
|
|
294
|
+
- [Live Demo](https://ballistics.sh/)
|