Skip to content

Commit 181c773

Browse files
committed
Merge branch 'master' into webpack-fix-2020-08-15
2 parents 3f51605 + ac297f3 commit 181c773

File tree

5 files changed

+64
-108
lines changed

5 files changed

+64
-108
lines changed

labextension/vpython/src/glowcommlab.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ var attrsb = {'a':'userzoom', 'b':'userspin', 'c':'range', 'd':'autoscale', 'e':
472472
'p':'left', 'q':'right', 'r':'top', 's':'bottom', 't':'_cloneid',
473473
'u':'logx', 'v':'logy', 'w':'dot', 'x':'dot_radius',
474474
'y':'markers', 'z':'legend', 'A':'label','B':'delta', 'C':'marker_color',
475-
'D':'size_units', 'E':'userpan', 'F':'scroll', 'G':'choices', 'H':'depth'}
475+
'D':'size_units', 'E':'userpan', 'F':'scroll', 'G':'choices', 'H':'depth', 'I':'round'}
476476

477477
// methods are X in {'m': '23X....'}
478478
var methods = {'a':'select', 'b':'pos', 'c':'start', 'd':'stop', 'f':'clear', // unused eghijklmnopvxyzCDFAB

vpython/vpython.py

Lines changed: 49 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import sys
1414
from . import __version__, __gs_version__
1515
from ._notebook_helpers import _isnotebook
16-
from ._vector_import_helper import (vector, mag, norm, cross, dot, adjust_up,
16+
from ._vector_import_helper import (vector, mag, norm, dot, adjust_up,
1717
adjust_axis, object_rotate)
1818

1919
# List of names that will be imported from this file with import *
@@ -97,7 +97,7 @@
9797
'right':'q', 'top':'r', 'bottom':'s', '_cloneid':'t',
9898
'logx':'u', 'logy':'v', 'dot':'w', 'dot_radius':'x',
9999
'markers':'y', 'legend':'z', 'label':'A', 'delta':'B', 'marker_color':'C',
100-
'size_units':'D', 'userpan':'E', 'scroll':'F', 'choices':'G', 'depth':'H'}
100+
'size_units':'D', 'userpan':'E', 'scroll':'F', 'choices':'G', 'depth':'H', 'round':'I'}
101101

102102
# methods are X in {'m': '23X....'}
103103
# pos is normally updated as an attribute, but for interval-based trails, it is updated (multiply) as a method
@@ -113,7 +113,7 @@
113113
'marker_color']
114114

115115
__textattrs = ['text', 'align', 'caption', 'title', 'xtitle', 'ytitle', 'selected', 'label', 'capture',
116-
'append_to_caption', 'append_to_title', 'bind', 'unbind', 'pause', 'GSprint', 'choices']
116+
'append_to_caption', 'append_to_title', 'bind', 'unbind', 'pause', 'GSprint']
117117

118118
def _encode_attr2(sendval, val, ismethods):
119119
s = ''
@@ -129,10 +129,8 @@ def _encode_attr2(sendval, val, ismethods):
129129
s += "{:.16G},".format(p)
130130
s = s[:-1]
131131
elif sendval == 'plot' or sendval == 'data':
132-
if sendval == 'data' and len(val) == 0: s += "None, None,"
133-
else:
134-
for p in val:
135-
s += "{:.16G},{:.16G},".format(p[0], p[1])
132+
for p in val:
133+
s += "{:.16G},{:.16G},".format(p[0], p[1])
136134
s = s[:-1]
137135
elif sendval in ['v0', 'v1', 'v2', 'v3']: # val is the vertex object referenced by triangle or quad
138136
s += str(val.idx)
@@ -330,10 +328,10 @@ def __del__(self):
330328
# Now there is no threading in Jupyter VPython. Data is sent to the
331329
# browser from the trigger() function, which is called by a
332330
# canvas_update event sent to Python from the browser (glowcomm.js), currently
333-
# every 17 milliseconds. When trigger() is called, it immediately signals
334-
# the browser to set a timeout of 17 ms to send another signal to Python.
331+
# every 33 milliseconds. When trigger() is called, it immediately signals
332+
# the browser to set a timeout of 33 ms to send another signal to Python.
335333
# Note that a typical VPython program starts out by creating objects (constructors) and
336-
# specifying their attributes. The 17 ms signal from the browser is adequate to ensure
334+
# specifying their attributes. The 33 ms signal from the browser is adequate to ensure
337335
# prompt data transmissions to the browser.
338336

339337
# The situation with non-notebook use is similar, but the http server is threaded,
@@ -402,10 +400,9 @@ def handle_close(self, data):
402400
def _wait(cvs): # wait for an event
403401
cvs._waitfor = None
404402
if _isnotebook: baseObj.trigger() # in notebook environment must send methods immediately
405-
t = clock()
406403
while cvs._waitfor is None:
407-
rate(100)
408-
if _isnotebook: baseObj.trigger() # restart activity in glowcomm.html
404+
rate(30)
405+
return cvs._waitfor
409406

410407
class color(object):
411408
black = vector(0,0,0)
@@ -491,7 +488,7 @@ class standardAttributes(baseObj):
491488
'shininess', 'emissive', 'texture', 'frame', 'material',
492489
'make_trail', 'trail_type', 'interval',
493490
'retain', 'trail_color', 'trail_radius', 'texture',
494-
'shaftwidth', 'headwidth', 'headlength', 'pickable'],
491+
'round', 'shaftwidth', 'headwidth', 'headlength', 'pickable'],
495492
['red', 'green', 'blue','length', 'width', 'height']],
496493
'ring':[['pos', 'color', 'trail_color', 'size'],
497494
['axis', 'up'],
@@ -546,7 +543,7 @@ class standardAttributes(baseObj):
546543
['v0', 'v1', 'v2', 'v3'] ],
547544
'attach_arrow': [ [ 'color', 'attrval'],
548545
[],
549-
['shaftwidth', 'scale', 'obj', 'attr'],
546+
['shaftwidth', 'round', 'scale', 'obj', 'attr'],
550547
[] ],
551548
'attach_trail': [ ['color'],
552549
[],
@@ -587,7 +584,6 @@ def setup(self, args):
587584
del args['_objName']
588585

589586
# default values
590-
self._sizing = True # axis/size connection is the default; False for sphere, ring, text, compound
591587
self._pos = vector(0,0,0)
592588
self._axis = vector(1,0,0)
593589
self._up = vector(0,1,0)
@@ -616,6 +612,7 @@ def setup(self, args):
616612
self._pickable = True
617613
self._save_oldaxis = None # used in linking axis and up
618614
self._save_oldup = None # used in linking axis and up
615+
self._round = False
619616
_special_clone = None
620617
if '_cloneid' in args: # text, extrusion, or compound is being cloned
621618
_special_clone = args['_cloneid']
@@ -764,52 +761,32 @@ def up(self,value):
764761
def axis(self):
765762
return self._axis
766763
@axis.setter
767-
def axis(self,value): # sphere or ring or text or compound have no axis/size link
768-
currentaxis = self._axis
769-
self._axis = value
770-
if value.mag2 == 0:
771-
if self._save_oldaxis is None: self._save_oldaxis = currentaxis
772-
else:
773-
if self._save_oldaxis is not None:
774-
self._save_oldaxis = adjust_up(self._axis, value, self._up, self._save_oldaxis) # this sets self._axis and self._up
764+
def axis(self,value):
765+
self._save_oldaxis = adjust_up(self._axis, value, self._up, self._save_oldaxis) # this sets self._axis and self._up
775766
if not self._constructing:
776767
self.addattr('axis')
777-
if self._sizing:
778-
self._size._x = value.mag # changing axis length changes size.x
768+
self._size._x = value.mag # changing axis length changes size.x
779769

780770
@property
781771
def size(self):
782772
return self._size
783773
@size.setter
784-
def size(self,value): # sphere or ring or text or compound have no axis/size link
785-
currentaxis = self._axis
786-
self._size = value
787-
if value.x == 0:
788-
if self._save_oldaxis is not None:
789-
currentaxis = self._save_oldaxis
790-
self._save_oldaxis = None
791-
else:
792-
currentaxis = vector(1,0,0)
774+
def size(self,value):
775+
self._size.value = value
793776
if not self._constructing:
794777
self.addattr('size')
795-
if self._sizing:
796-
self._axis = currentaxis.norm()*value.x
778+
a = self._axis.norm() * value.x
779+
if mag(self._axis) == 0:
780+
a = vector(value.x,0,0)
781+
self._axis.value = a # changing size changes length of axis
797782

798783
@property
799784
def length(self):
800785
return self._size.x
801786
@length.setter
802787
def length(self,value):
803-
if value == 0:
804-
if self._save_oldaxis is None: self._save_oldaxis = vector(self._axis.x, self._axis.y, self._axis.z)
805-
self._axis = vector(0,0,0)
806-
self._size._x = 0
807-
else:
808-
if self._save_oldaxis is not None:
809-
self._axis = self._save_oldaxis
810-
self._save_oldaxis = None
811-
if self._size._x == 0: self.axis = vector(value, 0, 0)
812-
else: self.axis = value*self._axis.norm() # this will set length
788+
self._axis = self._axis.norm() * value
789+
self._size._x = value
813790
if not self._constructing:
814791
self.addattr('axis')
815792
self.addattr('size')
@@ -1039,24 +1016,6 @@ def rotate(self, angle=None, axis=None, origin=None):
10391016
self._pos.value = newpos
10401017
self.addattr('pos')
10411018

1042-
def bounding_box(self):
1043-
centered = ['box', 'compound', 'ellipsoid', 'sphere', 'simple_sphere', 'ring']
1044-
x = norm(self._axis)
1045-
y = norm(self._up)
1046-
z = norm(cross(x,y))
1047-
L = self._size.x
1048-
H = self._size.y
1049-
W = self._size.z
1050-
p = vector(self._pos) # make a copy of pos, so changes to p won't affect the object
1051-
if self._objName not in centered:
1052-
p = p + 0.5*L*x # move to center
1053-
pts = []
1054-
for dx in [-L/2, L/2]:
1055-
for dy in [-H/2, H/2]:
1056-
for dz in [-W/2, W/2]:
1057-
pts.append(p + dx*x + dy*y + dz*z)
1058-
return pts
1059-
10601019
def _on_size_change(self): # the vector class calls this when there's a change in x, y, or z
10611020
self._axis.value = self._axis.norm() * self._size.x # update axis length when box.size.x is changed
10621021
self.addattr('size')
@@ -1145,7 +1104,6 @@ def __init__(self, **args):
11451104
args['_default_size'] = vector(2,2,2)
11461105
args['_objName'] = "sphere"
11471106
super(sphere, self).setup(args)
1148-
self._sizing = False # no axis/size connection
11491107

11501108
@property
11511109
def radius(self):
@@ -1236,7 +1194,6 @@ def __init__(self, **args):
12361194
args['_default_size'] = vector(0.2,2.2,2.2)
12371195
args['_objName'] = "ring"
12381196
super(ring, self).setup(args)
1239-
self._sizing = False # no axis/size connection
12401197

12411198
@property
12421199
def thickness(self):
@@ -1286,12 +1243,20 @@ class arrow(standardAttributes):
12861243
def __init__(self, **args):
12871244
args['_default_size'] = vector(1,0.2,0.2)
12881245
args['_objName'] = "arrow"
1246+
self._round = False
12891247
self._shaftwidth = 0
12901248
self._headwidth = 0
12911249
self._headlength = 0
12921250

12931251
super(arrow, self).setup(args)
12941252

1253+
@property
1254+
def round(self):
1255+
return self._round
1256+
@round.setter
1257+
def round(self,value):
1258+
raise AttributeError('Cannot change the "round" attribute of an arrow.')
1259+
12951260
@property
12961261
def shaftwidth(self):
12971262
return self._shaftwidth
@@ -1323,17 +1288,27 @@ class attach_arrow(standardAttributes):
13231288
def __init__(self, obj, attr, **args):
13241289
attrs = ['pos', 'size', 'axis', 'up', 'color']
13251290
args['_default_size'] = None
1291+
a = getattr(obj, attr) # This raises an error if obj does not have attr
1292+
if not isinstance(a, vector): raise AttributeError('The attach_arrow attribute "'+attr+ '" is not a vector.')
13261293
self.obj = args['obj'] = obj.idx
13271294
self.attr = args['attr'] = attr # could be for example "velocity"
13281295
self.attrval = args['attrval'] = getattr(baseObj.object_registry[self.obj], attr)
13291296
args['_objName'] = "attach_arrow"
13301297
self._last_val = None
13311298
self._scale = 1
13321299
self._shaftwidth = 0
1300+
self._round = False
13331301
super(attach_arrow, self).setup(args)
13341302
# Only if the attribute is a user attribute do we need to add to attach_arrows:
13351303
if attr not in attrs: baseObj.attach_arrows.append(self)
13361304

1305+
@property
1306+
def round(self):
1307+
return self._round
1308+
@round.setter
1309+
def round(self,value):
1310+
raise AttributeError('Cannot change the "round" attribute of an attach_arrow.')
1311+
13371312
@property
13381313
def scale(self):
13391314
return self._scale
@@ -1492,7 +1467,6 @@ def __init__(self, objList, **args):
14921467
self.compound_idx += 1
14931468
args['_objName'] = 'compound'+str(self.compound_idx)
14941469
super(compound, self).setup(args)
1495-
self._sizing = False # no axis/size connection
14961470

14971471
for obj in objList:
14981472
# GlowScript will make the objects invisible, so need not set obj.visible
@@ -1856,8 +1830,8 @@ def pop(self, *args):
18561830
return val
18571831

18581832
def point(self,N):
1859-
if N >= len(self._pts) or (N < 0 and -N >= len(self.pts)):
1860-
raise ValueError('N = {} is outside the bounds 0-{} of the curve points'.format(N, len(self._pos)))
1833+
if N >= len(self._pts) or (N < 0 and -N > len(self._pts)):
1834+
raise ValueError('N = {} is outside the bounds 0-{} of the curve points'.format(N, len(self._pts)-1))
18611835
info = self._pts[N]
18621836
if 'color' not in info: info['color'] = self.color
18631837
if 'radius' not in info: info['radius'] = self.radius
@@ -2026,8 +2000,6 @@ def setup(self, args):
20262000
self._legend = False
20272001
self._interval = -1
20282002
self._graph = None
2029-
self._visible = True
2030-
self._data = []
20312003
objName = args['_objName']
20322004
del args['_objName']
20332005
self._constructing = True ## calls are from constructor
@@ -2163,8 +2135,6 @@ def preresolve2(self, args):
21632135
raise AttributeError("Cannot currently change color in a plot statement.")
21642136
if 'pos' in args:
21652137
return self.resolveargs(args['pos'])
2166-
elif 'data' in args:
2167-
return self.resolveargs(args['data'])
21682138
else:
21692139
raise AttributeError("Must be plot(x,y) or plot(pos=[x,y]) or plot([x,y]) or plot([x,y], ...) or plot([ [x,y], ... ])")
21702140

@@ -2173,18 +2143,8 @@ def plot(self, *args1, **args2):
21732143
p = self.preresolve1(args1)
21742144
else:
21752145
p = self.preresolve2(args2)
2176-
self._data = self._data + p
21772146
self.addmethod('plot', p)
21782147

2179-
@property
2180-
def visible(self):
2181-
return self._visible
2182-
@visible.setter
2183-
def visible(self,value):
2184-
self._visible = value
2185-
if not self._constructing:
2186-
self.addattr('visible')
2187-
21882148
def delete(self):
21892149
self.addmethod('delete', 'None')
21902150

@@ -2881,8 +2841,7 @@ def __init__(self, **args):
28812841
baseObj._canvas_constructing = False
28822842

28832843
def follow(self, obj): ## should allow a function also
2884-
if obj is None: self.addmethod('follow', 'None')
2885-
else: self.addmethod('follow', obj.idx)
2844+
self.addmethod('follow', obj.idx)
28862845

28872846
def select(self):
28882847
canvas.selected = self
@@ -3369,7 +3328,6 @@ class controls(baseObj):
33693328
def setup(self, args):
33703329
super(controls, self).__init__() ## get idx, attrsupdt from baseObj
33713330
## default values of common attributes
3372-
self._disabled = False
33733331
self._constructing = True
33743332
argsToSend = []
33753333
objName = args['_objName']
@@ -3604,8 +3562,7 @@ def choices(self):
36043562
return self._choices
36053563
@choices.setter
36063564
def choices(self, value):
3607-
self._choices = value
3608-
self.addattr('choices')
3565+
raise AttributeError('choices cannot be modified after a menu is created')
36093566

36103567
@property
36113568
def index(self):
@@ -3889,7 +3846,6 @@ def end_face_color(self,value):
38893846
class text(standardAttributes):
38903847

38913848
def __init__(self, **args):
3892-
self._sizing = False # no axis/size connection
38933849
args['_default_size'] = vector(1,1,1) # to keep standardAttributes happy
38943850
args['_objName'] = "text"
38953851
self._height = 1 ## not derived from size
@@ -3944,10 +3900,10 @@ def axis(self):
39443900
return self._axis
39453901
@axis.setter
39463902
def axis(self,value): # changing axis does not affect size
3947-
old = vector(self.axis)
3903+
oldaxis = vector(self.axis)
39483904
u = self.up
39493905
self._axis.value = value
3950-
self._save_oldaxis = adjust_up(norm(old), self._axis, self._up, self._save_oldaxis)
3906+
self._save_oldaxis = adjust_up(norm(oldaxis), self._axis, self._up, self._save_oldaxis)
39513907
self.addattr('axis')
39523908
self.addattr('up')
39533909

@@ -3985,7 +3941,7 @@ def depth(self, val): # sign issue ??
39853941
if abs(val) < 0.01*self._height:
39863942
if val < 0: val = -0.01*self._height
39873943
else: val = 0.01*self._height
3988-
self._depth = val
3944+
self._depth = value
39893945
self.addattr('depth')
39903946

39913947
@property

vpython/vpython_libraries/glow.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)