linalg.rs
1 /* This file is part of DarkFi (https://dark.fi) 2 * 3 * Copyright (C) 2020-2025 Dyne.org foundation 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Affero General Public License as 7 * published by the Free Software Foundation, either version 3 of the 8 * License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Affero General Public License for more details. 14 * 15 * You should have received a copy of the GNU Affero General Public License 16 * along with this program. If not, see <https://www.gnu.org/licenses/>. 17 */ 18 19 use async_trait::async_trait; 20 use darkfi_serial::{SerialDecodable, SerialEncodable}; 21 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, Sub, SubAssign}; 22 23 #[derive(Clone, Copy, Debug, SerialEncodable, SerialDecodable)] 24 pub struct Dimension { 25 pub w: f32, 26 pub h: f32, 27 } 28 29 impl Dimension { 30 pub fn contains(&self, other: &Dimension) -> bool { 31 other.w <= self.w && other.h <= self.h 32 } 33 } 34 35 impl From<[f32; 2]> for Dimension { 36 fn from(dim: [f32; 2]) -> Self { 37 Self { w: dim[0], h: dim[1] } 38 } 39 } 40 41 impl Mul<f32> for Dimension { 42 type Output = Dimension; 43 44 fn mul(self, scale: f32) -> Self::Output { 45 Self { w: self.w * scale, h: self.h * scale } 46 } 47 } 48 49 impl Div<f32> for Dimension { 50 type Output = Dimension; 51 52 fn div(self, scale: f32) -> Self::Output { 53 Self { w: self.w / scale, h: self.h / scale } 54 } 55 } 56 57 #[derive(Clone, Copy, Default, SerialEncodable, SerialDecodable)] 58 pub struct Point { 59 pub x: f32, 60 pub y: f32, 61 } 62 63 impl Point { 64 pub const fn new(x: f32, y: f32) -> Self { 65 Self { x, y } 66 } 67 68 pub fn zero() -> Self { 69 Self { x: 0., y: 0. } 70 } 71 72 pub fn unpack(&self) -> (f32, f32) { 73 (self.x, self.y) 74 } 75 76 pub fn as_arr(&self) -> [f32; 2] { 77 [self.x, self.y] 78 } 79 80 pub fn offset(&self, off_x: f32, off_y: f32) -> Self { 81 Self { x: self.x + off_x, y: self.y + off_y } 82 } 83 84 pub fn to_rect(&self, w: f32, h: f32) -> Rectangle { 85 Rectangle { x: self.x, y: self.y, w, h } 86 } 87 88 pub fn dist_sq(&self, other: Point) -> f32 { 89 (self.x - other.x).powi(2) + (self.y - other.y).powi(2) 90 } 91 pub fn dist(&self, other: Point) -> f32 { 92 self.dist_sq(other).sqrt() 93 } 94 95 pub fn normalize(&mut self) { 96 let scale = self.dist(Point::zero()); 97 self.x /= scale; 98 self.y /= scale; 99 assert!((self.dist(Point::zero()) - 1.) < f32::EPSILON); 100 } 101 102 /// Counterclockwise perp vector (with -y up) 103 pub fn perp_left(&self) -> Point { 104 Point::new(self.y, -self.x) 105 } 106 /// Clockwise perp vector (with +y down) 107 pub fn perp_right(&self) -> Point { 108 Point::new(-self.y, self.x) 109 } 110 } 111 112 impl From<[f32; 2]> for Point { 113 fn from(pos: [f32; 2]) -> Self { 114 Self { x: pos[0], y: pos[1] } 115 } 116 } 117 118 impl std::fmt::Debug for Point { 119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 120 write!(f, "({}, {})", self.x, self.y) 121 } 122 } 123 124 impl Add for Point { 125 type Output = Self; 126 127 fn add(self, other: Self) -> Self::Output { 128 Self { x: self.x + other.x, y: self.y + other.y } 129 } 130 } 131 132 impl Sub for Point { 133 type Output = Self; 134 135 fn sub(self, other: Self) -> Self::Output { 136 Self { x: self.x - other.x, y: self.y - other.y } 137 } 138 } 139 140 impl AddAssign for Point { 141 fn add_assign(&mut self, other: Self) { 142 *self = Self { x: self.x + other.x, y: self.y + other.y }; 143 } 144 } 145 146 impl SubAssign for Point { 147 fn sub_assign(&mut self, other: Self) { 148 *self = Self { x: self.x - other.x, y: self.y - other.y }; 149 } 150 } 151 152 impl Mul<f32> for Point { 153 type Output = Self; 154 155 fn mul(self, scale: f32) -> Self { 156 Point::new(scale * self.x, scale * self.y) 157 } 158 } 159 160 #[derive(Clone, Copy, SerialEncodable, SerialDecodable)] 161 pub struct Rectangle { 162 pub x: f32, 163 pub y: f32, 164 pub w: f32, 165 pub h: f32, 166 } 167 168 impl Rectangle { 169 pub const fn new(x: f32, y: f32, w: f32, h: f32) -> Self { 170 Self { x, y, w, h } 171 } 172 173 pub fn zero() -> Self { 174 Self { x: 0., y: 0., w: 0., h: 0. } 175 } 176 177 /// Use from() instead 178 #[deprecated] 179 pub fn from_array(arr: [f32; 4]) -> Self { 180 Self { x: arr[0], y: arr[1], w: arr[2], h: arr[3] } 181 } 182 183 pub fn clip(&self, other: &Self) -> Option<Self> { 184 if other.x + other.w < self.x || 185 other.x > self.x + self.w || 186 other.y + other.h < self.y || 187 other.y > self.y + self.h 188 { 189 return None 190 } 191 192 let mut clipped = other.clone(); 193 if clipped.x < self.x { 194 clipped.x = self.x; 195 clipped.w = other.x + other.w - clipped.x; 196 } 197 if clipped.y < self.y { 198 clipped.y = self.y; 199 clipped.h = other.y + other.h - clipped.y; 200 } 201 if clipped.x + clipped.w > self.x + self.w { 202 clipped.w = self.x + self.w - clipped.x; 203 } 204 if clipped.y + clipped.h > self.y + self.h { 205 clipped.h = self.y + self.h - clipped.y; 206 } 207 Some(clipped) 208 } 209 210 pub fn with_zero_pos(&self) -> Self { 211 Self::new(0., 0., self.w, self.h) 212 } 213 214 pub fn clip_point(&self, mut point: Point) -> Point { 215 if point.x < self.x { 216 point.x = self.x; 217 } 218 if point.y < self.y { 219 point.y = self.y; 220 } 221 if point.x > self.x + self.w { 222 point.x = self.x + self.w; 223 } 224 if point.y > self.y + self.h { 225 point.y = self.y + self.h; 226 } 227 point 228 } 229 230 pub fn contains(&self, point: Point) -> bool { 231 self.x <= point.x && 232 point.x <= self.x + self.w && 233 self.y <= point.y && 234 point.y <= self.y + self.h 235 } 236 237 pub fn rhs(&self) -> f32 { 238 self.x + self.w 239 } 240 pub fn bhs(&self) -> f32 { 241 self.y + self.h 242 } 243 244 pub fn pos(&self) -> Point { 245 Point { x: self.x, y: self.y } 246 } 247 pub fn corner(&self) -> Point { 248 Point { x: self.x + self.w, y: self.y + self.h } 249 } 250 pub fn center(&self) -> Point { 251 Point { x: self.x + self.w / 2., y: self.y + self.h / 2. } 252 } 253 pub fn top_right(&self) -> Point { 254 Point { x: self.rhs(), y: self.y } 255 } 256 pub fn bot_left(&self) -> Point { 257 Point { x: self.x, y: self.y + self.h } 258 } 259 260 pub fn dim(&self) -> Dimension { 261 Dimension { w: self.w, h: self.h } 262 } 263 264 #[deprecated] 265 pub fn top_left(&self) -> Point { 266 Point { x: self.x, y: self.y } 267 } 268 #[deprecated] 269 pub fn bottom_right(&self) -> Point { 270 Point { x: self.x + self.w, y: self.y + self.h } 271 } 272 273 pub fn includes(&self, child: &Self) -> bool { 274 self.contains(child.pos()) && self.contains(child.corner()) 275 } 276 } 277 278 impl From<[f32; 4]> for Rectangle { 279 fn from(rect: [f32; 4]) -> Self { 280 Self { x: rect[0], y: rect[1], w: rect[2], h: rect[3] } 281 } 282 } 283 284 impl Add<Point> for Rectangle { 285 type Output = Rectangle; 286 287 fn add(self, other: Point) -> Self::Output { 288 Self { x: self.x + other.x, y: self.y + other.y, w: self.w, h: self.h } 289 } 290 } 291 292 impl Sub<Point> for Rectangle { 293 type Output = Rectangle; 294 295 fn sub(self, other: Point) -> Self::Output { 296 Self { x: self.x - other.x, y: self.y - other.y, w: self.w, h: self.h } 297 } 298 } 299 300 impl Mul<f32> for Rectangle { 301 type Output = Rectangle; 302 303 fn mul(self, scale: f32) -> Self::Output { 304 Self { x: self.x * scale, y: self.y * scale, w: self.w * scale, h: self.h * scale } 305 } 306 } 307 308 impl Div<f32> for Rectangle { 309 type Output = Rectangle; 310 311 fn div(self, scale: f32) -> Self::Output { 312 Self { x: self.x / scale, y: self.y / scale, w: self.w / scale, h: self.h / scale } 313 } 314 } 315 316 impl DivAssign<f32> for Rectangle { 317 fn div_assign(&mut self, scale: f32) { 318 self.x /= scale; 319 self.y /= scale; 320 self.w /= scale; 321 self.h /= scale; 322 } 323 } 324 325 impl std::fmt::Debug for Rectangle { 326 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 327 write!(f, "({}, {}, {}, {})", self.x, self.y, self.w, self.h) 328 } 329 } 330 331 impl From<parley::BoundingBox> for Rectangle { 332 fn from(rect: parley::BoundingBox) -> Self { 333 Self::new(rect.x0 as f32, rect.y0 as f32, rect.width() as f32, rect.height() as f32) 334 } 335 }