2D planar coordinate system conversion
The 2D planar coordinate system conversion I use at work, the demo code is implemented in Rust, and other code should be implemented in roughly the same way. 🤔
If you are using the standard right-handed Cartesian coordinate system you may need to transform the y-axis appropriately.
Rotation
clockwise
\[A= \begin{gathered} \begin{bmatrix} cos(\theta) & sin(\theta) & 0 \\ sin(\theta) & cos(\theta) & 0 \\ 0 & 0 & 1 \end{bmatrix} \end{gathered}\]counterclockwise
\[A= \begin{gathered} \begin{bmatrix} cos(\theta) & sin(-\theta) & 0 \\ sin(\theta) & cos(\theta) & 0 \\ 0 & 0 & 1 \end{bmatrix} \end{gathered}\]matrix equation
\[\begin{gathered} \begin{bmatrix} x_1 \\ y_1 \\ 1 \end{bmatrix} \end{gathered} = A \cdot \begin{gathered} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} \end{gathered}\]Rust demo code
use std::f64::consts::PI;
use ndarray::arr2;
fn rotation() {
// 2D point rotation 45 degrees
let theta = 45.0 * (PI / 180.0);
// Convert Ordinary Coordinate (x, y) to Homogeneous Coordinate (x, y, 1)
let point = arr2(&[[0.0], [10.0], [1.0]]);
// 2D rotated matrices
let a = arr2(&[
[f64::cos(theta), f64::sin(theta), 0.0],
[f64::sin(theta), f64::cos(theta), 0.0],
[0.0, 0.0, 1.0],
]);
let new_point = a.dot(&point);
println!("{}", &new_point);
}
Finished dev [unoptimized + debuginfo] target(s) in 0.11s
Running `target/debug/two_d_cover`
[[7.071067811865475],
[7.0710678118654755],
[1]]
Rotate a point around another point
- Translate the specified point to the origin to obtain the translation matrix $T_1$
- Perform a rotation to obtain the rotation matrix $R$
- Translate to the specified point to get the translation matrix $T_2$.
the point $(x_0, y_0)$ is rotated around the point $(x_s, y_s)$
\[T_1= \begin{gathered} \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ -x_s & -y_s & 1 \end{bmatrix} \end{gathered}\] \[R= \begin{gathered} \begin{bmatrix} cos(\theta) & -sin(\theta) & 0 \\ sin(\theta) & cos(\theta) & 0 \\ 0 & 0 & 1 \end{bmatrix} \end{gathered}\] \[T_2= \begin{gathered} \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ x_s & y_s & 1 \end{bmatrix} \end{gathered}\] \[\begin{gathered} \begin{bmatrix} x_1 \\ y_1 \\ 1 \end{bmatrix} \end{gathered} = \begin{gathered} \begin{bmatrix} x_0 \\ y_0 \\ 1 \end{bmatrix} \end{gathered} \cdot T_1 \cdot R \cdot T_2\]Translation
\[\begin{gathered} \begin{bmatrix} x_1 \\ y_1 \\ 1 \end{bmatrix} \end{gathered} = \begin{gathered} \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ dx & dy & 1 \end{bmatrix} \end{gathered} \cdot \begin{gathered} \begin{bmatrix} x_0 \\ y_0 \\ 1 \end{bmatrix} \end{gathered}\]Zoom
\[\begin{gathered} \begin{bmatrix} x_1 \\ y_1 \\ 1 \end{bmatrix} \end{gathered} = \begin{gathered} \begin{bmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \end{bmatrix} \end{gathered} \cdot \begin{gathered} \begin{bmatrix} x_0 \\ y_0 \\ 1 \end{bmatrix} \end{gathered}\]Rust demo code
use ndarray::arr2;
fn main() {
zoom(10.0, 10.0, 1.2, 1.2);
}
fn zoom(x_0: f64, y_0: f64, s_x: f64, s_y: f64) {
let point = arr2(&[[x_0], [y_0], [1.0]]);
let s = arr2(&[
[s_x, 0.0, 0.0],
[0.0, s_y, 0.0],
[0.0, 0.0, 1.0],
]);
let new_point = s.dot(&point);
println!("{}", &new_point);
}
Finished dev [unoptimized + debuginfo] target(s) in 0.34s
Running `target/debug/two_d_cover`
[[12],
[12],
[1]]