aboutsummaryrefslogtreecommitdiff
path: root/src/renderer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer.rs')
-rw-r--r--src/renderer.rs58
1 files changed, 23 insertions, 35 deletions
diff --git a/src/renderer.rs b/src/renderer.rs
index 757019c..1346ed1 100644
--- a/src/renderer.rs
+++ b/src/renderer.rs
@@ -1,8 +1,8 @@
use std::{fs, mem, path::Path};
use color_eyre::eyre::{bail, Result};
-use indicatif::ProgressBar;
use image::{ImageBuffer, Luma, Pixel, Rgba, RgbaImage};
+use indicatif::ProgressBar;
use nalgebra::{vector, Vector2};
use num_traits::identities::Zero;
@@ -11,32 +11,21 @@ use super::{
layer::{self, TileLayer},
};
-pub type HeatCounter = TileLayer<Luma<u32>>;
+pub type HeatCounter = TileLayer<Luma<u8>>;
pub type HeatMap = TileLayer<Rgba<u8>>;
-/// Returns (a - b)**2, but ensures that no underflow happens (if b > a).
-fn diff_squared(a: u64, b: u64) -> u64 {
- if a > b {
- (a - b).pow(2)
- } else {
- (b - a).pow(2)
- }
-}
-
fn render_circle<P: Pixel>(layer: &mut TileLayer<P>, center: (u64, u64), radius: u64, pixel: P) {
- let x_lower = center.0.saturating_sub(radius);
- let x_upper = (layer.width() - 1).min(center.0 + radius);
- let y_lower = center.1.saturating_sub(radius);
- let y_upper = (layer.height() - 1).min(center.1 + radius);
-
- for x in x_lower..=x_upper {
- for y in y_lower..=y_upper {
- if diff_squared(center.0, x) + diff_squared(center.1, y) <= radius * radius {
- *layer.get_pixel_mut(x, y) = pixel;
- }
- }
- }
+ let topleft = (center.0 - radius, center.1 - radius);
+ let rad_32: u32 = radius.try_into().unwrap();
+ let mut circle = ImageBuffer::<P, Vec<P::Subpixel>>::new(rad_32 * 2 + 1, rad_32 * 2 + 1);
+ imageproc::drawing::draw_filled_circle_mut(
+ &mut circle,
+ (i32::try_from(radius).unwrap(), i32::try_from(radius).unwrap()),
+ radius.try_into().unwrap(),
+ pixel,
+ );
+ layer.blit_nonzero(topleft.0, topleft.1, &circle);
}
fn direction_vector(a: (u64, u64), b: (u64, u64)) -> Vector2<f64> {
@@ -112,21 +101,20 @@ fn render_line<P: Pixel>(
.collect::<Vec<_>>();
imageproc::drawing::draw_polygon_mut(&mut overlay, &adjusted_poly, pixel);
- for (x, y, pixel) in overlay.enumerate_pixels() {
- if pixel.channels()[0] > Zero::zero() {
- *layer.get_pixel_mut(u64::from(x) + min_x, u64::from(y) + min_y) = *pixel;
- }
- }
+ layer.blit_nonzero(min_x, min_y, &overlay);
}
fn merge_heat_counter(base: &mut HeatCounter, overlay: &HeatCounter) {
- for (x, y, source) in overlay.enumerate_pixels() {
- let target = base.get_pixel_mut(x, y);
- target[0] += source[0];
+ for (tx, ty, source) in overlay.enumerate_tiles() {
+ let target = base.tile_mut(tx, ty);
+ for (x, y, source) in source.enumerate_pixels() {
+ let target = target.get_pixel_mut(x, y);
+ target[0] += source[0];
+ }
}
}
-fn colorize_tile(tile: &ImageBuffer<Luma<u32>, Vec<u32>>, max: u32) -> RgbaImage {
+fn colorize_tile(tile: &ImageBuffer<Luma<u8>, Vec<u8>>, max: u32) -> RgbaImage {
let gradient = colorgrad::yl_or_rd();
let mut result = ImageBuffer::from_pixel(tile.width(), tile.height(), [0, 0, 0, 0].into());
for (x, y, pixel) in tile.enumerate_pixels() {
@@ -147,7 +135,7 @@ pub fn colorize_heatcounter(layer: &HeatCounter) -> HeatMap {
return result;
}
for (tile_x, tile_y, tile) in layer.enumerate_tiles() {
- let colorized = colorize_tile(&tile, max);
+ let colorized = colorize_tile(&tile, max.into());
*result.tile_mut(tile_x, tile_y) = colorized;
}
result
@@ -167,7 +155,7 @@ pub fn lazy_colorization<P: AsRef<Path>>(layer: &HeatCounter, base_dir: P) -> Re
let bar = ProgressBar::new(layer.tile_count().try_into().unwrap());
for (tile_x, tile_y, tile) in layer.enumerate_tiles() {
- let colorized = colorize_tile(&tile, max);
+ let colorized = colorize_tile(&tile, max.into());
let folder = base_dir.join(&tile_x.to_string());
let metadata = folder.metadata();
match metadata {
@@ -200,7 +188,7 @@ pub fn render_heatcounter(zoom: u32, tracks: &[Vec<Coordinates>]) -> HeatCounter
.collect::<Vec<_>>();
for point in points.iter() {
- render_circle(&mut layer, *point, (zoom as u64 / 4).max(1), [1].into());
+ render_circle(&mut layer, *point, (zoom as u64 / 4).max(2) - 1, [1].into());
}
for (a, b) in points.iter().zip(points.iter().skip(1)) {