# [metapost] Re: all intersections between two paths

Boguslaw Jackowski bop at bop.com.pl
Sun Jan 16 19:12:28 CET 2005

LarryS> PS.  Who can offer MF substitutes for the MP functions 'ulcorner'
LarryS> and 'lrcorner' that I use for 'autosizing'.

LaurenceF> How about (0, h) and (w, -d)?

I understand that the argument to the macro that Larry needs should be
a curve (or a set of curves), not a glyph with a complete metric.

Below there is the definition of the `find_BB' procedure that finds lower
left and upper right coordinates (xl_crd, yl_crd, xh_crd, and yh_crd,
respectively) for a given set of curves.

A sample usage:

p:=unitsquare shifted (-1/2, -1/2) rotated 45;
find_BB p; show (xl_crd,yl_crd), (xh_crd,yh_crd);

Cheers -- Jacko

Ps. I believe that I talked about the problem of the finding
of the bounding box of a curve using MF during the EuroTeX/TUG
meeting in 1994 (Sobieszewo, Poland).

% --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
% |xl|, |yl|, |xh|, and |yh| can likely be used in a program, hence
% longer names: |xl_crd|, |yl_crd|, |xh_crd|, and |yh_crd|, respectively
def find_BB text t =
for CC_:=t: % |t| may be empty
if unknown xl_crd: xl_crd=yl_crd=-xh_crd=-yh_crd=infinity; fi
update_BC(CC_)(xl_crd,yl_crd,xh_crd,yh_crd);
endfor
enddef;
% ---
vardef update_BC(expr C)(suffix xl,yl,xh,yh) =
% updates variables |xl|, |yl|, |xh|, |yh| by finding extremal points
% of a B\'ezier curve |C|
if xl>xpart(point 0 of C): xl:=xpart(point 0 of C); fi
if xh<xpart(point 0 of C): xh:=xpart(point 0 of C); fi
if yl>ypart(point 0 of C): yl:=ypart(point 0 of C); fi
if yh<ypart(point 0 of C): yh:=ypart(point 0 of C); fi
for tt_:=0 upto length(C)-1:
update_BB(subpath (tt_,tt_+1) of C,xl,yl,xh,yh);
endfor
enddef;
% ---
vardef update_BB(expr B) (suffix xl,yl,xh,yh) =
% updates variables |xl|, |yl|, |xh|, |yh| by finding extremal points
% of a B\'ezier segment |B|; the |point 0 of B| is not taken into account
save Bx_,By_,ta_,tb_,vv_; path Bx_, By_; numeric ta_,tb_,vv_;
%
Bx_=(0,xpart(point 0 of B))
..controls
(0,xpart(postcontrol 0 of B)) and (1000,xpart(precontrol 1 of B))
..(1000,xpart(point 1 of B));
By_=(0,ypart(point 0 of B))
..controls
(0,ypart(postcontrol 0 of B)) and (1000,ypart(precontrol 1 of B))
..(1000,ypart(point 1 of B));
%
ta_:=directiontime right of Bx_;
if ta_>0:
vv_:=ypart (point ta_ of Bx_);
if vv_<xl: xl:=vv_; fi\\ if vv_>xh: xh:=vv_; fi
tb_:=directiontime right of subpath (ta_+eps,1) of Bx_;
if tb_>=0:
vv_:=ypart (point tb_ of (subpath (ta_+eps,1) of Bx_));
if vv_<xl: xl:=vv_; fi\\ if vv_>xh: xh:=vv_; fi
fi
fi
vv_:=ypart (point 1 of Bx_); if vv_<xl: xl:=vv_; fi\\ if vv_>xh: xh:=vv_; fi
%
ta_:=directiontime right of By_;
if ta_>0:
vv_:=ypart (point ta_ of By_);
if vv_<yl: yl:=vv_; fi\\ if vv_>yh: yh:=vv_; fi
tb_:=directiontime right of subpath (ta_+eps,1) of By_;
if tb_>=0:
vv_:=ypart (point tb_ of (subpath (ta_+eps,1) of By_));
if vv_<yl: yl:=vv_; fi\\ if vv_>yh: yh:=vv_; fi
fi
fi
vv_:=ypart (point 1 of By_); if vv_<yl: yl:=vv_; fi\\ if vv_>yh: yh:=vv_; fi
enddef;
% ---
def reset_BB =
xl_crd:=whatever; yl_crd:=whatever; xh_crd:=whatever; yh_crd:=whatever;
enddef;
% --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---

--
BOP s. c.
ul. Bora-Komorowskiego 24, 80-377 Gdansk, Poland
tel. (+48 58) 553 46 59,  fax (+48 58) 511 03 81
bop at bop.com.pl, http://www.bop.com.pl