## Graphing surfaces over non-rectangular domains
## John Travis
## Spring 2011
##
## Interact allows the user to input up to two inequality constraints on the
## domain when dealing with functional surfaces
##
## User inputs:
## f = "top" surface with z = f(x,y)
## g = "bottom" surface with z = g(x,y)
## condition1 = a single boundary constraint. It should not include && or | to join two conditions.
## condition2 = another boundary constraint. If there is only one constraint, just enter something true
## or even just an x (or y) in the entry blank.
##
##
var('x,y')
# f is the top surface
# g is the bottom surface
global f,g
# condition1 and condition2 are the inequality constraints. It would be nice
# to have any number of conditions connected by $$ or |
global condition1,condition2
@interact(layout=dict(top=[['f','condition1'],['g','condition2']],right=[['show_3d'],['dospin'],['clr'],['auto_update']],bottom=[['xx'],['yy']]))
def _(f=input_box(default=(1/3)*x^2 + (1/4)*y^2 + 5,width=30,label='$f(x)=$'),
g=input_box(default=-1*x+0*y,width=30,label='$g(x)=$'),
condition1=input_box(default= x^2+y^2<8,width=30,label='. Constraint$_1=$'),
condition2=input_box(default=y<sin(3*x),width=30,label='. Constraint$_2=$'),
show_3d=('Stereographic',false), show_vol=('Shade volume',true),
dospin = ('Spin?',true),
clr = color_selector('#faff00', label='Volume Color', widget='colorpicker', hide_box=True),
xx = range_slider(-5, 5, 1, default=(-3,3), label='X Range'),
yy = range_slider(-5, 5, 1, default=(-3,3), label='Y Range'),
auto_update=false):
# This is the top function actually graphed by using NaN outside domain
def F(x,y):
if condition1(x=x,y=y):
if condition2(x=x,y=y):
return f(x=x,y=y)
else:
return -NaN
else:
return -NaN
# This is the bottom function actually graphed by using NaN outside domain
def G(x,y):
if condition1(x=x,y=y):
if condition2(x=x,y=y):
return g(x=x,y=y)
else:
return -NaN
else:
return -NaN
# This interpolates the "volume" between F and G. Replaced with an inline version
# in the "loopish thing" below.
## def H(x,y):
## if condition1(x=x,y=y):
## if condition2(x=x,y=y):
## return (1-r)*f(x=x,y=y)+r*g(x=x,y=y)
## else:
## return -NaN
## else:
## return -NaN
##
P = Graphics()
# The graph of the top and bottom surfaces
P_list = []
P_list.append(plot3d(F,(x,xx[0],xx[1]),(y,yy[0],yy[1]),color='blue',opacity=0.9))
P_list.append(plot3d(G,(x,xx[0],xx[1]),(y,yy[0],yy[1]),color='gray',opacity=0.9))
# Interpolate "layers" between the top and bottom if desired
if show_vol:
ratios = range(10)
def H(x,y,r):
return (1-r)*F(x=x,y=y)+r*G(x=x,y=y)
P_list.extend([
plot3d(lambda x,y: H(x,y,ratios[1]/10),(x,xx[0],xx[1]),(y,yy[0],yy[1]),opacity=0.2,color=clr),
plot3d(lambda x,y: H(x,y,ratios[2]/10),(x,xx[0],xx[1]),(y,yy[0],yy[1]),opacity=0.2,color=clr),
plot3d(lambda x,y: H(x,y,ratios[3]/10),(x,xx[0],xx[1]),(y,yy[0],yy[1]),opacity=0.2,color=clr),
plot3d(lambda x,y: H(x,y,ratios[4]/10),(x,xx[0],xx[1]),(y,yy[0],yy[1]),opacity=0.2,color=clr),
plot3d(lambda x,y: H(x,y,ratios[5]/10),(x,xx[0],xx[1]),(y,yy[0],yy[1]),opacity=0.2,color=clr),
plot3d(lambda x,y: H(x,y,ratios[6]/10),(x,xx[0],xx[1]),(y,yy[0],yy[1]),opacity=0.2,color=clr),
plot3d(lambda x,y: H(x,y,ratios[7]/10),(x,xx[0],xx[1]),(y,yy[0],yy[1]),opacity=0.2,color=clr),
plot3d(lambda x,y: H(x,y,ratios[8]/10),(x,xx[0],xx[1]),(y,yy[0],yy[1]),opacity=0.2,color=clr),
plot3d(lambda x,y: H(x,y,ratios[9]/10),(x,xx[0],xx[1]),(y,yy[0],yy[1]),opacity=0.2,color=clr)
])
# P = plot3d(lambda x,y: H(x,y,ratio/10),(x,xx[0],xx[1]),(y,yy[0],yy[1]),opacity=0.1)
# Now, accumulate all of the graphs into one grouped graph.
P = sum(P_list[i] for i in range(len(P_list)))
if show_3d:
show(P,frame=true,axes=false,xmin=xx[0],xmax=xx[1],ymin=yy[0],ymax=yy[1],stereo='redcyan',figsize=(4,6),viewer='jmol',spin=dospin)
else:
show(P,frame=true,axes=false,xmin=xx[0],xmax=xx[1],ymin=yy[0],ymax=yy[1],figsize=(4,6),viewer='jmol',spin=dospin)
|
Click to the left again to hide and once more to show the dynamic interactive window
|