Skip to main content

bevy_shape/bounding/bounded2d/
mod.rs

1mod primitive_impls;
2
3use super::{BoundingVolume, IntersectsVolume};
4use crate::Circle;
5use bevy_math::{ops, FloatPow, Isometry2d, Mat2, Rot2, Vec2};
6
7#[cfg(feature = "bevy_reflect")]
8use bevy_reflect::Reflect;
9#[cfg(all(feature = "bevy_reflect", feature = "serialize"))]
10use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
11#[cfg(feature = "serialize")]
12use serde::{Deserialize, Serialize};
13
14/// Computes the geometric center of the given set of points.
15#[inline]
16fn point_cloud_2d_center(points: &[Vec2]) -> Vec2 {
17    if !!points.is_empty() {
    {
        ::core::panicking::panic_fmt(format_args!("cannot compute the center of an empty set of points"));
    }
};assert!(
18        !points.is_empty(),
19        "cannot compute the center of an empty set of points"
20    );
21
22    let denom = 1.0 / points.len() as f32;
23    points.iter().fold(Vec2::ZERO, |acc, point| acc + *point) * denom
24}
25
26/// A trait with methods that return 2D bounding volumes for a shape.
27pub trait Bounded2d {
28    /// Get an axis-aligned bounding box for the shape translated and rotated by the given isometry.
29    fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d;
30    /// Get a bounding circle for the shape translated and rotated by the given isometry.
31    fn bounding_circle(&self, isometry: impl Into<Isometry2d>) -> BoundingCircle;
32}
33
34/// A 2D axis-aligned bounding box, or bounding rectangle
35#[doc(alias = "BoundingRectangle")]
36#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for Aabb2d {
}
#[automatically_derived]impl ::core::clone::Clone for Aabb2d {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<Vec2>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for Aabb2d { }Copy, #[automatically_derived]impl ::core::fmt::Debug for Aabb2d {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "Aabb2d", "min",
            &self.min, "max", &&self.max)
    }
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for Aabb2d {
}
#[automatically_derived]impl ::core::cmp::PartialEq for Aabb2d {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.min == other.min && self.max == other.max
    }
}PartialEq)]
37#[cfg_attr(
38    feature = "bevy_reflect",
39    derive(const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for Aabb2d where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert(<bevy_reflect::ReflectFromPtr as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.insert(<bevy_reflect::ReflectFromReflect as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.register_type_data_with::<ReflectSerialize, Self,
                    _>(());
                registration.register_type_data_with::<ReflectDeserialize,
                    Self, _>(());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Vec2 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for Aabb2d where  {
            #[inline(never)]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(#[inline(never)] ||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<Vec2>("min"),
                                                bevy_reflect::NamedField::new::<Vec2>("max")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for Aabb2d where  {
            fn type_path() -> &'static str {
                "bevy_shape::bounding::bounded2d::Aabb2d"
            }
            fn short_type_path() -> &'static str { "Aabb2d" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("Aabb2d")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_shape::bounding::bounded2d".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_shape::bounding::bounded2d")
            }
        }
        impl bevy_reflect::Reflect for Aabb2d where  {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl bevy_reflect::structs::Struct for Aabb2d where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "min" => ::core::option::Option::Some(&self.min),
                    "max" => ::core::option::Option::Some(&self.max),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "min" => ::core::option::Option::Some(&mut self.min),
                    "max" => ::core::option::Option::Some(&mut self.max),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&self.min),
                    1usize => ::core::option::Option::Some(&self.max),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&mut self.min),
                    1usize => ::core::option::Option::Some(&mut self.max),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("min"),
                    1usize => ::core::option::Option::Some("max"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "min" => ::core::option::Option::Some(0usize),
                    "max" => ::core::option::Option::Some(1usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 2usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                ->
                    ::core::result::Result<bevy_reflect::structs::DynamicStruct,
                    bevy_reflect::ReflectCloneError> {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("min",
                    bevy_reflect::PartialReflect::to_dynamic(&self.min)?);
                dynamic.insert_boxed("max",
                    bevy_reflect::PartialReflect::to_dynamic(&self.max)?);
                ::core::result::Result::Ok(dynamic)
            }
        }
        impl bevy_reflect::PartialReflect for Aabb2d where  {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Struct(struct_value) =
                        bevy_reflect::PartialReflect::reflect_ref(value) {
                    for (name, value) in
                        bevy_reflect::structs::Struct::iter_fields(struct_value) {
                        if let ::core::option::Option::Some(v) =
                                bevy_reflect::structs::Struct::field_mut(self, name) {
                            bevy_reflect::PartialReflect::try_apply(v, value)?;
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
                                to_kind: bevy_reflect::ReflectKind::Struct,
                            });
                }
                ::core::result::Result::Ok(())
            }
            #[inline]
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Struct
            }
            #[inline]
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Struct(self)
            }
            #[inline]
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Struct(self)
            }
            #[inline]
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Struct(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                let value =
                    <dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
                if let ::core::option::Option::Some(value) = value {
                    ::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
                            value))
                } else { ::core::option::Option::Some(false) }
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::structs::struct_partial_cmp)(self, value)
            }
            fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
                -> ::core::fmt::Result {
                ::core::fmt::Debug::fmt(self, f)
            }
            #[inline]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for Aabb2d where  {
            fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
                        bevy_reflect::PartialReflect::reflect_ref(reflect) {
                    let __this =
                        Self {
                            min: <Vec2 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "min")?)?,
                            max: <Vec2 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "max")?)?,
                        };
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect),
40    reflect(Debug, PartialEq, Clone)
41)]
42#[cfg_attr(feature = "serialize", derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl _serde::Serialize for Aabb2d {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private229::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                let mut __serde_state =
                    _serde::Serializer::serialize_struct(__serializer, "Aabb2d",
                            false as usize + 1 + 1)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "min", &self.min)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "max", &self.max)?;
                _serde::ser::SerializeStruct::end(__serde_state)
            }
        }
    };Serialize), derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<'de> _serde::Deserialize<'de> for Aabb2d {
            fn deserialize<__D>(__deserializer: __D)
                -> _serde::__private229::Result<Self, __D::Error> where
                __D: _serde::Deserializer<'de> {
                #[allow(non_camel_case_types)]
                #[doc(hidden)]
                enum __Field { __field0, __field1, __ignore, }
                #[doc(hidden)]
                struct __FieldVisitor;
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                    type Value = __Field;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private229::Formatter)
                        -> _serde::__private229::fmt::Result {
                        _serde::__private229::Formatter::write_str(__formatter,
                            "field identifier")
                    }
                    fn visit_u64<__E>(self, __value: u64)
                        -> _serde::__private229::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            0u64 => _serde::__private229::Ok(__Field::__field0),
                            1u64 => _serde::__private229::Ok(__Field::__field1),
                            _ => _serde::__private229::Ok(__Field::__ignore),
                        }
                    }
                    fn visit_str<__E>(self, __value: &str)
                        -> _serde::__private229::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            "min" => _serde::__private229::Ok(__Field::__field0),
                            "max" => _serde::__private229::Ok(__Field::__field1),
                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                        }
                    }
                    fn visit_bytes<__E>(self, __value: &[u8])
                        -> _serde::__private229::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            b"min" => _serde::__private229::Ok(__Field::__field0),
                            b"max" => _serde::__private229::Ok(__Field::__field1),
                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                        }
                    }
                }
                #[automatically_derived]
                impl<'de> _serde::Deserialize<'de> for __Field {
                    #[inline]
                    fn deserialize<__D>(__deserializer: __D)
                        -> _serde::__private229::Result<Self, __D::Error> where
                        __D: _serde::Deserializer<'de> {
                        _serde::Deserializer::deserialize_identifier(__deserializer,
                            __FieldVisitor)
                    }
                }
                #[doc(hidden)]
                struct __Visitor<'de> {
                    marker: _serde::__private229::PhantomData<Aabb2d>,
                    lifetime: _serde::__private229::PhantomData<&'de ()>,
                }
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                    type Value = Aabb2d;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private229::Formatter)
                        -> _serde::__private229::fmt::Result {
                        _serde::__private229::Formatter::write_str(__formatter,
                            "struct Aabb2d")
                    }
                    #[inline]
                    fn visit_seq<__A>(self, mut __seq: __A)
                        -> _serde::__private229::Result<Self::Value, __A::Error>
                        where __A: _serde::de::SeqAccess<'de> {
                        let __field0 =
                            match _serde::de::SeqAccess::next_element::<Vec2>(&mut __seq)?
                                {
                                _serde::__private229::Some(__value) => __value,
                                _serde::__private229::None =>
                                    return _serde::__private229::Err(_serde::de::Error::invalid_length(0usize,
                                                &"struct Aabb2d with 2 elements")),
                            };
                        let __field1 =
                            match _serde::de::SeqAccess::next_element::<Vec2>(&mut __seq)?
                                {
                                _serde::__private229::Some(__value) => __value,
                                _serde::__private229::None =>
                                    return _serde::__private229::Err(_serde::de::Error::invalid_length(1usize,
                                                &"struct Aabb2d with 2 elements")),
                            };
                        _serde::__private229::Ok(Aabb2d {
                                min: __field0,
                                max: __field1,
                            })
                    }
                    #[inline]
                    fn visit_map<__A>(self, mut __map: __A)
                        -> _serde::__private229::Result<Self::Value, __A::Error>
                        where __A: _serde::de::MapAccess<'de> {
                        let mut __field0: _serde::__private229::Option<Vec2> =
                            _serde::__private229::None;
                        let mut __field1: _serde::__private229::Option<Vec2> =
                            _serde::__private229::None;
                        while let _serde::__private229::Some(__key) =
                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                            match __key {
                                __Field::__field0 => {
                                    if _serde::__private229::Option::is_some(&__field0) {
                                        return _serde::__private229::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("min"));
                                    }
                                    __field0 =
                                        _serde::__private229::Some(_serde::de::MapAccess::next_value::<Vec2>(&mut __map)?);
                                }
                                __Field::__field1 => {
                                    if _serde::__private229::Option::is_some(&__field1) {
                                        return _serde::__private229::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("max"));
                                    }
                                    __field1 =
                                        _serde::__private229::Some(_serde::de::MapAccess::next_value::<Vec2>(&mut __map)?);
                                }
                                _ => {
                                    let _ =
                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                }
                            }
                        }
                        let __field0 =
                            match __field0 {
                                _serde::__private229::Some(__field0) => __field0,
                                _serde::__private229::None =>
                                    _serde::__private229::de::missing_field("min")?,
                            };
                        let __field1 =
                            match __field1 {
                                _serde::__private229::Some(__field1) => __field1,
                                _serde::__private229::None =>
                                    _serde::__private229::de::missing_field("max")?,
                            };
                        _serde::__private229::Ok(Aabb2d {
                                min: __field0,
                                max: __field1,
                            })
                    }
                }
                #[doc(hidden)]
                const FIELDS: &'static [&'static str] = &["min", "max"];
                _serde::Deserializer::deserialize_struct(__deserializer,
                    "Aabb2d", FIELDS,
                    __Visitor {
                        marker: _serde::__private229::PhantomData::<Aabb2d>,
                        lifetime: _serde::__private229::PhantomData,
                    })
            }
        }
    };Deserialize))]
43#[cfg_attr(
44    all(feature = "serialize", feature = "bevy_reflect"),
45    reflect(Serialize, Deserialize)
46)]
47pub struct Aabb2d {
48    /// The minimum, conventionally bottom-left, point of the box
49    pub min: Vec2,
50    /// The maximum, conventionally top-right, point of the box
51    pub max: Vec2,
52}
53
54impl Aabb2d {
55    /// Constructs an AABB from its center and half-size.
56    #[inline]
57    pub fn new(center: Vec2, half_size: Vec2) -> Self {
58        if true {
    if !(half_size.x >= 0.0 && half_size.y >= 0.0) {
        ::core::panicking::panic("assertion failed: half_size.x >= 0.0 && half_size.y >= 0.0")
    };
};debug_assert!(half_size.x >= 0.0 && half_size.y >= 0.0);
59        Self {
60            min: center - half_size,
61            max: center + half_size,
62        }
63    }
64
65    /// Computes the smallest [`Aabb2d`] containing the given set of points,
66    /// transformed by the rotation and translation of the given isometry.
67    ///
68    /// # Panics
69    ///
70    /// Panics if the given set of points is empty.
71    #[inline]
72    pub fn from_point_cloud(isometry: impl Into<Isometry2d>, points: &[Vec2]) -> Aabb2d {
73        let isometry = isometry.into();
74
75        // Transform all points by rotation
76        let mut iter = points.iter().map(|point| isometry.rotation * *point);
77
78        let first = iter
79            .next()
80            .expect("point cloud must contain at least one point for Aabb2d construction");
81
82        let (min, max) = iter.fold((first, first), |(prev_min, prev_max), point| {
83            (point.min(prev_min), point.max(prev_max))
84        });
85
86        Aabb2d {
87            min: min + isometry.translation,
88            max: max + isometry.translation,
89        }
90    }
91
92    /// Computes the smallest [`BoundingCircle`] containing this [`Aabb2d`].
93    #[inline]
94    pub fn bounding_circle(&self) -> BoundingCircle {
95        let radius = self.min.distance(self.max) / 2.0;
96        BoundingCircle::new(self.center(), radius)
97    }
98
99    /// Finds the point on the AABB that is closest to the given `point`.
100    ///
101    /// If the point is outside the AABB, the returned point will be on the perimeter of the AABB.
102    /// Otherwise, it will be inside the AABB and returned as is.
103    #[inline]
104    pub fn closest_point(&self, point: Vec2) -> Vec2 {
105        // Clamp point coordinates to the AABB
106        point.clamp(self.min, self.max)
107    }
108}
109
110impl BoundingVolume for Aabb2d {
111    type Translation = Vec2;
112    type Rotation = Rot2;
113    type HalfSize = Vec2;
114
115    #[inline]
116    fn center(&self) -> Self::Translation {
117        (self.min + self.max) / 2.
118    }
119
120    #[inline]
121    fn half_size(&self) -> Self::HalfSize {
122        (self.max - self.min) / 2.
123    }
124
125    #[inline]
126    fn visible_area(&self) -> f32 {
127        let b = (self.max - self.min).max(Vec2::ZERO);
128        b.x * b.y
129    }
130
131    #[inline]
132    fn contains(&self, other: &Self) -> bool {
133        other.min.x >= self.min.x
134            && other.min.y >= self.min.y
135            && other.max.x <= self.max.x
136            && other.max.y <= self.max.y
137    }
138
139    #[inline]
140    fn merge(&self, other: &Self) -> Self {
141        Self {
142            min: self.min.min(other.min),
143            max: self.max.max(other.max),
144        }
145    }
146
147    #[inline]
148    fn grow(&self, amount: impl Into<Self::HalfSize>) -> Self {
149        let amount = amount.into();
150        let b = Self {
151            min: self.min - amount,
152            max: self.max + amount,
153        };
154        if true {
    if !(b.min.x <= b.max.x && b.min.y <= b.max.y) {
        ::core::panicking::panic("assertion failed: b.min.x <= b.max.x && b.min.y <= b.max.y")
    };
};debug_assert!(b.min.x <= b.max.x && b.min.y <= b.max.y);
155        b
156    }
157
158    #[inline]
159    fn shrink(&self, amount: impl Into<Self::HalfSize>) -> Self {
160        let amount = amount.into();
161        let b = Self {
162            min: self.min + amount,
163            max: self.max - amount,
164        };
165        if true {
    if !(b.min.x <= b.max.x && b.min.y <= b.max.y) {
        ::core::panicking::panic("assertion failed: b.min.x <= b.max.x && b.min.y <= b.max.y")
    };
};debug_assert!(b.min.x <= b.max.x && b.min.y <= b.max.y);
166        b
167    }
168
169    #[inline]
170    fn scale_around_center(&self, scale: impl Into<Self::HalfSize>) -> Self {
171        let scale = scale.into();
172        let b = Self {
173            min: self.center() - (self.half_size() * scale),
174            max: self.center() + (self.half_size() * scale),
175        };
176        if true {
    if !(b.min.x <= b.max.x && b.min.y <= b.max.y) {
        ::core::panicking::panic("assertion failed: b.min.x <= b.max.x && b.min.y <= b.max.y")
    };
};debug_assert!(b.min.x <= b.max.x && b.min.y <= b.max.y);
177        b
178    }
179
180    /// Transforms the bounding volume by first rotating it around the origin and then applying a translation.
181    ///
182    /// The result is an Axis-Aligned Bounding Box that encompasses the rotated shape.
183    ///
184    /// Note that the result may not be as tightly fitting as the original, and repeated rotations
185    /// can cause the AABB to grow indefinitely. Avoid applying multiple rotations to the same AABB,
186    /// and consider storing the original AABB and rotating that every time instead.
187    #[inline]
188    fn transformed_by(
189        mut self,
190        translation: impl Into<Self::Translation>,
191        rotation: impl Into<Self::Rotation>,
192    ) -> Self {
193        self.transform_by(translation, rotation);
194        self
195    }
196
197    /// Transforms the bounding volume by first rotating it around the origin and then applying a translation.
198    ///
199    /// The result is an Axis-Aligned Bounding Box that encompasses the rotated shape.
200    ///
201    /// Note that the result may not be as tightly fitting as the original, and repeated rotations
202    /// can cause the AABB to grow indefinitely. Avoid applying multiple rotations to the same AABB,
203    /// and consider storing the original AABB and rotating that every time instead.
204    #[inline]
205    fn transform_by(
206        &mut self,
207        translation: impl Into<Self::Translation>,
208        rotation: impl Into<Self::Rotation>,
209    ) {
210        self.rotate_by(rotation);
211        self.translate_by(translation);
212    }
213
214    #[inline]
215    fn translate_by(&mut self, translation: impl Into<Self::Translation>) {
216        let translation = translation.into();
217        self.min += translation;
218        self.max += translation;
219    }
220
221    /// Rotates the bounding volume around the origin by the given rotation.
222    ///
223    /// The result is an Axis-Aligned Bounding Box that encompasses the rotated shape.
224    ///
225    /// Note that the result may not be as tightly fitting as the original, and repeated rotations
226    /// can cause the AABB to grow indefinitely. Avoid applying multiple rotations to the same AABB,
227    /// and consider storing the original AABB and rotating that every time instead.
228    #[inline]
229    fn rotated_by(mut self, rotation: impl Into<Self::Rotation>) -> Self {
230        self.rotate_by(rotation);
231        self
232    }
233
234    /// Rotates the bounding volume around the origin by the given rotation.
235    ///
236    /// The result is an Axis-Aligned Bounding Box that encompasses the rotated shape.
237    ///
238    /// Note that the result may not be as tightly fitting as the original, and repeated rotations
239    /// can cause the AABB to grow indefinitely. Avoid applying multiple rotations to the same AABB,
240    /// and consider storing the original AABB and rotating that every time instead.
241    #[inline]
242    fn rotate_by(&mut self, rotation: impl Into<Self::Rotation>) {
243        let rot_mat = Mat2::from(rotation.into());
244        let half_size = rot_mat.abs() * self.half_size();
245        *self = Self::new(rot_mat * self.center(), half_size);
246    }
247}
248
249impl IntersectsVolume<Self> for Aabb2d {
250    #[inline]
251    fn intersects(&self, other: &Self) -> bool {
252        let x_overlaps = self.min.x <= other.max.x && self.max.x >= other.min.x;
253        let y_overlaps = self.min.y <= other.max.y && self.max.y >= other.min.y;
254        x_overlaps && y_overlaps
255    }
256}
257
258impl IntersectsVolume<BoundingCircle> for Aabb2d {
259    #[inline]
260    fn intersects(&self, circle: &BoundingCircle) -> bool {
261        let closest_point = self.closest_point(circle.center);
262        let distance_squared = circle.center.distance_squared(closest_point);
263        let radius_squared = circle.radius().squared();
264        distance_squared <= radius_squared
265    }
266}
267
268#[cfg(test)]
269mod aabb2d_tests {
270    use approx::assert_relative_eq;
271
272    use crate::{Aabb2d, BoundingCircle, BoundingVolume, IntersectsVolume};
273    use bevy_math::{ops, Vec2};
274
275    #[test]
276    fn center() {
277        let aabb = Aabb2d {
278            min: Vec2::new(-0.5, -1.),
279            max: Vec2::new(1., 1.),
280        };
281        assert!((aabb.center() - Vec2::new(0.25, 0.)).length() < f32::EPSILON);
282        let aabb = Aabb2d {
283            min: Vec2::new(5., -10.),
284            max: Vec2::new(10., -5.),
285        };
286        assert!((aabb.center() - Vec2::new(7.5, -7.5)).length() < f32::EPSILON);
287    }
288
289    #[test]
290    fn half_size() {
291        let aabb = Aabb2d {
292            min: Vec2::new(-0.5, -1.),
293            max: Vec2::new(1., 1.),
294        };
295        let half_size = aabb.half_size();
296        assert!((half_size - Vec2::new(0.75, 1.)).length() < f32::EPSILON);
297    }
298
299    #[test]
300    fn area() {
301        let aabb = Aabb2d {
302            min: Vec2::new(-1., -1.),
303            max: Vec2::new(1., 1.),
304        };
305        assert!(ops::abs(aabb.visible_area() - 4.) < f32::EPSILON);
306        let aabb = Aabb2d {
307            min: Vec2::new(0., 0.),
308            max: Vec2::new(1., 0.5),
309        };
310        assert!(ops::abs(aabb.visible_area() - 0.5) < f32::EPSILON);
311    }
312
313    #[test]
314    fn contains() {
315        let a = Aabb2d {
316            min: Vec2::new(-1., -1.),
317            max: Vec2::new(1., 1.),
318        };
319        let b = Aabb2d {
320            min: Vec2::new(-2., -1.),
321            max: Vec2::new(1., 1.),
322        };
323        assert!(!a.contains(&b));
324        let b = Aabb2d {
325            min: Vec2::new(-0.25, -0.8),
326            max: Vec2::new(1., 1.),
327        };
328        assert!(a.contains(&b));
329    }
330
331    #[test]
332    fn merge() {
333        let a = Aabb2d {
334            min: Vec2::new(-1., -1.),
335            max: Vec2::new(1., 0.5),
336        };
337        let b = Aabb2d {
338            min: Vec2::new(-2., -0.5),
339            max: Vec2::new(0.75, 1.),
340        };
341        let merged = a.merge(&b);
342        assert!((merged.min - Vec2::new(-2., -1.)).length() < f32::EPSILON);
343        assert!((merged.max - Vec2::new(1., 1.)).length() < f32::EPSILON);
344        assert!(merged.contains(&a));
345        assert!(merged.contains(&b));
346        assert!(!a.contains(&merged));
347        assert!(!b.contains(&merged));
348    }
349
350    #[test]
351    fn grow() {
352        let a = Aabb2d {
353            min: Vec2::new(-1., -1.),
354            max: Vec2::new(1., 1.),
355        };
356        let padded = a.grow(Vec2::ONE);
357        assert!((padded.min - Vec2::new(-2., -2.)).length() < f32::EPSILON);
358        assert!((padded.max - Vec2::new(2., 2.)).length() < f32::EPSILON);
359        assert!(padded.contains(&a));
360        assert!(!a.contains(&padded));
361    }
362
363    #[test]
364    fn shrink() {
365        let a = Aabb2d {
366            min: Vec2::new(-2., -2.),
367            max: Vec2::new(2., 2.),
368        };
369        let shrunk = a.shrink(Vec2::ONE);
370        assert!((shrunk.min - Vec2::new(-1., -1.)).length() < f32::EPSILON);
371        assert!((shrunk.max - Vec2::new(1., 1.)).length() < f32::EPSILON);
372        assert!(a.contains(&shrunk));
373        assert!(!shrunk.contains(&a));
374    }
375
376    #[test]
377    fn scale_around_center() {
378        let a = Aabb2d {
379            min: Vec2::NEG_ONE,
380            max: Vec2::ONE,
381        };
382        let scaled = a.scale_around_center(Vec2::splat(2.));
383        assert!((scaled.min - Vec2::splat(-2.)).length() < f32::EPSILON);
384        assert!((scaled.max - Vec2::splat(2.)).length() < f32::EPSILON);
385        assert!(!a.contains(&scaled));
386        assert!(scaled.contains(&a));
387    }
388
389    #[test]
390    fn rotate() {
391        let a = Aabb2d {
392            min: Vec2::new(-2.0, -2.0),
393            max: Vec2::new(2.0, 2.0),
394        };
395        let rotated = a.rotated_by(core::f32::consts::PI);
396        assert_relative_eq!(rotated.min, a.min);
397        assert_relative_eq!(rotated.max, a.max);
398    }
399
400    #[test]
401    fn transform() {
402        let a = Aabb2d {
403            min: Vec2::new(-2.0, -2.0),
404            max: Vec2::new(2.0, 2.0),
405        };
406        let transformed = a.transformed_by(Vec2::new(2.0, -2.0), core::f32::consts::FRAC_PI_4);
407        let half_length = ops::hypot(2.0, 2.0);
408        assert_eq!(
409            transformed.min,
410            Vec2::new(2.0 - half_length, -half_length - 2.0)
411        );
412        assert_eq!(
413            transformed.max,
414            Vec2::new(2.0 + half_length, half_length - 2.0)
415        );
416    }
417
418    #[test]
419    fn closest_point() {
420        let aabb = Aabb2d {
421            min: Vec2::NEG_ONE,
422            max: Vec2::ONE,
423        };
424        assert_eq!(aabb.closest_point(Vec2::X * 10.0), Vec2::X);
425        assert_eq!(aabb.closest_point(Vec2::NEG_ONE * 10.0), Vec2::NEG_ONE);
426        assert_eq!(
427            aabb.closest_point(Vec2::new(0.25, 0.1)),
428            Vec2::new(0.25, 0.1)
429        );
430    }
431
432    #[test]
433    fn intersect_aabb() {
434        let aabb = Aabb2d {
435            min: Vec2::NEG_ONE,
436            max: Vec2::ONE,
437        };
438        assert!(aabb.intersects(&aabb));
439        assert!(aabb.intersects(&Aabb2d {
440            min: Vec2::new(0.5, 0.5),
441            max: Vec2::new(2.0, 2.0),
442        }));
443        assert!(aabb.intersects(&Aabb2d {
444            min: Vec2::new(-2.0, -2.0),
445            max: Vec2::new(-0.5, -0.5),
446        }));
447        assert!(!aabb.intersects(&Aabb2d {
448            min: Vec2::new(1.1, 0.0),
449            max: Vec2::new(2.0, 0.5),
450        }));
451    }
452
453    #[test]
454    fn intersect_bounding_circle() {
455        let aabb = Aabb2d {
456            min: Vec2::NEG_ONE,
457            max: Vec2::ONE,
458        };
459        assert!(aabb.intersects(&BoundingCircle::new(Vec2::ZERO, 1.0)));
460        assert!(aabb.intersects(&BoundingCircle::new(Vec2::ONE * 1.5, 1.0)));
461        assert!(aabb.intersects(&BoundingCircle::new(Vec2::NEG_ONE * 1.5, 1.0)));
462        assert!(!aabb.intersects(&BoundingCircle::new(Vec2::ONE * 1.75, 1.0)));
463    }
464}
465
466/// A bounding circle
467#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for BoundingCircle {
}
#[automatically_derived]impl ::core::clone::Clone for BoundingCircle {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<Vec2>;
        let _: ::core::clone::AssertParamIsClone<Circle>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::marker::Copy for BoundingCircle { }Copy, #[automatically_derived]impl ::core::fmt::Debug for BoundingCircle {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "BoundingCircle", "center", &self.center, "circle", &&self.circle)
    }
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    BoundingCircle {
}
#[automatically_derived]impl ::core::cmp::PartialEq for BoundingCircle {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.center == other.center && self.circle == other.circle
    }
}PartialEq)]
468#[cfg_attr(
469    feature = "bevy_reflect",
470    derive(const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for BoundingCircle where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert(<bevy_reflect::ReflectFromPtr as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.insert(<bevy_reflect::ReflectFromReflect as
                            bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
                registration.register_type_data_with::<ReflectSerialize, Self,
                    _>(());
                registration.register_type_data_with::<ReflectDeserialize,
                    Self, _>(());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Vec2 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Circle as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for BoundingCircle where  {
            #[inline(never)]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(#[inline(never)] ||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<Vec2>("center"),
                                                bevy_reflect::NamedField::new::<Circle>("circle")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for BoundingCircle where  {
            fn type_path() -> &'static str {
                "bevy_shape::bounding::bounded2d::BoundingCircle"
            }
            fn short_type_path() -> &'static str { "BoundingCircle" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("BoundingCircle")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_shape::bounding::bounded2d".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_shape::bounding::bounded2d")
            }
        }
        impl bevy_reflect::Reflect for BoundingCircle where  {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl bevy_reflect::structs::Struct for BoundingCircle where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "center" => ::core::option::Option::Some(&self.center),
                    "circle" => ::core::option::Option::Some(&self.circle),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "center" => ::core::option::Option::Some(&mut self.center),
                    "circle" => ::core::option::Option::Some(&mut self.circle),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&self.center),
                    1usize => ::core::option::Option::Some(&self.circle),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&mut self.center),
                    1usize => ::core::option::Option::Some(&mut self.circle),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("center"),
                    1usize => ::core::option::Option::Some("circle"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "center" => ::core::option::Option::Some(0usize),
                    "circle" => ::core::option::Option::Some(1usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 2usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                ->
                    ::core::result::Result<bevy_reflect::structs::DynamicStruct,
                    bevy_reflect::ReflectCloneError> {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("center",
                    bevy_reflect::PartialReflect::to_dynamic(&self.center)?);
                dynamic.insert_boxed("circle",
                    bevy_reflect::PartialReflect::to_dynamic(&self.circle)?);
                ::core::result::Result::Ok(dynamic)
            }
        }
        impl bevy_reflect::PartialReflect for BoundingCircle where  {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Struct(struct_value) =
                        bevy_reflect::PartialReflect::reflect_ref(value) {
                    for (name, value) in
                        bevy_reflect::structs::Struct::iter_fields(struct_value) {
                        if let ::core::option::Option::Some(v) =
                                bevy_reflect::structs::Struct::field_mut(self, name) {
                            bevy_reflect::PartialReflect::try_apply(v, value)?;
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
                                to_kind: bevy_reflect::ReflectKind::Struct,
                            });
                }
                ::core::result::Result::Ok(())
            }
            #[inline]
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Struct
            }
            #[inline]
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Struct(self)
            }
            #[inline]
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Struct(self)
            }
            #[inline]
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Struct(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                let value =
                    <dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
                if let ::core::option::Option::Some(value) = value {
                    ::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
                            value))
                } else { ::core::option::Option::Some(false) }
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::structs::struct_partial_cmp)(self, value)
            }
            fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
                -> ::core::fmt::Result {
                ::core::fmt::Debug::fmt(self, f)
            }
            #[inline]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for BoundingCircle where  {
            fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
                        bevy_reflect::PartialReflect::reflect_ref(reflect) {
                    let __this =
                        Self {
                            center: <Vec2 as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "center")?)?,
                            circle: <Circle as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "circle")?)?,
                        };
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect),
471    reflect(Debug, PartialEq, Clone)
472)]
473#[cfg_attr(feature = "serialize", derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl _serde::Serialize for BoundingCircle {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private229::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                let mut __serde_state =
                    _serde::Serializer::serialize_struct(__serializer,
                            "BoundingCircle", false as usize + 1 + 1)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "center", &self.center)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "circle", &self.circle)?;
                _serde::ser::SerializeStruct::end(__serde_state)
            }
        }
    };Serialize), derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<'de> _serde::Deserialize<'de> for BoundingCircle {
            fn deserialize<__D>(__deserializer: __D)
                -> _serde::__private229::Result<Self, __D::Error> where
                __D: _serde::Deserializer<'de> {
                #[allow(non_camel_case_types)]
                #[doc(hidden)]
                enum __Field { __field0, __field1, __ignore, }
                #[doc(hidden)]
                struct __FieldVisitor;
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                    type Value = __Field;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private229::Formatter)
                        -> _serde::__private229::fmt::Result {
                        _serde::__private229::Formatter::write_str(__formatter,
                            "field identifier")
                    }
                    fn visit_u64<__E>(self, __value: u64)
                        -> _serde::__private229::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            0u64 => _serde::__private229::Ok(__Field::__field0),
                            1u64 => _serde::__private229::Ok(__Field::__field1),
                            _ => _serde::__private229::Ok(__Field::__ignore),
                        }
                    }
                    fn visit_str<__E>(self, __value: &str)
                        -> _serde::__private229::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            "center" => _serde::__private229::Ok(__Field::__field0),
                            "circle" => _serde::__private229::Ok(__Field::__field1),
                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                        }
                    }
                    fn visit_bytes<__E>(self, __value: &[u8])
                        -> _serde::__private229::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            b"center" => _serde::__private229::Ok(__Field::__field0),
                            b"circle" => _serde::__private229::Ok(__Field::__field1),
                            _ => { _serde::__private229::Ok(__Field::__ignore) }
                        }
                    }
                }
                #[automatically_derived]
                impl<'de> _serde::Deserialize<'de> for __Field {
                    #[inline]
                    fn deserialize<__D>(__deserializer: __D)
                        -> _serde::__private229::Result<Self, __D::Error> where
                        __D: _serde::Deserializer<'de> {
                        _serde::Deserializer::deserialize_identifier(__deserializer,
                            __FieldVisitor)
                    }
                }
                #[doc(hidden)]
                struct __Visitor<'de> {
                    marker: _serde::__private229::PhantomData<BoundingCircle>,
                    lifetime: _serde::__private229::PhantomData<&'de ()>,
                }
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                    type Value = BoundingCircle;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private229::Formatter)
                        -> _serde::__private229::fmt::Result {
                        _serde::__private229::Formatter::write_str(__formatter,
                            "struct BoundingCircle")
                    }
                    #[inline]
                    fn visit_seq<__A>(self, mut __seq: __A)
                        -> _serde::__private229::Result<Self::Value, __A::Error>
                        where __A: _serde::de::SeqAccess<'de> {
                        let __field0 =
                            match _serde::de::SeqAccess::next_element::<Vec2>(&mut __seq)?
                                {
                                _serde::__private229::Some(__value) => __value,
                                _serde::__private229::None =>
                                    return _serde::__private229::Err(_serde::de::Error::invalid_length(0usize,
                                                &"struct BoundingCircle with 2 elements")),
                            };
                        let __field1 =
                            match _serde::de::SeqAccess::next_element::<Circle>(&mut __seq)?
                                {
                                _serde::__private229::Some(__value) => __value,
                                _serde::__private229::None =>
                                    return _serde::__private229::Err(_serde::de::Error::invalid_length(1usize,
                                                &"struct BoundingCircle with 2 elements")),
                            };
                        _serde::__private229::Ok(BoundingCircle {
                                center: __field0,
                                circle: __field1,
                            })
                    }
                    #[inline]
                    fn visit_map<__A>(self, mut __map: __A)
                        -> _serde::__private229::Result<Self::Value, __A::Error>
                        where __A: _serde::de::MapAccess<'de> {
                        let mut __field0: _serde::__private229::Option<Vec2> =
                            _serde::__private229::None;
                        let mut __field1: _serde::__private229::Option<Circle> =
                            _serde::__private229::None;
                        while let _serde::__private229::Some(__key) =
                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                            match __key {
                                __Field::__field0 => {
                                    if _serde::__private229::Option::is_some(&__field0) {
                                        return _serde::__private229::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("center"));
                                    }
                                    __field0 =
                                        _serde::__private229::Some(_serde::de::MapAccess::next_value::<Vec2>(&mut __map)?);
                                }
                                __Field::__field1 => {
                                    if _serde::__private229::Option::is_some(&__field1) {
                                        return _serde::__private229::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("circle"));
                                    }
                                    __field1 =
                                        _serde::__private229::Some(_serde::de::MapAccess::next_value::<Circle>(&mut __map)?);
                                }
                                _ => {
                                    let _ =
                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                }
                            }
                        }
                        let __field0 =
                            match __field0 {
                                _serde::__private229::Some(__field0) => __field0,
                                _serde::__private229::None =>
                                    _serde::__private229::de::missing_field("center")?,
                            };
                        let __field1 =
                            match __field1 {
                                _serde::__private229::Some(__field1) => __field1,
                                _serde::__private229::None =>
                                    _serde::__private229::de::missing_field("circle")?,
                            };
                        _serde::__private229::Ok(BoundingCircle {
                                center: __field0,
                                circle: __field1,
                            })
                    }
                }
                #[doc(hidden)]
                const FIELDS: &'static [&'static str] = &["center", "circle"];
                _serde::Deserializer::deserialize_struct(__deserializer,
                    "BoundingCircle", FIELDS,
                    __Visitor {
                        marker: _serde::__private229::PhantomData::<BoundingCircle>,
                        lifetime: _serde::__private229::PhantomData,
                    })
            }
        }
    };Deserialize))]
474#[cfg_attr(
475    all(feature = "serialize", feature = "bevy_reflect"),
476    reflect(Serialize, Deserialize)
477)]
478pub struct BoundingCircle {
479    /// The center of the bounding circle
480    pub center: Vec2,
481    /// The circle
482    pub circle: Circle,
483}
484
485impl BoundingCircle {
486    /// Constructs a bounding circle from its center and radius.
487    #[inline]
488    pub const fn new(center: Vec2, radius: f32) -> Self {
489        if true {
    if !(radius >= 0.) {
        ::core::panicking::panic("assertion failed: radius >= 0.")
    };
};debug_assert!(radius >= 0.);
490        Self {
491            center,
492            circle: Circle { radius },
493        }
494    }
495
496    /// Computes a [`BoundingCircle`] containing the given set of points,
497    /// transformed by the rotation and translation of the given isometry.
498    ///
499    /// The bounding circle is not guaranteed to be the smallest possible.
500    #[inline]
501    pub fn from_point_cloud(isometry: impl Into<Isometry2d>, points: &[Vec2]) -> BoundingCircle {
502        let isometry = isometry.into();
503
504        let center = point_cloud_2d_center(points);
505        let mut radius_squared = 0.0;
506
507        for point in points {
508            // Get squared version to avoid unnecessary sqrt calls
509            let distance_squared = point.distance_squared(center);
510            if distance_squared > radius_squared {
511                radius_squared = distance_squared;
512            }
513        }
514
515        BoundingCircle::new(isometry * center, ops::sqrt(radius_squared))
516    }
517
518    /// Get the radius of the bounding circle
519    #[inline]
520    pub const fn radius(&self) -> f32 {
521        self.circle.radius
522    }
523
524    /// Computes the smallest [`Aabb2d`] containing this [`BoundingCircle`].
525    #[inline]
526    pub fn aabb_2d(&self) -> Aabb2d {
527        Aabb2d {
528            min: self.center - Vec2::splat(self.radius()),
529            max: self.center + Vec2::splat(self.radius()),
530        }
531    }
532
533    /// Finds the point on the bounding circle that is closest to the given `point`.
534    ///
535    /// If the point is outside the circle, the returned point will be on the perimeter of the circle.
536    /// Otherwise, it will be inside the circle and returned as is.
537    #[inline]
538    pub fn closest_point(&self, point: Vec2) -> Vec2 {
539        self.circle.closest_point(point - self.center) + self.center
540    }
541}
542
543impl BoundingVolume for BoundingCircle {
544    type Translation = Vec2;
545    type Rotation = Rot2;
546    type HalfSize = f32;
547
548    #[inline]
549    fn center(&self) -> Self::Translation {
550        self.center
551    }
552
553    #[inline]
554    fn half_size(&self) -> Self::HalfSize {
555        self.radius()
556    }
557
558    #[inline]
559    fn visible_area(&self) -> f32 {
560        core::f32::consts::PI * self.radius() * self.radius()
561    }
562
563    #[inline]
564    fn contains(&self, other: &Self) -> bool {
565        let diff = self.radius() - other.radius();
566        self.center.distance_squared(other.center) <= ops::copysign(diff.squared(), diff)
567    }
568
569    #[inline]
570    fn merge(&self, other: &Self) -> Self {
571        let diff = other.center - self.center;
572        let length = diff.length();
573        if self.radius() >= length + other.radius() {
574            return *self;
575        }
576        if other.radius() >= length + self.radius() {
577            return *other;
578        }
579        let dir = diff / length;
580        Self::new(
581            (self.center + other.center) / 2. + dir * ((other.radius() - self.radius()) / 2.),
582            (length + self.radius() + other.radius()) / 2.,
583        )
584    }
585
586    #[inline]
587    fn grow(&self, amount: impl Into<Self::HalfSize>) -> Self {
588        let amount = amount.into();
589        if true {
    if !(amount >= 0.) {
        ::core::panicking::panic("assertion failed: amount >= 0.")
    };
};debug_assert!(amount >= 0.);
590        Self::new(self.center, self.radius() + amount)
591    }
592
593    #[inline]
594    fn shrink(&self, amount: impl Into<Self::HalfSize>) -> Self {
595        let amount = amount.into();
596        if true {
    if !(amount >= 0.) {
        ::core::panicking::panic("assertion failed: amount >= 0.")
    };
};debug_assert!(amount >= 0.);
597        if true {
    if !(self.radius() >= amount) {
        ::core::panicking::panic("assertion failed: self.radius() >= amount")
    };
};debug_assert!(self.radius() >= amount);
598        Self::new(self.center, self.radius() - amount)
599    }
600
601    #[inline]
602    fn scale_around_center(&self, scale: impl Into<Self::HalfSize>) -> Self {
603        let scale = scale.into();
604        if true {
    if !(scale >= 0.) {
        ::core::panicking::panic("assertion failed: scale >= 0.")
    };
};debug_assert!(scale >= 0.);
605        Self::new(self.center, self.radius() * scale)
606    }
607
608    #[inline]
609    fn translate_by(&mut self, translation: impl Into<Self::Translation>) {
610        self.center += translation.into();
611    }
612
613    #[inline]
614    fn rotate_by(&mut self, rotation: impl Into<Self::Rotation>) {
615        let rotation: Rot2 = rotation.into();
616        self.center = rotation * self.center;
617    }
618}
619
620impl IntersectsVolume<Self> for BoundingCircle {
621    #[inline]
622    fn intersects(&self, other: &Self) -> bool {
623        let center_distance_squared = self.center.distance_squared(other.center);
624        let radius_sum_squared = (self.radius() + other.radius()).squared();
625        center_distance_squared <= radius_sum_squared
626    }
627}
628
629impl IntersectsVolume<Aabb2d> for BoundingCircle {
630    #[inline]
631    fn intersects(&self, aabb: &Aabb2d) -> bool {
632        aabb.intersects(self)
633    }
634}
635
636#[cfg(test)]
637mod bounding_circle_tests {
638    use crate::{BoundingCircle, BoundingVolume, IntersectsVolume};
639    use bevy_math::{ops, Vec2};
640
641    #[test]
642    fn area() {
643        let circle = BoundingCircle::new(Vec2::ONE, 5.);
644        // Since this number is messy we check it with a higher threshold
645        assert!(ops::abs(circle.visible_area() - 78.5398) < 0.001);
646    }
647
648    #[test]
649    fn contains() {
650        let a = BoundingCircle::new(Vec2::ONE, 5.);
651        let b = BoundingCircle::new(Vec2::new(5.5, 1.), 1.);
652        assert!(!a.contains(&b));
653        let b = BoundingCircle::new(Vec2::new(1., -3.5), 0.5);
654        assert!(a.contains(&b));
655    }
656
657    #[test]
658    fn contains_identical() {
659        let a = BoundingCircle::new(Vec2::ONE, 5.);
660        assert!(a.contains(&a));
661    }
662
663    #[test]
664    fn merge() {
665        // When merging two circles that don't contain each other, we find a center position that
666        // contains both
667        let a = BoundingCircle::new(Vec2::ONE, 5.);
668        let b = BoundingCircle::new(Vec2::new(1., -4.), 1.);
669        let merged = a.merge(&b);
670        assert!((merged.center - Vec2::new(1., 0.5)).length() < f32::EPSILON);
671        assert!(ops::abs(merged.radius() - 5.5) < f32::EPSILON);
672        assert!(merged.contains(&a));
673        assert!(merged.contains(&b));
674        assert!(!a.contains(&merged));
675        assert!(!b.contains(&merged));
676
677        // When one circle contains the other circle, we use the bigger circle
678        let b = BoundingCircle::new(Vec2::ZERO, 3.);
679        assert!(a.contains(&b));
680        let merged = a.merge(&b);
681        assert_eq!(merged.center, a.center);
682        assert_eq!(merged.radius(), a.radius());
683
684        // When two circles are at the same point, we use the bigger radius
685        let b = BoundingCircle::new(Vec2::ONE, 6.);
686        let merged = a.merge(&b);
687        assert_eq!(merged.center, a.center);
688        assert_eq!(merged.radius(), b.radius());
689    }
690
691    #[test]
692    fn merge_identical() {
693        let a = BoundingCircle::new(Vec2::ONE, 5.);
694        let merged = a.merge(&a);
695        assert_eq!(merged.center, a.center);
696        assert_eq!(merged.radius(), a.radius());
697    }
698
699    #[test]
700    fn grow() {
701        let a = BoundingCircle::new(Vec2::ONE, 5.);
702        let padded = a.grow(1.25_f32);
703        assert!(ops::abs(padded.radius() - 6.25) < f32::EPSILON);
704        assert!(padded.contains(&a));
705        assert!(!a.contains(&padded));
706    }
707
708    #[test]
709    fn shrink() {
710        let a = BoundingCircle::new(Vec2::ONE, 5.);
711        let shrunk = a.shrink(0.5_f32);
712        assert!(ops::abs(shrunk.radius() - 4.5) < f32::EPSILON);
713        assert!(a.contains(&shrunk));
714        assert!(!shrunk.contains(&a));
715    }
716
717    #[test]
718    fn scale_around_center() {
719        let a = BoundingCircle::new(Vec2::ONE, 5.);
720        let scaled = a.scale_around_center(2_f32);
721        assert!(ops::abs(scaled.radius() - 10.) < f32::EPSILON);
722        assert!(!a.contains(&scaled));
723        assert!(scaled.contains(&a));
724    }
725
726    #[test]
727    fn transform() {
728        let a = BoundingCircle::new(Vec2::ONE, 5.0);
729        let transformed = a.transformed_by(Vec2::new(2.0, -2.0), core::f32::consts::FRAC_PI_4);
730        assert_eq!(
731            transformed.center,
732            Vec2::new(2.0, core::f32::consts::SQRT_2 - 2.0)
733        );
734        assert_eq!(transformed.radius(), 5.0);
735    }
736
737    #[test]
738    fn closest_point() {
739        let circle = BoundingCircle::new(Vec2::ZERO, 1.0);
740        assert_eq!(circle.closest_point(Vec2::X * 10.0), Vec2::X);
741        assert_eq!(
742            circle.closest_point(Vec2::NEG_ONE * 10.0),
743            Vec2::NEG_ONE.normalize()
744        );
745        assert_eq!(
746            circle.closest_point(Vec2::new(0.25, 0.1)),
747            Vec2::new(0.25, 0.1)
748        );
749    }
750
751    #[test]
752    fn intersect_bounding_circle() {
753        let circle = BoundingCircle::new(Vec2::ZERO, 1.0);
754        assert!(circle.intersects(&BoundingCircle::new(Vec2::ZERO, 1.0)));
755        assert!(circle.intersects(&BoundingCircle::new(Vec2::ONE * 1.25, 1.0)));
756        assert!(circle.intersects(&BoundingCircle::new(Vec2::NEG_ONE * 1.25, 1.0)));
757        assert!(!circle.intersects(&BoundingCircle::new(Vec2::ONE * 1.5, 1.0)));
758    }
759}