blockworx_geom/grid/
bridge.rs1use blockworx_doc::geometry::{
8 FracVal, GridPoint, GridRect, GridSize, GridVec, ScreenPoint, ScreenRect, ScreenSize,
9};
10
11use crate::{
12 Pos2, Rect, Vec2,
13 grid::{grid_i32, grid_u32_ceil, px, px_u},
14 pos2, vec2,
15};
16
17pub fn grid_point(pos: Pos2) -> GridPoint {
19 GridPoint {
20 x: grid_i32(pos.x),
21 y: grid_i32(pos.y),
22 }
23}
24
25pub fn px_point(point: GridPoint) -> Pos2 {
27 pos2(px(point.x), px(point.y))
28}
29
30pub fn grid_size_ceil(extent: Vec2) -> GridSize {
33 GridSize {
34 w: grid_u32_ceil(extent.x),
35 h: grid_u32_ceil(extent.y),
36 }
37}
38
39pub fn grid_vec(delta: Vec2) -> GridVec {
41 GridVec::new(grid_i32(delta.x), grid_i32(delta.y))
42}
43
44pub fn px_vec(delta: GridVec) -> Vec2 {
47 vec2(px(delta.dx), px(delta.dy))
48}
49
50pub fn px_rect(rect: GridRect) -> Rect {
52 Rect::from_min_size(
53 pos2(px(rect.left()), px(rect.top())),
54 vec2(px_u(rect.size.w), px_u(rect.size.h)),
55 )
56}
57
58pub fn screen_rect(rect: Rect) -> ScreenRect {
62 ScreenRect {
63 top_left: ScreenPoint {
64 x: FracVal::from(rect.min.x),
65 y: FracVal::from(rect.min.y),
66 },
67 size: ScreenSize {
68 w: FracVal::from(rect.width()),
69 h: FracVal::from(rect.height()),
70 },
71 }
72}
73
74pub fn artwork_rect(rect: ScreenRect) -> Rect {
76 Rect::from_min_size(
77 pos2(rect.top_left.x.into(), rect.top_left.y.into()),
78 vec2(rect.size.w.into(), rect.size.h.into()),
79 )
80}
81
82pub fn grid_rect(start: Pos2, end: Pos2) -> GridRect {
85 GridRect::from_two_pos(grid_point(start), grid_point(end))
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91 use crate::grid::GRID_SIZE;
92
93 #[test]
94 fn a_point_lands_on_the_nearest_cell() {
95 let cell = |x: f32, y: f32| grid_point(pos2(x * GRID_SIZE, y * GRID_SIZE));
96 assert_eq!(cell(2.0, 3.0), GridPoint { x: 2, y: 3 });
97 assert_eq!(cell(2.4, 3.4), GridPoint { x: 2, y: 3 });
98 assert_eq!(cell(2.6, 3.6), GridPoint { x: 3, y: 4 });
99 assert_eq!(cell(-2.4, -3.6), GridPoint { x: -2, y: -4 });
100 }
101
102 #[test]
103 fn a_corner_pair_normalizes_whichever_way_it_was_dragged() {
104 let (start, end) = (pos2(5.0 * GRID_SIZE, 1.0 * GRID_SIZE), pos2(0.0, 0.0));
105 assert!(
106 start.x > end.x && start.y > end.y,
107 "precondition: the drag runs up and to the left, so normalization matters"
108 );
109 let expected = GridRect {
110 top_left: GridPoint { x: 0, y: 0 },
111 size: GridSize { w: 5, h: 1 },
112 };
113 assert_eq!(grid_rect(start, end), expected);
114 assert_eq!(grid_rect(end, start), expected);
115 }
116}