use pyo3::prelude::*;
use crate::math::rotation::EulerParameter;
use super::{FovShape, Instrument};
use nalgebra::Vector3;
use ndarray::Array1;
use numpy::{PyArray1, PyReadonlyArray1};
use pyo3::exceptions::PyValueError;
fn to_numpy_array<'py>(v: Vector3<f64>, py: Python<'py>) -> Bound<'py, PyArray1<f64>> {
let data: Vec<f64> = v.transpose().iter().copied().collect();
let arr = Array1::from_shape_vec((3,), data).unwrap();
PyArray1::<f64>::from_owned_array(py, arr)
}
fn to_vec3<'py>(arr: PyReadonlyArray1<'py, f64>, name: &str) -> PyResult<Vector3<f64>> {
let view = arr.as_array();
if view.len() != 3 {
return Err(PyValueError::new_err(format!(
"{} must be a length-3 vector, got length {}",
name,
view.len()
)));
}
Ok(Vector3::new(view[0], view[1], view[2]))
}
#[pymethods]
impl Instrument {
#[new]
fn py_new<'py>(
q_to_i: EulerParameter,
offset: PyReadonlyArray1<'py, f64>,
fov: FovShape,
) -> PyResult<Instrument> {
let translation = to_vec3(offset, "mounting_translation")?;
Ok(Self {
q_to_i,
offset_i: translation,
fov,
})
}
#[getter]
fn get_fov(&self) -> FovShape {
self.fov
}
#[getter]
fn get_q_to_i(&self) -> EulerParameter {
self.q_to_i
}
#[getter]
fn get_offset_i<'py>(&self, py: Python<'py>) -> Bound<'py, PyArray1<f64>> {
to_numpy_array(self.offset_i, py)
}
#[setter]
fn set_offset_i<'py>(&mut self, offset_i: PyReadonlyArray1<'py, f64>) -> PyResult<()> {
self.offset_i = to_vec3(offset_i, "mounting_translation")?;
Ok(())
}
#[setter]
fn set_q_to_i(&mut self, q_to_i: EulerParameter) {
self.q_to_i = q_to_i;
}
#[setter]
fn set_fov(&mut self, fov: FovShape) {
self.fov = fov;
}
}