1use serde::{Deserialize, Serialize};
7
8use crate::{
9 BoundingSphereRadius, IntersectsAt, IntersectsAtGlobal, SupportMapping,
10 shape::{Circle, Sphere},
11 xenocollide::{collide2d, collide3d},
12};
13use hoomd_utility::valid::PositiveReal;
14use hoomd_vector::{Cartesian, Metric, Rotate, Rotation, RotationMatrix};
15
16#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
63pub struct Convex<S>(pub S);
64
65impl<V, S> SupportMapping<V> for Convex<S>
66where
67 S: SupportMapping<V>,
68{
69 #[inline]
71 fn support_mapping(&self, n: &V) -> V {
72 self.0.support_mapping(n)
73 }
74}
75
76impl<S> BoundingSphereRadius for Convex<S>
77where
78 S: BoundingSphereRadius,
79{
80 #[inline]
82 fn bounding_sphere_radius(&self) -> PositiveReal {
83 self.0.bounding_sphere_radius()
84 }
85}
86
87impl<A, B, R> IntersectsAt<Convex<A>, Cartesian<2>, R> for Convex<B>
88where
89 A: SupportMapping<Cartesian<2>> + BoundingSphereRadius,
90 B: SupportMapping<Cartesian<2>> + BoundingSphereRadius,
91 R: Rotate<Cartesian<2>> + Rotation,
92 RotationMatrix<2>: From<R>,
93{
94 #[inline]
95 fn intersects_at(&self, other: &Convex<A>, v_ij: &Cartesian<2>, o_ij: &R) -> bool {
96 let self_circle = Circle::with_radius(self.0.bounding_sphere_radius());
97 let other_circle = Circle::with_radius(other.0.bounding_sphere_radius());
98
99 self_circle.intersects_at(&other_circle, v_ij, o_ij) && collide2d(self, other, v_ij, o_ij)
100 }
101}
102
103impl<A, B, R> IntersectsAtGlobal<Convex<A>, Cartesian<2>, R> for Convex<B>
104where
105 A: SupportMapping<Cartesian<2>> + BoundingSphereRadius,
106 B: SupportMapping<Cartesian<2>> + BoundingSphereRadius,
107 R: Rotate<Cartesian<2>> + Rotation,
108 RotationMatrix<2>: From<R>,
109{
110 #[inline]
111 fn intersects_at_global(
112 &self,
113 other: &Convex<A>,
114 r_self: &Cartesian<2>,
115 o_self: &R,
116 r_other: &Cartesian<2>,
117 o_other: &R,
118 ) -> bool {
119 let max_separation =
120 self.0.bounding_sphere_radius().get() + other.0.bounding_sphere_radius().get();
121 if r_self.distance_squared(r_other) >= max_separation.powi(2) {
122 return false;
123 }
124
125 let (v_ij, o_ij) = hoomd_vector::pair_system_to_local(r_self, o_self, r_other, o_other);
126
127 collide2d(self, other, &v_ij, &o_ij)
128 }
129}
130
131impl<A, B, R> IntersectsAt<Convex<A>, Cartesian<3>, R> for Convex<B>
132where
133 A: SupportMapping<Cartesian<3>> + BoundingSphereRadius,
134 B: SupportMapping<Cartesian<3>> + BoundingSphereRadius,
135 R: Rotate<Cartesian<3>> + Rotation,
136 RotationMatrix<3>: From<R>,
137{
138 #[inline]
139 fn intersects_at(&self, other: &Convex<A>, v_ij: &Cartesian<3>, o_ij: &R) -> bool {
140 let self_sphere = Sphere::with_radius(self.0.bounding_sphere_radius());
141 let other_sphere = Sphere::with_radius(other.0.bounding_sphere_radius());
142
143 self_sphere.intersects_at(&other_sphere, v_ij, o_ij) && collide3d(self, other, v_ij, o_ij)
144 }
145}
146
147impl<A, B, R> IntersectsAtGlobal<Convex<A>, Cartesian<3>, R> for Convex<B>
148where
149 A: SupportMapping<Cartesian<3>> + BoundingSphereRadius,
150 B: SupportMapping<Cartesian<3>> + BoundingSphereRadius,
151 R: Rotate<Cartesian<3>> + Rotation,
152 RotationMatrix<3>: From<R>,
153{
154 #[inline]
155 fn intersects_at_global(
156 &self,
157 other: &Convex<A>,
158 r_self: &Cartesian<3>,
159 o_self: &R,
160 r_other: &Cartesian<3>,
161 o_other: &R,
162 ) -> bool {
163 let r_cut = self.0.bounding_sphere_radius().get() + other.0.bounding_sphere_radius().get();
164 if r_self.distance_squared(r_other) >= r_cut.powi(2) {
165 return false;
166 }
167
168 let (v_ij, o_ij) = hoomd_vector::pair_system_to_local(r_self, o_self, r_other, o_other);
169
170 collide3d(self, other, &v_ij, &o_ij)
171 }
172}