# Symmetric Arrowhead in 3d Asymptote Plot

I am making a simple 3d plot with asymptote and would like to have a nice arrow in the plot. I did manage to get an arrow in there, but it looks very asymmetric. I wish the top and bottom side of the arrow would have the same line width. Any ideas of how to accomplish that? This image was generated with the following code:

``````settings.outformat = "png";
settings.render = 10;
settings.prc = false;
unitsize(1.0cm);
import three;
real width = 2.7;
real height = 1.6;
real depth = 1.2;
real lw = 2; //linewidth
currentprojection = obliqueX;

//define matplotlib default colors
pen C0 = RGB(31,119,180);
pen C3 = RGB(214,39,40);

//draw box
draw((0,0,0) -- (0,0,-height), C0+dashed+linewidth(lw));
draw((0,0,-height) -- (0,4*width,-height), C0+dashed+linewidth(lw));
draw((0,0,-height) -- (depth,0,-height), C0+dashed+linewidth(lw));
draw((0,0,0) -- (0,4*width,0), C0+linewidth(lw));
draw((depth,0,0) -- (0,0,0), C0+linewidth(lw));
draw((depth,0,-height) -- (depth,4*width,-height) -- (depth,4*width,0) -- (depth,0,0) -- (depth,0,-height), C0+linewidth(lw));
draw((depth,4*width,-height) -- (0,4*width,-height) -- (0,4*width,0) -- (depth,4*width,0), C0+linewidth(lw));
label("Box", (depth, 2*width, -0.40*height),C0);

//draw axis arrows
real axisZshift = -2.4;
real axisXshift = 0.2;
real axisLength = 1.0;
draw((0,axisZshift,axisXshift)--(-axisLength,axisZshift,axisXshift), arrow=Arrow3(TeXHead2(normal=Y)), L=Label("\$z\$", position=EndPoint, align=N+E));
draw((0,axisZshift,axisXshift)--(0,axisZshift,axisXshift+axisLength), arrow=Arrow3(TeXHead2(normal=X)), L=Label("\$x\$", position=EndPoint, align=N));
draw((0,axisZshift,axisXshift)--(0,axisZshift+axisLength,axisXshift), arrow=Arrow3(TeXHead2(normal=X)), L=Label("\$y\$", position=EndPoint, align=E));

//draw red arrow
draw((depth, 3.5*width, 1.5*height) -- (depth, 0.5*width, 1.5*height), arrow=Arrow3(TeXHead2, emissive(C3)), L=Label("red arrow", position=MidPoint, align=N), C3+linewidth(2*lw));
``````

## 1 Answer

One way is to use a `2D` arrows and `2D` projection instead, by means of `project()` function:

``````settings.outformat = "png";
settings.render = 10;
settings.prc = false;
unitsize(1.0cm);
import three;
real width = 2.7;
real height = 1.6;
real depth = 1.2;
real lw = 2; //linewidth

currentprojection = obliqueX;

//define matplotlib default colors
pen C0 = RGB(31,119,180);
pen C3 = RGB(214,39,40);

//draw box
draw(project((0,0,0) -- (0,0,-height)            ), C0+dashed+linewidth(lw));
draw(project((0,0,-height) -- (0,4*width,-height)), C0+dashed+linewidth(lw));
draw(project((0,0,-height) -- (depth,0,-height)  ), C0+dashed+linewidth(lw));
draw(project((0,0,0) -- (0,4*width,0)            ), C0+linewidth(lw));
draw(project((depth,0,0) -- (0,0,0)              ), C0+linewidth(lw));
draw(project((depth,0,-height) -- (depth,4*width,-height) -- (depth,4*width,0) -- (depth,0,0) -- (depth,0,-height)), C0+linewidth(lw));
draw(project((depth,4*width,-height) -- (0,4*width,-height) -- (0,4*width,0) -- (depth,4*width,0)), C0+linewidth(lw));
label("Box", project((depth, 2*width, -0.40*height)),C0);

//draw axis arrows
real axisZshift = -2.4;
real axisXshift = 0.2;
real axisLength = 1.0;
draw(project((0,axisZshift,axisXshift)--(-axisLength,axisZshift,axisXshift )), arrow=Arrow(TeXHead), L=Label("\$z\$", position=EndPoint, align=N+E));
draw(project((0,axisZshift,axisXshift)--(0,axisZshift,axisXshift+axisLength)), arrow=Arrow(TeXHead), L=Label("\$x\$", position=EndPoint, align=N));
draw(project((0,axisZshift,axisXshift)--(0,axisZshift+axisLength,axisXshift)), arrow=Arrow(TeXHead), L=Label("\$y\$", position=EndPoint, align=E));

//draw red arrow
draw(project((depth, 3.5*width, 1.5*height) -- (depth, 0.5*width, 1.5*height)), arrow=Arrow(TeXHead), L=Label("red arrow", position=MidPoint, align=N), C3+linewidth(2*lw));
`````` To simplify the process, you can also define some functions like

``````void draw(guide3 g, pen p){
draw(project(g),p);
};
``````

Then , for example, the commands like

``````draw((0,0,0) -- (0,0,-height), C0+dashed+linewidth(lw));
``````

will draw a projection automatically.

• Thanks a lot, it sure looks beautiful! However, it also means that I need to project everything, which can be a bit cumbersome in larger projects, even with your great `void draw(...)` example. So I will wait a bit longer to see if someone has a simpler answer before accepting your helpful answer. – laolux Nov 18 '20 at 7:30
• So, I got it to work in a larger example, but it is very unfortunate that `project(...)` does not work together with 3d stuff. So, I need to rearrange my figures according to what gets drawn behind what, as projected figures will not take into account 3 dimensionality anymore. :-| – laolux Nov 19 '20 at 3:18