bspy 4.0__py3-none-any.whl → 4.1__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/viewer.py CHANGED
@@ -1,10 +1,10 @@
1
1
  import numpy as np
2
2
  import tkinter as tk
3
+ from tkinter.ttk import Treeview
3
4
  from tkinter.colorchooser import askcolor
4
5
  from tkinter import filedialog
5
6
  import queue, threading
6
- from bspy import SplineOpenGLFrame
7
- from bspy import Spline
7
+ from bspy import SplineOpenGLFrame, Solid, Boundary, Hyperplane, Spline
8
8
 
9
9
  class _BitCheckbutton(tk.Checkbutton):
10
10
  """A tkinter `CheckButton` that gets/sets its variable based on a given `bitmask`."""
@@ -37,7 +37,7 @@ class _BitCheckbutton(tk.Checkbutton):
37
37
 
38
38
  class Viewer(tk.Tk):
39
39
  """
40
- A tkinter viewer (`tkinter.Tk`) that hosts a `SplineOpenGLFrame`, a listbox full of
40
+ A tkinter viewer (`tkinter.Tk`) that hosts a `SplineOpenGLFrame`, a treeview full of
41
41
  splines, and a set of controls to adjust and view the selected splines.
42
42
 
43
43
  See Also
@@ -46,11 +46,11 @@ class Viewer(tk.Tk):
46
46
 
47
47
  Examples
48
48
  --------
49
- Creates a Viewer, show some splines, and launches the viewer (blocks on the main loop).
49
+ Creates a Viewer, lists three splines, drawing (selecting) the third, and launches the viewer (blocks on the main loop).
50
50
  >>> viewer = Viewer()
51
- >>> viewer.show(spline1)
52
- >>> viewer.show(spline2)
53
- >>> viewer.show(spline3)
51
+ >>> viewer.list(spline1)
52
+ >>> viewer.list(spline2)
53
+ >>> viewer.draw(spline3)
54
54
  >>> viewer.mainloop()
55
55
  """
56
56
 
@@ -76,17 +76,20 @@ class Viewer(tk.Tk):
76
76
  horizontalScroll = tk.Scrollbar(controls, orient=tk.HORIZONTAL)
77
77
  horizontalScroll.pack(side=tk.BOTTOM, fill=tk.X)
78
78
 
79
- self.listBox = tk.Listbox(controls, selectmode=tk.EXTENDED)
80
- self.listBox.pack(side=tk.LEFT, fill=tk.Y)
81
- self.listBox.bind('<<ListboxSelect>>', self._ListSelectionChanged)
82
-
79
+ treeFrame = tk.Frame(controls, width=120)
80
+ treeFrame.pack(side=tk.LEFT, fill=tk.Y)
81
+ treeFrame.pack_propagate(0)
82
+ self.treeview = Treeview(treeFrame, show='tree')
83
+ self.treeview.pack(side=tk.LEFT, fill=tk.Y)
84
+ self.treeview.bind('<<TreeviewSelect>>', self._ListSelectionChanged)
85
+ self.bind('<Control-a>', lambda *args: self.treeview.selection_add(self.treeview.get_children()))
83
86
  verticalScroll = tk.Scrollbar(controls, orient=tk.VERTICAL)
84
87
  verticalScroll.pack(side=tk.LEFT, fill=tk.Y)
85
88
 
86
- horizontalScroll.config(command=self.listBox.xview)
87
- self.listBox.configure(xscrollcommand=horizontalScroll.set)
88
- verticalScroll.config(command=self.listBox.yview)
89
- self.listBox.configure(yscrollcommand=verticalScroll.set)
89
+ horizontalScroll.config(command=self.treeview.xview)
90
+ self.treeview.configure(xscrollcommand=horizontalScroll.set)
91
+ verticalScroll.config(command=self.treeview.yview)
92
+ self.treeview.configure(yscrollcommand=verticalScroll.set)
90
93
 
91
94
  # Controls on the right
92
95
  controls = tk.Frame(self)
@@ -107,15 +110,15 @@ class Viewer(tk.Tk):
107
110
  self.scale.pack(side=tk.LEFT)
108
111
  self.scale.set(0.5)
109
112
 
110
- self.splineList = []
113
+ self.splineList = {}
114
+ self.solidList = []
111
115
  self.splineDrawList = []
112
116
  self.splineRadius = 0.0
113
117
  self.adjust = None
114
118
  self.workQueue = workQueue
115
119
  if self.workQueue is not None:
116
120
  self.work = {
117
- "show" : self.show,
118
- "draw" : self.draw,
121
+ "list" : self.list,
119
122
  "erase_all" : self.erase_all,
120
123
  "empty" : self.empty,
121
124
  "set_background_color" : self.set_background_color,
@@ -135,61 +138,99 @@ class Viewer(tk.Tk):
135
138
  self.work[work[0]](*work[1])
136
139
  self.after(200, self._check_for_work)
137
140
 
138
- def list(self, spline, name = None):
139
- """List a `Spline` in the listbox. Can be called before viewer is running."""
140
- self.frame.make_drawable(spline)
141
- if name is not None:
142
- spline.metadata["Name"] = name
143
- self.splineList.append(spline)
144
- self.listBox.insert(tk.END, spline.metadata.get("Name", f"Spline({spline.nInd}, {spline.nDep})"))
145
-
146
- def show(self, spline, name = None):
147
- """Show a `Spline` in the listbox (calls the list method, kept for compatibility). Can be called before viewer is running."""
148
- self.list(spline, name)
149
-
150
- def draw(self, spline, name = None):
151
- """Add a `Spline` to the listbox and draw it. Can be called before the viewer is running."""
152
- self.list(spline, name)
153
- self.listBox.selection_set(self.listBox.size() - 1)
154
- self.update()
141
+ def list(self, spline, name = None, fillColor=None, lineColor=None, options=None, draw=False, parentIID = ''):
142
+ """List a `Spline`, `Boundary`, or `Solid` in the treeview. Can be called before viewer is running."""
143
+ if isinstance(spline, Solid):
144
+ solid = spline
145
+ if solid.dimension != 3:
146
+ return
147
+ if name is None:
148
+ name = "Solid"
149
+ iid = self.treeview.insert('', 'end', text=name, open=False)
150
+ self.splineList[iid] = solid
151
+ self.solidList.append(solid)
152
+ if draw:
153
+ self.treeview.selection_add(iid)
154
+ for i, boundary in enumerate(solid.boundaries):
155
+ self.list(boundary, f"{name} boundary {i+1}", fillColor, lineColor, options, False, iid)
156
+ elif isinstance(spline, Boundary):
157
+ boundary = spline
158
+ if isinstance(boundary.manifold, Hyperplane):
159
+ uvMin = boundary.domain.bounds[:,0]
160
+ uvMax = boundary.domain.bounds[:,1]
161
+ xyzMinMin = boundary.manifold.evaluate(uvMin)
162
+ xyzMinMax = boundary.manifold.evaluate((uvMin[0], uvMax[1]))
163
+ xyzMaxMin = boundary.manifold.evaluate((uvMax[0], uvMin[1]))
164
+ xyzMaxMax = boundary.manifold.evaluate(uvMax)
165
+ spline = Spline(2, 3, (2, 2), (2, 2),
166
+ np.array((uvMin, uvMin, uvMax, uvMax), np.float32).T,
167
+ np.array(((xyzMinMin, xyzMaxMin), (xyzMinMax, xyzMaxMax)), np.float32).T)
168
+ elif isinstance(boundary.manifold, Spline):
169
+ spline = boundary.manifold
170
+ if not hasattr(spline, "cache"):
171
+ spline.cache = {}
172
+ spline.cache["trim"] = self.frame.tessellate2DSolid(boundary.domain)
173
+ self.list(spline, name, fillColor, lineColor, options, draw, parentIID)
174
+ else:
175
+ if "Name" not in spline.metadata:
176
+ spline.metadata["Name"] = f"Spline({spline.nInd}, {spline.nDep})" if name is None else name
177
+ if fillColor is not None:
178
+ spline.metadata["fillColor"] = fillColor
179
+ if lineColor is not None:
180
+ spline.metadata["lineColor"] = lineColor
181
+ if options is not None:
182
+ spline.metadata["options"] = options
183
+ self.frame.make_drawable(spline)
184
+ iid = self.treeview.insert(parentIID, 'end', text=spline.metadata["Name"])
185
+ self.splineList[iid] = spline
186
+ if draw:
187
+ self.treeview.selection_add(iid)
188
+
189
+ show = list
190
+
191
+ def draw(self, spline, name = None, fillColor=None, lineColor=None, options=None):
192
+ """List a `Spline`, `Boundary`, or `Solid` in the treeview and draw it in the viewer. Can be called before viewer is running."""
193
+ self.list(spline, name, fillColor, lineColor, options, True)
155
194
 
156
195
  def save_splines(self):
157
- if self.splineDrawList:
158
- initialName = self.splineDrawList[0].metadata.get("Name", "spline") + ".json"
196
+ splines = [self.splineList[item] for item in self.treeview.selection()]
197
+ if splines:
198
+ initialName = self.treeview.item(self.treeview.selection()[0])["text"] + ".json"
159
199
  fileName = filedialog.asksaveasfilename(title="Save splines", initialfile=initialName,
160
200
  defaultextension=".json", filetypes=(('Json files', '*.json'),('All files', '*.*')))
161
201
  if fileName:
162
- self.splineDrawList[0].save(fileName, *self.splineDrawList[1:])
202
+ Solid.save(fileName, *splines)
163
203
 
164
204
  def load_splines(self):
165
205
  fileName = filedialog.askopenfilename(title="Load splines",
166
206
  defaultextension=".json", filetypes=(('Json files', '*.json'),('All files', '*.*')))
167
207
  if fileName:
168
- splines = Spline.load(fileName)
208
+ splines = Solid.load(fileName)
169
209
  for spline in splines:
170
- self.list(spline)
210
+ if isinstance(spline, Spline):
211
+ self.list(spline)
212
+ else:
213
+ self.list_solid(spline)
171
214
 
172
215
  def erase_all(self):
173
- """Stop drawing all splines. Splines remain in the listbox."""
174
- self.listBox.selection_clear(0, self.listBox.size() - 1)
216
+ """Stop drawing all splines. Splines remain in the treeview."""
217
+ self.treeview.selection_set()
175
218
  self.splineRadius = 0.0
176
219
  self.frame.ResetView()
177
220
  self.update()
178
221
 
179
222
  def remove(self):
180
- """Remove splines from the listbox."""
181
- while self.listBox.curselection():
182
- item = self.listBox.curselection()[0]
183
- spline = self.splineList[item]
184
- del self.splineList[item]
223
+ """Remove splines from the treeview."""
224
+ for item in self.treeview.selection():
225
+ spline = self.splineList.pop(item)
185
226
  self.splineDrawList.remove(spline)
186
- self.listBox.delete(item, item)
227
+ self.treeview.delete(*self.treeview.selection())
187
228
  self.update()
188
229
 
189
230
  def empty(self):
190
- """Stop drawing all splines and remove them from the listbox."""
191
- self.splineList = []
192
- self.listBox.delete(0, self.listBox.size() - 1)
231
+ """Stop drawing all splines and remove them from the treeview."""
232
+ self.splineList = {}
233
+ self.treeview.delete(*self.treeview.get_children())
193
234
  self.splineRadius = 0.0
194
235
  self.frame.ResetView()
195
236
  self.update()
@@ -219,18 +260,32 @@ class Viewer(tk.Tk):
219
260
  """Update the spline draw list, set the default view, reset the bounds, and refresh the frame."""
220
261
  self.splineDrawList = []
221
262
  gotOne = False
222
- for item in self.listBox.curselection():
263
+ for item in self.treeview.selection():
223
264
  spline = self.splineList[item]
224
- coefs = spline.cache["coefs32"].T[:3]
225
- coefsAxis = tuple(range(1, spline.nInd + 1))
226
- if gotOne:
227
- splineMin = np.minimum(splineMin, coefs.min(axis=coefsAxis))
228
- splineMax = np.maximum(splineMax, coefs.max(axis=coefsAxis))
229
- else:
230
- splineMin = coefs.min(axis=coefsAxis)
231
- splineMax = coefs.max(axis=coefsAxis)
232
- gotOne = True
233
- self.splineDrawList.append(spline)
265
+ if isinstance(spline, Spline):
266
+ coefs = spline.cache["coefs32"].T[:3]
267
+ coefsAxis = tuple(range(1, spline.nInd + 1))
268
+ if gotOne:
269
+ splineMin = np.minimum(splineMin, coefs.min(axis=coefsAxis))
270
+ splineMax = np.maximum(splineMax, coefs.max(axis=coefsAxis))
271
+ else:
272
+ splineMin = coefs.min(axis=coefsAxis)
273
+ splineMax = coefs.max(axis=coefsAxis)
274
+ gotOne = True
275
+ self.splineDrawList.append(spline)
276
+ elif isinstance(spline, Solid):
277
+ for subitem in self.treeview.get_children(item):
278
+ spline = self.splineList[subitem]
279
+ coefs = spline.cache["coefs32"].T[:3]
280
+ coefsAxis = tuple(range(1, spline.nInd + 1))
281
+ if gotOne:
282
+ splineMin = np.minimum(splineMin, coefs.min(axis=coefsAxis))
283
+ splineMax = np.maximum(splineMax, coefs.max(axis=coefsAxis))
284
+ else:
285
+ splineMin = coefs.min(axis=coefsAxis)
286
+ splineMax = coefs.max(axis=coefsAxis)
287
+ gotOne = True
288
+ self.splineDrawList.append(spline)
234
289
 
235
290
  if gotOne:
236
291
  newRadius = 0.5 * np.max(splineMax - splineMin)
@@ -263,7 +318,7 @@ class Viewer(tk.Tk):
263
318
  frame.DrawSpline(spline, transform)
264
319
 
265
320
  def _ListSelectionChanged(self, event):
266
- """Handle when the listbox selection has changed."""
321
+ """Handle when the treeview selection has changed."""
267
322
  self.update()
268
323
 
269
324
  def _ChangeFrameMode(self):
@@ -519,7 +574,7 @@ class Graphics:
519
574
 
520
575
  See Also
521
576
  --------
522
- `Viewer` : A tkinter app (`tkinter.Tk`) that hosts a `SplineOpenGLFrame`, a listbox full of
577
+ `Viewer` : A tkinter app (`tkinter.Tk`) that hosts a `SplineOpenGLFrame`, a treeview full of
523
578
  splines, and a set of controls to adjust and view the selected splines.
524
579
 
525
580
  Examples
@@ -541,38 +596,26 @@ class Graphics:
541
596
  viewer = Viewer(workQueue=self.workQueue)
542
597
  viewer.mainloop()
543
598
 
544
- def list(self, spline, name = None):
545
- """List a `Spline` in the listbox."""
546
- if name is not None:
547
- spline.metadata["Name"] = name
548
- elif "Name" not in spline.metadata:
599
+ def list(self, spline, name = None, fillColor=None, lineColor=None, options=None, draw=False):
600
+ """List a `Spline`, `Boundary`, or `Solid` in the treeview. Can be called before viewer is running."""
601
+ if name is None:
549
602
  for name, value in self.variableDictionary.items():
550
603
  if value is spline:
551
- spline.metadata["Name"] = name
552
604
  break
553
- self.workQueue.put(("show", (spline,)))
554
-
555
- def show(self, spline, name = None):
556
- """Show a `Spline` in the listbox (calls list method, kept for compatibility)."""
557
- self.list(spline, name)
605
+ self.workQueue.put(("list", (spline, name, fillColor, lineColor, options, draw)))
558
606
 
559
- def draw(self, spline, name = None):
560
- """Add a `Spline` to the listbox and draw it."""
561
- if name is not None:
562
- spline.metadata["Name"] = name
563
- elif "Name" not in spline.metadata:
564
- for name, value in self.variableDictionary.items():
565
- if value is spline:
566
- spline.metadata["Name"] = name
567
- break
568
- self.workQueue.put(("draw", (spline,)))
607
+ show = list
608
+
609
+ def draw(self, spline, name = None, fillColor=None, lineColor=None, options=None):
610
+ """List a `Spline`, `Boundary`, or `Solid` in the treeview and draw it in the viewer. Can be called before viewer is running."""
611
+ self.list(spline, name, fillColor, lineColor, options, True)
569
612
 
570
613
  def erase_all(self):
571
- """Stop drawing all splines. Splines remain in the listbox."""
614
+ """Stop drawing all splines. Splines remain in the treeview."""
572
615
  self.workQueue.put(("erase_all", ()))
573
616
 
574
617
  def empty(self):
575
- """Stop drawing all splines and remove them from the listbox."""
618
+ """Stop drawing all splines and remove them from the treeview."""
576
619
  self.workQueue.put(("empty", ()))
577
620
 
578
621
  def set_background_color(self, r, g=None, b=None, a=None):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bspy
3
- Version: 4.0
3
+ Version: 4.1
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
@@ -32,20 +32,25 @@ Requires-Dist: pyopengltk
32
32
  # BSpy
33
33
  Library for manipulating and rendering B-spline curves, surfaces, and multidimensional manifolds with non-uniform knots in each dimension.
34
34
 
35
+ The [Manifold](https://ericbrec.github.io/BSpy/bspy/manifold.html) abstract base class for [Hyperplane](https://ericbrec.github.io/BSpy/bspy/hyperplane.html) and [Spline](https://ericbrec.github.io/BSpy/bspy/spline.html).
36
+
35
37
  The [Spline](https://ericbrec.github.io/BSpy/bspy/spline.html) class has a method to fit multidimensional data for
36
38
  scalar and vector functions of single and multiple variables. It also has methods to create points, lines, circular arcs, spheres, cones, cylinders, tori, ruled surfaces, surfaces of revolution, and four-sided patches.
37
39
  Other methods add, subtract, and multiply splines, as well as confine spline curves to a given range.
38
40
  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, transpose, reverse, add and remove knots, elevate and extrapolate, and fold and unfold. There are methods to manipulate the range of splines, including dot product, cross product, translate, rotate, scale, and transform. Finally, there are methods to compute the zeros and contours of a spline and to intersect two splines.
39
41
 
42
+ The [Hyperplane](https://ericbrec.github.io/BSpy/bspy/hyperplane.html) class has methods to create individual hyperplanes in any dimension, along with axis-aligned hyperplanes and hypercubes.
43
+
44
+ The [Solid](https://ericbrec.github.io/BSpy/bspy/solid.html) class has methods to construct n-dimensional solids from trimmed [Manifold](https://ericbrec.github.io/BSpy/bspy/manifold.html) boundaries. Each solid consists of a list of boundaries and a Boolean value that indicates if the solid contains infinity. Each [Boundary](https://ericbrec.github.io/BSpy/bspy/solid.html) consists of a manifold (currently a [Hyperplane](https://ericbrec.github.io/BSpy/bspy/hyperplane.html) or [Spline](https://ericbrec.github.io/BSpy/bspy/spline.html)) and a domain solid that trims the manifold. Solids have methods to form the intersection, union, difference, and complement of solids. There are methods to compute point containment, winding numbers, surface integrals, and volume integrals. There are also methods to translate, transform, and slice solids.
45
+
40
46
  The [SplineOpenGLFrame](https://ericbrec.github.io/BSpy/bspy/splineOpenGLFrame.html) class is an
41
47
  [OpenGLFrame](https://pypi.org/project/pyopengltk/) with custom shaders to render spline curves and surfaces. Spline surfaces with more
42
48
  than 3 dependent variables will have their added dimensions rendered as colors (up to 6 dependent variables are supported). Only tested on Windows systems.
43
49
 
44
-
45
50
  The [Viewer](https://ericbrec.github.io/BSpy/bspy/viewer.html) class is a
46
51
  [tkinter.Tk](https://docs.python.org/3/library/tkinter.html) app that hosts a
47
52
  [SplineOpenGLFrame](https://ericbrec.github.io/BSpy/bspy/splineOpenGLFrame.html),
48
- a listbox full of splines, and a set of controls to adjust and view the selected splines. Only tested on Windows systems.
53
+ a tree view full of solids and splines, and a set of controls to adjust and view the selected solids and splines. Only tested on Windows systems.
49
54
 
50
55
  The [Graphics](https://ericbrec.github.io/BSpy/bspy/viewer.html#Graphics) class is a graphics engine to display splines.
51
56
  It launches a [Viewer](https://ericbrec.github.io/BSpy/bspy/viewer.html) and issues commands to the viewer for use
@@ -0,0 +1,17 @@
1
+ bspy/__init__.py,sha256=q8XOJK3FsbHybfy2CSPufY5Z5SQJNxK_tH-d9zXR5vY,1308
2
+ bspy/_spline_domain.py,sha256=kklvRrSeEEUUQ48yXvCCDzHMRPd4_BHICxAsOhyxhjk,30178
3
+ bspy/_spline_evaluation.py,sha256=3cWD3sL4odnZ4w1DBQFmUnPg2PuPpSfaGfNcBl8ZrW0,7079
4
+ bspy/_spline_fitting.py,sha256=hFhPyL39d87IGZiAs8teFhYZHxPN1EvzQYxHcDTeBLw,45318
5
+ bspy/_spline_intersection.py,sha256=EV19Qt-kccr5K17aB1EETJXENdz-_UJlYTKWjK-ueJU,58324
6
+ bspy/_spline_operations.py,sha256=y98zl-r31xsZzD6X0VYbuEPUabg3UNC_ERCbkXZRZXU,42530
7
+ bspy/hyperplane.py,sha256=gRConjCEdMAjP8UXA7kaYU--NQHr1tYiVHtmZzLNnqY,24639
8
+ bspy/manifold.py,sha256=29KkZXvv759-aywGd7Ek4Egm-DCBNDTEfusW_Az1kC4,14244
9
+ bspy/solid.py,sha256=qbHofcdNbMTaoCCfKfxloYiEqZDsxfOIJD3MwZguEJ8,36444
10
+ bspy/spline.py,sha256=747e_kChnGnN2Y93EcP9XymDrf2T4NFFweFB_YghEvw,94776
11
+ bspy/splineOpenGLFrame.py,sha256=ezPUyDr9QKF0KU7H6XjHL-HhN23ffC8KbxGhGgGJhQ0,95843
12
+ bspy/viewer.py,sha256=HdtjAj5CZnv4VKcfS8MhT-ciPEPRVNUTp-02TW1NQSU,33717
13
+ bspy-4.1.dist-info/LICENSE,sha256=nLfJULN68Jw6GfCJp4xeMksGuRdyWNdgEsZGjw2twig,1091
14
+ bspy-4.1.dist-info/METADATA,sha256=Fe5wy39gSJOVk7Z3Ruz1Utm3oYZQlPyyJJMYGu6YvP4,6152
15
+ bspy-4.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
16
+ bspy-4.1.dist-info/top_level.txt,sha256=fotZnJn6aCwgUbBEV3hslIko7Nw-eqtHLq2eyJLlFsY,5
17
+ bspy-4.1.dist-info/RECORD,,
bspy-4.0.dist-info/RECORD DELETED
@@ -1,15 +0,0 @@
1
- bspy/__init__.py,sha256=p2tWAqZDc7JQ6-9-N-RLjscETpU5UPxgPB03Yc6Divk,923
2
- bspy/_spline_domain.py,sha256=-DWbiUdYkG9AX-_IILWIe6Alj-U3QJ9vcOi3jp7jCv0,29737
3
- bspy/_spline_evaluation.py,sha256=DErClOQrvXlK6uBZTwsGxAd6GXxBwXF9FIVnt57dOWI,6904
4
- bspy/_spline_fitting.py,sha256=H5yWhYHwrpoqb7dN2lF7eDNhSHH5XngG7TYVCYyydlQ,46778
5
- bspy/_spline_intersection.py,sha256=0aoUB5vKKObOM5B6W2U6MjqB91o3xXBPJr8j5a-hZ8U,47777
6
- bspy/_spline_operations.py,sha256=C3O-v8FlQbUc3szKZJIKS0RkjjbqV38aQL-IDSqMVL8,42222
7
- bspy/manifold.py,sha256=l2mOKBe-ejvXIIi3S3VpZ1ONuVZI1DPbdpibRwR1fu8,4343
8
- bspy/spline.py,sha256=RH-OSleMxFgTyv9nCyOSmzSZIKU1R3Esh_R1nKFrekI,89834
9
- bspy/splineOpenGLFrame.py,sha256=1-xaw4LnAqpu4DbSDDquRiN7eQe1bu6A5QLrreLy35Y,82849
10
- bspy/viewer.py,sha256=CrPLdhPmCSuUeScAjxbb19iSbfxb2Ft9KBWx-K4IjLs,30727
11
- bspy-4.0.dist-info/LICENSE,sha256=nLfJULN68Jw6GfCJp4xeMksGuRdyWNdgEsZGjw2twig,1091
12
- bspy-4.0.dist-info/METADATA,sha256=CKnqv9yg3KJayKnOrPu_eC-W5hWsgeBi89eYtQj50l0,4857
13
- bspy-4.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
14
- bspy-4.0.dist-info/top_level.txt,sha256=fotZnJn6aCwgUbBEV3hslIko7Nw-eqtHLq2eyJLlFsY,5
15
- bspy-4.0.dist-info/RECORD,,
File without changes
File without changes
File without changes