Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
If *tensor* is false, there must be an equal number *n* of evaluation
points in all directions, and the return value will be an *n* × *dim*
array.
If there is only one evaluation point, a vector of length *dim* is
returned instead.
:param u,v,...: Parametric coordinates in which to evaluate
:type u,v,...: float or [float]
:param tensor: Whether to evaluate on a tensor product grid
:type tensor: bool
:return: Geometry coordinates
:rtype: numpy.array
"""
squeeze = all(is_singleton(p) for p in params)
params = [ensure_listlike(p) for p in params]
tensor = kwargs.get('tensor', True)
if not tensor and len({len(p) for p in params}) != 1:
raise ValueError('Parameters must have same length')
self._validate_domain(*params)
# Evaluate the corresponding bases at the corresponding points
# and build the result array
Ns = [b.evaluate(p) for b, p in zip(self.bases, params)]
result = evaluate(Ns, self.controlpoints, tensor)
# For rational objects, we divide out the weights, which are stored in the
# last coordinate
if self.rational:
This function returns an *n* × *dim* array, where *n* is the number of
evaluation points, and *dim* is the physical dimension of the curve.
If there is only one evaluation point, a vector of length *dim* is
returned instead.
:param t: Parametric coordinates in which to evaluate
:type t: float or [float]
:param int d: Number of derivatives to compute
:param bool above: Evaluation in the limit from above
:param bool tensor: Not used in this method
:return: Derivative array
:rtype: numpy.array
"""
if not is_singleton(d):
d = d[0]
if not self.rational or d < 2 or d > 3:
return super(Curve, self).derivative(t, d=d, above=above, tensor=tensor)
t = ensure_listlike(t)
result = np.zeros((len(t), self.dimension))
d2 = np.array(self.bases[0].evaluate(t, 2, above) @ self.controlpoints)
d1 = np.array(self.bases[0].evaluate(t, 1, above) @ self.controlpoints)
d0 = np.array(self.bases[0].evaluate(t) @ self.controlpoints)
W = d0[:, -1] # W(t)
W1 = d1[:, -1] # W'(t)
W2 = d2[:, -1] # W''(t)
if d == 2:
for i in range(self.dimension):
result[:, i] = (d2[:, i] * W * W - 2 * W1 *
returned instead.
:param u: Parametric coordinate(s) in the first direction
:type u: float or [float]
:param v: Parametric coordinate(s) in the second direction
:type v: float or [float]
:param int d: Number of derivatives to compute in each direction
:type d: [int]
:param (bool) above: Evaluation in the limit from above
:param tensor: Whether to evaluate on a tensor product grid
:type tensor: bool
:return: Derivative array *X[i,j,k]* of component *xk* evaluated at *(u[i], v[j])*
:rtype: numpy.array
"""
squeeze = all(is_singleton(t) for t in [u,v])
derivs = ensure_listlike(d, self.pardim)
if not self.rational or np.sum(derivs) < 2 or np.sum(derivs) > 3:
return super(Surface, self).derivative(u,v, d=derivs, above=above, tensor=tensor)
u = ensure_listlike(u)
v = ensure_listlike(v)
result = np.zeros((len(u), len(v), self.dimension))
# dNus = [self.bases[0].evaluate(u, d, above) for d in range(derivs[0]+1)]
# dNvs = [self.bases[1].evaluate(v, d, above) for d in range(derivs[1]+1)]
dNus = [self.bases[0].evaluate(u, d, above) for d in range(np.sum(derivs)+1)]
dNvs = [self.bases[1].evaluate(v, d, above) for d in range(np.sum(derivs)+1)]
d0ud0v = evaluate([dNus[0], dNvs[0]], self.controlpoints, tensor)
d1ud0v = evaluate([dNus[1], dNvs[0]], self.controlpoints, tensor)
d0ud1v = evaluate([dNus[0], dNvs[1]], self.controlpoints, tensor)
d1ud1v = evaluate([dNus[1], dNvs[1]], self.controlpoints, tensor)
def evaluate(self, *params):
""" Evaluate the object at given parametric values.
This function returns an *n1* × *n2* × ... × *dim* array, where *ni* is
the number of evaluation points in direction *i*, and *dim* is the
physical dimension of the object.
If there is only one evaluation point, a vector of length *dim* is
returned instead.
:param u,v,...: Parametric coordinates in which to evaluate
:type u,v,...: float or [float]
:return: Geometry coordinates
:rtype: numpy.array
"""
squeeze = is_singleton(params[0])
params = [ensure_listlike(p) for p in params]
self._validate_domain(*params)
# Evaluate the derivatives of the corresponding bases at the corresponding points
# and build the result array
N = self.bases[0].evaluate(params[0], sparse=True)
result = N @ self.controlpoints
# For rational objects, we divide out the weights, which are stored in the
# last coordinate
if self.rational:
for i in range(self.dimension):
result[..., i] /= result[..., -1]
result = np.delete(result, self.dimension, -1)
surface.derivative(0.5, 0.7, d=(1,0))
surface.derivative(0.5, 0.7, d=(0,1))
# Cross-derivative of surface:
surface.derivative(0.5, 0.7, d=(1,1))
:param u,v,...: Parametric coordinates in which to evaluate
:type u,v,...: float or [float]
:param (int) d: Order of derivative to compute
:param (bool) above: Evaluation in the limit from above
:param tensor: Whether to evaluate on a tensor product grid
:type tensor: bool
:return: Derivatives
:rtype: numpy.array
"""
squeeze = all(is_singleton(p) for p in params)
params = [ensure_listlike(p) for p in params]
derivs = kwargs.get('d', [1] * self.pardim)
derivs = ensure_listlike(derivs, self.pardim)
above = kwargs.get('above', [True] * self.pardim)
above = ensure_listlike(above, self.pardim)
tensor = kwargs.get('tensor', True)
if not tensor and len({len(p) for p in params}) != 1:
raise ValueError('Parameters must have same length')
self._validate_domain(*params)
# Evaluate the derivatives of the corresponding bases at the corresponding points