parallelize render_scalar_field

This commit is contained in:
2020-12-15 14:19:29 -08:00
parent b3aba7658b
commit 6362b5a60e
5 changed files with 39 additions and 32 deletions

View File

@@ -7,9 +7,11 @@ use crossterm::{cursor, QueueableCommand as _};
use crossterm::style::{style, Color, PrintStyledContent};
use font8x8::{BASIC_FONTS, GREEK_FONTS, UnicodeFonts as _};
use log::trace;
use num::integer::Integer;
use plotly;
use image::{RgbImage, Rgb};
use imageproc::{pixelops, drawing};
use rayon::prelude::*;
use serde::{Serialize, Deserialize};
use std::fs::File;
use std::io::{BufWriter, Write as _};
@@ -158,36 +160,39 @@ impl<'a> RenderSteps<'a> {
let w = self.im.width();
let h = self.im.height();
let vec_spacing = 10;
for y in 0..h {
for x in 0..w {
if x % vec_spacing == 0 && y % vec_spacing == 0 {
let vec = self.field_vector(x, y, vec_spacing, &measure);
let norm_vec = scale_vector(vec, typical);
let alpha = 0.7*scale_unsigned(vec.mag_sq(), typical * 5.0);
let vec = norm_vec * (vec_spacing as Flt);
let center = Vec2::new(x as _, y as _) + Vec2::new(vec_spacing as _, vec_spacing as _)*0.5;
self.im.draw_field_arrow(center, vec, color, alpha as f32);
}
for y in (0..h).into_iter().step_by(vec_spacing as _) {
for x in (0..w).into_iter().step_by(vec_spacing as _) {
let vec = self.field_vector(x, y, vec_spacing, &measure);
let norm_vec = scale_vector(vec, typical);
let alpha = 0.7*scale_unsigned(vec.mag_sq(), typical * 5.0);
let vec = norm_vec * (vec_spacing as Flt);
let center = Vec2::new(x as _, y as _) + Vec2::new(vec_spacing as _, vec_spacing as _)*0.5;
self.im.draw_field_arrow(center, vec, color, alpha as f32);
}
}
}
fn render_scalar_field<F: Fn(&Cell<mat::Static>) -> Flt>(&mut self, typical: Flt, signed: bool, slot: u32, measure: F) {
let w = self.im.width();
let h = self.im.height();
for y in 0..h {
for x in 0..w {
let cell = self.get_at_px(x, y);
let value = measure(&cell);
let scaled = if signed {
scale_signed_to_u8(value, typical)
} else {
scale_unsigned_to_u8(value, typical)
};
let mut p = *self.im.get_pixel(x, y);
p.0[slot as usize] = scaled;
self.im.put_pixel(x, y, p);
}
}
fn render_scalar_field<F: Fn(&Cell<mat::Static>) -> Flt + Sync>(&mut self, typical: Flt, signed: bool, slot: u32, measure: F) {
// XXX: get_at_px borrows self, so we need to clone the image to operate on it mutably.
let mut im = self.im.clone();
let w = im.width();
let h = im.height();
let samples = im.as_flat_samples_mut();
assert_eq!(samples.layout.channel_stride, 1);
assert_eq!(samples.layout.width_stride, 3);
assert_eq!(samples.layout.height_stride, 3*w as usize);
let pixel_buf: &mut [[u8; 3]] = unsafe { std::mem::transmute(samples.samples) };
pixel_buf[..(w*h) as usize].par_iter_mut().enumerate().for_each(|(idx, px)| {
let (y, x) = (idx as u32).div_rem(&w);
let cell = self.get_at_px(x, y);
let value = measure(&cell);
let scaled = if signed {
scale_signed_to_u8(value, typical)
} else {
scale_unsigned_to_u8(value, typical)
};
px[slot as usize] = scaled;
});
self.im = im;
}
fn render_measurements(&mut self) {
for (meas_no, m) in self.meas.iter().enumerate() {