diff --git a/geom/src/obb.rs b/geom/src/obb.rs index 5ab7a3f0..e56e8330 100644 --- a/geom/src/obb.rs +++ b/geom/src/obb.rs @@ -2,6 +2,7 @@ use crate::aabb::AABB; use crate::{vec2, Circle, Intersect, Polygon, Segment, Shape, Vec2}; use serde::{Deserialize, Serialize}; use std::hint::unreachable_unchecked; +use std::ops::Add; /// Oriented bounding box #[derive(Copy, Clone, Debug, Serialize, Deserialize)] @@ -15,6 +16,7 @@ impl OBB { }; /// cossin of `UNIT_X` makes this an AABB + #[inline] pub fn new(center: Vec2, cossin: Vec2, w: f32, h: f32) -> Self { let up = cossin * w * 0.5; let right = cossin.perpendicular() * h * 0.5; @@ -28,10 +30,23 @@ impl OBB { } } + #[inline] pub fn new_corners(corners: [Vec2; 4]) -> Self { Self { corners } } + #[inline] + pub fn from_rotated_aabb(aabb: AABB, cossin: Vec2) -> Self { + Self { + corners: [ + aabb.ll.rotated_by(cossin), + vec2(aabb.ur.x, aabb.ll.y).rotated_by(cossin), + aabb.ur.rotated_by(cossin), + vec2(aabb.ll.x, aabb.ur.y).rotated_by(cossin), + ], + } + } + #[inline] pub fn axis(&self) -> [Vec2; 2] { [ @@ -45,6 +60,7 @@ impl OBB { (self.corners[2] + self.corners[0]) * 0.5 } + #[inline] pub fn expand(&self, w: f32) -> Self { let [a, b] = self.axis(); let a = match a.try_normalize() { @@ -117,6 +133,7 @@ impl OBB { ok0 & ok1 & ok2 & ok3 } + #[inline] pub fn is_close(&self, p: Vec2, dist: f32) -> bool { if self.contains(p) { return true; @@ -151,6 +168,7 @@ impl OBB { /// 4 v ^ 2 /// +-->--+ /// 1 + #[inline] pub fn segments(&self) -> [Segment; 4] { [ Segment::new(self.corners[0], self.corners[1]), @@ -161,6 +179,31 @@ impl OBB { } } +impl Add for OBB { + type Output = OBB; + + #[inline] + fn add(self, rhs: Vec2) -> Self::Output { + Self { + corners: [ + self.corners[0] + rhs, + self.corners[1] + rhs, + self.corners[2] + rhs, + self.corners[3] + rhs, + ], + } + } +} + +impl Add for Vec2 { + type Output = OBB; + + #[inline] + fn add(self, rhs: OBB) -> Self::Output { + rhs + self + } +} + impl Shape for OBB { #[inline] fn bbox(&self) -> AABB { @@ -201,6 +244,7 @@ impl Intersect for OBB { } impl Intersect for OBB { + #[inline] fn intersects(&self, shape: &AABB) -> bool { let Vec2 { x: mut min_x, diff --git a/geom/src/plane.rs b/geom/src/plane.rs index 964229a8..4769e50c 100644 --- a/geom/src/plane.rs +++ b/geom/src/plane.rs @@ -14,6 +14,7 @@ pub struct Plane { impl Plane { pub const X: Self = Self { n: Vec3::X, o: 0.0 }; + #[inline] pub const fn new(n: Vec3, o: f32) -> Self { Self { n, o } } diff --git a/geom/src/polyline.rs b/geom/src/polyline.rs index a601521c..05258cae 100644 --- a/geom/src/polyline.rs +++ b/geom/src/polyline.rs @@ -21,6 +21,7 @@ impl From> for PolyLine { } impl PolyLine { + #[inline] pub fn new(x: Vec) -> Self { if x.is_empty() { panic!("Vec must have at least one point") @@ -31,6 +32,7 @@ impl PolyLine { } } + #[inline] pub fn clear_push(&mut self, x: Vec2) { self.points.clear(); self.points.push(x); @@ -47,6 +49,7 @@ impl PolyLine { self.l += length(&self.points[old_l - 1..]); } + #[inline] pub fn pop(&mut self) -> Vec2 { let v = match self.points.pop() { Some(x) => x, @@ -57,6 +60,7 @@ impl PolyLine { v } + #[inline] pub fn push(&mut self, item: Vec2) { self.l += (self.last() - item).mag(); self.points.push(item); @@ -168,6 +172,7 @@ impl PolyLine { self.points_dirs_along(std::iter::once(l)).next().unwrap() // Unwrap ok: std::iter::once } + #[inline] pub fn length(&self) -> f32 { self.l } @@ -286,6 +291,7 @@ impl PolyLine { } } + #[inline] pub fn bbox(&self) -> AABB { let (min, max) = match super::minmax(self.points.iter().copied()) { Some(x) => x, @@ -295,14 +301,17 @@ impl PolyLine { AABB::new_ll_ur(min, max) } + #[inline] pub fn n_points(&self) -> usize { self.points.len() } + #[inline] pub fn is_empty(&self) -> bool { self.points.is_empty() } + #[inline] pub fn get(&self, index: I) -> Option<&I::Output> where I: SliceIndex<[Vec2]>, @@ -310,10 +319,12 @@ impl PolyLine { self.points.get(index) } + #[inline] pub fn first(&self) -> Vec2 { unsafe { *self.points.get_unchecked(0) } } + #[inline] pub fn last(&self) -> Vec2 { unsafe { *self.points.get_unchecked(self.points.len() - 1) } } @@ -345,6 +356,7 @@ impl PolyLine { impl Index> for PolyLine { type Output = [Vec2]; + #[inline] fn index(&self, r: Range) -> &[Vec2] { &self.points[r] } @@ -353,6 +365,7 @@ impl Index> for PolyLine { impl Index for PolyLine { type Output = Vec2; + #[inline] fn index(&self, index: usize) -> &Vec2 { &self.points[index] } @@ -367,6 +380,7 @@ pub struct PointsAlongs<'a> { } impl<'a> PointsAlongs<'a> { + #[inline] pub fn next(&mut self, d: f32) -> Option<(Vec2, Vec2)> { while d > self.partial + self.dist { let w = self.windows.next()?; diff --git a/geom/src/polyline3.rs b/geom/src/polyline3.rs index d72cb2ae..f2f1b820 100644 --- a/geom/src/polyline3.rs +++ b/geom/src/polyline3.rs @@ -19,6 +19,7 @@ impl From> for PolyLine3 { } impl PolyLine3 { + #[inline] pub fn new(x: Vec) -> Self { if x.is_empty() { panic!("Vec must have at least one point") @@ -31,6 +32,7 @@ impl PolyLine3 { /// # Safety /// Must not be used with advanced functions if passed vector is empty, as it would lead to UB + #[inline] pub unsafe fn new_unchecked(x: Vec) -> Self { Self { l: length(&x), @@ -42,12 +44,14 @@ impl PolyLine3 { PolyLine::new(self.points.iter().copied().map(Vec3::xy).collect()) } + #[inline] pub fn clear_push(&mut self, x: Vec3) { self.points.clear(); self.points.push(x); self.l = 0.0; } + #[inline] pub fn len(&self) -> usize { self.points.len() } @@ -154,6 +158,7 @@ impl PolyLine3 { self.l += length(&self.points[old_l - 1..]); } + #[inline] pub fn pop(&mut self) -> Vec3 { let v = match self.points.pop() { Some(x) => x, @@ -164,11 +169,13 @@ impl PolyLine3 { v } + #[inline] pub fn push(&mut self, item: Vec3) { self.l += (self.last() - item).mag(); self.points.push(item); } + #[inline] pub fn pop_first(&mut self) -> Vec3 { let v = self.points.remove(0); self.check_empty(); @@ -274,6 +281,7 @@ impl PolyLine3 { Some(self.get(id + 1)? - self.get(id)?) } + #[inline] pub fn first_dir(&self) -> Option { if self.points.len() >= 2 { (self[1] - self[0]).try_normalize() @@ -282,6 +290,7 @@ impl PolyLine3 { } } + #[inline] pub fn last_dir(&self) -> Option { let l = self.points.len(); if l >= 2 { @@ -313,6 +322,7 @@ impl PolyLine3 { ) } + #[inline] pub fn length(&self) -> f32 { self.l } @@ -447,6 +457,7 @@ impl PolyLine3 { } } + #[inline] pub fn bbox(&self) -> AABB3 { let (min, max) = match super::minmax3(self.points.iter().copied()) { Some(x) => x, @@ -456,14 +467,17 @@ impl PolyLine3 { AABB3::new(min, max) } + #[inline] pub fn n_points(&self) -> usize { self.points.len() } + #[inline] pub fn is_empty(&self) -> bool { self.points.is_empty() } + #[inline] pub fn get(&self, index: I) -> Option<&I::Output> where I: SliceIndex<[Vec3]>, @@ -471,10 +485,12 @@ impl PolyLine3 { self.points.get(index) } + #[inline] pub fn first(&self) -> Vec3 { unsafe { *self.points.get_unchecked(0) } } + #[inline] pub fn last(&self) -> Vec3 { unsafe { *self.points.get_unchecked(self.points.len() - 1) } }