bspy 1.5.0__py3-none-any.whl → 2.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
bspy/spline.py CHANGED
@@ -6,14 +6,6 @@ import bspy._spline_intersection
6
6
  import bspy._spline_fitting
7
7
  import bspy._spline_operations
8
8
 
9
- def _isIterable(object):
10
- result = True
11
- try:
12
- iterator = iter(object)
13
- except TypeError:
14
- result = False
15
- return result
16
-
17
9
  class Spline:
18
10
  """
19
11
  A class to model, represent, and process piecewise polynomial tensor product
@@ -84,8 +76,8 @@ class Spline:
84
76
  self.accuracy = accuracy
85
77
  self.metadata = dict(metadata)
86
78
 
87
- def __call__(self, uvw):
88
- return self.evaluate(uvw)
79
+ def __call__(self, *uvw, **kwargs):
80
+ return self.evaluate(*uvw, **kwargs)
89
81
 
90
82
  def __repr__(self):
91
83
  return f"Spline({self.nInd}, {self.nDep}, {self.order}, " + \
@@ -94,81 +86,60 @@ class Spline:
94
86
 
95
87
  def __add__(self, other):
96
88
  if isinstance(other, Spline):
97
- return self.add(other)
98
- elif _isIterable(other):
99
- return self.translate(other)
89
+ return self.add(other, [(ix, ix) for ix in range(min(self.nInd, other.nInd))])
100
90
  else:
101
- return NotImplemented
91
+ return self.translate(other)
102
92
 
103
93
  def __radd__(self, other):
104
94
  if isinstance(other, Spline):
105
- return other.add(self)
106
- elif _isIterable(other):
107
- return self.translate(other)
95
+ return other.add(self, [(ix, ix) for ix in range(min(self.nInd, other.nInd))])
108
96
  else:
109
- return NotImplemented
97
+ return self.translate(other)
110
98
 
111
99
  def __matmul__(self, other):
112
- if _isIterable(other):
113
- if not isinstance(other, np.ndarray):
114
- other = np.array(other)
115
- if len(other.shape) == 2:
100
+ if isinstance(other, Spline):
101
+ return self.multiply(other, [(ix, ix) for ix in range(min(self.nInd, other.nInd))], 'D')
102
+ else:
103
+ other = np.atleast_1d(other)
104
+ if len(other.shape) > 1:
116
105
  return self.transform(other.T)
117
106
  else:
118
107
  return self.dot(other)
119
- else:
120
- return NotImplemented
121
108
 
122
109
  def __rmatmul__(self, other):
123
- if _isIterable(other):
124
- if not isinstance(other, np.ndarray):
125
- other = np.array(other)
126
- if len(other.shape) == 2:
110
+ if isinstance(other, Spline):
111
+ return other.multiply(self, [(ix, ix) for ix in range(min(self.nInd, other.nInd))], 'D')
112
+ else:
113
+ other = np.atleast_1d(other)
114
+ if len(other.shape) > 1:
127
115
  return self.transform(other)
128
116
  else:
129
117
  return self.dot(other)
130
- else:
131
- return NotImplemented
132
118
 
133
119
  def __mul__(self, other):
134
120
  if isinstance(other, Spline):
135
- if self.nDep == 1 or other.nDep == 1:
136
- return self.multiply(other, None, 'S')
137
- else:
138
- return self.multiply(other, None, 'D')
139
- elif np.isscalar(other) or _isIterable(other):
140
- return self.scale(other)
121
+ return self.multiply(other, [(ix, ix) for ix in range(min(self.nInd, other.nInd))], 'S')
141
122
  else:
142
- return NotImplemented
123
+ return self.scale(other)
143
124
 
144
125
  def __rmul__(self, other):
145
126
  if isinstance(other, Spline):
146
- if self.nDep == 1 or other.nDep == 1:
147
- return other.multiply(self, None, 'S')
148
- else:
149
- return other.multiply(self, None, 'D')
150
- return other.multiply(self)
151
- elif np.isscalar(other) or _isIterable(other):
152
- return self.scale(other)
127
+ return other.multiply(self, [(ix, ix) for ix in range(min(self.nInd, other.nInd))], 'S')
153
128
  else:
154
- return NotImplemented
129
+ return self.scale(other)
155
130
 
156
131
  def __sub__(self, other):
157
132
  if isinstance(other, Spline):
158
- return self.subtract(other)
159
- elif _isIterable(other):
160
- return self.translate(-np.array(other))
133
+ return self.subtract(other, [(ix, ix) for ix in range(min(self.nInd, other.nInd))])
161
134
  else:
162
- return NotImplemented
135
+ return self.translate(-np.atleast_1d(other))
163
136
 
164
137
  def __rsub__(self, other):
165
138
  if isinstance(other, Spline):
166
- return other.subtract(self)
167
- elif _isIterable(other):
139
+ return other.subtract(self, [(ix, ix) for ix in range(min(self.nInd, other.nInd))])
140
+ else:
168
141
  spline = self.scale(-1.0)
169
142
  return spline.translate(other)
170
- else:
171
- return NotImplemented
172
143
 
173
144
  def add(self, other, indMap = None):
174
145
  """
@@ -201,10 +172,12 @@ class Spline:
201
172
 
202
173
  Notes
203
174
  -----
175
+ Equivalent to spline1 + spline2 with indMap = range(min(spline1.nInd, spline2.nInd)).
176
+
204
177
  Uses `common_basis` to ensure mapped variables share the same order and knots.
205
178
  """
206
179
  if indMap is not None:
207
- indMap = [mapping if _isIterable(mapping) else (mapping, mapping) for mapping in indMap]
180
+ indMap = [(mapping, mapping) if np.isscalar(mapping) else mapping for mapping in indMap]
208
181
  return bspy._spline_operations.add(self, other, indMap)
209
182
 
210
183
  def blossom(self, uvw):
@@ -274,6 +247,33 @@ class Spline:
274
247
  """
275
248
  return bspy._spline_evaluation.bspline_values(knot, knots, splineOrder, u, derivativeOrder, taylorCoefs)
276
249
 
250
+ @staticmethod
251
+ def circular_arc(radius, angle, tolerance = None):
252
+ """
253
+ Create a 2D circular arc for a given radius and angle accurate to within a given tolerance.
254
+
255
+ Parameters
256
+ ----------
257
+ radius : `float`
258
+ The radius of the circular arc.
259
+
260
+ angle : `float`
261
+ The angle of the circular arc measured in degrees starting at the x-axis rotating counterclockwise.
262
+
263
+ tolerance : `float`, optional
264
+ The maximum allowed error in the circular arc (default is machine epsilon).
265
+
266
+ Returns
267
+ -------
268
+ spline : `Spline`
269
+ A spline curve for the circular arc (domain from 0 to 1).
270
+
271
+ See Also
272
+ --------
273
+ `section` : Fit a planar section to the list of 4-tuples of data.
274
+ `revolve` : Rotate the spline to create a surface of revolution.
275
+ """
276
+ return bspy._spline_fitting.circular_arc(radius, angle, tolerance)
277
277
 
278
278
  def clamp(self, left, right):
279
279
  """
@@ -477,7 +477,7 @@ class Spline:
477
477
  The type of product to perform on the dependent variables (default is 'S').
478
478
  'C' is for a cross product, self x other (nDep must be 2 or 3).
479
479
  'D' is for a dot product (nDep must match).
480
- 'S' is for a scalar product (nDep must be 1 for one of the splines).
480
+ 'S' is for a scalar product (nDep must match or be 1 for one of the splines).
481
481
 
482
482
  Returns
483
483
  -------
@@ -495,7 +495,7 @@ class Spline:
495
495
  Computer Aided Geometric Design 11, no. 6 (1994): 597-620.
496
496
  """
497
497
  if indMap is not None:
498
- indMap = [(*(mapping if _isIterable(mapping) else (mapping, mapping)), True) for mapping in indMap]
498
+ indMap = [(mapping, mapping, True) if np.isscalar(mapping) else (*mapping, True) for mapping in indMap]
499
499
  return bspy._spline_operations.multiplyAndConvolve(self, other, indMap, productType)
500
500
 
501
501
  def copy(self, metadata={}):
@@ -534,7 +534,28 @@ class Spline:
534
534
  """
535
535
  return bspy._spline_operations.cross(self, vector)
536
536
 
537
- def derivative(self, with_respect_to, uvw):
537
+ def curvature(self, uvw):
538
+ """
539
+ Compute the curvature of a univariate spline.
540
+
541
+ Parameters
542
+ ----------
543
+ uvw : `iterable`
544
+ An iterable of length `nInd` that specifies the values of each independent variable (the parameter values).
545
+
546
+ Returns
547
+ -------
548
+ value : scalar
549
+ The value of the curvature at the given point on the curve.
550
+
551
+ Notes
552
+ -----
553
+ Computes the curvature of the graph of the function if nDep == 1. If nDep == 1 or 2,
554
+ then the curvature is computed as a signed quantity.
555
+ """
556
+ return bspy._spline_evaluation.curvature(self, uvw)
557
+
558
+ def derivative(self, with_respect_to, *uvw, **kwargs):
538
559
  """
539
560
  Compute the derivative of the spline at given parameter values.
540
561
 
@@ -544,13 +565,18 @@ class Spline:
544
565
  An iterable of length `nInd` that specifies the integer order of derivative for each independent variable.
545
566
  A zero-order derivative just evaluates the spline normally.
546
567
 
547
- uvw : `iterable`
548
- An iterable of length `nInd` that specifies the values of each independent variable (the parameter values).
568
+ *uvw : `iterable` or iterable of iterables
569
+ An iterable of length `nInd` that specifies the values of each independent variable (the parameter values), or
570
+ an iterable of iterables of length `nInd` that specifies values for each independent variable (numpy ufunc style).
571
+
572
+ **kwargs:
573
+ For other keyword-only arguments, see the `ufunc docs <https://numpy.org/doc/stable/reference/ufuncs.html#ufuncs-kwargs>`_.
549
574
 
550
575
  Returns
551
576
  -------
552
577
  value : `numpy.array`
553
- The value of the derivative of the spline at the given parameter values.
578
+ The value of the derivative of the spline at the given parameter values (array of size nDep). If multiple points are
579
+ passed (numpy ufunc style), then multiple arrays are returned, one for each dependent variable.
554
580
 
555
581
  See Also
556
582
  --------
@@ -566,7 +592,13 @@ class Spline:
566
592
  evaluated, then the dot product of those B-splines with the vector of
567
593
  B-spline coefficients is computed.
568
594
  """
569
- return bspy._spline_evaluation.derivative(self, with_respect_to, uvw)
595
+ if len(uvw) > 1 or (not np.isscalar(uvw[0]) and len(uvw[0]) > self.nInd):
596
+ def vectorized(*uvwInstance):
597
+ return tuple(bspy._spline_evaluation.derivative(self, with_respect_to, uvwInstance))
598
+ uFunc = np.frompyfunc(vectorized, self.nInd, self.nDep)
599
+ return uFunc(*uvw, **kwargs)
600
+ else:
601
+ return bspy._spline_evaluation.derivative(self, with_respect_to, *uvw)
570
602
 
571
603
  def differentiate(self, with_respect_to = 0):
572
604
  """
@@ -623,6 +655,10 @@ class Spline:
623
655
  See Also
624
656
  --------
625
657
  `multiply` : Multiply two splines (cross, dot, or scalar product).
658
+
659
+ Notes
660
+ -----
661
+ Equivalent to spline @ vector.
626
662
  """
627
663
  return bspy._spline_operations.dot(self, vector)
628
664
 
@@ -685,19 +721,24 @@ class Spline:
685
721
  """
686
722
  return bspy._spline_domain.elevate_and_insert_knots(self, m, newKnots)
687
723
 
688
- def evaluate(self, uvw):
724
+ def evaluate(self, *uvw, **kwargs):
689
725
  """
690
726
  Compute the value of the spline at given parameter values.
691
727
 
692
728
  Parameters
693
729
  ----------
694
- uvw : `iterable`
695
- An iterable of length `nInd` that specifies the values of each independent variable (the parameter values).
730
+ *uvw : `iterable` or iterable of iterables
731
+ An iterable of length `nInd` that specifies the values of each independent variable (the parameter values), or
732
+ an iterable of iterables of length `nInd` that specifies values for each independent variable (numpy ufunc style).
733
+
734
+ **kwargs:
735
+ For other keyword-only arguments, see the `ufunc docs <https://numpy.org/doc/stable/reference/ufuncs.html#ufuncs-kwargs>`_.
696
736
 
697
737
  Returns
698
738
  -------
699
739
  value : `numpy.array`
700
- The value of the spline at the given parameter values.
740
+ The value of the spline at the given parameter values (array of size nDep). If multiple points are
741
+ passed (numpy ufunc style), then multiple arrays are returned, one for each dependent variable.
701
742
 
702
743
  See Also
703
744
  --------
@@ -705,12 +746,20 @@ class Spline:
705
746
 
706
747
  Notes
707
748
  -----
749
+ Equivalent to spline(*uvw, **kwargs).
750
+
708
751
  The evaluate method uses the de Boor recurrence relations for a B-spline
709
752
  series to evaluate a spline. The non-zero B-splines are
710
753
  evaluated, then the dot product of those B-splines with the vector of
711
754
  B-spline coefficients is computed.
712
755
  """
713
- return bspy._spline_evaluation.evaluate(self, uvw)
756
+ if len(uvw) > 1 or (not np.isscalar(uvw[0]) and len(uvw[0]) > self.nInd):
757
+ def vectorized(*uvwInstance):
758
+ return tuple(bspy._spline_evaluation.evaluate(self, uvwInstance))
759
+ uFunc = np.frompyfunc(vectorized, self.nInd, self.nDep)
760
+ return uFunc(*uvw, **kwargs)
761
+ else:
762
+ return bspy._spline_evaluation.evaluate(self, *uvw)
714
763
 
715
764
  def extrapolate(self, newDomain, continuityOrder):
716
765
  """
@@ -773,6 +822,31 @@ class Spline:
773
822
  """
774
823
  return bspy._spline_domain.fold(self, foldedInd)
775
824
 
825
+ def graph(self):
826
+ """
827
+ Generate the spline which is the graph of the given spline.
828
+
829
+ Parameters
830
+ ----------
831
+
832
+ Returns
833
+ -------
834
+ Given a spline with n independent variables and m dependent variables, generate a new
835
+ spline with n independent variables which has n + m dependent variables, the first n of
836
+ which are just the independent variables themselves. For example, given a scalar
837
+ valued function f of two variables u and v, return the spline of two variables whose
838
+ three dependent variables are (u, v, f(u,v)).
839
+
840
+ See Also
841
+ --------
842
+ `add` : Add two splines together
843
+
844
+ Notes
845
+ -----
846
+ Makes use of matrix spline multiply and tensor product addition for splines.
847
+ """
848
+ return bspy._spline_operations.graph(self)
849
+
776
850
  def insert_knots(self, newKnots):
777
851
  """
778
852
  Insert new knots into a spline.
@@ -893,9 +967,9 @@ class Spline:
893
967
  if not(self.nDep == other.nDep): raise ValueError("The number of dependent variables for both splines much match.")
894
968
  freeParameters = self.nInd + other.nInd - self.nDep
895
969
  if freeParameters == 0:
896
- return (self - other).zeros()
970
+ return self.subtract(other).zeros()
897
971
  elif freeParameters == 1:
898
- return (self - other).contours()
972
+ return self.subtract(other).contours()
899
973
  else:
900
974
  return NotImplemented
901
975
 
@@ -1061,7 +1135,7 @@ class Spline:
1061
1135
  The type of product to perform on the dependent variables (default is 'S').
1062
1136
  'C' is for a cross product, self x other (nDep must be 2 or 3).
1063
1137
  'D' is for a dot product (nDep must match).
1064
- 'S' is for a scalar product (nDep must be 1 for one of the splines).
1138
+ 'S' is for a scalar product (nDep must match or be 1 for one of the splines).
1065
1139
 
1066
1140
  Returns
1067
1141
  -------
@@ -1076,11 +1150,13 @@ class Spline:
1076
1150
 
1077
1151
  Notes
1078
1152
  -----
1153
+ Equivalent to spline1 * spline2 with indMap = range(min(spline1.nInd, spline2.nInd)) and productType = 'S'.
1154
+
1079
1155
  Taken in part from Lee, E. T. Y. "Computing a chain of blossoms, with application to products of splines."
1080
1156
  Computer Aided Geometric Design 11, no. 6 (1994): 597-620.
1081
1157
  """
1082
1158
  if indMap is not None:
1083
- indMap = [(*(mapping if _isIterable(mapping) else (mapping, mapping)), False) for mapping in indMap]
1159
+ indMap = [(mapping, mapping, False) if np.isscalar(mapping) else (*mapping, False) for mapping in indMap]
1084
1160
  return bspy._spline_operations.multiplyAndConvolve(self, other, indMap, productType)
1085
1161
 
1086
1162
  def normal(self, uvw, normalize=True, indices=None):
@@ -1156,49 +1232,60 @@ class Spline:
1156
1232
  """
1157
1233
  return bspy._spline_evaluation.range_bounds(self)
1158
1234
 
1159
- def remove_knots(self, oldKnots=((),), maxRemovalsPerKnot=0, tolerance=None):
1235
+ def remove_knot(self, iKnot):
1160
1236
  """
1161
- Remove interior knots from a spline.
1162
-
1237
+ Remove a single knot from a univariate spline.
1238
+
1163
1239
  Parameters
1164
1240
  ----------
1165
- oldKnots : `iterable` of length `nInd`, optional
1166
- An iterable that specifies the knots that can be removed from each independent variable's interior knots.
1167
- len(newKnots[ind]) == 0 if all interior knots can be removed for the `ind` independent variable (the default).
1168
- Knots that don't appear in the independent variable's interior knots are ignored.
1241
+ iKnot : integer
1242
+ index of the knot to remove from the spline
1243
+
1244
+ Returns
1245
+ -------
1246
+ spline : `Spline`
1247
+ New spline with the specified knot removed
1248
+ residual : array-like
1249
+ A vector containing the least squares residuals for each dependent variable
1169
1250
 
1170
- maxRemovalsPerKnot : `int`, optional
1171
- A non-zero count of the largest number of times a knot can be removed. For example, one means that
1172
- only one instance of each knot can be removed. (Zero means each knot can be removed completely,
1173
- which is the default.)
1251
+ See Also
1252
+ --------
1253
+ `remove_knots`
1174
1254
 
1175
- tolerance : `float` or `None`, optional
1176
- The maximum residual error permitted after removing a knot. Knots will not be removed if the
1177
- resulting residual error is above this threshold. Default is `None`, meaning all specified knots
1178
- will be removed up to `maxRemovalsPerKnot`.
1255
+ Notes
1256
+ -----
1257
+ Solves a simple least squares problem
1258
+ """
1259
+ return bspy._spline_domain.remove_knot(self, iKnot)
1260
+
1261
+ def remove_knots(self, tolerance = 1.0e-14):
1262
+ """
1263
+ Remove interior knots from a spline.
1264
+
1265
+ Parameters
1266
+ ----------
1267
+ tolerance : `float`, optional
1268
+ The maximum pointwise relative error permitted after removing all the knots. Knots will be
1269
+ removed until removal of the next knot would put the pointwise error above the threshold.
1270
+ The default is 1.0e-14 which is relative to the size of each of the dependent variables.
1179
1271
 
1180
1272
  Returns
1181
1273
  -------
1182
1274
  spline : `Spline`
1183
1275
  A spline with the knots removed.
1184
-
1185
- totalRemoved : `int`
1186
- The total number of knots removed.
1187
-
1188
- residualError : `float`
1189
- The residual error relative to the old spline. (The returned spline's accuracy is also adjusted accordingly.)
1190
1276
 
1191
1277
  See Also
1192
1278
  --------
1193
1279
  `insert_knots` : Insert new knots into a spline.
1280
+ `remove_knot` : Remove an indicated knot from a spline.
1194
1281
  `trim` : Trim the domain of a spline.
1195
1282
 
1196
1283
  Notes
1197
1284
  -----
1198
- Implements a variation of the algorithms from Tiller, Wayne. "Knot-removal algorithms for NURBS curves and surfaces." Computer-Aided Design 24, no. 8 (1992): 445-453.
1285
+ Calls `remove_knot` repeatedly until no longer possible.
1199
1286
  """
1200
- return bspy._spline_domain.remove_knots(self, oldKnots, maxRemovalsPerKnot, tolerance)
1201
-
1287
+ return bspy._spline_domain.remove_knots(self, tolerance)
1288
+
1202
1289
  def reparametrize(self, newDomain):
1203
1290
  """
1204
1291
  Reparametrize a spline to match new domain bounds. The spline's number of knots and its coefficients remain unchanged.
@@ -1241,9 +1328,46 @@ class Spline:
1241
1328
  """
1242
1329
  return bspy._spline_domain.reverse(self, variable)
1243
1330
 
1331
+ def revolve(self, angle):
1332
+ """
1333
+ Rotate the spline to create a surface of revolution (nDep must equal 2,
1334
+ first dimension provides the radius for x and y, second dimension provides the z).
1335
+
1336
+ Parameters
1337
+ ----------
1338
+ angle : `float`
1339
+ The angle of the circular arc measured in degrees starting at the x-axis rotating counterclockwise.
1340
+
1341
+ Returns
1342
+ -------
1343
+ spline : `Spline`
1344
+ Surface of revolution (first independent variable sweeps the arc from 0 to 1).
1345
+
1346
+ See Also
1347
+ --------
1348
+ `circular_arc` : Create a 2D circular arc for a given radius and angle accurate to within a given tolerance.
1349
+ """
1350
+ return bspy._spline_fitting.revolve(self, angle)
1351
+
1244
1352
  @staticmethod
1245
1353
  def ruled_surface(spline1, spline2):
1246
- return bspy._spline_fitting.ruled_surface(spline1, spline2)
1354
+ """
1355
+ Create a ruled surface between two splines.
1356
+
1357
+ Parameters
1358
+ ----------
1359
+ spline1 : `Spline`
1360
+ The first spline (must have the same nInd and nDep as the second spline).
1361
+
1362
+ spline2 : `Spline`
1363
+ The second spline (must have the same nInd and nDep as the first spline).
1364
+
1365
+ Returns
1366
+ -------
1367
+ spline : `Spline`
1368
+ Ruled surface between spline1 and spline2.
1369
+ """
1370
+ return bspy._spline_fitting.ruled_surface(spline1, spline2)
1247
1371
 
1248
1372
  def save(self, fileName):
1249
1373
  """
@@ -1288,6 +1412,10 @@ class Spline:
1288
1412
  `multiply` : Multiply two splines (cross, dot, or scalar product).
1289
1413
  `transform` : Transform a spline by the given matrix.
1290
1414
  `translate` : Translate a spline by the given translation vector.
1415
+
1416
+ Notes
1417
+ -----
1418
+ Equivalent to spline * multiplier.
1291
1419
  """
1292
1420
  return bspy._spline_operations.scale(self, multiplier)
1293
1421
 
@@ -1316,6 +1444,10 @@ class Spline:
1316
1444
  consecutive data points without passing through an intermediate inflection point (i.e. a point which
1317
1445
  has zero curvature and at which the sign of the curvature changes), then this method will fail
1318
1446
  with an error.
1447
+
1448
+ See Also
1449
+ --------
1450
+ `circular_arc` : Create a 2D circular arc for a given radius and angle accurate to within a given tolerance.
1319
1451
  """
1320
1452
  return bspy._spline_fitting.section(xytk)
1321
1453
 
@@ -1350,10 +1482,12 @@ class Spline:
1350
1482
 
1351
1483
  Notes
1352
1484
  -----
1485
+ Equivalent to spline1 - spline2 with indMap = range(min(spline1.nInd, spline2.nInd)).
1486
+
1353
1487
  Uses `common_basis` to ensure mapped variables share the same order and knots.
1354
1488
  """
1355
1489
  if indMap is not None:
1356
- indMap = [mapping if _isIterable(mapping) else (mapping, mapping) for mapping in indMap]
1490
+ indMap = [(mapping, mapping) if np.isscalar(mapping) else mapping for mapping in indMap]
1357
1491
  return self.add(other.scale(-1.0), indMap)
1358
1492
 
1359
1493
  def transform(self, matrix, maxSingularValue=None):
@@ -1378,6 +1512,10 @@ class Spline:
1378
1512
  --------
1379
1513
  `scale` : Scale a spline by the given scalar or scale vector.
1380
1514
  `translate` : Translate a spline by the given translation vector.
1515
+
1516
+ Notes
1517
+ -----
1518
+ Equivalent to spline @ matrix.
1381
1519
  """
1382
1520
  return bspy._spline_operations.transform(self, matrix, maxSingularValue)
1383
1521
 
@@ -1399,6 +1537,10 @@ class Spline:
1399
1537
  --------
1400
1538
  `scale` : Scale a spline by the given scalar or scale vector.
1401
1539
  `transform` : Transform a spline by the given matrix.
1540
+
1541
+ Notes
1542
+ -----
1543
+ Equivalent to spline + translationVector.
1402
1544
  """
1403
1545
  return bspy._spline_operations.translate(self, translationVector)
1404
1546
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bspy
3
- Version: 1.5.0
3
+ Version: 2.1.0
4
4
  Summary: Library for manipulating and rendering non-uniform b-splines
5
5
  Home-page: http://github.com/ericbrec/bspy
6
6
  Author: Eric Brechner
@@ -33,8 +33,9 @@ Requires-Dist: pyopengltk
33
33
  Library for manipulating and rendering b-spline curves, surfaces, and multidimensional manifolds with non-uniform knots in each dimension.
34
34
 
35
35
  The [Spline](https://ericbrec.github.io/bspy/bspy/spline.html) class has a method to fit multidimensional data for
36
- scalar and vector functions of single and multiple variables. Other methods add, subtract, multiply, and linearly transform splines, as well as confine spline curves to a given range.
37
- There are methods to evaluate spline values, derivatives, integrals, normals, and the Jacobian, as well as methods that return spline representations of derivatives, normals, integrals, and convolutions. In addition, there are methods to manipulate the domain of splines, including trim, join, reparametrize, reverse, add and remove knots, elevate and extrapolate, and fold and unfold. Finally, there are methods to compute the zeros and contours of a spline and to intersect two splines.
36
+ scalar and vector functions of single and multiple variables. It also has methods to create circular arcs, ruled surfaces, and surfaces of revolution.
37
+ Other methods add, subtract, multiply, and linearly transform splines, as well as confine spline curves to a given range.
38
+ There are methods to evaluate spline values, derivatives, integrals, normals, curvature, and the Jacobian, as well as methods that return spline representations of derivatives, normals, integrals, graphs, and convolutions. In addition, there are methods to manipulate the domain of splines, including trim, join, reparametrize, reverse, add and remove knots, elevate and extrapolate, and fold and unfold. Finally, there are methods to compute the zeros and contours of a spline and to intersect two splines.
38
39
 
39
40
  The [SplineOpenGLFrame](https://ericbrec.github.io/bspy/bspy/splineOpenGLFrame.html) class is an
40
41
  [OpenGLFrame](https://pypi.org/project/pyopengltk/) with custom shaders to render spline curves and surfaces.
@@ -0,0 +1,15 @@
1
+ bspy/__init__.py,sha256=XRBelbYtbhB6AWKh8DTsWVMDIteVxUm7Cf_S1fkqeEs,851
2
+ bspy/_spline_domain.py,sha256=XDctoM5Gd9KF5OhMb2eaZ6oAk4MSecCTdDqc9qX6BRE,28333
3
+ bspy/_spline_evaluation.py,sha256=1aCf4Op5zQNv-_wW2IOR13MieuYPVJrN1cJCBiI8AaY,7534
4
+ bspy/_spline_fitting.py,sha256=oPaP0kcaBUQK3T6eHPFys9rpfhkWccr8TQDPQi7Egb8,25993
5
+ bspy/_spline_intersection.py,sha256=gWs22hfIKqD6YZaeFWJO_3t0ohCNzVvxdiWJqVNlJMI,40934
6
+ bspy/_spline_operations.py,sha256=yWzOH0new78rE_movBVX2k-ais7It8t7wml6naCgcH4,42420
7
+ bspy/bspyApp.py,sha256=UxmNp_IGaG7gMVexUmA7YfuwX5iuMBr7ibW3DRan8R8,14524
8
+ bspy/drawableSpline.py,sha256=Ha7wh__aRTpGTr3cEDG49SeAyRrKtfMUQYkEZ3w9OJw,17004
9
+ bspy/spline.py,sha256=sfiYGRCP1h8rgnlHHaIYckVZ56-mRGnGpq4KdUC9qYs,69575
10
+ bspy/splineOpenGLFrame.py,sha256=77rikAbAood76cf5w1Idj7wciTwPV-Bn-yGSuRFvlJM,60616
11
+ bspy-2.1.0.dist-info/LICENSE,sha256=nLfJULN68Jw6GfCJp4xeMksGuRdyWNdgEsZGjw2twig,1091
12
+ bspy-2.1.0.dist-info/METADATA,sha256=V1uTS820oScmbcDcIsJgYpGz_i6iVQShCGDWZAfceWM,3963
13
+ bspy-2.1.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
14
+ bspy-2.1.0.dist-info/top_level.txt,sha256=fotZnJn6aCwgUbBEV3hslIko7Nw-eqtHLq2eyJLlFsY,5
15
+ bspy-2.1.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.2)
2
+ Generator: bdist_wheel (0.42.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,15 +0,0 @@
1
- bspy/__init__.py,sha256=XRBelbYtbhB6AWKh8DTsWVMDIteVxUm7Cf_S1fkqeEs,851
2
- bspy/_spline_domain.py,sha256=Fr7j6jTMAO22kL5ddVhfUdtbWHGDnpJ0q6s7HUGQ8GY,31078
3
- bspy/_spline_evaluation.py,sha256=6QqV59jHM-uJwtKaRxbBCRsJNqSNsHSibnloNCcnqfc,7059
4
- bspy/_spline_fitting.py,sha256=Q8IORwt-O8wCobmwupUMer5XcL66bn-b_kmxaXkJcAY,25303
5
- bspy/_spline_intersection.py,sha256=gWs22hfIKqD6YZaeFWJO_3t0ohCNzVvxdiWJqVNlJMI,40934
6
- bspy/_spline_operations.py,sha256=tmI8c6pN9MHzJBATGCVaXitmM4VjbGy1E0cD3-DgUzc,40879
7
- bspy/bspyApp.py,sha256=UxmNp_IGaG7gMVexUmA7YfuwX5iuMBr7ibW3DRan8R8,14524
8
- bspy/drawableSpline.py,sha256=Ha7wh__aRTpGTr3cEDG49SeAyRrKtfMUQYkEZ3w9OJw,17004
9
- bspy/spline.py,sha256=qGu_ST93T1tSVxmYGLOegIQrOAz901X0VaggWwXQ-WA,64031
10
- bspy/splineOpenGLFrame.py,sha256=77rikAbAood76cf5w1Idj7wciTwPV-Bn-yGSuRFvlJM,60616
11
- bspy-1.5.0.dist-info/LICENSE,sha256=nLfJULN68Jw6GfCJp4xeMksGuRdyWNdgEsZGjw2twig,1091
12
- bspy-1.5.0.dist-info/METADATA,sha256=SSeypwrd437pW4rS68JaCTs29hksspplZ5by-Y8ziZU,3853
13
- bspy-1.5.0.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
14
- bspy-1.5.0.dist-info/top_level.txt,sha256=fotZnJn6aCwgUbBEV3hslIko7Nw-eqtHLq2eyJLlFsY,5
15
- bspy-1.5.0.dist-info/RECORD,,
File without changes