1313import sys
1414from . import __version__ , __gs_version__
1515from ._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 *
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' }
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
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
118118def _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):
402400def _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
410407class color (object ):
411408 black = vector (0 ,0 ,0 )
@@ -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 )
@@ -764,52 +760,32 @@ def up(self,value):
764760 def axis (self ):
765761 return self ._axis
766762 @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
763+ def axis (self ,value ):
764+ self ._save_oldaxis = adjust_up (self ._axis , value , self ._up , self ._save_oldaxis ) # this sets self._axis and self._up
775765 if not self ._constructing :
776766 self .addattr ('axis' )
777- if self ._sizing :
778- self ._size ._x = value .mag # changing axis length changes size.x
767+ self ._size ._x = value .mag # changing axis length changes size.x
779768
780769 @property
781770 def size (self ):
782771 return self ._size
783772 @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 )
773+ def size (self ,value ):
774+ self ._size .value = value
793775 if not self ._constructing :
794776 self .addattr ('size' )
795- if self ._sizing :
796- self ._axis = currentaxis .norm ()* value .x
777+ a = self ._axis .norm () * value .x
778+ if mag (self ._axis ) == 0 :
779+ a = vector (value .x ,0 ,0 )
780+ self ._axis .value = a # changing size changes length of axis
797781
798782 @property
799783 def length (self ):
800784 return self ._size .x
801785 @length .setter
802786 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
787+ self ._axis = self ._axis .norm () * value
788+ self ._size ._x = value
813789 if not self ._constructing :
814790 self .addattr ('axis' )
815791 self .addattr ('size' )
@@ -1039,24 +1015,6 @@ def rotate(self, angle=None, axis=None, origin=None):
10391015 self ._pos .value = newpos
10401016 self .addattr ('pos' )
10411017
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-
10601018 def _on_size_change (self ): # the vector class calls this when there's a change in x, y, or z
10611019 self ._axis .value = self ._axis .norm () * self ._size .x # update axis length when box.size.x is changed
10621020 self .addattr ('size' )
@@ -1145,7 +1103,6 @@ def __init__(self, **args):
11451103 args ['_default_size' ] = vector (2 ,2 ,2 )
11461104 args ['_objName' ] = "sphere"
11471105 super (sphere , self ).setup (args )
1148- self ._sizing = False # no axis/size connection
11491106
11501107 @property
11511108 def radius (self ):
@@ -1236,7 +1193,6 @@ def __init__(self, **args):
12361193 args ['_default_size' ] = vector (0.2 ,2.2 ,2.2 )
12371194 args ['_objName' ] = "ring"
12381195 super (ring , self ).setup (args )
1239- self ._sizing = False # no axis/size connection
12401196
12411197 @property
12421198 def thickness (self ):
@@ -1492,7 +1448,6 @@ def __init__(self, objList, **args):
14921448 self .compound_idx += 1
14931449 args ['_objName' ] = 'compound' + str (self .compound_idx )
14941450 super (compound , self ).setup (args )
1495- self ._sizing = False # no axis/size connection
14961451
14971452 for obj in objList :
14981453 # GlowScript will make the objects invisible, so need not set obj.visible
@@ -1856,8 +1811,8 @@ def pop(self, *args):
18561811 return val
18571812
18581813 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 ) ))
1814+ if N >= len (self ._pts ) or (N < 0 and - N > len (self ._pts )):
1815+ raise ValueError ('N = {} is outside the bounds 0-{} of the curve points' .format (N , len (self ._pts ) - 1 ))
18611816 info = self ._pts [N ]
18621817 if 'color' not in info : info ['color' ] = self .color
18631818 if 'radius' not in info : info ['radius' ] = self .radius
@@ -2026,8 +1981,6 @@ def setup(self, args):
20261981 self ._legend = False
20271982 self ._interval = - 1
20281983 self ._graph = None
2029- self ._visible = True
2030- self ._data = []
20311984 objName = args ['_objName' ]
20321985 del args ['_objName' ]
20331986 self ._constructing = True ## calls are from constructor
@@ -2163,8 +2116,6 @@ def preresolve2(self, args):
21632116 raise AttributeError ("Cannot currently change color in a plot statement." )
21642117 if 'pos' in args :
21652118 return self .resolveargs (args ['pos' ])
2166- elif 'data' in args :
2167- return self .resolveargs (args ['data' ])
21682119 else :
21692120 raise AttributeError ("Must be plot(x,y) or plot(pos=[x,y]) or plot([x,y]) or plot([x,y], ...) or plot([ [x,y], ... ])" )
21702121
@@ -2173,18 +2124,8 @@ def plot(self, *args1, **args2):
21732124 p = self .preresolve1 (args1 )
21742125 else :
21752126 p = self .preresolve2 (args2 )
2176- self ._data = self ._data + p
21772127 self .addmethod ('plot' , p )
21782128
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-
21882129 def delete (self ):
21892130 self .addmethod ('delete' , 'None' )
21902131
@@ -2881,8 +2822,7 @@ def __init__(self, **args):
28812822 baseObj ._canvas_constructing = False
28822823
28832824 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 )
2825+ self .addmethod ('follow' , obj .idx )
28862826
28872827 def select (self ):
28882828 canvas .selected = self
@@ -3369,7 +3309,6 @@ class controls(baseObj):
33693309 def setup (self , args ):
33703310 super (controls , self ).__init__ () ## get idx, attrsupdt from baseObj
33713311 ## default values of common attributes
3372- self ._disabled = False
33733312 self ._constructing = True
33743313 argsToSend = []
33753314 objName = args ['_objName' ]
@@ -3604,8 +3543,7 @@ def choices(self):
36043543 return self ._choices
36053544 @choices .setter
36063545 def choices (self , value ):
3607- self ._choices = value
3608- self .addattr ('choices' )
3546+ raise AttributeError ('choices cannot be modified after a menu is created' )
36093547
36103548 @property
36113549 def index (self ):
@@ -3889,7 +3827,6 @@ def end_face_color(self,value):
38893827class text (standardAttributes ):
38903828
38913829 def __init__ (self , ** args ):
3892- self ._sizing = False # no axis/size connection
38933830 args ['_default_size' ] = vector (1 ,1 ,1 ) # to keep standardAttributes happy
38943831 args ['_objName' ] = "text"
38953832 self ._height = 1 ## not derived from size
@@ -3944,10 +3881,10 @@ def axis(self):
39443881 return self ._axis
39453882 @axis .setter
39463883 def axis (self ,value ): # changing axis does not affect size
3947- old = vector (self .axis )
3884+ oldaxis = vector (self .axis )
39483885 u = self .up
39493886 self ._axis .value = value
3950- self ._save_oldaxis = adjust_up (norm (old ), self ._axis , self ._up , self ._save_oldaxis )
3887+ self ._save_oldaxis = adjust_up (norm (oldaxis ), self ._axis , self ._up , self ._save_oldaxis )
39513888 self .addattr ('axis' )
39523889 self .addattr ('up' )
39533890
@@ -3985,7 +3922,7 @@ def depth(self, val): # sign issue ??
39853922 if abs (val ) < 0.01 * self ._height :
39863923 if val < 0 : val = - 0.01 * self ._height
39873924 else : val = 0.01 * self ._height
3988- self ._depth = val
3925+ self ._depth = value
39893926 self .addattr ('depth' )
39903927
39913928 @property
0 commit comments