13
13
import sys
14
14
from . import __version__ , __gs_version__
15
15
from ._notebook_helpers import _isnotebook
16
- from ._vector_import_helper import (vector , mag , norm , dot , adjust_up ,
16
+ from ._vector_import_helper import (vector , mag , norm , cross , dot , adjust_up ,
17
17
adjust_axis , object_rotate )
18
18
19
19
# List of names that will be imported from this file with import *
28
28
'standardAttributes' , 'text' , 'textures' , 'triangle' , 'vertex' ,
29
29
'wtext' , 'winput' , 'keysdown' ]
30
30
31
- from inspect import signature # needed to allow zero arguments in a bound function
31
+ __p = platform .python_version ()
32
+ _ispython3 = (__p [0 ] == '3' )
33
+
34
+ if _ispython3 :
35
+ from inspect import signature # Python 3; needed to allow zero arguments in a bound function
36
+ else :
37
+ from inspect import getargspec # Python 2; needed to allow zero arguments in a bound function
32
38
33
39
# __version__ is the version number of the Jupyter VPython installer, generated in building the installer.
34
40
version = [__version__ , 'jupyter' ]
91
97
'right' :'q' , 'top' :'r' , 'bottom' :'s' , '_cloneid' :'t' ,
92
98
'logx' :'u' , 'logy' :'v' , 'dot' :'w' , 'dot_radius' :'x' ,
93
99
'markers' :'y' , 'legend' :'z' , 'label' :'A' , 'delta' :'B' , 'marker_color' :'C' ,
94
- 'size_units' :'D' , 'userpan' :'E' , 'scroll' :'F' , 'choices' : 'G' }
100
+ 'size_units' :'D' , 'userpan' :'E' , 'scroll' :'F' }
95
101
96
102
# methods are X in {'m': '23X....'}
97
103
# pos is normally updated as an attribute, but for interval-based trails, it is updated (multiply) as a method
107
113
'marker_color' ]
108
114
109
115
__textattrs = ['text' , 'align' , 'caption' , 'title' , 'xtitle' , 'ytitle' , 'selected' , 'label' , 'capture' ,
110
- 'append_to_caption' , 'append_to_title' , 'bind' , 'unbind' , 'pause' , 'GSprint' , 'choices' ]
116
+ 'append_to_caption' , 'append_to_title' , 'bind' , 'unbind' , 'pause' , 'GSprint' ]
111
117
112
118
def _encode_attr2 (sendval , val , ismethods ):
113
119
s = ''
114
120
if sendval in __vecattrs : # it would be good to do some kind of compression of doubles
115
121
s += "{:.16G},{:.16G},{:.16G}" .format (val [0 ], val [1 ], val [2 ])
116
122
elif sendval in __textattrs :
117
- if sendval == 'choices' :
118
- s2 = ''
119
- for v in val :
120
- s2 += v + ' '
121
- val = s2 [0 :- 1 ]
122
- else :
123
- # '\n' doesn't survive JSON transmission, so we replace '\n' with '<br>' (and convert back in glowcomm)
124
- if not isinstance (val , str ): val = print_to_string (val )
125
- val = val .replace ('\n ' , '<br>' )
123
+ # '\n' doesn't survive JSON transmission, so we replace '\n' with '<br>' (and convert back in glowcomm)
124
+ if not isinstance (val , str ): val = print_to_string (val )
125
+ val = val .replace ('\n ' , '<br>' )
126
126
s += val
127
127
elif sendval == 'rotate' :
128
128
for p in val :
@@ -169,6 +169,10 @@ def _encode_attr(D, ismethods): # ismethods is True if a list of method operatio
169
169
out .append (s )
170
170
return out
171
171
172
+ if sys .version > '3' :
173
+ long = int
174
+
175
+
172
176
def list_to_vec (L ):
173
177
return vector (L [0 ], L [1 ], L [2 ])
174
178
@@ -375,9 +379,14 @@ def handle_msg(self, msg):
375
379
obj ._text = evt ['text' ]
376
380
obj ._number = evt ['value' ]
377
381
# inspect the bound function and see what it's expecting
378
- a = signature (obj ._bind )
379
- if str (a ) != '()' : obj ._bind ( obj )
380
- else : obj ._bind ()
382
+ if _ispython3 : # Python 3
383
+ a = signature (obj ._bind )
384
+ if str (a ) != '()' : obj ._bind ( obj )
385
+ else : obj ._bind ()
386
+ else : # Python 2
387
+ a = getargspec (obj ._bind )
388
+ if len (a .args ) > 0 : obj ._bind ( obj )
389
+ else : obj ._bind ()
381
390
else : ## a canvas event
382
391
if 'trigger' not in evt :
383
392
cvs = baseObj .object_registry [evt ['canvas' ]]
@@ -392,7 +401,7 @@ def _wait(cvs): # wait for an event
392
401
cvs ._waitfor = None
393
402
if _isnotebook : baseObj .trigger () # in notebook environment must send methods immediately
394
403
while cvs ._waitfor is None :
395
- rate (100 )
404
+ rate (30 )
396
405
return cvs ._waitfor
397
406
398
407
class color (object ):
@@ -547,7 +556,7 @@ class standardAttributes(baseObj):
547
556
'extrusion' :[ ['pos' , 'color' , 'start_face_color' , 'end_face_color' ],
548
557
[ 'axis' , 'size' , 'up' ],
549
558
['path' , 'shape' , 'visible' , 'opacity' ,'shininess' , 'emissive' ,
550
- 'show_start_face' , 'show_end_face' , 'smooth' ,
559
+ 'show_start_face' , 'show_end_face' ,
551
560
'make_trail' , 'trail_type' , 'interval' , 'show_start_face' , 'show_end_face' ,
552
561
'retain' , 'trail_color' , 'trail_radius' , 'texture' , 'pickable' ],
553
562
['red' , 'green' , 'blue' ,'length' , 'width' , 'height' ] ],
@@ -1006,6 +1015,24 @@ def rotate(self, angle=None, axis=None, origin=None):
1006
1015
self ._pos .value = newpos
1007
1016
self .addattr ('pos' )
1008
1017
1018
+ def bounding_box (self ):
1019
+ centered = ['box' , 'compound' , 'ellipsoid' , 'sphere' , 'simple_sphere' , 'ring' ]
1020
+ x = norm (self ._axis )
1021
+ y = norm (self ._up )
1022
+ z = norm (cross (x ,y ))
1023
+ L = self ._size .x
1024
+ H = self ._size .y
1025
+ W = self ._size .z
1026
+ p = vector (self ._pos ) # make a copy of pos, so changes to p won't affect the object
1027
+ if self ._objName not in centered :
1028
+ p = p + 0.5 * L * x # move to center
1029
+ pts = []
1030
+ for dx in [- L / 2 , L / 2 ]:
1031
+ for dy in [- H / 2 , H / 2 ]:
1032
+ for dz in [- W / 2 , W / 2 ]:
1033
+ pts .append (p + dx * x + dy * y + dz * z )
1034
+ return pts
1035
+
1009
1036
def _on_size_change (self ): # the vector class calls this when there's a change in x, y, or z
1010
1037
self ._axis .value = self ._axis .norm () * self ._size .x # update axis length when box.size.x is changed
1011
1038
self .addattr ('size' )
@@ -1431,6 +1458,11 @@ def __init__(self, objList, **args):
1431
1458
savesize = args ['size' ]
1432
1459
del args ['size' ]
1433
1460
1461
+ baseObj .sent = False
1462
+ while not baseObj .sent : # wait for compounding objects to exist
1463
+ if _isnotebook : rate (1000 )
1464
+ else : time .sleep (0.001 )
1465
+
1434
1466
self .compound_idx += 1
1435
1467
args ['_objName' ] = 'compound' + str (self .compound_idx )
1436
1468
super (compound , self ).setup (args )
@@ -2688,7 +2720,7 @@ def rotate(self, angle=0, axis=None, origin=None):
2688
2720
c = self ._canvas
2689
2721
if axis is None : axis = c .up
2690
2722
if origin is not None and origin != self .pos :
2691
- origin = origin + (self .pos - origin ).rotate (angle = angle , axis = axis )
2723
+ origin = self . pos + (self .pos - origin ).rotate (angle = angle , axis = axis )
2692
2724
else :
2693
2725
origin = self .pos
2694
2726
if c ._axis .diff_angle (axis ) > 1e-6 :
@@ -3084,6 +3116,7 @@ def handle_event(self, evt): ## events and scene info updates
3084
3116
# Set attribute_vector.value, which avoids nullifying the
3085
3117
# on_change functions that detect changes in e.g. obj.pos.y
3086
3118
obj ._pos .value = list_to_vec (p )
3119
+ obj ._origin = obj ._pos
3087
3120
s = evt ['size' ]
3088
3121
obj ._size .value = obj ._size0 = list_to_vec (s )
3089
3122
obj ._axis .value = obj ._size ._x * norm (obj ._axis )
@@ -3097,9 +3130,14 @@ def handle_event(self, evt): ## events and scene info updates
3097
3130
del evt ['height' ]
3098
3131
for fct in self ._binds ['resize' ]:
3099
3132
# inspect the bound function and see what it's expecting
3100
- a = signature (fct )
3101
- if str (a ) != '()' : fct ( evt )
3102
- else : fct ()
3133
+ if _ispython3 : # Python 3
3134
+ a = signature (fct )
3135
+ if str (a ) != '()' : fct ( evt )
3136
+ else : fct ()
3137
+ else : # Python 2
3138
+ a = getargspec (fct )
3139
+ if len (a .args ) > 0 : fct ( evt )
3140
+ else : fct ()
3103
3141
else : # pause/waitfor, update_canvas
3104
3142
if 'pos' in evt :
3105
3143
pos = evt ['pos' ]
@@ -3119,9 +3157,14 @@ def handle_event(self, evt): ## events and scene info updates
3119
3157
evt1 = event_return (evt ) ## turn it into an object
3120
3158
for fct in self ._binds [ev ]:
3121
3159
# inspect the bound function and see what it's expecting
3122
- a = signature (fct )
3123
- if str (a ) != '()' : fct ( evt1 )
3124
- else : fct ()
3160
+ if _ispython3 : # Python 3
3161
+ a = signature (fct )
3162
+ if str (a ) != '()' : fct ( evt1 )
3163
+ else : fct ()
3164
+ else : # Python 2
3165
+ a = getargspec (fct )
3166
+ if len (a .args ) > 0 : fct ( evt1 )
3167
+ else : fct ()
3125
3168
self ._waitfor = evt1 # what pause and waitfor are looking for
3126
3169
else : ## user can change forward (spin), range/autoscale (zoom), up (touch), center (pan)
3127
3170
if 'forward' in evt and self .userspin and not self ._set_forward :
@@ -3518,10 +3561,7 @@ def choices(self):
3518
3561
return self ._choices
3519
3562
@choices .setter
3520
3563
def choices (self , value ):
3521
- self ._choices = value
3522
- if not self ._constructing :
3523
- self .addattr ('choices' )
3524
- #raise AttributeError('choices cannot be modified after a menu is created')
3564
+ raise AttributeError ('choices cannot be modified after a menu is created' )
3525
3565
3526
3566
@property
3527
3567
def index (self ):
@@ -3762,16 +3802,6 @@ def shape(self):
3762
3802
def shape (self , value ):
3763
3803
raise AttributeError ('shape cannot be changed after extrusion is created' )
3764
3804
3765
- @property
3766
- def smooth (self ):
3767
- if self ._constructing :
3768
- return self ._smooth
3769
- else :
3770
- return None
3771
- @smooth .setter
3772
- def smooth (self , value ):
3773
- raise AttributeError ('smooth cannot be changed after extrusion is created' )
3774
-
3775
3805
@property
3776
3806
def show_start_face (self ):
3777
3807
if self ._constructing :
@@ -4081,4 +4111,4 @@ def set_browser(type='default'):
4081
4111
if type == 'pyqt' :
4082
4112
_browsertype = 'pyqt'
4083
4113
else :
4084
- _browsertype = 'default'
4114
+ _browsertype = 'default'
0 commit comments