# Errors with Asymptote

I am trying to draw a simple tetrahedron with the following code (in Asymptote)

``````size(10cm,0);
import math;
import three;
import graph3;
currentprojection=perspective(1/3,-1,1/2);

real l2=sqrt(0.75);
triple x1=(0,0,0), x2=(1,0,0), x3=(0.5,l2,0);
draw(x1--x2--x3--cycle);
label("\$x_1\$",x1,W);
label("\$x_2\$",x2,E);
label("\$x_3\$",x3,NW);
dot(x1);dot(x2);dot(x3);

triple b3=(0.5,l2/2,0);
dot(b3,red);
label("\$B_3\$",b3,S,red);

real l3=sqrt( (5+4*l2*l2)/9 );
triple x4=(0.5,l2/2,l3);
draw(b3--x4,red);
label("\$x_4\$",x4,N,red);

draw(x4--x1,dashed);
draw(x4--x2,dashed);
draw(x4--x3,dashed);
``````

Compiling with `asy tetrahedron.asy` gives me an `eps` image in which the line `x1--x2` is dashed for some reason, and compiling with `asy tetrahedron.asy -tex pdflatex` gives me a blank image. `tex.SE` doesn't allow me to upload images in either format, but I can share them with any other tool that users may request. Just post a comment with the tool I should use.

Any help would be greatly appreciated, to understand why I'm getting these errors, and/or how I could fix my script.

• I don't think it's dashed - I think the jaggies are just an artefact of the way the 3d line is rendered. Nov 14, 2014 at 16:25
• @Thruston It's quite strange that lines are drawn with segments. Nov 14, 2014 at 16:32
• Thanks for including the figure :) Alright then, but this doesn't explain why Asymptote doesn't produce a pdf output. `epstopdf` does work though, so maybe I will just use this. Nov 14, 2014 at 16:32
• @egreg If you look at the eps files produced by Asymptote they contain rendered images, rather than PS drawing commands. (At least they do on my TL2014 system). I'm not expert enough in Asymptote to know if this behaviour can be changed. It does seem like a rather basic limitation. Nov 14, 2014 at 16:37
• What I don't understand is that the PDF is blank if I run `asy -f pdf tetra.asy` unless I open it with Adobe Reader. Nov 14, 2014 at 16:48

The line is not dashed, it's just rendered like that. With the `three` module, Asymptote produces raster output rather than vector output. You can increase the resolution (and slow down the time it takes to do the rendering) with the `-render` option. The default value is 2 for `eps` output. Your drawing looks better on my system, if I turn the viewing angle slightly and compile with `asy -render 7`. Here it is using

``````currentprojection=perspective(1,-1,1/2);
``````

and converted using OSX Preview to `png` at 142 pixels per inch.

If you would rather have proper vector output, then you should probably use `pstricks`, which does 3D very well (although most of the documentation is only in French). Metapost is another alternative that produces vector PostScript but there's no standard approach to 3D. You could try mp3d or mp-solid, but for something as simple as your tetrahedron however all you need is a routine to project a 3D point to a 2D one. Like this:

``````prologues := 3;
outputtemplate := "%j%c.eps";

vardef pp(expr xx,yy,zz) =
_x := yy*cosd(theta) - xx*sind(theta);
_y := zz*cosd(phi) - yy*sind(theta)*sind(phi) - xx*cosd(theta)*sind(phi);
_z := 12 - zz*sind(phi) - yy*sind(theta)*cosd(phi) - xx*cosd(theta)*cosd(phi);
1000*(_x/_z, _y/_z)
enddef;

theta := 288; % rotation of viewpoint
phi := 18;    % elevation of viewpoint

beginfig(1);

z0 = pp(0,0,0);
z1 = pp(-sqrt(3)/2, -1/2, 0);
z2 = pp(+sqrt(3)/2, -1/2, 0);
z3 = pp(0,1,0);
z4 = pp(0,0,sqrt(2));

draw z1--z2--z3--cycle;
draw z0 -- z4 withcolor .67 red;
draw z1 -- z4 dashed evenly scaled .7;
draw z2 -- z4 dashed evenly scaled .7;
draw z3 -- z4 dashed evenly scaled .7;

dotlabel.lft (btex \$x_1\$ etex, z1);
dotlabel.rt  (btex \$x_2\$ etex, z2);
dotlabel.ulft(btex \$x_3\$ etex scaled .8, z3);
dotlabel.top (btex \$x_4\$ etex, z4);
dotlabel.rt  (btex \$B_3\$ etex, z0) withcolor .67 red;

endfig;
end.
``````

The advantages are (a) it's very simple and fast and (b) it's proper vector output, so there are no jagged edges. But that's about it; PSTricks or Asymptote will do a better job at more or less every other aspect of 3D drawing.

• Thank you very much :) I copied `import three;` blindly thinking that it was required to generate 3D figures, but I removed it now. Changing the perspective also eliminates the dashing effect. The option `-tex pdflatex` still generates a blank PDF, unless opened with AcroRead as egreg pointed out. Weird, but I can use `epstopdf` on the `eps` output instead. Many thanks! Nov 14, 2014 at 17:02
• `three.asy' is the basis of 3D routines and in fact `graph3.asy` imports `three.asy`.
– O.G.
Nov 14, 2014 at 20:56

According to the documentation of Asymptote, you have 3 (or 4) different ways to deal with the 3D

• OpenGL based renderer : `-V` option. An OpenGL window is opened with your 3D scene, interactive manipulation (changing the point of view, show camera), export (bitmap)
• with the previous OpenGL renderer, `-render=n` n pixels per bitmap, png, pdf, eps output. Some problems occurs with some opengl drivers/graphic cards (like vertical lines)
• `render=0` : the very old 3D mode of Asymptote. Only a 2D projection of the 3D scene, no algorithm to deal with hidden faces. But vectorized output

For such an example or a very simple 3D scene for which you can manage by yourself hidden faces, dashed segments, `asy -render=0` gives a vectorised output. Of course `-render=0` is very limited for 3D (I remember some asy package for solids to manage dashed/not dashed segment with respect to the camera).

• I tried the option `-render=0`, it didn't work. Nov 17, 2014 at 12:52
• Could you precise in which sense it didn't work ?
– O.G.
Nov 17, 2014 at 13:55
• This is why I included the link; compare the image to the OP. There seems to be something going wrong with the perspective. Nov 17, 2014 at 16:02
• So try `Try `currentprojection=perspective( camera=(0.588713035976962,-2.00929053352262,0.850671117466611), up=(-3.38734229622102e-05,0.000822063916635694,0.0046026371920217), target=(0.488713035976961,0.417579397965576,0.416478835962233), zoom=1, angle=27.0219146440952);`
– O.G.
Nov 17, 2014 at 16:30
• Perhaps I was not clear. Because choosing appropriate parameters for the perspective could be difficult, it is possible to launch `asy -V`, then with the OpenGL renderer you can change the point of view, {x,y,z}rotate, etc and at last show the perspective parameters with the 'c' keyboard (or the menu). Copy this parameters (like I did) and with `asy -render=0 -f pdf` you will have the same view.
– O.G.
Nov 17, 2014 at 20:29

I clean the code of this old post. A `transform3` that projects in the direction `dir` onto the plane with normal `n` through point `O` is returned by

``````transform3 planeproject(triple n, triple O=O, triple dir=n);
``````

One can use `normal(path3 p)` to find the unit normal vector to a planar three-dimensional path `p`. A `transform3` that projects in the direction `dir` onto the plane defined by a planar path `p` is returned by

``````transform3 planeproject(path3 p, triple dir=normal(p));
``````

In this case, to get the orthogonal projection of the vertex `x4` (consider as a special `path3`) on the base plane `x1--x2--x3`, we use

``````path3 base=x1--x2--x3;
triple b3=planeproject(base,normal(base))*x4;
``````

``````// http://asymptote.ualberta.ca/
unitsize(1cm);
import three;
size(6cm);
currentprojection=perspective(1/3,-1,1/2);
real l2=sqrt(0.75);
real l3=sqrt( (5+4*l2*l2)/9 );
triple x1=(0,0,0), x2=(1,0,0), x3=(0.5,l2,0), x4=(0.5,l2/2,l3);

path3 base=x1--x2--x3;
triple b3=planeproject(base,normal(base))*x4;

draw(x4--x1^^x4--x2^^x4--x3,dashed);
draw(b3--x4,red);
draw(x1--x2--x3--cycle);

dot("\$x_1\$",x1,W);
dot("\$x_2\$",x2,E);
dot("\$x_3\$",x3,E);
dot("\$x_4\$",x4,N);
dot("\$B_3\$",b3,S,red);
``````