summaryrefslogtreecommitdiff
path: root/metapost
diff options
context:
space:
mode:
Diffstat (limited to 'metapost')
-rw-r--r--metapost/context/base/mpiv/mp-node.mpiv66
-rw-r--r--metapost/context/base/mpiv/mp-tool.mpiv56
2 files changed, 92 insertions, 30 deletions
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