parry3d_f64/query/visitors/
composite_point_containment_test.rs

1use crate::bounding_volume::SimdAabb;
2use crate::math::{Point, Real, SimdReal, SIMD_WIDTH};
3use crate::partitioning::{SimdVisitStatus, SimdVisitor};
4use crate::query::point::point_query::PointQuery;
5use crate::shape::TypedSimdCompositeShape;
6use crate::utils::IsometryOpt;
7use simba::simd::{SimdBool as _, SimdValue};
8
9/// Visitor for checking if a composite shape contains a specific point.
10pub struct CompositePointContainmentTest<'a, S: 'a> {
11    /// The composite shape on which the point containment test should be performed.
12    pub shape: &'a S,
13    /// The point to be tested.
14    pub point: &'a Point<Real>,
15    /// A traversal will set this to `true` if the point is inside of `self.shape`.
16    pub found: bool,
17}
18
19impl<'a, S> CompositePointContainmentTest<'a, S> {
20    /// Creates a new visitor for the testing containment of the given `point`
21    /// into the given `shape`.
22    pub fn new(shape: &'a S, point: &'a Point<Real>) -> Self {
23        Self {
24            shape,
25            point,
26            found: false,
27        }
28    }
29}
30
31impl<S: TypedSimdCompositeShape> SimdVisitor<S::PartId, SimdAabb>
32    for CompositePointContainmentTest<'_, S>
33{
34    #[inline]
35    fn visit(
36        &mut self,
37        bv: &SimdAabb,
38        b: Option<[Option<&S::PartId>; SIMD_WIDTH]>,
39    ) -> SimdVisitStatus {
40        let simd_point: Point<SimdReal> = Point::splat(*self.point);
41        let mask = bv.contains_local_point(&simd_point);
42
43        if let Some(data) = b {
44            let bitmask = mask.bitmask();
45
46            for (ii, data) in data.into_iter().enumerate() {
47                if (bitmask & (1 << ii)) != 0 {
48                    let Some(data) = data else { continue };
49                    self.shape.map_typed_part_at(*data, |part_pos, obj, _| {
50                        if obj.contains_local_point(&part_pos.inverse_transform_point(self.point)) {
51                            self.found = true;
52                        }
53                    });
54
55                    if self.found {
56                        return SimdVisitStatus::ExitEarly;
57                    }
58                }
59            }
60        }
61
62        SimdVisitStatus::MaybeContinue(mask)
63    }
64}