[python-affine] 04/08: Imported Upstream version 1.1.0
Bas Couwenberg
sebastic at xs4all.nl
Sun Dec 28 14:08:14 UTC 2014
This is an automated email from the git hooks/post-receive script.
sebastic-guest pushed a commit to branch master
in repository python-affine.
commit 784c9d578948a2f309f0b1dfa97e678777cced80
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Sun Dec 28 14:50:22 2014 +0100
Imported Upstream version 1.1.0
---
.travis.yml | 14 +++
AUTHORS.txt | 1 +
CHANGES.txt | 6 +-
README.rst | 25 +++--
affine/__init__.py | 93 ++++++++++++-----
affine/tests/test_transform.py | 228 ++++++++++++++++++++++++++++++-----------
setup.py | 28 +++--
7 files changed, 289 insertions(+), 106 deletions(-)
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..f30a897
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,14 @@
+language: python
+python:
+ - "2.6"
+ - "2.7"
+ - "3.3"
+ - "3.4"
+install:
+ - "pip install pytest"
+ - "pip install coveralls"
+ - "pip install -e ."
+script:
+ - coverage run --source=affine --omit='*.pxd,*.pyx,*/tests/*,*/docs/*,*/examples/*,*/benchmarks/*' -m py.test
+after_success:
+ - coveralls
diff --git a/AUTHORS.txt b/AUTHORS.txt
index 3c9e19e..91ba223 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -4,3 +4,4 @@ Authors
- Sean Gillies <sean.gillies at gmail.com>
- Sean Gillies <sean at mapbox.com> (same as ^^)
- Steven Ring <smr at southsky.com.au>
+- Mike Toews <mwtoews at gmail.com>
diff --git a/CHANGES.txt b/CHANGES.txt
index d4a4667..15d1bc2 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,11 @@
CHANGES
=======
+1.1.0 (2014-11-13)
+------------------
+- add loadsw/dumpsw world file utilities (#6).
+- Travis-CI and Coveralls config and web hooks added (#10).
+
1.0.1 (2014-10-20)
------------------
- set_epsilon() now actually sets module EPSILON (#4).
@@ -10,4 +15,3 @@ CHANGES
----------------
- Code ported from Casey Duncan's Planar package.
- from_gdal() class method added.
-
diff --git a/README.rst b/README.rst
index 5f1a1cf..9e8ee0b 100644
--- a/README.rst
+++ b/README.rst
@@ -3,8 +3,14 @@ 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.png
+ :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>`__.
+the copyright statement in `affine/__init__.py <affine/__init__.py>`__.
Usage
-----
@@ -41,8 +47,8 @@ Matrices can be created by passing the values ``a, b, c, d, e, f`` to the
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')`.
+These matrices can be applied to ``(x, y)`` tuples to obtain transformed
+coordinates ``(x', y')``.
.. code-block:: pycon
@@ -64,23 +70,24 @@ 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 geotransforms
-<http://www.gdal.org/classGDALDataset.html#af9593cc241e7d140f5f3c4798a43a668>`__,
+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
+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
- >>> fwd = Affine.from_gdal(-237481.5, 425.0, 0.0, 237536.4, 0.0, -425.0)
+ >>> 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 obained using the `~` operator.
+The reverse transformation is obtained using the ``~`` operator.
.. code-block:: pycon
diff --git a/affine/__init__.py b/affine/__init__.py
index 30f1247..f7d8af9 100644
--- a/affine/__init__.py
+++ b/affine/__init__.py
@@ -47,10 +47,11 @@ import math
__all__ = ['Affine']
__author__ = "Sean Gillies"
-__version__ = "1.0.1"
+__version__ = "1.1.0"
+
+EPSILON = 1e-5
+EPSILON2 = EPSILON ** 2
-EPSILON=1e-5
-EPSILON2=EPSILON**2
def set_epsilon(epsilon):
"""Set the global absolute error value and rounding limit for approximate
@@ -65,7 +66,7 @@ def set_epsilon(epsilon):
"""
global EPSILON, EPSILON2
EPSILON = float(epsilon)
- EPSILON2 = EPSILON**2
+ EPSILON2 = EPSILON ** 2
class TransformNotInvertibleError(Exception):
@@ -76,12 +77,12 @@ class TransformNotInvertibleError(Exception):
# across major Python versions
try:
3 > ""
-except TypeError: # pragma: no cover
+except TypeError: # pragma: no cover
# No implicit ordering (newer Python)
def assert_unorderable(a, b):
"""Assert that a and b are unorderable"""
return NotImplemented
-else: # pragma: no cover
+else: # pragma: no cover
# Implicit ordering by default (older Python)
# We must raise an exception ourselves
# To prevent nonsensical ordering
@@ -90,6 +91,7 @@ else: # pragma: no cover
raise TypeError("unorderable types: %s and %s"
% (type(a).__name__, type(b).__name__))
+
def cached_property(func):
"""Special property decorator that caches the computed
property value in the object's instance dict the first
@@ -97,6 +99,7 @@ def cached_property(func):
"""
name = func.__name__
doc = func.__doc__
+
def getter(self, name=name):
try:
return self.__dict__[name]
@@ -106,6 +109,7 @@ def cached_property(func):
getter.func_name = name
return property(getter, doc=doc)
+
def cos_sin_deg(deg):
"""Return the cosine and sin for the given angle
in degrees, with special-case handling of multiples
@@ -145,13 +149,18 @@ class Affine(
return tuple.__new__(Affine, mat3x3)
else:
raise TypeError(
- "Expected 6 number args, got %s" % len(members))
+ "Expected 6 coefficients, found %d" % len(members))
@classmethod
def from_gdal(cls, c, a, b, f, d, e):
+ """Use same coefficient order as GDAL's GetGeoTransform().
+
+ :param c, a, b, f, d, e: 6 floats ordered by GDAL.
+ :rtype: Affine
+ """
members = [a, b, c, d, e, f]
mat3x3 = [x * 1.0 for x in members] + [0.0, 0.0, 1.0]
- return tuple.__new__(Affine, mat3x3)
+ return tuple.__new__(cls, mat3x3)
@classmethod
def identity(cls):
@@ -233,8 +242,8 @@ class Affine(
else:
px, py = pivot
return tuple.__new__(cls,
- (ca, sa, px - px*ca + py*sa,
- -sa, ca, py - px*sa - py*ca,
+ (ca, sa, px - px * ca + py * sa,
+ -sa, ca, py - px * sa - py * ca,
0.0, 0.0, 1.0))
def __str__(self):
@@ -249,14 +258,20 @@ class Affine(
" %r, %r, %r)") % self[:6]
def to_gdal(self):
+ """Return same coefficient order as GDAL's SetGeoTransform().
+
+ :rtype: tuple
+ """
return (self.c, self.a, self.b, self.f, self.d, self.e)
@property
def xoff(self):
+ """Alias for 'c'"""
return self.c
@property
def yoff(self):
+ """Alias for 'f'"""
return self.f
@cached_property
@@ -266,7 +281,7 @@ class Affine(
is applied to a shape.
"""
a, b, c, d, e, f, g, h, i = self
- return a*e - b*d
+ return a * e - b * d
@cached_property
def is_identity(self):
@@ -292,7 +307,7 @@ class Affine(
This implies that the transform has no effective shear.
"""
a, b, c, d, e, f, g, h, i = self
- return abs(a*b + d*e) < EPSILON
+ return abs(a * b + d * e) < EPSILON
@cached_property
def is_orthonormal(self):
@@ -304,8 +319,8 @@ class Affine(
"""
a, b, c, d, e, f, g, h, i = self
return (self.is_conformal
- and abs(1.0 - (a*a + d*d)) < EPSILON
- and abs(1.0 - (b*b + e*e)) < EPSILON)
+ and abs(1.0 - (a * a + d * d)) < EPSILON
+ and abs(1.0 - (b * b + e * e)) < EPSILON)
@cached_property
def is_degenerate(self):
@@ -327,7 +342,7 @@ class Affine(
:param other: Transform being compared.
:type other: Affine
:return: True if absolute difference between each element
- of each respective tranform matrix < ``EPSILON``.
+ of each respective transform matrix < ``EPSILON``.
"""
for i in (0, 1, 2, 3, 4, 5):
if abs(self[i] - other[i]) >= EPSILON:
@@ -362,15 +377,15 @@ class Affine(
if isinstance(other, Affine):
oa, ob, oc, od, oe, of, _, _, _ = other
return tuple.__new__(Affine,
- (sa*oa + sb*od, sa*ob + sb*oe, sa*oc + sb*of + sc,
- sd*oa + se*od, sd*ob + se*oe, sd*oc + se*of + sf,
+ (sa * oa + sb * od, sa * ob + sb * oe, sa * oc + sb * of + sc,
+ sd * oa + se * od, sd * ob + se * oe, sd * oc + se * of + sf,
0.0, 0.0, 1.0))
else:
try:
vx, vy = other
except Exception:
return NotImplemented
- return (vx*sa + vy*sd + sc, vx*sb + vy*se + sf)
+ return (vx * sa + vy * sd + sc, vx * sb + vy * se + sf)
def __rmul__(self, other):
# We should not be called if other is an affine instance
@@ -395,7 +410,7 @@ class Affine(
if self is not identity and self != identity:
sa, sb, sc, sd, se, sf, _, _, _ = self
for i, (x, y) in enumerate(seq):
- seq[i] = (x*sa + y*sd + sc, x*sb + y*se + sf)
+ seq[i] = (x * sa + y * sd + sc, x * sb + y * se + sf)
def __invert__(self):
"""Return the inverse transform.
@@ -413,16 +428,48 @@ class Affine(
rd = -sd * idet
re = sa * idet
return tuple.__new__(Affine,
- (ra, rb, -sc*ra - sf*rb,
- rd, re, -sc*rd - sf*re,
+ (ra, rb, -sc * ra - sf * rb,
+ rd, re, -sc * rd - sf * re,
0.0, 0.0, 1.0))
- __hash__ = tuple.__hash__ # hash is not inherited in Py 3
+ __hash__ = tuple.__hash__ # hash is not inherited in Py 3
identity = Affine(1, 0, 0, 0, 1, 0)
"""The identity transform"""
+# Miscellaneous utilities
-# vim: ai ts=4 sts=4 et sw=4 tw=78
+def loadsw(s):
+ """Returns Affine from the contents of a world file string.
+
+ This method also translates the coefficients from from center- to
+ corner-based coordinates.
+
+ :param s: str with 6 floats ordered in a world file.
+ :rtype: Affine
+ """
+ if not hasattr(s, 'split'):
+ raise TypeError("Cannot split input string")
+ coeffs = s.split()
+ if len(coeffs) != 6:
+ raise ValueError("Expected 6 coefficients, found %d" % len(coeffs))
+ a, d, b, e, c, f = [float(x) for x in coeffs]
+ center = tuple.__new__(Affine, [a, b, c, d, e, f, 0.0, 0.0, 1.0])
+ return center * Affine.translation(-0.5, -0.5)
+
+
+def dumpsw(obj):
+ """Return string for a world file.
+
+ This method also translates the coefficients from from corner- to
+ center-based coordinates.
+
+ :rtype: str
+ """
+ center = obj * Affine.translation(0.5, 0.5)
+ return '\n'.join(repr(getattr(center, x)) for x in list('adbecf')) + '\n'
+
+
+# vim: ai ts=4 sts=4 et sw=4 tw=78
diff --git a/affine/tests/test_transform.py b/affine/tests/test_transform.py
index e731e02..d456cba 100644
--- a/affine/tests/test_transform.py
+++ b/affine/tests/test_transform.py
@@ -5,7 +5,7 @@
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
-# * Redistributions of source code must retain the above copyright notice,
+# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
@@ -19,7 +19,7 @@
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
@@ -29,9 +29,10 @@
"""Transform unit tests"""
from __future__ import division
-import sys
+
import math
import unittest
+from textwrap import dedent
from nose.tools import assert_equal, assert_almost_equal, raises
from affine import Affine
@@ -98,93 +99,166 @@ class PyAffineTestCase(unittest.TestCase):
def test_str(self):
assert_equal(
- str(Affine(1.111, 2.222, 3.333, -4.444, -5.555, 6.666)),
+ 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|")
def test_repr(self):
assert_equal(
- repr(Affine(1.111, 2.222, 3.456, 4.444, 5.5, 6.25)),
+ repr(Affine(1.111, 2.222, 3.456, 4.444, 5.5, 6.25)),
("Affine(1.111, 2.222, 3.456,\n"
" 4.444, 5.5, 6.25)"))
def test_identity_constructor(self):
ident = Affine.identity()
assert isinstance(ident, Affine)
- assert_equal(tuple(ident), (1,0,0, 0,1,0, 0,0,1))
+ assert_equal(
+ tuple(ident),
+ (1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1))
assert ident.is_identity
def test_translation_constructor(self):
trans = Affine.translation(2, -5)
assert isinstance(trans, Affine)
- assert_equal(tuple(trans), (1,0,2, 0,1,-5, 0,0,1))
+ assert_equal(
+ tuple(trans),
+ (1, 0, 2,
+ 0, 1, -5,
+ 0, 0, 1))
def test_scale_constructor(self):
scale = Affine.scale(5)
assert isinstance(scale, Affine)
- assert_equal(tuple(scale), (5,0,0, 0,5,0, 0,0,1))
+ assert_equal(
+ tuple(scale),
+ (5, 0, 0,
+ 0, 5, 0,
+ 0, 0, 1))
scale = Affine.scale(-1, 2)
- assert_equal(tuple(scale), (-1,0,0, 0,2,0, 0,0,1))
- assert_equal(tuple(Affine.scale(1)),
- tuple(Affine.identity()))
+ assert_equal(
+ tuple(scale),
+ (-1, 0, 0,
+ 0, 2, 0,
+ 0, 0, 1))
+ assert_equal(tuple(Affine.scale(1)), tuple(Affine.identity()))
def test_shear_constructor(self):
shear = Affine.shear(30)
assert isinstance(shear, Affine)
sx = math.tan(math.radians(30))
- seq_almost_equal(tuple(shear), (1,0,0, sx,1,0, 0,0,1))
+ seq_almost_equal(
+ tuple(shear),
+ (1, 0, 0,
+ sx, 1, 0,
+ 0, 0, 1))
shear = Affine.shear(-15, 60)
sx = math.tan(math.radians(-15))
sy = math.tan(math.radians(60))
- seq_almost_equal(tuple(shear), (1,sy,0, sx,1,0, 0,0,1))
+ seq_almost_equal(
+ tuple(shear),
+ (1, sy, 0,
+ sx, 1, 0,
+ 0, 0, 1))
shear = Affine.shear(y_angle=45)
- seq_almost_equal(tuple(shear), (1,1,0, 0,1,0, 0,0,1))
+ seq_almost_equal(
+ tuple(shear),
+ (1, 1, 0,
+ 0, 1, 0,
+ 0, 0, 1))
def test_rotation_constructor(self):
rot = Affine.rotation(60)
assert isinstance(rot, Affine)
r = math.radians(60)
s, c = math.sin(r), math.cos(r)
- assert_equal(tuple(rot), (c,s,0, -s,c,0, 0,0,1))
+ assert_equal(
+ tuple(rot),
+ (c, s, 0,
+ -s, c, 0,
+ 0, 0, 1))
rot = Affine.rotation(337)
r = math.radians(337)
s, c = math.sin(r), math.cos(r)
- seq_almost_equal(tuple(rot), (c,s,0, -s,c,0, 0,0,1))
- assert_equal(tuple(Affine.rotation(0)),
- tuple(Affine.identity()))
+ seq_almost_equal(
+ tuple(rot),
+ (c, s, 0,
+ -s, c, 0,
+ 0, 0, 1))
+ assert_equal(tuple(Affine.rotation(0)), tuple(Affine.identity()))
def test_rotation_constructor_quadrants(self):
- assert_equal(tuple(Affine.rotation(0)), (1,0,0, 0,1,0, 0,0,1))
- assert_equal(tuple(Affine.rotation(90)), (0,1,0, -1,0,0, 0,0,1))
- assert_equal(tuple(Affine.rotation(180)), (-1,0,0, 0,-1,0, 0,0,1))
- assert_equal(tuple(Affine.rotation(-180)), (-1,0,0, 0,-1,0, 0,0,1))
- assert_equal(tuple(Affine.rotation(270)), (0,-1,0, 1,0,0, 0,0,1))
- assert_equal(tuple(Affine.rotation(-90)), (0,-1,0, 1,0,0, 0,0,1))
- assert_equal(tuple(Affine.rotation(360)), (1,0,0, 0,1,0, 0,0,1))
- assert_equal(tuple(Affine.rotation(450)), (0,1,0, -1,0,0, 0,0,1))
- assert_equal(tuple(Affine.rotation(-450)), (0,-1,0, 1,0,0, 0,0,1))
+ assert_equal(
+ tuple(Affine.rotation(0)),
+ (1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1))
+ assert_equal(
+ tuple(Affine.rotation(90)),
+ (0, 1, 0,
+ -1, 0, 0,
+ 0, 0, 1))
+ assert_equal(
+ tuple(Affine.rotation(180)),
+ (-1, 0, 0,
+ 0, -1, 0,
+ 0, 0, 1))
+ assert_equal(
+ tuple(Affine.rotation(-180)),
+ (-1, 0, 0,
+ 0, -1, 0,
+ 0, 0, 1))
+ assert_equal(
+ tuple(Affine.rotation(270)),
+ (0, -1, 0,
+ 1, 0, 0,
+ 0, 0, 1))
+ assert_equal(
+ tuple(Affine.rotation(-90)),
+ (0, -1, 0,
+ 1, 0, 0,
+ 0, 0, 1))
+ assert_equal(
+ tuple(Affine.rotation(360)),
+ (1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1))
+ assert_equal(
+ tuple(Affine.rotation(450)),
+ (0, 1, 0,
+ -1, 0, 0,
+ 0, 0, 1))
+ assert_equal(
+ tuple(Affine.rotation(-450)),
+ (0, -1, 0,
+ 1, 0, 0,
+ 0, 0, 1))
def test_rotation_constructor_with_pivot(self):
assert_equal(tuple(Affine.rotation(60)),
- tuple(Affine.rotation(60, pivot=(0,0))))
- rot = Affine.rotation(27, pivot=(2,-4))
+ 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)
- assert_equal(tuple(rot),
- (c,s,2 - 2*c - 4*s, -s,c,-4 - 2*s + 4*c, 0,0,1))
- assert_equal(tuple(Affine.rotation(0, (-3, 2))),
- tuple(Affine.identity()))
+ assert_equal(
+ tuple(rot),
+ (c, s, 2 - 2 * c - 4 * s,
+ -s, c, -4 - 2 * s + 4 * c,
+ 0, 0, 1))
+ assert_equal(tuple(Affine.rotation(0, (-3, 2))),
+ tuple(Affine.identity()))
@raises(TypeError)
def test_rotation_contructor_wrong_arg_types(self):
- Affine.rotation(1,1)
+ Affine.rotation(1, 1)
def test_determinant(self):
assert_equal(Affine.identity().determinant, 1)
assert_equal(Affine.scale(2).determinant, 4)
assert_equal(Affine.scale(0).determinant, 0)
- assert_equal(Affine.scale(5,1).determinant, 5)
- assert_equal(Affine.scale(-1,1).determinant, -1)
- assert_equal(Affine.scale(-1,0).determinant, 0)
+ assert_equal(Affine.scale(5, 1).determinant, 5)
+ assert_equal(Affine.scale(-1, 1).determinant, -1)
+ assert_equal(Affine.scale(-1, 0).determinant, 0)
assert_almost_equal(Affine.rotation(77).determinant, 1)
assert_almost_equal(Affine.translation(32, -47).determinant, 1)
@@ -228,7 +302,6 @@ class PyAffineTestCase(unittest.TestCase):
assert Affine.scale(EPSILON).is_degenerate
def test_column_vectors(self):
- import affine
a, b, c = Affine(2, 3, 4, 5, 6, 7).column_vectors
assert isinstance(a, tuple)
assert isinstance(b, tuple)
@@ -241,7 +314,7 @@ class PyAffineTestCase(unittest.TestCase):
from affine import EPSILON
assert EPSILON != 0, EPSILON
E = EPSILON * 0.5
- t = Affine(1.0, E, 0, -E, 1.0+E, E)
+ t = Affine(1.0, E, 0, -E, 1.0 + E, E)
assert t.almost_equals(Affine.identity())
assert Affine.identity().almost_equals(t)
assert t.almost_equals(t)
@@ -265,22 +338,22 @@ class PyAffineTestCase(unittest.TestCase):
@raises(TypeError)
def test_gt(self):
- Affine(1,2,3,4,5,6) > Affine(6,5,4,3,2,1)
+ Affine(1, 2, 3, 4, 5, 6) > Affine(6, 5, 4, 3, 2, 1)
@raises(TypeError)
def test_lt(self):
- Affine(1,2,3,4,5,6) < Affine(6,5,4,3,2,1)
+ Affine(1, 2, 3, 4, 5, 6) < Affine(6, 5, 4, 3, 2, 1)
@raises(TypeError)
def test_add(self):
- Affine(1,2,3,4,5,6) + Affine(6,5,4,3,2,1)
-
+ Affine(1, 2, 3, 4, 5, 6) + Affine(6, 5, 4, 3, 2, 1)
+
@raises(TypeError)
def test_sub(self):
- Affine(1,2,3,4,5,6) - Affine(6,5,4,3,2,1)
+ Affine(1, 2, 3, 4, 5, 6) - Affine(6, 5, 4, 3, 2, 1)
def test_mul_by_identity(self):
- t = Affine(1,2,3,4,5,6)
+ t = Affine(1, 2, 3, 4, 5, 6)
assert_equal(tuple(t * Affine.identity()), tuple(t))
def test_mul_transform(self):
@@ -291,14 +364,14 @@ class PyAffineTestCase(unittest.TestCase):
seq_almost_equal(t, Affine.scale(6, 10))
def test_itransform(self):
- pts = [(4,1), (-1,0), (3,2)]
+ pts = [(4, 1), (-1, 0), (3, 2)]
r = Affine.scale(-2).itransform(pts)
assert r is None, r
- assert_equal(pts, [(-8, -2), (2,0), (-6,-4)])
+ assert_equal(pts, [(-8, -2), (2, 0), (-6, -4)])
@raises(TypeError)
def test_mul_wrong_type(self):
- Affine(1,2,3,4,5,6) * None
+ Affine(1, 2, 3, 4, 5, 6) * None
@raises(TypeError)
def test_mul_sequence_wrong_member_types(self):
@@ -306,10 +379,12 @@ class PyAffineTestCase(unittest.TestCase):
@classmethod
def from_points(cls, points):
list(points)
+
def __iter__(self):
yield 0
- Affine(1,2,3,4,5,6) * NotPtSeq()
-
+
+ Affine(1, 2, 3, 4, 5, 6) * NotPtSeq()
+
def test_imul_transform(self):
t = Affine.translation(3, 5)
t *= Affine.translation(-2, 3.5)
@@ -322,9 +397,9 @@ class PyAffineTestCase(unittest.TestCase):
~Affine.translation(2, -3), Affine.translation(-2, 3))
seq_almost_equal(
~Affine.rotation(-33.3), Affine.rotation(33.3))
- t = Affine(1,2,3,4,5,6)
+ t = Affine(1, 2, 3, 4, 5, 6)
seq_almost_equal(~t * t, Affine.identity())
-
+
def test_cant_invert_degenerate(self):
from affine import TransformNotInvertibleError
t = Affine.scale(0)
@@ -334,17 +409,55 @@ class PyAffineTestCase(unittest.TestCase):
import affine
old_epsilon = affine.EPSILON
- old_epsilon2 = affine.EPSILON2
try:
affine.set_epsilon(123)
assert_equal(123, affine.EPSILON)
- assert_equal(123*123, affine.EPSILON2)
+ assert_equal(123 * 123, affine.EPSILON2)
finally:
affine.set_epsilon(old_epsilon)
-
-
+ @raises(TypeError)
+ def test_bad_type_world(self):
+ from affine import loadsw
+ # wrong type, i.e don't use readlines()
+ loadsw(['1.0', '0.0', '0.0', '1.0', '0.0', '0.0'])
+
+ @raises(ValueError)
+ def test_bad_value_world(self):
+ from affine import loadsw
+ # wrong number of parameters
+ loadsw('1.0\n0.0\n0.0\n1.0\n0.0\n0.0\n0.0')
+
+ def test_simple_world(self):
+ from affine import loadsw, dumpsw
+ s = '1.0\n0.0\n0.0\n-1.0\n100.5\n199.5\n'
+ a = loadsw(s)
+ self.assertEqual(
+ a,
+ Affine(
+ 1.0, 0.0, 100.0,
+ 0.0, -1., 200.0))
+ self.assertEqual(dumpsw(a), s)
+
+ def test_real_world(self):
+ from affine import loadsw, dumpsw
+ s = dedent('''\
+ 39.9317755024
+ 30.0907511581
+ 30.0907511576
+ -39.9317755019
+ 2658137.2266720217
+ 5990821.7039887439''') # no EOL
+ a1 = loadsw(s)
+ self.assertTrue(a1.almost_equals(
+ Affine(
+ 39.931775502364644, 30.090751157602412, 2658102.2154086917,
+ 30.090751157602412, -39.931775502364644, 5990826.624500916)))
+ a1out = dumpsw(a1)
+ self.assertTrue(isinstance(a1out, str))
+ a2 = loadsw(a1out)
+ self.assertTrue(a1.almost_equals(a2))
def test_gdal():
@@ -352,7 +465,7 @@ def test_gdal():
assert t.c == t.xoff == -237481.5
assert t.a == 425.0
assert t.b == 0.0
- assert t.f == t.yoff == 237536.4
+ 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)
@@ -364,4 +477,3 @@ if __name__ == '__main__':
# vim: ai ts=4 sts=4 et sw=4 tw=78
-
diff --git a/setup.py b/setup.py
old mode 100644
new mode 100755
index 4915923..ae9c86b
--- a/setup.py
+++ b/setup.py
@@ -1,23 +1,26 @@
-from setuptools import setup, find_packages
-import sys, os
+#!/usr/bin/env python
-# Parse the version from the fiona module.
+from setuptools import setup
+
+
+# Parse the version from the affine module.
with open('affine/__init__.py') as f:
for line in f:
- if line.find("__version__") >= 0:
+ if "__version__" in line:
version = line.split("=")[1].strip()
- version = version.strip('"')
- version = version.strip("'")
- continue
+ version = version.strip('"').strip("'")
+ break
+
+with open('README.rst') as f:
+ readme = f.read()
-readme = open('README.rst').read()
setup(name='affine',
version=version,
description="Matrices describing affine transformation of the plane",
long_description=readme,
classifiers=[],
- keywords='',
+ keywords='affine transformation matrix',
author='Sean Gillies',
author_email='sean at mapbox.com',
url='https://github.com/sgillies/affine',
@@ -26,10 +29,5 @@ setup(name='affine',
packages=['affine'],
include_package_data=True,
zip_safe=False,
- install_requires=[
- # -*- Extra requirements: -*-
- ],
- entry_points="""
- # -*- Entry points: -*-
- """,
+ extras_require = {'test': ['pytest']}
)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/python-affine.git
More information about the Pkg-grass-devel
mailing list