diff options
Diffstat (limited to 'share/extensions/tests/test_inkex_transforms.py')
-rw-r--r-- | share/extensions/tests/test_inkex_transforms.py | 567 |
1 files changed, 567 insertions, 0 deletions
diff --git a/share/extensions/tests/test_inkex_transforms.py b/share/extensions/tests/test_inkex_transforms.py new file mode 100644 index 0000000..07224ca --- /dev/null +++ b/share/extensions/tests/test_inkex_transforms.py @@ -0,0 +1,567 @@ +# coding=utf-8 +""" +Test Inkex transformational logic. +""" +from math import sqrt, pi +from inkex.transforms import ( + Vector2d, ImmutableVector2d, BoundingBox, BoundingInterval, Transform, DirectedLineSegment +) +from inkex.utils import PY3 +from inkex.tester import TestCase +import pytest + +class ImmutableVector2dTest(TestCase): + """Test the ImmutableVector2d object""" + def test_vector_creation(self): + """Test ImmutableVector2d creation""" + vec0 = ImmutableVector2d(15, 22) + self.assertEqual(vec0.x, 15) + self.assertEqual(vec0.y, 22) + + vec1 = ImmutableVector2d() + self.assertEqual(vec1.x, 0) + self.assertEqual(vec1.y, 0) + + vec2 = ImmutableVector2d((17, 32)) + self.assertEqual(vec2.x, 17) + self.assertEqual(vec2.y, 32) + + vec3 = ImmutableVector2d(vec0) + self.assertEqual(vec3.x, 15) + self.assertEqual(vec3.y, 22) + + self.assertRaises(ValueError, ImmutableVector2d, (1)) + self.assertRaises(ValueError, ImmutableVector2d, (1, 2, 3)) + + def test_binary_operators(self): + """Test binary operators for vector2d""" + vec1 = ImmutableVector2d(15, 22) + vec2 = ImmutableVector2d(5, 3) + + self.assertTrue((vec1 - vec2).is_close((10, 19))) + self.assertTrue((vec1 - (5, 3)).is_close((10, 19))) + self.assertTrue(((15, 22) - vec2).is_close((10, 19))) + self.assertTrue((vec1 + vec2).is_close((20, 25))) + self.assertTrue((vec1 + (5, 3)).is_close((20, 25))) + self.assertTrue(((15, 22) + vec2).is_close((20, 25))) + self.assertTrue((vec1 * 2).is_close((30, 44))) + self.assertTrue((2 * vec1).is_close((30, 44))) + self.assertTrue((vec1 / 2).is_close((7.5, 11))) + self.assertTrue((vec1.__div__(2)).is_close((7.5, 11))) + self.assertTrue((vec1 // 2).is_close((7.5, 11))) + + def test_ioperators(self): + """Test operators for vector2d""" + vec0 = vec = ImmutableVector2d(15, 22) + vec += (1, 1) + vec = ImmutableVector2d(vec) + self.assertTrue(vec.is_close((16, 23))) + vec -= (10, 20) + vec = ImmutableVector2d(vec) + self.assertTrue(vec.is_close((6, 3))) + vec *= 5 + vec = ImmutableVector2d(vec) + self.assertTrue(vec.is_close((30, 15))) + vec /= 90 + vec = ImmutableVector2d(vec) + self.assertTrue(vec.is_close((1.0/3, 1.0/6))) + vec //= 1.0/3 + vec = ImmutableVector2d(vec) + self.assertTrue(vec.is_close((1, 0.5))) + self.assertTrue(vec0.is_close((15, 22))) + self.assertFalse(vec0.is_close(vec)) + + def test_unary_operators(self): + """Test unary operators""" + vec = ImmutableVector2d(1, 2) + self.assertTrue((-vec).is_close((-1, -2))) + self.assertTrue((+vec).is_close(vec)) + self.assertTrue(+vec is not vec) # returned value is a copy + + def test_representations(self): + """Test ImmutableVector2d Repr""" + self.assertEqual(str(ImmutableVector2d(1, 2)), "1, 2") + self.assertEqual(repr(ImmutableVector2d(1, 2)), "Vector2d(1, 2)") + self.assertEqual(ImmutableVector2d(1, 2).to_tuple(), (1, 2)) + + def test_assign(self): + """Test ImmutableVector2d assignement""" + vec = ImmutableVector2d(10, 20) + with pytest.raises(AttributeError): + vec.assign(5, 10) + + def test_getitem(self): + """Test getitem for ImmutableVector2d""" + vec = ImmutableVector2d(10, 20) + self.assertEqual(len(vec), 2) + self.assertEqual(vec[0], 10) + self.assertEqual(vec[1], 20) + + +class Vector2dTest(TestCase): + """Test the Vector2d object""" + def test_vector_creation(self): + """Test Vector2D creation""" + vec0 = Vector2d(15, 22) + self.assertEqual(vec0.x, 15) + self.assertEqual(vec0.y, 22) + + vec1 = Vector2d() + self.assertEqual(vec1.x, 0) + self.assertEqual(vec1.y, 0) + + vec2 = Vector2d((17, 32)) + self.assertEqual(vec2.x, 17) + self.assertEqual(vec2.y, 32) + + vec3 = Vector2d(vec0) + self.assertEqual(vec3.x, 15) + self.assertEqual(vec3.y, 22) + + self.assertRaises(ValueError, Vector2d, (1)) + self.assertRaises(ValueError, Vector2d, (1, 2, 3)) + + def test_binary_operators(self): + """Test binary operators for vector2d""" + vec1 = Vector2d(15, 22) + vec2 = Vector2d(5, 3) + + self.assertTrue((vec1 - vec2).is_close((10, 19))) + self.assertTrue((vec1 - (5, 3)).is_close((10, 19))) + self.assertTrue(((15, 22) - vec2).is_close((10, 19))) + self.assertTrue((vec1 + vec2).is_close((20, 25))) + self.assertTrue((vec1 + (5, 3)).is_close((20, 25))) + self.assertTrue(((15, 22) + vec2).is_close((20, 25))) + self.assertTrue((vec1 * 2).is_close((30, 44))) + self.assertTrue((2 * vec1).is_close((30, 44))) + self.assertTrue((vec1 / 2).is_close((7.5, 11))) + self.assertTrue((vec1.__div__(2)).is_close((7.5, 11))) + self.assertTrue((vec1 // 2).is_close((7.5, 11))) + + def test_ioperators(self): + """Test operators for vector2d""" + vec0 = vec = Vector2d(15, 22) + vec += (1, 1) + self.assertTrue(vec.is_close((16, 23))) + vec -= (10, 20) + self.assertTrue(vec.is_close((6, 3))) + vec *= 5 + self.assertTrue(vec.is_close((30, 15))) + vec /= 90 + self.assertTrue(vec.is_close((1.0/3, 1.0/6))) + vec //= 1.0/3 + self.assertTrue(vec.is_close((1, 0.5))) + self.assertFalse(vec0.is_close((15, 22))) + self.assertTrue(vec0.is_close(vec)) + + def test_unary_operators(self): + """Test unary operators""" + vec = Vector2d(1, 2) + self.assertTrue((-vec).is_close((-1, -2))) + self.assertTrue((+vec).is_close(vec)) + self.assertTrue(+vec is not vec) # returned value is a copy + + def test_representations(self): + """Test Vector2D Repr""" + self.assertEqual(str(Vector2d(1, 2)), "1, 2") + self.assertEqual(repr(Vector2d(1, 2)), "Vector2d(1, 2)") + self.assertEqual(Vector2d(1, 2).to_tuple(), (1, 2)) + + def test_assign(self): + """Test vector2d assignement""" + vec = Vector2d(10, 20) + vec.assign(5, 10) + self.assertAlmostTuple(vec, (5, 10)) + vec.assign((7, 11)) + self.assertAlmostTuple(vec, (7, 11)) + + def test_getitem(self): + """Test getitem for Vector2D""" + vec = Vector2d(10, 20) + self.assertEqual(len(vec), 2) + self.assertEqual(vec[0], 10) + self.assertEqual(vec[1], 20) + + +class TransformTest(TestCase): + """Test transformation API and calculations""" + + def test_new_empty(self): + """Create a transformation from two triplets matrix""" + self.assertEqual(Transform(), ((1, 0, 0), (0, 1, 0))) + + def test_new_from_triples(self): + """Create a transformation from two triplets matrix""" + self.assertEqual(Transform(((1, 2, 3), (4, 5, 6))), ((1, 2, 3), (4, 5, 6))) + + def test_new_from_sextlet(self): + """Create a transformation from a list of six numbers""" + self.assertEqual(Transform((1, 2, 3, 4, 5, 6)), ((1, 3, 5), (2, 4, 6))) + + def test_new_from_matrix_str(self): + """Create a transformation from a list of six numbers""" + self.assertEqual(Transform('matrix(1, 2, 3, 4, 5, 6)'), ((1, 3, 5), (2, 4, 6))) + + def test_new_from_scale(self): + """Create a scale based transformation""" + self.assertEqual(Transform('scale(10)'), ((10, 0, 0), (0, 10, 0))) + self.assertEqual(Transform('scale(10, 3.3)'), ((10, 0, 0), (0, 3.3, 0))) + + def test_new_from_translate(self): + """Create a translate transformation""" + self.assertEqual(Transform('translate(12)'), ((1, 0, 12), (0, 1, 0))) + self.assertEqual(Transform('translate(12, 14)'), ((1, 0, 12), (0, 1, 14))) + + def test_new_from_rotate(self): + """Create a rotational transformation""" + self.assertEqual(str(Transform('rotate(90)')), 'rotate(90)') + self.assertEqual(str(Transform('rotate(90 10 12)')), + 'matrix(6.12323e-17 1 -1 6.12323e-17 22 2)') + + def test_new_from_skew(self): + """Create skew x/y transformations""" + self.assertEqual(str(Transform('skewX(10)')), 'matrix(1 0 0.176327 1 0 0)') + self.assertEqual(str(Transform('skewY(10)')), 'matrix(1 0.176327 0 1 0 0)') + + def test_invalid_creation_string(self): + """Test creating invalid transforms""" + self.assertEqual(Transform('boo(4)'), ((1, 0, 0), (0, 1, 0))) + + def test_invalid_creation_matrix(self): + """Test creating invalid transforms""" + self.assertRaises(ValueError, Transform, 0.0) + self.assertRaises(ValueError, Transform, (0.0,)) + self.assertRaises(ValueError, Transform, (0.0, 0.0, 0.0)) + + def test_repr(self): + """Test repr string""" + self.assertEqual(repr(Transform()), 'Transform(((1, 0, 0), (0, 1, 0)))') + + def test_matrix_inversion(self): + """Test the negative of a transformation""" + self.assertEqual(-Transform('rotate(45)'), Transform('rotate(-45)')) + self.assertEqual(-Transform('translate(12, 10)'), Transform('translate(-12, -10)')) + self.assertEqual(-Transform('scale(4)'), Transform('scale(0.25)')) + + def test_apply_to_point(self): + """Test applying the transformation to a point""" + trans = Transform('translate(10, 10)') + self.assertEqual(trans.apply_to_point((10, 10)).to_tuple(), (20, 20)) + self.assertRaises(ValueError, trans.apply_to_point, '') + + def test_translate(self): + """Test making translate specific items""" + self.assertEqual(str(Transform(translate=(10.6, 99.9))), "translate(10.6, 99.9)") + + def test_scale(self): + """Test making scale specific items""" + self.assertEqual(str(Transform(scale=(1.0, 2.2))), "scale(1, 2.2)") + + def test_rotate(self): + """Test making rotate specific items""" + self.assertEqual(str(Transform(rotate=45)), "rotate(45)") + self.assertEqual(str(Transform(rotate=(45, 10, 10))), "matrix(0.707107 0.707107 -0.707107 0.707107 10 -4.14214)") + + def test_add_transform(self): + """Quickly add known transforms""" + tr1 = Transform() + tr1.add_scale(5.0, 1.0) + self.assertEqual(str(tr1), 'scale(5, 1)') + tr1.add_translate(10, 10) + self.assertEqual(str(tr1), 'matrix(5 0 0 1 50 10)') + + def test_is_unity(self): + unity = Transform() + self.assertTrue(unity.is_rotate()) + self.assertTrue(unity.is_scale()) + self.assertTrue(unity.is_translate()) + + def test_is_rotation(self): + rot1 = Transform(rotate=21) + rot2 = Transform(rotate=35) + rot3 = Transform(rotate=53) + + self.assertFalse(Transform(translate=1e-9).is_rotate(exactly=True)) + self.assertFalse(Transform(scale=1+1e-9).is_rotate(exactly=True)) + self.assertFalse(Transform(skewx=1e-9).is_rotate(exactly=True)) + self.assertFalse(Transform(skewy=1e-9).is_rotate(exactly=True)) + + self.assertTrue(Transform(translate=1e-9).is_rotate(exactly=False)) + self.assertTrue(Transform(scale=1+1e-9).is_rotate(exactly=False)) + self.assertTrue(Transform(skewx=1e-9).is_rotate(exactly=False)) + self.assertTrue(Transform(skewy=1e-9).is_rotate(exactly=False)) + + self.assertTrue(rot1.is_rotate()) + self.assertTrue(rot2.is_rotate()) + self.assertTrue(rot3.is_rotate()) + + self.assertFalse(rot1.is_translate()) + self.assertFalse(rot2.is_translate()) + self.assertFalse(rot3.is_translate()) + + self.assertFalse(rot1.is_scale()) + self.assertFalse(rot2.is_scale()) + self.assertFalse(rot3.is_scale()) + + self.assertTrue((rot1 * rot1).is_rotate()) + self.assertTrue((rot1 * rot2).is_rotate()) + self.assertTrue((rot1 * rot2 * rot3 * rot2 * rot1).is_rotate()) + + def test_is_translate(self): + tr1 = Transform(translate=(1.1,)) + tr2 = Transform(translate=(1.3, 2.7)) + tr3 = Transform(translate=(sqrt(2) / 2, pi)) + + self.assertFalse(Transform(rotate=1e-9).is_translate(exactly=True)) + self.assertFalse(Transform(scale=1+1e-9).is_translate(exactly=True)) + self.assertFalse(Transform(skewx=1e-9).is_translate(exactly=True)) + self.assertFalse(Transform(skewy=1e-9).is_translate(exactly=True)) + + self.assertTrue(Transform(rotate=1e-9).is_translate(exactly=False)) + self.assertTrue(Transform(scale=1+1e-9).is_translate(exactly=False)) + self.assertTrue(Transform(skewx=1e-9).is_translate(exactly=False)) + self.assertTrue(Transform(skewy=1e-9).is_translate(exactly=False)) + + self.assertTrue(tr1.is_translate()) + self.assertTrue(tr2.is_translate()) + self.assertTrue(tr3.is_translate()) + self.assertFalse(tr1.is_rotate()) + self.assertFalse(tr2.is_rotate()) + self.assertFalse(tr3.is_rotate()) + self.assertFalse(tr1.is_scale()) + self.assertFalse(tr2.is_scale()) + self.assertFalse(tr3.is_scale()) + + self.assertTrue((tr1 * tr1).is_translate()) + self.assertTrue((tr1 * tr2).is_translate()) + self.assertTrue((tr1 * tr2 * tr3 * tr2 * tr1).is_translate()) + self.assertFalse(tr1 * tr2 * tr3 * -tr1 * -tr2 * -tr3) # is almost unity + + def test_is_scale(self): + s1 = Transform(scale=(1.1,)) + s2 = Transform(scale=(1.3, 2.7)) + s3 = Transform(scale=(sqrt(2) / 2, pi)) + + self.assertFalse(Transform(translate=1e-9).is_scale(exactly=True)) + self.assertFalse(Transform(rotate=1e-9).is_scale(exactly=True)) + self.assertFalse(Transform(skewx=1e-9).is_scale(exactly=True)) + self.assertFalse(Transform(skewy=1e-9).is_scale(exactly=True)) + + self.assertTrue(Transform(translate=1e-9).is_scale(exactly=False)) + self.assertTrue(Transform(rotate=1e-9).is_scale(exactly=False)) + self.assertTrue(Transform(skewx=1e-9).is_scale(exactly=False)) + self.assertTrue(Transform(skewy=1e-9).is_scale(exactly=False)) + + self.assertFalse(s1.is_translate()) + self.assertFalse(s2.is_translate()) + self.assertFalse(s3.is_translate()) + self.assertFalse(s1.is_rotate()) + self.assertFalse(s2.is_rotate()) + self.assertFalse(s3.is_rotate()) + self.assertTrue(s1.is_scale()) + self.assertTrue(s2.is_scale()) + self.assertTrue(s3.is_scale()) + + def test_rotation_degrees(self): + self.assertAlmostEqual(Transform(rotate=30).rotation_degrees(), 30) + self.assertAlmostEqual(Transform(translate=(10, 20)).rotation_degrees(), 0) + self.assertAlmostEqual(Transform(scale=(1, 1)).rotation_degrees(), 0) + + self.assertAlmostEqual(Transform(rotate=35, translate=(10, 20)).rotation_degrees(), 35) + self.assertAlmostEqual(Transform(rotate=35, translate=(10, 20), scale=5).rotation_degrees(), 35) + self.assertAlmostEqual(Transform(rotate=35, translate=(10, 20), scale=(5, 5)).rotation_degrees(), 35) + + def rotation_degrees(**kwargs): + return Transform(**kwargs).rotation_degrees() + + self.assertRaises(ValueError, rotation_degrees, rotate=35, skewx=1) + self.assertRaises(ValueError, rotation_degrees, rotate=35, skewy=1) + self.assertRaises(ValueError, rotation_degrees, rotate=35, scale=(10, 11)) + self.assertRaises(ValueError, rotation_degrees, rotate=35, scale=(10, 11)) + + def test_construction_order(self): + """Test transform kwargs construction order""" + if not PY3: + self.skipTest("Construction order is known to fail on python2 (by design).") + return + + self.assertEqual(str(Transform(scale=2.0, translate=(5, 6))), + 'matrix(2 0 0 2 5 6)') + self.assertEqual(str(Transform(scale=2.0, rotate=45)), + 'matrix(1.41421 1.41421 -1.41421 1.41421 0 0)') + + x, y, angle = 5, 7, 31 + rotation = Transform(rotate=angle) + translation = Transform(translate=(x, y)) + + rotation_then_translation = translation * rotation + translation_then_rotation = rotation * translation + + tr1 = Transform(rotate=angle, translate=(x, y)) + tr2 = Transform(translate=(x, y), rotate=angle) + + self.assertNotEqual(tr1, tr2) + self.assertDeepAlmostEqual(tr1.matrix, rotation_then_translation.matrix) + self.assertDeepAlmostEqual(tr2.matrix, translation_then_rotation.matrix) + + def test_interpolate(self): + """Test interpolate with other transform""" + t1 = Transform((0,0,0,0,0,0)) + t2 = Transform((1,1,1,1,1,1)) + val = t1.interpolate(t2, 0.5) + assert all(getattr(val, a) == pytest.approx(0.5, 1e-3) for a in 'abcdef') + + + +class ScaleTest(TestCase): + """Test scale class""" + + def test_creation(self): + """Creating scales""" + self.assertEqual(BoundingInterval(0, 0), (0, 0)) + self.assertEqual(BoundingInterval(1), (1, 1)) + self.assertEqual(BoundingInterval(10), (10, 10)) + self.assertEqual(BoundingInterval(10, 20), (10, 20)) + self.assertEqual(BoundingInterval((2, 50)), (2, 50)) + self.assertEqual(repr(BoundingInterval((5, 10))), 'BoundingInterval(5, 10)') + + def test_center(self): + """Center of a scale""" + self.assertEqual(BoundingInterval(0, 0).center, 0) + self.assertEqual(BoundingInterval(0, 10).center, 5) + self.assertEqual(BoundingInterval(-10, 10).center, 0) + + def test_neg(self): + """-Span(...)""" + self.assertEqual(tuple(-BoundingInterval(-10, 10)), (-10, 10)) + self.assertEqual(tuple(-BoundingInterval(-15, 2)), (-2, 15)) + self.assertEqual(tuple(-BoundingInterval(100, 110)), (-110, -100)) + self.assertEqual(tuple(-BoundingInterval(-110, -100)), (100, 110)) + + def test_size(self): + """Size of the scale""" + self.assertEqual(BoundingInterval(0, 0).size, 0) + self.assertEqual(BoundingInterval(10, 30).size, 20) + self.assertEqual(BoundingInterval(-10, 10).size, 20) + self.assertEqual(BoundingInterval(-30, -10).size, 20) + + def test_combine(self): + """Combine scales together""" + self.assertEqual(BoundingInterval(9, 10) + BoundingInterval(4, 5), (4, 10)) + self.assertEqual(sum([BoundingInterval(4), BoundingInterval(3), BoundingInterval(10)], None), (3, 10)) + self.assertEqual(BoundingInterval(2, 2) * 2, (4, 4)) + + def test_errors(self): + """Expected errors""" + self.assertRaises(ValueError, BoundingInterval, 'foo') + + +class BoundingBoxTest(TestCase): + """Test bounding box calculations""" + + def test_bbox(self): + """Creating bounding boxes""" + self.assertEqual(tuple(BoundingBox(1, 3)), ((1, 1), (3, 3))) + self.assertEqual(tuple(BoundingBox((1, 2), 3)), ((1, 2), (3, 3))) + self.assertEqual(tuple(BoundingBox(1, (3, 4))), ((1, 1), (3, 4))) + self.assertEqual(tuple(BoundingBox((1, 2), (3, 4))), ((1, 2), (3, 4))) + self.assertEqual(repr(BoundingBox((1, 2), (3, 4))), 'BoundingBox((1, 2),(3, 4))') + + def test_bbox_sum(self): + """Test adding bboxes together""" + self.assertEqual(tuple(BoundingBox((0, 10), (0, 10)) + BoundingBox((-10, 0), (-10, 0))), ((-10, 10), (-10, 10))) + ret = sum([ + BoundingBox((-5, 0), (0, 0)), + BoundingBox((0, 5), (0, 0)), + BoundingBox((0, 0), (-5, 0)), + BoundingBox((0, 0), (0, 5))], None) + self.assertEqual(tuple(ret), ((-5, 5), (-5, 5))) + self.assertEqual(tuple(BoundingBox(-10, 2) + ret), ((-10, 5), (-5, 5))) + self.assertEqual(tuple(ret + BoundingBox(1, -10)), ((-5, 5), (-10, 5))) + + def test_bbox_neg(self): + self.assertEqual(tuple(-BoundingBox(-10, 2)), ((10, 10), (-2, -2))) + self.assertEqual(tuple(-BoundingBox((-10, 15), (2, 10))), ((-15, 10), (-10, -2))) + + def test_bbox_scale(self): + """Bounding Boxes can be scaled""" + self.assertEqual(tuple(BoundingBox(1, 3) * 2), ((2, 2), (6, 6))) + + def test_bbox_anchor_left_right(self): + """Bunding box anchoring (left to right)""" + bbox = BoundingBox((-1, 1), (10, 20)) + self.assertEqual([ + bbox.get_anchor('l', 't', 'lr'), + bbox.get_anchor('m', 't', 'lr'), + bbox.get_anchor('r', 't', 'lr'), + bbox.get_anchor('l', 't', 'rl'), + bbox.get_anchor('m', 't', 'rl'), + bbox.get_anchor('r', 't', 'rl'), + ], [-1, 0.0, 1, 1, -0.0, -1]) + + def test_bbox_anchor_top_bottom(self): + """Bunding box anchoring (top to bottom)""" + bbox = BoundingBox((10, 20), (-1, 1)) + self.assertEqual([ + bbox.get_anchor('l', 't', 'tb'), + bbox.get_anchor('l', 'm', 'tb'), + bbox.get_anchor('l', 'b', 'tb'), + bbox.get_anchor('l', 't', 'bt'), + bbox.get_anchor('l', 'm', 'bt'), + bbox.get_anchor('l', 'b', 'bt'), + ], [-1, 0.0, 1, 1, -0.0, -1]) + + def test_bbox_anchor_custom(self): + """Bounding box anchoring custom angle""" + bbox = BoundingBox((10, 10), (5, 5)) + self.assertEqual([ + bbox.get_anchor('l', 't', 0), + bbox.get_anchor('l', 't', 90), + bbox.get_anchor('l', 't', 180), + bbox.get_anchor('l', 't', 270), + bbox.get_anchor('l', 't', 45), + ], [10, -5, -10, 5, 3.5355339059327378]) + + def test_bbox_anchor_radial(self): + """Bounding box anchoring radial in/out""" + bbox = BoundingBox((10, 10), (5, 5)) + self.assertRaises(ValueError, bbox.get_anchor, 'm', 'm', 'ro') + selbox = BoundingBox((100, 100), (100, 100)) + self.assertEqual(int(bbox.get_anchor('m', 'm', 'ro', selbox)), 130) + +class SegmentTest(TestCase): + """Test special Segments""" + + def test_segment_creation(self): + """Test segments""" + self.assertEqual(DirectedLineSegment((1, 2), (3, 4)), (1, 3, 2, 4)) + self.assertEqual(repr(DirectedLineSegment((1, 2), (3, 4))), 'DirectedLineSegment((1, 2), (3, 4))') + + def test_segment_maths(self): + """Segments have calculations""" + self.assertEqual(DirectedLineSegment((0, 0), (10, 0)).angle, 0) + + +class ExtremaTest(TestCase): + """Test school formula implementation""" + + def test_cubic_extrema_1(self): + from inkex.transforms import cubic_extrema + a, b, c, d = 14.644651000000003194,-4.881549508464541276,-4.8815495084645448287,14.644651000000003194 + cmin, cmax = cubic_extrema(a, b, c, d) + self.assertAlmostEqual(cmin, 0, delta=1e-6) + self.assertAlmostEqual(cmax, a, delta=1e-6) + + def test_quadratic_extrema_1(self): + from inkex.transforms import quadratic_extrema + a, b = 5.0, 12.0 + cmin, cmax = quadratic_extrema(a, b, a) + self.assertAlmostEqual(cmin, 5, delta=1e-6) + self.assertAlmostEqual(cmax, 8.5, delta=1e-6) + + def test_quadratic_extrema_2(self): + from inkex.transforms import quadratic_extrema + a = 5.0 + cmin, cmax = quadratic_extrema(a,a,a) + self.assertAlmostEqual(cmin, a, delta=1e-6) + self.assertAlmostEqual(cmax, a, delta=1e-6) |