summaryrefslogtreecommitdiff
path: root/metapost/context/base/mpiv/mp-node.mpiv
diff options
context:
space:
mode:
Diffstat (limited to 'metapost/context/base/mpiv/mp-node.mpiv')
-rw-r--r--metapost/context/base/mpiv/mp-node.mpiv220
1 files changed, 151 insertions, 69 deletions
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 ;