Browse Source

move to monospline

Erwin 5 years ago
parent
commit
62817a950a
2 changed files with 122 additions and 76 deletions
  1. 5 1
      Cargo.toml
  2. 117 75
      src/lib.rs

+ 5 - 1
Cargo.toml

@@ -11,4 +11,8 @@ serde = "1.0"
 serde_derive = "1.0"
 serde_json = "1.0"
 splines = "3.0.0"
-mentat = { git = "https://gitlab.com/ruivieira/mentat.git" }
+mentat = { git = "https://gitlab.com/ruivieira/mentat.git" }
+
+
+[dev-dependencies]
+plotlib = { git = "https://github.com/milliams/plotlib.git" }

+ 117 - 75
src/lib.rs

@@ -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),
     }
-}
+
+}