Asymptote 中方便使用的 TikZ 的 `node` 版本?

Asymptote 中方便使用的 TikZ 的 `node` 版本?

我对流行病中经典 SIR 模型的变体很感兴趣。使用 TikZ 的插图简单易用node

在此处输入图片描述

\documentclass[tikz,border=5mm]{standalone}
\begin{document}
\begin{tikzpicture}
\def\a{1.5}
\path[nodes={draw,circle,minimum size=8mm,fill=yellow,draw=blue}]
(210:\a) node (S) {$S$}
(-30:\a) node (I) {$I$}
(90:\a)  node (R) {$R$}
;
\draw[->] (S)--(I);
\draw[->] (I)--(R);
\draw[->] (R)--(S);
\draw[->] (R.0) to[out=0,in=60] (I.60);
\end{tikzpicture}
\end{document}

对我来说,使用 Asymptote 来说明上面的简单图表相当复杂。Asymptote 功能强大,我认为它应该涵盖 TikZ 的优美功能nodeinner sepminimum width、、、、等)。以下是我迄今为止尝试过的。shape=circleshape=ellipseanchor.centerS.30

第一次尝试控制箭头尖、圆形和标签大小失败。

在此处输入图片描述

// http://asymptote.ualberta.ca/
unitsize(1.5cm);
path R=dir(90), S=dir(210), I=dir(-30);

Label LS = Label("$S$", FillDraw(yellow,blue));
Label LI = Label("$I$", FillDraw(yellow,blue));
Label LR = Label("$R$", FillDraw(yellow,blue));

draw(S--I--R--cycle);
path pRI=arc((0,0),1,90,-30);
draw(pRI);
label(LS,S);
label(LI,I);
label(LR,R);

第二次尝试可以制作圆形、箭头尖端,但无法控制倾斜连接器、标签大小、用颜色(黄色、蓝色)填充和绘制形状。

在此处输入图片描述

// http://asymptote.ualberta.ca/
unitsize(1.5cm);
import flowchart;
pair R=dir(90), S=dir(210), I=dir(-30);
block blockS=circle("S",S);
block blockI=circle("I",I);
block blockR=circle("R",R);

draw(blockS,blue);
draw(blockI);
draw(blockR);

add(new void(picture pic, transform t) {
    blockconnector operator --=blockconnector(pic,t);
    blockS--Arrow(TeXHead)--blockI;
   blockI--Arrow(TeXHead)--blockR;
  });

总结一下,我在用 Asymptote 绘图时有 2 个问题。

问题 1:如何绘制从 S 到 I、从 I 到 R、从 R 到 I 的箭头,使得箭头尖触及蓝色边界?

问题2:如何制作标签 S、I、R 周围的圆形/椭圆形?

2020 年 12 月 24 日更新看来 Asymptote 的objects 可以完成这项工作。在我第三次尝试时,箭头尖端触及了蓝色边界,但所有形状都是椭圆形,而不是圆形(参见I),我必须手动指定边界点(参见point(LI,dir(120),t))。代码摘自Asymptote 的画廊,所以我的疑问更加合理。

在此处输入图片描述

unitsize(1.5cm);
pair R=dir(90), S=dir(210), I=dir(-30);
real margin=3mm;

object LS=draw("$S$",ellipse,S,margin,FillDraw(yellow,blue));
object LI=draw("$I$",ellipse,I,margin,FillDraw(yellow,blue));
object LR=draw("$R$",ellipse,R,margin,FillDraw(yellow,blue));

add(new void(frame f, transform t) {
    picture pic;
    draw(pic,point(LS,E,t)--point(LI,W,t),red,Arrow(TeXHead),PenMargin);
    draw(pic,point(LI,dir(120),t)--point(LR,dir(-60),t),red,Arrow(TeXHead),PenMargin);
    draw(pic,point(LR,dir(240),t)--point(LS,dir(60),t),red,Arrow(TeXHead),PenMargin);
    pair R1=point(LR,NE,t), I1=point(LI,NE,t);
    path pRI=R1 .. controls R1+30*dir(45) and I1+40*dir(35).. I1; 
   draw(pic,pRI,red,Arrow(TeXHead),PenMargin);

    add(f,pic.fit());
  });

shipout(bbox(5mm));

答案1

可以用普通的 Asymptote 绘制带箭头的图表,几乎和用普通的 TikZ 一样简单

我对这个解决方案很满意,但仍然愿意接受更好的解决方案。我的方法是使用普通的 Asymptote:不需要其他命令/模块。

注意,圆是大小相等的椭圆。通过组合objectlabel,我们可以得到circle形状,从而使所有圆形具有统一的大小(类似于minimum widthTikZ 的节点)。

在此处输入图片描述

object
S=draw("",ellipse,(0,0),xmargin=3mm,FillDraw(yellow,blue)),
I=draw("",ellipse,(4cm,0),xmargin=3mm,FillDraw(yellow,blue)),
R=draw("",ellipse,(2cm,3cm),xmargin=3mm,FillDraw(yellow,blue));
label("S",(0,0));
label("I",(4cm,0));
label("R",(2cm,3cm));
pair
S1=point(S,E), I1=point(I,W),
I2=point(I,dir(120)), R1=point(R,dir(-60)),
R2=point(R,dir(-120)), S2=point(S,dir(60)),
R3=point(R,dir(-20)), I3=point(I,dir(70))
;
DefaultHead=TeXHead;
draw(S1--I1,red,Arrow());
draw(I2--R1,red,Arrow());
draw(R2--S2,red,Arrow());
draw(R3 .. controls R3+1cm*dir(0) and I3+1cm*dir(70) .. I3,red,Arrow());

到目前为止,通常的 TikZnode涉及选项(inner sepinner xsep形状inner ysep、、、、、、、、、、、)都可以轻松转换为Asymptote 。我不会测试其他一些功能(fill文本、对齐节点等)。drawminimum sizeshorten >anchorshorten <circleellipserectangleloopscaleslopedrotatetext coloranchor

在此处输入图片描述

// Diagrams with arrows can be drawn with plain Asymptote
object
S=draw("",ellipse,(0,0),xmargin=6mm,FillDraw(yellow,blue)),
I=draw("",ellipse,(4cm,0),xmargin=3mm,FillDraw(yellow,blue)),
R=draw("",ellipse,(2cm,3cm),xmargin=3mm,FillDraw(yellow,blue));
label(scale(3)*"S",(0,0));
label(scale(.5)*"i",(4cm,0));
label("R",(2cm,3cm));

pair
S1=point(S,E), I1=point(I,W),
I2=point(I,dir(120)), R1=point(R,dir(-60)),
R2=point(R,dir(-120)), S2=point(S,dir(60)),
R3=point(R,dir(-20)), I3=point(I,dir(70)),
I4=point(I,dir(-45))
;

DefaultHead=TeXHead;
draw("$\alpha$",S1--I1,purple,Arrow(),margin=TrueMargin(.5mm, 2mm));
draw(Label("$\beta$",align=SW),I2--R1,red,Arrow(),margin=TrueMargin(1mm));
draw(Label("gamma",Rotate(R2-S2)),R2--S2,red,Arrow());
draw("$\delta$",R3{0} .. {-60}I3,red,Arrow(),margin=TrueMargin(2mm));
draw(Label("go to Heaven",align=plain.S,EndPoint),I4--I4+1cm*dir(-45),cyan,Arrow);

add(bbox(5mm));

有时 TikZ 会通过 、 等表格使 LaTeX 更加美观,就像 tikzpicture 一样matrix of nodesmatrix of math nodes在我看来,由于每个图形都是独立的,所以 Asymptote 不应该有这些选项,而 Asymptote 的优势在于真正的 3D。我并不认为 TikZ 是绘图的标准,但它是关心 Asymptote 能帮助我/我们以视觉方式表达想法的起点。

答案2

这是一个很长的评论,但仍然不是一个简洁的答案。

我发现2009年链接import node;在我看来,语法node.asy仍然不太方便。另请参阅Jim Heffron 的回答从 2014 年开始。

object从上面的链接,我进行了第四次尝试。首先回想一下from的语法plain_boxes.asy

object draw(picture pic=currentpicture, Label L, envelope e,
            pair position=(0,0), real xmargin=0, real ymargin=xmargin,
            pen p=currentpen, filltype filltype=NoFill);

box(矩形)的形状ellipse,,,roundbox但是没有circle形状我们可以控制DrawFill和(xmargin就像ymarginTikZ 的);我们可以获取定义的inner sep边界(TikZ 的 )内的任意点。anchorobject

在此处输入图片描述

object
cat = draw("cat", box, (0,0), Draw),
dog = draw("dog", ellipse, (2cm,0), Fill(olive)),
elephant = draw("elephant", roundbox, (0,-2cm),xmargin=2mm,FillDraw(lightblue, darkblue));

pair C=point(cat,E),Ct=point(cat,S);
pair D=point(dog,-90), Dt=point(dog,SW);
pair E=point(elephant,N), Et=point(elephant,NNE);
draw(C--D,red,Arrow(TeXHead));
draw(Et--Dt,red,Arrow(TeXHead));
draw(E--Ct,red,Arrow(TeXHead));

然后我想到这个,简单的代码,看起来相当不错,除了所有形状都是椭圆形,而不是圆形。

在此处输入图片描述

object
S=draw("S",ellipse,(0,0),xmargin=3mm,FillDraw(yellow,blue)),
I=draw("I",ellipse,(4cm,0),xmargin=3mm,FillDraw(yellow,blue)),
R=draw("R",ellipse,(2cm,3cm),xmargin=3mm,FillDraw(yellow,blue));

pair 
S1=point(S,E), I1=point(I,W),
I2=point(I,dir(120)), R1=point(R,dir(-60)),
R2=point(R,dir(-120)), S2=point(S,dir(60)),
R3=point(R,dir(-20)), I3=point(I,dir(70))
;

DefaultHead=TeXHead;
draw(S1--I1,red,Arrow());
draw(I2--R1,red,Arrow());
draw(R2--S2,red,Arrow());
draw(R3 .. controls  R3+1cm*dir(0) and  I3+1cm*dir(70) .. I3,red,Arrow());

更新:通过放置circle形状(@Nguyen Van Chi 模仿了roundbox中的形状plain_boxes.asy),效果很好(改变ellipsecircle)^^ 我认为现在在 Asymptote 中定义一个新形状(梯形、平行四边形、星形……)是一项舒适的任务(甚至比在 TikZ 中定义新形状更舒服node

在此处输入图片描述

//////////////////////////////////////////////////////
// code for the `circle` shape from Nguyen Van Chi, 
// inspired by the `roundbox` shape (see `plain_boxes.asy`)
path circle(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;
path g=shift(m-(xmargin,ymargin))*(circle((a/2,b/2),max(a,b)/2));
frame F;
 if(above == false) {
    filltype.fill(F,g,p);
    prepend(dest,F);
  } else filltype.fill(dest,g,p);
return g;
}

path circle(frame f, Label L, real xmargin=0, real ymargin=xmargin,
            pen p=currentpen, filltype filltype=NoFill, bool above=true)
{
add(f,L);
return circle(f,xmargin,ymargin,p,filltype,above);
}
//////////////////////////////////////////////////////

object
S=draw("S",circle,(0,0),xmargin=3mm,FillDraw(yellow,blue)),
I=draw("I",circle,(4cm,0),xmargin=3mm,FillDraw(yellow,blue)),
R=draw("R",circle,(2cm,3cm),xmargin=3mm,FillDraw(yellow,blue));

pair 
S1=point(S,E), I1=point(I,W),
I2=point(I,dir(120)), R1=point(R,dir(-60)),
R2=point(R,dir(-120)), S2=point(S,dir(60)),
R3=point(R,dir(-20)), I3=point(I,dir(70))
;

DefaultHead=TeXHead;
draw(S1--I1,red,Arrow());
draw(I2--R1,red,Arrow());
draw(R2--S2,red,Arrow());
draw(R3 .. controls  R3+1cm*dir(0) and  I3+1cm*dir(70) .. I3,red,Arrow());

add(bbox(5mm));

相关内容