%D \module %D [ file=mp-node.mpiv, %D version=1998.02.15, %D title=\CONTEXT\ \METAPOST\ graphics, %D subtitle=Node Based Graphics, %D author=Alan Braslau, %D date=\currentdate, %D copyright={Alan Braslau & \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. %D The crossing macros were written as part of this module but as they %D can be of use elsewhere they are defined in mp-tool. if known context_node : endinput ; fi ; boolean context_node ; context_node := true ; % Build a path from the node positions. % Must be integer and continuous in index starting at 0. vardef makenodepath(suffix p) = if unknown p : if not path p : d := dimension p ; if d>0 : scantokens("path " & prefix p & for i=1 upto d : "[]" & endfor " ;") ; else : path p ; fi fi save i ; i = -1 ; p = forever : exitif unknown p.pos[incr i] ; p.pos[i] -- endfor cycle ; fi enddef ; def clearnodepath suffix p = save p ; path p ; enddef ; clearnodepath nodepath ; vardef makenode@#(text t) = for a = t : if (known a) and (numeric a) : _makenode(nodepath, t) else : _makenode(t) fi exitif true ; endfor enddef ; vardef node@#(text t) = for a = t : if (known a) and (numeric a) : _node(nodepath, t) else : _node(t) fi exitif true ; endfor enddef ; vardef nodeboundingpoint@#(text t) = for a = t : if (known a) and (numeric a) : _nodeboundingpoint@#(nodepath,a) else : _nodeboundingpoint@#(t) fi exitif true ; endfor enddef ; vardef fromto@#(expr d,f)(text t) = fromtopaths(d,nodepath,f,nodepath,t) enddef ; % returns a pair suffix if the path is unknown vardef _makenode@#(suffix p)(text t) = save i, d, b ; numeric i, d ; string b ; for a = t : if unknown i : % first argument is the index i = a ; d = dimension p ; if d > 0 : b := prefix p ; if not picture p.pic[i] : scantokens("picture " & b & for j=1 upto d : "[]" & endfor "pic[] ;") ; fi if not pair p.pos[i] : scantokens("pair " & b & for j=1 upto d : "[]" & endfor "pos[] ;") ; fi else : if not picture p.pic[i] : picture p.pic[] ; fi if not pair p.pos[i] : pair p.pos[] ; fi fi else : if known p.pic[i] : addto p.pic[i] also else : p.pic[i] = fi if picture a : a elseif string a : textext@#(a) elseif numeric a : textext@#(decimal a) elseif ((boolean a) and a) : image(draw origin withpen currentpen scaled 4) else : nullpicture fi ; fi endfor p.pos[i] if known p : := point i of p ; fi enddef ; % returns a picture vardef _node@#(suffix p)(text t) = if pair _makenode@#(p,t) : % nop: enclose in "if ... fi" to gobble the function return. fi % now pick-off only the index: for a = t : if (unknown p) and (known p.pos[a]) : makenodepath(p) ; fi if known p.pic[a] : p.pic[a] if known p : shifted point a of p fi else : nullpicture fi exitif true ; endfor enddef ; % returns a path vardef fromtopaths@#(expr d)(suffix p)(expr f)(suffix q)(text s) = save r, t, l ; path r[] ; numeric t ; picture l ; for a = s : if unknown t : t = a ; if (unknown p) and (known p.pos[f]) : makenodepath(p) ; fi if (unknown q) and (known q.pos[t]) : makenodepath(q) ; fi r0 = if ((not numeric d) and (point f of p = point f of q) and (point t of p = point t of q)) : subpath (f,t) of p else : point f of p -- point t of q fi ; save deviation ; numeric deviation ; deviation := if numeric d: d else: 0 fi ; r1 = if deviation=0 : r0 else : point 0 of r0 .. unitvector direction .5length r0 of r0 rotated 90 scaled deviation * arclength r0 shifted point .5length r0 of r0 .. point length r0 of r0 fi ; else : if known l : addto l also else : l := fi if picture a : a elseif string a : textext@#(a) elseif numeric a : textext@#(decimal a) elseif ((boolean a) and a) : image(draw origin withpen currentpen scaled 4) else : nullpicture fi ; fi endfor r2 = r1 if known p.pic[f if cycle p: mod length p fi] : cutbefore boundingbox (p.pic[f if cycle p: mod length p fi] shifted point f of p) fi if known q.pic[t if cycle q: mod length q fi] : cutafter boundingbox (q.pic[t if cycle q: mod length q fi] shifted point t of q) fi ; if known l : l := l shifted point .5length r2 of r2 ; draw l ; (r2 if str @# = "" : crossingunder l fi) else : r2 fi enddef ; % returns pair: bounding point of the node picture vardef _nodeboundingpoint@#(suffix p)(expr i) = if known p.pic[i] : boundingpoint@#(p.pic[i]) else : origin fi enddef ; % returns pair: scaled laboff direction vardef relative@#(expr s) = (mfun_laboff@# scaled s) enddef ; % returns pair: vector between nodes (+ optional scale) vardef betweennodes@#(suffix p)(expr f)(suffix q)(text s) = save t ; numeric t ; for a = s : if unknown t : t = a ; nodeboundingpoint@#(q,t) + nodeboundingpoint@#(p,f) else : + relative@#(a) fi endfor enddef ;