summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/base/flowchart.asy
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/base/flowchart.asy')
-rw-r--r--Build/source/utils/asymptote/base/flowchart.asy202
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;
+}