pub struct AffineTransform<T: CoordNum = f64>(/* private fields */);
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::{point, line_string, BoundingRect};
use approx::assert_relative_eq;
let line_string = line_string![(x: 0.0, y: 0.0),(x: 1.0, y: 1.0)];
let transform = AffineTransform::translate(1.0, 1.0).scaled(2.0, 2.0, point!(x: 0.0, y: 0.0));
let transformed_line_string = line_string.affine_transform(&transform);
assert_relative_eq!(
transformed_line_string,
line_string![(x: 2.0, y: 2.0),(x: 4.0, y: 4.0)]
);
§Create affine transform manually, and access elements using getter methods
use geo::AffineTransform;
let transform = AffineTransform::new(10.0, 0.0, 400_000.0, 0.0, -10.0, 500_000.0);
let a: f64 = transform.a();
let b: f64 = transform.b();
let xoff: f64 = transform.xoff();
let d: f64 = transform.d();
let e: f64 = transform.e();
let yoff: f64 = transform.yoff();
assert_eq!(transform, AffineTransform::new(a, b, xoff, d, e, yoff))
Implementations§
Source§impl<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 compose_many(&self, transforms: &[Self]) -> Self
pub fn compose_many(&self, transforms: &[Self]) -> Self
Create a new affine transformation by composing an arbitrary number of AffineTransform
s.
This is a cumulative operation; the new transform is added to the existing transform.
use geo::AffineTransform;
let mut transform = AffineTransform::identity();
// create two transforms that cancel each other
let transform1 = AffineTransform::translate(1.0, 2.0);
let transform2 = AffineTransform::translate(-1.0, -2.0);
let transforms = vec![transform1, transform2];
// apply them
let outcome = transform.compose_many(&transforms);
// we should be back to square one
assert!(outcome.is_identity());
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<Coord<T>>) -> Self
pub fn scale(xfact: T, yfact: T, origin: impl Into<Coord<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<Coord<T>>) -> Self
pub fn scaled(self, xfact: T, yfact: T, origin: impl Into<Coord<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 new(a: T, b: T, xoff: T, d: T, e: T, yoff: T) -> Self
pub fn new(a: T, b: T, xoff: T, d: T, e: T, yoff: T) -> Self
Create a new custom transform matrix
The argument order matches that of the affine transform matrix:
[[a, b, xoff],
[d, e, yoff],
[0, 0, 1]] <-- not part of the input arguments
Sourcepub fn a(&self) -> T
pub fn a(&self) -> T
See AffineTransform::new for this value’s role in the affine transformation.
Sourcepub fn b(&self) -> T
pub fn b(&self) -> T
See AffineTransform::new for this value’s role in the affine transformation.
Sourcepub fn xoff(&self) -> T
pub fn xoff(&self) -> T
See AffineTransform::new for this value’s role in the affine transformation.
Sourcepub fn d(&self) -> T
pub fn d(&self) -> T
See AffineTransform::new for this value’s role in the affine transformation.
Sourcepub fn e(&self) -> T
pub fn e(&self) -> T
See AffineTransform::new for this value’s role in the affine transformation.
Sourcepub fn yoff(&self) -> T
pub fn yoff(&self) -> T
See AffineTransform::new for this value’s role in the affine transformation.
Source§impl<T: CoordNum + Neg> AffineTransform<T>
impl<T: CoordNum + Neg> AffineTransform<T>
Source§impl<U: CoordFloat> AffineTransform<U>
impl<U: CoordFloat> AffineTransform<U>
Sourcepub fn rotate(degrees: U, origin: impl Into<Coord<U>>) -> Self
pub fn rotate(degrees: U, origin: impl Into<Coord<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<Coord<U>>) -> Self
pub fn rotated(self, angle: U, origin: impl Into<Coord<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<Coord<U>>) -> Self
pub fn skew(xs: U, ys: U, origin: impl Into<Coord<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<Coord<U>>) -> Self
pub fn skewed(self, xs: U, ys: U, origin: impl Into<Coord<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§
Source§impl<T: Clone + CoordNum> Clone for AffineTransform<T>
impl<T: Clone + CoordNum> Clone for AffineTransform<T>
Source§fn clone(&self) -> AffineTransform<T>
fn clone(&self) -> AffineTransform<T>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moreSource§impl<T: CoordNum> Debug for AffineTransform<T>
impl<T: CoordNum> Debug for AffineTransform<T>
Source§impl<T: CoordNum> Default for AffineTransform<T>
impl<T: CoordNum> Default for AffineTransform<T>
Source§impl<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>
Source§fn from(tup: (T, T, T, T, T, T)) -> Self
fn from(tup: (T, T, T, T, T, T)) -> Self
impl<T: Copy + CoordNum> Copy for AffineTransform<T>
impl<T: Eq + CoordNum> Eq for AffineTransform<T>
impl<T: CoordNum> StructuralPartialEq for AffineTransform<T>
Auto Trait Implementations§
impl<T> Freeze for AffineTransform<T>where
T: Freeze,
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§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more