Skip to content

Commit 8faf138

Browse files
committed
Further simplify Plane methods now that coefficients are always normalized
1 parent a1b05e4 commit 8faf138

File tree

2 files changed

+25
-37
lines changed

2 files changed

+25
-37
lines changed

core/src/geom/prim.rs

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//! Includes vertices, polygons, planes, rays, and more.
44
55
use alloc::vec::Vec;
6-
76
use core::fmt::{self, Debug, Formatter};
87

98
use crate::math::{
@@ -402,9 +401,9 @@ impl<B> Plane3<B> {
402401
///
403402
/// ```
404403
pub fn from_point_and_normal(pt: Point3<B>, n: Normal3) -> Self {
405-
let n = n.normalize();
406-
let d = dot(&pt.0, &n.0);
407-
Plane::new(n.x(), n.y(), n.z(), d)
404+
let mut n = n.to().normalize().to_hom();
405+
n[3] = -n.dot(&pt.to_hom());
406+
Self(n)
408407
}
409408

410409
/// Returns the normal vector of `self`.
@@ -439,8 +438,7 @@ impl<B> Plane3<B> {
439438
/// ```
440439
#[inline]
441440
pub fn offset(&self) -> f32 {
442-
// plane dist from origin is origin dist from plane, negated
443-
-self.signed_dist(Point3::origin())
441+
-self.0[3]
444442
}
445443

446444
/// Returns the perpendicular projection of a point on `self`.
@@ -470,9 +468,9 @@ impl<B> Plane3<B> {
470468
/// assert_eq!(<Plane3>::new(0.0, 0.0, 1.0, 2.0).project(pt), pt3(1.0, 2.0, 2.0));
471469
/// ```
472470
pub fn project(&self, pt: Point3<B>) -> Point3<B> {
473-
// t = -(plane · orig) / (plane · dir)
474-
// In this case dir is normal to the plane and (plane · dir) = 1
475-
let t = -self.dot(pt);
471+
// The vector that projects pt on the plane is parallel with the plane
472+
// normal and its length is the distance of pt from the plane.
473+
let t = -self.signed_dist(pt);
476474
let dir = self.normal();
477475
pt + t * dir.to()
478476
}
@@ -494,7 +492,7 @@ impl<B> Plane3<B> {
494492
/// ```
495493
#[inline]
496494
pub fn signed_dist(&self, pt: Point3<B>) -> f32 {
497-
self.dot(pt)
495+
self.0.dot(&pt.to_hom())
498496
}
499497

500498
/// Returns whether a point is in the half-space that the normal of `self`
@@ -513,19 +511,7 @@ impl<B> Plane3<B> {
513511
// TODO "plane.is_inside(point)" reads wrong
514512
#[inline]
515513
pub fn is_inside(&self, pt: Point3<B>) -> bool {
516-
self.dot(pt) <= 0.0
517-
}
518-
519-
/// Returns the dot product of the coefficients of self and a point,
520-
/// interpreted as a homogeneous vector.
521-
///
522-
/// Let `self` = (*a*, *b*, *c*, *d*) and `pt` = (*x*, *y*, *z*).
523-
/// Then `self.dot(pt)` = *ax + by + cz* + d.
524-
#[inline]
525-
pub fn dot(&self, pt: Point3<B>) -> f32 {
526-
// Use homogeneous pt to get self · pt = ax + by + cz + d
527-
// Could also just add d manually to ax + by + cz
528-
dot(&self.0.0, &pt.to_hom().0)
514+
self.signed_dist(pt) <= 0.0
529515
}
530516

531517
/// Returns an orthonormal affine basis on `self`.
@@ -686,7 +672,7 @@ impl<B> Line2<B> {
686672
///
687673
/// # Panics
688674
/// If the vector (a, b) is not unit-length.
689-
pub const fn new(a: f32, b: f32, c: f32) -> Self {
675+
pub fn new(a: f32, b: f32, c: f32) -> Self {
690676
// TODO This method can't itself normalize because const
691677
assert!((a * a + b * b - 1.0).abs() < 1e-6, "non-unit normal");
692678
Self(Vector::new([a, b, -c]))

geom/src/isect.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -307,11 +307,13 @@ impl<B> Intersect<Self> for Line2<B> {
307307
/// };
308308
/// use retrofire_geom::{Intersect, isect::LineIntersect::*};
309309
///
310-
/// let horiz = Line2::<()>::from(Ray(pt2(0.0, 2.0), vec2(1.0, 0.0)));
311-
/// let vert = Line2::<()>::from(Ray(pt2(3.0, 0.0), vec2(0.0, 1.0)));
312-
/// assert_eq!(horiz.intersect(&vert), Some(Point(pt2(3.0, 2.0))));
310+
/// let horiz: Line2 = Ray(pt2(0.0, 2.0), vec2(1.0, 0.0)).into();
311+
/// let vert: Line2 = Ray(pt2(3.0, 0.0), vec2(0.0, 1.0)).into();
313312
///
314-
/// let horiz2 = Line2::<()>::from(Ray(pt2(0.0, 3.0), vec2(1.0, 0.0)));
313+
/// let isect = horiz.intersect(&vert).and_then(|i| i.point());
314+
/// assert_approx_eq!(isect, Some(pt2(3.0, 2.0)));
315+
///
316+
/// let horiz2 = <Line2>::from(Ray(pt2(0.0, 3.0), vec2(1.0, 0.0)));
315317
/// assert_eq!(horiz.intersect(&horiz2), None);
316318
///
317319
/// assert_eq!(horiz.intersect(&horiz), Some(Coincident));
@@ -323,23 +325,23 @@ impl<B> Intersect<Self> for Line2<B> {
323325
let [d, e, f] = other.coeffs();
324326

325327
// Solve the system of equations for x and y:
326-
// ax + by = c // self
327-
// dx + ey = f // other
328+
// ax + by + c = 0 // self
329+
// dx + ey + f = 0 // other
328330
//
329331
// Write in matrix form and solve:
330-
// (a b) (x) = (c)
331-
// (d e) (y) (f)
332+
// (a b) (x) = (-c)
333+
// (d e) (y) (-f)
332334
//
333335
// -1
334-
// (x) = (a b) (c)
335-
// (y) (d e) (f)
336+
// (x) = (a b) (-c)
337+
// (y) (d e) (-f)
336338
let abde: Mat2<B> = mat![
337339
a, b;
338340
d, e;
339341
];
340342
match abde.checked_inverse() {
341343
Some(inv) => {
342-
let res = inv.apply(&pt2(c, f));
344+
let res = inv.apply(&pt2(-c, -f));
343345
Some(LineIntersect::Point(res))
344346
}
345347
None if [a, b, c].approx_eq(&[d, e, f]) => {
@@ -430,8 +432,8 @@ impl<B> Intersect<Edge<Point2<B>>> for Ray2<B> {
430432
// Ray intersects the line of edge, but still have to check
431433
// whether the point is between edge endpoints
432434
let e01 = edge.1 - edge.0;
433-
let u = (pt - edge.0).dot(&e01);
434-
if u.approx_in(0.0..e01.len_sqr()) {
435+
let u = (pt - edge.0).scalar_project(&e01);
436+
if u.approx_in(0.0..1.0) {
435437
return Some((t, pt));
436438
}
437439

0 commit comments

Comments
 (0)