# Asymptote: prevent label scaling in 3d perspective

Is there a simple way to prevent labels from scaling based on their distance to the camera in a `perspective` 3d view? (For example, see the first comment on this question or page 65 of this tutorial.)

Edit: I'm using rasterized (settings.render != 0) because with settings.render=0 the order of the commands (rather than the mathematical equations) dictates which objects are in front (see page 54 in the tutorial).

• Great question! If someone comes up with an answer, I'll incorporate the technique into the tutorial (with credit). May 9, 2015 at 3:01
• In my own work, the only "solution" I've found is to put the camera far enough away that the difference is not instantly obvious (or else use an orthographic projection, which essentially puts the camera at infinity). May 9, 2015 at 3:03
• I seem to recall that if you use the command line option `-render 0` it does three-D as vectors with no scaling. This might help with the labels, but perhaps won't make the lines look as good. May 9, 2015 at 12:42
• As quick experiment at this end confirms that if you use the command line option `-render 0` the label scaling is disabled and all the lines are drawn as simple vectors rather than rendered as proper 3D lines. Does this do what you want? May 9, 2015 at 12:48
• @Thruston Interesting, that does seem to keep the labels all the same size. It also makes it so that it uses vector graphics rather than rasterized. Unfortunately that option makes it so that things are printed in the order of the commands rather than how they should actually appear and intersect, so I'm having to use rasterized. I'll edit my question to reflect this. May 11, 2015 at 0:01

I've just realized that there is, in fact, a simple solution. First, a demonstration of what happens normally (a MWE if you will):

``````settings.outformat="png";
settings.render=4;
import three;
size(4cm);

currentprojection = perspective(2,0.7,0.8);

path3 thecircle = circle(c=X, r=0.5, normal=X);
surface cyl = extrude(thecircle, -2X);

draw(cyl, surfacepen=white);
dot((1,0.5,0), L=Label("\$a\$", align=E));
dot((-1,0.5,0), L=Label("\$b\$", align=E));
`````` If we add the labels using a `label` command rather than the `dot` command, then there is a parameter called `interaction` that comes to the rescue. An interaction, defined in `three_surface.asy`, is created with the constructor

``````interaction(int type, bool targetsize=false);
``````

The parameter we really care about is the second one, `targetsize`; if it's `true`, then the labels are rescaled so that they appear the same size from the current point of view (and look very strange from any other point of view). The first parameter determines whether the labels rotate to face the viewer in interactive view: `1` if they do, `0` if they don't.

Thus, the following code gives the desired result (although the interactive view is not good):

``````settings.outformat="png";
settings.render=4;
import three;
size(4cm);

currentprojection = perspective(2,0.7,0.8);

path3 thecircle = circle(c=X, r=0.5, normal=X);
surface cyl = extrude(thecircle, -2X);

draw(cyl, surfacepen=white);

interaction constantsize = settings.autobillboard ? interaction(1,true) : interaction(0,true);

dot((1,0.5,0) ^^ (-1,0.5,0));
label(position=(1,0.5,0), L=Label("\$a\$", align=E), constantsize);
label(position=(-1,0.5,0), L=Label("\$b\$", align=E), constantsize);
`````` Note that the camera is actually in a slightly different position since it does not have to move to keep the larger `a` within view.

• very cool, thank you! I think in interactive mode it's fine to have scaling labels with camera view, but this is definitely a great simple solution for the non-interactive versions! May 15, 2015 at 8:21