This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

🚧 Try fixing Line.intersects_with(Line)

+86 -17
+21 -1
src/geometry/point.rs
··· 3 3 #[cfg(feature = "web")] 4 4 use wasm_bindgen::prelude::*; 5 5 6 - use crate::Region; 6 + use crate::{ 7 + Point::{Center, Corner}, 8 + Region, 9 + }; 7 10 8 11 use super::Angle; 9 12 ··· 182 185 Point::Corner(x, y) => write!(f, "({x}, {y})"), 183 186 Point::Center(x, y) => write!(f, "centered ({x}, {y})"), 184 187 } 188 + } 189 + } 190 + 191 + impl std::ops::Sub for Point { 192 + type Output = (isize, isize); 193 + 194 + fn sub(self, rhs: Point) -> Self::Output { 195 + match (self, rhs) { 196 + (Corner(..), Corner(..)) => {} 197 + (Center(..), Center(..)) => {} 198 + _ => panic!("Cannot subtract CornerPoint and CenterPoint"), 199 + } 200 + 201 + let (x1, y1) = self.xy::<isize>(); 202 + let (x2, y2) = rhs.xy::<isize>(); 203 + 204 + (x1 - x2, y1 - y2) 185 205 } 186 206 } 187 207
+65 -16
src/graphics/objects.rs
··· 1 - use crate::{Angle, Fill, Filter, Point, Region, Transformation}; 1 + use crate::{Angle, Containable, Fill, Filter, Point, Region, Transformation}; 2 2 use anyhow::anyhow; 3 3 use itertools::Itertools; 4 4 use std::fmt::Display; ··· 347 347 self.fillable() && !matches!(self, Object::Dot(..)) 348 348 } 349 349 350 + pub fn point_is_on_line(self, point: Point) -> bool { 351 + match (&self, point) { 352 + (Object::Line(s, e, _), Point::Corner(x, y)) => { 353 + if !self.region().contains(&point) { 354 + return false; 355 + } 356 + 357 + let (sx, sy) = s.xy::<f32>(); 358 + let (ex, ey) = e.xy::<f32>(); 359 + 360 + let m = (ey - sy) / (ex - sx); 361 + let p = sy - m * sx; 362 + 363 + (m * x as f32 + p) as usize == y 364 + } 365 + (Object::Line(..), _) => panic!("Point type not supported"), 366 + _ => panic!("{self:?} is not a line object"), 367 + } 368 + } 369 + 370 + // 371 + // ```rs 372 + // use shapemaker::{Object::Line, Point::Corner}; 373 + // let line = |x1: usize, y1: usize, x2: usize, y2: usize| Line(Corner(x1, y1), Corner(x2, y2), 1.0); 374 + // assert!(line(1, 1, 4, 4).intersects_with(line(1, 4, 4, 1))); 375 + // assert!(line(7, 6, 9, 7).intersects_with(line(7, 7, 9, 4))); 376 + // ``` 350 377 pub fn intersects_with(&self, line: Object) -> bool { 351 378 match (self, &line) { 352 - (Object::Line(s1, e1, _), Object::Line(s2, e2, _)) => { 353 - let x1 = s1.x() as f32; 354 - let y1 = s1.y() as f32; 355 - let x2 = s2.x() as f32; 356 - let y2 = s2.y() as f32; 357 - let x3 = e1.x() as f32; 358 - let y3 = e1.y() as f32; 359 - let x4 = e2.x() as f32; 360 - let y4 = e2.y() as f32; 379 + (&Object::Line(s1, e1, _), &Object::Line(s2, e2, _)) => { 380 + let (dx1, dy1) = e1 - s1; 381 + let (dx2, dy2) = e2 - s2; 382 + let (dx3, dy3) = s2 - s1; 383 + 384 + let det = dx1 * dy2 - dy1 * dx2; 385 + 386 + let det1 = dx1 * dy3 - dx3 * dy1; 387 + let det2 = dx2 * dy3 - dx3 * dy2; 388 + 389 + if det == 0 { 390 + if det1 != 0 || det2 != 0 { 391 + return false; 392 + } 393 + 394 + let (x1, y1) = s1.xy::<isize>(); 395 + let (x2, y2) = e1.xy::<isize>(); 396 + let (x3, y3) = s2.xy::<isize>(); 397 + 398 + if dx1 != 0 && (x1 < x3 && x3 < x2 || x1 > x3 && x3 > x2) { 399 + return true; 400 + } 401 + 402 + if dx1 == 0 && (y1 < y3 && y3 < y2 || y1 > y3 && y3 > y2) { 403 + return true; 404 + } 405 + 406 + return false; 407 + } 408 + 409 + let frac_less_than_one = |num: isize, den: isize| { 410 + if num.signum() != den.signum() { 411 + return false; 412 + } 361 413 362 - let d1 = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3); 363 - let d2 = (x4 - x3) * (y2 - y3) - (y4 - y3) * (x2 - x3); 364 - let d3 = (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1); 365 - let d4 = (x2 - x1) * (y4 - y1) - (y2 - y1) * (x4 - x1); 414 + num.abs() <= den.abs() 415 + }; 366 416 367 - return ((d1 > 0. && d2 < 0.) || (d1 < 0. && d2 > 0.)) 368 - && ((d3 > 0. && d4 < 0.) || (d3 < 0. && d4 > 0.)); 417 + frac_less_than_one(det1, det) && frac_less_than_one(det2, det) 369 418 } 370 419 _ => { 371 420 unimplemented!(