Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def make_periodic(self, continuity=None, direction=0):
""" Make the spline object periodic in a given parametric direction.
:param int continuity: The continuity along the boundary (default max).
:param int direction: The direction to ensure continuity in.
"""
direction = check_direction(direction, self.pardim)
basis = self.bases[direction]
if continuity is None:
continuity = basis.order - 2
if not -1 <= continuity <= basis.order - 2:
raise ValueError('Illegal continuity for basis of order {}: {}'.format(
continuity, basis.order
))
if continuity == -1:
raise ValueError(
'Operation not supported. '
'For discontinuous spline spaces, consider SplineObject.split().'
)
if basis.periodic >= 0:
raise ValueError('Basis is already periodic')
basis = basis.make_periodic(continuity)
for i in range(self.pardim):
derivative[i] = 1
# compute velocity in this direction
v = self.derivative(*params, d=derivative, above=above, tensor=tensor)
# normalize
if len(v.shape)==1:
speed = np.linalg.norm(v)
else:
speed = np.apply_along_axis(np.linalg.norm, -1, v)
speed = np.reshape(speed, speed.shape +(1,))
# store in result tuple
result += (v/speed,)
derivative[i] = 0
return result
i = check_direction(direction, self.pardim)
derivative[i] = 1
# compute velocity in this direction
v = self.derivative(*params, d=derivative, above=above, tensor=tensor)
# normalize
if len(v.shape)==1:
speed = np.linalg.norm(v)
else:
speed = np.apply_along_axis(np.linalg.norm, -1, v)
speed = np.reshape(speed, speed.shape +(1,))
return v / speed
def start(self, direction=None):
""" Return the start of the parametric domain.
If `direction` is given, returns the start of that direction, as a
float. If it is not given, returns the start of all directions, as a
tuple.
:param int direction: Direction in which to get the start.
:raises ValueError: For invalid direction
"""
if direction is None:
return tuple(b.start() for b in self.bases)
direction = check_direction(direction, self.pardim)
return self.bases[direction].start()
Refine an object towards the center in a direction, by sampling an
tan function.
:param obj: The object to refine
:type obj: :class:`splipy.SplineObject`
:param float S: The slope of the tan function (range 0,pi/2)
:param int n: The number of knots to insert
:param direction: The direction to refine in
"""
# some error tests on input
if n<=0:
raise ValueError('n should be greater than 0')
assert 0 < S < np.pi/2
direction = check_direction(direction, obj.pardim)
# fetch knots
knots = obj.knots()
knot_start = knots[direction][0]
knot_end = knots[direction][-1]
dk = knot_end - knot_start
# compute knot locations
new_knots = []
max_tan = tan(S)
for i in range(1,n+1):
xi = -1.0 + 2.0*i/(n+1)
xi *= S
k = knot_start + (tan(xi)+max_tan)/2/max_tan*dk
if not knot_exists(knots[direction], k):
new_knots.append(k)
"""geometric_refine(obj, alpha, n, [direction=0], [reverse=False])
Refine a spline object by making a geometric distribution of element sizes.
:param obj: The object to refine
:type obj: :class:`splipy.SplineObject`
:param float alpha: The length ratio between two sequential knot segments
:param int n: The number of knots to insert
:param direction: The direction to refine in
:param bool reverse: Set to `True` to refine towards the other end
"""
# some error tests on input
if n<=0:
raise ValueError('n should be greater than 0')
direction = check_direction(direction, obj.pardim)
if reverse:
obj.reverse(direction)
# fetch knots
knots = obj.knots()
knot_start = knots[direction][0]
knot_end = knots[direction][-1]
dk = knot_end - knot_start
# evaluate the factors
n = n+1 # redefine n to be knot spans instead of new internal knots
totProd = 1.0
totSum = 0.0
for i in range(n):
totSum += totProd
totProd *= alpha
def insert_knot(self, knot, direction=0):
""" Insert a new knot into the spline.
:param int direction: The direction to insert in
:param knot: The new knot(s) to insert
:type knot: float or [float]
:raises ValueError: For invalid direction
:return: self
"""
shape = self.controlpoints.shape
# for single-value input, wrap it into a list
knot = ensure_listlike(knot)
direction = check_direction(direction, self.pardim)
C = np.identity(shape[direction])
for k in knot:
C = self.bases[direction].insert_knot(k) @ C
self.controlpoints = np.tensordot(C, self.controlpoints, axes=(1, direction))
self.controlpoints = self.controlpoints.transpose(transpose_fix(self.pardim, direction))
return self
print(surf.order()) # prints (3,3)
print(du.order()) # prints (2,3)
:param int direction: The tangential direction
:return: Derivative spline
:rtype: SplineObject
"""
if self.rational:
raise RuntimeError('Not working for rational splines')
# if no direction is specified, return a tuple with all derivatives
if direction is None:
return tuple([self.get_derivative_spline(dim) for dim in range(self.pardim)])
else:
d = check_direction(direction, self.pardim)
k = self.knots(d, with_multiplicities=True)
p = self.order(d)-1
n = self.shape[d]
if self.bases[d].periodic < 0:
C = np.zeros((n-1, n))
for i in range(n-1):
C[i,i] = -float(p) / (k[i+p+1] - k[i+1])
C[i,i+1] = float(p) / (k[i+p+1] - k[i+1])
else:
C = np.zeros((n, n))
for i in range(n):
ip1 = np.mod(i+1,n)
C[i,i] = -float(p) / (k[i+p+1] - k[i+1])
C[i,ip1] = float(p) / (k[i+p+1] - k[i+1])
derivative_cps = np.tensordot(C, self.controlpoints, axes=(1, d))
def reverse(self, direction=0):
""" Swap the direction of a parameter by making it go in the reverse
direction. The parametric domain remains unchanged.
:param int direction: The direction to flip.
:return: self
"""
direction = check_direction(direction, self.pardim)
self.bases[direction].reverse()
# This creates the following slice programmatically
# array[:, :, :, ..., ::-1,]
# index=direction -----^
# : => slice(None, None, None)
# ::-1 => slice(None, None, -1)
direction = check_direction(direction, self.pardim)
slices = [slice(None, None, None) for _ in range(direction)] + [slice(None, None, -1)]
self.controlpoints = self.controlpoints[tuple(slices)]
return self
def end(self, direction=None):
""" Return the end of the parametric domain.
If `direction` is given, returns the end of that direction, as a float.
If it is not given, returns the end of all directions, as a tuple.
:param int direction: Direction in which to get the end.
:raises ValueError: For invalid direction
"""
if direction is None:
return tuple(b.end() for b in self.bases)
direction = check_direction(direction, self.pardim)
return self.bases[direction].end()