%% %% This is file `feynmp.mp', %% generated with the docstrip utility. %% %% The original source files were: %% %% feynmf.dtx (with options: `base,mp') %% %% Copyright (C) 1989, 1990, 1992-1995 by Thorsten.Ohl@Physik.TH-Darmstadt.de %% %% This file is NOT the source for feynmf, because almost all comments %% have been stripped from it. It is NOT the preferred form of feynmf %% for making modifications to it. %% %% Therefore you can NOT redistribute and/or modify THIS file. You can %% however redistribute the complete source (feynmf.dtx and feynmf.ins) %% and/or modify it under the terms of the GNU General Public License as %% published by the Free Software Foundation; either version 2, or (at %% your option) any later version. %% %% As a special exception, you can redistribute parts of this file for %% the electronic distribution of scientific papers, provided that you %% include a short note pointing to the complete source. %% %% Feynmf is distributed in the hope that it will be useful, but %% WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% \CheckSum{924} %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% def subgraph (expr x, y, wd, ht) = begingroup save c, ne, nw, sw, se; pair c, ne, nw, sw, se; sw = (x,y); se = sw + (wd,0); nw = sw + (0,ht); ne = sw + (wd,ht); c = .5[sw,ne]; enddef; def endsubgraph = endgroup enddef; if known cmbase: errhelp "feynmf will only work with plain Metafont, as described in the book."; errmessage "feynmf: CMBASE detected. Please use the PLAIN base."; forever: errmessage "No use in trying! You'd better eXit now ..."; errorstopmode; endfor fi vardef parse_RCS (suffix RCS) (expr s) = save n, c; numeric n, RCS[]; string c; RCS[0] := 0; for n = 1 upto length (s): c := substring (n-1,n) of s; exitif ((RCS[0] > 0) and (c = " ")); if ((c = "0") or (c = "1") or (c = "2") or (c = "3") or (c = "4") or (c = "5") or (c = "6") or (c = "7") or (c = "8") or (c = "9")): if RCS[0] = 0: RCS[0] := 1; RCS[RCS[0]] := 0; fi RCS[RCS[0]] := 10 * RCS[RCS[0]] + scantokens (c); elseif c = ".": RCS[0] := RCS[0] + 1; RCS[RCS[0]] := 0; else: fi endfor enddef; vardef require_RCS_revision expr s = save n, TeX_rev, mf_rev; numeric n; parse_RCS (TeX_rev, s); parse_RCS (mf_rev, "$Revision: 1.30 $"); for n = 1 upto min (2, TeX_rev[0], mf_rev[0]): if TeX_rev[n] > mf_rev[n]: errhelp "Your version of `feynmf.sty' is higher that of your `feynmf.mf'."; errmessage "feynmf: Metafont macros out of date"; elseif TeX_rev[n] < mf_rev[n]: errhelp "Your version of `feynmf.mf' is higher that of your `feynmf.sty'."; errmessage "feynmf: LaTeX style out of date"; fi exitif (TeX_rev[n] <> mf_rev[n]); endfor enddef; vardef cullit = \ enddef; color foreground; foreground = black; vardef beginchar (expr c, wd, ht, dp) = LaTeX_file := ""; beginfig(c); w:=wd; h:=ht; enddef; string LaTeX_file; vardef endchar = setbounds currentpicture to (0,0)--(w,0)--(w,h)--(0,h)--cycle; if LaTeX_file <> "": write EOF to LaTeX_file; LaTeX_file := ""; fi endfig enddef; bp# := bp; cc# := cc; cm# := cm; dd# := dd; in# := in; mm# := mm; pc# := pc; pt# := pt; vardef define_blacker_pixels(text t) = forsuffixes $=t: $:=$.#; endfor enddef; picture unitpixel; unitpixel = nullpicture; addto unitpixel contour unitsquare; def t_ = \ enddef; boolean feynmfwizard; feynmfwizard := false; thin# := 1pt#; % dimension of the lines thick# := 2thin#; arrow_len# := 4mm#; arrow_ang := 15; curly_len# := 3mm#; dash_len# := 3mm#; % 'photon' lines dot_len# := 2mm#; % 'photon' lines wiggly_len# := 4mm#; % 'photon' lines wiggly_slope := 60; zigzag_len# := 2mm#; zigzag_width# := 2thick#; decor_size# := 5mm#; dot_size# := 2thick#; define_blacker_pixels (thick, thin, dash_len, dot_len, wiggly_len, curly_len, zigzag_len, zigzag_width, arrow_len, decor_size, dot_size); def shrink expr s = begingroup if shrinkables <> "": save tmp_; forsuffixes $ = scantokens shrinkables: if known $.#: tmp_ := $.#; save $; $.# := s * tmp_; define_blacker_pixels ($); else: tmp_ := $; save $; $ := s * tmp_; fi endfor fi enddef; def endshrink = endgroup enddef; string shrinkables; shrinkables := ""; vardef addto_shrinkables (text l) = forsuffixes $ = l: shrinkables := shrinkables & "," & str $; endfor enddef; shrinkables := "thick,thin"; addto_shrinkables (dash_len, dot_len); addto_shrinkables (wiggly_len, curly_len); addto_shrinkables (zigzag_len, zigzag_width); addto_shrinkables (arrow_len); addto_shrinkables (decor_size, dot_size); LaTeX_unitlength := mm; vardef count (text list) = forsuffixes $ = list: + 1 endfor enddef; vardef getopt (suffix opt) (expr s) = save n, argp, escape, anchor, skip; numeric opt.first, opt.last, n, anchor; string opt[], opt[]arg; boolean opt[]tainted, argp, escape, skip; opt.first := 0; opt.last := 0; opt[opt.last] := ""; argp := false; escape := false; anchor := 0; skip := true; for n = 1 upto length (s): if skip and (substring (n-1, n) of s = " "): anchor := anchor + 1; else: skip := false; if not escape and (substring (n-1, n) of s = ","): if substring (n, n+1) of s = ",": escape := true; opt[opt.last]tainted := true; else: if argp: opt[opt.last]arg := substring (anchor, n-1) of s; else: opt[opt.last] := substring (anchor, n-1) of s; fi anchor := n; argp := false; skip := true; opt.last := opt.last + 1; fi elseif not argp and (substring (n-1, n) of s = "="): opt[opt.last] := substring (anchor, n-1) of s; anchor := n; argp := true; skip := true; elseif argp or (substring (n-1, n) of s <> " "): escape := false; fi fi endfor if argp: opt[opt.last]arg := substring (anchor, length s) of s; else: opt[opt.last] := substring (anchor, length s) of s; fi for n = opt.first upto opt.last: if known opt[n]tainted: if opt[n]tainted: opt[n]arg := untaint_string opt[n]arg; fi fi endfor enddef; vardef untaint_string suffix s = save n, anchor; numeric n, anchor; anchor := 0; for n = 1 upto length (s) - 1: if substring (n-1,n+1) of s = ",,": substring (anchor, n-1) of s & hide (anchor := n) fi endfor substring (anchor, length s) of s enddef; vardef split_string (suffix comp) (expr s) = save n, anchor; numeric comp.first, comp.last, n, anchor; string comp[]; comp.first := 0; comp.last := 0; comp[comp.last] := ""; anchor := 0; for n = 1 upto length (s): if substring (n-1,n) of s = ".": comp[comp.last] := substring (anchor, n-1) of s; comp.last := comp.last + 1; anchor := n; fi endfor comp[comp.last] := substring (anchor, length s) of s; enddef; vardef match_prefix (expr prefix, s) = (prefix = substring (0, length prefix) of s) enddef; vardef match_option (expr s, option) = save sc, optionc, n, i; numeric sc.first, sc.last, optionc.first, optionc.last; string sc[], optionc[]; numeric n, i; split_string (sc, s); split_string (optionc, option); n := sc.last - sc.first; if n <> (optionc.last - optionc.first): false else: true for i = 0 upto n: and match_prefix (sc[sc.first+i], optionc[optionc.first+i]) endfor fi enddef; def save_picture text t = save t; picture t; forsuffixes p=t: p:=nullpicture; endfor enddef; def begin_sketch = begingroup save_picture currentpicture; sketchlevel := sketchlevel+1; enddef; def end_sketch = sketchlevel := sketchlevel-1; sketchpad[sketchlevel] := currentpicture; endgroup enddef; picture sketchpad[]; sketchlevel := 1; vardef use_sketch text t = addto currentpicture also (sketchpad[sketchlevel] t) enddef; vardef cdraw expr p = draw p withcolor foreground enddef; vardef cfill expr p = fill p withcolor foreground enddef; vardef cfilldraw expr p = filldraw p withcolor foreground enddef; vardef ccutdraw expr p = cutdraw p withcolor foreground enddef; vardef cdrawdot expr p = drawdot p withcolor foreground enddef; vardef isdigit expr s = save n; (s = "0") for n = 1 upto 9: or (s = decimal n) endfor enddef; vardef digits_index (expr s, start) = save n, m, from, to; for n = start upto (length s)-1: if isdigit (substring (n,n+1) of s): from := n; for m = n upto length s: if not isdigit (substring (m,m+1) of s): to := m; fi exitif known to; endfor fi exitif known from; endfor (from, if known to: to else: infinity fi) enddef; vardef digits_to_brackets suffix suf = save s, idx; string s; pair idx; s = str suf; idx = (0,0); forever: idx := digits_index (s, xpart idx); exitif unknown xpart idx; s := substring (0,xpart idx) of s & "[]" & substring (ypart idx,infinity) of s; endfor s enddef; tile_grain := 1in/300; vardef def_tile (suffix t) (expr wd, ht) = if not picture tlist.t: picture tlist.scantokens (digits_to_brackets t); fi tlist.t := nullpicture; tlist.t.dx := max (floor wd, 1); tlist.t.dy := max (floor ht, 1); enddef; vardef use_tile (suffix t) (expr x, y, wd, ht) = fill unitsquare xscaled wd yscaled ht shifted (x,y) withcolor background; if str t = "shaded": shade_rectangle (4thin, x, y, wd, ht); elseif str t = "hatched": shade_rectangle (5thin, x, y, wd, ht); shade_rectangle (-5thin, x, y, wd, ht); else: if (picture tlist.t): for nx = 0 upto wd/tlist.t.dx: for ny = 0 upto ht/tlist.t.dy: addto currentpicture also (tlist.t shifted ((x,y) + (nx*tlist.t.dx, ny*tlist.t.dy)) t_); endfor endfor else: errhelp "feynmf: your tiling has not been defined, " & "check spelling and reprocess!"; errmessage "feynmf: tiling `" & str t & "' not known, " & "replaced by `shaded'"; use_tile (shaded, x, y, wd, ht); fi fi enddef; vardef shade_rectangle (expr dd, x, y, wd, ht) = save d, u, dx, dy, currentpen; pen currentpen; pickup pencircle scaled thin; d := max (floor (abs dd), 1); dx := max (wd, ht); dy := max (wd, ht); for u = 0 step d/dx until 1: if dd > 0: cdraw (x-d,y+u*dy-d)--(x+(1-u)*dx+d,y+dy+d); cdraw (x+u*dx-d,y-d)--(x+dx+d,y+(1-u)*dy+d); else: cdraw (x-d,y+u*dy+d)--(x+u*dx+d,y-d); cdraw (x+(1-u)*dx-d,y+dy+d)--(x+dx+d,y+(1-u)*dy-d); fi endfor enddef; def addto_tile (suffix t) = addto tlist.t enddef; vardef tile_from_string (suffix t) (expr str) = tile_grain := max (floor tile_grain, 1); save grain, mx, x, y, n, c, pic; string c; picture pic; pic := nullpicture; grain := tile_grain; mx := 0; x := 0; y := 0; for n := 1 upto length str: c := substring (n-1,n) of str; if c = "/": mx := max (mx, x); y := y+1; x := 0; elseif c = "*": addto pic also (unitpixel shifted (x,-y) t_); x := x+1; elseif c = ".": x := x+1; fi endfor def_tile (t, grain*mx, grain*(y+1)); addto_tile (t) also (pic shifted (0,y) scaled grain t_); pic := nullpicture; enddef; tile_from_string (gray10, " ... /"& " .*. /"& " ... "); tile_from_string (gray25, " .. /"& " *. "); tile_from_string (gray50, " .* /"& " *. "); tile_from_string (gray75, " ** /"& " .* "); tile_from_string (gray90, " *** /"& " *.* /"& " *** "); vardef make_halftone (suffix t) (expr g, wd, ht) = def_tile (t, wd, ht); addto tlist.t contour unitsquare xscaled wd yscaled ht withcolor ((1-g)*foreground + g*background) enddef; vardef tile (suffix t) (expr p) = save u, x, y, max_x, min_x, max_y, min_y, xx, yy; -max_x = -max_y = min_x = min_y = infinity; for u = 0 step 0.1 until length p: x := xpart (point u of p); y := ypart (point u of p); max_x := max(max_x, x); max_y := max(max_y, y); min_x := min(min_x, x); min_y := min(min_y, y); endfor begin_sketch use_tile (t, min_x, min_y, max_x-min_x, max_y-min_y); clip currentpicture to p; end_sketch; use_sketch; enddef; vardef drawtile (suffix t) (expr p) = tile (t, p); cdraw p enddef; vardef use_halftone (expr g, x, y, wd, ht) = fill unitsquare xscaled wd yscaled ht shifted (x,y) withcolor ((1-g)*foreground + g*background) enddef; vardef halftone (expr g, p) = fill p withcolor ((1-g)*foreground + g*background) enddef; vardef drawhalftone (expr g, p) = fill p withcolor ((1-g)*foreground + g*background); cdraw p enddef; vardef shade expr p = tile (shaded, p) enddef; vardef hatch expr p = tile (hatched, p) enddef; vardef emptydraw expr p = cullit; unfill p; cullit; cdraw p; enddef; vardef shadedraw expr p = cullit; unfill p; cullit; shade p; cdraw p; enddef; vardef hatchdraw expr p = cullit; unfill p; cullit; hatch p; cdraw p; enddef; vardef marrow (expr p, frac) = save a, t, z; pair z; a = angle direction frac*length(p) of p; z = point frac*length(p) of p; (t1,whatever) = p intersectiontimes (halfcircle scaled 2/3arrow_len rotated (a+90) shifted z); (t2,whatever) = p intersectiontimes (halfcircle scaled 4/3arrow_len rotated (a-90) shifted z); arrow_head (p, t1, t2, arrow_ang) enddef; vardef tarrow (expr p, frac) = save a, t, z; pair z; t1 = frac*length p; a = angle direction t1 of p; z = point t1 of p; (t2,whatever) = p intersectiontimes (halfcircle scaled 2arrow_len rotated (a-90) shifted z); arrow_head (p, t1, t2, arrow_ang) enddef; vardef harrow (expr p, frac) = save a, t, z; pair z; t2 = frac*length p; a = angle direction t2 of p; z = point t2 of p; (t1,whatever) = p intersectiontimes (halfcircle scaled 2arrow_len rotated (a+90) shifted z); arrow_head (p, t1, t2, arrow_ang) enddef; vardef arrow_head (expr p, from, to, ang) = save tip, ap, t; pair tip; path ap; t1 := from; t2 := to; if t1 = -1: t1 := 0; fi if t2 = -1: t2 := infinity; fi tip = point t2 of p; ap = subpath (t1,t2) of p shifted -tip; (ap rotated ang forced_join reverse ap rotated -ang -- cycle) shifted tip enddef; vardef arrow expr p = marrow (p, .5) enddef; tertiarydef p forced_join q = subpath (0, length p - 1) of p & point (length p - 1) of p .. controls postcontrol (length p - 1) of p and precontrol infinity of p .. .5[point infinity of p, point 0 of q] .. controls postcontrol 0 of q and precontrol 1 of q .. point 1 of q & subpath (1, infinity) of q enddef; vardef cut_decors (suffix from) (expr p) (suffix to) = subpath (if known from.decor.shape: xpart (p intersectiontimes (from.decor.shape scaled from.decor.size shifted from.loc)) else: 0 fi, if known to.decor.shape: length p - xpart (reverse p intersectiontimes (to.decor.shape scaled to.decor.size shifted to.loc)) else: infinity fi) of p enddef; vardef make_blob (expr z_arg, diameter) = save p,currentpen; path p; pen currentpen; pickup pencircle scaled thick; p = fullcircle scaled diameter shifted z_arg; shadedraw p; enddef; vardef draw_blob (expr z_arg, diameter) = if sketched_blob_diameter <> diameter: % drawn lately? begin_sketch make_blob (origin, diameter); end_sketch; % redo hard work! sketched_blob_diameter:= diameter; % record it fi use_sketch shifted z_arg; % the easy way ... enddef; def force_new_blob = sketched_blob_diameter := -1; enddef; force_new_blob; % initialize it. vardef pixlen (expr p, n) = for k=1 upto length(p): + segment_pixlen (subpath (k-1,k) of p, n) endfor enddef; vardef segment_pixlen (expr p, n) = for k=1 upto n: + abs (point k/n of p - point (k-1)/n of p) endfor enddef; vardef wiggly expr p_arg = save wpp; numeric wpp; wpp = ceiling (pixlen (p_arg, 10) / wiggly_len) / length p_arg; for k=0 upto wpp*length(p_arg) - 1: point k/wpp of p_arg {direction k/wpp of p_arg rotated wiggly_slope} .. point (k+.5)/wpp of p_arg {direction (k+.5)/wpp of p_arg rotated - wiggly_slope} .. endfor if cycle p_arg: cycle else: point infinity of p_arg fi enddef; vardef curly expr p = save cpp; numeric cpp; cpp := ceiling (pixlen (p, 10) / curly_len) / length p; if cycle p: for k=0 upto cpp*length(p) - 1: point (k+.33)/cpp of p {direction (k+.33)/cpp of p rotated 90} .. point (k-.33)/cpp of p {direction (k-.33)/cpp of p rotated -90} .. endfor cycle else: point 0 of p {direction 0 of p rotated -90} .. for k=1 upto cpp*length(p) - 1: point (k+.33)/cpp of p {direction (k+.33)/cpp of p rotated 90} .. point (k-.33)/cpp of p {direction (k-.33)/cpp of p rotated -90} .. endfor point infinity of p {direction infinity of p rotated 90} fi enddef; vardef zigzag expr p = save zpp; numeric zpp; zpp = ceiling (pixlen (p, 10) / zigzag_len) / length p; if not cycle p: point 0 of p -- fi for k = 0 upto zpp*length(p) - 1: point (k+1/3)/zpp of p shifted (zigzag_width * dir angle (direction (k+1/3)/zpp of p rotated 90)) -- point (k+2/3)/zpp of p shifted (zigzag_width * dir angle (direction (k+2/3)/zpp of p rotated -90)) -- endfor if cycle p: cycle else: point infinity of p fi enddef; save vsty_hash; def style_def suffix s = vsty_hash.s := 1; expandafter quote vardef scantokens ("draw_" & str s) enddef; vardef vsty_exists suffix s = known vsty_hash.s enddef; vardef valid_style expr s = expandafter vsty_exists scantokens (s) enddef; style_def phantom expr p = \ enddef; style_def phantom_arrow expr p = cfill (arrow p); enddef; style_def plain expr p = cdraw p; enddef; style_def plain_arrow expr p = cdraw p; cfill (arrow p); enddef; style_def dbl_plain expr p = draw_double p; enddef; style_def dbl_plain_arrow expr p = draw_double_arrow p; enddef; style_def wiggly expr p = cdraw (wiggly p); enddef; style_def dbl_wiggly expr p = draw_double (wiggly p); enddef; style_def curly expr p = cdraw (curly p); enddef; style_def dbl_curly expr p = draw_double (curly p); enddef; style_def zigzag expr p = cdraw (zigzag p); enddef; style_def dbl_zigzag expr p = draw_double (zigzag p); enddef; style_def dashes expr p = save dpp; numeric dpp; dpp = ceiling (pixlen (p, 10) / dash_len) / length p; for k=0 upto dpp*length(p) - 1: cdraw point k/dpp of p .. point (k+.5)/dpp of p; endfor enddef; style_def dbl_dashes expr p = save dpp; numeric dpp; dpp = ceiling (pixlen (p, 10) / dash_len) / length p; for k=0 upto dpp*length(p) - 1: draw_double point k/dpp of p .. point (k+.5)/dpp of p; endfor enddef; style_def dbl_dashes_arrow expr p = draw_dbl_dashes p; shrink (1.5); cfill (arrow p); endshrink; enddef; style_def dashes_arrow expr p = draw_dashes p; cfill (arrow p); enddef; style_def dots expr p = save dpp; numeric dpp; dpp = ceiling (pixlen (p, 10) / dot_len) / length p; for k=0 upto dpp*length(p): cdrawdot point k/dpp of p; endfor enddef; style_def dbl_dots expr p = save dpp; numeric dpp; dpp = ceiling (pixlen (p, 10) / dot_len) / length p; begingroup save oldpen; pen oldpen; oldpen := currentpen; pickup oldpen scaled 3; % draw a thick linn for k=0 upto dpp*length(p): cdrawdot point k/dpp of p; endfor pickup oldpen; cullit; for k=0 upto dpp*length(p): undrawdot point k/dpp of p; endfor cullit; % and remove the stuffing endgroup; enddef; style_def dbl_dots_arrow expr p = draw_dbl_dots p; shrink (1.5); cfill (arrow p); endshrink; enddef; style_def dots_arrow expr p = draw_dots p; cfill (arrow p); enddef; style_def double expr p = save oldpen; pen oldpen; oldpen := currentpen; pickup oldpen scaled 3; ccutdraw p; pickup oldpen; cullit; undraw p; cullit; enddef; style_def double_arrow expr p = draw_double p; shrink (1.5); cfill (arrow p); endshrink; enddef; style_def vanilla expr p = draw_plain p enddef; style_def fermion expr p = draw_plain_arrow p enddef; style_def quark expr p = draw_plain_arrow p enddef; style_def electron expr p = draw_plain_arrow p enddef; style_def photon expr p = draw_wiggly p enddef; style_def boson expr p = draw_wiggly p enddef; style_def gluon expr p = draw_curly p enddef; style_def heavy expr p = draw_dbl_plain_arrow p enddef; style_def ghost expr p = draw_dots_arrow p enddef; style_def scalar expr p = draw_dashes_arrow p enddef; vardef fermion expr path_arg = cfill (arrow (path_arg)); path_arg enddef; vardef photon expr path_arg = wiggly path_arg enddef; vardef gluon expr path_arg = curly path_arg enddef; tracingstats:=1; boolean vtracing; vtracing := false; % true def vinit = save vhash; numeric vlist.first, vlist.last; vlist.first := 1; vlist.last := 0; pair vlist[]loc; numeric vlist[]decor.size, vlist[]decor.ang, vlist[]arc.first, vlist[]arc.last, vlist[]arc[], vlist[]arc[]lsr, vlist[]arc[]tns, vlist[]arc[]lbl.dist, vlist[]arc[]tag, vlist[]arc[]wd, vlist[]arc[]rub, vlist[]constr.first, vlist[]constr.last, vlist[]constr[], lambdax[][], lambday[][]; string vlist[]name, vlist[]lbl, vlist[]decor.sty, vlist[]arc[]sty, vlist[]arc[]lbl, vlist[]arc[]lbl.side; numeric vlist[]lbl.ang; path vlist[]decor.shape; color vlist[]fore, vlist[]back, vlist[]arc[]fore, vlist[]arc[]back; numeric plist.first, plist.last, plist[]cnt, plist[]vtx[], plist[]pull, plist[]lbl.ang, plist[]lbl.dist; string plist[]lbl, plist[]sty, plist[]cona, plist[]conb; plist.first := 1; plist.last := 0; numeric vlist[]poly.first, vlist[]poly.last, vlist[]poly[], vlist[]poly[]idx; pair lambdap[][]; color plist[]fore, plist[]back; enddef; def vertices = vlist.first upto vlist.last enddef; def varcs (text i) = vlist[i]arc.first upto vlist[i]arc.last enddef; def vconstr (text i) = vlist[i]constr.first upto vlist[i]constr.last enddef; def polygons = plist.first upto plist.last enddef; def vpoly (text i) = vlist[i]poly.first upto vlist[i]poly.last enddef; vardef venter suffix v = if not vexists v: vlist.last := vlist.last + 1; vhash.v := vlist.last; vlist[vhash.v]name := str v; vlist[vhash.v]loc := (whatever,whatever); vlist[vhash.v]arc.first := 1; vlist[vhash.v]arc.last := 0; vlist[vhash.v]constr.first := 1; vlist[vhash.v]constr.last := 0; vlist[vhash.v]lbl := ""; vlist[vhash.v]lbl.ang := whatever; vlist[vhash.v]lbl.dist := 3thick; vlist[vhash.v]fore := (whatever, whatever, whatever); vlist[vhash.v]back := (whatever, whatever, whatever); vlist[vhash.v]poly.first := 1; vlist[vhash.v]poly.last := 0; fi enddef; vardef vexists suffix v = if known vhash.v: true else: false fi enddef; vardef vlookup suffix v = if vexists v: vhash.v else: 0 fi enddef; vardef vloc suffix v = vlist[vlookup v]loc enddef; vardef vconnect (expr linesty) (text vl) = save from, nfrom, nto, nopt, sty; numeric from, nfrom, nto, nopt; string sty; getopt (opt, linesty); sty := opt[opt.first]; if known opt[opt.first]arg: message "feynmf: line styles don't take arguments. " & "Argument `" & opt[opt.first]arg & "' ignored."; fi opt.first := opt.first + 1; forsuffixes to = vl: venter to; nto := vlookup to; if known nfrom: vlist[nfrom]arc.last := vlist[nfrom]arc.last + 1; vlist[nfrom]arc[vlist[nfrom]arc.last] := nto; vlist[nfrom]arc[vlist[nfrom]arc.last]tns := 1; if nfrom <> nto: vlist[nto]arc.last := vlist[nto]arc.last + 1; vlist[nto]arc[vlist[nto]arc.last] := nfrom; vlist[nto]arc[vlist[nto]arc.last]tns := 1; fi vlist[nfrom]arc[vlist[nfrom]arc.last]lbl := ""; vlist[nfrom]arc[vlist[nfrom]arc.last]lbl.side := ""; vlist[nfrom]arc[vlist[nfrom]arc.last]lbl.dist := 3thick; for nopt = opt.first upto opt.last: if match_option (opt[nopt], "tension"): get_argument (opt[nopt], scantokens (opt[nopt]arg), vlist[nfrom]arc[vlist[nfrom]arc.last]tns); get_argument (opt[nopt], scantokens (opt[nopt]arg), vlist[nto]arc[vlist[nto]arc.last]tns); elseif match_option (opt[nopt], "left"): if known opt[nopt]arg: vlist[nfrom]arc[vlist[nfrom]arc.last]lsr := - scantokens (opt[nopt]arg); else: vlist[nfrom]arc[vlist[nfrom]arc.last]lsr := -1; fi elseif match_option (opt[nopt], "straight"): vlist[nfrom]arc[vlist[nfrom]arc.last]lsr := 0; ignore_argument (opt[nopt], opt[nopt]arg); elseif match_option (opt[nopt], "right"): if known opt[nopt]arg: vlist[nfrom]arc[vlist[nfrom]arc.last]lsr := scantokens (opt[nopt]arg); else: vlist[nfrom]arc[vlist[nfrom]arc.last]lsr := 1; fi elseif match_option (opt[nopt], "label"): get_argument (opt[nopt], opt[nopt]arg, vlist[nfrom]arc[vlist[nfrom]arc.last]lbl); elseif match_option (opt[nopt], "label.side"): get_argument (opt[nopt], opt[nopt]arg, vlist[nfrom]arc[vlist[nfrom]arc.last]lbl.side); elseif match_option (opt[nopt], "label.dist"): get_argument (opt[nopt], scantokens (opt[nopt]arg), vlist[nfrom]arc[vlist[nfrom]arc.last]lbl.dist); elseif match_option (opt[nopt], "tag"): if known opt[nopt]arg: vlist[nfrom]arc[vlist[nfrom]arc.last]tag := scantokens (opt[nopt]arg); else: vlist[nfrom]arc[vlist[nfrom]arc.last]tag := 0; fi elseif match_option (opt[nopt], "width"): get_argument (opt[nopt], scantokens (opt[nopt]arg), vlist[nfrom]arc[vlist[nfrom]arc.last]wd); elseif match_option (opt[nopt], "foreground"): get_argument (opt[nopt], scantokens (opt[nopt]arg), vlist[nfrom]arc[vlist[nfrom]arc.last]fore); elseif match_option (opt[nopt], "background"): get_argument (opt[nopt], scantokens (opt[nopt]arg), vlist[nfrom]arc[vlist[nfrom]arc.last]back); elseif match_option (opt[nopt], "rubout"): if known opt[nopt]arg: vlist[nfrom]arc[vlist[nfrom]arc.last]rub := scantokens (opt[nopt]arg); else: vlist[nfrom]arc[vlist[nfrom]arc.last]rub := 2; fi else: ignore_option (opt[nopt], opt[nopt]arg); fi endfor handle_line_style (vlist[nfrom]arc[vlist[nfrom]arc.last]sty, sty); vlist[nto]arc[vlist[nto]arc.last]lsr := vlist[nfrom]arc[vlist[nfrom]arc.last]lsr; fi nfrom := nto; endfor enddef; vardef handle_line_style (suffix sty) (expr name) = if valid_style name: sty := name; else: errhelp "feynmf: your linestyle is not recognizable, " & "check spelling and reprocess!"; errmessage "feynmf: line style `" & name & "' not known, " & "replaced by `vanilla'"; sty := "vanilla"; fi enddef; vardef get_argument (expr opt, arg) (suffix variable) = if known arg: variable := arg; else: message "feynmf: option `" & opt & "' needs an argument. Ignored."; fi enddef; vardef ignore_argument (expr opt, arg) = if known arg: message "feynmf: option `" & opt & "' doesn't take an argument. " & "Argument `" & arg & "' ignored."; fi enddef; vardef ignore_option (expr opt, arg)= if known arg: message "feynmf: ignoring option " & opt & "=" & arg & "."; else: message "feynmf: ignoring option " & opt & "."; fi enddef; vardef vconnectn (expr linesty) (suffix v) (expr n) = vconnect (linesty, vmklist (v, n)); enddef; vardef vpath@# (suffix from, to) = save nfrom, nto, origin, index, unknown_path; numeric nfrom, nto, origin, index; path unknown_path; if (known vloc from) and (known vloc to): nfrom := vlookup from; nto := vlookup to; vmatch_path (nfrom, nto, maybe_empty@#); if (unknown origin) or (unknown index): vmatch_path (nto, nfrom, maybe_empty@#); fi fi if (known origin) and (known index): vbuild_cut_arc (origin, index) else: unknown_path fi enddef; vardef maybe_empty@# = save _prefix; _prefix=137; if known _prefix@#: whatever else: @# fi enddef; vardef vmatch_path (expr nfrom, nto, t) = save i; for i = varcs (nfrom): if (vlist[nfrom]arc[i] = nto) and (known vlist[nfrom]arc[i]sty): if unknown t: origin := nfrom; index := i; else: if known vlist[nfrom]arc[i]tag: if vlist[nfrom]arc[i]tag = t: origin := nfrom; index := i; fi fi fi fi endfor enddef; vardef vcyclen (expr sty) (suffix v) (expr n) = for $ = 1 upto n - 1: vconnect (sty, v[$], v[$+1]); endfor vconnect (sty, v[n], v[1]); enddef; vardef vrcyclen (expr sty) (suffix v) (expr n) = vconnect (sty, v[1], v[n]); for $ = n downto 2: vconnect (sty, v[$], v[$-1]); endfor enddef; vardef vforce (expr z) (suffix v) = venter v; vlist[vlookup v]loc := z; enddef; vardef vshift (expr z) (text vl) = forsuffixes $=vl: if vexists $: vlist[vlookup $]loc := vlist[vlookup $]loc + z; fi endfor enddef; vardef vconstraint (expr z) (text vl) = save nfrom, nto; numeric nfrom, nto; forsuffixes to = vl: venter to; nto := vlookup to; if known nfrom: vlist[nfrom]constr.last := vlist[nfrom]constr.last + 1; vlist[nto]constr.last := vlist[nto]constr.last + 1; vlist[nfrom]constr[vlist[nfrom]constr.last] := nto; vlist[nto]constr[vlist[nto]constr.last] := nfrom; vlist[nto]loc = vlist[nfrom]loc + z; fi nfrom := nto; endfor enddef; vardef vpolygon (expr psty) (suffix v) (text vl) = save nopt, csty, nfrom, nfrom_, nto, i, n, j; numeric nopt, nfrom, nfrom_, nto, i, n, j; string csty; n := count (vl) + 1; plist.last := plist.last + 1; plist[plist.last]cnt := n; plist[plist.last]lbl := ""; plist[plist.last]lbl.ang := whatever; plist[plist.last]lbl.dist := 0; csty := "phantom"; getopt (opt, psty); for nopt = opt.first upto opt.last: if match_option (opt[nopt], "filled"): get_argument (opt[nopt], opt[nopt]arg, plist[plist.last]sty); elseif match_option (opt[nopt], "tension"): if known opt[nopt]arg: csty := csty & ",tension=" & opt[nopt]arg; else: message "feynmf: option `tension' needs an argument. Ignored."; fi elseif match_option (opt[nopt], "label"): get_argument (opt[nopt], opt[nopt]arg, plist[plist.last]lbl); elseif match_option (opt[nopt], "label.angle"): get_argument (opt[nopt], scantokens (opt[nopt]arg), plist[plist.last]lbl.ang); elseif match_option (opt[nopt], "label.dist"): get_argument (opt[nopt], scantokens (opt[nopt]arg), plist[plist.last]lbl.dist); elseif match_option (opt[nopt], "pull"): get_argument (opt[nopt], scantokens (opt[nopt]arg), plist[plist.last]pull); elseif match_option (opt[nopt], "cona"): get_argument (opt[nopt], opt[nopt]arg, plist[plist.last]cona); elseif match_option (opt[nopt], "conb"): get_argument (opt[nopt], opt[nopt]arg, plist[plist.last]conb); elseif match_option (opt[nopt], "smooth"): plist[plist.last]cona := ".."; plist[plist.last]conb := ".."; ignore_argument (opt[nopt], opt[nopt]arg); elseif match_option (opt[nopt], "foreground"): get_argument (opt[nopt], scantokens (opt[nopt]arg), plist[plist.last]fore); elseif match_option (opt[nopt], "background"): get_argument (opt[nopt], scantokens (opt[nopt]arg), plist[plist.last]back); elseif match_option (opt[nopt], "phantom"): plist[plist.last]sty := "phantom"; elseif match_option (opt[nopt], "empty"): plist[plist.last]sty := "empty"; elseif match_option (opt[nopt], "full"): plist[plist.last]sty := "full"; elseif match_option (opt[nopt], "hatched"): plist[plist.last]sty := "hatched"; elseif match_option (opt[nopt], "shaded"): plist[plist.last]sty := "shaded"; else: ignore_option (opt[nopt], opt[nopt]arg); fi endfor canonicalize_filling plist[plist.last]sty; vconnect (csty, v, vl, v); i := 1; forsuffixes to = v, vl, v: nto := vlookup to; if known nfrom: if known nfrom_: vlist[nto]loc = vlist[nfrom]loc + (vlist[nfrom]loc - vlist[nfrom_]loc) rotated (360/n); fi vlist[nto]poly.last := vlist[nto]poly.last + 1; vlist[nto]poly[vlist[nto]poly.last] := plist.last; vlist[nto]poly[vlist[nto]poly.last]idx := i; plist[plist.last]vtx[i] := nto; i := i + 1; nfrom_ := nfrom; fi nfrom := nto; endfor enddef; vardef canonicalize_filling suffix f = if known f: if is_a_number (f): if scantokens f <= 1: f := if scantokens f = 1: "full" elseif scantokens f > 0: "shaded" elseif scantokens f = 0: "empty" else: "hatched" fi; fi fi fi enddef; vardef vpolygonn (expr sty) (suffix v) (expr n) = vpolygon (sty, v[1], for $=2 upto n-1: v[$], endfor v[n]); enddef; vardef vrpolygonn (expr sty) (suffix v) (expr n) = vpolygon (sty, v[n], for $=n-1 downto 2: v[$], endfor v[1]); enddef; vardef vlabel (expr s) (suffix v) = venter v; vlist[vlookup v]lbl := s; enddef; vardef vvertex (expr vtxsty) (text vl) = save nopt, sty, arg; numeric nopt, arg; string sty; getopt (opt, vtxsty); forsuffixes v = vl: venter v; n := vlookup v; for nopt = opt.first upto opt.last: handle_vertex_option (vlist[n], opt[nopt], opt[nopt]arg); endfor endfor enddef; vardef handle_vertex_option (suffix v) (expr opt, arg) = if match_option (opt, "label"): get_argument (opt, arg, v.lbl); elseif match_option (opt, "label.angle"): get_argument (opt, scantokens (arg), v.lbl.ang); elseif match_option (opt, "label.dist"): get_argument (opt, scantokens (arg), v.lbl.dist); elseif match_option (opt, "decoration.shape"): if known arg: make_decor_shape (v.decor.shape, arg); else: message "feynmf: option `decor.shape' needs an argument. Ignored."; fi elseif match_option (opt, "decoration.filled"): get_argument (opt, arg, v.decor.sty); canonicalize_filling v.decor.sty; elseif match_option (opt, "decoration.size"): get_argument (opt, scantokens (arg), v.decor.size); elseif match_option (opt, "decoration.angle"): get_argument (opt, scantokens (arg), v.decor.ang); elseif match_option (opt, "foreground"): get_argument (opt, scantokens (arg), v.fore); elseif match_option (opt, "background"): get_argument (opt, scantokens (arg), v.back); else: ignore_option (opt, arg); fi enddef; vardef make_decor_shape (suffix p) (expr n) = if match_prefix (n, "circle"): p := fullcircle; elseif match_prefix (n, "square"): p := unitsquare shifted -(.5,.5); elseif match_prefix (n, "cross"): p := polycross 4; elseif match_prefix (n, "triangle"): p := polygon 3; elseif match_prefix (n, "triagon"): p := polygon 3; elseif match_prefix (n, "diamond"): p := polygon 4; elseif match_prefix (n, "tetragon"): p := polygon 4; elseif match_prefix (n, "pentagon"): p := polygon 5; elseif match_prefix (n, "hexagon"): p := polygon 6; elseif match_prefix (n, "triagram"): p := polygram 3; elseif match_prefix (n, "tetragram"): p := polygram 4; elseif match_prefix (n, "pentagram"): p := polygram 5; elseif match_prefix (n, "hexagram"): p := polygram 6; elseif match_prefix (n, "triacross"): p := polycross 3; elseif match_prefix (n, "tetracross"): p := polycross 4; elseif match_prefix (n, "pentacross"): p := polycross 5; elseif match_prefix (n, "hexacross"): p := polycross 6; else: if feynmfwizard: p := scantokens(n); else: message "feynmf: invalid argument `" & n & "' to option `decor.shape'. Ignored."; fi fi enddef; vardef is_a_number expr s = save n; if known s: (true for n = 1 upto length s: and ((substring (n-1,n) of s = ".") or (substring (n-1,n) of s = "-") or isdigit substring (n-1,n) of s) endfor) else: false fi enddef; vardef vvertexn (expr vtxsty) (suffix v) (expr n) = vvertex (vtxsty, vmklist (v, n)); enddef; vardef vblob (expr bd) (text vl)= forsuffixes $=vl: if not vexists $: venter $; fi vlist[vlookup $]decor.shape := fullcircle; vlist[vlookup $]decor.size := bd; vlist[vlookup $]decor.sty := "shaded"; endfor enddef; vardef vdot (text vl)= forsuffixes $=vl: if not vexists $: venter $; fi vlist[vlookup $]decor.shape := fullcircle; vlist[vlookup $]decor.size := dot_size; vlist[vlookup $]decor.sty := "full"; endfor enddef; vardef vdotn (suffix v) (expr n) = vdot (vmklist (v, n)); enddef; vardef vblobn (suffix v) (expr n) = vblob (vmklist (v, n)); enddef; vardef curved_left_gallery = .9[se,sw] .. .5[sw,nw] .. .1[nw,ne] enddef; vardef curved_right_gallery = .9[sw,se] .. .5[se,ne] .. .1[ne,nw] enddef; vardef curved_bottom_gallery = .9[nw,sw] .. .5[sw,se] .. .1[se,ne] enddef; vardef curved_top_gallery = .9[sw,nw] .. .5[nw,ne] .. .1[ne,se] enddef; vardef curved_surround_gallery = superellipse (.5[se,ne], .5[ne,nw], .5[nw,sw], .5[sw,se], .75) enddef; vardef straight_left_gallery = sw -- nw enddef; vardef straight_right_gallery = se -- ne enddef; vardef straight_bottom_gallery = sw -- se enddef; vardef straight_top_gallery = nw -- ne enddef; vardef straight_surround_gallery = .5[se,ne] -- ne -- .5[ne,nw] -- nw -- .5[nw,sw] -- sw -- .5[sw,se] -- se -- cycle enddef; vardef curved_galleries = vardef left_gallery = curved_left_gallery enddef; vardef right_gallery = curved_right_gallery enddef; vardef bottom_gallery = curved_bottom_gallery enddef; vardef top_gallery = curved_top_gallery enddef; vardef surround_gallery = curved_surround_gallery enddef; enddef; vardef straight_galleries = vardef left_gallery = straight_left_gallery enddef; vardef right_gallery = straight_right_gallery enddef; vardef bottom_gallery = straight_bottom_gallery enddef; vardef top_gallery = straight_top_gallery enddef; vardef surround_gallery = straight_surround_gallery enddef; enddef; vardef vleft (text vl) = vdistribute (left_gallery, vl) enddef; vardef vright (text vl) = vdistribute (right_gallery, vl) enddef; vardef vbottom (text vl) = vdistribute (bottom_gallery, vl) enddef; vardef vtop (text vl) = vdistribute (top_gallery, vl) enddef; vardef vsurround (text vl) = vdistribute (surround_gallery, vl) enddef; curved_galleries; vardef vdistribute (expr p) (text vl) = save numv, len, off; numeric numv, len, off; numv = count (vl); if cycle p: numv := numv + 1; fi len := length (p); if numv = 1: vforce (point len/2 of p, vl); else: off := 0; forsuffixes $ = vl: vforce (point off of p, $); off := off + len/(numv-1); endfor fi enddef; def vmklist (suffix v) (expr n) = for $ = 1 upto n-1: v[$], endfor v[n] enddef; vardef vleftn (suffix v) (expr n) = vleft (vmklist (v, n)); enddef; vardef vrightn (suffix v) (expr n) = vright (vmklist (v, n)); enddef; vardef vbottomn (suffix v) (expr n) = vbottom (vmklist (v, n)); enddef; vardef vtopn (suffix v) (expr n) = vtop (vmklist (v, n)); enddef; vardef vsurroundn (suffix v) (expr n) = vsurround (vmklist (v, n)); enddef; vardef vfreeze = for i = vertices: if unknown vlist[i]loc: origin = origin for j = varcs (i): + vlist[i]arc[j]tns * (vlist[i]loc - vlist[vlist[i]arc[j]]loc) endfor for j = vconstr (i): if i < vlist[i]constr[j]: + lambda (i, vlist[i]constr[j]) elseif i > vlist[i]constr[j]: - lambda (vlist[i]constr[j], i) fi endfor for j = vpoly (i): + lambdapoly (vlist[i]poly[j], plist[vlist[i]poly[j]]cnt, vlist[i]poly[j]idx) endfor; fi endfor if vtracing: vdump; fi enddef; vardef lambda (expr i, j) = (if known (xpart(vlist[i]loc - vlist[j]loc)): lambdax[i][j] else: 0 fi, if known (ypart(vlist[i]loc - vlist[j]loc)): lambday[i][j] else: 0 fi) enddef; vardef lambdapoly (expr p, n, i) = origin if i = 1: + lambdap[p][2] rotated (-360/n) elseif i = 2: - lambdap[p][1] fi if i = n - 1: - lambdap[p][n] rotated (-360/n) elseif i = n: + lambdap[p][n-1] fi if (i > 1) and (i < n): + lambdap[p][i-1] + lambdap[p][i+1] rotated (-360/n) - lambdap[p][i] - lambdap[p][i] rotated (-360/n) fi enddef; vardef idraw (expr linesty, p) = save nopt, sty, lbl, wd, rub; numeric nopt, lbl.dist, wd, rub; save fore, back; color fore, back; string sty, lbl, lbl.side; getopt (opt, linesty); sty := opt[opt.first]; if known opt[opt.first]arg: message "feynmf: line styles don't take arguments. " & "Argument `" & opt[opt.first]arg & "' ignored."; fi opt.first := opt.first + 1; lbl := ""; lbl.side := ""; lbl.dist := 3thick; for nopt = opt.first upto opt.last: if match_option (opt[nopt], "label"): get_argument (opt[nopt], opt[nopt]arg, lbl); elseif match_option (opt[nopt], "label.side"): get_argument (opt[nopt], opt[nopt]arg, lbl.side); elseif match_option (opt[nopt], "label.dist"): get_argument (opt[nopt], scantokens (opt[nopt]arg), lbl.dist); elseif match_option (opt[nopt], "width"): get_argument (opt[nopt], scantokens (opt[nopt]arg), wd); elseif match_option (opt[nopt], "foreground"): get_argument (opt[nopt], scantokens (opt[nopt]arg), fore); elseif match_option (opt[nopt], "background"): get_argument (opt[nopt], scantokens (opt[nopt]arg), back); elseif match_option (opt[nopt], "rubout"): if known opt[nopt]arg: rub := scantokens (opt[nopt]arg); else: rub := 2; fi else: ignore_option (opt[nopt], opt[nopt]arg); fi endfor handle_line_style (sty, sty); begingroup if known fore: save foreground; color foreground; foreground = fore; fi if known back: save background; color background; foreground = back; fi vdraw_arc_rubout (rub, sty, wd, p, lbl); endgroup; enddef; vardef ivertex (expr vtxsty, pos) = save nopt, v; numeric nopt, v.lbl.ang, v.lbl.dist, v.decor.size, v.decor.ang; pair v.loc; string v.lbl, v.decor.sty; path v.decor.shape; v.loc := pos; v.lbl := ""; v.lbl.ang := whatever; v.lbl.dist := 3thick; v.decor.size := decor_size; getopt (opt, vtxsty); for nopt = opt.first upto opt.last: handle_vertex_option (v, opt[nopt], opt[nopt]arg); endfor vdraw_label (v.loc, v.lbl); vdraw_vertex v; enddef; vardef vdraw = if not feynmfwizard: vcheck_typos; fi for i = vertices: if not known vlist[i]loc: errhelp "Your graph specification was not complete (probably a " & "lone vertex). Check logic and reprocess!"; errmessage "feynmf: vertex `" & vlist[i]name & "' not determined, " & "replaced by `(0,0)'."; vlist[i]loc := origin; fi if unknown vlist[i]decor.size: vlist[i]decor.size = decor_size; fi endfor for i = vertices: for j = varcs (i): if known vlist[i]arc[j]sty: if vlist[i]arc[j]sty <> "": if unknown vlist[i]arc[j]rub: begingroup if known vlist[i]arc[j]fore: save foreground; color foreground; foreground = vlist[i]arc[j]fore; fi if known vlist[i]arc[j]back: save background; color background; background = vlist[i]arc[j]back; fi vdraw_arc (vlist[i]arc[j]sty, vlist[i]arc[j]wd, vbuild_cut_arc (i, j), vlist[i]arc[j]lbl); vlist[i]arc[j]sty := ""; endgroup; fi fi fi endfor; endfor for i = polygons: vdraw_label (pcenter plist[i], plist[i]lbl); vdraw_polygon plist[i]; endfor for i = vertices: vdraw_label (vlist[i]loc, vlist[i]lbl); vdraw_vertex vlist[i]; endfor for i = vertices: for j = varcs (i): if known vlist[i]arc[j]sty: if vlist[i]arc[j]sty <> "": if known vlist[i]arc[j]rub: begingroup if known vlist[i]arc[j]fore: save foreground; color foreground; foreground = vlist[i]arc[j]fore; fi if known vlist[i]arc[j]back: save background; color background; background = vlist[i]arc[j]back; fi vdraw_arc_rubout (vlist[i]arc[j]rub, vlist[i]arc[j]sty, vlist[i]arc[j]wd, vbuild_cut_arc (i, j), vlist[i]arc[j]lbl); vlist[i]arc[j]sty := ""; endgroup; fi fi fi endfor; endfor enddef; vardef vcheck_typos = save j, err; boolean wrn; wrn := false; for i = vertices: save connections; connections = vlist[i]arc.last - vlist[i]arc.first + 1; if connections < 1: if unknown vlist[i]loc: message "feynmf: warning: disconnected and unspecified vertex `" & substring (2,infinity) of vlist[i]name & "'."; wrn := true; fi elseif connections = 1: j := vlist[i]arc[vlist[i]arc.last]; if j < i: if vlist[i]loc = vlist[j]loc: message "feynmf: warning: dangling vertex `" & substring (2,infinity) of vlist[i]name & "' colliding with `" & substring (2,infinity) of vlist[j]name & "'."; wrn := true; fi fi fi endfor if wrn: message "feynmf: Have you seen the warning messages above?"; message " They are usually caused by misspelling a vertex'"; message " name and can trigger errors further below!"; message " Fix the typos and run LaTeX and Metafont again."; fi enddef; vardef vbuild_arc (expr lsr, from, to) = if unknown lsr: from -- to else: if lsr = 0: from -- to else: from .. (1-lsr)/2 *(to rotatedabout (.5[from,to], 90)) + (1+lsr)/2 * (to rotatedabout (.5[from,to], -90)) .. to fi fi enddef; vardef vbuild_cut_arc (expr origin, index) = cut_decors (vlist[origin], if vlist[origin]arc[index] <> origin: vbuild_arc (vlist[origin]arc[index]lsr, vlist[origin]loc, vlist[vlist[origin]arc[index]]loc) else: vbuild_tadpole (origin, index) fi, vlist[vlist[origin]arc[index]]) enddef; vardef vbuild_tadpole (expr origin, index) = save j, n, nn, nnn, aidx, aang, agap, bgap, ngap, distsum; n := 0; distsum := 0; for j = varcs (origin): if vlist[origin]arc[j] <> origin: ang := angle direction 0 of vbuild_arc (vlist[origin]arc[j]lsr, vlist[origin]loc, vlist[vlist[origin]arc[j]]loc); n := n + 1; distsum := distsum + abs (vlist[vlist[origin]arc[j]]loc - vlist[origin]loc); aang[n] := 360; for nn = 1 upto n: if ang < aang[nn]: for nnn = n - 1 downto nn: aang[nnn+1] := aang[nnn]; aidx[nnn+1] := aidx[nnn]; endfor aang[nn] := ang; aidx[nn] := n; fi exitif known aidx[n]; endfor fi endfor aidx[n+1] := aidx[1]; aang[n+1] := aang[1] + 360; for nn = 1 upto n: agap[nn] = aang[nn+1] - aang[nn]; endfor if known vlist[origin]arc[index]lsr: ngap := n; for nn = 1 upto n: if (aang[nn] < vlist[origin]arc[index]lsr) and (vlist[origin]arc[index]lsr < aang[nn+1]): ngap := nn; fi endfor else: bgap := 0; for nn = 1 upto n: if agap[nn] > bgap: bgap := agap[nn]; ngap := nn; fi endfor fi if vtracing: adump (n + 1); fi vlist[origin]loc{dir(aang[ngap]+agap[ngap]/4)} ... vlist[origin]loc + 2/3 * distsum/n / vlist[origin]arc[index]tns * dir(aang[ngap]+agap[ngap]/2) ... {-dir(aang[ngap+1]-agap[ngap]/4)}vlist[origin]loc enddef; vardef adump expr n = save i; for i = 1 upto n: message "aidx[" & decimal_ (i) & "]=" & decimal_ (aidx[i]) & ", aang[" & decimal_ (i) & "]=" & decimal_ (aang[i]) & ", agap[" & decimal_ (i) & "]=" & decimal_ (agap[i]); endfor enddef; vardef vdraw_arc (expr sty, wd, arc) (suffix lbl) = if known wd: save currentpen; pen currentpen; pickup pencircle scaled wd; fi scantokens ("draw_" & sty) (arc); vdraw_arc_label (arc, lbl); enddef; let plain_draw = draw; vardef vdraw_arc_rubout (expr rub, sty, wd, arc) (suffix lbl) = if known rub: begingroup def draw expr p = save oldpen; pen oldpen; oldpen := currentpen; save currentpen; pen currentpen; pickup oldpen scaled rub; erase plain_draw (subpath (.1,.9)*length(p) of p) enddef; vdraw_arc (sty, wd, arc, lbl); let draw = plain_draw; endgroup; fi vdraw_arc (sty, wd, arc, lbl); enddef; vardef vbuild_polygon suffix p = if known p.pull: save c; pair c; c := pcenter p; for i = 1 upto (p.cnt - 1): vbuild_polygon_section (p, i, i+1) endfor vbuild_polygon_section (p, p.cnt, 1) else: for i = 1 upto p.cnt: vlist[p.vtx[i]]loc if known p.cona: scantokens (p.cona) else: -- fi endfor fi cycle enddef; def vbuild_polygon_section (suffix p) (expr from, to) = vlist[p.vtx[from]]loc if known p.cona: scantokens (p.cona) else: -- fi p.pull[c,.5[vlist[p.vtx[from]]loc,vlist[p.vtx[to]]loc]] if known p.conb: scantokens (p.conb) else: -- fi enddef; vardef pcenter suffix p = (origin for i = 1 upto p.cnt: + vlist[p.vtx[i]]loc endfor) / p.cnt enddef; vardef vdraw_arc_label (expr arc) (suffix lbl) = if lbl <> "": save _a, _z, _zz, _r; numeric _a; pair _z, _zz, _r; _z := point .5 length (arc) of arc; if lbl.dist = 0: LaTeX_text (_z, whatever, lbl); else: _r := direction .5 length (arc) of arc rotated - 90; if lbl.side = "left": _a := angle (-_r); elseif lbl.side = "right": _a := angle (_r); else: _zz = _z - .5[point 0 of arc, point infinity of arc]; if ((_zz if length (_zz) > 0: / length (_zz) fi) dotprod _r) >= 0: _a := angle (_r); else: _a := angle (-_r); fi fi LaTeX_text (_z + lbl.dist * dir _a, _a, lbl); fi fi enddef; vardef vdraw_label (expr loc) (suffix lbl) = if lbl <> "": save a; numeric a; if lbl.dist = 0: LaTeX_text (loc, whatever, lbl); else: if unknown lbl.ang: if loc = (.5w,.5h): a := 0; else: a := angle (loc - (.5w,.5h)); fi else: a := lbl.ang; fi LaTeX_text (loc + lbl.dist * dir a, a, lbl); fi fi enddef; vardef vdraw_vertex suffix v = if known v.decor.shape: if known v.fore: save foreground; color foreground; foreground = v.fore; fi if known v.back: save background; color background; background = v.back; fi if known v.decor.sty: if v.decor.sty = "empty": emptydraw ( elseif v.decor.sty = "full": cfilldraw ( elseif is_a_number v.decor.sty: drawhalftone (1 - scantokens v.decor.sty / 100, else: drawtile (scantokens v.decor.sty, fi else: cfilldraw ( fi v.decor.shape if known v.decor.ang: rotated v.decor.ang fi scaled v.decor.size shifted v.loc); fi enddef; vardef polygon expr n = if n > 2: for i = 1 upto n: (.5up rotated (360i/n)) -- endfor cycle else: fullcircle fi enddef; vardef polygram expr n = if n > 2: for i = 1 upto n: (.5up rotated (360i/n)) -- (.2up rotated (360(i+.5)/n)) -- endfor cycle else: fullcircle fi enddef; vardef polycross expr n = save i; for i = 1 upto n: origin -- .5 dir (360(i-.5)/n) -- endfor cycle enddef; vardef vdraw_polygon suffix p = if known p.fore: save foreground; color foreground; foreground = p.fore; fi if known p.back: save background; color background; background = p.back; fi if known p.sty: if p.sty = "phantom": elseif p.sty = "empty": emptydraw (vbuild_polygon p); elseif p.sty = "full": cfilldraw (vbuild_polygon p); elseif is_a_number p.sty: drawhalftone (1 - scantokens p.sty / 100, vbuild_polygon p); else: drawtile (scantokens p.sty, vbuild_polygon p); fi else: cdraw (vbuild_polygon p); fi enddef; vardef LaTeX expr text = if LaTeX_file = "": LaTeX_file := jobname & ".t" & decimal charcode; write ("% " & LaTeX_file & " -- generated from " & jobname & ".mp") to LaTeX_file; fi write (text & "%") to LaTeX_file enddef; vardef LaTeX_text (expr z, a, txt) = LaTeX "\fmfL(" & (decimal (xpart z/LaTeX_unitlength)) & "," & (decimal (ypart z/LaTeX_unitlength)) & "," & (voctant a) & "){" & txt & "}"; enddef; vardef voctant expr a = if known a: voctant_list[floor (a/45 + .5)] else: "c" fi enddef; string voctant_list[]; voctant_list[-4] := "r"; voctant_list[-3] := "rt"; voctant_list[-2] := "t"; voctant_list[-1] := "lt"; voctant_list[0] := "l"; voctant_list[1] := "lb"; voctant_list[2] := "b"; voctant_list[3] := "rb"; voctant_list[4] := "r"; vardef vdump = message ">>>>> Vertices and arcs for diagram #" & decimal charcode & " of " & jobname & ".mf:"; for i = vertices: message "> " & vlist[i]name & "=" & decimal_pair (vlist[i]loc) & ": #lines=" & decimal (vlist[i]arc.last - vlist[i]arc.first + 1) if vlist[i]lbl <> "": & ", lbl=" & vlist[i]lbl & ", l.angle=" & decimal_ (vlist[i]lbl.ang) & ", l.dist=" & decimal_ (vlist[i]lbl.dist) fi & "."; endfor for i = vertices: for j = varcs (i): if known vlist[i]arc[j]sty: message "> " & vlist[i]name & "*" & vlist[vlist[i]arc[j]]name & ": " & vlist[i]arc[j]sty & ", tns=" & decimal_ (vlist[i]arc[j]tns) & ", lsr=" & decimal_ (vlist[i]arc[j]lsr) & ", wd=" & decimal_ (vlist[i]arc[j]wd) & ", rub=" & decimal_ (vlist[i]arc[j]rub) if vlist[i]arc[j]lbl <> "": & ", lbl=" & vlist[i]arc[j]lbl & ", l.side=" & vlist[i]arc[j]lbl.side & ", l.dist=" & decimal_ (vlist[i]arc[j]lbl.dist) fi & "."; fi endfor for j = vconstr (i): if i < vlist[i]constr[j]: save z; pair z; z = vlist[vlist[i]constr[j]]loc - vlist[i]loc; message "> " & vlist[i]name & "&" & vlist[vlist[i]constr[j]]name & ": " & decimal_pair (z); fi endfor; endfor enddef; vardef decimal_ (text n) = if known n: decimal n else: "?" fi enddef; vardef decimal_pair (text z) = "(" & decimal_ (xpart z) & "," & decimal_ (ypart z) & ")" enddef; def show_diagram_ expr frame = if (screen_cols < w + 2 xpart frame) or (screen_rows < h + 2 ypart frame): screen_cols := w + 2 xpart frame; screen_rows := h + 2 ypart frame; openwindow currentwindow from origin to (screen_rows, screen_cols) at (- xpart frame, h + ypart frame); fi showit_; if showstopping > 0: stop "This is diagram #" & decimal charcode & ". Hit return to continue..."; fi enddef; def show_diagram = def show_diagram = display blankpicture inwindow currentwindow; show_diagram_ enddef; show_diagram_ enddef; def show_all_diagrams expr frame = def showit = show_diagram frame enddef; displaying:=1; enddef; endinput; \endinput %% %% End of file `feynmp.mp'.