[Tex/LaTex] Planes’ intersection in Asymptote

3dasymptoteintersectionslabels

I have made a picture:
enter image description here

The code:

\documentclass{article}
\usepackage{asymptote}
\begin{document}
\begin{asy}
//================ Format =================
settings.outformat = "pdf";
settings.prc = false;  
settings.render = 0;   
import three;
import bsp;
texpreamble("\usepackage{euler,beton}");
size(5cm, 0);
currentprojection=orthographic((5,4,3));
//================ Drawing ===================
path3 pl =plane((0,-2,0),(-2,0,0),(0,1,0));
path3 pl1=rotate(-28,X)*pl;
path3 pl2=rotate(-56,X)*pl;
path3 pl3=shift(-0.3*normal(pl1))*pl1;

triple[] asd=intersectionpoints(pl2,pl3);
triple A=asd[1];
triple B=asd[0];


triple[] asf=intersectionpoints(pl,pl2);
triple C=asf[1];
triple D=asf[0];


triple[] asg=intersectionpoints(pl,pl3);
triple E=asg[1];
triple F=asg[0];


face[] faces;

filldraw(faces.push(pl),project(pl),  white+opacity(0.6));
filldraw(faces.push(pl1),project(pl1),white+opacity(0.6));
filldraw(faces.push(pl2),project(pl2),white+opacity(0.6));
filldraw(faces.push(pl3),project(pl3),white+opacity(0.6));
add(faces);


draw(B--A);
draw(C--D);
draw(E--F);

dot(A,red); 
dot(B,red); 
dot(C,red); 
dot(D,red); 
dot(E,red); 
dot(F,red); 

\end{asy}

If I add the following labeling at the very end of the code above:

label("$A$",A,S);
label("$B$",B,S);
label("$C$",C,S);
label("$D$",D,S);
label("$E$",E,S);
label("$F$",F,S);
\end{asy}


\end{document}

Asymptote produses this:
enter image description here

Question #1: Why does it shift the points?

Question #2: How to make the line CD be "covered" by the plane? So, I want it to look like the invisible edges of the planes: not the whole CD, but the only invisible part of it.

Best Answer

Note that I know nothing about Asymptote.

Caveat emptor ...

This answer is almost exclusively drawn from Charles Staats's fantastic tutorial and the interested reader is encouraged to look there for further details and more correct advice!

If you use settings.render=0, then Asymptote draws things in the order they are given i.e. pretty much as if we were in 2D TikZ. So, setting settings.render to some other value is required for the plane to 'cover' stuff layered below.

These should also probably really be surfaces, I guess, perhaps with no light.

\documentclass{article}
\usepackage{asymptote}
\begin{document}
\begin{asy}
settings.outformat = "pdf";
settings.prc = false;
settings.render = 16;
import three;
import bsp;
texpreamble("\usepackage{euler,beton}");
size(5cm, 0);
currentprojection=orthographic((5,4,3));

path3 pl =plane((0,-2,0),(-2,0,0),(0,1,0));
path3 pl1=rotate(-28,X)*pl;
path3 pl2=rotate(-56,X)*pl;
path3 pl3=shift(-0.3*normal(pl1))*pl1;

draw (pl);
draw (pl1);
draw (pl2);
draw (pl3);

triple[] asd=intersectionpoints(pl2,pl3);
triple A=asd[1];
triple B=asd[0];

triple[] asf=intersectionpoints(pl,pl2);
triple C=asf[1];
triple D=asf[0];

triple[] asg=intersectionpoints(pl,pl3);
triple E=asg[1];
triple F=asg[0];

surface s1=surface(pl);
draw(s1,white+opacity(.6),light=nolight);
surface s2=surface(pl1);
draw(s2,white+opacity(.6),light=nolight);
surface s3=surface(pl2);
draw(s3,white+opacity(.6),light=nolight);
surface s4=surface(pl3);
draw(s4,white+opacity(.6),light=nolight);


draw(B--A);
draw(C--D);
draw(E--F);

dot(A,red);
dot(B,red);
dot(C,red);
dot(D,red);
dot(E,red);
dot(F,red);

//From Charles Staats's tutorial
//Direction of a point toward the camera.
triple cameradirection(triple pt, projection P=currentprojection) {
  if (P.infinity) {
    return unit(P.camera);
  } else {
    return unit(P.camera - pt);
  }
}

//Move a point closer to the camera.
triple towardcamera(triple pt, real distance=1, projection P=currentprojection) {
  return pt + distance * cameradirection(pt, P);
}

label("$A$",align=NE,position=towardcamera((A)));
label("$B$",align=S,position=towardcamera((B)));
label("$C$",align=SE,position=towardcamera((C)));
label("$D$",align=SE,position=towardcamera((D)));
label("$E$",align=NE,position=towardcamera((E)));
label("$F$",align=S,position=towardcamera((F)));
\end{asy}


\end{document}

rendered output

EDIT

If you simply must have vector graphics - a restriction which was not mentioned in the question - then you need to take care of the drawing order yourself. This requires splitting each surface into pieces and reassembling them according to their position relative to other pieces.

Here is an example rendered with settings.render=0 to ensure vector output.

vector versions

The diagram on the right uses colouring to demonstrate that the drawing order is (as far as I can tell) correct. The version on the left is identical except that it uses white in place of the colours for the surfaces and does not specify a colour for the drawn outlines.

\documentclass{article}
\usepackage{asymptote}
\begin{document}
\begin{asy}
settings.outformat = "pdf";
settings.prc = false;
settings.render = 0;
import three;
import bsp;
texpreamble("\usepackage{euler,beton}");
size(5cm, 0);
currentprojection=orthographic((5,4,3));

path3 pl =plane((0,-2,0),(-2,0,0),(0,1,0));
path3 pl1=rotate(-28,X)*pl;
path3 pl2=rotate(-56,X)*pl;
path3 pl3=shift(-0.3*normal(pl1))*pl1;

triple[] asd=intersectionpoints(pl2,pl3);
triple A=asd[1];
triple B=asd[0];

triple[] asf=intersectionpoints(pl,pl2);
triple C=asf[1];
triple D=asf[0];

triple[] asg=intersectionpoints(pl,pl3);
triple E=asg[1];
triple F=asg[0];

path3 q11=(D -- -Y -- C-Y -- C -- cycle);
surface sq11=surface(q11);
draw(sq11,white+opacity(.6),light=nolight);
draw(D -- -Y -- C-Y -- C--cycle);

path3 q21=rotate(-28,X)*q11;
surface sq21=surface(q21);
draw(sq21,white+opacity(.6),light=nolight);
draw(rotate(-28,X)*(D -- -Y -- C-Y -- C -- cycle));

path3 q31=(D--C--A--B--cycle);
surface sq31=surface(q31);
draw(sq31,white+opacity(.6),light=nolight);
draw(D--C--A--B--cycle);

path3 q34=(C -- D -- rotate(-56,X)*(D+Y) -- rotate(-56,X)*(C+Y) -- cycle);
surface sq34=surface(q34);
draw(sq34,white+opacity(.6),light=nolight);
draw(C -- D -- rotate(-56,X)*(D+Y) -- rotate(-56,X)*(C+Y) -- cycle);

path3 q22=(C -- D -- rotate(-28,X)*(D+Y) -- rotate(-28,X)*(C+Y) -- cycle);
surface sq22=surface(q22);
draw(sq22,white+opacity(.6),light=nolight);
draw(C -- D -- rotate(-28,X)*(D+Y) -- rotate(-28,X)*(C+Y) -- cycle);

path3 q12=(D -- C -- E -- F -- cycle);
surface sq12=surface(q12);
draw(sq12,white+opacity(.6),light=nolight);
draw(q12);

surface s4=surface(pl3);
draw(s4,white+opacity(.6),light=nolight);
draw(pl3);

path3 q32=(rotate(-56,X)*(D-Y) -- rotate(-56,X)*(C-Y) -- A -- B -- cycle);
surface sq32=surface(q32);
draw(sq32,white+opacity(.6),light=nolight);
draw(rotate(-56,X)*(D-Y) -- rotate(-56,X)*(C-Y) -- A -- B -- cycle);

path3 q13=(Y -- C+Y -- E -- F -- cycle);
surface sq13=surface(q13);
draw(sq13,white+opacity(.6),light=nolight);
draw(Y -- C+Y -- E -- F -- cycle);

dot(A,red);
dot(B,red);
dot(C,red);
dot(D,red);
dot(E,red);
dot(F,red);

//From Charles Staats's tutorial
//Direction of a point toward the camera.
triple cameradirection(triple pt, projection P=currentprojection) {
  if (P.infinity) {
    return unit(P.camera);
  } else {
    return unit(P.camera - pt);
  }
}

//Move a point closer to the camera.
triple towardcamera(triple pt, real distance=1, projection P=currentprojection) {
  return pt + distance * cameradirection(pt, P);
}

label("$A$",align=NE,position=towardcamera((A)));
label("$B$",align=S,position=towardcamera((B)));
label("$C$",align=SE,position=towardcamera((C)));
label("$D$",align=SW,position=towardcamera((D)));
label("$E$",align=NE,position=towardcamera((E)));
label("$F$",align=S,position=towardcamera((F)));
\end{asy}
\begin{asy}
settings.outformat = "pdf";
settings.prc = false;
settings.render = 0;
import three;
import bsp;
texpreamble("\usepackage{euler,beton}");
size(5cm, 0);
currentprojection=orthographic((5,4,3));

path3 pl =plane((0,-2,0),(-2,0,0),(0,1,0));
path3 pl1=rotate(-28,X)*pl;
path3 pl2=rotate(-56,X)*pl;
path3 pl3=shift(-0.3*normal(pl1))*pl1;

triple[] asd=intersectionpoints(pl2,pl3);
triple A=asd[1];
triple B=asd[0];

triple[] asf=intersectionpoints(pl,pl2);
triple C=asf[1];
triple D=asf[0];

triple[] asg=intersectionpoints(pl,pl3);
triple E=asg[1];
triple F=asg[0];

path3 q11=(D -- -Y -- C-Y -- C -- cycle);
surface sq11=surface(q11);
draw(sq11,red+opacity(.6),light=nolight);
draw(D -- -Y -- C-Y -- C--cycle,red);

path3 q21=rotate(-28,X)*q11;
surface sq21=surface(q21);
draw(sq21,blue+opacity(.6),light=nolight);
draw(rotate(-28,X)*(D -- -Y -- C-Y -- C -- cycle),blue);

path3 q31=(D--C--A--B--cycle);
surface sq31=surface(q31);
draw(sq31,green+opacity(.6),light=nolight);
draw(D--C--A--B--cycle,green);

path3 q34=(C -- D -- rotate(-56,X)*(D+Y) -- rotate(-56,X)*(C+Y) -- cycle);
surface sq34=surface(q34);
draw(sq34,green+opacity(.6),light=nolight);
draw(C -- D -- rotate(-56,X)*(D+Y) -- rotate(-56,X)*(C+Y) -- cycle,green);

path3 q22=(C -- D -- rotate(-28,X)*(D+Y) -- rotate(-28,X)*(C+Y) -- cycle);
surface sq22=surface(q22);
draw(sq22,blue+opacity(.6),light=nolight);
draw(C -- D -- rotate(-28,X)*(D+Y) -- rotate(-28,X)*(C+Y) -- cycle,blue);

path3 q12=(D -- C -- E -- F -- cycle);
surface sq12=surface(q12);
draw(sq12,red+opacity(.6),light=nolight);
draw(q12,red);

surface s4=surface(pl3);
draw(s4,yellow+opacity(.6),light=nolight);
draw(pl3,yellow);

path3 q32=(rotate(-56,X)*(D-Y) -- rotate(-56,X)*(C-Y) -- A -- B -- cycle);
surface sq32=surface(q32);
draw(sq32,green+opacity(.6),light=nolight);
draw(rotate(-56,X)*(D-Y) -- rotate(-56,X)*(C-Y) -- A -- B -- cycle,green);

path3 q13=(Y -- C+Y -- E -- F -- cycle);
surface sq13=surface(q13);
draw(sq13,red+opacity(.6),light=nolight);
draw(Y -- C+Y -- E -- F -- cycle,red);

dot(A,red);
dot(B,red);
dot(C,red);
dot(D,red);
dot(E,red);
dot(F,red);

//From Charles Staats's tutorial
//Direction of a point toward the camera.
triple cameradirection(triple pt, projection P=currentprojection) {
  if (P.infinity) {
    return unit(P.camera);
  } else {
    return unit(P.camera - pt);
  }
}

//Move a point closer to the camera.
triple towardcamera(triple pt, real distance=1, projection P=currentprojection) {
  return pt + distance * cameradirection(pt, P);
}

label("$A$",align=NE,position=towardcamera((A)));
label("$B$",align=S,position=towardcamera((B)));
label("$C$",align=SE,position=towardcamera((C)));
label("$D$",align=SW,position=towardcamera((D)));
label("$E$",align=NE,position=towardcamera((E)));
label("$F$",align=S,position=towardcamera((F)));
\end{asy}
\end{document}
Related Question