GLE Library: shape.gle


! Subroutines to draw various shapes

shape_use_tex  = 0
shape_color_1$ = clear
shape_color_2$ = clear
shadow_color$  = "gray10"

shape_dx = 0.1
shape_dy = 0.1

sub set_shape_use_tex use
   shape_use_tex = use
end sub

sub set_shape_color color$
   ! Set the primary filling color for the shapes
   shape_color_1$ = color$
end sub

sub set_shape_color_2 color$
   ! Set the secondary filling color for the shapes
   shape_color_2$ = color$
end sub

sub set_shadow_color color$
   ! Set the color of the shadow
   shadow_color$ = color$
end sub

sub set_shape_dxdy dx dy
   ! Set the internal gap of a shape (for shapes containing text)
   shape_dx = dx
   shape_dy = dy
end sub

sub line_label x1 y1 x2 y2 str$ dist
   ! Draw a label at the center of an imaginary line from (x1,y1) to (x2,y2)
   ! (x1,y1): starting point of the line
   ! (x2,y2): ending point of the line
   ! str$: label to draw
   ! dist: distance between label and line
   if dist > 0 then set just bc
   else set just tc
   amove (x1+x2)/2 (y1+y2)/2
   begin rotate xy2angle(x2-x1,y2-y1)
      rmove 0 dist
      write str$
   end rotate
end sub

sub accolade x1 y1 x2 y2 r
   ! Draw an accolade from (x1,y1) to (x2,y2) with radius r
   ! To draw the accolade on the "other side" of the line, swap (x1,y1) and (x2,y2)
   local xm = (x1+x2)/2
   local ym = (y1+y2)/2
   wd = sqrt((xm-x1)^2+(ym-y1)^2)
   amove xm ym
   begin rotate xy2angle(x2-x1,y2-y1)
      rmove -wd+r 0
      begin path stroke
         arc r 90 180
         rmove 0 r
         rline wd-2*r 0
         rsetpos 0 r
         arc r 270 0
         rsetpos 2*r 0
         arc r 180 270
         rmove 0 -r
         rline wd-2*r 0
         rsetpos 0 -r
         narc r 90 0
      end path
   end rotate
end sub

sub named_hexagon x y h n1$ n2$
   ! Draw a named hexagon
   ! x, y: the center point of the hexagon
   ! h: half of the hexagon's height
   ! n1$ name for the surrounding box
   ! n2$ name for the internal box 
   dx=h*cos(torad(30))
   dy=h*sin(torad(30))
   amove x-dx y+h/2
   begin path stroke fill shape_color_1$
      aline x-dx y-h/2
      aline x y-h/2-dy
      aline x+dx y-h/2
      aline x+dx y+h/2
      aline x y+h/2+dy
      aline x-dx y+h/2
      closepath
   end path
   amove x-dx y-h/2-dy
   box 2*dx h+2*dy nobox name n1$
   amove x-dx y-h/2
   box 2*dx h nobox name n2$
end sub

sub hexagon x y h
   ! Draw a hexagon
   ! x, y: the center point of the hexagon
   ! h: half of the hexagon's height
   named_hexagon x y h "none" "none"
end sub

sub disk wd hi ellh
   ! Draw a disk
   ! wd: disk width
   ! hi: disk height
   ! ellh: height of top ellipse
   set join round
   local crx = xpos()
   local cry = ypos()
   amove crx cry+hi/2-ellh
   begin path stroke fill shape_color_1$
      elliptical_narc wd/2 ellh 0 180
      aline crx-wd/2 cry-hi/2+ellh
      asetpos crx cry-hi/2+ellh
      elliptical_arc wd/2 ellh 180 0
      closepath
   end path
   amove crx cry+hi/2-ellh
   begin path stroke fill shape_color_2$
      elliptical_arc wd/2 ellh 0 180
      asetpos crx cry+hi/2-ellh
      elliptical_arc wd/2 ellh 180 0
      closepath
   end path
   amove crx cry
end sub

sub textdisk str$ wd hi ellh txtd
   ! Draw a disk
   ! str$: text to write
   ! wd: disk width
   ! hi: disk height
   ! ellh: height of top ellipse
   ! txtd: offset for text (normally 0)
   disk wd hi ellh
   set just cc
   rmove 0 txtd-ellh
   write str$
end sub

sub updn_arrow wd hi angle
   ! Draw an up/down arrow
   ! wd: width of the arrow
   ! hi: height of the arrow
   ! angle: rotation angle
   local xp = xpos()
   local yp = ypos()
   begin rotate angle
      amove xp yp-hi/2
      begin path stroke fill shape_color_1$
         aline wd/2+xp yp-hi/6
         aline wd/4+xp yp-hi/6
         aline wd/4+xp yp+hi/6
         aline wd/2+xp yp+hi/6
         aline xp      yp+hi/2
         aline xp-wd/2 yp+hi/6
         aline xp-wd/4 yp+hi/6
         aline xp-wd/4 yp-hi/6
         aline xp-wd/2 yp-hi/6
         closepath
      end path
   end rotate
end sub

sub left_arrow wd hi angle
   ! Draw a left facing arrow
   ! wd: width of the arrow
   ! hi: height of the arrow
   ! angle: rotation angle
   local xp = xpos()
   local yp = ypos()
   begin rotate angle
      amove xp-wd/2 yp   
      begin path stroke fill shape_color_1$
         aline xp      yp-hi/2
         aline xp      yp-hi/4
         aline xp+wd/2 yp-hi/4
         aline xp+wd/2 yp+hi/4
         aline xp      yp+hi/4
         aline xp      yp+hi/2
         closepath
      end path
   end rotate
end sub

sub rhomb wd hi
   ! Draw a rhomb
   ! wd: width of the rhomb
   ! hi: height of the rhomb
   local xp = xpos()
   local yp = ypos()
   amove xp yp+hi/2
   begin path stroke fill shape_color_1$
      aline xp-wd/2 yp
      aline xp      yp-hi/2
      aline xp+wd/2 yp
      closepath
   end path
end sub

sub rootnode xp yp wd hi name$
   amove xp-wd/2 yp-hi
   box wd hi name name$ fill shape_color_1$
end sub

sub drawnode wd hi name$ type
   if type = 0 then
      amove xpos()-wd/2 ypos()-hi
      box wd hi name name$ fill shape_color_1$
   else
      amove xpos()-wd/2 ypos()-hi
      box wd hi name name$ nobox
      rmove wd/2 hi/2
      ellipse wd/2 hi/2 fill shape_color_2$
   end if
end sub

sub binchilds par$ wd hi ydel xdel l1 l2
   amove pointx(par$+".bc")-xdel pointy(par$+".bc")-ydel
   drawnode wd hi par$+"1" l1
   amove pointx(par$+".bc")+xdel pointy(par$+".bc")-ydel
   drawnode wd hi par$+"2" l2
   join par$+".bc" - par$+"1.tc"
   join par$+".bc" - par$+"2.tc"
end sub

sub r_tree wd hi wdfac hifac
   ! Draw a small tree (with right subtree)
   ! wd: width of the tree
   ! hi: height of the tree
   ! wdfac: proportion of width = width of node
   ! hifac: proportion of height = height of node
   local nodewd = wd*wdfac
   local nodehi = hi*hifac
   local yoffs = (hi-3*nodehi)/2
   local xoffs = (wd-nodewd)/3
   rootnode xpos()-wd/2+nodewd/2+xoffs ypos()+hi/2 nodewd nodehi "t"
   binchilds "t" nodewd nodehi yoffs xoffs 1 0
   binchilds "t2" nodewd nodehi yoffs xoffs 1 1
end sub

sub l_tree wd hi wdfac hifac
   ! Draw a small tree (with left subtree)
   ! wd: width of the tree
   ! hi: height of the tree
   ! wdfac: proportion of width = width of node
   ! hifac: proportion of height = height of node
   local nodewd = wd*wdfac
   local nodehi = hi*hifac
   local yoffs = (hi-3*nodehi)/2
   local xoffs = (wd-nodewd)/3
   rootnode xpos()-wd/2+nodewd/2+2*xoffs ypos()+hi/2 nodewd nodehi "t"
   binchilds "t" nodewd nodehi yoffs xoffs 0 1
   binchilds "t1" nodewd nodehi yoffs xoffs 1 1
end sub

sub cross d
   ! Draw a cross "+" at current position
   ! d: the size of the cross
   gsave
   set color red
   rmove -d/2  0
   rline  d    0
   rmove -d/2 -d/2
   rline  0    d
   grestore
end sub

sub shadow_box obj$ margin shadow
   local xp = xpos()
   local yp = ypos()
   local wd = width("o_"+obj$)
   local hi = height("o_"+obj$)
   begin path fill shadow_color$
      amove xp+shadow-margin yp-hi
      aline xp+wd yp-hi
      aline xp+wd yp+margin-shadow
      aline xp+wd+margin+shadow yp+margin-shadow
      aline xp+wd+margin+shadow yp-hi-margin-shadow
      aline xp+shadow-margin yp-hi-margin-shadow
      closepath
   end path
   amove xp-margin yp-hi-margin
   box wd+2*margin hi+2*margin fill white
   amove xp yp
   draw obj$+".tl"
end sub

sub pmove d a
   amove xpos()+d*cos(torad(a)) ypos()+d*sin(torad(a))
end sub

sub set_angle_just angle
   if angle = 0 then
      set just lc
   else if angle = 90 then
      set just bc
   else if angle = 180 then
      set just rc
   else if angle = -90 then
      set just tc
   else if (angle > 0) and (angle < 90) then
      set just bl
   else if (angle > 90) and (angle < 180) then
      set just br
   else if (angle > -90) and (angle < 0) then
      set just tl
   else
      set just tr
   end if
end sub

sub labeled_circle label$ radius lradius langle name$ lcolor$
   default lradius 0.1
   default langle  90
   default name    "n"
   default lcolor  black
   gsave
   begin name name$
      circle radius
   end name
   set color lcolor$	
   pmove radius+lradius langle
   set_angle_just langle
   tex label$	
   grestore
end sub