如何在 Asymptote 中根据公式的各个部分制作箭头?(或者:测量标签的宽度,在标签周围获取锚点)

如何在 Asymptote 中根据公式的各个部分制作箭头?(或者:测量标签的宽度,在标签周围获取锚点)

总结一下:我想在Asymptote中画出下面的图形。

图像

我的代码如下。

size(5cm);
draw(scale(8, 4)*unitsquare);
label("$\underbrace{123}+\underbrace{456}=\underbrace{789}$", (4, 3));
draw((2.1, 2.5)--(1, 1), Arrow);
draw((3.95, 2.5)--(4, 1), Arrow);
draw((5.9, 2.5)--(7, 1), Arrow);
label("\strut$a$", (1, 1.1), S);
label("\strut$b$", (4, 1.1), S);
label("\strut$c$", (7, 1.1), S); // \strut is used to make the baselines horizontally aligned.

问题:在这 3draw行中,箭头起点的 x 坐标是硬编码的。

我怎样才能根据下支撑尖端的位置自动计算箭头起点的位置?

(能够计算标签的宽度会有所帮助,但我也不知道该怎么做。)

tikzmark与以下功能类似的功能https://tex.stackexchange.com/a/145696/250119会有所帮助,但我不知道 Asymptote 中有任何这样的功能。

答案1

部分解决方案。部分改编自https://sourceforge.net/p/asymptote/discussion/409349/thread/3fc73fb8/

如果你仔细想想,标签相对于用户坐标的大小直到程序的最后才确定——这肯定会导致问题。所以,这只是一个部分解决方案,它假设unitsize是固定的

基本上,它构造 5 个标签对象,然后将每个对象放入picture,然后用测量其大小min()/max()/size()以确定框底边的中点。

注意,为了使等min()返回正确的值,unitsize()子图片的设置必须正确。

很遗憾,这种方法破坏了间距--- 我不确定如何修复它。

var unitsize=1cm;
unitsize(unitsize);

string template="$\underbrace{1}$";

picture a;
unitsize(a, unitsize);
// draw the labels, and compute the coordinate of the bottom points along the way
label(a, baseline("$\underbrace{123}$", template), (0, 0), align=NE);
pair bottom1=((min(a, user=true).x+max(a, user=true).x)/2, min(a, user=true).y);
label(a, baseline("$+$", template), (max(a, user=true).x, 0), align=NE);
real u=max(a, user=true).x;
label(a, baseline("$\underbrace{456}$", template), (max(a, user=true).x, 0), align=NE);
pair bottom2=((u+max(a, user=true).x)/2, min(a, user=true).y);
label(a, baseline("$=$", template), (max(a, user=true).x, 0), align=NE);
real u=max(a, user=true).x;
label(a, baseline("$\underbrace{789}$", template), (max(a, user=true).x, 0), align=NE);
pair bottom3=((u+max(a, user=true).x)/2, min(a, user=true).y);

// compute shift such that the text is centered at x = 4
pair ashift=(4-size(a, user=true).x/2, 3);

// draw the text on currentpicture
add(shift(ashift)*a);

// some other text for comparison
label("$\underbrace{123}+\underbrace{456}=\underbrace{789}$", (4, 4), align=N);
label("$123+456=789$", (4, 5), align=N);

// draw the arrows
draw(ashift+bottom1--(1, 1), Arrow);
draw(ashift+bottom2--(4, 1), Arrow);
draw(ashift+bottom3--(7, 1), Arrow);
label(baseline("$a$"), (1, 1.1), S);
label(baseline("$b$"), (4, 1.1), S);
label(baseline("$c$"), (7, 1.1), S);

输出:渐近线输出

相关内容