Method similar to `transform_point` for point sets represented by D x N matrix in addition to only a single point (D x 1 vector)
- Dominant language
- Rust
- Stars
- 4.8k
- Forks
- 565
- PR merge metrics
- No merged PRs in 30d
Description
Enhancement idea:
I think it would be a good idea to make a method similar to [`transform_point` method of `Transform`](https://docs.rs/nalgebra/0.28.0/nalgebra/geometry/struct.Transform.html#method.transform_point) work for point sets represented by a dynamic D x N matrix. This way we could transform many points at once without using a loop. In particular this would be useful for:
* transforming the vertices of a mesh
* transforming a point cloud (e.g. from a lidar)
Furthermore, if the D x N matrix is internally stored in row major format, i.e. [x_0, x_1, x_2, ... , x_{n-1}, y_0, y_1, ...], then we can benefit from huge performance boosts with SIMD. (SIMD benefits would also exist if it's column major format, but a stride of 3 for D=3 with [x_0, y_0, z_0, x_1, y_1, z_1 ...] might be suboptimal).
Likewise for `transform_vector`.
By the way, Eigen's [`Transform`](https://eigen.tuxfamily.org/dox/classEigen_1_1Transform.html) has methods `.linear()` and `.translation()` to get views of the top left D x D and top right D x 1 submatrices respectively. I couldn't find a similar method in `nalgebra`'s `Transform`. Or should I just manually call `transform.matrix().slice((0, 0), (D, D))` and `transform.matrix().slice((0, D), (D, 1))`?
Currently, I would like to transform `ndarray::Array3` of shape `(3, height, width)` for which you can easily make a view of the shape `(3, height * width)` using `na::DMatrixSlice::from_slice_with_strides` or whatever.
```rust
use ndarray::prelude::*;
/// apply an affine transformation a point cloud
pub fn affine(aff: &na::Matrix3, points: &Array3) -> anyhow::Result> {
let (_, height, width) = points.dim();
let slice = na::DMatrixSlice::from_slice_with_strides(
points
.as_slice()
.ok_or(anyhow!("points array malformed (not contiguous?)"))?,
height * width,
3,
1,
height * width,
);
let affined = slice * aff.transpose();
let affined_array: Array3 =
ArrayView3::from_shape((3, height, width), affined.as_slice())?.to_owned();
Ok(affined_array)
}
/// transform a point cloud using homogeneous transformation (affine + translation)
pub fn transform(trans: &na::Transform3, points: &Array3) -> anyhow::Result> {
let aff: na::Matrix3 = trans.matrix().fixed_slice::<3, 3>(0, 0).into();
let translation = trans.matrix().fixed_slice::<3, 1>(0, 3);
let translation = ArrayView3::from_shape((3, 1, 1), translation.as_slice())?;
let transformed = affine(&aff, &points)? + translation;
Ok(transformed)
}
```
My code is currently somewhat inefficient so some advice would be highly appreciated.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.