diff options
Diffstat (limited to 'Build/source/utils/asymptote/base/flowchart.asy')
-rw-r--r-- | Build/source/utils/asymptote/base/flowchart.asy | 202 |
1 files changed, 186 insertions, 16 deletions
diff --git a/Build/source/utils/asymptote/base/flowchart.asy b/Build/source/utils/asymptote/base/flowchart.asy index 5fe96ae8508..bb8fe21a4d6 100644 --- a/Build/source/utils/asymptote/base/flowchart.asy +++ b/Build/source/utils/asymptote/base/flowchart.asy @@ -10,28 +10,17 @@ 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 relative center of the block. - pair f_center; - // The size of the block pair size; - // Returns the relative position along the boundary of the block. - pair f_position(real x); - - pair shift(transform t=identity()) { - return t*center-f_center; - } - - // Returns the absolute position along the boundary of the block. - pair position(real x, transform t=identity()) { - return shift(t)+f_position(x); - } + // 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). @@ -44,6 +33,26 @@ struct block { 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()) { @@ -73,6 +82,15 @@ struct block { // 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. @@ -160,6 +178,47 @@ block rectangle(object body, pair center=(0,0), 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, @@ -327,7 +386,7 @@ path path(pair point[] ... flowdir dir[]) path line=point[0]; pair current, prev=point[0]; for(int i=1; i < point.length; ++i) { - if(dir[i-1] == Horizontal) + 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); @@ -348,9 +407,120 @@ path path(pair point[] ... flowdir dir[]) void draw(picture pic=currentpicture, block block, pen p=currentpen) { - pic.add(new void (frame f, transform t) { + 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)(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)(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)(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)(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; +} |