Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-affine for openSUSE:Factory checked in at 2022-09-27 20:13:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-affine (Old) and /work/SRC/openSUSE:Factory/.python-affine.new.2275 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-affine" Tue Sep 27 20:13:46 2022 rev:5 rq:1006323 version:2.3.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-affine/python-affine.changes 2022-01-17 22:34:50.974275663 +0100 +++ /work/SRC/openSUSE:Factory/.python-affine.new.2275/python-affine.changes 2022-09-27 20:13:50.309814817 +0200 @@ -1,0 +2,7 @@ +Sat Sep 24 10:30:37 UTC 2022 - Dirk M??ller <[email protected]> + +- update to 2.3.1: + * Return NotImplemented for both ValueError and TypeError in __mul__ to + support fallback to __rmul__ in more cases (gh-71). + +------------------------------------------------------------------- Old: ---- affine-2.3.0.tar.gz New: ---- affine-2.3.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-affine.spec ++++++ --- /var/tmp/diff_new_pack.RRbYIV/_old 2022-09-27 20:13:50.945816220 +0200 +++ /var/tmp/diff_new_pack.RRbYIV/_new 2022-09-27 20:13:50.949816228 +0200 @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-affine -Version: 2.3.0 +Version: 2.3.1 Release: 0 Summary: Affine transformation matrices License: BSD-3-Clause ++++++ affine-2.3.0.tar.gz -> affine-2.3.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/affine-2.3.0/CHANGES.txt new/affine-2.3.1/CHANGES.txt --- old/affine-2.3.0/CHANGES.txt 2019-09-05 00:22:41.000000000 +0200 +++ new/affine-2.3.1/CHANGES.txt 2022-03-25 03:34:49.000000000 +0100 @@ -1,6 +1,14 @@ CHANGES ======= +2.3.1 (2022-03-24) +------------------ + +Bug fixes: + +- Return NotImplemented for both ValueError and TypeError in __mul__ to support + fallback to __rmul__ in more cases (gh-71). + 2.3.0 (2019-09-04) ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/affine-2.3.0/PKG-INFO new/affine-2.3.1/PKG-INFO --- old/affine-2.3.0/PKG-INFO 2019-09-05 00:23:11.000000000 +0200 +++ new/affine-2.3.1/PKG-INFO 2022-03-25 03:38:10.509298000 +0100 @@ -1,109 +1,113 @@ Metadata-Version: 2.1 Name: affine -Version: 2.3.0 +Version: 2.3.1 Summary: Matrices describing affine transformation of the plane. Home-page: https://github.com/sgillies/affine Author: Sean Gillies Author-email: [email protected] License: BSD -Description: Affine - ====== - - Matrices describing affine transformation of the plane. - - .. image:: https://travis-ci.org/sgillies/affine.svg?branch=master - :target: https://travis-ci.org/sgillies/affine - - .. image:: https://coveralls.io/repos/sgillies/affine/badge.svg - :target: https://coveralls.io/r/sgillies/affine - - The Affine package is derived from Casey Duncan's Planar package. Please see - the copyright statement in `affine/__init__.py <affine/__init__.py>`__. - - Usage - ----- - - The 3x3 augmented affine transformation matrix for transformations in two - dimensions is illustrated below. - - .. :: - - | x' | | a b c | | x | - | y' | = | d e f | | y | - | 1 | | 0 0 1 | | 1 | - - Matrices can be created by passing the values ``a, b, c, d, e, f`` to the - ``affine.Affine`` constructor or by using its ``identity()``, - ``translation()``, ``scale()``, ``shear()``, and ``rotation()`` class methods. - - .. code-block:: pycon - - >>> from affine import Affine - >>> Affine.identity() - Affine(1.0, 0.0, 0.0, - 0.0, 1.0, 0.0) - >>> Affine.translation(1.0, 5.0) - Affine(1.0, 0.0, 1.0, - 0.0, 1.0, 5.0) - >>> Affine.scale(2.0) - Affine(2.0, 0.0, 0.0, - 0.0, 2.0, 0.0) - >>> Affine.shear(45.0, 45.0) # decimal degrees - Affine(1.0, 0.9999999999999999, 0.0, - 0.9999999999999999, 1.0, 0.0) - >>> Affine.rotation(45.0) # decimal degrees - Affine(0.7071067811865476, -0.7071067811865475, 0.0, - 0.7071067811865475, 0.7071067811865476, 0.0) - - These matrices can be applied to ``(x, y)`` tuples to obtain transformed - coordinates ``(x', y')``. - - .. code-block:: pycon - - >>> Affine.translation(1.0, 5.0) * (1.0, 1.0) - (2.0, 6.0) - >>> Affine.rotation(45.0) * (1.0, 1.0) - (1.1102230246251565e-16, 1.414213562373095) - - They may also be multiplied together to combine transformations. - - .. code-block:: pycon - - >>> Affine.translation(1.0, 5.0) * Affine.rotation(45.0) - Affine(0.7071067811865476, -0.7071067811865475, 1.0, - 0.7071067811865475, 0.7071067811865476, 5.0) - - Usage with GIS data packages - ---------------------------- - - Georeferenced raster datasets use affine transformations to map from image - coordinates to world coordinates. The ``affine.Affine.from_gdal()`` class - method helps convert `GDAL GeoTransform - <http://www.gdal.org/classGDALDataset.html#af9593cc241e7d140f5f3c4798a43a668>`__, - sequences of 6 numbers in which the first and fourth are the x and y offsets - and the second and sixth are the x and y pixel sizes. - - Using a GDAL dataset transformation matrix, the world coordinates ``(x, y)`` - corresponding to the top left corner of the pixel 100 rows down from the - origin can be easily computed. - - .. code-block:: pycon - - >>> geotransform = (-237481.5, 425.0, 0.0, 237536.4, 0.0, -425.0) - >>> fwd = Affine.from_gdal(*geotransform) - >>> col, row = 0, 100 - >>> fwd * (col, row) - (-237481.5, 195036.4) - - The reverse transformation is obtained using the ``~`` operator. - - .. code-block:: pycon - - >>> rev = ~fwd - >>> rev * fwd * (col, row) - (0.0, 99.99999999999999) - - Keywords: affine transformation matrix Platform: UNKNOWN Provides-Extra: test +License-File: LICENSE.txt +License-File: AUTHORS.txt + +Affine +====== + +Matrices describing affine transformation of the plane. + +.. image:: https://travis-ci.org/sgillies/affine.svg?branch=master + :target: https://travis-ci.org/sgillies/affine + +.. image:: https://coveralls.io/repos/sgillies/affine/badge.svg + :target: https://coveralls.io/r/sgillies/affine + +The Affine package is derived from Casey Duncan's Planar package. Please see +the copyright statement in `affine/__init__.py <affine/__init__.py>`__. + +Usage +----- + +The 3x3 augmented affine transformation matrix for transformations in two +dimensions is illustrated below. + +:: + + | x' | | a b c | | x | + | y' | = | d e f | | y | + | 1 | | 0 0 1 | | 1 | + +Matrices can be created by passing the values ``a, b, c, d, e, f`` to the +``affine.Affine`` constructor or by using its ``identity()``, +``translation()``, ``scale()``, ``shear()``, and ``rotation()`` class methods. + +.. code-block:: pycon + + >>> from affine import Affine + >>> Affine.identity() + Affine(1.0, 0.0, 0.0, + 0.0, 1.0, 0.0) + >>> Affine.translation(1.0, 5.0) + Affine(1.0, 0.0, 1.0, + 0.0, 1.0, 5.0) + >>> Affine.scale(2.0) + Affine(2.0, 0.0, 0.0, + 0.0, 2.0, 0.0) + >>> Affine.shear(45.0, 45.0) # decimal degrees + Affine(1.0, 0.9999999999999999, 0.0, + 0.9999999999999999, 1.0, 0.0) + >>> Affine.rotation(45.0) # decimal degrees + Affine(0.7071067811865476, -0.7071067811865475, 0.0, + 0.7071067811865475, 0.7071067811865476, 0.0) + +These matrices can be applied to ``(x, y)`` tuples to obtain transformed +coordinates ``(x', y')``. + +.. code-block:: pycon + + >>> Affine.translation(1.0, 5.0) * (1.0, 1.0) + (2.0, 6.0) + >>> Affine.rotation(45.0) * (1.0, 1.0) + (1.1102230246251565e-16, 1.414213562373095) + +They may also be multiplied together to combine transformations. + +.. code-block:: pycon + + >>> Affine.translation(1.0, 5.0) * Affine.rotation(45.0) + Affine(0.7071067811865476, -0.7071067811865475, 1.0, + 0.7071067811865475, 0.7071067811865476, 5.0) + +Usage with GIS data packages +---------------------------- + +Georeferenced raster datasets use affine transformations to map from image +coordinates to world coordinates. The ``affine.Affine.from_gdal()`` class +method helps convert `GDAL GeoTransform +<https://gdal.org/user/raster_data_model.html#affine-geotransform>`__, +sequences of 6 numbers in which the first and fourth are the x and y offsets +and the second and sixth are the x and y pixel sizes. + +Using a GDAL dataset transformation matrix, the world coordinates ``(x, y)`` +corresponding to the top left corner of the pixel 100 rows down from the +origin can be easily computed. + +.. code-block:: pycon + + >>> geotransform = (-237481.5, 425.0, 0.0, 237536.4, 0.0, -425.0) + >>> fwd = Affine.from_gdal(*geotransform) + >>> col, row = 0, 100 + >>> fwd * (col, row) + (-237481.5, 195036.4) + +The reverse transformation is obtained using the ``~`` operator. + +.. code-block:: pycon + + >>> rev = ~fwd + >>> rev * fwd * (col, row) + (0.0, 99.99999999999999) + + + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/affine-2.3.0/README.rst new/affine-2.3.1/README.rst --- old/affine-2.3.0/README.rst 2019-09-05 00:22:41.000000000 +0200 +++ new/affine-2.3.1/README.rst 2022-03-23 14:29:19.000000000 +0100 @@ -18,7 +18,7 @@ The 3x3 augmented affine transformation matrix for transformations in two dimensions is illustrated below. -.. :: +:: | x' | | a b c | | x | | y' | = | d e f | | y | @@ -71,7 +71,7 @@ Georeferenced raster datasets use affine transformations to map from image coordinates to world coordinates. The ``affine.Affine.from_gdal()`` class method helps convert `GDAL GeoTransform -<http://www.gdal.org/classGDALDataset.html#af9593cc241e7d140f5f3c4798a43a668>`__, +<https://gdal.org/user/raster_data_model.html#affine-geotransform>`__, sequences of 6 numbers in which the first and fourth are the x and y offsets and the second and sixth are the x and y pixel sizes. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/affine-2.3.0/affine/__init__.py new/affine-2.3.1/affine/__init__.py --- old/affine-2.3.0/affine/__init__.py 2019-09-05 00:22:41.000000000 +0200 +++ new/affine-2.3.1/affine/__init__.py 2022-03-25 03:35:14.000000000 +0100 @@ -41,7 +41,7 @@ __all__ = ['Affine'] __author__ = "Sean Gillies" -__version__ = "2.3.0" +__version__ = "2.3.1" EPSILON = 1e-5 @@ -311,6 +311,16 @@ """ return (self.c, self.a, self.b, self.f, self.d, self.e) + def to_shapely(self): + """Return an affine transformation matrix compatible with shapely + + Shapely's affinity module expects an affine transformation matrix + in (a,b,d,e,xoff,yoff) order. + + :rtype: tuple + """ + return (self.a, self.b, self.d, self.e, self.xoff, self.yoff) + @property def xoff(self): """Alias for 'c'""" @@ -374,7 +384,7 @@ assuming it is in the form M = R S, where R is a rotation and S is a scaling. - Raises NotImplementedError for improper transformations. + Raises UndefinedRotationError for improper and degenerate transformations. """ a, b, _, c, d, _, _, _, _ = self if self.is_proper or self.is_degenerate: @@ -501,9 +511,9 @@ else: try: vx, vy = other - except Exception: + return (vx * sa + vy * sb + sc, vx * sd + vy * se + sf) + except (ValueError, TypeError): return NotImplemented - return (vx * sa + vy * sb + sc, vx * sd + vy * se + sf) def __rmul__(self, other): """Right hand multiplication @@ -518,7 +528,8 @@ just a guarantee, since we would potentially return the wrong answer in that case. """ - warnings.warn("Right multiplication will be prohibited in version 3.0", DeprecationWarning, stacklevel=2) + warnings.warn("Right multiplication will be prohibited in version 3.0", + DeprecationWarning, stacklevel=2) assert not isinstance(other, Affine) return self.__mul__(other) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/affine-2.3.0/affine/tests/test_transform.py new/affine-2.3.1/affine/tests/test_transform.py --- old/affine-2.3.0/affine/tests/test_transform.py 2019-09-05 00:22:41.000000000 +0200 +++ new/affine-2.3.1/affine/tests/test_transform.py 2022-03-25 03:34:49.000000000 +0100 @@ -30,10 +30,9 @@ from __future__ import division -import os import math import unittest -import textwrap +from textwrap import dedent import pytest @@ -101,14 +100,17 @@ t['foobar'] def test_str(self): - assert \ - str(Affine(1.111, 2.222, 3.333, -4.444, -5.555, 6.666)) \ - == "| 1.11, 2.22, 3.33|\n|-4.44,-5.55, 6.67|\n| 0.00, 0.00, 1.00|" + t = Affine(1.111, 2.222, 3.333, -4.444, -5.555, 6.666) + assert str(t) == dedent("""\ + | 1.11, 2.22, 3.33| + |-4.44,-5.55, 6.67| + | 0.00, 0.00, 1.00|""") def test_repr(self): - assert \ - repr(Affine(1.111, 2.222, 3.456, 4.444, 5.5, 6.25)) == \ - os.linesep.join(["Affine(1.111, 2.222, 3.456,", " 4.444, 5.5, 6.25)"]) + t = Affine(1.111, 2.222, 3.456, 4.444, 5.5, 6.25) + assert repr(t) == dedent("""\ + Affine(1.111, 2.222, 3.456, + 4.444, 5.5, 6.25)""") def test_identity_constructor(self): ident = Affine.identity() @@ -128,8 +130,8 @@ (0, 1, 0, 1, 0, 0, 0, 0, 1) - assert (perm*perm).is_identity - + assert (perm*perm).is_identity + def test_translation_constructor(self): trans = Affine.translation(2, -5) assert isinstance(trans, Affine) @@ -247,7 +249,8 @@ 0, 0, 1) def test_rotation_constructor_with_pivot(self): - assert tuple(Affine.rotation(60)) == tuple(Affine.rotation(60, pivot=(0, 0))) + assert tuple(Affine.rotation(60)) == \ + tuple(Affine.rotation(60, pivot=(0, 0))) rot = Affine.rotation(27, pivot=(2, -4)) r = math.radians(27) s, c = math.sin(r), math.cos(r) @@ -452,7 +455,7 @@ assert affine.dumpsw(a) == s def test_real_world(self): - s = textwrap.dedent('''\ + s = dedent('''\ 39.9317755024 30.0907511581 30.0907511576 @@ -481,10 +484,15 @@ assert t.f == t.yoff == 237536.4 assert t.d == 0.0 assert t.e == -425.0 - assert tuple(t) == (425.0, 0.0, -237481.5, 0.0, -425.0, 237536.4, 0, 0, 1.0) + assert tuple(t) == (425.0, 0.0, -237481.5, 0.0, -425.0, 237536.4, 0, 0, 1) assert t.to_gdal() == (-237481.5, 425.0, 0.0, 237536.4, 0.0, -425.0) +def test_shapely(): + t = Affine(425.0, 0.0, -237481.5, 0.0, -425.0, 237536.4) + assert t.to_shapely() == (425.0, 0.0, 0.0, -425, -237481.5, 237536.4) + + def test_imul_number(): t = Affine(1, 2, 3, 4, 5, 6) try: @@ -534,7 +542,7 @@ def test_eccentricity(): assert Affine.identity().eccentricity == 0.0 assert Affine.scale(2).eccentricity == 0.0 - #assert_equal(Affine.scale(0).eccentricity, ?) + # assert_equal(Affine.scale(0).eccentricity, ?) assert Affine.scale(2, 1).eccentricity == pytest.approx(math.sqrt(3) / 2) assert Affine.scale(2, 3).eccentricity == pytest.approx(math.sqrt(5) / 3) assert Affine.scale(1, 0).eccentricity == 1.0 @@ -551,7 +559,9 @@ (Affine.rotation(77) * Affine.scale(2, 3)).eccentricity == \ pytest.approx(math.sqrt(5) / 3) assert \ - (Affine.translation(32, -47) * Affine.rotation(77) * Affine.scale(2, 3)).eccentricity == \ + (Affine.translation(32, -47) * + Affine.rotation(77) * + Affine.scale(2, 3)).eccentricity == \ pytest.approx(math.sqrt(5) / 3) @@ -569,5 +579,32 @@ Affine.scale(-1, 1).rotation_angle +# See gh-71 for bug report motivating this test. +def test_mul_fallback_unpack(): + """Support fallback in case that other is a single object.""" + + class TextPoint: + """Not iterable, will trigger ValueError in Affine.__mul__.""" + def __rmul__(self, other): + return other * (1, 2) + + assert Affine.identity() * TextPoint() == (1, 2) + + +# See gh-71 for bug report motivating this test. +def test_mul_fallback_type_error(): + """Support fallback in case that other is an unexpected type.""" + + class TextPoint: + """Iterable, but values trigger TypeError in Affine.__mul__.""" + def __iter__(self): + return ("1", "2") + + def __rmul__(self, other): + return other * (1, 2) + + assert Affine.identity() * TextPoint() == (1, 2) + + if __name__ == '__main__': unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/affine-2.3.0/affine.egg-info/PKG-INFO new/affine-2.3.1/affine.egg-info/PKG-INFO --- old/affine-2.3.0/affine.egg-info/PKG-INFO 2019-09-05 00:23:11.000000000 +0200 +++ new/affine-2.3.1/affine.egg-info/PKG-INFO 2022-03-25 03:38:10.000000000 +0100 @@ -1,109 +1,113 @@ Metadata-Version: 2.1 Name: affine -Version: 2.3.0 +Version: 2.3.1 Summary: Matrices describing affine transformation of the plane. Home-page: https://github.com/sgillies/affine Author: Sean Gillies Author-email: [email protected] License: BSD -Description: Affine - ====== - - Matrices describing affine transformation of the plane. - - .. image:: https://travis-ci.org/sgillies/affine.svg?branch=master - :target: https://travis-ci.org/sgillies/affine - - .. image:: https://coveralls.io/repos/sgillies/affine/badge.svg - :target: https://coveralls.io/r/sgillies/affine - - The Affine package is derived from Casey Duncan's Planar package. Please see - the copyright statement in `affine/__init__.py <affine/__init__.py>`__. - - Usage - ----- - - The 3x3 augmented affine transformation matrix for transformations in two - dimensions is illustrated below. - - .. :: - - | x' | | a b c | | x | - | y' | = | d e f | | y | - | 1 | | 0 0 1 | | 1 | - - Matrices can be created by passing the values ``a, b, c, d, e, f`` to the - ``affine.Affine`` constructor or by using its ``identity()``, - ``translation()``, ``scale()``, ``shear()``, and ``rotation()`` class methods. - - .. code-block:: pycon - - >>> from affine import Affine - >>> Affine.identity() - Affine(1.0, 0.0, 0.0, - 0.0, 1.0, 0.0) - >>> Affine.translation(1.0, 5.0) - Affine(1.0, 0.0, 1.0, - 0.0, 1.0, 5.0) - >>> Affine.scale(2.0) - Affine(2.0, 0.0, 0.0, - 0.0, 2.0, 0.0) - >>> Affine.shear(45.0, 45.0) # decimal degrees - Affine(1.0, 0.9999999999999999, 0.0, - 0.9999999999999999, 1.0, 0.0) - >>> Affine.rotation(45.0) # decimal degrees - Affine(0.7071067811865476, -0.7071067811865475, 0.0, - 0.7071067811865475, 0.7071067811865476, 0.0) - - These matrices can be applied to ``(x, y)`` tuples to obtain transformed - coordinates ``(x', y')``. - - .. code-block:: pycon - - >>> Affine.translation(1.0, 5.0) * (1.0, 1.0) - (2.0, 6.0) - >>> Affine.rotation(45.0) * (1.0, 1.0) - (1.1102230246251565e-16, 1.414213562373095) - - They may also be multiplied together to combine transformations. - - .. code-block:: pycon - - >>> Affine.translation(1.0, 5.0) * Affine.rotation(45.0) - Affine(0.7071067811865476, -0.7071067811865475, 1.0, - 0.7071067811865475, 0.7071067811865476, 5.0) - - Usage with GIS data packages - ---------------------------- - - Georeferenced raster datasets use affine transformations to map from image - coordinates to world coordinates. The ``affine.Affine.from_gdal()`` class - method helps convert `GDAL GeoTransform - <http://www.gdal.org/classGDALDataset.html#af9593cc241e7d140f5f3c4798a43a668>`__, - sequences of 6 numbers in which the first and fourth are the x and y offsets - and the second and sixth are the x and y pixel sizes. - - Using a GDAL dataset transformation matrix, the world coordinates ``(x, y)`` - corresponding to the top left corner of the pixel 100 rows down from the - origin can be easily computed. - - .. code-block:: pycon - - >>> geotransform = (-237481.5, 425.0, 0.0, 237536.4, 0.0, -425.0) - >>> fwd = Affine.from_gdal(*geotransform) - >>> col, row = 0, 100 - >>> fwd * (col, row) - (-237481.5, 195036.4) - - The reverse transformation is obtained using the ``~`` operator. - - .. code-block:: pycon - - >>> rev = ~fwd - >>> rev * fwd * (col, row) - (0.0, 99.99999999999999) - - Keywords: affine transformation matrix Platform: UNKNOWN Provides-Extra: test +License-File: LICENSE.txt +License-File: AUTHORS.txt + +Affine +====== + +Matrices describing affine transformation of the plane. + +.. image:: https://travis-ci.org/sgillies/affine.svg?branch=master + :target: https://travis-ci.org/sgillies/affine + +.. image:: https://coveralls.io/repos/sgillies/affine/badge.svg + :target: https://coveralls.io/r/sgillies/affine + +The Affine package is derived from Casey Duncan's Planar package. Please see +the copyright statement in `affine/__init__.py <affine/__init__.py>`__. + +Usage +----- + +The 3x3 augmented affine transformation matrix for transformations in two +dimensions is illustrated below. + +:: + + | x' | | a b c | | x | + | y' | = | d e f | | y | + | 1 | | 0 0 1 | | 1 | + +Matrices can be created by passing the values ``a, b, c, d, e, f`` to the +``affine.Affine`` constructor or by using its ``identity()``, +``translation()``, ``scale()``, ``shear()``, and ``rotation()`` class methods. + +.. code-block:: pycon + + >>> from affine import Affine + >>> Affine.identity() + Affine(1.0, 0.0, 0.0, + 0.0, 1.0, 0.0) + >>> Affine.translation(1.0, 5.0) + Affine(1.0, 0.0, 1.0, + 0.0, 1.0, 5.0) + >>> Affine.scale(2.0) + Affine(2.0, 0.0, 0.0, + 0.0, 2.0, 0.0) + >>> Affine.shear(45.0, 45.0) # decimal degrees + Affine(1.0, 0.9999999999999999, 0.0, + 0.9999999999999999, 1.0, 0.0) + >>> Affine.rotation(45.0) # decimal degrees + Affine(0.7071067811865476, -0.7071067811865475, 0.0, + 0.7071067811865475, 0.7071067811865476, 0.0) + +These matrices can be applied to ``(x, y)`` tuples to obtain transformed +coordinates ``(x', y')``. + +.. code-block:: pycon + + >>> Affine.translation(1.0, 5.0) * (1.0, 1.0) + (2.0, 6.0) + >>> Affine.rotation(45.0) * (1.0, 1.0) + (1.1102230246251565e-16, 1.414213562373095) + +They may also be multiplied together to combine transformations. + +.. code-block:: pycon + + >>> Affine.translation(1.0, 5.0) * Affine.rotation(45.0) + Affine(0.7071067811865476, -0.7071067811865475, 1.0, + 0.7071067811865475, 0.7071067811865476, 5.0) + +Usage with GIS data packages +---------------------------- + +Georeferenced raster datasets use affine transformations to map from image +coordinates to world coordinates. The ``affine.Affine.from_gdal()`` class +method helps convert `GDAL GeoTransform +<https://gdal.org/user/raster_data_model.html#affine-geotransform>`__, +sequences of 6 numbers in which the first and fourth are the x and y offsets +and the second and sixth are the x and y pixel sizes. + +Using a GDAL dataset transformation matrix, the world coordinates ``(x, y)`` +corresponding to the top left corner of the pixel 100 rows down from the +origin can be easily computed. + +.. code-block:: pycon + + >>> geotransform = (-237481.5, 425.0, 0.0, 237536.4, 0.0, -425.0) + >>> fwd = Affine.from_gdal(*geotransform) + >>> col, row = 0, 100 + >>> fwd * (col, row) + (-237481.5, 195036.4) + +The reverse transformation is obtained using the ``~`` operator. + +.. code-block:: pycon + + >>> rev = ~fwd + >>> rev * fwd * (col, row) + (0.0, 99.99999999999999) + + + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/affine-2.3.0/affine.egg-info/requires.txt new/affine-2.3.1/affine.egg-info/requires.txt --- old/affine-2.3.0/affine.egg-info/requires.txt 2019-09-05 00:23:11.000000000 +0200 +++ new/affine-2.3.1/affine.egg-info/requires.txt 2022-03-25 03:38:10.000000000 +0100 @@ -1,6 +1,7 @@ [test] -pytest>=3.0 +pytest>=4.6 pytest-cov pydocstyle +flake8 coveralls diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/affine-2.3.0/setup.py new/affine-2.3.1/setup.py --- old/affine-2.3.0/setup.py 2019-09-05 00:22:41.000000000 +0200 +++ new/affine-2.3.1/setup.py 2022-03-23 14:29:19.000000000 +0100 @@ -30,5 +30,6 @@ packages=find_packages(exclude=["ez_setup", "examples", "tests"]), include_package_data=True, zip_safe=True, - extras_require={"test": ["pytest>=3.0", "pytest-cov", "pydocstyle", "coveralls"]}, + extras_require={"test": ["pytest>=4.6", "pytest-cov", "pydocstyle", + "flake8", "coveralls"]}, )
