diff options
Diffstat (limited to 'Master/texmf/asymptote/plain_arrows.asy')
-rw-r--r-- | Master/texmf/asymptote/plain_arrows.asy | 569 |
1 files changed, 569 insertions, 0 deletions
diff --git a/Master/texmf/asymptote/plain_arrows.asy b/Master/texmf/asymptote/plain_arrows.asy new file mode 100644 index 00000000000..0ef8c2b2d5c --- /dev/null +++ b/Master/texmf/asymptote/plain_arrows.asy @@ -0,0 +1,569 @@ +real arrowlength=0.75cm; +real arrowfactor=15; +real arrowangle=15; +real arcarrowfactor=0.5*arrowfactor; +real arcarrowangle=2*arrowangle; +real arrowsizelimit=0.5; +real arrow2sizelimit=1/3; +real arrowdir=5; +real arrowbarb=3; +real arrowhookfactor=1.5; +real arrowtexfactor=1; + +real barfactor=arrowfactor; + +real arrowsize(pen p=currentpen) +{ + return arrowfactor*linewidth(p); +} + +real arcarrowsize(pen p=currentpen) +{ + return arcarrowfactor*linewidth(p); +} + +real barsize(pen p=currentpen) +{ + return barfactor*linewidth(p); +} + +struct arrowhead +{ + path head(path g, position position=EndPoint, pen p=currentpen, + real size=0, real angle=arrowangle); + real size(pen p)=arrowsize; + real arcsize(pen p)=arcarrowsize; + filltype defaultfilltype(pen) {return FillDraw;} +} + +real[] arrowbasepoints(path base, path left, path right) +{ + real[][] Tl=transpose(intersections(left,base)); + real[][] Tr=transpose(intersections(right,base)); + return new real[] {Tl.length > 0 ? Tl[0][0] : 1, + Tr.length > 0 ? Tr[0][0] : 1}; +} + +path arrowbase(path r, pair y, real t, real size) +{ + pair perp=2*size*I*dir(r,t); + return size == 0 ? y : y+perp--y-perp; +} + +arrowhead DefaultHead; +DefaultHead.head=new path(path g, position position=EndPoint, pen p=currentpen, + real size=0, real angle=arrowangle) { + if(size == 0) size=DefaultHead.size(p); + bool relative=position.relative; + real position=position.position.x; + if(relative) position=reltime(g,position); + path r=subpath(g,position,0); + pair x=point(r,0); + real t=arctime(r,size); + pair y=point(r,t); + path base=arrowbase(r,y,t,size); + path left=rotate(-angle,x)*r; + path right=rotate(angle,x)*r; + real[] T=arrowbasepoints(base,left,right); + pair denom=point(right,T[1])-y; + real factor=denom != 0 ? length((point(left,T[0])-y)/denom) : 1; + path left=rotate(-angle,x)*r; + path right=rotate(angle*factor,x)*r; + real[] T=arrowbasepoints(base,left,right); + return subpath(left,0,T[0])--subpath(right,T[1],0)&cycle; +}; + +arrowhead SimpleHead; +SimpleHead.head=new path(path g, position position=EndPoint, pen p=currentpen, + real size=0, real angle=arrowangle) { + if(size == 0) size=SimpleHead.size(p); + bool relative=position.relative; + real position=position.position.x; + if(relative) position=reltime(g,position); + path r=subpath(g,position,0); + pair x=point(r,0); + real t=arctime(r,size); + pair y=point(r,t); + path base=arrowbase(r,y,t,size); + path left=rotate(-angle,x)*r; + path right=rotate(angle,x)*r; + real[] T=arrowbasepoints(base,left,right); + pair denom=point(right,T[1])-y; + real factor=denom != 0 ? length((point(left,T[0])-y)/denom) : 1; + path left=rotate(-angle,x)*r; + path right=rotate(angle*factor,x)*r; + real[] T=arrowbasepoints(base,left,right); + return subpath(left,T[0],0)--subpath(right,T[1],0); +}; + +arrowhead HookHead(real dir=arrowdir, real barb=arrowbarb) +{ + arrowhead a; + a.head=new path(path g, position position=EndPoint, pen p=currentpen, + real size=0, real angle=arrowangle) + { + if(size == 0) size=a.size(p); + angle=min(angle*arrowhookfactor,45); + bool relative=position.relative; + real position=position.position.x; + if(relative) position=reltime(g,position); + path r=subpath(g,position,0); + pair x=point(r,0); + real t=arctime(r,size); + pair y=point(r,t); + path base=arrowbase(r,y,t,size); + path left=rotate(-angle,x)*r; + path right=rotate(angle,x)*r; + real[] T=arrowbasepoints(base,left,right); + pair denom=point(right,T[1])-y; + real factor=denom != 0 ? length((point(left,T[0])-y)/denom) : 1; + path left=rotate(-angle,x)*r; + path right=rotate(angle*factor,x)*r; + real[] T=arrowbasepoints(base,left,right); + left=subpath(left,0,T[0]); + right=subpath(right,T[1],0); + pair pl0=point(left,0), pl1=relpoint(left,1); + pair pr0=relpoint(right,0), pr1=relpoint(right,1); + pair M=(pl1+pr0)/2; + pair v=barb*unit(M-pl0); + pl1=pl1+v; pr0=pr0+v; + left=pl0{dir(-dir+degrees(M-pl0,false))}..pl1--M; + right=M--pr0..pr1{dir(dir+degrees(pr1-M,false))}; + return left--right&cycle; + }; + return a; +} +arrowhead HookHead=HookHead(); + +arrowhead TeXHead; +TeXHead.size=new real(pen p) +{ + static real hcoef=2.1; // 84/40=abs(base-hint)/base_height + return hcoef*arrowtexfactor*linewidth(p); +}; +TeXHead.arcsize=TeXHead.size; + +TeXHead.head=new path(path g, position position=EndPoint, pen p=currentpen, + real size=0, real angle=arrowangle) { + static real wcoef=1/84; // 1/abs(base-hint) + static path texhead=scale(wcoef)* + ((0,20) .. controls (-75,75) and (-108,158) .. + (-108,166) .. controls (-108,175) and (-100,178) .. + (-93,178) .. controls (-82,178) and (-80,173) .. + (-77,168) .. controls (-62,134) and (-30,61) .. + (70,14) .. controls (82,8) and (84,7) .. + (84,0) .. controls (84,-7) and (82,-8) .. + (70,-14) .. controls (-30,-61) and (-62,-134) .. + (-77,-168) .. controls (-80,-173) and (-82,-178) .. + (-93,-178) .. controls (-100,-178) and (-108,-175).. + (-108,-166).. controls (-108,-158) and (-75,-75) .. + (0,-20)--cycle); + if(size == 0) size=TeXHead.size(p); + path gp=scale(size)*texhead; + bool relative=position.relative; + real position=position.position.x; + if(relative) position=reltime(g,position); + path r=subpath(g,position,0); + pair y=point(r,arctime(r,size)); + return shift(y)*rotate(degrees(-dir(r,arctime(r,0.5*size))))*gp; +}; +TeXHead.defaultfilltype=new filltype(pen p) {return Fill(p);}; + +private real position(position position, real size, path g, bool center) +{ + bool relative=position.relative; + real position=position.position.x; + if(relative) { + position *= arclength(g); + if(center) position += 0.5*size; + position=arctime(g,position); + } else if(center) + position=arctime(g,arclength(subpath(g,0,position))+0.5*size); + return position; +} + +void drawarrow(frame f, arrowhead arrowhead=DefaultHead, + path g, pen p=currentpen, real size=0, + real angle=arrowangle, + filltype filltype=null, + position position=EndPoint, bool forwards=true, + margin margin=NoMargin, bool center=false) +{ + if(size == 0) size=arrowhead.size(p); + if(filltype == null) filltype=arrowhead.defaultfilltype(p); + size=min(arrowsizelimit*arclength(g),size); + real position=position(position,size,g,center); + + g=margin(g,p).g; + int L=length(g); + if(!forwards) { + g=reverse(g); + position=L-position; + } + path r=subpath(g,position,0); + size=min(arrowsizelimit*arclength(r),size); + path head=arrowhead.head(g,position,p,size,angle); + bool endpoint=position > L-sqrtEpsilon; + if(cyclic(head) && (filltype == NoFill || endpoint)) { + if(position > 0) + draw(f,subpath(r,arctime(r,size),length(r)),p); + if(!endpoint) + draw(f,subpath(g,position,L),p); + } else draw(f,g,p); + filltype.fill(f,head,p+solid); +} + +void drawarrow2(frame f, arrowhead arrowhead=DefaultHead, + path g, pen p=currentpen, real size=0, + real angle=arrowangle, filltype filltype=null, + margin margin=NoMargin) +{ + if(size == 0) size=arrowhead.size(p); + if(filltype == null) filltype=arrowhead.defaultfilltype(p); + g=margin(g,p).g; + size=min(arrow2sizelimit*arclength(g),size); + + path r=reverse(g); + int L=length(g); + path head=arrowhead.head(g,L,p,size,angle); + path tail=arrowhead.head(r,L,p,size,angle); + if(cyclic(head)) + draw(f,subpath(r,arctime(r,size),L-arctime(g,size)),p); + else draw(f,g,p); + filltype.fill(f,head,p+solid); + filltype.fill(f,tail,p+solid); +} + +// Add to picture an estimate of the bounding box contribution of arrowhead +// using the local slope at endpoint and ignoring margin. +void addArrow(picture pic, arrowhead arrowhead, path g, pen p, real size, + real angle, filltype filltype, real position) +{ + if(filltype == null) filltype=arrowhead.defaultfilltype(p); + pair z=point(g,position); + path g=z-(size+linewidth(p))*dir(g,position)--z; + frame f; + filltype.fill(f,arrowhead.head(g,position,p,size,angle),p); + pic.addBox(z,z,min(f)-z,max(f)-z); +} + +picture arrow(arrowhead arrowhead=DefaultHead, + path g, pen p=currentpen, real size=0, + real angle=arrowangle, filltype filltype=null, + position position=EndPoint, bool forwards=true, + margin margin=NoMargin, bool center=false) +{ + if(size == 0) size=arrowhead.size(p); + picture pic; + pic.add(new void(frame f, transform t) { + drawarrow(f,arrowhead,t*g,p,size,angle,filltype,position,forwards,margin, + center); + }); + + pic.addPath(g,p); + + real position=position(position,size,g,center); + path G; + if(!forwards) { + G=reverse(g); + position=length(g)-position; + } else G=g; + addArrow(pic,arrowhead,G,p,size,angle,filltype,position); + + return pic; +} + +picture arrow2(arrowhead arrowhead=DefaultHead, + path g, pen p=currentpen, real size=0, + real angle=arrowangle, filltype filltype=null, + margin margin=NoMargin) +{ + if(size == 0) size=arrowhead.size(p); + picture pic; + pic.add(new void(frame f, transform t) { + drawarrow2(f,arrowhead,t*g,p,size,angle,filltype,margin); + }); + + pic.addPath(g,p); + + int L=length(g); + addArrow(pic,arrowhead,g,p,size,angle,filltype,L); + addArrow(pic,arrowhead,reverse(g),p,size,angle,filltype,L); + + return pic; +} + +void bar(picture pic, pair a, pair d, pen p=currentpen) +{ + picture opic; + Draw(opic,-0.5d--0.5d,p+solid); + add(pic,opic,a); +} + +picture bar(pair a, pair d, pen p=currentpen) +{ + picture pic; + bar(pic,a,d,p); + return pic; +} + +typedef bool arrowbar(picture, path, pen, margin); + +bool Blank(picture, path, pen, margin) +{ + return false; +} + +bool None(picture, path, pen, margin) +{ + return true; +} + +arrowbar BeginArrow(arrowhead arrowhead=DefaultHead, + real size=0, real angle=arrowangle, + filltype filltype=null, position position=BeginPoint) +{ + return new bool(picture pic, path g, pen p, margin margin) { + add(pic,arrow(arrowhead,g,p,size,angle,filltype,position,forwards=false, + margin)); + return false; + }; +} + +arrowbar Arrow(arrowhead arrowhead=DefaultHead, + real size=0, real angle=arrowangle, + filltype filltype=null, position position=EndPoint) +{ + return new bool(picture pic, path g, pen p, margin margin) { + add(pic,arrow(arrowhead,g,p,size,angle,filltype,position,margin)); + return false; + }; +} + +arrowbar EndArrow(arrowhead arrowhead=DefaultHead, + real size=0, real angle=arrowangle, + filltype filltype=null, position position=EndPoint)=Arrow; + +arrowbar MidArrow(arrowhead arrowhead=DefaultHead, + real size=0, real angle=arrowangle, filltype filltype=null) +{ + return new bool(picture pic, path g, pen p, margin margin) { + add(pic,arrow(arrowhead,g,p,size,angle,filltype,MidPoint,margin, + center=true)); + return false; + }; +} + +arrowbar Arrows(arrowhead arrowhead=DefaultHead, + real size=0, real angle=arrowangle, + filltype filltype=null) +{ + return new bool(picture pic, path g, pen p, margin margin) { + add(pic,arrow2(arrowhead,g,p,size,angle,filltype,margin)); + return false; + }; +} + +arrowbar BeginArcArrow(arrowhead arrowhead=DefaultHead, + real size=0, real angle=arcarrowangle, + filltype filltype=null, position position=BeginPoint) +{ + return new bool(picture pic, path g, pen p, margin margin) { + real size=size == 0 ? arrowhead.arcsize(p) : size; + add(pic,arrow(arrowhead,g,p,size,angle,filltype,position, + forwards=false,margin)); + return false; + }; +} + +arrowbar ArcArrow(arrowhead arrowhead=DefaultHead, + real size=0, real angle=arcarrowangle, + filltype filltype=null, position position=EndPoint) +{ + return new bool(picture pic, path g, pen p, margin margin) { + real size=size == 0 ? arrowhead.arcsize(p) : size; + add(pic,arrow(arrowhead,g,p,size,angle,filltype,position,margin)); + return false; + }; +} + +arrowbar EndArcArrow(arrowhead arrowhead=DefaultHead, + real size=0, real angle=arcarrowangle, + filltype filltype=null, + position position=EndPoint)=ArcArrow; + +arrowbar MidArcArrow(arrowhead arrowhead=DefaultHead, + real size=0, real angle=arcarrowangle, + filltype filltype=null) +{ + return new bool(picture pic, path g, pen p, margin margin) { + real size=size == 0 ? arrowhead.arcsize(p) : size; + add(pic,arrow(arrowhead,g,p,size,angle,filltype,MidPoint,margin, + center=true)); + return false; + }; +} + +arrowbar ArcArrows(arrowhead arrowhead=DefaultHead, + real size=0, real angle=arcarrowangle, + filltype filltype=null) +{ + return new bool(picture pic, path g, pen p, margin margin) { + real size=size == 0 ? arrowhead.arcsize(p) : size; + add(pic,arrow2(arrowhead,g,p,size,angle,filltype,margin)); + return false; + }; +} + +arrowbar BeginBar(real size=0) +{ + return new bool(picture pic, path g, pen p, margin margin) { + real size=size == 0 ? barsize(p) : size; + bar(pic,point(g,0),size*dir(g,0)*I,p); + return true; + }; +} + +arrowbar Bar(real size=0) +{ + return new bool(picture pic, path g, pen p, margin margin) { + int L=length(g); + real size=size == 0 ? barsize(p) : size; + bar(pic,point(g,L),size*dir(g,L)*I,p); + return true; + }; +} + +arrowbar EndBar(real size=0)=Bar; + +arrowbar Bars(real size=0) +{ + return new bool(picture pic, path g, pen p, margin margin) { + real size=size == 0 ? barsize(p) : size; + BeginBar(size)(pic,g,p,margin); + EndBar(size)(pic,g,p,margin); + return true; + }; +} + +arrowbar BeginArrow=BeginArrow(), +MidArrow=MidArrow(), +Arrow=Arrow(), +EndArrow=Arrow(), +Arrows=Arrows(), +BeginArcArrow=BeginArcArrow(), +MidArcArrow=MidArcArrow(), +ArcArrow=ArcArrow(), +EndArcArrow=ArcArrow(), +ArcArrows=ArcArrows(), +BeginBar=BeginBar(), +Bar=Bar(), +EndBar=Bar(), +Bars=Bars(); + +void draw(frame f, path g, pen p=currentpen, arrowbar arrow) +{ + picture pic; + if(arrow(pic,g,p,NoMargin)) + draw(f,g,p); + add(f,pic.fit()); +} + +void draw(picture pic=currentpicture, Label L="", path g, align align=NoAlign, + pen p=currentpen, arrowbar arrow=None, arrowbar bar=None, + margin margin=NoMargin, Label legend="", marker marker=nomarker) +{ + Label L=L.copy(); + L.align(align); + if(marker != nomarker && !marker.above) marker.mark(pic,g); + bool drawpath=arrow(pic,g,p,margin); + if(bar(pic,g,p,margin) && drawpath) _draw(pic,g,p,margin); + if(L.s != "") { + L.p(p); + L.out(pic,g); + } + if(legend.s != "") { + legend.p(p); + pic.legend.push(Legend(legend.s,legend.p,p,marker.f,marker.above)); + } + if(marker != nomarker && marker.above) marker.mark(pic,g); +} + +// Draw a fixed-size line about the user-coordinate 'origin'. +void draw(pair origin, picture pic=currentpicture, Label L="", path g, + align align=NoAlign, pen p=currentpen, arrowbar arrow=None, + arrowbar bar=None, margin margin=NoMargin, Label legend="", + marker marker=nomarker) +{ + picture opic; + draw(opic,L,g,align,p,arrow,bar,margin,legend,marker); + add(pic,opic,origin); +} + +void draw(picture pic=currentpicture, explicit path[] g, pen p=currentpen, + Label legend="", marker marker=nomarker) +{ + for(int i=0; i < g.length-1; ++i) + draw(pic,g[i],p,marker); + if(g.length > 0) draw(pic,g[g.length-1],p,legend,marker); +} + +void draw(picture pic=currentpicture, guide[] g, pen p=currentpen, + Label legend="", marker marker=nomarker) +{ + draw(pic,(path[]) g,p,legend,marker); +} + +void draw(pair origin, picture pic=currentpicture, explicit path[] g, + pen p=currentpen, Label legend="", marker marker=nomarker) +{ + picture opic; + draw(opic,g,p,legend,marker); + add(pic,opic,origin); +} + +void draw(pair origin, picture pic=currentpicture, guide[] g, pen p=currentpen, + Label legend="", marker marker=nomarker) +{ + draw(origin,pic,(path[]) g,p,legend,marker); +} + +// Align an arrow pointing to b from the direction dir. The arrow is +// 'length' PostScript units long. +void arrow(picture pic=currentpicture, Label L="", pair b, pair dir, + real length=arrowlength, align align=NoAlign, + pen p=currentpen, arrowbar arrow=Arrow, margin margin=EndMargin) +{ + Label L=L.copy(); + if(L.defaultposition) L.position(0); + L.align(L.align,dir); + L.p(p); + marginT margin=margin(b--b,p); // Extract margin.begin and margin.end + pair a=(margin.begin+length+margin.end)*unit(dir); + draw(b,pic,L,a--(0,0),align,p,arrow,margin); +} + +// Force an array of 2D pictures to be as least as large as picture all. +void rescale2(picture[] pictures, picture all) +{ + if(!all.empty2()) { + transform t=inverse(all.calculateTransform()*pictures[0].T); + pair m=t*min(all); + pair M=t*max(all); + for(int i=0; i < pictures.length; ++i) { + draw(pictures[i],m,nullpen); + draw(pictures[i],M,nullpen); + } + } +} + +// Force an array of pictures to have a uniform scaling. +void rescale(picture[] pictures) +{ + if(pictures.length == 0) return; + picture all; + size(all,pictures[0]); + for(picture pic : pictures) + add(all,pic); + rescale2(pictures,all); +} |