From b939b3acdd2e96d2f6b94aaab041ba18d3ef4b05 Mon Sep 17 00:00:00 2001 From: jcoady Date: Wed, 20 Mar 2024 14:56:35 -0700 Subject: [PATCH] updated some no_notebook demo programs --- .../Color-RGB-HSV-from-terminal.py | 47 ++++++++++++++ .../DipoleElectricField-from-terminal.py | 65 +++++++++++++++++++ .../MousePicking-from-terminal.py | 56 ++++++++++++++++ Demos_no_notebook/qt.py | 2 +- vpython/no_notebook.py | 7 +- 5 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 Demos_no_notebook/Color-RGB-HSV-from-terminal.py create mode 100644 Demos_no_notebook/DipoleElectricField-from-terminal.py create mode 100644 Demos_no_notebook/MousePicking-from-terminal.py diff --git a/Demos_no_notebook/Color-RGB-HSV-from-terminal.py b/Demos_no_notebook/Color-RGB-HSV-from-terminal.py new file mode 100644 index 0000000..a3626e6 --- /dev/null +++ b/Demos_no_notebook/Color-RGB-HSV-from-terminal.py @@ -0,0 +1,47 @@ +from vpython import * +# This version uses VPython slider +# See ButtonsSlidersMenus1 for a version that uses Jupyter slider + +scene.userzoom = False +scene.userspin = False +scene.width = 400 +scene.height = 200 +scene.range = 1 +scene.background = color.red +box(pos=vector(10,0,0)) # Force creation of canvas; box is not seen because it is outside the canvas +cancopy = 'You can Ctrl-C or Command-C copy these RGB and HSV values:\n' +scene.title = cancopy +scene.append_to_title("RGB = <1.000, 0.000, 0.000>, HSV = <0.000, 0.000, 0.000>") + +C = ['Red', 'Green', 'Blue', 'Hue', 'Saturation', 'Value'] +sliders = [] + +def set_background(sl): + if sl.id < 3: + rgb = vector(sliders[0].value, sliders[1].value, sliders[2].value) + hsv = color.rgb_to_hsv(rgb) + sliders[3].value = int(1000*hsv.x)/1000# reset HSV slider positions; display 3 figures + sliders[4].value = int(1000*hsv.y)/1000 + sliders[5].value = int(1000*hsv.z)/1000 + else: + hsv = vector(sliders[3].value, sliders[4].value, sliders[5].value) + rgb = color.hsv_to_rgb(hsv) + sliders[0].value = int(1000*rgb.x)/1000 # reset RGB slider positions; display 3 figures + sliders[1].value = int(1000*rgb.y)/1000 + sliders[2].value = int(1000*rgb.z)/1000 + scene.background = rgb + # For readability, limit precision of display of quantities to 3 figures + f = "RGB = <{:1.3f}, {:1.3f}, {:1.3f}>, HSV = <{:1.3f}, {:1.3f}, {:1.3f}>" + scene.title = cancopy + f.format(rgb.x, rgb.y, rgb.z, hsv.x, hsv.y, hsv.z) + +scene.caption = '\n' +for i in range(6): # Create the 3 RGB and 3 HSV sliders + sliders.append(slider(length=300, left=10, min=0, max=1, bind=set_background, id=i)) + scene.append_to_caption(' '+C[i]+'\n\n') # Display slider name + if i == 2: scene.append_to_caption("\n\n") # Separate the RGB and HSV sliders +sliders[0].value = 1 # make the background red +sliders[4].value = sliders[5].value = 1 + + +while True: # Needed when running from a terminal + rate(30) diff --git a/Demos_no_notebook/DipoleElectricField-from-terminal.py b/Demos_no_notebook/DipoleElectricField-from-terminal.py new file mode 100644 index 0000000..29d6d53 --- /dev/null +++ b/Demos_no_notebook/DipoleElectricField-from-terminal.py @@ -0,0 +1,65 @@ +from vpython import * + +scale = 4e-14/1e17 +ec = 1.6e-19 # electron charge +kel = 9e9 # Coulomb constant +scene.range = 2e-13 + +charges = [ sphere( pos=vector(-1e-13,0,0), Q=ec, color=color.red, size=1.2e-14*vector(1,1,1) ), + sphere( pos=vector( 1e-13,0,0), Q=-ec, color=color.blue, size=1.2e-14*vector(1,1,1) )] + +s = "Click or drag to plot an electric field vector produced by the two charges.\n" +s += "On a touch screen, tap, or press and hold, then drag.\n" +s += "Arrows representing the field are bluer if low magnitude, redder if high." +scene.caption = s + +def getfield(p): + f = vec(0,0,0) + for c in charges: + f = f + (p-c.pos) * kel * c.Q / mag(p-c.pos)**3 + return f + +def mouse_to_field(a): + p = scene.mouse.pos + f = getfield(p) + m = mag(f) + red = max( 1-1e17/m, 0 ) + blue = min( 1e17/m, 1 ) + if red >= blue: + blue = blue/red + red = 1.0 + else: + red = red/blue + blue = 1.0 + a.pos = p + a.axis = scale*f + a.color = vector(red,0,blue) + a.visible = True + +drag = False +a = None + +def down(ev): + global a, drag + a = arrow(shaftwidth=6e-15, visible=False) + mouse_to_field(a) + drag = True + +def move(ev): + global a, drag + if not drag: return + mouse_to_field(a) + +def up(ev): + global a, drag + mouse_to_field(a) + drag = False + +scene.bind("mousedown", down) + +scene.bind("mousemove", move) + +scene.bind("mouseup", up) + +while True: # Needed when running from a terminal + rate(30) diff --git a/Demos_no_notebook/MousePicking-from-terminal.py b/Demos_no_notebook/MousePicking-from-terminal.py new file mode 100644 index 0000000..08887e4 --- /dev/null +++ b/Demos_no_notebook/MousePicking-from-terminal.py @@ -0,0 +1,56 @@ +from vpython import * +scene.width = scene.height = 500 +scene.background = color.gray(0.8) +scene.range = 2.2 +scene.caption = "Click to pick an object and make it red." +scene.append_to_caption("\nNote picking of individual curve segments.") +box(pos=vector(-1,0,0), color=color.cyan, opacity=1) +box(pos=vector(1,-1,0), color=color.green) +arrow(pos=vector(-1,-1.3,0), color=color.orange) +cone(pos=vector(2,0,0), axis=vector(0,1,-.3), color=color.blue, size=vector(2,1,1)) +sphere(pos=vector(-1.5,1.5,0), color=color.white, size=.4*vector(3,2,1)) +square = curve(color=color.yellow, radius=.05) +square.append(vector(0,0,0)) +square.append(pos=vector(0,1,0), color=color.cyan, radius=.1) +square.append(vector(1,1,0)) +square.append(pos=vector(1,0,0), radius=.1) +square.append(vector(0.3,-.3,0)) +v0 = vertex(pos=vector(-.5,1.2,0), color=color.green) +v1 = vertex(pos=vector(1,1.2,0), color=color.red) +v2 = vertex(pos=vector(1,2,0), color=color.blue) +v3 = vertex(pos=vector(-.5,2,0), color=color.yellow) +quad(vs=[v0, v1, v2, v3]) +extrusion(path=[vector(-1.8,-1.3,0), vector(-1.4,-1.3,0)], + shape=shapes.circle(radius=.5, thickness=0.4), color=color.yellow) +ring(pos=vector(-0.6,-1.3,0), size=vector(0.2,1,1), color=color.green) +lasthit = None +lastpick = None +lastcolor = None + +def getevent(evt): + global lasthit, lastpick, lastcolor + if lasthit != None: + if lastpick != None: lasthit.modify(lastpick, color=lastcolor) + else: lasthit.color = vector(lastcolor) + lasthit = lastpick = None + + hit = scene.mouse.pick + if hit != None: + lasthit = hit + lastpick = None + if isinstance(hit, curve): # pick individual point of curve + lastpick = hit.segment + lastcolor = hit.point(lastpick)['color'] + hit.modify(lastpick, color=color.red) + elif isinstance(hit, quad): + lasthit = hit.v0 + lastcolor = vector(lasthit.color) # make a copy + lasthit.color = color.red + else: + lastcolor = vector(hit.color) # make a copy + hit.color = color.red + +scene.bind("mousedown", getevent) + +while True: # Needed when running from a terminal + rate(30) diff --git a/Demos_no_notebook/qt.py b/Demos_no_notebook/qt.py index b9f6993..6b9f76a 100644 --- a/Demos_no_notebook/qt.py +++ b/Demos_no_notebook/qt.py @@ -1,4 +1,4 @@ from vpython import * -set_browser(type='pyqt') +set_browser(type='pyqt5') b = box() scene.caption = "A box should appear in the window above" diff --git a/vpython/no_notebook.py b/vpython/no_notebook.py index 5119408..db7ac07 100755 --- a/vpython/no_notebook.py +++ b/vpython/no_notebook.py @@ -52,7 +52,12 @@ def run(*args, **kwargs): # Check for Ctrl+C. SIGINT will also be sent by our code if WServer is closed. def signal_handler(signal, frame): #print("in signal handler, calling stop server") - stop_server() + try: + stop_server() + except (KeyboardInterrupt): + pass + except: + raise signal.signal(signal.SIGINT, signal_handler)