Johann Woelper 5 years ago
parent
commit
a2511a021a
2 changed files with 102 additions and 48 deletions
  1. 2 1
      Cargo.toml
  2. 100 47
      src/lib.rs

+ 2 - 1
Cargo.toml

@@ -10,4 +10,5 @@ edition = "2018"
 serde = "1.0"
 serde_derive = "1.0"
 serde_json = "1.0"
-splines = "3.0.0"
+splines = "3.0.0"
+mentat = { git = "https://gitlab.com/ruivieira/mentat.git" }

+ 100 - 47
src/lib.rs

@@ -3,29 +3,48 @@
 extern crate serde_derive;
 extern crate serde;
 extern crate serde_json;
-use std::io::BufWriter;
-use std::io::BufReader;
-use std::fs::File;
-use std::collections::HashMap;
+use mentat::MonotonicCubicSpline;
 use splines::{Interpolation, Key, Spline};
+use std::collections::HashMap;
+use std::fs::File;
+use std::io::BufReader;
+use std::io::BufWriter;
+
+#[derive(Serialize, Deserialize, Debug)]
+pub enum Adjustment {
+    MOAQuarter = 4,
+    MOAHalf = 2,
+}
+
+impl Default for Adjustment {
+    fn default() -> Self {
+        Adjustment::MOAQuarter
+    }
+}
+
+#[derive(Serialize, Deserialize, Debug, Default)]
+pub struct Gun {
+    pub name: String,
+    pub adjustment: Adjustment,
+    pub caliber: f32,
+    #[serde(default)]
+    pub weight: f32,
+}
 
 #[derive(Serialize, Deserialize, Debug, Default)]
-struct BallisticsData {
-    // velocity:   HashMap<i32, f32>,
-    // energy:     HashMap<i32, f32>,
-    // trajectory: HashMap<i32, f32>
-    velocity:   Vec<(i32, f32)>,
-    energy:     Vec<(i32, f32)>,
-    trajectory: Vec<(i32, f32)>,
+pub struct BallisticsData {
+    pub velocity: Vec<(i32, f32)>,
+    pub energy: Vec<(i32, f32)>,
+    pub trajectory: Vec<(i32, f32)>,
+    #[serde(default)]
+    pub trajectory_filled: Vec<(i32, f32)>,
 }
 
 impl BallisticsData {
-    fn attr_at(&self, d: i32, attribute: &Vec<(i32, f32)>) -> f32{
-        
-        
+    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 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);
@@ -34,6 +53,32 @@ impl BallisticsData {
         0.0
     }
 
+    pub fn monospline(&self) -> Spline<f32, f32> {
+        // 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];
+
+        let x: Vec<f64> = self.trajectory.iter().map(|x| x.0 as f64).collect();
+        let y: Vec<f64> = self.trajectory.iter().map(|x| x.1 as f64).collect();
+
+        // let smooth = MonotonicCubicSpline::partial(x.clone(), y.clone());
+
+        let mut smooth = MonotonicCubicSpline::new(&x, &y);
+
+        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));
+        }
+
+        Spline::from_vec(a)
+    }
+
     fn data_at(&self, d: i32) {
         let vel = self.attr_at(d, &self.velocity);
         let energy = self.attr_at(d, &self.energy);
@@ -41,31 +86,54 @@ impl BallisticsData {
         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;
+        }
 
-    fn spline(&self) -> Spline<f32, f32>{
+        // 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);
 
-        let a: Vec<Key<f32, f32>> = self.trajectory
-            .iter()
-            .map(|x| Key::new(x.0 as f32, x.1, Interpolation::Cosine))
-            .collect();
         Spline::from_vec(a)
     }
 
-
     fn drop(&self, dist: i32) -> f32 {
-        self.spline()
+        self.monospline()
             .clamped_sample(dist as f32)
             .unwrap_or(-999999.0)
     }
 
-    fn drop_zeroed(&self, dist: i32, zero_dist: i32) -> f32 {
-        let z_comp = self.spline().clamped_sample(zero_dist as f32).unwrap_or(0.0);
+    pub fn drop_zeroed(&self, dist: i32, zero_dist: i32) -> f32 {
+        let z_comp = self
+            .monospline()
+            .clamped_sample(zero_dist as f32)
+            .unwrap_or(0.0);
         // println!("drop at {} {}", dist, z_comp);
-        self.spline()
+        self.monospline()
             .clamped_sample(dist as f32)
-            .unwrap_or(-999999.0) - z_comp
+            .unwrap_or(-999999.0)
+            - z_comp
     }
+}
 
+fn drop_to_clicks (d: f32, moa_divisor: Adjustment) -> i32 {
+    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 {
@@ -73,14 +141,12 @@ fn normalized_pos_in_range(min: f32, max: f32, d: f32) -> f32 {
 }
 
 fn lerp(y1: f32, y2: f32, mu: f32) -> f32 {
-    y1*(1.0-mu)+y2*mu
+    y1 * (1.0 - mu) + y2 * mu
 }
 
-
-
 fn write_sample() {
     let mut bd = BallisticsData::default();
-    bd.velocity.push((0,720.0));
+    bd.velocity.push((0, 720.0));
     let mut map = HashMap::new();
     map.insert("Hammerhead", bd);
     // write out the file
@@ -88,23 +154,17 @@ fn write_sample() {
     serde_json::to_writer_pretty(writer, &map).unwrap();
 }
 
-
-fn load_cartridges() -> Result<HashMap<String, BallisticsData>, serde_json::Error> {
+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]
 fn w() {
     //write_sample();
 
-
     match load_cartridges() {
         Ok(c) => {
             for (name, cartridge) in c {
@@ -114,22 +174,15 @@ fn w() {
                 // dbg!(cartridge.drop_zeroed(300, 150));
                 // dbg!(cartridge.drop(250));
 
-                let s = cartridge.spline();
+                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)
+        }
+        Err(e) => println!("{:?}", e),
     }
-
-
-
-
-
 }