%!PS-Adobe-3.0
%%Title: (Face)
%%
%%Creator: Andrew C. Bulhak <acb@cs.monash.edu.au>
% The basic code for drawing a face.
% Note: this is not a complete program; only the functions for drawing faces.
% To use, run this in the PostScript interpreter and then use the face operator
% to draw faces.
%% (theta) (r) (closedness) eye -- draws an eye centered at the origin, with a
%% specified degree of closedness
/eye {
% draw lower, invariant half of eye
% draw upper, variant half
4 dict begin
% top of stack contains degree of closedness
dup /closedness exch def
/makeeyepath {
-1 0 moveto -1 -0.55 -0.55 -1 0 -1 curveto
0.55 -1 1 -0.55 1 0 curveto
1 cpy 0.55 ceny 0 ceny curveto -0.55 ceny -1 cpy -1 0 curveto
} def
dup /cpy exch 2 mul 1 sub -0.55 mul def % y of control pts of upward curve
/ceny exch 2 mul 1 sub neg def %
% here, the stack contains (theta) (r). We need to convert these
% into (x) (y)
% r is from 0 to 1. Convert to degrees.
360 mul
dup sin 2 index mul 3 1 roll cos mul
makeeyepath stroke
makeeyepath clip
newpath 1 index
closedness neg 2 index add
0.25 0 360 arc fill
pop pop
end
} def
%% sf co mouth -- draw a mouth with parameters as specified.
%% the mouth is drawn centered at the origin, with a bounding box of (-1,-1)..(1,1).
/mouth {
16 dict begin
/co exch def /sf exch def
0 sf -0.5 mul translate
/ucpy co 45 mul sin 0.5 mul def % upper spline control point y value
/cnrx 1 co 0.15 mul sub def % mouth corner x value
/ctrllen 1 co sub 0.5 mul 0.25 add def % control line length
/cp1x cnrx neg co 45 mul cos ctrllen mul add def
/cp2x cnrx co 45 mul cos ctrllen mul sub def
/lcpy co 45 mul sin -0.5 mul def
/vy sf 2 mul 1 sub 0.5 mul def
cnrx neg vy moveto cp1x ucpy cp2x ucpy cnrx vy curveto
cp2x lcpy cp1x lcpy cnrx neg vy curveto closepath stroke
end
} def
%% code for drawing an eyebrow, on the left side of the face.
%% (raiselower) eyebrow
%%
%% The way this code works is to handle the eyebrow as a spline. The
%% spline is always curved upwards, but the polarity of the parameter
%% determines which control point has the most magnitude.
/eyebrow {
9 dict begin
dup 45 mul /aparam exch def
0 lt { % eyebrow raised
/outmagn 0.5 def
/inmagn 0 def
} { %eyebrow lowered
/outmagn 0 def
/inmagn 0.5 def
} ifelse
/outx aparam cos outmagn mul -1 add def
/inx aparam cos inmagn mul 1 exch sub def
/outy aparam sin outmagn mul def
/iny aparam sin inmagn mul def
-1 0 moveto outx outy inx iny 1 0 curveto stroke
end
} def
%% face
%% (brow) (brow) (eyetheta) (eyerad) (iclose) (eyetheta) (eyerad) (iclose)
%% (mthsf) (mthco) (mthsc)
%% (xrot) (yrot) (zrot) face
/face {
8 dict begin
/zrot exch 22.5 mul def
/yrot exch 22.5 mul def
/xrot exch 22.5 mul def
% draw the outline
/outline {newpath 0 0 1 0 360 arc} bind def
outline stroke outline clip
%% handle mouth
/mouthheight xrot 63 add sin 30 xrot sub sin add 2 div def
gsave
yrot sin xrot 15 sub sin translate
dup 0.625 mul mouthheight 2 index mul scale pop
mouth
grestore
%% handle eyes
/leyewidth -33 yrot add sin -4 yrot add sin sub abs 2 div def
/reyewidth 33 yrot add sin 4 yrot add sin sub abs 2 div def
/eyeheight 30 xrot add sin xrot sin sub 2 div def
gsave
leyewidth eyeheight scale yrot 18 sub sin 0.25 div xrot 15
add sin 0.25 div translate eye
grestore
gsave
reyewidth eyeheight scale yrot 18 add sin 0.25 div xrot 15
add sin 0.25 div translate eye
grestore
%% handle eyebrows
gsave
0.25 0.25 scale yrot 18 sub sin 0.25 div xrot 34 add sin 0.25 div
translate eyebrow
grestore
gsave
-0.25 0.25 scale 18 yrot add sin -0.25 div xrot 34 add sin 0.25 div
translate eyebrow
grestore
end
} def
% rescale uniformly and set the line width to be equal to one unit beforehand
/rescale { dup dup scale 1 exch div setlinewidth } def
%% face definitions are defined as arrays, each containing a name and
%% a chromosome
/genename
[(brow) (itheta) (irad) (icl) (msf) (mco) (mscl) (xrot) (yrot) (zrot)] def