From a4e07f30e880ab27c2918f81f136e257475b7729 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Thu, 15 Mar 2018 16:04:31 +0100 Subject: 2018-03-15 15:36:00 --- metapost/context/base/mpiv/mp-node.mpiv | 220 ++++++++++++++++++++++---------- 1 file changed, 151 insertions(+), 69 deletions(-) (limited to 'metapost/context/base/mpiv/mp-node.mpiv') diff --git a/metapost/context/base/mpiv/mp-node.mpiv b/metapost/context/base/mpiv/mp-node.mpiv index fdd308ad1..79391220b 100644 --- a/metapost/context/base/mpiv/mp-node.mpiv +++ b/metapost/context/base/mpiv/mp-node.mpiv @@ -11,76 +11,137 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D Ths crossing macros were written as part of this module but as they +%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 ; -% returns a pair suffix if the path is unknown +% Build a path from the node positions. +% Must be integer and continuous in index starting at 0. -vardef makenode@#(suffix p)(text t) = - save i, b ; numeric i ; string b ; - for a = t : - if unknown i : % first argument is the index - i = a ; - if isarray p : - % - % note that one needs to declare "path p[] ; picture p[]pic[] ;" - % before calling node() if one is to use a pseudo-array for p - % because "picture p1.pic[] ;" is not a valid syntax! - % - % The following works, but is a bit awkward... - % - b := prefix p ; - if not picture p.pic[i] : scantokens("picture " & b & "[]pic[] ;") ; fi - if not pair p.pos[i] : scantokens("pair " & b & "[]pos[] ;") ; fi +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 : - if not picture p.pic[i] : picture p.pic[] ; fi - if not pair p.pos[i] : pair p.pos[] ; fi + path p ; fi + fi + save i ; i = -1 ; + p = forever : exitif unknown p.pos[incr i] ; + p.pos[i] -- + endfor cycle ; + fi +enddef ; + +% can take a list: +def clearpath text t = + save t ; path t ; +enddef ; + +def clearnodepath = clearpath nodepath enddef ; + +clearnodepath ; + +% the trailing "," below handles when number of t<3 + +vardef makenode@#(text t) = + for a = t : + if (path a) or (unknown a) : + mfun_makenode@#(t,) else : - if known p.pic[i] : - addto p.pic[i] also - else : - p.pic[i] := - fi + mfun_makenode@#(nodepath, t,) + fi + exitif true ; + endfor +enddef ; + +vardef node@#(text t) = + for a = t : + if (path a) or (unknown a) : + mfun_node@#(t,) + else : + mfun_node@#(nodepath, t,) + fi + exitif true ; + endfor +enddef ; + +vardef nodeboundingpoint@#(text t) = + for a = t : + if (path a) or (unknown a) : + mfun_nodeboundingpoint@#(t) + else : + mfun_nodeboundingpoint@#(nodepath,a) + 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 mfun_makenode@#(suffix p)(expr i)(text t) = + save d, b ; string b ; + 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 + for a = t : + 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 string a : if (length(a) > 0) : textext@#(a) else : nullpicture fi elseif numeric a : textext@#(decimal a) - elseif ((boolean a) and a) : image(draw origin) + 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: gobble the function return. +vardef mfun_node@#(suffix p)(expr i)(text t) = + if pair mfun_makenode@#(p,i,t) : + % nop: enclose in "if ... fi" to gobble the function return. + fi + if (unknown p) and (known p.pos[i]) : + makenodepath(p) ; + fi + if known p.pic[i] : + p.pic[i] if known p : shifted point i of p fi + else : + nullpicture fi - 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 ; +newinternal node_loopback_yscale ; node_loopback_yscale := 1 ; + % returns a path -vardef fromto@#(expr d)(suffix p)(expr f)(suffix q)(text s) = +vardef fromtopaths@#(expr d)(suffix p)(expr f)(suffix q)(text s) = save r, t, l ; - path r[] ; numeric t ; picture l ; + path r[] ; picture l ; for a = s : if unknown t : t = a ; @@ -97,15 +158,24 @@ vardef fromto@#(expr d)(suffix p)(expr f)(suffix q)(text s) = else : point f of p -- point t of q fi ; - save deviation ; numeric deviation ; + save 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 + r1 = if (point 0 of r0) = (point length r0 of r0) : + (fullcircle yscaled node_loopback_yscale rotated 180 + if mfun_laboff@# <> origin : + rotated angle mfun_laboff@# + shifted .5mfun_laboff@# + fi) + scaled deviation + shifted point 0 of r0 + elseif 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 : @@ -113,12 +183,12 @@ vardef fromto@#(expr d)(suffix p)(expr f)(suffix q)(text s) = 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 ; + if picture a : a + elseif string a : if (length(a) > 0) : textext@#(a) else : nullpicture fi + 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 @@ -140,7 +210,7 @@ enddef ; % returns pair: bounding point of the node picture -vardef nodeboundingpoint@#(suffix p)(expr i) = +vardef mfun_nodeboundingpoint@#(suffix p)(expr i) = if known p.pic[i] : boundingpoint@#(p.pic[i]) else : @@ -157,7 +227,7 @@ enddef ; % returns pair: vector between nodes (+ optional scale) vardef betweennodes@#(suffix p)(expr f)(suffix q)(text s) = - save t ; numeric t ; + save t ; for a = s : if unknown t : t = a ; @@ -168,15 +238,27 @@ vardef betweennodes@#(suffix p)(expr f)(suffix q)(text s) = endfor enddef ; -% build a path from the node positions. -% Must be continuous in index starting at 0. +% helpers that save passing tokens -vardef makenodepath(suffix p) = - if unknown p : - save i ; i = -1 ; - p = forever : exitif unknown p.pos[incr i] ; - p.pos[i] -- - endfor cycle ; - fi +def mfun_node_init(expr dx, dy, da) = + save nodelattice ; pair nodelattice[] ; + nodelattice0 = (dx,0) ; + nodelattice1 = dy * dir(da) ; + clearnodepath ; + save nodecount ; nodecount = -1; +enddef ; + +def mfun_node_make(expr x, y, s) = + nodecount := nodecount + 1 ; + makenode(nodecount,s) = x * nodelattice0 + y * nodelattice1 ; enddef ; +def mfun_node_flush = + for i=0 upto nodecount: + draw node(i) ; + endfor +enddef ; + +vardef mfun_nodes_fromto@#(expr d, f)(text t) = + fromtopaths@#(d,nodepath,f,nodepath,t) +enddef ; -- cgit v1.2.3