void fillbox(frame dest, path g, pen p=currentpen, filltype filltype=NoFill, bool above=true)
{
if(above == false) {
frame F;
filltype.fill(F,g,p);
prepend(dest,F);
} else filltype.fill(dest,g,p);
}
// Draw and/or fill a box on frame dest using the dimensions of frame src.
path box(frame dest, frame src=dest, real xmargin=0, real ymargin=xmargin,
pen p=currentpen, filltype filltype=NoFill, bool above=true)
{
pair z=(xmargin,ymargin);
int sign=filltype == NoFill ? 1 : -1;
pair h=0.5*sign*(max(p)-min(p));
path g=box(min(src)-h-z,max(src)+h+z);
fillbox(dest,g,p,filltype,above);
return g;
}
path roundbox(frame dest, frame src=dest, real xmargin=0, real ymargin=xmargin,
pen p=currentpen, filltype filltype=NoFill, bool above=true)
{
pair m=min(src);
pair M=max(src);
pair bound=M-m;
real a=bound.x+2*xmargin;
real b=bound.y+2*ymargin;
real ds=0;
real dw=min(a,b)*0.3;
path g=shift(m-(xmargin,ymargin))*((0,dw)--(0,b-dw){up}..{right}
(dw,b)--(a-dw,b){right}..{down}
(a,b-dw)--(a,dw){down}..{left}
(a-dw,0)--(dw,0){left}..{up}cycle);
fillbox(dest,g,p,filltype,above);
return g;
}
path ellipse(frame dest, frame src=dest, real xmargin=0, real ymargin=xmargin,
pen p=currentpen, filltype filltype=NoFill, bool above=true)
{
pair m=min(src);
pair M=max(src);
pair D=M-m;
static real factor=0.5*sqrt(2);
int sign=filltype == NoFill ? 1 : -1;
pair h=0.5*sign*(max(p)-min(p));
path g=ellipse(0.5*(M+m),factor*D.x+h.x+xmargin,factor*D.y+h.y+ymargin);
fillbox(dest,g,p,filltype,above);
return g;
}
path box(frame f, Label L, real xmargin=0, real ymargin=xmargin,
pen p=currentpen, filltype filltype=NoFill, bool above=true)
{
add(f,L);
return box(f,xmargin,ymargin,p,filltype,above);
}
path roundbox(frame f, Label L, real xmargin=0, real ymargin=xmargin,
pen p=currentpen, filltype filltype=NoFill, bool above=true)
{
add(f,L);
return roundbox(f,xmargin,ymargin,p,filltype,above);
}
path ellipse(frame f, Label L, real xmargin=0, real ymargin=xmargin,
pen p=currentpen, filltype filltype=NoFill, bool above=true)
{
add(f,L);
return ellipse(f,xmargin,ymargin,p,filltype,above);
}
using envelope=path(frame dest, frame src=dest, real xmargin=0,
real ymargin=xmargin, pen p=currentpen,
filltype filltype=NoFill, bool above=true);
object object(Label L, envelope e, real xmargin=0, real ymargin=xmargin,
pen p=currentpen, filltype filltype=NoFill, bool above=true)
{
object F;
F.L=L.copy();
Label L0=L.copy();
L0.position(0);
L0.p(p);
add(F.f,L0);
F.g=e(F.f,xmargin,ymargin,p,filltype,above);
return F;
}
object draw(picture pic=currentpicture, Label L, envelope e,
real xmargin=0, real ymargin=xmargin, pen p=currentpen,
filltype filltype=NoFill, bool above=true)
{
object F=object(L,e,xmargin,ymargin,p,filltype,above);
pic.add(new void (frame f, transform t) {
frame d;
add(d,t,F.L);
e(f,d,xmargin,ymargin,p,filltype,above);
add(f,d);
},true);
pic.addBox(L.position,L.position,min(F.f),max(F.f));
return F;
}
object draw(picture pic=currentpicture, Label L, envelope e, pair position,
real xmargin=0, real ymargin=xmargin, pen p=currentpen,
filltype filltype=NoFill, bool above=true)
{
return draw(pic,Label(L,position),e,xmargin,ymargin,p,filltype,above);
}
pair point(object F, pair dir, transform t=identity())
{
pair m=min(F.g);
pair M=max(F.g);
pair c=0.5*(m+M);
pair z=t*F.L.position;
real[] T=intersect(F.g,c--2*(m+realmult(rectify(dir),M-m))-c);
if(T.length == 0) return z;
return z+point(F.g,T[0]);
}
frame bbox(picture pic=currentpicture,
real xmargin=0, real ymargin=xmargin,
pen p=currentpen, filltype filltype=NoFill)
{
real penwidth=linewidth(p);
frame f=pic.fit(max(pic.xsize-2*(xmargin+penwidth),0),
max(pic.ysize-2*(ymargin+penwidth),0));
box(f,xmargin,ymargin,p,filltype,above=false);
return f;
}