diff --git a/crates/re_data_ui/src/transform3d.rs b/crates/re_data_ui/src/transform3d.rs index 4438d7bad1bf..0ad7c28bb28d 100644 --- a/crates/re_data_ui/src/transform3d.rs +++ b/crates/re_data_ui/src/transform3d.rs @@ -154,7 +154,7 @@ impl DataUi for TranslationAndMat3x3 { ) { let TranslationAndMat3x3 { translation, - matrix, + mat3x3, from_parent: _, } = self; @@ -167,7 +167,7 @@ impl DataUi for TranslationAndMat3x3 { ui.end_row(); } - if let Some(matrix) = matrix { + if let Some(matrix) = mat3x3 { ui.label("matrix"); matrix.data_ui(ctx, ui, verbosity, query); ui.end_row(); diff --git a/crates/re_types/definitions/rerun/datatypes/translation_and_mat3x3.fbs b/crates/re_types/definitions/rerun/datatypes/translation_and_mat3x3.fbs index 5b23287f8480..9b016b687fae 100644 --- a/crates/re_types/definitions/rerun/datatypes/translation_and_mat3x3.fbs +++ b/crates/re_types/definitions/rerun/datatypes/translation_and_mat3x3.fbs @@ -23,7 +23,7 @@ table TranslationAndMat3x3 ( // // NOTE: Nullable rather than defaulting to an identity-like value because we want to be able // to differentiate between no value vs. default value in the backend. - matrix: Mat3x3 (nullable, order: 200); + mat3x3: Mat3x3 (nullable, order: 200); // TODO(#2641): make this field non-nullable when default values are supported /// If true, the transform maps from the parent space to the space where the transform was logged. diff --git a/crates/re_types/src/archetypes/transform3d.rs b/crates/re_types/src/archetypes/transform3d.rs index 928f77e8cf97..5adf147a3878 100644 --- a/crates/re_types/src/archetypes/transform3d.rs +++ b/crates/re_types/src/archetypes/transform3d.rs @@ -23,9 +23,7 @@ /// /// use rerun::{ /// archetypes::{Arrows3D, Transform3D}, -/// datatypes::{ -/// Angle, RotationAxisAngle, Scale3D, TranslationAndMat3x3, TranslationRotationScale3D, -/// }, +/// datatypes::{Angle, RotationAxisAngle, Scale3D, TranslationRotationScale3D}, /// RecordingStreamBuilder, /// }; /// use std::f32::consts::PI; @@ -40,7 +38,7 @@ /// /// rec.log( /// "base/translated", -/// &Transform3D::new(TranslationAndMat3x3::translation([1.0, 0.0, 0.0])), +/// &Transform3D::new(TranslationRotationScale3D::translation([1.0, 0.0, 0.0])), /// )?; /// /// rec.log( diff --git a/crates/re_types/src/datatypes/transform3d_ext.rs b/crates/re_types/src/datatypes/transform3d_ext.rs index d92fda90bcd8..2c5184b09819 100644 --- a/crates/re_types/src/datatypes/transform3d_ext.rs +++ b/crates/re_types/src/datatypes/transform3d_ext.rs @@ -67,10 +67,10 @@ impl From for glam::Affine3A { match value { Transform3D::TranslationAndMat3x3(TranslationAndMat3x3 { translation, - matrix, + mat3x3, from_parent: _, }) => glam::Affine3A::from_mat3_translation( - matrix.unwrap_or(super::Mat3x3::IDENTITY).into(), + mat3x3.unwrap_or(super::Mat3x3::IDENTITY).into(), translation.map_or(glam::Vec3::ZERO, |v| v.into()), ), diff --git a/crates/re_types/src/datatypes/translation_and_mat3x3.rs b/crates/re_types/src/datatypes/translation_and_mat3x3.rs index 494a60373d47..d9048235c806 100644 --- a/crates/re_types/src/datatypes/translation_and_mat3x3.rs +++ b/crates/re_types/src/datatypes/translation_and_mat3x3.rs @@ -23,7 +23,7 @@ pub struct TranslationAndMat3x3 { pub translation: Option, /// 3x3 matrix for scale, rotation & shear. - pub matrix: Option, + pub mat3x3: Option, /// If true, the transform maps from the parent space to the space where the transform was logged. /// Otherwise, the transform maps from the space to its parent. @@ -64,7 +64,7 @@ impl crate::Loggable for TranslationAndMat3x3 { metadata: [].into(), }, Field { - name: "matrix".to_owned(), + name: "mat3x3".to_owned(), data_type: ::arrow_datatype(), is_nullable: true, metadata: [].into(), @@ -170,26 +170,26 @@ impl crate::Loggable for TranslationAndMat3x3 { } }, { - let (somes, matrix): (Vec<_>, Vec<_>) = data + let (somes, mat3x3): (Vec<_>, Vec<_>) = data .iter() .map(|datum| { let datum = datum .as_ref() .map(|datum| { - let Self { matrix, .. } = &**datum; - matrix.clone() + let Self { mat3x3, .. } = &**datum; + mat3x3.clone() }) .flatten(); (datum.is_some(), datum) }) .unzip(); - let matrix_bitmap: Option<::arrow2::bitmap::Bitmap> = { + let mat3x3_bitmap: Option<::arrow2::bitmap::Bitmap> = { let any_nones = somes.iter().any(|some| !*some); any_nones.then(|| somes.into()) }; { use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; - let matrix_inner_data: Vec<_> = matrix + let mat3x3_inner_data: Vec<_> = mat3x3 .iter() .map(|datum| { datum @@ -202,8 +202,8 @@ impl crate::Loggable for TranslationAndMat3x3 { .flatten() .map(Some) .collect(); - let matrix_inner_bitmap: Option<::arrow2::bitmap::Bitmap> = - matrix_bitmap.as_ref().map(|bitmap| { + let mat3x3_inner_bitmap: Option<::arrow2::bitmap::Bitmap> = + mat3x3_bitmap.as_ref().map(|bitmap| { bitmap .iter() .map(|i| std::iter::repeat(i).take(9usize)) @@ -223,14 +223,14 @@ impl crate::Loggable for TranslationAndMat3x3 { ), PrimitiveArray::new( DataType::Float32, - matrix_inner_data + mat3x3_inner_data .into_iter() .map(|v| v.unwrap_or_default()) .collect(), - matrix_inner_bitmap, + mat3x3_inner_bitmap, ) .boxed(), - matrix_bitmap, + mat3x3_bitmap, ) .boxed() } @@ -291,7 +291,7 @@ impl crate::Loggable for TranslationAndMat3x3 { metadata: [].into(), }, Field { - name: "matrix".to_owned(), + name: "mat3x3".to_owned(), data_type: ::arrow_datatype(), is_nullable: true, metadata: [].into(), @@ -403,15 +403,15 @@ impl crate::Loggable for TranslationAndMat3x3 { .into_iter() } }; - let matrix = { - if !arrays_by_name.contains_key("matrix") { + let mat3x3 = { + if !arrays_by_name.contains_key("mat3x3") { return Err(crate::DeserializationError::missing_struct_field( Self::arrow_datatype(), - "matrix", + "mat3x3", )) .with_context("rerun.datatypes.TranslationAndMat3x3"); } - let arrow_data = &**arrays_by_name["matrix"]; + let arrow_data = &**arrays_by_name["mat3x3"]; { let arrow_data = arrow_data .as_any() @@ -430,7 +430,7 @@ impl crate::Loggable for TranslationAndMat3x3 { arrow_data.data_type().clone(), ) }) - .with_context("rerun.datatypes.TranslationAndMat3x3#matrix")?; + .with_context("rerun.datatypes.TranslationAndMat3x3#mat3x3")?; if arrow_data.is_empty() { Vec::new() } else { @@ -448,7 +448,7 @@ impl crate::Loggable for TranslationAndMat3x3 { arrow_data_inner.data_type().clone(), ) }) - .with_context("rerun.datatypes.TranslationAndMat3x3#matrix")? + .with_context("rerun.datatypes.TranslationAndMat3x3#mat3x3")? .into_iter() .map(|opt| opt.copied()) .collect::>() @@ -509,14 +509,14 @@ impl crate::Loggable for TranslationAndMat3x3 { .into_iter() }; arrow2::bitmap::utils::ZipValidity::new_with_validity( - ::itertools::izip!(translation, matrix, from_parent), + ::itertools::izip!(translation, mat3x3, from_parent), arrow_data.validity(), ) .map(|opt| { - opt.map(|(translation, matrix, from_parent)| { + opt.map(|(translation, mat3x3, from_parent)| { Ok(Self { translation, - matrix, + mat3x3, from_parent: from_parent .ok_or_else(crate::DeserializationError::missing_data) .with_context("rerun.datatypes.TranslationAndMat3x3#from_parent")?, diff --git a/crates/re_types/src/datatypes/translation_and_mat3x3_ext.rs b/crates/re_types/src/datatypes/translation_and_mat3x3_ext.rs index 90e98fdff55e..6328a0c30bbd 100644 --- a/crates/re_types/src/datatypes/translation_and_mat3x3_ext.rs +++ b/crates/re_types/src/datatypes/translation_and_mat3x3_ext.rs @@ -11,16 +11,16 @@ impl Default for TranslationAndMat3x3 { impl TranslationAndMat3x3 { pub const IDENTITY: Self = Self { translation: None, - matrix: None, + mat3x3: None, from_parent: false, }; /// Create a new `TranslationAndMat3`. #[inline] - pub fn new, M: Into>(translation: T, matrix: M) -> Self { + pub fn new, M: Into>(translation: T, mat3x3: M) -> Self { Self { translation: Some(translation.into()), - matrix: Some(matrix.into()), + mat3x3: Some(mat3x3.into()), from_parent: false, } } @@ -29,16 +29,16 @@ impl TranslationAndMat3x3 { pub fn translation>(translation: T) -> Self { Self { translation: Some(translation.into()), - matrix: None, + mat3x3: None, from_parent: false, } } #[inline] - pub fn rotation>(matrix: M) -> Self { + pub fn rotation>(mat3x3: M) -> Self { Self { translation: None, - matrix: Some(matrix.into()), + mat3x3: Some(mat3x3.into()), from_parent: false, } } diff --git a/crates/re_types/tests/transform3d.rs b/crates/re_types/tests/transform3d.rs index 7047217bcc8f..60e957c9bf35 100644 --- a/crates/re_types/tests/transform3d.rs +++ b/crates/re_types/tests/transform3d.rs @@ -63,7 +63,7 @@ fn roundtrip() { transform: components::Transform3D(datatypes::Transform3D::TranslationAndMat3x3( TranslationAndMat3x3 { translation: None, - matrix: None, + mat3x3: None, from_parent: false, }, )), @@ -72,7 +72,7 @@ fn roundtrip() { transform: components::Transform3D(datatypes::Transform3D::TranslationAndMat3x3( TranslationAndMat3x3 { translation: Some(Vec3D([1.0, 2.0, 3.0])), - matrix: None, + mat3x3: None, from_parent: true, }, )), @@ -81,7 +81,7 @@ fn roundtrip() { transform: components::Transform3D(datatypes::Transform3D::TranslationAndMat3x3( TranslationAndMat3x3 { translation: None, - matrix: Some(Mat3x3([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])), + mat3x3: Some(Mat3x3([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])), from_parent: true, }, )), diff --git a/docs/code-examples/transform3d_simple.py b/docs/code-examples/transform3d_simple.py index afed39ff2af7..5f20a14aad7a 100644 --- a/docs/code-examples/transform3d_simple.py +++ b/docs/code-examples/transform3d_simple.py @@ -8,12 +8,12 @@ rr.log("base", rr.Arrows3D(origins=[0, 0, 0], vectors=[0, 1, 0])) -rr.log("base/translated", rr.TranslationAndMat3x3(translation=[1, 0, 0])) +rr.log("base/translated", rr.Transform3D(translation=[1, 0, 0])) rr.log("base/translated", rr.Arrows3D(origins=[0, 0, 0], vectors=[0, 1, 0])) rr.log( "base/rotated_scaled", - rr.TranslationRotationScale3D( + rr.Transform3D( rotation=RotationAxisAngle(axis=[0, 0, 1], angle=Angle(rad=pi / 4)), scale=2, ), diff --git a/docs/code-examples/transform3d_simple.rs b/docs/code-examples/transform3d_simple.rs index 448e091a1341..79034c1245b0 100644 --- a/docs/code-examples/transform3d_simple.rs +++ b/docs/code-examples/transform3d_simple.rs @@ -2,9 +2,7 @@ use rerun::{ archetypes::{Arrows3D, Transform3D}, - datatypes::{ - Angle, RotationAxisAngle, Scale3D, TranslationAndMat3x3, TranslationRotationScale3D, - }, + datatypes::{Angle, RotationAxisAngle, Scale3D, TranslationRotationScale3D}, RecordingStreamBuilder, }; use std::f32::consts::PI; @@ -19,7 +17,7 @@ fn main() -> Result<(), Box> { rec.log( "base/translated", - &Transform3D::new(TranslationAndMat3x3::translation([1.0, 0.0, 0.0])), + &Transform3D::new(TranslationRotationScale3D::translation([1.0, 0.0, 0.0])), )?; rec.log( diff --git a/examples/python/live_depth_sensor/main.py b/examples/python/live_depth_sensor/main.py index be487fa79ccd..ec030b31a429 100755 --- a/examples/python/live_depth_sensor/main.py +++ b/examples/python/live_depth_sensor/main.py @@ -40,7 +40,7 @@ def run_realsense(num_frames: int | None) -> None: rr.log_transform3d( "realsense/rgb", transform=rr.TranslationAndMat3( - translation=rgb_from_depth.translation, matrix=np.reshape(rgb_from_depth.rotation, (3, 3)) + translation=rgb_from_depth.translation, mat3x3=np.reshape(rgb_from_depth.rotation, (3, 3)) ), from_parent=True, timeless=True, diff --git a/examples/python/open_photogrammetry_format/main.py b/examples/python/open_photogrammetry_format/main.py index 6bd21c91b6c3..0de4a51f136d 100755 --- a/examples/python/open_photogrammetry_format/main.py +++ b/examples/python/open_photogrammetry_format/main.py @@ -161,7 +161,7 @@ def log_calibrated_cameras(self) -> None: ) ) - rr.log_transform3d(entity, rr.TranslationAndMat3(translation=calib_camera.position, matrix=rot)) + rr.log_transform3d(entity, rr.TranslationAndMat3(translation=calib_camera.position, mat3x3=rot)) assert calib_sensor.internals.type == "perspective" diff --git a/examples/python/raw_mesh/main.py b/examples/python/raw_mesh/main.py index 4ab656e21e4d..21590be4b31f 100755 --- a/examples/python/raw_mesh/main.py +++ b/examples/python/raw_mesh/main.py @@ -43,8 +43,9 @@ def log_scene(scene: trimesh.Scene, node: str, path: str | None = None) -> None: world_from_mesh = node_data[0] rr.log( path, - rr.datatypes.TranslationAndMat3x3( - trimesh.transformations.translation_from_matrix(world_from_mesh), world_from_mesh[0:3, 0:3] + rr.Transform3D( + mat3x3=trimesh.transformations.translation_from_matrix(world_from_mesh), + translation=world_from_mesh[0:3, 0:3], ), ) diff --git a/examples/python/ros_node/rerun_urdf.py b/examples/python/ros_node/rerun_urdf.py index 48b2ead21d25..f4cc2d489be6 100644 --- a/examples/python/ros_node/rerun_urdf.py +++ b/examples/python/ros_node/rerun_urdf.py @@ -45,7 +45,7 @@ def log_scene(scene: trimesh.Scene, node: str, path: str | None = None, timeless rr.Translation3D( rr.TranslationAndMat3( translation=trimesh.transformations.translation_from_matrix(world_from_mesh), - matrix=world_from_mesh[0:3, 0:3], + mat3x3=world_from_mesh[0:3, 0:3], ) ), timeless=timeless, diff --git a/rerun_cpp/src/rerun/archetypes/transform3d.hpp b/rerun_cpp/src/rerun/archetypes/transform3d.hpp index 16d5c702e33b..e3cce4525e1e 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d.hpp @@ -102,7 +102,7 @@ namespace rerun { /// where the transform was logged. Otherwise, the transform maps from the space to its /// parent. Transform3D(const datatypes::Vec3D& translation, bool from_parent = false) - : Transform3D(datatypes::TranslationAndMat3x3(translation, from_parent)) {} + : Transform3D(datatypes::TranslationRotationScale3D(translation, from_parent)) {} /// From 3x3 matrix only. /// diff --git a/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp b/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp index 2805d3419f89..2c89a2d68608 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp @@ -55,7 +55,7 @@ namespace rerun { /// where the transform was logged. Otherwise, the transform maps from the space to its /// parent. Transform3D(const datatypes::Vec3D& translation, bool from_parent = false) - : Transform3D(datatypes::TranslationAndMat3x3(translation, from_parent)) {} + : Transform3D(datatypes::TranslationRotationScale3D(translation, from_parent)) {} /// From 3x3 matrix only. /// diff --git a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.cpp b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.cpp index 268a195be8df..179e1f745993 100644 --- a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.cpp +++ b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.cpp @@ -14,7 +14,7 @@ namespace rerun { const std::shared_ptr &TranslationAndMat3x3::arrow_datatype() { static const auto datatype = arrow::struct_({ arrow::field("translation", rerun::datatypes::Vec3D::arrow_datatype(), true), - arrow::field("matrix", rerun::datatypes::Mat3x3::arrow_datatype(), true), + arrow::field("mat3x3", rerun::datatypes::Mat3x3::arrow_datatype(), true), arrow::field("from_parent", arrow::boolean(), false), }); return datatype; @@ -74,10 +74,10 @@ namespace rerun { ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { const auto &element = elements[elem_idx]; - if (element.matrix.has_value()) { + if (element.mat3x3.has_value()) { RR_RETURN_NOT_OK(rerun::datatypes::Mat3x3::fill_arrow_array_builder( field_builder, - &element.matrix.value(), + &element.mat3x3.value(), 1 )); } else { diff --git a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.hpp b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.hpp index d4e5385e5628..49ad947c7ffe 100644 --- a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.hpp +++ b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.hpp @@ -27,7 +27,7 @@ namespace rerun { std::optional translation; /// 3x3 matrix for scale, rotation & shear. - std::optional matrix; + std::optional mat3x3; /// If true, the transform maps from the parent space to the space where the transform /// was logged. Otherwise, the transform maps from the space to its parent. @@ -44,18 +44,18 @@ namespace rerun { /// where the transform was logged. Otherwise, the transform maps from the space to its /// parent. TranslationAndMat3x3( - const std::optional& _translation, const std::optional& _matrix, + const std::optional& _translation, const std::optional& _mat3x3, bool _from_parent ) - : translation(_translation), matrix(_matrix), from_parent(_from_parent) {} + : translation(_translation), mat3x3(_mat3x3), from_parent(_from_parent) {} /// From rotation only. /// /// @param _from_parent If true, the transform maps from the parent space to the space /// where the transform was logged. Otherwise, the transform maps from the space to its /// parent. - TranslationAndMat3x3(const Mat3x3& _matrix, bool _from_parent = false) - : translation(std::nullopt), matrix(_matrix), from_parent(_from_parent) {} + TranslationAndMat3x3(const Mat3x3& _mat3x3, bool _from_parent = false) + : translation(std::nullopt), mat3x3(_mat3x3), from_parent(_from_parent) {} /// From translation only. /// @@ -63,7 +63,7 @@ namespace rerun { /// where the transform was logged. Otherwise, the transform maps from the space to its /// parent. TranslationAndMat3x3(const Vec3D& _translation, bool _from_parent = false) - : translation(_translation), matrix(std::nullopt), from_parent(_from_parent) {} + : translation(_translation), mat3x3(std::nullopt), from_parent(_from_parent) {} public: TranslationAndMat3x3() = default; diff --git a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3_ext.cpp b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3_ext.cpp index 430bb712fafc..0f28bd49f8b7 100644 --- a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3_ext.cpp +++ b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3_ext.cpp @@ -9,7 +9,7 @@ namespace rerun { #ifdef EDIT_EXTENSION struct TranslationAndMat3x3Ext { std::optional translation; - std::optional matrix; + std::optional mat3x3; bool from_parent; #define TranslationAndMat3x3 TranslationAndMat3x3Ext @@ -23,18 +23,18 @@ namespace rerun { /// where the transform was logged. Otherwise, the transform maps from the space to its /// parent. TranslationAndMat3x3( - const std::optional& _translation, const std::optional& _matrix, + const std::optional& _translation, const std::optional& _mat3x3, bool _from_parent ) - : translation(_translation), matrix(_matrix), from_parent(_from_parent) {} + : translation(_translation), mat3x3(_mat3x3), from_parent(_from_parent) {} /// From rotation only. /// /// @param _from_parent If true, the transform maps from the parent space to the space /// where the transform was logged. Otherwise, the transform maps from the space to its /// parent. - TranslationAndMat3x3(const Mat3x3& _matrix, bool _from_parent = false) - : translation(std::nullopt), matrix(_matrix), from_parent(_from_parent) {} + TranslationAndMat3x3(const Mat3x3& _mat3x3, bool _from_parent = false) + : translation(std::nullopt), mat3x3(_mat3x3), from_parent(_from_parent) {} /// From translation only. /// @@ -42,7 +42,7 @@ namespace rerun { /// where the transform was logged. Otherwise, the transform maps from the space to its /// parent. TranslationAndMat3x3(const Vec3D& _translation, bool _from_parent = false) - : translation(_translation), matrix(std::nullopt), from_parent(_from_parent) {} + : translation(_translation), mat3x3(std::nullopt), from_parent(_from_parent) {} // [CODEGEN COPY TO HEADER END] }; diff --git a/rerun_cpp/tests/archetypes/transform3d.cpp b/rerun_cpp/tests/archetypes/transform3d.cpp index cf30e546a15b..add0371c187d 100644 --- a/rerun_cpp/tests/archetypes/transform3d.cpp +++ b/rerun_cpp/tests/archetypes/transform3d.cpp @@ -39,7 +39,7 @@ SCENARIO( AND_GIVEN("matrix as initializer list") { auto utility = from_parent ? Transform3D({1.0f, 2.0f, 3.0f}, MATRIX_ILIST, true) : Transform3D({1.0f, 2.0f, 3.0f}, MATRIX_ILIST); - translation_and_mat3.matrix = rrd::Mat3x3(MATRIX_ILIST); + translation_and_mat3.mat3x3 = rrd::Mat3x3(MATRIX_ILIST); manual.transform.repr = rrd::Transform3D::translation_and_mat3x3(translation_and_mat3); @@ -48,24 +48,13 @@ SCENARIO( AND_GIVEN("matrix as column vectors") { auto utility = from_parent ? Transform3D({1.0f, 2.0f, 3.0f}, columns, true) : Transform3D({1.0f, 2.0f, 3.0f}, columns); - translation_and_mat3.matrix = columns; + translation_and_mat3.mat3x3 = columns; manual.transform.repr = rrd::Transform3D::translation_and_mat3x3(translation_and_mat3); test_serialization_for_manual_and_builder(manual, utility); } } - GIVEN("Transform3D from translation only and from_parent==" << from_parent) { - auto utility = from_parent ? Transform3D({1.0f, 2.0f, 3.0f}, true) - : Transform3D({1.0f, 2.0f, 3.0f}); - - translation_and_mat3.translation = {1.0f, 2.0f, 3.0f}; - translation_and_mat3.matrix = std::nullopt; - translation_and_mat3.from_parent = from_parent; - manual.transform.repr = rrd::Transform3D::translation_and_mat3x3(translation_and_mat3); - - test_serialization_for_manual_and_builder(manual, utility); - } GIVEN("Transform3D from matrix as initializer list and from_parent==" << from_parent) { translation_and_mat3.translation = std::nullopt; translation_and_mat3.from_parent = from_parent; @@ -73,7 +62,7 @@ SCENARIO( AND_GIVEN("matrix as initializer list") { auto utility = from_parent ? Transform3D(MATRIX_ILIST, true) : Transform3D(MATRIX_ILIST); - translation_and_mat3.matrix = rrd::Mat3x3(MATRIX_ILIST); + translation_and_mat3.mat3x3 = rrd::Mat3x3(MATRIX_ILIST); manual.transform.repr = rrd::Transform3D::translation_and_mat3x3(translation_and_mat3); @@ -81,7 +70,7 @@ SCENARIO( } AND_GIVEN("matrix as column vectors") { auto utility = from_parent ? Transform3D(columns, true) : Transform3D(columns); - translation_and_mat3.matrix = columns; + translation_and_mat3.mat3x3 = columns; manual.transform.repr = rrd::Transform3D::translation_and_mat3x3(translation_and_mat3); @@ -96,6 +85,19 @@ SCENARIO( Transform3D manual; rrd::TranslationRotationScale3D translation_rotation_scale; + GIVEN("Transform3D from translation only and from_parent==" << from_parent) { + auto utility = from_parent ? Transform3D({1.0f, 2.0f, 3.0f}, true) + : Transform3D({1.0f, 2.0f, 3.0f}); + + translation_rotation_scale.translation = {1.0f, 2.0f, 3.0f}; + translation_rotation_scale.rotation = std::nullopt; + translation_rotation_scale.scale = std::nullopt; + translation_rotation_scale.from_parent = from_parent; + manual.transform.repr = + rrd::Transform3D::translation_rotation_scale(translation_rotation_scale); + + test_serialization_for_manual_and_builder(manual, utility); + } GIVEN("Transform3D from translation/rotation/scale and from_parent==" << from_parent) { auto utility = from_parent ? Transform3D({1.0f, 2.0f, 3.0f}, rotation, 1.0f, true) : Transform3D({1.0f, 2.0f, 3.0f}, rotation, 1.0f); diff --git a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py index 7a35feb2cf02..d4cff90637cb 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py @@ -5,19 +5,17 @@ from __future__ import annotations -from typing import Any - from attrs import define, field -from .. import components, datatypes +from .. import components from .._baseclasses import Archetype -from ..error_utils import catch_and_log_exceptions +from .transform3d_ext import Transform3DExt __all__ = ["Transform3D"] @define(str=False, repr=False, init=False) -class Transform3D(Archetype): +class Transform3D(Transform3DExt, Archetype): """ A 3D transform. @@ -33,12 +31,12 @@ class Transform3D(Archetype): rr.log("base", rr.Arrows3D(origins=[0, 0, 0], vectors=[0, 1, 0])) - rr.log("base/translated", rr.TranslationAndMat3x3(translation=[1, 0, 0])) + rr.log("base/translated", rr.Transform3D(translation=[1, 0, 0])) rr.log("base/translated", rr.Arrows3D(origins=[0, 0, 0], vectors=[0, 1, 0])) rr.log( "base/rotated_scaled", - rr.TranslationRotationScale3D( + rr.Transform3D( rotation=RotationAxisAngle(axis=[0, 0, 1], angle=Angle(rad=pi / 4)), scale=2, ), @@ -54,21 +52,7 @@ class Transform3D(Archetype): """ - def __init__(self: Any, transform: datatypes.Transform3DLike): - """ - Create a new instance of the Transform3D archetype. - - Parameters - ---------- - transform: - The transform - """ - - # You can define your own __init__ function as a member of Transform3DExt in transform3d_ext.py - with catch_and_log_exceptions(context=self.__class__.__name__): - self.__attrs_init__(transform=transform) - return - self.__attrs_clear__() + # __init__ can be found in transform3d_ext.py def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" @@ -93,3 +77,7 @@ def _clear(cls) -> Transform3D: __str__ = Archetype.__str__ __repr__ = Archetype.__repr__ + + +if hasattr(Transform3DExt, "deferred_patch_class"): + Transform3DExt.deferred_patch_class(Transform3D) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/transform3d_ext.py b/rerun_py/rerun_sdk/rerun/archetypes/transform3d_ext.py new file mode 100644 index 000000000000..78adb2d448d2 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/archetypes/transform3d_ext.py @@ -0,0 +1,76 @@ +from __future__ import annotations + +from typing import Any + +from rerun.datatypes.mat3x3 import Mat3x3Like +from rerun.datatypes.rotation3d import Rotation3DLike +from rerun.datatypes.scale3d import Scale3DLike +from rerun.datatypes.transform3d import Transform3DLike +from rerun.datatypes.translation_and_mat3x3 import TranslationAndMat3x3 +from rerun.datatypes.translation_rotation_scale3d import TranslationRotationScale3D +from rerun.datatypes.vec3d import Vec3DLike + +from ..error_utils import catch_and_log_exceptions + + +class Transform3DExt: + def __init__( + self: Any, + transform: Transform3DLike | None = None, + *, + translation: Vec3DLike | None = None, + rotation: Rotation3DLike | None = None, + scale: Scale3DLike | None = None, + mat3x3: Mat3x3Like | None = None, + from_parent: bool = False, + ): + """ + Create a new instance of the Transform3D archetype. + + Parameters + ---------- + transform: + Transform using an existing Transform3D datatype object. + If not provided, none of the other named parameters must be set. + translation: + 3D translation vector, applied last. + Not compatible with `transform`. + rotation: + 3D rotation, applied second. + Not compatible with `transform` and `mat3x3` parameters. + scale: + 3D scale, applied last. + Not compatible with `transform` and `mat3x3` parameters. + mat3x3: + 3x3 matrix representing scale and rotation, applied after translation. + Not compatible with `rotation` and `scale` parameters. + TODO(#3559): Support 4x4 and 4x3 matrices. + from_parent: + If true, the transform maps from the parent space to the space where the transform was logged. + Otherwise, the transform maps from the space to its parent. + """ + + with catch_and_log_exceptions(context=self.__class__.__name__): + if transform is not None: + if translation is not None or rotation is not None or scale is not None or mat3x3 is not None: + raise ValueError("If a transform is given, none of the other parameters can be set.") + self.__attrs_init__(transform=transform) + else: + if rotation is not None and mat3x3 is not None: + raise ValueError("Rotation and mat3x3 parameters are mutually exclusive.") + if scale is not None and mat3x3 is not None: + raise ValueError("Scale and mat3x3 parameters are mutually exclusive.") + + if mat3x3 is not None: + self.__attrs_init__( + transform=TranslationAndMat3x3(translation=translation, mat3x3=mat3x3, from_parent=from_parent) + ) + else: + self.__attrs_init__( + transform=TranslationRotationScale3D( + translation=translation, rotation=rotation, scale=scale, from_parent=from_parent + ) + ) + return + + self.__attrs_clear__() diff --git a/rerun_py/rerun_sdk/rerun/datatypes/transform3d.py b/rerun_py/rerun_sdk/rerun/datatypes/transform3d.py index 8e8e7730ed71..7ae94c209a6e 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/transform3d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/transform3d.py @@ -68,7 +68,7 @@ def __init__(self) -> None: metadata={}, ), pa.field( - "matrix", + "mat3x3", pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 9), nullable=True, metadata={}, diff --git a/rerun_py/rerun_sdk/rerun/datatypes/transform3d_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/transform3d_ext.py index c0c882b98882..a604715a19d9 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/transform3d_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/transform3d_ext.py @@ -124,12 +124,12 @@ def _build_struct_array_from_translation_mat3x3( translation_mat3: TranslationAndMat3x3, type_: pa.StructType ) -> pa.StructArray: translation = _optional_translation_to_arrow(translation_mat3.translation) - matrix = _optional_mat3x3_to_arrow(translation_mat3.matrix) + mat3x3 = _optional_mat3x3_to_arrow(translation_mat3.mat3x3) return pa.StructArray.from_arrays( [ translation, - matrix, + mat3x3, pa.array([translation_mat3.from_parent], type=pa.bool_()), ], fields=list(type_), diff --git a/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py b/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py index 3316c1f72d31..7f03b651145e 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py @@ -34,7 +34,7 @@ def _translation_and_mat3x3__translation__special_field_converter_override( return datatypes.Vec3D(x) -def _translation_and_mat3x3__matrix__special_field_converter_override( +def _translation_and_mat3x3__mat3x3__special_field_converter_override( x: datatypes.Mat3x3Like | None, ) -> datatypes.Mat3x3 | None: if x is None: @@ -68,8 +68,8 @@ class TranslationAndMat3x3(TranslationAndMat3x3Ext): 3D translation, applied after the matrix. """ - matrix: datatypes.Mat3x3 | None = field( - default=None, converter=_translation_and_mat3x3__matrix__special_field_converter_override + mat3x3: datatypes.Mat3x3 | None = field( + default=None, converter=_translation_and_mat3x3__mat3x3__special_field_converter_override ) """ 3x3 matrix for scale, rotation & shear. @@ -98,7 +98,7 @@ def __init__(self) -> None: metadata={}, ), pa.field( - "matrix", + "mat3x3", pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 9), nullable=True, metadata={}, diff --git a/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3_ext.py index 1420fc80d26a..4cf8f47f6749 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3_ext.py @@ -1,9 +1,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Iterable, cast +from typing import TYPE_CHECKING, Any if TYPE_CHECKING: - from .._log import ComponentBatchLike from . import Mat3x3Like, Vec3DLike @@ -12,7 +11,7 @@ class TranslationAndMat3x3Ext: def __init__( self: Any, translation: Vec3DLike | None = None, - matrix: Mat3x3Like | None = None, + mat3x3: Mat3x3Like | None = None, *, from_parent: bool = False, ) -> None: @@ -23,7 +22,7 @@ def __init__( ---------- translation: 3D translation, applied after the matrix. - matrix: + mat3x3: 3x3 matrix for scale, rotation & shear. from_parent: If true, the transform maps from the parent space to the space where the transform was logged. @@ -31,16 +30,5 @@ def __init__( """ self.__attrs_init__( # pyright: ignore[reportGeneralTypeIssues] - translation=translation, matrix=matrix, from_parent=from_parent + translation=translation, mat3x3=mat3x3, from_parent=from_parent ) - - # Implement the AsComponents - def as_component_batches(self) -> Iterable[ComponentBatchLike]: - from ..archetypes import Transform3D - from ..datatypes import TranslationAndMat3x3 - - return Transform3D(cast(TranslationAndMat3x3, self)).as_component_batches() - - def num_instances(self) -> int: - # Always a mono-component - return 1 diff --git a/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d_ext.py index 53ae6624ae6a..66d96ef44c69 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d_ext.py @@ -1,9 +1,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Iterable, cast +from typing import TYPE_CHECKING, Any if TYPE_CHECKING: - from .._log import ComponentBatchLike from . import Rotation3DLike, Scale3DLike, Vec3D, Vec3DLike @@ -29,14 +28,3 @@ def translation__field_converter_override(data: Vec3DLike | None) -> Vec3D | Non from . import Vec3D return Vec3D(data) - - # Implement the AsComponents protocol - def as_component_batches(self) -> Iterable[ComponentBatchLike]: - from ..archetypes import Transform3D - from ..datatypes import TranslationRotationScale3D - - return Transform3D(cast(TranslationRotationScale3D, self)).as_component_batches() - - def num_instances(self) -> int: - # Always a mono-component - return 1 diff --git a/rerun_py/rerun_sdk/rerun/log_deprecated/file.py b/rerun_py/rerun_sdk/rerun/log_deprecated/file.py index c8116132e68e..73b492257e40 100644 --- a/rerun_py/rerun_sdk/rerun/log_deprecated/file.py +++ b/rerun_py/rerun_sdk/rerun/log_deprecated/file.py @@ -113,7 +113,7 @@ def log_mesh_file( transform = np.require(transform, dtype="float32") translation = transform[..., -1] mat = [transform[..., 0], transform[..., 1], transform[..., 2]] - asset3d.transform = OutOfTreeTransform3DBatch(TranslationAndMat3x3(translation=translation, matrix=mat)) + asset3d.transform = OutOfTreeTransform3DBatch(TranslationAndMat3x3(translation=translation, mat3x3=mat)) return log(entity_path, asset3d, timeless=timeless, recording=recording) diff --git a/rerun_py/tests/unit/test_transform3d.py b/rerun_py/tests/unit/test_transform3d.py index 3cbf16d3b617..22fed0a02338 100644 --- a/rerun_py/tests/unit/test_transform3d.py +++ b/rerun_py/tests/unit/test_transform3d.py @@ -144,15 +144,15 @@ def test_translation_rotation_from_parent() -> None: @pytest.mark.parametrize("trans", VEC_3D_INPUT + [None]) @pytest.mark.parametrize("mat", MAT_3X3_INPUT + [None]) def test_translation_and_mat3x3(trans: Vec3DLike | None, mat: Mat3x3Like | None) -> None: - tm = TranslationAndMat3x3(translation=trans, matrix=mat) + tm = TranslationAndMat3x3(translation=trans, mat3x3=mat) if trans is None: assert tm.translation is None else: assert_correct_vec3d(tm.translation) if mat is None: - assert tm.matrix is None + assert tm.mat3x3 is None else: - assert_correct_mat3x3(tm.matrix) + assert_correct_mat3x3(tm.mat3x3) def test_translation_and_mat3x3_from_parent() -> None: @@ -171,28 +171,50 @@ def test_transform3d_translation_and_mat3x3(trans: Vec3DLike | None, mat: Mat3x3 expected_trans = Vec3D([1, 2, 3]) if trans is not None else None expected_mat = Mat3x3([1, 2, 3, 4, 5, 6, 7, 8, 9]) if mat is not None else None - tm = rr.Transform3D(TranslationAndMat3x3(translation=trans, matrix=mat)) + tm = rr.Transform3D(TranslationAndMat3x3(translation=trans, mat3x3=mat)) assert tm.transform == Transform3DBatch( Transform3D( TranslationAndMat3x3( translation=expected_trans, - matrix=expected_mat, + mat3x3=expected_mat, ) ) ) + if mat is None: + assert rr.Transform3D(TranslationRotationScale3D(translation=trans)) == rr.Transform3D( + translation=trans, + mat3x3=mat, + ) + else: + assert tm == rr.Transform3D( + translation=trans, + mat3x3=mat, + ) - tm2 = rr.Transform3D(TranslationAndMat3x3(translation=trans, matrix=mat, from_parent=True)) + tm2 = rr.Transform3D(TranslationAndMat3x3(translation=trans, mat3x3=mat, from_parent=True)) assert tm2.transform == Transform3DBatch( Transform3D( TranslationAndMat3x3( translation=expected_trans, - matrix=expected_mat, + mat3x3=expected_mat, from_parent=True, ) ) ) + if mat is None: + assert rr.Transform3D(TranslationRotationScale3D(translation=trans, from_parent=True)) == rr.Transform3D( + translation=trans, + mat3x3=mat, + from_parent=True, + ) + else: + assert tm2 == rr.Transform3D( + translation=expected_trans, + mat3x3=expected_mat, + from_parent=True, + ) assert tm != tm2 @@ -202,12 +224,14 @@ def test_transform3d_translation_rotation_scale3d_translation(trans: Vec3DLike) tm = rr.Transform3D(TranslationRotationScale3D(translation=trans)) assert tm.transform == Transform3DBatch(Transform3D(TranslationRotationScale3D(translation=Vec3D([1, 2, 3])))) + assert tm == rr.Transform3D(translation=Vec3D([1, 2, 3])) tm2 = rr.Transform3D(TranslationRotationScale3D(translation=trans, from_parent=True)) assert tm2.transform == Transform3DBatch( Transform3D(TranslationRotationScale3D(translation=Vec3D([1, 2, 3]), from_parent=True)) ) + assert tm2 == rr.Transform3D(translation=Vec3D([1, 2, 3]), from_parent=True) assert tm2 != tm @@ -222,6 +246,10 @@ def test_transform3d_translation_rotation_scale3d_rotation(rot: Rotation3DLike) Transform3D(TranslationRotationScale3D(rotation=Rotation3D(RotationAxisAngle(Vec3D([1, 2, 3]), Angle(rad=4))))) ) + assert tm == rr.Transform3D(rotation=Rotation3D(Quaternion(xyzw=[1, 2, 3, 4]))) or tm == rr.Transform3D( + rotation=Rotation3D(RotationAxisAngle(Vec3D([1, 2, 3]), Angle(rad=4))) + ) + @pytest.mark.parametrize("scale", SCALE_3D_INPUT) def test_transform3d_translation_rotation_scale3d_scale(scale: Scale3DLike) -> None: @@ -230,3 +258,26 @@ def test_transform3d_translation_rotation_scale3d_scale(scale: Scale3DLike) -> N assert tm.transform == Transform3DBatch( Transform3D(TranslationRotationScale3D(scale=Scale3D([1, 2, 3]))) ) or tm.transform == Transform3DBatch(Transform3D(TranslationRotationScale3D(scale=Scale3D(4.0)))) + assert tm == rr.Transform3D(scale=Scale3D([1, 2, 3])) or tm == rr.Transform3D(scale=Scale3D(4.0)) + + +def test_transform3d_invalid_parameter_combinations() -> None: + rr.set_strict_mode(True) + + # combine transform with anything else. + with pytest.raises(ValueError): + rr.Transform3D(transform=TranslationRotationScale3D(translation=[1, 2, 3]), translation=[1, 2, 3]) + with pytest.raises(ValueError): + rr.Transform3D(transform=TranslationRotationScale3D(translation=[1, 2, 3]), scale=2) + with pytest.raises(ValueError): + rr.Transform3D( + transform=TranslationRotationScale3D(translation=[1, 2, 3]), rotation=rr.Quaternion(xyzw=[1, 2, 3, 4]) + ) + with pytest.raises(ValueError): + rr.Transform3D(transform=TranslationRotationScale3D(translation=[1, 2, 3]), mat3x3=[1, 2, 3, 4, 5, 6, 7, 8, 9]) + + # combine 3x3 matrix with rotation or scale + with pytest.raises(ValueError): + rr.Transform3D(mat3x3=[1, 2, 3, 4, 5, 6, 7, 8, 9], scale=2) + with pytest.raises(ValueError): + rr.Transform3D(mat3x3=[1, 2, 3, 4, 5, 6, 7, 8, 9], rotation=rr.Quaternion(xyzw=[1, 2, 3, 4])) diff --git a/tests/python/roundtrips/transform3d/main.py b/tests/python/roundtrips/transform3d/main.py index e04d78fe8d08..041e5123305f 100644 --- a/tests/python/roundtrips/transform3d/main.py +++ b/tests/python/roundtrips/transform3d/main.py @@ -27,7 +27,7 @@ def main() -> None: rr.log( "translation_and_mat3x3/rotation", - rr.Transform3D(TranslationAndMat3x3(matrix=[1, 2, 3, 4, 5, 6, 7, 8, 9])), + rr.Transform3D(TranslationAndMat3x3(mat3x3=[1, 2, 3, 4, 5, 6, 7, 8, 9])), ) rr.log( diff --git a/tests/python/test_api/main.py b/tests/python/test_api/main.py index 434a94ce6a69..ae8ea225c7fa 100755 --- a/tests/python/test_api/main.py +++ b/tests/python/test_api/main.py @@ -228,7 +228,7 @@ def transforms(experimental_api: bool) -> None: # Log a transform with translation and shear along x. rr.log( "transforms/shear", - TranslationAndMat3x3(translation=(3, 0, 1), matrix=np.array([[1, 1, 0], [0, 1, 0], [0, 0, 1]])), + TranslationAndMat3x3(translation=(3, 0, 1), mat3x3=np.array([[1, 1, 0], [0, 1, 0], [0, 0, 1]])), ) else: # Log scale along the x axis only.