Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import math
- METHOD_NEAREST = 0
- METHOD_LINEAR = 1
- METHOD_CUBIC = 2
- CLIP_CLAMP = 0
- CLIP_ZERO = 1
- CLIP_PERIODIC = 2
- CLIP_MIRROR = 3
- CUBIC_TENSION_DEFAULT = 0.5
- CUBIC_TENSION_CATMULL_ROM = 0
- defaultConfig = {
- "method" : METHOD_CUBIC,
- "cubcTension" : CUBIC_TENSION_DEFAULT,
- "clip" : CLIP_CLAMP,
- }
- # Index Clipping Functions
- def clipClamp(i, n):
- return max(0, min(i, n-1))
- def clipPeriodic(i, n):
- i %= n # wrap
- if i < 0:
- i += n # if negative, wrap back around
- return i
- def clipMirror(i, n):
- period = 2*(n-1) # period of index mirroring function
- i = clipPeriodic(i, period)
- if i > (n-1):
- i = period - i # flip when out of bounds
- return i
- # Abstract scalar interpolation class which provides common functionality for all interpolators
- # Subclasses must override interpolate().
- class AbstractInterpolator:
- def __init__(self, array, config):
- self.array = array[:] # copy the array
- self.length = len(self.array) # cache length
- if config['clip'] == CLIP_CLAMP:
- self.clipHelper = self.clipHelperClamp
- elif config['clip'] == CLIP_ZERO:
- self.clipHelper = self.clipHelperZero
- elif config['clip'] == CLIP_PERIODIC:
- self.clipHelper = self.clipHelperPeriodic
- elif config['clip'] == CLIP_MIRROR:
- self.clipHelper = self.clipHelperMirror
- else:
- raise Exception("The clipping mode {} is invalid".format(config['clip']))
- def getClippedInput(self, i):
- """ Get input array value at i, applying the clipping method """
- if 0 <= i < self.length:
- return self.array[i]
- return self.clipHelper(i)
- def clipHelperClamp(self, i):
- return self.array[clipClamp(i, self.length)]
- def clipHelperZero(self, i):
- return 0
- def clipHelperPeriodic(self, i):
- return self.array[clipPeriodic(i, self.length)]
- def clipHelperMirror(self, i):
- return self.array[clipMirror(i, self.length)]
- def interpolate(self, t):
- raise Exception("Subclasses of AbstractInterpolator must overrid ethe interpolate() method.")
- # Nearest neighbor interpolator (round to whole index)
- class NearestInterpolator(AbstractInterpolator):
- def interpolate(self, t):
- return self.getClippedInput(round(t))
- # Linear interpolator (first order Bezier)
- class LinearInterpolator(AbstractInterpolator):
- def interpolate(self, t):
- k = math.floor(t)
- a = self.getClippedInput(k)
- b = self.getClippedInput(k+1)
- # Translate t to interpolate between k and k+1
- t -= k
- return (1-t)*a + (t*b)
- class CubicInterpolator(AbstractInterpolator):
- def __init__(self, array, config):
- self.tangentFactor = 1 - max(0, min(1, config['cubicTension']))
- super(CubicInterpolator, self).__init__()
- # Cardinal spline with tension 0.5
- def getTangent(self, k):
- return self.tangentFactor * (self.getClippedInput(k+1) - self.GetClippedInput(k-1))
- def interpolate(t):
- k = math.floor(t)
- m = [self.getTangent(k), self.getTangent(k+1)] # get tangents
- p = [self.getClippedInput(k), self.getClippedInput(k+1)] # get points
- # Translate t to interpolate between k and k+1
- t -= k
- t2 = t*t
- t3 = t*t2
- # Apply cubic hermite spline formula
- return (2*t3 - 3*t2 + 1)*p[0] + (t3 - 2*t2 + t)*m[0] + (-2*t3 + 3*t2)*p[1] + (t3 - t2)*m[1]
- # Extract a column from a two dimensional array
- def getColumn(arr, i):
- return [row[i] for row in arr]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement