Struct geo::algorithm::affine_ops::AffineTransform
source · [−]Expand description
A general affine transformation matrix, and associated operations.
Note that affine ops are already implemented on most geo-types
primitives, using this module.
Affine transforms using the same numeric type (e.g. CoordFloat
) can be composed,
and the result can be applied to geometries using e.g. MapCoords
. This allows the
efficient application of transforms: an arbitrary number of operations can be chained.
These are then composed, producing a final transformation matrix which is applied to the geometry coordinates.
AffineTransform
is a row-major matrix.
2D affine transforms require six matrix parameters:
[a, b, xoff, d, e, yoff]
these map onto the AffineTransform
rows as follows:
[[a, b, xoff],
[d, e, yoff],
[0, 0, 1]]
The equations for transforming coordinates (x, y) -> (x', y')
are given as follows:
x' = ax + by + xoff
y' = dx + ey + yoff
Usage
Two types of operation are provided: construction and mutation. Construction functions create a new transform
and are denoted by the use of the present tense: scale()
, translate()
, rotate()
, and skew()
.
Mutation methods add a transform to the existing AffineTransform
, and are denoted by the use of the past participle:
scaled()
, translated()
, rotated()
, and skewed()
.
Examples
Build up transforms by beginning with a constructor, then chaining mutation operations
use geo::{AffineOps, AffineTransform};
use geo::{line_string, BoundingRect, Point, LineString};
use approx::assert_relative_eq;
let ls: LineString = line_string![
(x: 0.0f64, y: 0.0f64),
(x: 0.0f64, y: 10.0f64),
];
let center = ls.bounding_rect().unwrap().center();
let transform = AffineTransform::skew(40.0, 40.0, center).rotated(45.0, center);
let skewed_rotated = ls.affine_transform(&transform);
assert_relative_eq!(skewed_rotated, line_string![
(x: 0.5688687f64, y: 4.4311312),
(x: -0.5688687, y: 5.5688687)
], max_relative = 1.0);
Implementations
sourceimpl<T: CoordNum> AffineTransform<T>
impl<T: CoordNum> AffineTransform<T>
sourcepub fn compose(&self, other: &Self) -> Self
pub fn compose(&self, other: &Self) -> Self
Create a new affine transformation by composing two AffineTransform
s.
This is a cumulative operation; the new transform is added to the existing transform.
sourcepub fn identity() -> Self
pub fn identity() -> Self
Create the identity matrix
The matrix is:
[[1, 0, 0],
[0, 1, 0],
[0, 0, 1]]
sourcepub fn is_identity(&self) -> bool
pub fn is_identity(&self) -> bool
Whether the transformation is equivalent to the identity matrix, that is, whether it’s application will be a a no-op.
use geo::AffineTransform;
let mut transform = AffineTransform::identity();
assert!(transform.is_identity());
// mutate the transform a bit
transform = transform.translated(1.0, 2.0);
assert!(!transform.is_identity());
// put it back
transform = transform.translated(-1.0, -2.0);
assert!(transform.is_identity());
sourcepub fn scale(xfact: T, yfact: T, origin: impl Into<Coordinate<T>>) -> Self
pub fn scale(xfact: T, yfact: T, origin: impl Into<Coordinate<T>>) -> Self
Create a new affine transform for scaling, scaled by factors along the x
and y
dimensions.
The point of origin is usually given as the 2D bounding box centre of the geometry, but
any coordinate may be specified.
Negative scale factors will mirror or reflect coordinates.
The matrix is:
[[xfact, 0, xoff],
[0, yfact, yoff],
[0, 0, 1]]
xoff = origin.x - (origin.x * xfact)
yoff = origin.y - (origin.y * yfact)
sourcepub fn scaled(self, xfact: T, yfact: T, origin: impl Into<Coordinate<T>>) -> Self
pub fn scaled(self, xfact: T, yfact: T, origin: impl Into<Coordinate<T>>) -> Self
Add an affine transform for scaling, scaled by factors along the x
and y
dimensions.
The point of origin is usually given as the 2D bounding box centre of the geometry, but
any coordinate may be specified.
Negative scale factors will mirror or reflect coordinates.
This is a cumulative operation; the new transform is added to the existing transform.
sourcepub fn translate(xoff: T, yoff: T) -> Self
pub fn translate(xoff: T, yoff: T) -> Self
Create an affine transform for translation, shifted by offsets along the x
and y
dimensions.
The matrix is:
[[1, 0, xoff],
[0, 1, yoff],
[0, 0, 1]]
sourcepub fn translated(self, xoff: T, yoff: T) -> Self
pub fn translated(self, xoff: T, yoff: T) -> Self
Add an affine transform for translation, shifted by offsets along the x
and y
dimensions
This is a cumulative operation; the new transform is added to the existing transform.
sourcepub fn apply(&self, coord: Coordinate<T>) -> Coordinate<T>
pub fn apply(&self, coord: Coordinate<T>) -> Coordinate<T>
Apply the current transform to a coordinate
sourceimpl<U: CoordFloat> AffineTransform<U>
impl<U: CoordFloat> AffineTransform<U>
sourcepub fn rotate(degrees: U, origin: impl Into<Coordinate<U>>) -> Self
pub fn rotate(degrees: U, origin: impl Into<Coordinate<U>>) -> Self
Create an affine transform for rotation, using an arbitrary point as its centre.
Note that this operation is only available for geometries with floating point coordinates.
angle
is given in degrees.
The matrix (angle denoted as theta) is:
[[cos_theta, -sin_theta, xoff],
[sin_theta, cos_theta, yoff],
[0, 0, 1]]
xoff = origin.x - (origin.x * cos(theta)) + (origin.y * sin(theta))
yoff = origin.y - (origin.x * sin(theta)) + (origin.y * cos(theta))
sourcepub fn rotated(self, angle: U, origin: impl Into<Coordinate<U>>) -> Self
pub fn rotated(self, angle: U, origin: impl Into<Coordinate<U>>) -> Self
Add an affine transform for rotation, using an arbitrary point as its centre.
Note that this operation is only available for geometries with floating point coordinates.
angle
is given in degrees.
This is a cumulative operation; the new transform is added to the existing transform.
sourcepub fn skew(xs: U, ys: U, origin: impl Into<Coordinate<U>>) -> Self
pub fn skew(xs: U, ys: U, origin: impl Into<Coordinate<U>>) -> Self
Create an affine transform for skewing.
Note that this operation is only available for geometries with floating point coordinates.
Geometries are sheared by angles along x (xs
) and y (ys
) dimensions.
The point of origin is usually given as the 2D bounding box centre of the geometry, but
any coordinate may be specified. Angles are given in degrees.
The matrix is:
[[1, tan(x), xoff],
[tan(y), 1, yoff],
[0, 0, 1]]
xoff = -origin.y * tan(xs)
yoff = -origin.x * tan(ys)
sourcepub fn skewed(self, xs: U, ys: U, origin: impl Into<Coordinate<U>>) -> Self
pub fn skewed(self, xs: U, ys: U, origin: impl Into<Coordinate<U>>) -> Self
Add an affine transform for skewing.
Note that this operation is only available for geometries with floating point coordinates.
Geometries are sheared by angles along x (xs
) and y (ys
) dimensions.
The point of origin is usually given as the 2D bounding box centre of the geometry, but
any coordinate may be specified. Angles are given in degrees.
This is a cumulative operation; the new transform is added to the existing transform.
Trait Implementations
sourceimpl<T: Clone + CoordNum> Clone for AffineTransform<T>
impl<T: Clone + CoordNum> Clone for AffineTransform<T>
sourcefn clone(&self) -> AffineTransform<T>
fn clone(&self) -> AffineTransform<T>
Returns a copy of the value. Read more
1.0.0 · sourcefn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source
. Read more
sourceimpl<T: CoordNum> Debug for AffineTransform<T>
impl<T: CoordNum> Debug for AffineTransform<T>
sourceimpl<T: CoordNum> Default for AffineTransform<T>
impl<T: CoordNum> Default for AffineTransform<T>
sourceimpl<T: CoordNum> From<(T, T, T, T, T, T)> for AffineTransform<T>
impl<T: CoordNum> From<(T, T, T, T, T, T)> for AffineTransform<T>
sourcefn from(tup: (T, T, T, T, T, T)) -> Self
fn from(tup: (T, T, T, T, T, T)) -> Self
Converts to this type from the input type.
sourceimpl<T: PartialEq + CoordNum> PartialEq<AffineTransform<T>> for AffineTransform<T>
impl<T: PartialEq + CoordNum> PartialEq<AffineTransform<T>> for AffineTransform<T>
sourcefn eq(&self, other: &AffineTransform<T>) -> bool
fn eq(&self, other: &AffineTransform<T>) -> bool
This method tests for self
and other
values to be equal, and is used
by ==
. Read more
impl<T: Copy + CoordNum> Copy for AffineTransform<T>
impl<T: Eq + CoordNum> Eq for AffineTransform<T>
impl<T: CoordNum> StructuralEq for AffineTransform<T>
impl<T: CoordNum> StructuralPartialEq for AffineTransform<T>
Auto Trait Implementations
impl<T> RefUnwindSafe for AffineTransform<T> where
T: RefUnwindSafe,
impl<T> Send for AffineTransform<T> where
T: Send,
impl<T> Sync for AffineTransform<T> where
T: Sync,
impl<T> Unpin for AffineTransform<T> where
T: Unpin,
impl<T> UnwindSafe for AffineTransform<T> where
T: UnwindSafe,
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more