How can I draw the point is intersection of a plane and a line?

Let SOAB be a pypamid with OAB is an equilateral triangle and SO perpendicular to the plane OAB. The plane passing through O and perpendicular to the line SB cuts SB at M and SA at N. I tried

\documentclass[border=3mm,12pt,tikz]{standalone}
\usepackage{fouriernc}
\usepackage{tikz,tikz-3dplot}
\tikzset{projection of point/.style args={(#1,#2,#3) on line through (#4,#5,#6)
and (#7,#8,#9)}{%
/utils/exec=\pgfmathsetmacro{\myprefactor}{((#1-#4)*(#7-#4)+(#2-#5)*(#8-#5)+(#3-#6)*(#9-#6))/((#7-#4)*(#7-#4)+(#8-#5)*(#8-#5)+(#9-#6)*(#9-#6))},
insert path={%
({#4+\myprefactor*(#7-#4)},{#5+\myprefactor*(#8-#5)},{#6+\myprefactor*(#9-#6)})}
}}
\begin{document}
\tdplotsetmaincoords{60}{70}
\begin{tikzpicture}[tdplot_main_coords]
\pgfmathsetmacro\a{4}
\pgfmathsetmacro\h{5}
\path
coordinate(O) at (0,0,0)
coordinate (A) at (\a,0,0)
coordinate (B) at   (\a/2,{\a*sqrt(3)/2},0)
coordinate (S) at (0,0,\h)
;
\path[projection of point={(0,0,0) on line through (\a/2,{\a*sqrt(3)/2},0) and (0,0,\h)}]
coordinate  (M);
\draw (S) -- (O) -- (A) -- (B) -- cycle (S) -- (A);
\draw[dashed] (O) -- (B) (O) -- (M);
\foreach \point/\position in {A/below,B/right,O/below,S/above,M/above}
{\fill (\point) circle (1.5pt);
\node[\position=1.5pt] at (\point) {$\point$};
}
\end{tikzpicture}
\end{document}

I can not draw the point N. How can I draw it?

First way The coordinates of the point N is coordinate (N) at ({2*\h*\h*\a/(\a*\a + 2*\h*\h)}, 0,{\a*\a*\h/(\a*\a + 2*\h*\h)} )

\documentclass[border=3mm,12pt,tikz]{standalone}
\usepackage{fouriernc}
\usepackage{tikz,tikz-3dplot}
\tikzset{projection of point/.style args={(#1,#2,#3) on line through (#4,#5,#6)
and (#7,#8,#9)}{%
/utils/exec=\pgfmathsetmacro{\myprefactor}{((#1-#4)*(#7-#4)+(#2-#5)*(#8-#5)+(#3-#6)*(#9-#6))/((#7-#4)*(#7-#4)+(#8-#5)*(#8-#5)+(#9-#6)*(#9-#6))},
insert path={%
({#4+\myprefactor*(#7-#4)},{#5+\myprefactor*(#8-#5)},{#6+\myprefactor*(#9-#6)})}
}}
\begin{document}
\tdplotsetmaincoords{60}{70}
\begin{tikzpicture}[tdplot_main_coords]
\pgfmathsetmacro\a{4}
\pgfmathsetmacro\h{5}
\path
coordinate(O) at (0,0,0)
coordinate (A) at (\a,0,0)
coordinate (B) at   (\a/2,{\a*sqrt(3)/2},0)
coordinate (S) at (0,0,\h)
coordinate  (N) at ({2*\h*\h*\a/(\a*\a + 2*\h*\h)}, 0,{\a*\a*\h/(\a*\a + 2*\h*\h)} )
;
\path[projection of point={(0,0,0) on line through (\a/2,{\a*sqrt(3)/2},0) and (0,0,\h)}]
coordinate  (M);
\draw (S) -- (O) -- (A) -- (B) -- cycle (S) -- (A);
\draw[dashed] (O) -- (B) (O) -- (M);
\foreach \point/\position in {A/below,B/right,O/below,S/above,M/above,N/left}
{\fill (\point) circle (1.5pt);
\node[\position=1.5pt] at (\point) {$\point$};
}
\end{tikzpicture}
\end{document}

Second way

Calculate coordinates of two points M, N with Maple.

\documentclass[border=3mm,12pt,tikz]{standalone}
\usepackage{tikz-3dplot}
\begin{document}
\tdplotsetmaincoords{60}{70}
\begin{tikzpicture}[tdplot_main_coords]
\pgfmathsetmacro\a{4}
\pgfmathsetmacro\h{5}
\path
coordinate(O) at (0,0,0)
coordinate (A) at (\a,0,0)
coordinate (B) at   (\a/2,{\a*sqrt(3)/2},0)
coordinate (S) at (0,0,\h)
coordinate  (N) at ({2*\h*\h*\a/(\a*\a + 2*\h*\h)}, 0,{\a*\a*\h/(\a*\a + 2*\h*\h)} )
coordinate  (M) at  ({\h*\h*\a/(2*\a*\a + 2*\h*\h)}, {\h*\h*\a*sqrt(3)/(2*\a*\a + 2*\h*\h)},{\a*\a*\h/(\a*\a + \h*\h)} )
;
\draw (S) -- (O) -- (A) -- (B) -- cycle (S) -- (A);
\draw[dashed] (O) -- (B) (O) -- (M);
\foreach \point/\position in {A/below,B/right,O/below,S/above,N/right,M/right}
{\fill (\point) circle (1.5pt);
\node[\position=1.5pt] at (\point) {$\point$};
}
\end{tikzpicture}
\end{document}

Third way Use 3dtool The plane passing through the point O and perpendicular to the line SB take vector SB as normal vector. And then, you find two points M and N.

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{3dtools,calc}

\begin{document}
\begin{tikzpicture}[line cap=round,line join=round,c/.style={circle,fill,inner sep=1pt},
3d/install view={phi=70,theta=65},declare function={a=4;h=5;}]
\path
(0,0,0) coordinate (O)
(a,0,0) coordinate (A)
(a/2,{a*sqrt(3)/2},0) coordinate (B)
(0,0,h) coordinate (S)
[3d coordinate={(n)=(S)-(B)}]
;
\path[3d/plane with normal={(n) through (O) named p},
3d/line through={(S) and (A) named lSA},
3d/line through={(S) and (B) named lSB}];

\path[3d/intersection of={lSA with p}] coordinate (N);
\path[3d/intersection of={lSB with p}] coordinate (M);
\draw[3d/visible] (S) -- (O) -- (A) -- (B)--cycle (S) -- (A);
\draw[3d/hidden] (O) -- (B) (O) -- (M);

\path foreach \p/\g in {S/90,A/-90,B/-90,O/-90,M/0,N/180}
{(\p)node[c]{}+(\g:2.5mm) node{$\p$}};
\end{tikzpicture}
\end{document}

Or you can try

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{3dtools,calc}
\begin{document}
\foreach \Angle in {5,10,...,355}
{\begin{tikzpicture}[line cap=round,line join=round,c/.style={circle,fill,inner sep=1pt},
3d/install view={phi=\Angle,theta=65},declare function={a=4;h=5;},same bounding box=A]
\path
(0,0,0) coordinate (O)
(a,0,0) coordinate (A)
(a/2,{a*sqrt(3)/2},0) coordinate (B)
(0,0,h) coordinate (S)
[3d coordinate={(n)=(S)-(B)}]
;
\path[3d/plane with normal={(n) through (O) named p},
3d/line through={(S) and (A) named lSA},
3d/line through={(S) and (B) named lSB}];

\path[3d/intersection of={lSA with p}] coordinate (N);

\path[3d/intersection of={lSB with p}] coordinate (M);

\pgfmathsetmacro{\mybarycenter}{barycenter("(S),(O),(B),(A)")}
\path (\mybarycenter) coordinate (I);
\tikzset{3d/polyhedron/.cd,O={(I)},fore/.append style={fill=none},
back/.append style={3d/hidden},
draw face with corners={{(S)},{(O)},{(N)}},
draw face with corners={{(O)},{(A)},{(N)}},
draw face with corners={{(S)},{(M)},{(N)}},
draw face with corners={{(A)},{(B)},{(M)},{(N)}},
draw face with corners={{(A)},{(B)},{(O)}},
draw face with corners={{(S)},{(M)},{(O)}},
draw  face with corners={{(B)},{(M)},{(O)}}}
\path foreach \p/\g in {S/90,A/-90,B/-90,O/-90,M/0,N/180}
{(\p)node[c]{}+(\g:2.5mm) node{$\p$}};
\end{tikzpicture}}
\end{document}

One way to draw the point N Let Ebe midpoint of segment OB; I is intersection of two lines SE and OM, then IN parallel to AE.

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{3dtools,calc}
\begin{document}
\begin{tikzpicture}[line cap=round,line join=round,c/.style={circle,fill,inner sep=1pt},
3d/install view={phi=75,theta=65},declare function={a=4;h=5;}]
\path
(0,0,0) coordinate (O)
(a,0,0) coordinate (A)
(a/2,{a*sqrt(3)/2},0) coordinate (B)
(0,0,h) coordinate (S)
[3d coordinate={(E)=0.5*(O)+0.5*(B) }];
\path[
3d/line through={(S) and (A) named lSA},
3d/line through={(S) and (B) named lSB},
3d/line through={(S) and (E) named lSE}];
\path [3d/project={(O) on lSB}] coordinate (M);
\path [3d/line through={(O) and (M) named lOM}];

\path[3d/intersection of={lOM with lSE}] coordinate (I);

\path[3d/line with direction={(A) - (E) through (I) named lIN}];

\path[3d/intersection of={lIN with lSA}] coordinate (N);

\draw[3d/visible] (S) --(O) -- (A) -- (B) --cycle (S) -- (A) (O) -- (N) -- (M);
\draw[3d/hidden] (O) -- (B) (O) -- (M) (S) -- (E) (A) -- (E) (I) -- (N);
\path foreach \p/\g in {S/90,A/-90,B/-90,O/-150,M/60,E/-90,I/180,N/-30}
{(\p)node[c]{}+(\g:2.5mm) node{$\p$}};
\end{tikzpicture}
\end{document}

There is a built-in function in the module math of Asymptote

real intersect(triple P, triple Q, triple n, triple Z)

returns the intersection time of the extension of the line segment PQ with the plane perpendicular to n and passing through Z.

In this case, the plane through O with normal n=BS, so the intersection time is tM=intersect(S,B,n,O), and then the intersection point M of the segment SB and that plane can be get with M=point(S--B,tM). Similarly for the other intersection point N.

// http://asymptote.ualberta.ca/
unitsize(1cm);
import math; // for intersection of a line and a plane
import three;
real a=4,h=5;
triple O=(0,0,0),A=(a,0,0),B=(a/2,a*sqrt(3)/2,0),S=(0,0,h);
triple n=S-B;
real tM=intersect(S,B,n,O);
real tN=intersect(S,A,n,O);
triple M=point(S--B,tM);dot(M,red);
triple N=point(S--A,tN);dot(N,red);
draw(O--S^^O--A^^O--B,dashed);
draw(O--M^^O--N,dashed+red);
draw(S--A--B--cycle);
draw(M--N,red);

label("$A$",A,W);
label("$B$",B,E);
//label("$O$",O);
label("$S$",S,plain.N);
label("$M$",M,E,red);
label("$N$",N,W,red);

View and light can be set via settings currentprojection and currentlight, then manually change dashed accordingly. The option opacity should be used for the plane section OMN.

unitsize(1cm);
import math; // for intersection of a line and a plane
import three;
currentprojection=orthographic(1,-1,.5,zoom=.9);
real a=4,h=3.5;
triple O=(0,0,0),A=(a,0,0),B=(a/2,a*sqrt(3)/2,0),S=(0,0,h);
triple n=S-B;
real tM=intersect(S,B,n,O);
real tN=intersect(S,A,n,O);
triple M=point(S--B,tM);dot(M,red);
triple N=point(S--A,tN);dot(N,red);
draw(surface(O--M--N--cycle),.2red+.8white+opacity(.2));
draw(O--B,dashed);
draw(O--M,dashed+red);
draw(S--A--B--cycle^^S--O--A);
draw(M--N--O,red);

label("$A$",A,plain.S);
label("$B$",B,E);
label("$O$",O,W);
label("$S$",S,plain.N);
label("$M$",M,NE);
label("$N$",N,E);
• I think, style of line ON none dashed. Can you make style of lines automatically (hidden or visible) like minh_thien2016'answer? Sep 11, 2021 at 1:51
• @JohnPaulPeter Yes, ON is not dashed, I will correct later. Minhthien seems like automatic hidden lines in rotating figure (AHLirf). I know the idea behind it, but I don't like it. In my opinion, AHLirf is 1. not general enough for any angle view (any attempt reducing from 3D to 2D is a kind of fake one. Where is the missing dimension?); 2. can not be used for perspective; 3. (more important) not concentrate to math problem, and not useful for thingking. Thinking is in silent, static, ... all that stuff. Anyway, this is just my personal opinion, and sorry for many NOTs in this comment Sep 11, 2021 at 2:34
• @JohnPaulPeter on automatic hidden+dashed line: that can be done in some simple cases, but in generally, mathematically, technically, it is really overcomplicated. Example 1. 3D-like (or fake 3D) with manual dashed is good enough tex.stackexchange.com/a/616640/140722; Example 2. wanna dashed ? tex.stackexchange.com/questions/615836/… Sep 25, 2021 at 2:26

Compile with Asymptote at http://asymptote.ualberta.ca/

About the problem of hidden or visible lines in Asymptote, this is an example about that, https://asy.marris.fr/asymptote/Solides/index.html#fig_py05_261011_pyramide

Now, IMHO, we still draw the dashed lines manually.

I guess that, in the future (maybe Asymptote 3.0 or later), we will have an implementation for this issue (automatically hidden lines).

// settings.render=7;
import three;

size(5cm,0);
currentprojection=orthographic(1,-0.8,0.8);

// Project P onto plane through point O with normal n.
triple pointproject(triple P, triple O=O, triple n)
{
return planeproject(n,O)*P;
}

// Project P onto plane through 3 points A,B,C
triple pointproject(triple P, triple A, triple B, triple C)
{
return pointproject(P,A,unit(cross(B-A,C-A)));
}

// Project P onto line through 2 points A,B
triple pointproject(triple P, triple A, triple B)
{
triple normalPAB=normal(P--A--B--cycle);
triple thirdpoint=shift(planeproject(P--A--B--cycle)*normalPAB-normalPAB)*A;
return pointproject(P,A,B,thirdpoint);
}

triple extension(triple P, triple Q, triple p, triple q) // uncompleted
{
triple PQ=Q-P;
triple pq=q-p;
real a=PQ.x,b=PQ.y,c=PQ.z;
real a_=pq.x,b_=pq.y,c_=pq.z;
/*
x=P.x+a*t,           x'=p.x+a_*u,
(PQ) y=P.y+b*t,  and (pq) y'=p.y+b_*u,
z=P.z+c*t            z'=p.z+c_*u
Solving system of equations
x=P.x+a*t,       x'=p.x+a_*u,
y=P.y+b*t,  and  y'=p.y+b_*u,
*/
real[][] A={{a,-a_},{b,-b_}};
real[] B={p.x-P.x,p.y-P.y};
real[] result=solve(A,B);
return (P.x+a*result[0],P.y+b*result[0],P.z+c*result[0]);
}

real AngleBetweenTwoLines(triple P, triple Q, triple p, triple q)
{
triple PQ=Q-P;
triple pq=q-p;
real a=dot(PQ,pq),b=abs(PQ),c=abs(pq);
return aCos(abs(a)/(b*c));
}

real a=4, h=5;
triple A=(a,0,0),B=(a/2,a*sqrt(3)/2,0),S=(0,0,h);

draw(S--O^^S--A^^S--B);
draw(O--A--B);
draw(O--B,dashed);

dot("$S$",S,dir(90));
dot("$O$",O,dir(-135));
dot("$A$",A,dir(-90));
dot("$B$",B,dir(0));

triple M=pointproject(O,S,B);
triple E=(A+B)/2;
triple K=pointproject(O,S,E);
triple N=extension(S,A,M,K);

dot("$M$",M,dir(30));
dot("$E$",E,dir(-10));
dot("$K$",K,dir(-10));
dot("$N$",N,dir(-10));

draw(O--M,dashed);
draw(O--E,dashed);
draw(O--K,dashed);
draw(S--E^^M--N--O);

write(AngleBetweenTwoLines(S,B,O,N)); // Outputs: 90