From e677a7fb12047017595fb29e212463dcb1cb2fa6 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Fri, 2 Dec 2016 10:51:35 +0100 Subject: 2016-12-02 10:19:00 --- metapost/context/base/mpiv/mp-node.mpiv | 66 +++++++++++++++++++++++++++++++-- metapost/context/base/mpiv/mp-tool.mpiv | 56 +++++++++++++++------------- 2 files changed, 92 insertions(+), 30 deletions(-) (limited to 'metapost') diff --git a/metapost/context/base/mpiv/mp-node.mpiv b/metapost/context/base/mpiv/mp-node.mpiv index e511ca20c..c7b0bcabe 100644 --- a/metapost/context/base/mpiv/mp-node.mpiv +++ b/metapost/context/base/mpiv/mp-node.mpiv @@ -18,14 +18,15 @@ if known context_node : endinput ; fi ; boolean context_node ; context_node := true ; -% returns a picture +% returns a pair suffix if the path is unknown vardef makenode@#(suffix p)(text t) = save i ; numeric i ; for a = t : - if not known i : % first argument is the index + if unknown i : % first argument is the index i = a ; if not picture p.pic[i] : picture p.pic[] ; fi + if not pair p.pos[i] : pair p.pos[] ; fi % % note that one needs to declare "path p[] ; picture p[]pic[] ;" % before calling node() if one is to use a pseudo-array for p @@ -45,11 +46,19 @@ vardef makenode@#(suffix p)(text t) = fi ; fi endfor + p.pos[i] if known p : := point i of p ; fi enddef ; +% returns a picture + vardef node@#(suffix p)(text t) = - makenode@#(p)(t) ; + if pair makenode@#(p)(t) : + % nop: gobble the function return. + 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 : @@ -65,8 +74,14 @@ vardef fromto@#(expr d)(suffix p)(expr f)(suffix q)(text s) = save r, t, l ; path r[] ; numeric t ; picture l ; for a = s : - if not known t : + 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)) : @@ -114,3 +129,46 @@ vardef fromto@#(expr d)(suffix p)(expr f)(suffix q)(text s) = 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 ; + +% build a path from the node positions. +% Must be continuous in index starting at 0. + +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 +enddef ; + diff --git a/metapost/context/base/mpiv/mp-tool.mpiv b/metapost/context/base/mpiv/mp-tool.mpiv index 68bc0a9c7..809384ef7 100644 --- a/metapost/context/base/mpiv/mp-tool.mpiv +++ b/metapost/context/base/mpiv/mp-tool.mpiv @@ -871,7 +871,7 @@ secondarydef p intersection_point q = begingroup save x_, y_ ; (x_,y_) = p intersectiontimes q ; - if x_<0 : + if x_ < 0 : intersection_found := false ; center p % origin else : @@ -3262,25 +3262,21 @@ primarydef p crossingunder q = fi endfor elseif path p : - save n, m, t, a, b, c, r, h ; + save n, m, t, a, b, c, r, bcuttings, hold ; numeric n, m, t[] ; - path a, b, c, r, hold[] ; + path a, b, c, r, bcuttings, hold[] ; c := makepath(currentpen scaled crossingscale) ; r := if picture q : boundingbox fi q ; t[0] := n := m := 0 ; a := p ; -save last ; numeric last ; last := infinity ; - forever : % find all intersections + % The cutbefore/cutafter using c below prevents endless loops! + %forever : % find all intersections + for i=1 upto 100 : % limit the number, until we can make this robust clearxy ; z = a intersectiontimes r ; -exitif x = last ; % prevent loop -last := x ; -% maybe we need a threshold for x ; -% message(decimal x & "+" & decimal m) ; - if (x < 0) and (m > 0) : + if x < 0 : + exitif m < 1 ; a := hold[m] ; m := m - 1 ; clearxy ; z = a intersectiontimes r ; - else : - exitif x < 0 ; fi (t[incr n], whatever) = p intersectiontimes point x of a ; if x = 0 : @@ -3288,18 +3284,26 @@ last := x ; elseif x = length a : a := a cutafter c shifted point x of a ; else : % before or after? - b := subpath (0,x) of a cutafter c shifted point x of a ; + b := subpath (0,x) of a cutafter c shifted point x of a ; + bcuttings := cuttings ; a := subpath (x,length a) of a cutbefore c shifted point x of a ; clearxy ; z = a intersectiontimes r ; if x < 0 : a := b ; + cuttings := bcuttings ; else : - clearxy ; z = b intersectiontimes r ; - if x >= 0 : - hold[incr m] := b ; + if length bcuttings > 0 : + clearxy ; z = b intersectiontimes r ; + if x >= 0 : + hold[incr m] := b ; + fi fi fi fi + if length cuttings = 0 : + exitif m < 1 ; + a := hold[m] ; m := m - 1 ; + fi endfor if n = 0 : % No crossings, we return the PATH @@ -3316,6 +3320,16 @@ last := x ; for i=if cycle p: 2 else: 1 fi upto n : % skip the first segment if cyclic % as it gets repeated (fully) at the end. + if crossingoption > 0 : + if crossingoption = 1 : + addto pic doublepath c shifted point t[i] of p + withpen currentpen withtransparency(1,.5) ; + elseif crossingoption = 2 : + addto pic also + infotext (incr m,crossingscale/5) + shifted point t[i] of p ; + fi + fi a := subpath (t[i-1],t[i]) of p if i > 1 : cutbefore (c shifted point t[i-1] of p) @@ -3324,16 +3338,6 @@ last := x ; cutafter (c shifted point t[i] of p) fi ; if (not picture q) or (a outsideof q) : - if crossingoption > 0 : - addto pic also infotext ( - if crossingoption = 1 : - incr(m) - elseif crossingoption = 2 : - i if cycle p: -1 fi - fi - ,crossingscale/5) - shifted point t[i] of p ; ; - fi ; addto pic doublepath a withpen currentpen ; fi endfor -- cgit v1.2.3