125 lines
4.3 KiB
Rust
125 lines
4.3 KiB
Rust
#[derive(Debug, Clone)]
|
|
pub struct Domain {
|
|
pub width: usize,
|
|
pub height: usize,
|
|
pub cells: Vec<(f64, f64)>,
|
|
pub enabled: Vec<f64>,
|
|
}
|
|
|
|
impl Domain {
|
|
pub fn empty(width: usize, height: usize) -> Self {
|
|
let grid_size = (width+2)*(height*2);
|
|
let cells = core::iter::repeat_n((0.0, 0.0), grid_size).collect();
|
|
let mut enabled: Vec<f64> = core::iter::repeat_n(1.0, grid_size).collect();
|
|
|
|
for x in 0..width+2 {
|
|
*enabled.get_mut(x).unwrap() = 0.0;
|
|
*enabled.get_mut((height+1)*width + x).unwrap() = 0.0;
|
|
}
|
|
for y in 0..height+2 {
|
|
*enabled.get_mut(y*width + 0).unwrap() = 0.0;
|
|
*enabled.get_mut(y*width + width-1).unwrap() = 0.0;
|
|
}
|
|
|
|
Domain {
|
|
width,
|
|
height,
|
|
cells,
|
|
enabled
|
|
}
|
|
}
|
|
|
|
pub fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut (f64, f64)> {
|
|
self.cells.get_mut((y + 1)*self.width + x + 1)
|
|
}
|
|
}
|
|
|
|
pub fn simulate(start: &mut Domain) {
|
|
let dT: f64 = 1.0 / 30.0;
|
|
|
|
for i in 0..25 {
|
|
for y in 1..start.height-1 {
|
|
for x in 1..start.width-1 {
|
|
let own_cell_idx = y * start.width + x;
|
|
let top_cell_idx = (y-1) * start.width + x;
|
|
let right_cell_idx = y * start.width + x + 1;
|
|
|
|
let own_cell = start.cells.get(own_cell_idx).copied().unwrap();
|
|
let top_cell = start.cells.get(top_cell_idx).copied().unwrap();
|
|
let right_cell = start.cells.get(right_cell_idx).copied().unwrap();
|
|
|
|
let d = right_cell.0 - own_cell.0 + top_cell.1 - own_cell.1;
|
|
|
|
let s_right = start.enabled.get(y*start.width+x+1).copied().unwrap();
|
|
let s_left = start.enabled.get(y*start.width+x-1).copied().unwrap();
|
|
let s_top = start.enabled.get((y-1)*start.width+x).copied().unwrap();
|
|
let s_bot = start.enabled.get((y+1)*start.width+x).copied().unwrap();
|
|
let total = s_right + s_left + s_top + s_bot;
|
|
|
|
start.cells.get_mut(own_cell_idx).unwrap().0 = own_cell.0 + d*(s_left/total);
|
|
start.cells.get_mut(own_cell_idx).unwrap().1 = own_cell.1 + d*(s_top/total);
|
|
|
|
start.cells.get_mut(right_cell_idx).unwrap().0 = right_cell.0 - d*(s_right/total);
|
|
start.cells.get_mut(top_cell_idx).unwrap().1 = top_cell.1 - d*(s_bot/total);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Advaction
|
|
simulate_advaction(start, dT);
|
|
}
|
|
|
|
fn simulate_advaction(start: &mut Domain, dT: f64) {
|
|
for y in 1..start.height-1 {
|
|
for x in 1..start.width-1 {
|
|
let own_cell_idx = y * start.width + x;
|
|
|
|
let own_cell = start.cells.get(own_cell_idx).copied().unwrap();
|
|
|
|
let u = own_cell.0;
|
|
|
|
let v = (own_cell.1 + start.cells.get(y * start.width + x - 1).copied().unwrap().1
|
|
+ start.cells.get((y-1) * start.width + x).copied().unwrap().1
|
|
+ start.cells.get((y-1) * start.width + x - 1).copied().unwrap().1) / 4.0;
|
|
|
|
let prev_x = x as f64 + 0.5 - dT*u;
|
|
let prev_y = y as f64 + 0.5 - dT*v;
|
|
|
|
println!("[AD] ({}, {}) --({}, {})--> ({}, {})", x, y, u, v, prev_x, prev_y);
|
|
|
|
let cell = (prev_x.round() as usize, prev_y.round() as usize);
|
|
let cell_left = (cell.0 - 1, cell.1);
|
|
let cell_left_top = (cell.0 - 1, cell.1 - 1);
|
|
let cell_top = (cell.0, cell.1 - 1);
|
|
|
|
println!("[AD] Right-B {:?} - Left-B {:?} - Right-T {:?} - Left-T {:?}", cell, cell_left, cell_top, cell_left_top);
|
|
|
|
let w00 = 1.0 - (prev_x - (cell_left.0 as f64 + 0.5))/1.0;
|
|
let w01 = (prev_x - (cell_left.0 as f64 + 0.5))/1.0;
|
|
let w10 = 1.0 - (prev_y - (cell_left.1 as f64 + 0.5))/1.0;
|
|
let w11 = (prev_y - (cell_left.1 as f64 + 0.5))/1.0;
|
|
println!("W00 {} - W01 {} - W10 {} - W11 {}", w00, w01, w10, w11);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn advaction_x_only() {
|
|
let input = Domain::empty(6, 6);
|
|
|
|
let mut target = input.clone();
|
|
|
|
target.get_mut(2, 2).unwrap().0 = 1.0;
|
|
|
|
println!("{:?}", target);
|
|
simulate_advaction(&mut target, 0.1);
|
|
println!("{:?}", target);
|
|
|
|
assert!(false);
|
|
}
|
|
}
|