from visual import * ### EFieldBuilder.py ### Interactive E-Field Builder (requires VPython) ### Rob Salgado ### salgado@physics.syr.edu http://physics.syr.edu/~salgado/ ### v0.9990 2005-03-08 tested on Windows 2000 ### with Python-2.3.3.exe and VPython-2003-10-05.exe ### * added fixedwidth to arrows ### * hide small vectors ### v0.9972 2002-01-10 tested on Windows 2000 ### with Python-2.2.exe and VPython-2001-12-31.exe ### * used .click instead of .button ### * modified the drag flag #### ### ### v0.997 2001-11-07 tested on Windows 2000 ### with Python-2.1.1.exe and VPython-2001-10-31.exe ### * uses specified shaftwidth for the arrows ### * removes the dependence on fpformat ### v0.996 2001-11-03 tested on Windows 2000 ### with Python-2.1.1.exe and VPython-2001-10-31.exe ### v0.99 2001-10-23 tested on Windows 2000 ### with Python-2.1.1.exe and VPython-2001-10-08.exe print""" Interactive E-Field Builder (v0.9990) Rob Salgado (salgado@physics.syr.edu) This VPython program allows you to position point charges in space. The Electric Field due to those charges is computed dynamically. Use the control panel to change the sign and magnitude of the next charge to be placed. In 'Create' mode:" Left-Clicking once on an empty location will place a new charge there. Left-Clicking-and-Dragging on an existing charge will reposition it. In 'Edit' mode: Left-Clicking once on an existing charge will change its properties. In 'Copy' mode: Left-Clicking once on an existing charge will copy its settings. To delete an existing charge: First, select the 'Edit' mode and set the charge to 0.0. Then, select the charge to be deleted. Wheel-Click-and-Drag or Left-and-Right-Click-and-Drag to zoom in and out. Right-Click-and-Drag to rotate about the origin. """ scene2 = display(title='set Q', x=0,y=0,width=100, height=100, center=(0,0,0), background=(0.25,0.25,0.25)) setQ = sphere(pos=(1,0,0), radius=1, color=color.blue,Q=1.0 ) incQ=cylinder(pos=(-1.5,0.5,0), axis=(0,1,0), radius=0.2,color=color.blue) decQ=cylinder(pos=(-1.5,-0.5,0), axis=(0,-1,0), radius=0.2,color=color.red) #labQ=label(pos=(1,0,0), text=fpformat.fix(setQ.Q, 1),opacity=0.,box=0) labQ=label(pos=(1,0,0), text="%.1f" % setQ.Q,opacity=0.,box=0) modestate=['create','edit','copy'] modeboxQ=box(pos=(-1.5,0,0),color=color.black) modeQ=label(pos=(-1.5,0,0), text='create',box=0,mode=0) scene2.visible=1 scene2.userspin=0 scene2.userzoom=0 scene2.autoscale=0 scene = display(title="E-Field Builder (Rob Salgado)", x=100,y=100) scene.select() scene.newzoom=1 scale=0.2 step=1. S=3. drag=0 zeroV=vector(0,0,0) charges=[] Efield=[] for x in arange(-S,S,step): for y in arange(-S,S,step): for z in arange(-S,S,step): vec=arrow(pos=(x,y,z),axis=(0,0,0),shaftwidth=scale/4.,fixedwidth=1) Efield.append(vec) scene.autoscale=0 scene.range=(5,5,5) def EFieldAt(p): E = zeroV for c in charges: delta=p-c.pos if mag(delta)<2e-10: print "small" print mag(delta) else: E = E + (delta) * c.Q / mag(delta)**3 return scale*E def updateEField(): for v in Efield: v.axis=EFieldAt(v.pos) if mag2(v.axis)<2e-3: #hide small vectors v.axis=zeroV def update2(): modeQ.text=modestate[modeQ.mode] if modeQ.mode==0: scene2.background=(0.25,0.25,0.25) else: scene2.background=(1,1,1) if setQ.Q>0.0: setQ.color=color.blue elif setQ.Q<0.0: setQ.color=color.red else: setQ.color=color.green labQ.text="%.1f" % setQ.Q n=None while 1: if scene2.mouse.clicked: m = scene2.mouse.getclick() newPick2=scene2.mouse.pick if newPick2==incQ: setQ.Q=setQ.Q+0.5 elif newPick2==decQ: setQ.Q=setQ.Q-0.5 elif newPick2==modeboxQ: modeQ.mode=(modeQ.mode+1)%3 update2() if scene.mouse.clicked: m = scene.mouse.getclick() newPick=scene.mouse.pick if m.click == "none": drag=0 if n!=None: if n.Q>0.0: n.color=color.blue elif n.Q<0.0: n.color=color.red else: n.color=color.green print "Release" elif m.click == "left": if newPick==None:#if vacant, make new charge newChg=sphere(pos=m.pos, radius=abs(setQ.Q)/5.0, color=setQ.color, Q=setQ.Q) if setQ.Q==0:#give neutral charge a nonzero radius newChg.radius=1.0/5.0 charges.append(newChg) updateEField() n=newChg #n.green=(1-n.green) drag=0 #### if drag==0: if n.Q>0.0: n.color=color.blue elif n.Q<0.0: n.color=color.red else: n.color=color.green else: n=newPick if modeQ.mode==0:#toggle drag state drag=(drag+1)%2 #### if drag==0: if n.Q>0.0: n.color=color.blue elif n.Q<0.0: n.color=color.red else: n.color=color.green else: n.green=(1-n.green) elif modeQ.mode==1:#update charge if setQ.Q !=0.0: n.radius=abs(setQ.Q)/5.0 n.color=setQ.color n.Q=setQ.Q else: n.visible=0 charges.remove(n) modeQ.mode=0 update2() updateEField() elif modeQ.mode==2:#clone existing charge setQ.Q=n.Q setQ.color=n.color labQ.text= "%.1f" % setQ.Q modeQ.mode=0 update2() elif m.click == "right": print "Right" if drag==1: #print "Drag ", #print scene.mouse.button if n!=None: n.pos=scene.mouse.pos updateEField()