5

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

7
  • Great question! If someone comes up with an answer, I'll incorporate the technique into the tutorial (with credit). Commented 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). Commented 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.
    – Thruston
    Commented May 9, 2015 at 12:42
  • 1
    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?
    – Thruston
    Commented 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.
    – Hanmyo
    Commented May 11, 2015 at 0:01

1 Answer 1

5

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

cylinder with two points labeled a and b, the farther label appearing much smaller

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

cylinder with two points labeled a and b, both labels appearing the same size

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.

1
  • 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!
    – Hanmyo
    Commented May 15, 2015 at 8:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .