假设 SOAB 是一个金字塔,OAB
是一个等边三角形,SO
垂直于平面OAB
。通过O
并垂直于线的平面在和处与SB
相交。我试过了SB
M
SA
N
\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}
我无法绘制该点N
。我该如何绘制它?
答案1
第一种方式该点的坐标N
为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}
第二种方式
计算两点的坐标M
,N
枫。
\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}
第三条道路利用3dtool
过点O
且垂直于直线的平面SB
取向量SB
为法向量,求得两点M
和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}
或者你可以尝试
\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}
绘制点 N 的一种方法
设E
是线段的中点OB
;I
是两条线段SE
和的交点OM
,且IN
平行于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}
答案2
模块中有一个内置函数数学渐近线
real intersect(triple P, triple Q, triple n, triple Z)
返回线段PQ的延长线与垂直于n且过Z的平面的相交时间。
此时平面O
与法线 相交n=BS
,所以交点为tM=intersect(S,B,n,O)
,则线段SB 与该平面的交点M为 ,M=point(S--B,tM)
另一交点 同理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);
currentprojection
可以通过设置和来设置视图和灯光currentlight
,然后手动进行dashed
相应更改。该选项opacity
应用于平面部分OMN
。
unitsize(1cm);
import math; // for intersection of a line and a plane
import three;
currentprojection=orthographic(1,-1,.5,zoom=.9);
currentlight=Headlamp;
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);
答案3
使用 Asymptote 进行编译http://asymptote.ualberta.ca/
关于隐藏或可见线的问题渐近线这是一个例子,https://asy.marris.fr/asymptote/Solides/index.html#fig_py05_261011_pyramide
现在,恕我直言,我们仍然手动绘制虚线。
我想,在未来(也许渐近线3.0 或更高版本),我们会针对此问题做出实现(自动隐藏线条)。
// 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
关于平面与直线的交点,另请参阅这个例子。
命令是
triple[] intersectionpoints(path3 p, surface s, real fuzz=-1);