diff --git a/src/fixed_resolution_buffer.rs b/src/fixed_resolution_buffer.rs index af95e2d..d9adc60 100644 --- a/src/fixed_resolution_buffer.rs +++ b/src/fixed_resolution_buffer.rs @@ -40,20 +40,29 @@ impl FixedResolutionBuffer { } } - pub fn deposit(&mut self, vmesh: &VariableMesh, buffer: &mut [f64], name: String) -> u32 { + pub fn deposit( + &mut self, + vmesh: &VariableMesh, + buffer: &mut [f64], + name: String, + position: Option, + ) -> u32 { let mut count: u32 = 0; // We do need to clear the buffer -- in cases where the buffer is completely filled this // will result in extra work being done, but the alternate is to allocate a bunch of memory // and do filling of values anyway, so it may be the best we can do. - for val in buffer.iter_mut() { - *val = 0.0; - } + buffer.fill(0.0); let mut image_buffer: Vec<&mut [f64]> = buffer.chunks_exact_mut(self.height).rev().collect(); - for pixel in vmesh.iter(&name) { // Compute our left edge pixel + if match position { + Some(v) => (pixel.pz + pixel.pdz <= v || pixel.pz - pixel.pdz >= v), + None => false, + } { + continue; + }; if pixel.px + pixel.pdx < self.x_low || pixel.py + pixel.pdy < self.y_low || pixel.px - pixel.pdx > self.x_high @@ -97,5 +106,4 @@ mod tests { assert_eq!(_frb_test.ipdx, 128.0); assert_eq!(_frb_test.ipdy, 259.0 / 2.3); } - } diff --git a/src/lib.rs b/src/lib.rs index 0e3ac19..d66befd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,7 +78,7 @@ mod tests { assert_eq!(x, 1.0); - let mut _vm = VariableMesh::new(px, py, pdx, pdy); + let mut _vm = VariableMesh::new(px, py, pdx, pdy, None, None); _vm.add_field("default", field1); _vm.add_field("alternate", field2); @@ -96,16 +96,125 @@ mod tests { // This does not always work, because of how we compute rows and columns, // so we don't assert. We will eventually do so, though. - let _count = _frb_test.deposit(&_vm, buffer.as_mut_slice(), "default".to_string()); + let _count = _frb_test.deposit(&_vm, buffer.as_mut_slice(), "default".to_string(), None); for &v in buffer.iter() { assert_eq!(v, 1.0); } - let _count = _frb_test.deposit(&_vm, buffer.as_mut_slice(), "alternate".to_string()); + let _count = _frb_test.deposit(&_vm, buffer.as_mut_slice(), "alternate".to_string(), None); for &v in buffer.iter() { assert_eq!(v, 2.13); } } + + #[test] + fn deposit_layered_vm_fixed_res() { + // This should eventually be parameterized, and we'll do a bit of that here. + let mut px: Vec = Vec::new(); + let mut py: Vec = Vec::new(); + let mut pz: Vec = Vec::new(); + let mut pdx: Vec = Vec::new(); + let mut pdy: Vec = Vec::new(); + let mut pdz: Vec = Vec::new(); + let mut field1: Vec = Vec::new(); + let mut field2: Vec = Vec::new(); + + let _nval = 32; + let _npix = 1024; + + // We will now create a generic mesh + + let mut sum_x = 0.0; + let mut sum_y = 0.0; + // Compute our widths, which we'll use to generate the + let mut widths_x: Vec = Vec::new(); + let mut widths_y: Vec = Vec::new(); + for _i in 0.._nval { + // Just some generic values which we'll clean up at the end. + // We do the second divide by two so that we have half-widths + let _px = (1.0 - sum_x) / 2.0; + // Also note that we're going to do something funky here, + // just to make sure we're not always the same for x and y. + let _py = (0.9 - sum_y) / 2.0; + widths_x.push(_px / 2.0); + widths_y.push(_py / 2.0); + sum_x += _px; + sum_y += _py; + } + + widths_x.push((1.0 - sum_x) / 2.0); + widths_y.push((1.0 - sum_y) / 2.0); + + let mut x; + let mut y; + + let zs = vec![0.0, 1.0, 1.5, 2.0, 10.0]; + let pdzs = vec![0.01, 0.1, 0.40, 0.05, 5.0]; + + for (&_pz, &_pdz) in zs.iter().zip(pdzs.iter()) { + x = 0.0; + for &_pdx in widths_x.iter() { + x += _pdx; + y = 0.0; + for &_pdy in widths_y.iter() { + y += _pdy; + px.push(x); + py.push(y); + pz.push(_pz); + pdx.push(_pdx); + pdy.push(_pdy); + pdz.push(_pdz); + field1.push(_pz); + field2.push(_pdz); + y += _pdy; + } + assert_eq!(y, 1.0); + x += _pdx; + } + assert_eq!(x, 1.0); + } + + let mut _vm = VariableMesh::new(px, py, pdx, pdy, Some(pz), Some(pdz)); + _vm.add_field("default", field1); + _vm.add_field("alternate", field2); + + for pixel in _vm.iter("default") { + assert_eq!(pixel.val, pixel.pz); + } + for pixel in _vm.iter("alternate") { + assert_eq!(pixel.val, pixel.pdz); + } + + let mut _frb_test = FixedResolutionBuffer::new(_npix, _npix, 0.0, 1.0, 0.0, 1.0); + + let mut buffer: Vec = Vec::new(); + buffer.resize(_npix * _npix, 0.0); + + // This does not always work, because of how we compute rows and columns, + // so we don't assert. We will eventually do so, though. + for (&_pz, &_pdz) in zs.iter().zip(pdzs.iter()) { + buffer.fill(0.0); + let _count = _frb_test.deposit( + &_vm, + buffer.as_mut_slice(), + "default".to_string(), + Some(_pz + 0.25 * _pdz), + ); + for &v in buffer.iter() { + assert_eq!(v, _pz); + } + buffer.fill(0.0); + let _count = _frb_test.deposit( + &_vm, + buffer.as_mut_slice(), + "alternate".to_string(), + Some(_pz - 0.25 * _pdz), + ); + for &v in buffer.iter() { + assert_eq!(v, _pdz); + } + } + } } diff --git a/src/variable_mesh.rs b/src/variable_mesh.rs index eb98c3f..f0752c2 100644 --- a/src/variable_mesh.rs +++ b/src/variable_mesh.rs @@ -8,8 +8,10 @@ use std::collections::HashMap; pub struct VariableMesh { px: Vec, py: Vec, + pz: Vec, pdx: Vec, pdy: Vec, + pdz: Vec, field_values: HashMap>, } @@ -17,8 +19,10 @@ pub struct VariableMesh { pub struct VariablePixel { pub px: f64, pub py: f64, + pub pz: f64, pub pdx: f64, pub pdy: f64, + pub pdz: f64, pub val: f64, } @@ -31,7 +35,14 @@ pub struct VariablePixelIterator<'a> { #[wasm_bindgen] impl VariableMesh { #[wasm_bindgen(constructor)] - pub fn new(px: Vec, py: Vec, pdx: Vec, pdy: Vec) -> VariableMesh { + pub fn new( + px: Vec, + py: Vec, + pdx: Vec, + pdy: Vec, + pz: Option>, + pdz: Option>, + ) -> VariableMesh { let size = px.len(); if !((size == py.len()) && (size == pdx.len()) && (size == pdy.len())) { // This should eventually be a Result @@ -44,16 +55,32 @@ impl VariableMesh { ); } let mut field_values = HashMap::new(); - let mut default_values: Vec = Vec::new(); - for _i in 0..size { - default_values.push(1.0); + let default_values = vec![1.0f64; size]; + let pz = match pz { + Some(v) => v, + None => vec![0.0; size], + }; + let pdz = match pdz { + Some(v) => v, + None => vec![1.0; size], + }; + if !((size == pz.len()) && (size == pdz.len())) { + // This should eventually be a Result + panic!( + "Size mismatch for Vector components: {:?}, {:?}, {:?}", + size, + pz.len(), + pdz.len() + ); } field_values.insert(String::from("ones"), default_values); VariableMesh { px, py, + pz, pdx, pdy, + pdz, field_values, } } @@ -87,8 +114,10 @@ impl<'a> Iterator for VariablePixelIterator<'_> { Some(VariablePixel { px: self.mesh.px[self.index - 1], py: self.mesh.py[self.index - 1], + pz: self.mesh.pz[self.index - 1], pdx: self.mesh.pdx[self.index - 1], pdy: self.mesh.pdy[self.index - 1], + pdz: self.mesh.pdz[self.index - 1], val: self.values[self.index - 1], }) } @@ -106,7 +135,9 @@ mod tests { vec![1.0, 2.0, 3.0, 4.0, 5.0], vec![1.0, 2.0, 3.0, 4.0, 5.0], vec![1.0, 2.0, 3.0, 4.0, 5.0], - vec![1.0, 2.0, 3.0, 4.0, 5.0] + vec![1.0, 2.0, 3.0, 4.0, 5.0], + None, + None, ); } @@ -117,7 +148,9 @@ mod tests { vec![1.0, 2.0, 3.0, 4.0, 5.0], vec![1.0, 2.0, 3.0, 4.0, 5.0], vec![1.0, 2.0, 3.0, 4.0, 5.0], - vec![1.0, 2.0, 3.0, 4.0] + vec![1.0, 2.0, 3.0, 4.0], + None, + None, ); } @@ -136,7 +169,7 @@ mod tests { pdy.push((i as f64) * 0.22); val.push((i as f64) * 4.05); } - let mut vm = VariableMesh::new(px, py, pdx, pdy); + let mut vm = VariableMesh::new(px, py, pdx, pdy, None, None); vm.add_field("default", val); for (i, pixel) in vm.iter("default").enumerate() { assert_eq!(pixel.px, (i as f64) * 1.0);