summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2025-09-29 22:05:33 +0800
committerlittleblack111 <littleblack11111@gmail.com>2025-09-29 22:05:33 +0800
commit2d4c92814a4a5d425edfe6da36acd75c56e0eb5e (patch)
tree77e28c7ffa30225b6a2da4d66e2273ce48828301 /src
parentfad7c9d38136a0e3065778d2651b2166bba4f8fa (diff)
image(draw_direction): adaptive
Diffstat (limited to 'src')
-rw-r--r--src/image.rs96
1 files changed, 61 insertions, 35 deletions
diff --git a/src/image.rs b/src/image.rs
index a67fd3b..db03f31 100644
--- a/src/image.rs
+++ b/src/image.rs
@@ -1,7 +1,7 @@
use ab_glyph::{FontArc, PxScale};
use fontdb::{Database, Family, Query, Source};
-use image::{imageops, ColorType, DynamicImage, ImageBuffer};
-use imageproc::drawing::{draw_filled_rect_mut, draw_polygon_mut, draw_text_mut, text_size, Canvas};
+use image::{ColorType, DynamicImage, ImageBuffer, imageops};
+use imageproc::drawing::{Canvas, draw_filled_rect_mut, draw_polygon_mut, draw_text_mut, text_size};
use imageproc::point::Point;
use imageproc::rect::Rect;
use std::path::Path;
@@ -19,7 +19,7 @@ const TEXT_SCALE: f32 = 12.0 * RESOLUTION_MULTIPLIER as f32;
const TEXT_LEN_WRAP: usize = 10;
// TODO: LENGTH based on where to where
-const DIRECTION_LINE_THICKNESS: u32 = 2 * RESOLUTION_MULTIPLIER;
+const DIRECTION_LINE_THICKNESS: u32 = 2 * RESOLUTION_MULTIPLIER / 2;
const DIRECTION_LINE_LENGTH: u32 = 13 * RESOLUTION_MULTIPLIER;
const DIRECTION_LINE_ARROW_OFFSET: u32 = 5 * RESOLUTION_MULTIPLIER / 2;
@@ -134,49 +134,76 @@ fn draw_process(img: &mut DynamicImage, txt: &str, (curw, curh, c): &mut Offset)
}
fn draw_direction(img: &mut DynamicImage, (_, orih, c): &mut Offset, dst: Option<&NCOffset>) {
- let (srcx, srcy) = (*c - (DIRECTION_LINE_THICKNESS / 2), *orih);
- let default = (srcx + DIRECTION_LINE_THICKNESS, srcy + DIRECTION_LINE_LENGTH - DIRECTION_LINE_ARROW_OFFSET);
- let (dstx, dsty) = dst.unwrap_or(&default);
- ext(img, &mut (*c, *orih), &mut (dstx - *c, dsty - *c));
- let (srcx, srcy) = (srcx as i32, srcy as i32);
- let (dsty, dstx) = (*dsty as i32, *dstx as i32);
- draw_polygon_mut(
- img,
- &[
- Point::new(srcx, srcy),
- Point::new(srcx, dsty),
- Point::new(dstx, dsty),
- Point::new(dstx, srcy),
- ],
- colors::DIRECT,
- );
-
- *orih = dsty as u32;
+ let srcx = *c as i32;
+ let srcy = *orih as i32;
+ let (dstx, dsty) = dst.unwrap_or(&(0, DIRECTION_LINE_LENGTH - DIRECTION_LINE_ARROW_OFFSET));
+ let dstx = srcx + *dstx as i32;
+ let dsty = srcy + *dsty as i32;
+
+ // perpendicular(thickness)
+ let xdiff = (dstx - srcx) as f32;
+ let ydiff = (dsty - srcy) as f32;
+ let length = (xdiff * xdiff + ydiff * ydiff)
+ .sqrt()
+ .max(1_f32);
+
+ let prepx = -ydiff / length;
+ let prepy = xdiff / length;
+
+ let linemaxx = (dstx as f32 - (xdiff / length) * DIRECTION_LINE_ARROW_OFFSET as f32).round() as i32;
+ let linemaxy = (dsty as f32 - (ydiff / length) * DIRECTION_LINE_ARROW_OFFSET as f32).round() as i32;
+
+ let line = [
+ Point::new((srcx as f32 - prepx * DIRECTION_LINE_THICKNESS as f32).round() as i32, (srcy as f32 - prepy * DIRECTION_LINE_THICKNESS as f32).round() as i32),
+ Point::new((srcx as f32 + prepx * DIRECTION_LINE_THICKNESS as f32).round() as i32, (srcy as f32 + prepy * DIRECTION_LINE_THICKNESS as f32).round() as i32),
+ Point::new((linemaxx as f32 + prepx * DIRECTION_LINE_THICKNESS as f32).round() as i32, (linemaxy as f32 + prepy * DIRECTION_LINE_THICKNESS as f32).round() as i32),
+ Point::new((linemaxx as f32 - prepx * DIRECTION_LINE_THICKNESS as f32).round() as i32, (linemaxy as f32 - prepy * DIRECTION_LINE_THICKNESS as f32).round() as i32),
+ ];
+
+ let xc = dstx as f32 - (xdiff / length) * DIRECTION_LINE_ARROW_OFFSET as f32;
+ let yc = dsty as f32 - (ydiff / length) * DIRECTION_LINE_ARROW_OFFSET as f32;
+
+ let left = Point::new((xc + prepx * DIRECTION_LINE_ARROW_OFFSET as f32).round() as i32, (yc + prepy * DIRECTION_LINE_ARROW_OFFSET as f32).round() as i32);
+ let right = Point::new((xc - prepx * DIRECTION_LINE_ARROW_OFFSET as f32).round() as i32, (yc - prepy * DIRECTION_LINE_ARROW_OFFSET as f32).round() as i32);
+ let tip = Point::new(dstx, dsty);
+ let center = Point::new(xc.round() as i32, yc.round() as i32);
+
+ let mut maxx = srcx.max(dstx);
+ let mut maxy = srcy.max(dsty);
+ for p in line
+ .iter()
+ .copied()
+ .chain([
+ tip, center, left, right,
+ ])
+ {
+ if p.x > maxx {
+ maxx = p.x;
+ }
+ if p.y > maxy {
+ maxy = p.y;
+ }
+ }
+ ext(img, &mut (*c, *orih), &mut (maxx.saturating_sub(*c as i32) as u32, maxy.saturating_sub(*orih as i32) as u32));
- // arrow
- let x = *c as i32;
- let y = *orih as i32;
- let offset = DIRECTION_LINE_ARROW_OFFSET as i32;
- // left
+ draw_polygon_mut(img, &line, colors::DIRECT);
draw_polygon_mut(
img,
&[
- Point::new(x, y),
- Point::new(x - offset, y - offset),
- Point::new(x, y - offset),
+ tip, left, center,
],
colors::DIRECT,
);
- // right
draw_polygon_mut(
img,
&[
- Point::new(x, y),
- Point::new(x + offset, y - offset),
- Point::new(x, y - offset),
+ tip, right, center,
],
colors::DIRECT,
);
+
+ *c = dstx as u32;
+ *orih = dsty as u32;
}
fn build(ast: &[DepthExpr]) -> DynamicImage {
@@ -192,8 +219,7 @@ fn build(ast: &[DepthExpr]) -> DynamicImage {
draw_process(&mut img, "a", &mut offset);
draw_direction(&mut img, &mut offset, None);
draw_process(&mut img, "a", &mut offset);
- let (a, b) = (offset.2, offset.1);
- draw_direction(&mut img, &mut offset, Some(&(a + 100, b + 1000)));
+ draw_direction(&mut img, &mut offset, Some(&(10, 100)));
draw_process(&mut img, "a", &mut offset);
img