1

In summary: I want to draw the following figure in Asymptote.

image

My code is as follows.

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.

Problem: In the 3 draw lines, the x-coordinate of the starting point of the arrows are hard coded.

How can I automatically compute the location of the start of the arrow from the position of the tip of the underbrace?

(being able to compute the width of the label would help, but I can't see how either.)

Something similar to the tikzmark feature shown in https://tex.stackexchange.com/a/145696/250119 would help, but I'm unaware of any such feature in Asymptote.

user202729
  • 7,143

1 Answers1

1

Partial solution. Somewhat adapted from https://sourceforge.net/p/asymptote/discussion/409349/thread/3fc73fb8/ .

If you think about it, the size of the label relative to user coordinate is not determined until the very end of the program --- which definitely causes a problem. So, this is only a partial solution that it assumes unitsize is fixed.

Basically, it constructs 5 label objects, then for each object it is put into a picture, then its size is measured with min()/max()/size() in order to determine the midpoint of the bottom edge of the box.

Note that in order to make min() etc. return correct value, unitsize() of the sub-picture must be set correctly.

Unfortunately, this method disrupts the spacing --- I'm not sure how it can be fixed.

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);

Output: asymptote output

user202729
  • 7,143