Cache arc length (#82)

* add Arc.__hash__()

This function returns a hash of the Arc parameters, providing a kind of
Arc object fingerprint.

* Arc: cache segment length

Computing the length of an Arc segment takes a relatively long time.

This commit teaches the Arc class to remember its segment length,
to avoid recomputing it.  It invalidates the cache and recomputes the
segment length if any of the Arc parameters have changed.
pull/114/head
Sebastian Kuzminsky 2020-06-19 19:45:56 -06:00 committed by GitHub
parent c7b6c030a6
commit 929202aa62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 19 additions and 0 deletions

View File

@ -1327,6 +1327,9 @@ class Arc(object):
self.end = end
self.autoscale_radius = autoscale_radius
self.segment_length_hash = None
self.segment_length = None
# Convenience parameters
self.phi = radians(self.rotation)
self.rot_matrix = exp(1j*self.phi)
@ -1334,6 +1337,9 @@ class Arc(object):
# Derive derived parameters
self._parameterize()
def __hash__(self):
return hash((self.start, self.radius, self.rotation, self.large_arc, self.sweep, self.end))
def __repr__(self):
params = (self.start, self.radius, self.rotation,
self.large_arc, self.sweep, self.end)
@ -1626,6 +1632,19 @@ class Arc(object):
integration, and in that case it's simpler to just do a geometric
approximation, as for cubic bezier curves."""
assert 0 <= t0 <= 1 and 0 <= t1 <= 1
if t0 == 0 and t1 == 1:
h = hash(self)
if self.segment_length_hash is None or self.segment_length_hash != h:
self.segment_length_hash = h
if _quad_available:
self.segment_length = quad(lambda tau: abs(self.derivative(tau)),
t0, t1, epsabs=error, limit=1000)[0]
else:
self.segment_length = segment_length(self, t0, t1, self.point(t0),
self.point(t1), error, min_depth, 0)
return self.segment_length
if _quad_available:
return quad(lambda tau: abs(self.derivative(tau)), t0, t1,
epsabs=error, limit=1000)[0]