Struct fj_kernel::algorithms::intersect::HorizontalRayToTheRight
source · Expand description
A horizontal ray that goes to the right
For in-kernel use, we don’t need anything more flexible, and being exactly horizontal simplifies some calculations.
Fields§
§origin: Point<D>The point where the ray originates
Implementations§
source§impl<const D: usize> HorizontalRayToTheRight<D>
impl<const D: usize> HorizontalRayToTheRight<D>
sourcepub fn direction(&self) -> Vector<D>
pub fn direction(&self) -> Vector<D>
Access the direction of this ray
Examples found in repository?
src/algorithms/intersect/ray_face.rs (line 31)
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
fn intersect(self) -> Option<Self::Intersection> {
let (ray, face) = self;
let plane = match face.surface().geometry().u {
GlobalPath::Circle(_) => todo!(
"Casting a ray against a swept circle is not supported yet"
),
GlobalPath::Line(line) => Plane::from_parametric(
line.origin(),
line.direction(),
face.surface().geometry().v,
),
};
if plane.is_parallel_to_vector(&ray.direction()) {
let a = plane.origin();
let b = plane.origin() + plane.u();
let c = plane.origin() + plane.v();
let d = ray.origin;
let [a, b, c, d] = [a, b, c, d]
.map(|point| [point.x, point.y, point.z])
.map(|point| point.map(Scalar::into_f64));
if robust_predicates::orient3d(&a, &b, &c, &d) == 0. {
return Some(RayFaceIntersection::RayHitsFaceAndAreParallel);
} else {
return None;
}
}
// The pattern in this assertion resembles `ax*by = ay*bx`, which holds
// true if the vectors `a = (ax, ay)` and `b = (bx, by)` are parallel.
//
// We're looking at the plane's direction vectors here, but we're
// ignoring their x-components. By doing that, we're essentially
// projecting those vectors into the yz-plane.
//
// This means that the following assertion verifies that the projections
// of the plane's direction vectors into the yz-plane are not parallel.
// If they were, then the plane could only be parallel to the x-axis,
// and thus our ray.
//
// We already handled the case of the ray and plane being parallel
// above. The following assertion should thus never be triggered.
assert_ne!(
plane.u().y * plane.v().z,
plane.u().z * plane.v().y,
"Plane and ray are parallel; should have been ruled out previously"
);
// Let's figure out the intersection between the ray and the plane.
let (t, u, v) = {
// The following math would get *very* unwieldy with those
// full-length variable names. Let's define some short-hands.
let orx = ray.origin.x;
let ory = ray.origin.y;
let orz = ray.origin.z;
let opx = plane.origin().x;
let opy = plane.origin().y;
let opz = plane.origin().z;
let d1x = plane.u().x;
let d1y = plane.u().y;
let d1z = plane.u().z;
let d2x = plane.v().x;
let d2y = plane.v().y;
let d2z = plane.v().z;
// Let's figure out where the intersection between the ray and the
// plane is. By equating the parametric equations of the ray and the
// plane, we get a vector equation, which in turn gives us a system
// of three equations with three unknowns: `t` (for the ray) and
// `u`/`v` (for the plane).
//
// Since the ray's direction vector is `(1, 0, 0)`, it works out
// such that `t` is not in the equations for y and z, meaning we can
// solve those equations for `u` and `v` independently.
//
// By doing some math, we get the following solutions:
let v = (d1y * (orz - opz) + (opy - ory) * d1z)
/ (d1y * d2z - d2y * d1z);
let u = (ory - opy - d2y * v) / d1y;
let t = opx - orx + d1x * u + d2x * v;
(t, u, v)
};
if t < Scalar::ZERO {
// Ray points away from plane.
return None;
}
let point = Point::from([u, v]);
let intersection = match (face, &point).intersect()? {
FacePointIntersection::PointIsInsideFace => {
RayFaceIntersection::RayHitsFace
}
FacePointIntersection::PointIsOnEdge(edge) => {
RayFaceIntersection::RayHitsEdge(edge)
}
FacePointIntersection::PointIsOnVertex(vertex) => {
RayFaceIntersection::RayHitsVertex(vertex)
}
};
Some(intersection)
}Trait Implementations§
source§impl<const D: usize> Clone for HorizontalRayToTheRight<D>
impl<const D: usize> Clone for HorizontalRayToTheRight<D>
source§fn clone(&self) -> HorizontalRayToTheRight<D>
fn clone(&self) -> HorizontalRayToTheRight<D>
Returns a copy of the value. Read more
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moresource§impl<const D: usize> Debug for HorizontalRayToTheRight<D>
impl<const D: usize> Debug for HorizontalRayToTheRight<D>
source§impl<const D: usize> PartialEq<HorizontalRayToTheRight<D>> for HorizontalRayToTheRight<D>
impl<const D: usize> PartialEq<HorizontalRayToTheRight<D>> for HorizontalRayToTheRight<D>
source§fn eq(&self, other: &HorizontalRayToTheRight<D>) -> bool
fn eq(&self, other: &HorizontalRayToTheRight<D>) -> bool
This method tests for
self and other values to be equal, and is used
by ==.impl<const D: usize> Copy for HorizontalRayToTheRight<D>
impl<const D: usize> Eq for HorizontalRayToTheRight<D>
impl<const D: usize> StructuralEq for HorizontalRayToTheRight<D>
impl<const D: usize> StructuralPartialEq for HorizontalRayToTheRight<D>
Auto Trait Implementations§
impl<const D: usize> RefUnwindSafe for HorizontalRayToTheRight<D>
impl<const D: usize> Send for HorizontalRayToTheRight<D>
impl<const D: usize> Sync for HorizontalRayToTheRight<D>
impl<const D: usize> Unpin for HorizontalRayToTheRight<D>
impl<const D: usize> UnwindSafe for HorizontalRayToTheRight<D>
Blanket Implementations§
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>
fn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>
Convert
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
Convert
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
Convert
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
Convert
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
The inverse inclusion map: attempts to construct
self from the equivalent element of its
superset. Read more§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
Checks if
self is actually part of its subset T (and can be converted to it).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
Use with care! Same as
self.to_subset but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
The inclusion map: converts
self to the equivalent element of its superset.