diff options
Diffstat (limited to 'Master/texmf-dist/asymptote/flowchart.asy')
-rw-r--r-- | Master/texmf-dist/asymptote/flowchart.asy | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/Master/texmf-dist/asymptote/flowchart.asy b/Master/texmf-dist/asymptote/flowchart.asy new file mode 100644 index 00000000000..3db66173755 --- /dev/null +++ b/Master/texmf-dist/asymptote/flowchart.asy @@ -0,0 +1,526 @@ +// Flowchart routines written by Jacques Pienaar, Steve Melenchuk, John Bowman. + +private import math; + +struct flowdir {} + +restricted flowdir Horizontal; +restricted flowdir Vertical; + +real minblockwidth=0; +real minblockheight=0; +real mincirclediameter=0; +real defaultexcursion=0.1; + +struct block { + // The absolute center of the block in user coordinates. + pair center; + + // The size of the block + pair size; + + // The relative center of the block. + pair f_center; + + // These eight variables return the appropriate location on the block + // in relative coordinates, where the lower left corner of the block is (0,0). + pair f_top; + pair f_left; + pair f_right; + pair f_bottom; + pair f_topleft; + pair f_topright; + pair f_bottomleft; + pair f_bottomright; + + void operator init(pair z) { + center=z; + } + + void operator init(real x, real y) { + center=(x,y); + } + + pair shift(transform t=identity()) { + return t*center-f_center; + } + + // Returns the relative position along the boundary of the block. + pair f_position(real x); + + // Returns the absolute position along the boundary of the block. + pair position(real x, transform t=identity()) { + return shift(t)+f_position(x); + } + + // These eight functions return the appropriate location on the block + // in absolute coordinates. + pair top(transform t=identity()) { + return shift(t)+f_top; + } + pair bottom(transform t=identity()) { + return shift(t)+f_bottom; + } + pair left(transform t=identity()) { + return shift(t)+f_left; + } + pair right(transform t=identity()) { + return shift(t)+f_right; + } + pair topleft(transform t=identity()) { + return shift(t)+f_topleft; + } + pair topright(transform t=identity()) { + return shift(t)+f_topright; + } + pair bottomleft(transform t=identity()) { + return shift(t)+f_bottomleft; + } + pair bottomright(transform t=identity()) { + return shift(t)+f_bottomright; + } + + // Return a frame representing the block. + frame draw(pen p=currentpen); + + // Store optional label on outgoing edge. + Label label; + + // Store rectilinear path directions. + pair[] dirs; + + // Store optional arrow. + arrowbar arrow=None; +}; + +// Construct a rectangular block with header and body objects. +block rectangle(object header, object body, pair center=(0,0), + pen headerpen=mediumgray, pen bodypen=invisible, + pen drawpen=currentpen, + real dx=3, real minheaderwidth=minblockwidth, + real minheaderheight=minblockwidth, + real minbodywidth=minblockheight, + real minbodyheight=minblockheight) +{ + frame fbody=body.f; + frame fheader=header.f; + pair mheader=min(fheader); + pair Mheader=max(fheader); + pair mbody=min(fbody); + pair Mbody=max(fbody); + pair bound0=Mheader-mheader; + pair bound1=Mbody-mbody; + real width=max(bound0.x,bound1.x); + pair z0=maxbound((width+2dx,bound0.y+2dx),(minbodywidth,minbodyheight)); + pair z1=maxbound((width+2dx,bound1.y+2dx),(minheaderwidth,minheaderheight)); + path shape=(0,0)--(0,z1.y)--(0,z0.y+z1.y)--(z0.x,z0.y+z1.y)--z1--(z0.x,0)-- + cycle; + + block block; + block.draw=new frame(pen p) { + frame block; + filldraw(block,shift(0,z1.y)*box((0,0),z0),headerpen,drawpen); + add(block,shift(-0.5*(Mheader+mheader))*fheader,(0,z1.y)+0.5z0); + filldraw(block,box((0,0),z1),bodypen,drawpen); + add(block,shift(-0.5*(Mbody+mbody))*fbody,0.5z1); + return block; + }; + block.f_position=new pair(real x) { + return point(shape,x); + }; + block.f_center=interp(point(shape,0),point(shape,3),0.5); + block.f_bottomleft=point(shape,0); + block.f_bottom=point(shape,5.5); + block.f_bottomright=point(shape,5); + block.f_right=point(shape,4.5); + block.f_topright=point(shape,3); + block.f_top=point(shape,2.5); + block.f_topleft=point(shape,2); + block.f_left=point(shape,0.5); + block.center=center; + block.size=point(shape,3); + return block; +} + +// As above, but without the header. +block rectangle(object body, pair center=(0,0), + pen fillpen=invisible, pen drawpen=currentpen, + real dx=3, real minwidth=minblockwidth, + real minheight=minblockheight) +{ + frame f=body.f; + pair m=min(f); + pair M=max(f); + pair z=maxbound(M-m+dx*(2,2),(minwidth,minheight)); + path shape=box((0,0),z); + + block block; + block.draw=new frame(pen p) { + frame block; + filldraw(block,shape,fillpen,drawpen); + add(block,shift(-0.5*(M+m))*f,0.5z); + return block; + }; + block.f_position=new pair(real x) { + return point(shape,x); + }; + block.f_center=0.5*z; + block.center=center; + block.size=z; + block.f_bottomleft=point(shape,0); + block.f_bottom=point(shape,0.5); + block.f_bottomright=point(shape,1); + block.f_right=point(shape,1.5); + block.f_topright=point(shape,2); + block.f_top=point(shape,2.5); + block.f_topleft=point(shape,3); + block.f_left=point(shape,3.5); + return block; +} + +block parallelogram(object body, pair center=(0,0), + pen fillpen=invisible, pen drawpen=currentpen, + real dx=3, real slope=2, + real minwidth=minblockwidth, + real minheight=minblockheight) +{ + frame f=body.f; + pair m=min(f); + pair M=max(f); + pair bound=maxbound(M-m+dx*(0,2),(minwidth,minheight)); + + real skew=bound.y/slope; + real a=bound.x+skew; + real b=bound.y; + + path shape=(0,0)--(a,0)--(a+skew,b)--(skew,b)--cycle; + + block block; + block.draw=new frame(pen p) { + frame block; + filldraw(block,shape,fillpen,drawpen); + add(block,shift(-0.5*(M+m))*f,((a+skew)/2,b/2)); + return block; + }; + block.f_position=new pair(real x) { + return point(shape,x); + }; + block.f_center=((a+skew)/2,b/2); + block.center=center; + block.size=(a+skew,b); + block.f_bottomleft=(0,0); + block.f_bottom=((a+skew)/2,0); + block.f_bottomright=(a,0); + block.f_right=(a+skew/2,b/2); + block.f_topright=(a+skew,b); + block.f_top=((a+skew)/2,b); + block.f_topleft=(skew,b); + block.f_left=(skew/2,b/2); + return block; +} + +block diamond(object body, pair center=(0,0), + pen fillpen=invisible, pen drawpen=currentpen, + real ds=5, real dw=1, + real height=20, real minwidth=minblockwidth, + real minheight=minblockheight) +{ + frame f=body.f; + pair m=min(f); + pair M=max(f); + pair bound=maxbound(M-m,(minwidth,minheight)); + + real e=ds; + real a=0.5bound.x-dw; + real b=0.5bound.y; + real c=b+height; + + real arg=a^2+b^2+c^2-2b*c-e^2; + real denom=e^2-a^2; + real slope=arg >= 0 && denom != 0 ? (a*(c-b)-e*sqrt(arg))/denom : 1.0; + real d=abs(c/slope); + + path shape=(2d,c)--(d,2c)--(0,c)--(d,0)--cycle; + + block block; + block.draw=new frame(pen p) { + frame block; + filldraw(block,shape,fillpen,drawpen); + add(block,shift(-0.5*(M+m))*f,(d,c)); + return block; + }; + block.f_position=new pair(real x) { + return point(shape,x); + }; + block.f_center=(point(shape,1).x,point(shape,0).y); + block.center=center; + block.size=(point(shape,0).x,point(shape,1).y); + block.f_bottomleft=point(shape,2.5); + block.f_bottom=point(shape,3); + block.f_bottomright=point(shape,3.5); + block.f_right=point(shape,0); + block.f_topright=point(shape,0.5); + block.f_top=point(shape,1); + block.f_topleft=point(shape,1.5); + block.f_left=point(shape,2); + return block; +} + +block circle(object body, pair center=(0,0), pen fillpen=invisible, + pen drawpen=currentpen, real dr=3, + real mindiameter=mincirclediameter) +{ + frame f=body.f; + pair m=min(f); + pair M=max(f); + real r=max(0.5length(M-m)+dr,0.5mindiameter); + + path shape=(0,r)..(r,2r)..(2r,r)..(r,0)..cycle; + + block block; + block.draw=new frame(pen p) { + frame block; + filldraw(block,shape,fillpen,drawpen); + add(block,shift(-0.5*(M+m))*f,(r,r)); + return block; + }; + block.f_position=new pair(real x) { + return point(shape,x); + }; + block.f_center=(r,r); + block.center=center; + block.size=(2r,2r); + block.f_left=point(shape,0); + block.f_topleft=point(shape,0.5); + block.f_top=point(shape,1); + block.f_topright=point(shape,1.5); + block.f_right=point(shape,2); + block.f_bottomright=point(shape,2.5); + block.f_bottom=point(shape,3); + block.f_bottomleft=point(shape,3.5); + return block; +} + +block roundrectangle(object body, pair center=(0,0), + pen fillpen=invisible, pen drawpen=currentpen, + real ds=5, real dw=0, real minwidth=minblockwidth, + real minheight=minblockheight) +{ + frame f=body.f; + pair m=min(f); + pair M=max(f); + pair bound=maxbound(M-m,(minwidth,minheight)); + + real a=bound.x; + real b=bound.y; + + path shape=(0,ds+dw)--(0,ds+b-dw){up}..{right} + (ds+dw,2ds+b)--(ds+a-dw,2ds+b){right}..{down} + (2ds+a,ds+b-dw)--(2ds+a,ds+dw){down}..{left} + (ds+a-dw,0)--(ds+dw,0){left}..{up}cycle; + + block block; + block.draw=new frame(pen p) { + frame block; + filldraw(block,shape,fillpen,drawpen); + add(block,shift(-0.5*(M+m))*f,(ds,ds)+0.5bound); + return block; + }; + block.f_position=new pair(real x) { + return point(shape,x); + }; + block.f_center=(ds+0.5a,ds+0.5b); + block.center=center; + block.size=(2ds+a,2ds+b); + block.f_bottomleft=point(shape,7.5); + block.f_bottom=point(shape,6.5); + block.f_bottomright=point(shape,5.5); + block.f_right=point(shape,4.5); + block.f_topright=point(shape,3.5); + block.f_top=point(shape,2.5); + block.f_topleft=point(shape,1.5); + block.f_left=point(shape,0.5); + return block; +} + +block bevel(object body, pair center=(0,0), pen fillpen=invisible, + pen drawpen=currentpen, real dh=5, real dw=5, + real minwidth=minblockwidth, real minheight=minblockheight) +{ + frame f=body.f; + pair m=min(f); + pair M=max(f); + pair bound=maxbound(M-m,(minwidth,minheight)); + + real a=bound.x; + real b=0.5bound.y; + + path shape=(2dw+a,b+dh)--(dw+a,2b+2dh)--(dw,2b+2dh)--(0,b+dh)--(dw,0)-- + (dw+a,0)--cycle; + block block; + block.draw=new frame(pen p) { + frame block; + filldraw(block,shape,fillpen,drawpen); + add(block,shift(-0.5*(M+m))*f,(0.5bound+(dw,dh))); + return block; + }; + block.f_position=new pair(real x) { + return point(shape,x); + }; + block.f_center=(dw+0.5a,dh+b); + block.center=center; + block.size=(2dw+a,2dh+2b); + block.f_bottomleft=point(shape,4); + block.f_bottom=point(shape,4.5); + block.f_bottomright=point(shape,5); + block.f_right=point(shape,0); + block.f_topright=point(shape,1); + block.f_top=point(shape,1.5); + block.f_topleft=point(shape,2); + block.f_left=point(shape,3); + return block; +} + +path path(pair point[] ... flowdir dir[]) +{ + path line=point[0]; + pair current, prev=point[0]; + for(int i=1; i < point.length; ++i) { + if(i-1 >= dir.length || dir[i-1] == Horizontal) + current=(point[i].x,point[i-1].y); + else + current=(point[i-1].x,point[i].y); + + if(current != prev) { + line=line--current; + prev=current; + } + + current=point[i]; + if(current != prev) { + line=line--current; + prev=current; + } + } + return line; +} + +void draw(picture pic=currentpicture, block block, pen p=currentpen) +{ + pic.add(new void(frame f, transform t) { + add(f,shift(block.shift(t))*block.draw(p)); + },true); + pic.addBox(block.center,block.center, + -0.5*block.size+min(p),0.5*block.size+max(p)); +} + +typedef block blockconnector(block, block); + +blockconnector blockconnector(picture pic, transform t, pen p=currentpen, + margin margin=PenMargin) +{ + return new block(block b1, block b2) { + if(b1.dirs.length == 0) { + if(abs(b1.center.y-b2.center.y) < sqrtEpsilon) { + // horizontally aligned + b1.dirs[0]=b1.center.x < b2.center.x ? right : left; + blockconnector(pic,t,p,margin)(b1,b2); + } else if(abs(b1.center.x-b2.center.x) < sqrtEpsilon) { + // vertically aligned + b1.dirs[0]=b1.center.y < b2.center.y ? up : down; + blockconnector(pic,t,p,margin)(b1,b2); + } else { + if(abs(b1.center.y-b2.center.y) < abs(b1.center.x-b2.center.x)) { + b1.dirs[0]=b1.center.x < b2.center.x ? right : left; + b1.dirs[1]=b1.center.y < b2.center.y ? up : down; + blockconnector(pic,t,p,margin)(b1,b2); + } else { + b1.dirs[0]=b1.center.y < b2.center.y ? up : down; + b1.dirs[1]=b1.center.x < b2.center.x ? right : left; + blockconnector(pic,t,p,margin)(b1,b2); + } + } + return b2; + } + + // compute the link for given directions (and label if any) + pair[] dirs=copy(b1.dirs); // deep copy + pair current,prev; + pair dir=dirs[0]; + if(dir == up) prev=b1.top(t); + if(dir == down) prev=b1.bottom(t); + if(dir == left) prev=b1.left(t); + if(dir == right) prev=b1.right(t); + path line=prev; + arrowbar arrow=b1.arrow; + + int i; + for(i=1; i < dirs.length-1; ++i) { + if(abs(length(dirs[i-1])-1) < sqrtEpsilon) + current=prev+t*dirs[i-1]*defaultexcursion; + else + current=prev+t*dirs[i-1]; + + if(current != prev) { + line=line--current; + prev=current; + } + } + dir=dirs[dirs.length-1]; + current=0; + if(dir == up) current=b2.bottom(t); + if(dir == down) current=b2.top(t); + if(dir == left) current=b2.right(t); + if(dir == right) current=b2.left(t); + if(abs(dirs[i-1].y) < sqrtEpsilon && + abs(prev.x-current.x) > sqrtEpsilon) { + prev=(current.x,prev.y); + line=line--prev; // horizontal + } else if(abs(dirs[i-1].x) < sqrtEpsilon && + abs(prev.y-current.y) > sqrtEpsilon) { + prev=(prev.x,current.y); + line=line--prev; + } + if(current != prev) + line=line--current; + + draw(pic,b1.label,line,p,arrow,margin); + + b1.label=""; + b1.dirs.delete(); + b1.arrow=None; + return b2; + }; +} + +struct Dir +{ + pair z; + void operator init(pair z) {this.z=z;} +} + +Dir Right=Dir(right); +Dir Left=Dir(left); +Dir Up=Dir(up); +Dir Down=Dir(down); + +// Add a label to the current link +block operator --(block b1, Label label) +{ + b1.label=label; + return b1; +} + +// Add a direction to the current link +block operator --(block b1, Dir dir) +{ + b1.dirs.push(dir.z); + return b1; +} + +// Add an arrowbar to the current link +block operator --(block b, arrowbar arrowbar) +{ + b.arrow=arrowbar; + return b; +} |