Skip to main content

bevy_math/
isometry.rs

1//! Isometry types for expressing rigid motions in two and three dimensions.
2
3use crate::{Affine2, Affine3, Affine3A, Dir2, Dir3, Mat3, Mat3A, Quat, Rot2, Vec2, Vec3, Vec3A};
4use core::ops::Mul;
5
6#[cfg(feature = "approx")]
7use approx::{AbsDiffEq, RelativeEq, UlpsEq};
8
9#[cfg(feature = "bevy_reflect")]
10use bevy_reflect::{std_traits::ReflectDefault, Reflect};
11#[cfg(all(feature = "bevy_reflect", feature = "serialize"))]
12use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
13
14/// An isometry in two dimensions, representing a rotation followed by a translation.
15/// This can often be useful for expressing relative positions and transformations from one position to another.
16///
17/// In particular, this type represents a distance-preserving transformation known as a *rigid motion* or a *direct motion*,
18/// and belongs to the special [Euclidean group] SE(2). This includes translation and rotation, but excludes reflection.
19///
20/// For the three-dimensional version, see [`Isometry3d`].
21///
22/// [Euclidean group]: https://en.wikipedia.org/wiki/Euclidean_group
23///
24/// # Example
25///
26/// Isometries can be created from a given translation and rotation:
27///
28/// ```
29/// # use bevy_math::{Isometry2d, Rot2, Vec2};
30/// #
31/// let iso = Isometry2d::new(Vec2::new(2.0, 1.0), Rot2::degrees(90.0));
32/// ```
33///
34/// Or from separate parts:
35///
36/// ```
37/// # use bevy_math::{Isometry2d, Rot2, Vec2};
38/// #
39/// let iso1 = Isometry2d::from_translation(Vec2::new(2.0, 1.0));
40/// let iso2 = Isometry2d::from_rotation(Rot2::degrees(90.0));
41/// ```
42///
43/// The isometries can be used to transform points:
44///
45/// ```
46/// # use approx::assert_abs_diff_eq;
47/// # use bevy_math::{Isometry2d, Rot2, Vec2};
48/// #
49/// let iso = Isometry2d::new(Vec2::new(2.0, 1.0), Rot2::degrees(90.0));
50/// let point = Vec2::new(4.0, 4.0);
51///
52/// // These are equivalent
53/// let result = iso.transform_point(point);
54/// let result = iso * point;
55///
56/// assert_eq!(result, Vec2::new(-2.0, 5.0));
57/// ```
58///
59/// Isometries can also be composed together:
60///
61/// ```
62/// # use bevy_math::{Isometry2d, Rot2, Vec2};
63/// #
64/// # let iso = Isometry2d::new(Vec2::new(2.0, 1.0), Rot2::degrees(90.0));
65/// # let iso1 = Isometry2d::from_translation(Vec2::new(2.0, 1.0));
66/// # let iso2 = Isometry2d::from_rotation(Rot2::degrees(90.0));
67/// #
68/// assert_eq!(iso1 * iso2, iso);
69/// ```
70///
71/// One common operation is to compute an isometry representing the relative positions of two objects
72/// for things like intersection tests. This can be done with an inverse transformation:
73///
74/// ```
75/// # use bevy_math::{Isometry2d, Rot2, Vec2};
76/// #
77/// let circle_iso = Isometry2d::from_translation(Vec2::new(2.0, 1.0));
78/// let rectangle_iso = Isometry2d::from_rotation(Rot2::degrees(90.0));
79///
80/// // Compute the relative position and orientation between the two shapes
81/// let relative_iso = circle_iso.inverse() * rectangle_iso;
82///
83/// // Or alternatively, to skip an extra rotation operation:
84/// let relative_iso = circle_iso.inverse_mul(rectangle_iso);
85/// ```
86#[derive(#[automatically_derived]
impl ::core::marker::Copy for Isometry2d { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Isometry2d {
    #[inline]
    fn clone(&self) -> Isometry2d {
        let _: ::core::clone::AssertParamIsClone<Rot2>;
        let _: ::core::clone::AssertParamIsClone<Vec2>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::default::Default for Isometry2d {
    #[inline]
    fn default() -> Isometry2d {
        Isometry2d {
            rotation: ::core::default::Default::default(),
            translation: ::core::default::Default::default(),
        }
    }
}Default, #[automatically_derived]
impl ::core::fmt::Debug for Isometry2d {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "Isometry2d",
            "rotation", &self.rotation, "translation", &&self.translation)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Isometry2d {
    #[inline]
    fn eq(&self, other: &Isometry2d) -> bool {
        self.rotation == other.rotation &&
            self.translation == other.translation
    }
}PartialEq)]
87#[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 Isometry2d {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private228::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                let mut __serde_state =
                    _serde::Serializer::serialize_struct(__serializer,
                            "Isometry2d", false as usize + 1 + 1)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "rotation", &self.rotation)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "translation", &self.translation)?;
                _serde::ser::SerializeStruct::end(__serde_state)
            }
        }
    };serde::Serialize, #[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 Isometry2d {
            fn deserialize<__D>(__deserializer: __D)
                -> _serde::__private228::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::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "field identifier")
                    }
                    fn visit_u64<__E>(self, __value: u64)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            0u64 => _serde::__private228::Ok(__Field::__field0),
                            1u64 => _serde::__private228::Ok(__Field::__field1),
                            _ => _serde::__private228::Ok(__Field::__ignore),
                        }
                    }
                    fn visit_str<__E>(self, __value: &str)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            "rotation" => _serde::__private228::Ok(__Field::__field0),
                            "translation" =>
                                _serde::__private228::Ok(__Field::__field1),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                    fn visit_bytes<__E>(self, __value: &[u8])
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            b"rotation" => _serde::__private228::Ok(__Field::__field0),
                            b"translation" =>
                                _serde::__private228::Ok(__Field::__field1),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                }
                #[automatically_derived]
                impl<'de> _serde::Deserialize<'de> for __Field {
                    #[inline]
                    fn deserialize<__D>(__deserializer: __D)
                        -> _serde::__private228::Result<Self, __D::Error> where
                        __D: _serde::Deserializer<'de> {
                        _serde::Deserializer::deserialize_identifier(__deserializer,
                            __FieldVisitor)
                    }
                }
                #[doc(hidden)]
                struct __Visitor<'de> {
                    marker: _serde::__private228::PhantomData<Isometry2d>,
                    lifetime: _serde::__private228::PhantomData<&'de ()>,
                }
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                    type Value = Isometry2d;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "struct Isometry2d")
                    }
                    #[inline]
                    fn visit_seq<__A>(self, mut __seq: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::SeqAccess<'de> {
                        let __field0 =
                            match _serde::de::SeqAccess::next_element::<Rot2>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
                                                &"struct Isometry2d with 2 elements")),
                            };
                        let __field1 =
                            match _serde::de::SeqAccess::next_element::<Vec2>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
                                                &"struct Isometry2d with 2 elements")),
                            };
                        _serde::__private228::Ok(Isometry2d {
                                rotation: __field0,
                                translation: __field1,
                            })
                    }
                    #[inline]
                    fn visit_map<__A>(self, mut __map: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::MapAccess<'de> {
                        let mut __field0: _serde::__private228::Option<Rot2> =
                            _serde::__private228::None;
                        let mut __field1: _serde::__private228::Option<Vec2> =
                            _serde::__private228::None;
                        while let _serde::__private228::Some(__key) =
                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                            match __key {
                                __Field::__field0 => {
                                    if _serde::__private228::Option::is_some(&__field0) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("rotation"));
                                    }
                                    __field0 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Rot2>(&mut __map)?);
                                }
                                __Field::__field1 => {
                                    if _serde::__private228::Option::is_some(&__field1) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("translation"));
                                    }
                                    __field1 =
                                        _serde::__private228::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::__private228::Some(__field0) => __field0,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("rotation")?,
                            };
                        let __field1 =
                            match __field1 {
                                _serde::__private228::Some(__field1) => __field1,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("translation")?,
                            };
                        _serde::__private228::Ok(Isometry2d {
                                rotation: __field0,
                                translation: __field1,
                            })
                    }
                }
                #[doc(hidden)]
                const FIELDS: &'static [&'static str] =
                    &["rotation", "translation"];
                _serde::Deserializer::deserialize_struct(__deserializer,
                    "Isometry2d", FIELDS,
                    __Visitor {
                        marker: _serde::__private228::PhantomData::<Isometry2d>,
                        lifetime: _serde::__private228::PhantomData,
                    })
            }
        }
    };serde::Deserialize))]
88#[cfg_attr(
89    feature = "bevy_reflect",
90    derive(const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for Isometry2d where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration.register_type_data::<ReflectDefault, Self>();
                registration.register_type_data::<ReflectSerialize, Self>();
                registration.register_type_data::<ReflectDeserialize, Self>();
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Rot2 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Vec2 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for Isometry2d where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<Rot2>("rotation"),
                                                bevy_reflect::NamedField::new::<Vec2>("translation")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for Isometry2d where  {
            fn type_path() -> &'static str {
                "bevy_math::isometry::Isometry2d"
            }
            fn short_type_path() -> &'static str { "Isometry2d" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("Isometry2d")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::isometry".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::isometry")
            }
        }
        impl bevy_reflect::Reflect for Isometry2d 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 Isometry2d where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "rotation" => ::core::option::Option::Some(&self.rotation),
                    "translation" =>
                        ::core::option::Option::Some(&self.translation),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "rotation" =>
                        ::core::option::Option::Some(&mut self.rotation),
                    "translation" =>
                        ::core::option::Option::Some(&mut self.translation),
                    _ => ::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.rotation),
                    1usize => ::core::option::Option::Some(&self.translation),
                    _ => ::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.rotation),
                    1usize =>
                        ::core::option::Option::Some(&mut self.translation),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("rotation"),
                    1usize => ::core::option::Option::Some("translation"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "rotation" => ::core::option::Option::Some(0usize),
                    "translation" => ::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)
                -> bevy_reflect::structs::DynamicStruct {
                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("rotation",
                    bevy_reflect::PartialReflect::to_dynamic(&self.rotation));
                dynamic.insert_boxed("translation",
                    bevy_reflect::PartialReflect::to_dynamic(&self.translation));
                dynamic
            }
        }
        impl bevy_reflect::PartialReflect for Isometry2d 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 Isometry2d 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 mut __this =
                        <Self as ::core::default::Default>::default();
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <Rot2 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "rotation")?))() {
                        __this.rotation = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <Vec2 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "translation")?))() {
                        __this.translation = __field;
                    }
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect),
91    reflect(Debug, PartialEq, Default, Clone)
92)]
93#[cfg_attr(
94    all(feature = "serialize", feature = "bevy_reflect"),
95    reflect(Serialize, Deserialize)
96)]
97pub struct Isometry2d {
98    /// The rotational part of a two-dimensional isometry.
99    pub rotation: Rot2,
100    /// The translational part of a two-dimensional isometry.
101    pub translation: Vec2,
102}
103
104impl Isometry2d {
105    /// The identity isometry which represents the rigid motion of not doing anything.
106    pub const IDENTITY: Self = Isometry2d {
107        rotation: Rot2::IDENTITY,
108        translation: Vec2::ZERO,
109    };
110
111    /// Create a two-dimensional isometry from a rotation and a translation.
112    #[inline]
113    pub const fn new(translation: Vec2, rotation: Rot2) -> Self {
114        Isometry2d {
115            rotation,
116            translation,
117        }
118    }
119
120    /// Create a two-dimensional isometry from a rotation.
121    #[inline]
122    pub const fn from_rotation(rotation: Rot2) -> Self {
123        Isometry2d {
124            rotation,
125            translation: Vec2::ZERO,
126        }
127    }
128
129    /// Create a two-dimensional isometry from a translation.
130    #[inline]
131    pub const fn from_translation(translation: Vec2) -> Self {
132        Isometry2d {
133            rotation: Rot2::IDENTITY,
134            translation,
135        }
136    }
137
138    /// Create a two-dimensional isometry from a translation with the given `x` and `y` components.
139    #[inline]
140    pub const fn from_xy(x: f32, y: f32) -> Self {
141        Isometry2d {
142            rotation: Rot2::IDENTITY,
143            translation: Vec2::new(x, y),
144        }
145    }
146
147    /// The inverse isometry that undoes this one.
148    #[inline]
149    pub fn inverse(&self) -> Self {
150        let inv_rot = self.rotation.inverse();
151        Isometry2d {
152            rotation: inv_rot,
153            translation: inv_rot * -self.translation,
154        }
155    }
156
157    /// Compute `iso1.inverse() * iso2` in a more efficient way for one-shot cases.
158    ///
159    /// If the same isometry is used multiple times, it is more efficient to instead compute
160    /// the inverse once and use that for each transformation.
161    #[inline]
162    pub fn inverse_mul(&self, rhs: Self) -> Self {
163        let inv_rot = self.rotation.inverse();
164        let delta_translation = rhs.translation - self.translation;
165        Self::new(inv_rot * delta_translation, inv_rot * rhs.rotation)
166    }
167
168    /// Transform a point by rotating and translating it using this isometry.
169    #[inline]
170    pub fn transform_point(&self, point: Vec2) -> Vec2 {
171        self.rotation * point + self.translation
172    }
173
174    /// Transform a point by rotating and translating it using the inverse of this isometry.
175    ///
176    /// This is more efficient than `iso.inverse().transform_point(point)` for one-shot cases.
177    /// If the same isometry is used multiple times, it is more efficient to instead compute
178    /// the inverse once and use that for each transformation.
179    #[inline]
180    pub fn inverse_transform_point(&self, point: Vec2) -> Vec2 {
181        self.rotation.inverse() * (point - self.translation)
182    }
183}
184
185impl From<Isometry2d> for Affine2 {
186    #[inline]
187    fn from(iso: Isometry2d) -> Self {
188        Affine2 {
189            matrix2: iso.rotation.into(),
190            translation: iso.translation,
191        }
192    }
193}
194
195impl From<Vec2> for Isometry2d {
196    #[inline]
197    fn from(translation: Vec2) -> Self {
198        Isometry2d::from_translation(translation)
199    }
200}
201
202impl From<Rot2> for Isometry2d {
203    #[inline]
204    fn from(rotation: Rot2) -> Self {
205        Isometry2d::from_rotation(rotation)
206    }
207}
208
209impl Mul for Isometry2d {
210    type Output = Self;
211
212    #[inline]
213    fn mul(self, rhs: Self) -> Self::Output {
214        Isometry2d {
215            rotation: self.rotation * rhs.rotation,
216            translation: self.rotation * rhs.translation + self.translation,
217        }
218    }
219}
220
221impl Mul<Vec2> for Isometry2d {
222    type Output = Vec2;
223
224    #[inline]
225    fn mul(self, rhs: Vec2) -> Self::Output {
226        self.transform_point(rhs)
227    }
228}
229
230impl Mul<Dir2> for Isometry2d {
231    type Output = Dir2;
232
233    #[inline]
234    fn mul(self, rhs: Dir2) -> Self::Output {
235        self.rotation * rhs
236    }
237}
238
239#[cfg(feature = "approx")]
240impl AbsDiffEq for Isometry2d {
241    type Epsilon = <f32 as AbsDiffEq>::Epsilon;
242
243    fn default_epsilon() -> Self::Epsilon {
244        f32::default_epsilon()
245    }
246
247    fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
248        self.rotation.abs_diff_eq(&other.rotation, epsilon)
249            && self.translation.abs_diff_eq(other.translation, epsilon)
250    }
251}
252
253#[cfg(feature = "approx")]
254impl RelativeEq for Isometry2d {
255    fn default_max_relative() -> Self::Epsilon {
256        Self::default_epsilon()
257    }
258
259    fn relative_eq(
260        &self,
261        other: &Self,
262        epsilon: Self::Epsilon,
263        max_relative: Self::Epsilon,
264    ) -> bool {
265        self.rotation
266            .relative_eq(&other.rotation, epsilon, max_relative)
267            && self
268                .translation
269                .relative_eq(&other.translation, epsilon, max_relative)
270    }
271}
272
273#[cfg(feature = "approx")]
274impl UlpsEq for Isometry2d {
275    fn default_max_ulps() -> u32 {
276        4
277    }
278
279    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
280        self.rotation.ulps_eq(&other.rotation, epsilon, max_ulps)
281            && self
282                .translation
283                .ulps_eq(&other.translation, epsilon, max_ulps)
284    }
285}
286
287/// An isometry in three dimensions, representing a rotation followed by a translation.
288/// This can often be useful for expressing relative positions and transformations from one position to another.
289///
290/// In particular, this type represents a distance-preserving transformation known as a *rigid motion* or a *direct motion*,
291/// and belongs to the special [Euclidean group] SE(3). This includes translation and rotation, but excludes reflection.
292///
293/// For the two-dimensional version, see [`Isometry2d`].
294///
295/// [Euclidean group]: https://en.wikipedia.org/wiki/Euclidean_group
296///
297/// # Example
298///
299/// Isometries can be created from a given translation and rotation:
300///
301/// ```
302/// # use bevy_math::{Isometry3d, Quat, Vec3};
303/// # use std::f32::consts::FRAC_PI_2;
304/// #
305/// let iso = Isometry3d::new(Vec3::new(2.0, 1.0, 3.0), Quat::from_rotation_z(FRAC_PI_2));
306/// ```
307///
308/// Or from separate parts:
309///
310/// ```
311/// # use bevy_math::{Isometry3d, Quat, Vec3};
312/// # use std::f32::consts::FRAC_PI_2;
313/// #
314/// let iso1 = Isometry3d::from_translation(Vec3::new(2.0, 1.0, 3.0));
315/// let iso2 = Isometry3d::from_rotation(Quat::from_rotation_z(FRAC_PI_2));
316/// ```
317///
318/// The isometries can be used to transform points:
319///
320/// ```
321/// # use approx::assert_relative_eq;
322/// # use bevy_math::{Isometry3d, Quat, Vec3};
323/// # use std::f32::consts::FRAC_PI_2;
324/// #
325/// let iso = Isometry3d::new(Vec3::new(2.0, 1.0, 3.0), Quat::from_rotation_z(FRAC_PI_2));
326/// let point = Vec3::new(4.0, 4.0, 4.0);
327///
328/// // These are equivalent
329/// let result = iso.transform_point(point);
330/// let result = iso * point;
331///
332/// assert_relative_eq!(result, Vec3::new(-2.0, 5.0, 7.0));
333/// ```
334///
335/// Isometries can also be composed together:
336///
337/// ```
338/// # use bevy_math::{Isometry3d, Quat, Vec3};
339/// # use std::f32::consts::FRAC_PI_2;
340/// #
341/// # let iso = Isometry3d::new(Vec3::new(2.0, 1.0, 3.0), Quat::from_rotation_z(FRAC_PI_2));
342/// # let iso1 = Isometry3d::from_translation(Vec3::new(2.0, 1.0, 3.0));
343/// # let iso2 = Isometry3d::from_rotation(Quat::from_rotation_z(FRAC_PI_2));
344/// #
345/// assert_eq!(iso1 * iso2, iso);
346/// ```
347///
348/// One common operation is to compute an isometry representing the relative positions of two objects
349/// for things like intersection tests. This can be done with an inverse transformation:
350///
351/// ```
352/// # use bevy_math::{Isometry3d, Quat, Vec3};
353/// # use std::f32::consts::FRAC_PI_2;
354/// #
355/// let sphere_iso = Isometry3d::from_translation(Vec3::new(2.0, 1.0, 3.0));
356/// let cuboid_iso = Isometry3d::from_rotation(Quat::from_rotation_z(FRAC_PI_2));
357///
358/// // Compute the relative position and orientation between the two shapes
359/// let relative_iso = sphere_iso.inverse() * cuboid_iso;
360///
361/// // Or alternatively, to skip an extra rotation operation:
362/// let relative_iso = sphere_iso.inverse_mul(cuboid_iso);
363/// ```
364#[derive(#[automatically_derived]
impl ::core::marker::Copy for Isometry3d { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Isometry3d {
    #[inline]
    fn clone(&self) -> Isometry3d {
        let _: ::core::clone::AssertParamIsClone<Quat>;
        let _: ::core::clone::AssertParamIsClone<Vec3A>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::default::Default for Isometry3d {
    #[inline]
    fn default() -> Isometry3d {
        Isometry3d {
            rotation: ::core::default::Default::default(),
            translation: ::core::default::Default::default(),
        }
    }
}Default, #[automatically_derived]
impl ::core::fmt::Debug for Isometry3d {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "Isometry3d",
            "rotation", &self.rotation, "translation", &&self.translation)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Isometry3d {
    #[inline]
    fn eq(&self, other: &Isometry3d) -> bool {
        self.rotation == other.rotation &&
            self.translation == other.translation
    }
}PartialEq)]
365#[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 Isometry3d {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private228::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                let mut __serde_state =
                    _serde::Serializer::serialize_struct(__serializer,
                            "Isometry3d", false as usize + 1 + 1)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "rotation", &self.rotation)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "translation", &self.translation)?;
                _serde::ser::SerializeStruct::end(__serde_state)
            }
        }
    };serde::Serialize, #[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 Isometry3d {
            fn deserialize<__D>(__deserializer: __D)
                -> _serde::__private228::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::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "field identifier")
                    }
                    fn visit_u64<__E>(self, __value: u64)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            0u64 => _serde::__private228::Ok(__Field::__field0),
                            1u64 => _serde::__private228::Ok(__Field::__field1),
                            _ => _serde::__private228::Ok(__Field::__ignore),
                        }
                    }
                    fn visit_str<__E>(self, __value: &str)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            "rotation" => _serde::__private228::Ok(__Field::__field0),
                            "translation" =>
                                _serde::__private228::Ok(__Field::__field1),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                    fn visit_bytes<__E>(self, __value: &[u8])
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            b"rotation" => _serde::__private228::Ok(__Field::__field0),
                            b"translation" =>
                                _serde::__private228::Ok(__Field::__field1),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                }
                #[automatically_derived]
                impl<'de> _serde::Deserialize<'de> for __Field {
                    #[inline]
                    fn deserialize<__D>(__deserializer: __D)
                        -> _serde::__private228::Result<Self, __D::Error> where
                        __D: _serde::Deserializer<'de> {
                        _serde::Deserializer::deserialize_identifier(__deserializer,
                            __FieldVisitor)
                    }
                }
                #[doc(hidden)]
                struct __Visitor<'de> {
                    marker: _serde::__private228::PhantomData<Isometry3d>,
                    lifetime: _serde::__private228::PhantomData<&'de ()>,
                }
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                    type Value = Isometry3d;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "struct Isometry3d")
                    }
                    #[inline]
                    fn visit_seq<__A>(self, mut __seq: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::SeqAccess<'de> {
                        let __field0 =
                            match _serde::de::SeqAccess::next_element::<Quat>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
                                                &"struct Isometry3d with 2 elements")),
                            };
                        let __field1 =
                            match _serde::de::SeqAccess::next_element::<Vec3A>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
                                                &"struct Isometry3d with 2 elements")),
                            };
                        _serde::__private228::Ok(Isometry3d {
                                rotation: __field0,
                                translation: __field1,
                            })
                    }
                    #[inline]
                    fn visit_map<__A>(self, mut __map: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::MapAccess<'de> {
                        let mut __field0: _serde::__private228::Option<Quat> =
                            _serde::__private228::None;
                        let mut __field1: _serde::__private228::Option<Vec3A> =
                            _serde::__private228::None;
                        while let _serde::__private228::Some(__key) =
                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                            match __key {
                                __Field::__field0 => {
                                    if _serde::__private228::Option::is_some(&__field0) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("rotation"));
                                    }
                                    __field0 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Quat>(&mut __map)?);
                                }
                                __Field::__field1 => {
                                    if _serde::__private228::Option::is_some(&__field1) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("translation"));
                                    }
                                    __field1 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec3A>(&mut __map)?);
                                }
                                _ => {
                                    let _ =
                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                }
                            }
                        }
                        let __field0 =
                            match __field0 {
                                _serde::__private228::Some(__field0) => __field0,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("rotation")?,
                            };
                        let __field1 =
                            match __field1 {
                                _serde::__private228::Some(__field1) => __field1,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("translation")?,
                            };
                        _serde::__private228::Ok(Isometry3d {
                                rotation: __field0,
                                translation: __field1,
                            })
                    }
                }
                #[doc(hidden)]
                const FIELDS: &'static [&'static str] =
                    &["rotation", "translation"];
                _serde::Deserializer::deserialize_struct(__deserializer,
                    "Isometry3d", FIELDS,
                    __Visitor {
                        marker: _serde::__private228::PhantomData::<Isometry3d>,
                        lifetime: _serde::__private228::PhantomData,
                    })
            }
        }
    };serde::Deserialize))]
366#[cfg_attr(
367    feature = "bevy_reflect",
368    derive(const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for Isometry3d where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration.register_type_data::<ReflectDefault, Self>();
                registration.register_type_data::<ReflectSerialize, Self>();
                registration.register_type_data::<ReflectDeserialize, Self>();
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Quat as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Vec3A as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for Isometry3d where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<Quat>("rotation"),
                                                bevy_reflect::NamedField::new::<Vec3A>("translation")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for Isometry3d where  {
            fn type_path() -> &'static str {
                "bevy_math::isometry::Isometry3d"
            }
            fn short_type_path() -> &'static str { "Isometry3d" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("Isometry3d")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::isometry".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::isometry")
            }
        }
        impl bevy_reflect::Reflect for Isometry3d 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 Isometry3d where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "rotation" => ::core::option::Option::Some(&self.rotation),
                    "translation" =>
                        ::core::option::Option::Some(&self.translation),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "rotation" =>
                        ::core::option::Option::Some(&mut self.rotation),
                    "translation" =>
                        ::core::option::Option::Some(&mut self.translation),
                    _ => ::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.rotation),
                    1usize => ::core::option::Option::Some(&self.translation),
                    _ => ::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.rotation),
                    1usize =>
                        ::core::option::Option::Some(&mut self.translation),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("rotation"),
                    1usize => ::core::option::Option::Some("translation"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "rotation" => ::core::option::Option::Some(0usize),
                    "translation" => ::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)
                -> bevy_reflect::structs::DynamicStruct {
                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("rotation",
                    bevy_reflect::PartialReflect::to_dynamic(&self.rotation));
                dynamic.insert_boxed("translation",
                    bevy_reflect::PartialReflect::to_dynamic(&self.translation));
                dynamic
            }
        }
        impl bevy_reflect::PartialReflect for Isometry3d 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 Isometry3d 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 mut __this =
                        <Self as ::core::default::Default>::default();
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <Quat as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "rotation")?))() {
                        __this.rotation = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <Vec3A as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "translation")?))() {
                        __this.translation = __field;
                    }
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect),
369    reflect(Debug, PartialEq, Default, Clone)
370)]
371#[cfg_attr(
372    all(feature = "serialize", feature = "bevy_reflect"),
373    reflect(Serialize, Deserialize)
374)]
375pub struct Isometry3d {
376    /// The rotational part of a three-dimensional isometry.
377    pub rotation: Quat,
378    /// The translational part of a three-dimensional isometry.
379    pub translation: Vec3A,
380}
381
382impl Isometry3d {
383    /// The identity isometry which represents the rigid motion of not doing anything.
384    pub const IDENTITY: Self = Isometry3d {
385        rotation: Quat::IDENTITY,
386        translation: Vec3A::ZERO,
387    };
388
389    /// Create a three-dimensional isometry from a rotation and a translation.
390    #[inline]
391    pub fn new(translation: impl Into<Vec3A>, rotation: Quat) -> Self {
392        Isometry3d {
393            rotation,
394            translation: translation.into(),
395        }
396    }
397
398    /// Create a three-dimensional isometry from a rotation.
399    #[inline]
400    pub const fn from_rotation(rotation: Quat) -> Self {
401        Isometry3d {
402            rotation,
403            translation: Vec3A::ZERO,
404        }
405    }
406
407    /// Create a three-dimensional isometry from a translation.
408    #[inline]
409    pub fn from_translation(translation: impl Into<Vec3A>) -> Self {
410        Isometry3d {
411            rotation: Quat::IDENTITY,
412            translation: translation.into(),
413        }
414    }
415
416    /// Create a three-dimensional isometry from a translation with the given `x`, `y`, and `z` components.
417    #[inline]
418    pub const fn from_xyz(x: f32, y: f32, z: f32) -> Self {
419        Isometry3d {
420            rotation: Quat::IDENTITY,
421            translation: Vec3A::new(x, y, z),
422        }
423    }
424
425    /// The inverse isometry that undoes this one.
426    #[inline]
427    pub fn inverse(&self) -> Self {
428        let inv_rot = self.rotation.inverse();
429        Isometry3d {
430            rotation: inv_rot,
431            translation: inv_rot * -self.translation,
432        }
433    }
434
435    /// Compute `iso1.inverse() * iso2` in a more efficient way for one-shot cases.
436    ///
437    /// If the same isometry is used multiple times, it is more efficient to instead compute
438    /// the inverse once and use that for each transformation.
439    #[inline]
440    pub fn inverse_mul(&self, rhs: Self) -> Self {
441        let inv_rot = self.rotation.inverse();
442        let delta_translation = rhs.translation - self.translation;
443        Self::new(inv_rot * delta_translation, inv_rot * rhs.rotation)
444    }
445
446    /// Transform a point by rotating and translating it using this isometry.
447    #[inline]
448    pub fn transform_point(&self, point: impl Into<Vec3A>) -> Vec3A {
449        self.rotation * point.into() + self.translation
450    }
451
452    /// Transform a point by rotating and translating it using the inverse of this isometry.
453    ///
454    /// This is more efficient than `iso.inverse().transform_point(point)` for one-shot cases.
455    /// If the same isometry is used multiple times, it is more efficient to instead compute
456    /// the inverse once and use that for each transformation.
457    #[inline]
458    pub fn inverse_transform_point(&self, point: impl Into<Vec3A>) -> Vec3A {
459        self.rotation.inverse() * (point.into() - self.translation)
460    }
461}
462
463impl From<Isometry3d> for Affine3 {
464    #[inline]
465    fn from(iso: Isometry3d) -> Self {
466        Affine3 {
467            matrix3: Mat3::from_quat(iso.rotation),
468            translation: iso.translation.into(),
469        }
470    }
471}
472
473impl From<Isometry3d> for Affine3A {
474    #[inline]
475    fn from(iso: Isometry3d) -> Self {
476        Affine3A {
477            matrix3: Mat3A::from_quat(iso.rotation),
478            translation: iso.translation,
479        }
480    }
481}
482
483impl From<Vec3> for Isometry3d {
484    #[inline]
485    fn from(translation: Vec3) -> Self {
486        Isometry3d::from_translation(translation)
487    }
488}
489
490impl From<Vec3A> for Isometry3d {
491    #[inline]
492    fn from(translation: Vec3A) -> Self {
493        Isometry3d::from_translation(translation)
494    }
495}
496
497impl From<Quat> for Isometry3d {
498    #[inline]
499    fn from(rotation: Quat) -> Self {
500        Isometry3d::from_rotation(rotation)
501    }
502}
503
504impl Mul for Isometry3d {
505    type Output = Self;
506
507    #[inline]
508    fn mul(self, rhs: Self) -> Self::Output {
509        Isometry3d {
510            rotation: self.rotation * rhs.rotation,
511            translation: self.rotation * rhs.translation + self.translation,
512        }
513    }
514}
515
516impl Mul<Vec3A> for Isometry3d {
517    type Output = Vec3A;
518
519    #[inline]
520    fn mul(self, rhs: Vec3A) -> Self::Output {
521        self.transform_point(rhs)
522    }
523}
524
525impl Mul<Vec3> for Isometry3d {
526    type Output = Vec3;
527
528    #[inline]
529    fn mul(self, rhs: Vec3) -> Self::Output {
530        self.transform_point(rhs).into()
531    }
532}
533
534impl Mul<Dir3> for Isometry3d {
535    type Output = Dir3;
536
537    #[inline]
538    fn mul(self, rhs: Dir3) -> Self::Output {
539        self.rotation * rhs
540    }
541}
542
543#[cfg(feature = "approx")]
544impl AbsDiffEq for Isometry3d {
545    type Epsilon = <f32 as AbsDiffEq>::Epsilon;
546
547    fn default_epsilon() -> Self::Epsilon {
548        f32::default_epsilon()
549    }
550
551    fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
552        self.rotation.abs_diff_eq(other.rotation, epsilon)
553            && self.translation.abs_diff_eq(other.translation, epsilon)
554    }
555}
556
557#[cfg(feature = "approx")]
558impl RelativeEq for Isometry3d {
559    fn default_max_relative() -> Self::Epsilon {
560        Self::default_epsilon()
561    }
562
563    fn relative_eq(
564        &self,
565        other: &Self,
566        epsilon: Self::Epsilon,
567        max_relative: Self::Epsilon,
568    ) -> bool {
569        self.rotation
570            .relative_eq(&other.rotation, epsilon, max_relative)
571            && self
572                .translation
573                .relative_eq(&other.translation, epsilon, max_relative)
574    }
575}
576
577#[cfg(feature = "approx")]
578impl UlpsEq for Isometry3d {
579    fn default_max_ulps() -> u32 {
580        4
581    }
582
583    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
584        self.rotation.ulps_eq(&other.rotation, epsilon, max_ulps)
585            && self
586                .translation
587                .ulps_eq(&other.translation, epsilon, max_ulps)
588    }
589}
590
591#[cfg(test)]
592#[cfg(feature = "approx")]
593mod tests {
594    use super::*;
595    use crate::{vec2, vec3, vec3a};
596    use approx::assert_abs_diff_eq;
597    use core::f32::consts::{FRAC_PI_2, FRAC_PI_3};
598
599    #[test]
600    fn mul_2d() {
601        let iso1 = Isometry2d::new(vec2(1.0, 0.0), Rot2::FRAC_PI_2);
602        let iso2 = Isometry2d::new(vec2(0.0, 1.0), Rot2::FRAC_PI_2);
603        let expected = Isometry2d::new(vec2(0.0, 0.0), Rot2::PI);
604        assert_abs_diff_eq!(iso1 * iso2, expected);
605    }
606
607    #[test]
608    fn inverse_mul_2d() {
609        let iso1 = Isometry2d::new(vec2(1.0, 0.0), Rot2::FRAC_PI_2);
610        let iso2 = Isometry2d::new(vec2(0.0, 0.0), Rot2::PI);
611        let expected = Isometry2d::new(vec2(0.0, 1.0), Rot2::FRAC_PI_2);
612        assert_abs_diff_eq!(iso1.inverse_mul(iso2), expected);
613    }
614
615    #[test]
616    fn mul_3d() {
617        let iso1 = Isometry3d::new(vec3(1.0, 0.0, 0.0), Quat::from_rotation_x(FRAC_PI_2));
618        let iso2 = Isometry3d::new(vec3(0.0, 1.0, 0.0), Quat::IDENTITY);
619        let expected = Isometry3d::new(vec3(1.0, 0.0, 1.0), Quat::from_rotation_x(FRAC_PI_2));
620        assert_abs_diff_eq!(iso1 * iso2, expected);
621    }
622
623    #[test]
624    fn inverse_mul_3d() {
625        let iso1 = Isometry3d::new(vec3(1.0, 0.0, 0.0), Quat::from_rotation_x(FRAC_PI_2));
626        let iso2 = Isometry3d::new(vec3(1.0, 0.0, 1.0), Quat::from_rotation_x(FRAC_PI_2));
627        let expected = Isometry3d::new(vec3(0.0, 1.0, 0.0), Quat::IDENTITY);
628        assert_abs_diff_eq!(iso1.inverse_mul(iso2), expected);
629    }
630
631    #[test]
632    fn identity_2d() {
633        let iso = Isometry2d::new(vec2(-1.0, -0.5), Rot2::degrees(75.0));
634        assert_abs_diff_eq!(Isometry2d::IDENTITY * iso, iso);
635        assert_abs_diff_eq!(iso * Isometry2d::IDENTITY, iso);
636    }
637
638    #[test]
639    fn identity_3d() {
640        let iso = Isometry3d::new(vec3(-1.0, 2.5, 3.3), Quat::from_rotation_z(FRAC_PI_3));
641        assert_abs_diff_eq!(Isometry3d::IDENTITY * iso, iso);
642        assert_abs_diff_eq!(iso * Isometry3d::IDENTITY, iso);
643    }
644
645    #[test]
646    fn inverse_2d() {
647        let iso = Isometry2d::new(vec2(-1.0, -0.5), Rot2::degrees(75.0));
648        let inv = iso.inverse();
649        assert_abs_diff_eq!(iso * inv, Isometry2d::IDENTITY);
650        assert_abs_diff_eq!(inv * iso, Isometry2d::IDENTITY);
651    }
652
653    #[test]
654    fn inverse_3d() {
655        let iso = Isometry3d::new(vec3(-1.0, 2.5, 3.3), Quat::from_rotation_z(FRAC_PI_3));
656        let inv = iso.inverse();
657        assert_abs_diff_eq!(iso * inv, Isometry3d::IDENTITY);
658        assert_abs_diff_eq!(inv * iso, Isometry3d::IDENTITY);
659    }
660
661    #[test]
662    fn transform_2d() {
663        let iso = Isometry2d::new(vec2(0.5, -0.5), Rot2::FRAC_PI_2);
664        let point = vec2(1.0, 1.0);
665        assert_abs_diff_eq!(vec2(-0.5, 0.5), iso * point);
666    }
667
668    #[test]
669    fn inverse_transform_2d() {
670        let iso = Isometry2d::new(vec2(0.5, -0.5), Rot2::FRAC_PI_2);
671        let point = vec2(-0.5, 0.5);
672        assert_abs_diff_eq!(vec2(1.0, 1.0), iso.inverse_transform_point(point));
673    }
674
675    #[test]
676    fn transform_3d() {
677        let iso = Isometry3d::new(vec3(1.0, 0.0, 0.0), Quat::from_rotation_y(FRAC_PI_2));
678        let point = vec3(1.0, 1.0, 1.0);
679        assert_abs_diff_eq!(vec3(2.0, 1.0, -1.0), iso * point);
680    }
681
682    #[test]
683    fn inverse_transform_3d() {
684        let iso = Isometry3d::new(vec3(1.0, 0.0, 0.0), Quat::from_rotation_y(FRAC_PI_2));
685        let point = vec3(2.0, 1.0, -1.0);
686        assert_abs_diff_eq!(vec3a(1.0, 1.0, 1.0), iso.inverse_transform_point(point));
687    }
688}