Merge pull request #54 from playi/scale
add scale() for curves, and scaled() for pathspull/48/merge
commit
55661d18a4
|
@ -169,7 +169,7 @@ def rotate(curve, degs, origin=None):
|
||||||
def transform(z):
|
def transform(z):
|
||||||
return exp(1j*radians(degs))*(z - origin) + origin
|
return exp(1j*radians(degs))*(z - origin) + origin
|
||||||
|
|
||||||
if origin == None:
|
if origin is None:
|
||||||
if isinstance(curve, Arc):
|
if isinstance(curve, Arc):
|
||||||
origin = curve.center
|
origin = curve.center
|
||||||
else:
|
else:
|
||||||
|
@ -207,6 +207,47 @@ def translate(curve, z0):
|
||||||
"QuadraticBezier, CubicBezier, or Arc object.")
|
"QuadraticBezier, CubicBezier, or Arc object.")
|
||||||
|
|
||||||
|
|
||||||
|
def scale(curve, sx, sy=None, origin=0j):
|
||||||
|
"""Scales `curve`, about `origin`, by diagonal matrix `[[sx,0],[0,sy]]`.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
------
|
||||||
|
* If `sy` is not specified, it is assumed to be equal to `sx` and
|
||||||
|
a scalar transformation of `curve` about `origin` will be returned.
|
||||||
|
I.e.
|
||||||
|
scale(curve, sx, origin).point(t) ==
|
||||||
|
((curve.point(t) - origin) * sx) + origin
|
||||||
|
"""
|
||||||
|
|
||||||
|
if sy is None:
|
||||||
|
isy = 1j*sx
|
||||||
|
else:
|
||||||
|
isy = 1j*sy
|
||||||
|
|
||||||
|
def transform(z, sx=sx, sy=sy, origin=origin):
|
||||||
|
zeta = z - origin
|
||||||
|
return x*zeta.real + isy*zeta.imag + origin
|
||||||
|
|
||||||
|
if isinstance(curve, Path):
|
||||||
|
return Path(*[scale(seg, sx, sy, origin) for seg in curve])
|
||||||
|
elif is_bezier_segment(curve):
|
||||||
|
return bpoints2bezier([transform(z) for z in curve.bpoints()])
|
||||||
|
elif isinstance(curve, Arc):
|
||||||
|
if y is None or y == x:
|
||||||
|
return Arc(start=transform(curve.start),
|
||||||
|
radius=transform(radius, origin=0),
|
||||||
|
rotation=curve.rotation,
|
||||||
|
large_arc=curve.large_arc,
|
||||||
|
sweep=curve.sweep,
|
||||||
|
end=transform(curve.end))
|
||||||
|
else:
|
||||||
|
raise Excpetion("For `Arc` objects, only scale transforms "
|
||||||
|
"with sx==sy are implemenented.")
|
||||||
|
else:
|
||||||
|
raise TypeError("Input `curve` should be a Path, Line, "
|
||||||
|
"QuadraticBezier, CubicBezier, or Arc object.")
|
||||||
|
|
||||||
|
|
||||||
def bezier_unit_tangent(seg, t):
|
def bezier_unit_tangent(seg, t):
|
||||||
"""Returns the unit tangent of the segment at t.
|
"""Returns the unit tangent of the segment at t.
|
||||||
|
|
||||||
|
@ -637,6 +678,10 @@ class Line(object):
|
||||||
that self.translated(z0).point(t) = self.point(t) + z0 for any t."""
|
that self.translated(z0).point(t) = self.point(t) + z0 for any t."""
|
||||||
return translate(self, z0)
|
return translate(self, z0)
|
||||||
|
|
||||||
|
def scaled(self, sx, sy=None, origin=0j):
|
||||||
|
"""Scale transform. See `scale` function for further explanation."""
|
||||||
|
return scale(self, sx=sx, sy=sy, origin=origin)
|
||||||
|
|
||||||
|
|
||||||
class QuadraticBezier(object):
|
class QuadraticBezier(object):
|
||||||
# For compatibility with old pickle files.
|
# For compatibility with old pickle files.
|
||||||
|
@ -881,6 +926,10 @@ class QuadraticBezier(object):
|
||||||
that self.translated(z0).point(t) = self.point(t) + z0 for any t."""
|
that self.translated(z0).point(t) = self.point(t) + z0 for any t."""
|
||||||
return translate(self, z0)
|
return translate(self, z0)
|
||||||
|
|
||||||
|
def scaled(self, sx, sy=None, origin=0j):
|
||||||
|
"""Scale transform. See `scale` function for further explanation."""
|
||||||
|
return scale(self, sx=sx, sy=sy, origin=origin)
|
||||||
|
|
||||||
|
|
||||||
class CubicBezier(object):
|
class CubicBezier(object):
|
||||||
# For compatibility with old pickle files.
|
# For compatibility with old pickle files.
|
||||||
|
@ -1121,6 +1170,10 @@ class CubicBezier(object):
|
||||||
that self.translated(z0).point(t) = self.point(t) + z0 for any t."""
|
that self.translated(z0).point(t) = self.point(t) + z0 for any t."""
|
||||||
return translate(self, z0)
|
return translate(self, z0)
|
||||||
|
|
||||||
|
def scaled(self, sx, sy=None, origin=0j):
|
||||||
|
"""Scale transform. See `scale` function for further explanation."""
|
||||||
|
return scale(self, sx=sx, sy=sy, origin=origin)
|
||||||
|
|
||||||
|
|
||||||
class Arc(object):
|
class Arc(object):
|
||||||
def __init__(self, start, radius, rotation, large_arc, sweep, end,
|
def __init__(self, start, radius, rotation, large_arc, sweep, end,
|
||||||
|
@ -1686,6 +1739,10 @@ class Arc(object):
|
||||||
that self.translated(z0).point(t) = self.point(t) + z0 for any t."""
|
that self.translated(z0).point(t) = self.point(t) + z0 for any t."""
|
||||||
return translate(self, z0)
|
return translate(self, z0)
|
||||||
|
|
||||||
|
def scaled(self, sx, sy=None, origin=0j):
|
||||||
|
"""Scale transform. See `scale` function for further explanation."""
|
||||||
|
return scale(self, sx=sx, sy=sy, origin=origin)
|
||||||
|
|
||||||
|
|
||||||
def is_bezier_segment(x):
|
def is_bezier_segment(x):
|
||||||
return (isinstance(x, Line) or
|
return (isinstance(x, Line) or
|
||||||
|
@ -2242,3 +2299,7 @@ class Path(MutableSequence):
|
||||||
"""Returns a copy of self shifted by the complex quantity `z0` such
|
"""Returns a copy of self shifted by the complex quantity `z0` such
|
||||||
that self.translated(z0).point(t) = self.point(t) + z0 for any t."""
|
that self.translated(z0).point(t) = self.point(t) + z0 for any t."""
|
||||||
return translate(self, z0)
|
return translate(self, z0)
|
||||||
|
|
||||||
|
def scaled(self, sx, sy=None, origin=0j):
|
||||||
|
"""Scale transform. See `scale` function for further explanation."""
|
||||||
|
return scale(self, sx=sx, sy=sy, origin=origin)
|
||||||
|
|
|
@ -3,7 +3,7 @@ from __future__ import division, absolute_import, print_function
|
||||||
import unittest
|
import unittest
|
||||||
from math import sqrt, pi
|
from math import sqrt, pi
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from numpy import poly1d
|
from numpy import poly1d, linspace
|
||||||
|
|
||||||
# Internal dependencies
|
# Internal dependencies
|
||||||
from svgpathtools import *
|
from svgpathtools import *
|
||||||
|
@ -48,12 +48,12 @@ class LineTest(unittest.TestCase):
|
||||||
# This is to test the __eq__ and __ne__ methods, so we can't use
|
# This is to test the __eq__ and __ne__ methods, so we can't use
|
||||||
# assertEqual and assertNotEqual
|
# assertEqual and assertNotEqual
|
||||||
line = Line(0j, 400 + 0j)
|
line = Line(0j, 400 + 0j)
|
||||||
|
cubic = CubicBezier(600 + 500j, 600 + 350j, 900 + 650j, 900 + 500j)
|
||||||
self.assertTrue(line == Line(0, 400))
|
self.assertTrue(line == Line(0, 400))
|
||||||
self.assertTrue(line != Line(100, 400))
|
self.assertTrue(line != Line(100, 400))
|
||||||
self.assertFalse(line == str(line))
|
self.assertFalse(line == str(line))
|
||||||
self.assertTrue(line != str(line))
|
self.assertTrue(line != str(line))
|
||||||
self.assertFalse(
|
self.assertFalse(cubic == line)
|
||||||
CubicBezier(600 + 500j, 600 + 350j, 900 + 650j, 900 + 500j) == line)
|
|
||||||
|
|
||||||
|
|
||||||
class CubicBezierTest(unittest.TestCase):
|
class CubicBezierTest(unittest.TestCase):
|
||||||
|
@ -233,8 +233,9 @@ class CubicBezierTest(unittest.TestCase):
|
||||||
|
|
||||||
self.assertAlmostEqual(cub.length(), sqrt(2 * 100 * 100))
|
self.assertAlmostEqual(cub.length(), sqrt(2 * 100 * 100))
|
||||||
|
|
||||||
# A quarter circle large_arc with radius 100:
|
# A quarter circle large_arc with radius 100
|
||||||
kappa = 4 * (sqrt(2) - 1) / 3 # http://www.whizkidtech.redprince.net/bezier/circle/
|
# http://www.whizkidtech.redprince.net/bezier/circle/
|
||||||
|
kappa = 4 * (sqrt(2) - 1) / 3
|
||||||
|
|
||||||
cub = CubicBezier(
|
cub = CubicBezier(
|
||||||
complex(0, 0),
|
complex(0, 0),
|
||||||
|
@ -345,8 +346,10 @@ class QuadraticBezierTest(unittest.TestCase):
|
||||||
# This is to test the __eq__ and __ne__ methods, so we can't use
|
# This is to test the __eq__ and __ne__ methods, so we can't use
|
||||||
# assertEqual and assertNotEqual
|
# assertEqual and assertNotEqual
|
||||||
segment = QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j)
|
segment = QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j)
|
||||||
self.assertTrue(segment == QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j))
|
self.assertTrue(segment ==
|
||||||
self.assertTrue(segment != QuadraticBezier(200 + 301j, 400 + 50j, 600 + 300j))
|
QuadraticBezier(200 + 300j, 400 + 50j, 600 + 300j))
|
||||||
|
self.assertTrue(segment !=
|
||||||
|
QuadraticBezier(200 + 301j, 400 + 50j, 600 + 300j))
|
||||||
self.assertFalse(segment == Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j))
|
self.assertFalse(segment == Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j))
|
||||||
self.assertTrue(Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j) != segment)
|
self.assertTrue(Arc(0j, 100 + 50j, 0, 0, 0, 100 + 50j) != segment)
|
||||||
|
|
||||||
|
@ -439,16 +442,26 @@ class ArcTest(unittest.TestCase):
|
||||||
225.6910319606926, 1, 1,
|
225.6910319606926, 1, 1,
|
||||||
(-624.6375539637027+896.5483089399895j))
|
(-624.6375539637027+896.5483089399895j))
|
||||||
self.assertAlmostEqual(arc5.point(0.0), (725.307482226-915.554819928j))
|
self.assertAlmostEqual(arc5.point(0.0), (725.307482226-915.554819928j))
|
||||||
self.assertAlmostEqual(arc5.point(0.0909090909091), (1023.47397369-597.730444283j))
|
self.assertAlmostEqual(arc5.point(0.0909090909091),
|
||||||
self.assertAlmostEqual(arc5.point(0.181818181818), (1242.80253007-232.251400124j))
|
(1023.47397369-597.730444283j))
|
||||||
self.assertAlmostEqual(arc5.point(0.272727272727), (1365.52445614+151.273373978j))
|
self.assertAlmostEqual(arc5.point(0.181818181818),
|
||||||
self.assertAlmostEqual(arc5.point(0.363636363636), (1381.69755131+521.772981736j))
|
(1242.80253007-232.251400124j))
|
||||||
self.assertAlmostEqual(arc5.point(0.454545454545), (1290.01156757+849.231748376j))
|
self.assertAlmostEqual(arc5.point(0.272727272727),
|
||||||
self.assertAlmostEqual(arc5.point(0.545454545455), (1097.89435807+1107.12091209j))
|
(1365.52445614+151.273373978j))
|
||||||
self.assertAlmostEqual(arc5.point(0.636363636364), (820.910116547+1274.54782658j))
|
self.assertAlmostEqual(arc5.point(0.363636363636),
|
||||||
self.assertAlmostEqual(arc5.point(0.727272727273), (481.49845896+1337.94855893j))
|
(1381.69755131+521.772981736j))
|
||||||
self.assertAlmostEqual(arc5.point(0.818181818182), (107.156499251+1292.18675889j))
|
self.assertAlmostEqual(arc5.point(0.454545454545),
|
||||||
self.assertAlmostEqual(arc5.point(0.909090909091), (-271.788803303+1140.96977533j))
|
(1290.01156757+849.231748376j))
|
||||||
|
self.assertAlmostEqual(arc5.point(0.545454545455),
|
||||||
|
(1097.89435807+1107.12091209j))
|
||||||
|
self.assertAlmostEqual(arc5.point(0.636363636364),
|
||||||
|
(820.910116547+1274.54782658j))
|
||||||
|
self.assertAlmostEqual(arc5.point(0.727272727273),
|
||||||
|
(481.49845896+1337.94855893j))
|
||||||
|
self.assertAlmostEqual(arc5.point(0.818181818182),
|
||||||
|
(107.156499251+1292.18675889j))
|
||||||
|
self.assertAlmostEqual(arc5.point(0.909090909091),
|
||||||
|
(-271.788803303+1140.96977533j))
|
||||||
|
|
||||||
def test_length(self):
|
def test_length(self):
|
||||||
# I'll test the length calculations by making a circle, in two parts.
|
# I'll test the length calculations by making a circle, in two parts.
|
||||||
|
@ -485,26 +498,31 @@ class TestPath(unittest.TestCase):
|
||||||
path = Path(Line(300 + 200j, 150 + 200j),
|
path = Path(Line(300 + 200j, 150 + 200j),
|
||||||
Arc(150 + 200j, 150 + 150j, 0, 1, 0, 300 + 50j),
|
Arc(150 + 200j, 150 + 150j, 0, 1, 0, 300 + 50j),
|
||||||
Line(300 + 50j, 300 + 200j))
|
Line(300 + 50j, 300 + 200j))
|
||||||
# The points and length for this path are calculated and not regression tests.
|
# The points and length for this path are calculated and not
|
||||||
|
# regression tests.
|
||||||
self.assertAlmostEqual(path.point(0.0), (300 + 200j))
|
self.assertAlmostEqual(path.point(0.0), (300 + 200j))
|
||||||
self.assertAlmostEqual(path.point(0.14897825542), (150 + 200j))
|
self.assertAlmostEqual(path.point(0.14897825542), (150 + 200j))
|
||||||
self.assertAlmostEqual(path.point(0.5), (406.066017177 + 306.066017177j))
|
self.assertAlmostEqual(path.point(0.5), (406.066017177 + 306.066017177j))
|
||||||
self.assertAlmostEqual(path.point(1 - 0.14897825542), (300 + 50j))
|
self.assertAlmostEqual(path.point(1 - 0.14897825542), (300 + 50j))
|
||||||
self.assertAlmostEqual(path.point(1.0), (300 + 200j))
|
self.assertAlmostEqual(path.point(1.0), (300 + 200j))
|
||||||
# The errors seem to accumulate. Still 6 decimal places is more than good enough.
|
# The errors seem to accumulate. Still 6 decimal places is more
|
||||||
|
# than good enough.
|
||||||
self.assertAlmostEqual(path.length(), pi * 225 + 300, places=6)
|
self.assertAlmostEqual(path.length(), pi * 225 + 300, places=6)
|
||||||
|
|
||||||
# Little pie: M275,175 v-150 a150,150 0 0,0 -150,150 z
|
# Little pie: M275,175 v-150 a150,150 0 0,0 -150,150 z
|
||||||
path = Path(Line(275 + 175j, 275 + 25j),
|
path = Path(Line(275 + 175j, 275 + 25j),
|
||||||
Arc(275 + 25j, 150 + 150j, 0, 0, 0, 125 + 175j),
|
Arc(275 + 25j, 150 + 150j, 0, 0, 0, 125 + 175j),
|
||||||
Line(125 + 175j, 275 + 175j))
|
Line(125 + 175j, 275 + 175j))
|
||||||
# The points and length for this path are calculated and not regression tests.
|
# The points and length for this path are calculated and not
|
||||||
|
# regression tests.
|
||||||
self.assertAlmostEqual(path.point(0.0), (275 + 175j))
|
self.assertAlmostEqual(path.point(0.0), (275 + 175j))
|
||||||
self.assertAlmostEqual(path.point(0.2800495767557787), (275 + 25j))
|
self.assertAlmostEqual(path.point(0.2800495767557787), (275 + 25j))
|
||||||
self.assertAlmostEqual(path.point(0.5), (168.93398282201787 + 68.93398282201787j))
|
self.assertAlmostEqual(path.point(0.5),
|
||||||
|
(168.93398282201787 + 68.93398282201787j))
|
||||||
self.assertAlmostEqual(path.point(1 - 0.2800495767557787), (125 + 175j))
|
self.assertAlmostEqual(path.point(1 - 0.2800495767557787), (125 + 175j))
|
||||||
self.assertAlmostEqual(path.point(1.0), (275 + 175j))
|
self.assertAlmostEqual(path.point(1.0), (275 + 175j))
|
||||||
# The errors seem to accumulate. Still 6 decimal places is more than good enough.
|
# The errors seem to accumulate. Still 6 decimal places is more
|
||||||
|
# than good enough.
|
||||||
self.assertAlmostEqual(path.length(), pi * 75 + 300, places=6)
|
self.assertAlmostEqual(path.length(), pi * 75 + 300, places=6)
|
||||||
|
|
||||||
# Bumpy path: M600,350 l 50,-25
|
# Bumpy path: M600,350 l 50,-25
|
||||||
|
@ -531,14 +549,17 @@ class TestPath(unittest.TestCase):
|
||||||
# self.assertAlmostEqual(path.point(0.5), (827.730749264+147.824157418j))
|
# self.assertAlmostEqual(path.point(0.5), (827.730749264+147.824157418j))
|
||||||
# self.assertAlmostEqual(path.point(0.9), (971.284357806+106.302352605j))
|
# self.assertAlmostEqual(path.point(0.9), (971.284357806+106.302352605j))
|
||||||
# self.assertAlmostEqual(path.point(1), (1050+125j))
|
# self.assertAlmostEqual(path.point(1), (1050+125j))
|
||||||
# # The errors seem to accumulate. Still 6 decimal places is more than good enough.
|
# # The errors seem to accumulate. Still 6 decimal places is more
|
||||||
|
# # than good enough.
|
||||||
# self.assertAlmostEqual(path.length(), 928.3886394081095)
|
# self.assertAlmostEqual(path.length(), 928.3886394081095)
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
path = Path(
|
path = Path(
|
||||||
Line(start=600 + 350j, end=650 + 325j),
|
Line(start=600 + 350j, end=650 + 325j),
|
||||||
Arc(start=650 + 325j, radius=25 + 25j, rotation=-30, large_arc=0, sweep=1, end=700 + 300j),
|
Arc(start=650 + 325j, radius=25 + 25j, rotation=-30,
|
||||||
CubicBezier(start=700 + 300j, control1=800 + 400j, control2=750 + 200j, end=600 + 100j),
|
large_arc=0, sweep=1, end=700 + 300j),
|
||||||
|
CubicBezier(start=700 + 300j, control1=800 + 400j,
|
||||||
|
control2=750 + 200j, end=600 + 100j),
|
||||||
QuadraticBezier(start=600 + 100j, control=600, end=600 + 300j))
|
QuadraticBezier(start=600 + 100j, control=600, end=600 + 300j))
|
||||||
self.assertEqual(eval(repr(path)), path)
|
self.assertEqual(eval(repr(path)), path)
|
||||||
|
|
||||||
|
@ -547,13 +568,17 @@ class TestPath(unittest.TestCase):
|
||||||
# assertEqual and assertNotEqual
|
# assertEqual and assertNotEqual
|
||||||
path1 = Path(
|
path1 = Path(
|
||||||
Line(start=600 + 350j, end=650 + 325j),
|
Line(start=600 + 350j, end=650 + 325j),
|
||||||
Arc(start=650 + 325j, radius=25 + 25j, rotation=-30, large_arc=0, sweep=1, end=700 + 300j),
|
Arc(start=650 + 325j, radius=25 + 25j, rotation=-30,
|
||||||
CubicBezier(start=700 + 300j, control1=800 + 400j, control2=750 + 200j, end=600 + 100j),
|
large_arc=0, sweep=1, end=700 + 300j),
|
||||||
|
CubicBezier(start=700 + 300j, control1=800 + 400j,
|
||||||
|
control2=750 + 200j, end=600 + 100j),
|
||||||
QuadraticBezier(start=600 + 100j, control=600, end=600 + 300j))
|
QuadraticBezier(start=600 + 100j, control=600, end=600 + 300j))
|
||||||
path2 = Path(
|
path2 = Path(
|
||||||
Line(start=600 + 350j, end=650 + 325j),
|
Line(start=600 + 350j, end=650 + 325j),
|
||||||
Arc(start=650 + 325j, radius=25 + 25j, rotation=-30, large_arc=0, sweep=1, end=700 + 300j),
|
Arc(start=650 + 325j, radius=25 + 25j, rotation=-30,
|
||||||
CubicBezier(start=700 + 300j, control1=800 + 400j, control2=750 + 200j, end=600 + 100j),
|
large_arc=0, sweep=1, end=700 + 300j),
|
||||||
|
CubicBezier(start=700 + 300j, control1=800 + 400j,
|
||||||
|
control2=750 + 200j, end=600 + 100j),
|
||||||
QuadraticBezier(start=600 + 100j, control=600, end=600 + 300j))
|
QuadraticBezier(start=600 + 100j, control=600, end=600 + 300j))
|
||||||
|
|
||||||
self.assertTrue(path1 == path2)
|
self.assertTrue(path1 == path2)
|
||||||
|
@ -701,6 +726,63 @@ class TestPath(unittest.TestCase):
|
||||||
with self.assertRaises(AssertionError):
|
with self.assertRaises(AssertionError):
|
||||||
p_open.cropped(1, 0)
|
p_open.cropped(1, 0)
|
||||||
|
|
||||||
|
def test_transform_scale(self):
|
||||||
|
line1 = Line(600.5 + 350.5j, 650.5 + 325.5j)
|
||||||
|
arc1 = Arc(650 + 325j, 25 + 25j, -30, 0, 1, 700 + 300j)
|
||||||
|
arc2 = Arc(650 + 325j, 30 + 25j, -30, 0, 0, 700 + 300j)
|
||||||
|
cub1 = CubicBezier(650 + 325j, 25 + 25j, -30, 700 + 300j)
|
||||||
|
cub2 = CubicBezier(700 + 300j, 800 + 400j, 750 + 200j, 600 + 100j)
|
||||||
|
quad3 = QuadraticBezier(600 + 100j, 600, 600 + 300j)
|
||||||
|
linez = Line(600 + 300j, 600 + 350j)
|
||||||
|
|
||||||
|
bezpath = Path(line1, cub1, cub2, quad3)
|
||||||
|
bezpathz = Path(line1, cub1, cub2, quad3, linez)
|
||||||
|
path = Path(line1, arc1, cub2, quad3)
|
||||||
|
pathz = Path(line1, arc1, cub2, quad3, linez)
|
||||||
|
lpath = Path(linez)
|
||||||
|
qpath = Path(quad3)
|
||||||
|
cpath = Path(cub1)
|
||||||
|
apath = Path(arc1, arc2)
|
||||||
|
|
||||||
|
test_curves = ([bezpath, bezpathz, path, pathz, lpath, qpath, cpath, apath] +
|
||||||
|
[line1, arc1, arc2, cub1, cub2, quad3, linez])
|
||||||
|
|
||||||
|
for path_orig in test_curves:
|
||||||
|
|
||||||
|
# scale by 2 around (100, 100)
|
||||||
|
path_trns = path_orig.scaled(2.0, complex(100, 100))
|
||||||
|
|
||||||
|
# expected length
|
||||||
|
len_orig = path_orig.length()
|
||||||
|
len_trns = path_trns.length()
|
||||||
|
self.assertAlmostEqual(len_orig * 2.0, len_trns)
|
||||||
|
|
||||||
|
# expected positions
|
||||||
|
for T in linspace(0.0, 1.0, num=100):
|
||||||
|
pt_orig = path_orig.point(T)
|
||||||
|
pt_trns = path_trns.point(T)
|
||||||
|
pt_xpct = (pt_orig - complex(100, 100)) * 2.0 + complex(100, 100)
|
||||||
|
self.assertAlmostEqual(pt_xpct, pt_trns)
|
||||||
|
|
||||||
|
for path_orig in test_curves:
|
||||||
|
|
||||||
|
# scale by 0.3 around (0, -100)
|
||||||
|
# the 'almost equal' test fails at the 7th decimal place for
|
||||||
|
# some length and position tests here.
|
||||||
|
path_trns = path_orig.scaled(0.3, complex(0, -100))
|
||||||
|
|
||||||
|
# expected length
|
||||||
|
len_orig = path_orig.length()
|
||||||
|
len_trns = path_trns.length()
|
||||||
|
self.assertAlmostEqual(len_orig * 0.3, len_trns, delta = 0.000001)
|
||||||
|
|
||||||
|
# expected positions
|
||||||
|
for T in linspace(0.0, 1.0, num=100):
|
||||||
|
pt_orig = path_orig.point(T)
|
||||||
|
pt_trns = path_trns.point(T)
|
||||||
|
pt_xpct = (pt_orig - complex(0, -100)) * 0.3 + complex(0, -100)
|
||||||
|
self.assertAlmostEqual(pt_xpct, pt_trns, delta = 0.000001)
|
||||||
|
|
||||||
|
|
||||||
class Test_ilength(unittest.TestCase):
|
class Test_ilength(unittest.TestCase):
|
||||||
# See svgpathtools.notes.inv_arclength.py for information on how these
|
# See svgpathtools.notes.inv_arclength.py for information on how these
|
||||||
|
@ -992,14 +1074,18 @@ class Test_intersect(unittest.TestCase):
|
||||||
###################################################################
|
###################################################################
|
||||||
|
|
||||||
def test_line_line_0(self):
|
def test_line_line_0(self):
|
||||||
l0 = Line(start=(25.389999999999997+99.989999999999995j), end=(25.389999999999997+90.484999999999999j))
|
l0 = Line(start=(25.389999999999997+99.989999999999995j),
|
||||||
l1 = Line(start=(25.390000000000001+84.114999999999995j), end=(25.389999999999997+74.604202137430320j))
|
end=(25.389999999999997+90.484999999999999j))
|
||||||
|
l1 = Line(start=(25.390000000000001+84.114999999999995j),
|
||||||
|
end=(25.389999999999997+74.604202137430320j))
|
||||||
i = l0.intersect(l1)
|
i = l0.intersect(l1)
|
||||||
assert(len(i)) == 0
|
assert(len(i)) == 0
|
||||||
|
|
||||||
def test_line_line_1(self):
|
def test_line_line_1(self):
|
||||||
l0 = Line(start=(-124.705378549+327.696674827j), end=(12.4926214511+121.261674827j))
|
l0 = Line(start=(-124.705378549+327.696674827j),
|
||||||
l1 = Line(start=(-12.4926214511+121.261674827j), end=(124.705378549+327.696674827j))
|
end=(12.4926214511+121.261674827j))
|
||||||
|
l1 = Line(start=(-12.4926214511+121.261674827j),
|
||||||
|
end=(124.705378549+327.696674827j))
|
||||||
i = l0.intersect(l1)
|
i = l0.intersect(l1)
|
||||||
assert(len(i)) == 1
|
assert(len(i)) == 1
|
||||||
assert(abs(l0.point(i[0][0])-l1.point(i[0][1])) < 1e-9)
|
assert(abs(l0.point(i[0][0])-l1.point(i[0][1])) < 1e-9)
|
||||||
|
|
Loading…
Reference in New Issue