dimforge / dimforge/nalgebra

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)

Open
#946 0 comments 0 reactions 0 assignees View on GitHub
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.