|
@@ -4,7 +4,7 @@ extern crate serde_derive;
|
|
|
extern crate serde;
|
|
|
extern crate serde_json;
|
|
|
use mentat::MonotonicCubicSpline;
|
|
|
-use splines::{Interpolation, Key, Spline};
|
|
|
+// use splines::{Interpolation, Key, Spline};
|
|
|
use std::collections::HashMap;
|
|
|
use std::fs::File;
|
|
|
use std::io::BufReader;
|
|
@@ -33,27 +33,28 @@ pub struct Gun {
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
|
|
pub struct BallisticsData {
|
|
|
- pub velocity: Vec<(i32, f32)>,
|
|
|
- pub energy: Vec<(i32, f32)>,
|
|
|
- pub trajectory: Vec<(i32, f32)>,
|
|
|
+ pub velocity: Vec<(u32, f32)>,
|
|
|
+ pub energy: Vec<(u32, f32)>,
|
|
|
+ pub trajectory: Vec<(u32, f32)>,
|
|
|
#[serde(default)]
|
|
|
- pub trajectory_filled: Vec<(i32, f32)>,
|
|
|
+ pub trajectory_filled: Vec<(u32, f32)>,
|
|
|
}
|
|
|
|
|
|
impl BallisticsData {
|
|
|
- fn attr_at(&self, d: i32, attribute: &Vec<(i32, f32)>) -> f32 {
|
|
|
- for i in 0..attribute.len() {
|
|
|
- if attribute[i].0 >= d {
|
|
|
- let start = attribute.get(i - 1).unwrap_or(&attribute[i]);
|
|
|
- let end = attribute[i];
|
|
|
- let mu = normalized_pos_in_range(start.0 as f32, end.0 as f32, d as f32);
|
|
|
- return lerp(start.1 as f32, end.1 as f32, mu);
|
|
|
- }
|
|
|
- }
|
|
|
+ fn attr_at(&self, d: u32, attribute: &Vec<(u32, f32)>) -> f32 {
|
|
|
+ // for i in 0..attribute.len() {
|
|
|
+ // if attribute[i].0 >= d {
|
|
|
+ // let start = attribute.get(i - 1).unwrap_or(&attribute[i]);
|
|
|
+ // let end = attribute[i];
|
|
|
+ // let mu = normalized_pos_in_range(start.0 as f32, end.0 as f32, d as f32);
|
|
|
+ // return lerp(start.1 as f32, end.1 as f32, mu);
|
|
|
+ // }
|
|
|
+ // }
|
|
|
0.0
|
|
|
}
|
|
|
|
|
|
- pub fn monospline(&self) -> Spline<f32, f32> {
|
|
|
+
|
|
|
+ pub fn monospline(&self) -> MonotonicCubicSpline {
|
|
|
// let x = vec![50.0, 100.0, 150.0, 200.0, 300.0];
|
|
|
// let y = vec![1.0, 4.0, -8.0, -10.5, -40.0];
|
|
|
|
|
@@ -62,89 +63,82 @@ impl BallisticsData {
|
|
|
|
|
|
// let smooth = MonotonicCubicSpline::partial(x.clone(), y.clone());
|
|
|
|
|
|
- let mut smooth = MonotonicCubicSpline::new(&x, &y);
|
|
|
+ MonotonicCubicSpline::new(&x, &y)
|
|
|
|
|
|
- let mut a = vec![];
|
|
|
+ // let mut a = vec![];
|
|
|
|
|
|
- for i in self.trajectory[0].0..self.trajectory[self.trajectory.len() - 1].0 {
|
|
|
- let p = i as f32;
|
|
|
- a.push(Key::new(
|
|
|
- p as f32,
|
|
|
- smooth.interpolate(p as f64) as f32,
|
|
|
- Interpolation::Linear,
|
|
|
- ));
|
|
|
- // a.push(Key::new(p as f32, spline.smooth(p as f64) as f32, Interpolation::Linear));
|
|
|
- }
|
|
|
+ // for i in self.trajectory[0].0..self.trajectory[self.trajectory.len() - 1].0 {
|
|
|
+ // let p = i as f32;
|
|
|
+ // a.push(Key::new(
|
|
|
+ // p as f32,
|
|
|
+ // smooth.interpolate(p as f64) as f32,
|
|
|
+ // Interpolation::Linear,
|
|
|
+ // ));
|
|
|
+ // // a.push(Key::new(p as f32, spline.smooth(p as f64) as f32, Interpolation::Linear));
|
|
|
+ // }
|
|
|
|
|
|
- Spline::from_vec(a)
|
|
|
+ //Spline::from_vec(a)
|
|
|
+ // smooth
|
|
|
}
|
|
|
|
|
|
- fn data_at(&self, d: i32) {
|
|
|
+ fn data_at(&self, d: u32) {
|
|
|
let vel = self.attr_at(d, &self.velocity);
|
|
|
let energy = self.attr_at(d, &self.energy);
|
|
|
let trajectory = self.attr_at(d, &self.trajectory);
|
|
|
println!("D{} V{} E{} T{}", d, vel, energy, trajectory);
|
|
|
}
|
|
|
|
|
|
- pub fn spline(&self) -> Spline<f32, f32> {
|
|
|
- // let mut a: Vec<Key<f32, f32>> = self.trajectory
|
|
|
- // .iter()
|
|
|
- // .map(|x| Key::new(x.0 as f32, x.1, Interpolation::CatmullRom))
|
|
|
- // .collect();
|
|
|
-
|
|
|
- let mut a = vec![];
|
|
|
-
|
|
|
- let mut i = 0;
|
|
|
- for pt in &self.trajectory {
|
|
|
- // let mut interp : Interpolation<f32, f32> = Interpolation::Cosine;
|
|
|
- let mut interp: Interpolation<f32, f32> = Interpolation::CatmullRom;
|
|
|
- if i == 0 || i >= self.trajectory.len() - 2 {
|
|
|
- interp = Interpolation::Linear;
|
|
|
- }
|
|
|
- a.push(Key::new(pt.0 as f32, pt.1, interp));
|
|
|
- i += 1;
|
|
|
- }
|
|
|
+ // pub fn spline(&self) -> Spline<f32, f32> {
|
|
|
+ // // let mut a: Vec<Key<f32, f32>> = self.trajectory
|
|
|
+ // // .iter()
|
|
|
+ // // .map(|x| Key::new(x.0 as f32, x.1, Interpolation::CatmullRom))
|
|
|
+ // // .collect();
|
|
|
+
|
|
|
+ // let mut a = vec![];
|
|
|
+
|
|
|
+ // let mut i = 0;
|
|
|
+ // for pt in &self.trajectory {
|
|
|
+ // // let mut interp : Interpolation<f32, f32> = Interpolation::Cosine;
|
|
|
+ // let mut interp: Interpolation<f32, f32> = Interpolation::CatmullRom;
|
|
|
+ // if i == 0 || i >= self.trajectory.len() - 2 {
|
|
|
+ // interp = Interpolation::Linear;
|
|
|
+ // }
|
|
|
+ // a.push(Key::new(pt.0 as f32, pt.1, interp));
|
|
|
+ // i += 1;
|
|
|
+ // }
|
|
|
|
|
|
// a[0] = Key::new(self.trajectory[0].0 as f32, self.trajectory[0].1, Interpolation::Linear);
|
|
|
// a[self.trajectory.len()-1] = Key::new(self.trajectory[self.trajectory.len()-1].0 as f32, self.trajectory[self.trajectory.len()-1].1, Interpolation::Linear);
|
|
|
|
|
|
- Spline::from_vec(a)
|
|
|
- }
|
|
|
+ // Spline::from_vec(a)
|
|
|
+ // }
|
|
|
|
|
|
- fn drop(&self, dist: i32) -> f32 {
|
|
|
+ fn interpolate_drop_at(&self, dist: u32) -> f64 {
|
|
|
self.monospline()
|
|
|
- .clamped_sample(dist as f32)
|
|
|
- .unwrap_or(-999999.0)
|
|
|
+ .interpolate(dist as f64)
|
|
|
}
|
|
|
|
|
|
- pub fn drop_zeroed(&self, dist: i32, zero_dist: i32) -> f32 {
|
|
|
+ pub fn drop_zeroed(&self, dist: u32, zero_dist: u32) -> f64 {
|
|
|
let z_comp = self
|
|
|
- .monospline()
|
|
|
- .clamped_sample(zero_dist as f32)
|
|
|
- .unwrap_or(0.0);
|
|
|
+ .interpolate_drop_at(zero_dist);
|
|
|
// println!("drop at {} {}", dist, z_comp);
|
|
|
- self.monospline()
|
|
|
- .clamped_sample(dist as f32)
|
|
|
- .unwrap_or(-999999.0)
|
|
|
- - z_comp
|
|
|
+ self.interpolate_drop_at(dist) - z_comp
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-fn drop_to_clicks (d: f32, moa_divisor: Adjustment) -> i32 {
|
|
|
+fn drop_to_clicks (d: f32, moa_divisor: Adjustment) -> u32 {
|
|
|
let radius = d;
|
|
|
let diameter = 2.0 * radius * std::f32::consts::PI;
|
|
|
1
|
|
|
}
|
|
|
|
|
|
-fn normalized_pos_in_range(min: f32, max: f32, d: f32) -> f32 {
|
|
|
+fn _normalized_pos_in_range(min: f32, max: f32, d: f32) -> f32 {
|
|
|
(d - min) / (max - min)
|
|
|
}
|
|
|
-
|
|
|
-fn lerp(y1: f32, y2: f32, mu: f32) -> f32 {
|
|
|
+fn _lerp(y1: f32, y2: f32, mu: f32) -> f32 {
|
|
|
y1 * (1.0 - mu) + y2 * mu
|
|
|
}
|
|
|
-
|
|
|
-fn write_sample() {
|
|
|
+fn _write_sample() {
|
|
|
let mut bd = BallisticsData::default();
|
|
|
bd.velocity.push((0, 720.0));
|
|
|
let mut map = HashMap::new();
|
|
@@ -156,9 +150,7 @@ fn write_sample() {
|
|
|
|
|
|
pub fn load_cartridges() -> Result<HashMap<String, BallisticsData>, serde_json::Error> {
|
|
|
let reader = BufReader::new(File::open("loading_data.json").unwrap());
|
|
|
- // let s: Result<HashMap<String, BallisticsData>, _> = serde_json::from_reader(reader);
|
|
|
serde_json::from_reader(reader)
|
|
|
- // println!("{:?}", loaded_car);
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
@@ -170,19 +162,69 @@ fn w() {
|
|
|
for (name, cartridge) in c {
|
|
|
println!("=== Cartridge {} ===", name);
|
|
|
|
|
|
- dbg!(cartridge.drop_zeroed(200, 100));
|
|
|
+ dbg!(cartridge.interpolate_drop_at(250));
|
|
|
+ dbg!(cartridge.drop_zeroed(250, 100));
|
|
|
// dbg!(cartridge.drop_zeroed(300, 150));
|
|
|
- // dbg!(cartridge.drop(250));
|
|
|
|
|
|
- let s = cartridge.monospline();
|
|
|
- for d in (50..310).step_by(10) {
|
|
|
- // cartridge.data_at(d);
|
|
|
- let z = s.clamped_sample(100.0).unwrap_or(-999999.0);
|
|
|
- let r = s.clamped_sample(d as f32).unwrap_or(-999999.0) - z;
|
|
|
+ // let s = cartridge.monospline();
|
|
|
+ // for d in (50..310).step_by(10) {
|
|
|
+ // // cartridge.data_at(d);
|
|
|
+ // let z = s.clamped_sample(100.0).unwrap_or(-999999.0);
|
|
|
+ // let r = s.clamped_sample(d as f32).unwrap_or(-999999.0) - z;
|
|
|
+ // println!("{} {:?}", d, r);
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Err(e) => println!("{:?}", e),
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#[cfg(test)]
|
|
|
+use plotlib::page::Page;
|
|
|
+#[cfg(test)]
|
|
|
+use plotlib::repr::Scatter;
|
|
|
+#[cfg(test)]
|
|
|
+use plotlib::style::{PointMarker, PointStyle};
|
|
|
+#[cfg(test)]
|
|
|
+use plotlib::view::ContinuousView;
|
|
|
+#[test]
|
|
|
+fn plot(){
|
|
|
+
|
|
|
+ match load_cartridges() {
|
|
|
+ Ok(c) => {
|
|
|
+ for (name, cartridge) in c {
|
|
|
+ // println!("=== Cartridge {} ===", name);
|
|
|
+
|
|
|
+ let mut data = vec![];
|
|
|
+
|
|
|
+ // let mut s = cartridge.monospline();
|
|
|
+ for d in 50..300 {
|
|
|
+ // let z = s.interpolate(d as f64);
|
|
|
+ // let r = s.interpolate(d as f64) - z;
|
|
|
+ let r = cartridge.interpolate_drop_at(d);
|
|
|
println!("{} {:?}", d, r);
|
|
|
+ data.push((d as f64, r as f64));
|
|
|
}
|
|
|
+
|
|
|
+ // We create our scatter plot from the data
|
|
|
+ let s1: Scatter = Scatter::from_slice(&data).style(
|
|
|
+ PointStyle::new()
|
|
|
+ .size(1.1)
|
|
|
+ );
|
|
|
+ // The 'view' describes what set of data is drawn
|
|
|
+ let v = ContinuousView::new()
|
|
|
+ .add(s1)
|
|
|
+ .x_range(0., 300.)
|
|
|
+ .y_range(-100., 20.)
|
|
|
+ .x_label("Distance")
|
|
|
+ .y_label("Drop");
|
|
|
+
|
|
|
+ // A page with a single view is then saved to an SVG file
|
|
|
+ Page::single(&v).save(format!("plot-{}.svg", name)).unwrap();
|
|
|
}
|
|
|
}
|
|
|
Err(e) => println!("{:?}", e),
|
|
|
}
|
|
|
-}
|
|
|
+
|
|
|
+}
|