Metapost intersectiontimes

In the code below intersectiontimes is not giving an intersection point of the two paths. Could anyone provide some guidance on how to find (and mark) the intersection points of the curves below? (I'm a metapost noob, so if you wanted to throw in any other advice, then that would be appreciated as well!)

\documentclass{article}
\usepackage{luamplib}
\begin{document}

\begin{mplibcode}

gu:=1cm;
vardef j(expr t) = 2*t*t*gu enddef;
vardef g(expr t) = t*t*t*t*gu-2*t*t*gu enddef;

vardef Function(suffix f)(expr ti,tf,n) =
save fpas;
fpas := (tf-ti)/n;
(ti*gu,f(ti)) for i=1 upto n: ..(ti*gu+i*fpas*gu,f(ti+i*fpas)) endfor
enddef;

def mybox(expr l,r,t,b) =
clip currentpicture to
( (l*gu,b*gu)--(r*gu,b*gu)--(r*gu,t*gu)--(l*gu,t*gu)--cycle)
enddef;

beginfig(1);
a = -4;
b = 4;

path p;
p = Function(j,a,b,200);

path q;
q = Function(g,a,b,200);

draw p
yscaled .15
xscaled .7
withpen pencircle scaled .5;

draw q
yscaled .15
xscaled .7
withpen pencircle scaled .5;

fill buildcycle(reverse(q),p) xscaled .7 yscaled .15 withcolor .7red;

drawdblarrow ((-2,0)*gu--(2,0)*gu);
drawdblarrow ((0,-1)*gu--(0,3)*gu) xscaled .7 yscaled .8;

z1 = (p yscaled .15 xscaled .7) intersectiontimes (q yscaled .15 xscaled .7);
dotlabel.lft("x",z1);

mybox(-2,2,-1,2.5);

endfig;
end

\end{mplibcode}

\end{document}

-
Don't you want intersectionpoint? –  egreg Jan 28 '13 at 21:42
I have no idea what I want! –  Scott H. Jan 28 '13 at 23:02

You need intersectionpoint; if I change the line

z1 = (p yscaled .15 xscaled .7) intersectiontimes (q yscaled .15 xscaled .7);


into

z1 = (p yscaled .15 xscaled .7) intersectionpoint (q yscaled .15 xscaled .7);


I get

The primitive intersectiontimes returns a pair, but its components are two "times": (t1,t2), where t1 and t2 are the times when the two paths intersect; so it's not intended for use as a point. Instead, intersectionpoint returns the coordinates of the same intersection point.

The rules about the intersections are laid out in section 9.2 of the Metapost manual and in chapter 5 of the METAFONTbook. In this case you can find the intersection at zero with

p' = p yscaled .15 xscaled .7; % a couple of shortcuts
q' = q yscaled .15 xscaled .7;

z1 = p' intersectionpoint q'; % find the first intersection
dotlabel.lft("x",z1);

pair meet;
meet = p' intersectiontimes q';
p' := subpath (eps+xpart meet,infinity) of p'; % cut the paths
q' := subpath (eps+ypart meet,infinity) of q';

z2 = p' intersectionpoint q'; % find the second intersection
dotlabel.bot("y",z2);

z3 = (reverse p') intersectionpoint (reverse q'); % find the third intersection
dotlabel.lft("z",z3);


The trick of going a bit further with the time that finds (0,0) doesn't work for finding the third point, because it's a minimum on one curve and a maximum on the other. But reversing the path works. However, it would be simpler to find the symmetric point of z1, of course.

-
Aha! That was silly of me, thanks egreg :) A quick question about the intersection at 0...in general, would it find that intersection if my increment (or position of the touching point) was such that when building the path, neither function contained the point (0,f(0))? –  Scott H. Jan 28 '13 at 23:11
Look at section 9.2 of the manual; what among the various intersection points will be chosen is not readily predictable. You have to cut the paths to find the other points (and you can do it with intersectiontimes). –  egreg Jan 28 '13 at 23:15
Sorry, I think that was another silly question. In essence, I was wondering whether metapost is finding the intersections of the approximating paths, or whether it could infer that the functions intersect even if the approximating paths may not (depending on how fine an increment is chosen to build them). Thus, if the graphs of the functions simply touch one another (and do not cross), then depending on how many points are used to build the approximating paths, metapost might not find that intersection point. It seems now like that must be the case, is that correct? –  Scott H. Jan 28 '13 at 23:33
@ScottH. It finds the origin as intersection, as the code I added shows. However, for tangent paths it might not find it, because it works only with discrete increments. At least, this is what I believe: the program is surprising, at times. :) –  egreg Jan 28 '13 at 23:36
Thanks for the info and the edit! –  Scott H. Jan 28 '13 at 23:37