Source code for pdftools_toolbox.geometry.real.affine_transform
from __future__ import annotations
import io
from typing import List, Iterator, Tuple, Optional, Any, TYPE_CHECKING, Callable
from ctypes import *
from datetime import datetime
from numbers import Number
from pdftools_toolbox.internal import _lib
from pdftools_toolbox.internal.utils import _string_to_utf16, _utf16_to_string
from pdftools_toolbox.internal.streams import _StreamDescriptor, _NativeStream
from pdftools_toolbox.internal.native_base import _NativeBase
import pdftools_toolbox.internal
if TYPE_CHECKING:
from pdftools_toolbox.geometry.real.point import Point
from pdftools_toolbox.geometry.real.rectangle import Rectangle
from pdftools_toolbox.geometry.real.quadrilateral import Quadrilateral
else:
Point = "pdftools_toolbox.geometry.real.point.Point"
Rectangle = "pdftools_toolbox.geometry.real.rectangle.Rectangle"
Quadrilateral = "pdftools_toolbox.geometry.real.quadrilateral.Quadrilateral"
[docs]
class AffineTransform(Structure):
"""
Attributes:
a (c_double):
This is the 'a' element in the affine transformation matrix [a b 0; c d 0; e f 1]
b (c_double):
This is the 'b' element in the affine transformation matrix [a b 0; c d 0; e f 1]
c (c_double):
This is the 'c' element in the affine transformation matrix [a b 0; c d 0; e f 1]
d (c_double):
This is the 'd' element in the affine transformation matrix [a b 0; c d 0; e f 1]
e (c_double):
This is the 'e' element in the affine transformation matrix [a b 0; c d 0; e f 1]
f (c_double):
This is the 'f' element in the affine transformation matrix [a b 0; c d 0; e f 1]
"""
_fields_ = [
("a", c_double),
("b", c_double),
("c", c_double),
("d", c_double),
("e", c_double),
("f", c_double),
]
[docs]
def translate(self, tx: float, ty: float) -> None:
"""
Translate.
Translations are specified as [1 0 0 1 tx ty],
where tx and ty are the distances to translate the origin of the
coordinate system in the horizontal and vertical dimensions, respectively.
Args:
tx (float):
horizontal translation
ty (float):
vertical translation
Raises:
StateError:
If the affine transform is singular, e.g. default initialized.
(Use :attr:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.identity` as an initial value.)
"""
if not isinstance(tx, Number):
raise TypeError(f"Expected type {Number.__name__}, but got {type(tx).__name__}.")
if not isinstance(ty, Number):
raise TypeError(f"Expected type {Number.__name__}, but got {type(ty).__name__}.")
_lib.PtxGeomReal_AffineTransform_Translate.argtypes = [POINTER(AffineTransform), c_double, c_double]
_lib.PtxGeomReal_AffineTransform_Translate.restype = c_bool
if not _lib.PtxGeomReal_AffineTransform_Translate(byref(self), tx, ty):
_NativeBase._throw_last_error(False)
[docs]
def scale(self, sx: float, sy: float) -> None:
"""
Scale.
Scaling is obtained by [sx 0 0 sy 0 0].
This scales the coordinates so that 1 unit in the horizontal and vertical dimensions
of the new coordinate system is the same size as sx and sy units,
respectively, in the previous coordinate system.
Args:
sx (float):
horizontal scale factor
sy (float):
vertical scale factor
Raises:
StateError:
If the affine transform is singular, e.g. default initialized.
(Use :attr:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.identity` as an initial value.)
"""
if not isinstance(sx, Number):
raise TypeError(f"Expected type {Number.__name__}, but got {type(sx).__name__}.")
if not isinstance(sy, Number):
raise TypeError(f"Expected type {Number.__name__}, but got {type(sy).__name__}.")
_lib.PtxGeomReal_AffineTransform_Scale.argtypes = [POINTER(AffineTransform), c_double, c_double]
_lib.PtxGeomReal_AffineTransform_Scale.restype = c_bool
if not _lib.PtxGeomReal_AffineTransform_Scale(byref(self), sx, sy):
_NativeBase._throw_last_error(False)
[docs]
def rotate(self, angle: float, center: Optional[Point]) -> None:
"""
Rotate.
Rotations are produced by [cos(a) sin(a) -sin(a) cos(a) 0 0],
which has the effect of rotating the coordinate system axes
by an angle "a" in counterclockwise direction around the origin.
If the given `center` is not `None`,
then the rotation is performed around the given center point,
which is equivalent to the following sequence:
- :meth:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.translate` to `center`.
- :meth:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.rotate` by `angle` around the origin.
- :meth:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.translate` "back" to the original origin.
Args:
angle (float):
The angle of the rotation in degrees.
center (Optional[pdftools_toolbox.geometry.real.point.Point]):
The center of the rotation.
If `None` then the origin (0/0) is taken as center.
Raises:
StateError:
If the affine transform is singular, e.g. default initialized.
(Use :attr:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.identity` as an initial value.)
"""
from pdftools_toolbox.geometry.real.point import Point
if not isinstance(angle, Number):
raise TypeError(f"Expected type {Number.__name__}, but got {type(angle).__name__}.")
if center is not None and not isinstance(center, Point):
raise TypeError(f"Expected type {Point.__name__} or None, but got {type(center).__name__}.")
_lib.PtxGeomReal_AffineTransform_Rotate.argtypes = [POINTER(AffineTransform), c_double, POINTER(Point)]
_lib.PtxGeomReal_AffineTransform_Rotate.restype = c_bool
if not _lib.PtxGeomReal_AffineTransform_Rotate(byref(self), angle, center):
_NativeBase._throw_last_error(False)
[docs]
def skew(self, alpha: float, beta: float) -> None:
"""
Skew.
Skew is specified by [1 tan a tan b 1 0 0],
which skews the x axis by an angle a and the y axis by an angle b.
Args:
alpha (float):
angle a in degrees
beta (float):
angle b in degrees
Raises:
StateError:
If the affine transform is singular, e.g. default initialized.
(Use :attr:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.identity` as an initial value.)
ValueError:
if any of the given angles is too close to 90 + k*180 degrees for k = ..., -2, -1, 0, 1, 2, ...
"""
if not isinstance(alpha, Number):
raise TypeError(f"Expected type {Number.__name__}, but got {type(alpha).__name__}.")
if not isinstance(beta, Number):
raise TypeError(f"Expected type {Number.__name__}, but got {type(beta).__name__}.")
_lib.PtxGeomReal_AffineTransform_Skew.argtypes = [POINTER(AffineTransform), c_double, c_double]
_lib.PtxGeomReal_AffineTransform_Skew.restype = c_bool
if not _lib.PtxGeomReal_AffineTransform_Skew(byref(self), alpha, beta):
_NativeBase._throw_last_error(False)
[docs]
def concatenate(self, other: AffineTransform) -> None:
"""
Concatenate transform with other transform.
Concatenating a transform with an other transform is equivalent to left-multiplying the transform's matrix with with the other transform's matrix.
Args:
other (pdftools_toolbox.geometry.real.affine_transform.AffineTransform):
the transform to be concatenated to this transform
Raises:
StateError:
If the affine transform is singular, e.g. default initialized.
(Use :attr:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.identity` as an initial value.)
ValueError:
If the `other` affine transform is singular, e.g. default initialized.
(Use :attr:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.identity` as an initial value.)
"""
if not isinstance(other, AffineTransform):
raise TypeError(f"Expected type {AffineTransform.__name__}, but got {type(other).__name__}.")
_lib.PtxGeomReal_AffineTransform_Concatenate.argtypes = [POINTER(AffineTransform), POINTER(AffineTransform)]
_lib.PtxGeomReal_AffineTransform_Concatenate.restype = c_bool
if not _lib.PtxGeomReal_AffineTransform_Concatenate(byref(self), other):
_NativeBase._throw_last_error(False)
[docs]
def invert(self) -> None:
"""
Invert the transform
A transform usually maps from the transformed coordinate system to the untransformed coordinate system.
Use this method to create the reverse transform.
Raises:
StateError:
If the affine transform is singular, e.g. default initialized.
(Use :attr:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.identity` as an initial value.)
"""
_lib.PtxGeomReal_AffineTransform_Invert.argtypes = [POINTER(AffineTransform)]
_lib.PtxGeomReal_AffineTransform_Invert.restype = c_bool
if not _lib.PtxGeomReal_AffineTransform_Invert(byref(self)):
_NativeBase._throw_last_error(False)
[docs]
def transform_point(self, original: Point) -> Point:
"""
Transforms the given point.
Args:
original (pdftools_toolbox.geometry.real.point.Point):
the point to be transformed
Returns:
pdftools_toolbox.geometry.real.point.Point:
the transformed point
Raises:
StateError:
If the affine transform is singular, e.g. default initialized.
(Use :attr:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.identity` as an initial value.)
"""
from pdftools_toolbox.geometry.real.point import Point
if not isinstance(original, Point):
raise TypeError(f"Expected type {Point.__name__}, but got {type(original).__name__}.")
_lib.PtxGeomReal_AffineTransform_TransformPoint.argtypes = [POINTER(AffineTransform), POINTER(Point), POINTER(Point)]
_lib.PtxGeomReal_AffineTransform_TransformPoint.restype = c_bool
ret_val = Point()
if not _lib.PtxGeomReal_AffineTransform_TransformPoint(byref(self), original, byref(ret_val)):
_NativeBase._throw_last_error(False)
return ret_val
[docs]
def transform_rectangle(self, original: Rectangle) -> Quadrilateral:
"""
Transform the given rectangle
For a general affine transformation, the returned :class:`pdftools_toolbox.geometry.real.quadrilateral.Quadrilateral` is a parallelogram.
Args:
original (pdftools_toolbox.geometry.real.rectangle.Rectangle):
the rectangle to be transformed
Returns:
pdftools_toolbox.geometry.real.quadrilateral.Quadrilateral:
the transformed rectangle. For a general affine transform this is a parallelogram.
Raises:
StateError:
if the affine transform is singular, e.g. default initialized.
(Use :attr:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.identity` as an initial value.)
"""
from pdftools_toolbox.geometry.real.rectangle import Rectangle
from pdftools_toolbox.geometry.real.quadrilateral import Quadrilateral
if not isinstance(original, Rectangle):
raise TypeError(f"Expected type {Rectangle.__name__}, but got {type(original).__name__}.")
_lib.PtxGeomReal_AffineTransform_TransformRectangle.argtypes = [POINTER(AffineTransform), POINTER(Rectangle), POINTER(Quadrilateral)]
_lib.PtxGeomReal_AffineTransform_TransformRectangle.restype = c_bool
ret_val = Quadrilateral()
if not _lib.PtxGeomReal_AffineTransform_TransformRectangle(byref(self), original, byref(ret_val)):
_NativeBase._throw_last_error(False)
return ret_val
[docs]
def transform_quadrilateral(self, original: Quadrilateral) -> Quadrilateral:
"""
Transform a given quadrilateral
If the input quadrilateral is a parallelogram, then the output is also a parallelogram.
Args:
original (pdftools_toolbox.geometry.real.quadrilateral.Quadrilateral):
the quadrilateral to be transformed
Returns:
pdftools_toolbox.geometry.real.quadrilateral.Quadrilateral:
the transformed quadrilateral. If the input is a parallelogram then the output is also a parallelogram.
Raises:
StateError:
if the affine transform is singular, e.g. default initialized.
(Use :attr:`pdftools_toolbox.geometry.real.affine_transform.AffineTransform.identity` as an initial value.)
"""
from pdftools_toolbox.geometry.real.quadrilateral import Quadrilateral
if not isinstance(original, Quadrilateral):
raise TypeError(f"Expected type {Quadrilateral.__name__}, but got {type(original).__name__}.")
_lib.PtxGeomReal_AffineTransform_TransformQuadrilateral.argtypes = [POINTER(AffineTransform), POINTER(Quadrilateral), POINTER(Quadrilateral)]
_lib.PtxGeomReal_AffineTransform_TransformQuadrilateral.restype = c_bool
ret_val = Quadrilateral()
if not _lib.PtxGeomReal_AffineTransform_TransformQuadrilateral(byref(self), original, byref(ret_val)):
_NativeBase._throw_last_error(False)
return ret_val
[docs]
@staticmethod
def get_identity() -> AffineTransform:
"""
The identity transform
Returns:
pdftools_toolbox.geometry.real.affine_transform.AffineTransform
"""
_lib.PtxGeomReal_AffineTransform_GetIdentity.argtypes = [POINTER(AffineTransform)]
_lib.PtxGeomReal_AffineTransform_GetIdentity.restype = c_bool
ret_val = AffineTransform()
if not _lib.PtxGeomReal_AffineTransform_GetIdentity(byref(ret_val)):
_NativeBase._throw_last_error(False)
return ret_val