pybevy_math 0.2.1

Math types (Vec2, Vec3, Vec4, Quat, Mat3, Mat4) for PyBevy
Documentation
use bevy::math::{
    Vec2,
    bounding::{BoundingCircle, BoundingVolume, IntersectsVolume},
};
use pybevy_core::{FromBorrowedStorage, ValueStorage};
use pyo3::prelude::*;

use super::aabb2d::PyAabb2d;
use crate::vec2::PyVec2;

#[pyclass(name = "BoundingCircle")]
#[derive(Debug, Clone)]
pub struct PyBoundingCircle {
    storage: ValueStorage<BoundingCircle>,
}

impl From<PyBoundingCircle> for BoundingCircle {
    #[inline(always)]
    fn from(py_circle: PyBoundingCircle) -> Self {
        match py_circle.storage.get() {
            Ok(val) => val,
            Err(_) => BoundingCircle::new(Vec2::ZERO, 0.0),
        }
    }
}

impl From<&PyBoundingCircle> for BoundingCircle {
    #[inline(always)]
    fn from(py_circle: &PyBoundingCircle) -> Self {
        match py_circle.storage.get() {
            Ok(val) => val,
            Err(_) => BoundingCircle::new(Vec2::ZERO, 0.0),
        }
    }
}

impl From<BoundingCircle> for PyBoundingCircle {
    #[inline(always)]
    fn from(circle: BoundingCircle) -> Self {
        PyBoundingCircle::from_bounding_circle(circle)
    }
}

impl FromBorrowedStorage<ValueStorage<BoundingCircle>> for PyBoundingCircle {
    fn from_borrowed(storage: ValueStorage<BoundingCircle>) -> Self {
        PyBoundingCircle { storage }
    }
}

impl PyBoundingCircle {
    #[inline(always)]
    pub fn from_bounding_circle(circle: BoundingCircle) -> Self {
        PyBoundingCircle {
            storage: ValueStorage::owned(circle),
        }
    }

    #[inline(always)]
    fn as_ref(&self) -> PyResult<&BoundingCircle> {
        Ok(self.storage.as_ref()?)
    }

    pub(crate) fn to_bounding_circle(&self) -> BoundingCircle {
        match self.storage.get() {
            Ok(val) => val,
            Err(_) => BoundingCircle::new(Vec2::ZERO, 0.0),
        }
    }
}

#[pymethods]
impl PyBoundingCircle {
    #[new]
    pub fn new(center: PyVec2, radius: f32) -> Self {
        let center_vec: Vec2 = center.into();
        PyBoundingCircle::from_bounding_circle(BoundingCircle::new(center_vec, radius))
    }

    #[getter]
    pub fn center(&self) -> PyResult<PyVec2> {
        Ok(PyVec2::from_vec2(self.as_ref()?.center))
    }

    pub fn radius(&self) -> PyResult<f32> {
        Ok(self.as_ref()?.radius())
    }

    pub fn closest_point(&self, point: PyVec2) -> PyResult<PyVec2> {
        let point_vec: Vec2 = point.into();
        Ok(PyVec2::from_vec2(self.as_ref()?.closest_point(point_vec)))
    }

    pub fn contains(&self, other: &PyBoundingCircle) -> PyResult<bool> {
        let other_circle: BoundingCircle = other.into();
        Ok(self.as_ref()?.contains(&other_circle))
    }

    pub fn merge(&self, other: &PyBoundingCircle) -> PyResult<PyBoundingCircle> {
        let other_circle: BoundingCircle = other.into();
        Ok(PyBoundingCircle::from_bounding_circle(
            self.as_ref()?.merge(&other_circle),
        ))
    }

    pub fn grow(&self, amount: f32) -> PyResult<PyBoundingCircle> {
        Ok(PyBoundingCircle::from_bounding_circle(
            self.as_ref()?.grow(amount),
        ))
    }

    pub fn shrink(&self, amount: f32) -> PyResult<PyBoundingCircle> {
        Ok(PyBoundingCircle::from_bounding_circle(
            self.as_ref()?.shrink(amount),
        ))
    }

    pub fn scale_around_center(&self, scale: f32) -> PyResult<PyBoundingCircle> {
        Ok(PyBoundingCircle::from_bounding_circle(
            self.as_ref()?.scale_around_center(scale),
        ))
    }

    pub fn visible_area(&self) -> PyResult<f32> {
        Ok(self.as_ref()?.visible_area())
    }

    pub fn aabb_2d(&self) -> PyResult<PyAabb2d> {
        Ok(PyAabb2d::from_aabb2d(self.as_ref()?.aabb_2d()))
    }

    pub fn intersects_circle(&self, other: &PyBoundingCircle) -> PyResult<bool> {
        let other_circle: BoundingCircle = other.into();
        Ok(self.as_ref()?.intersects(&other_circle))
    }

    pub fn intersects_aabb(&self, aabb: &PyAabb2d) -> PyResult<bool> {
        let aabb_2d: bevy::math::bounding::Aabb2d = aabb.into();
        Ok(self.as_ref()?.intersects(&aabb_2d))
    }

    #[staticmethod]
    pub fn from_point_cloud(
        isometry: super::aabb2d::PyIsometry2d,
        points: Vec<PyVec2>,
    ) -> PyResult<PyBoundingCircle> {
        use bevy::math::Isometry2d;

        let iso: Isometry2d = isometry.into();
        let point_refs: Vec<Vec2> = points.into_iter().map(|p| p.into()).collect();

        Ok(PyBoundingCircle::from_bounding_circle(
            BoundingCircle::from_point_cloud(iso, &point_refs),
        ))
    }

    pub fn __eq__(&self, other: &PyBoundingCircle) -> PyResult<bool> {
        Ok(self.as_ref()? == other.as_ref()?)
    }

    fn __repr__(&self) -> PyResult<String> {
        let circle = self.as_ref()?;
        Ok(format!(
            "BoundingCircle(center={:?}, radius={})",
            circle.center,
            circle.radius()
        ))
    }
}