fixed scaled (before cleanup)

pull/55/head
Andy 2018-07-06 22:59:28 -04:00
parent 2cb56c50c5
commit fd521748fa
3 changed files with 81 additions and 35 deletions

View File

@ -1,8 +0,0 @@
<?xml version="1.0" ?>
<svg baseProfile="full" height="600px" version="1.1" viewBox="161.5 79.0 152.0 242.0" width="377px" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<path d="M 300.0,100.0 C 100.0,100.0 200.0,200.0 200.0,300.0" fill="none" stroke="blue" stroke-width="0.2"/>
<path d="M 175.0,162.5 L 175.0,236.805280985" fill="none" stroke="green" stroke-width="0.2"/>
<path d="M 175.0,162.5 L 249.305280985,162.5" fill="none" stroke="pink" stroke-width="0.2"/>
<circle cx="175.0" cy="162.5" fill="#ff0000" r="1.0"/>
</svg>

Before

Width:  |  Height:  |  Size: 618 B

View File

@ -225,25 +225,31 @@ def scale(curve, sx, sy=None, origin=0j):
else:
isy = 1j*sy
def transform(z, origin=origin):
zeta = z - origin
return sx*zeta.real + isy*zeta.imag + origin
def _scale(z):
if sy is None:
return sx*z
return sx*z.real + isy*z.imag
def scale_bezier(bez):
p = [_scale(c) for c in bez2poly(bez)]
p[-1] += origin - _scale(origin)
return poly2bez(p)
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()])
return scale_bezier(curve)
elif isinstance(curve, Arc):
if sy is None or sy == sx:
return Arc(start=transform(curve.start),
radius=transform(curve.radius, origin=0),
return Arc(start=sx*(curve.start - origin) + origin,
radius=sx*curve.radius,
rotation=curve.rotation,
large_arc=curve.large_arc,
sweep=curve.sweep,
end=transform(curve.end))
end=sx*(curve.end - origin) + origin)
else:
raise Exception("For `Arc` objects, only scale transforms "
"with sx==sy are implemented.")
raise Exception("\nFor `Arc` objects, only scale transforms "
"with sx==sy are implemented.\n")
else:
raise TypeError("Input `curve` should be a Path, Line, "
"QuadraticBezier, CubicBezier, or Arc object.")

View File

@ -7,6 +7,7 @@ import numpy as np
# Internal dependencies
from svgpathtools import *
from svgpathtools.path import _NotImplemented4ArcException
# An important note for those doing any debugging:
# ------------------------------------------------
@ -780,39 +781,86 @@ class TestPath(unittest.TestCase):
isinstance(curve, Path) and
any(isinstance(seg, Arc) for seg in curve))
# find seg which t lands on for failure reporting
seg = curve
if isinstance(curve, Path):
seg_idx, seg_t = curve.T2t(t)
seg = curve[seg_idx]
_fail_msg = "Failure!\nseg {}\n".format(seg)
# case where no `sy` and no `origin` given
curve_scaled = curve.scaled(sx)
# res = curve_scaled.point(t)
if isinstance(curve, Path):
res = curve_scaled[seg_idx].point(seg_t)
else:
res = curve_scaled.point(t)
ans = scale_a_point(pt, sx, None)
self.assertAlmostEqual(ans, curve.scaled(sx).point(t))
fail_msg = _fail_msg + ("curve.scaled({}, {}, {}) = \n{}\n"
"".format(sx, None, None, curve_scaled))
# fail_msg += "curve.point({}) = {}".format(t, res)
fail_msg += "seg_scaled.point({}) = {}\n".format(seg_t, res)
fail_msg += "ans = {}".format(ans)
self.assertAlmostEqual(ans, res, places=4, msg=fail_msg)
# case where no `sy` and random `origin` given
# case where random `origin` given but no `sy`
ans = scale_a_point(pt, sx, None, origin)
self.assertAlmostEqual(ans,
curve.scaled(sx, origin=origin).point(t))
# the cases with sx != sy are not yet imp
if isinstance(curve, Arc):
continue
curve_scaled = curve.scaled(sx, origin=origin)
# res = curve_scaled.point(t)
if isinstance(curve, Path):
res = curve_scaled[seg_idx].point(seg_t)
else:
res = curve_scaled.point(t)
fail_msg = _fail_msg + ("curve.scaled({}, {}, {}) = \n{}\n"
"".format(sx, None, origin, curve_scaled))
# fail_msg += "curve.point({}) = {}\n".format(t, res)
fail_msg += "seg_scaled.point({}) = {}\n".format(seg_t, res)
fail_msg += "ans = {}".format(ans)
self.assertAlmostEqual(ans, res, places=4, msg=fail_msg)
# case where `sx != sy`, and no `origin` given
ans = scale_a_point(pt, sx, sy)
if has_arc:
self.assertRaises(Exception, curve.scaled(sx, sy).point(t))
if has_arc: # the cases with sx != sy are not yet imp for arcs
with self.assertRaises(Exception):
curve.scaled(sx, sy).point(t)
else:
self.assertAlmostEqual(ans, curve.scaled(sx, sy).point(t))
curve_scaled = curve.scaled(sx, sy)
seg_scaled = seg.scaled(sx, sy)
# res = curve_scaled.point(t)
if isinstance(curve, Path):
res = curve_scaled[seg_idx].point(seg_t)
else:
res = curve_scaled.point(t)
fail_msg = _fail_msg + ("curve.scaled({}, {}, {}) = \n{}\n"
"".format(sx, sy, None, curve_scaled))
# fail_msg += "curve.point({}) = {}\n".format(t, res)
fail_msg += "seg_scaled.point({}) = {}\n".format(seg_t, res)
fail_msg += "ans = {}".format(ans)
self.assertAlmostEqual(ans, res, places=4, msg=fail_msg)
# case where `sx != sy`, and random `origin` given
ans = scale_a_point(pt, sx, sy, origin)
if has_arc:
self.assertRaises(Exception,
curve.scaled(sx, sy, origin).point(t))
if has_arc: # the cases with sx != sy are not yet imp for arcs
with self.assertRaises(Exception):
curve.scaled(sx, sy, origin).point(t)
else:
self.assertAlmostEqual(ans,
curve.scaled(sx, sy, origin).point(t))
curve_scaled = curve.scaled(sx, sy, origin)
# res = curve_scaled.point(t)
if isinstance(curve, Path):
res = curve_scaled[seg_idx].point(seg_t)
else:
res = curve_scaled.point(t)
fail_msg = _fail_msg + ("curve.scaled({}, {}, {}) = \n{}\n"
"".format(sx, sy, origin, curve_scaled))
# fail_msg += "curve.point({}) = {}\n".format(t, res)
fail_msg += "seg_scaled.point({}) = {}\n".format(seg_t, res)
fail_msg += "ans = {}".format(ans)
self.assertAlmostEqual(ans, res, places=4, msg=fail_msg)
# more tests for scalar (i.e. `sx == sy`) case
for curve in test_curves:
# scale by 2 around (100, 100)
scaled_curve = curve.scaled(2.0, complex(100, 100))
scaled_curve = curve.scaled(2.0, origin=complex(100, 100))
# expected length
len_orig = curve.length()
@ -829,7 +877,7 @@ class TestPath(unittest.TestCase):
# scale by 0.3 around (0, -100)
# the 'almost equal' test fails at the 7th decimal place for
# some length and position tests here.
scaled_curve = curve.scaled(0.3, complex(0, -100))
scaled_curve = curve.scaled(0.3, origin=complex(0, -100))
# expected length
len_orig = curve.length()