6

From here Is there a command to find coordinates of projection of a point on a plane?, I got an answer. I know that, the calc library got updated and way before the update of calc made it to CTAN. I hope that, there is a simpler answer to this equation.

2 Answers2

6

UPDATE: Some further developments using the experimental 3dtools library. Still not the final word in this story, I hope.

\documentclass[border=3mm,12pt,tikz]{standalone}
\usepackage{tikz-3dplot} 
\usetikzlibrary{3dtools}
\tikzset{3d projection of point/.style args={(#1,#2,#3) on plane through (#4,#5,#6)
with normal (#7,#8,#9)}{
/utils/exec={\pgfmathsetmacro{\myprefactor}{(#7*(#1-#4)%
+#8*(#2-#5)+#9*(#3-#6))%
/(#7*#7+#8*#8+#9*#9)}
\pgfmathsetmacro{\myx}{#1-\myprefactor*#7}
\pgfmathsetmacro{\myy}{#2-\myprefactor*#8}
\pgfmathsetmacro{\myz}{#3-\myprefactor*#9}},
insert path={%
({\myx},{\myy},{\myz})}},% symbolic version
symbolic 3d projection of point/.style args={#1 on plane through #2
with normal #3}{insert path={let \p1=(#1),\p2=(#2),\p3=(#3) in 
[3d projection of point/.expanded=\coord1 on plane through \coord2 with normal \coord3]}}}

\begin{document}
    \tdplotsetmaincoords{70}{110}
    \begin{tikzpicture}[tdplot_main_coords,scale=1.5]
    \pgfmathsetmacro\a{4}
    \pgfmathsetmacro\b{3}
    \pgfmathsetmacro\c{4}
    % define the coordinates (note: \coordinate (A) at (0,0,0) does *NOT* work)
    \path (0,0,0) coordinate(A)
        (\a,0,0) coordinate (B)
        (0,\b,0) coordinate (C)                           
        (0,0,\c) coordinate (S)
        [overlay,3d coordinate={(n)=(C)-(B)x(S)-(B)}];
    % do the projection
    \path[symbolic 3d projection of point={A on plane through S with
          normal n}]  coordinate (H);
    % draw various parts          
    \draw[dashed,thick] (A) -- (B)  (A) -- (C)  (S)--(A) --(H) ;
    \draw[thick]    (S) -- (B) -- (C) -- cycle;
    \foreach \point/\position in {A/left,B/left,C/below,S/above,H/above}
    {
        \fill (\point) circle (1.5pt);
        \node[\position=3pt] at (\point) {$\point$};
    }
    \end{tikzpicture}
\end{document} 

This is an upgrade, yet likely not the final word in this evolving story. With the parsers here, you can work with symbolic coordinates. The code is long because it has several definitions, which hopefully make it to a library one day. These tricks are made possible by a recent commit by Henri Menke, and have been used here. Unfortunately, in this version you cannot mix symbolic with explicit coordinates. You can now use symbolic coordinates like

\path[symbolic 3d projection of point={A on plane through S with
          normal n}]  coordinate (H);

The normal n can be computed from the symbolic coordinates. It is given by

 n = (C-B) x (S-B)

and the computation is done by

\lincomb(CB)=1*(C)+(-1)*(B);
\lincomb(SB)=1*(S)+(-1)*(B);
\vecprod(n)=(CB)x(SB);

That is, we first need to form the linear combinations C-B and S-B and can then compute the vector product of those. Nested parsing would require a parsing expert to have a look at this.

\documentclass[border=3mm,12pt,tikz]{standalone}
\usepackage{tikz-3dplot} 
% allows us to do linear combinations
\def\lincomb#1=#2*#3+#4*#5;{%
\path[overlay] let \p1=#3,\p2=#5 in 
({(#2)*(xcomp3\coord1)+(#4)*(xcomp3\coord2)},%
 {(#2)*(ycomp3\coord1)+(#4)*(ycomp3\coord2)},%
 {(#2)*(zcomp3\coord1)+(#4)*(zcomp3\coord2)}) coordinate #1;}
\def\vecprod#1=#2x#3;{%
\path[overlay] let \p1=#2,\p2=#3 in 
 ({vpx({\coord1},{\coord2})},%
 {vpy({\coord1},{\coord2})},%
 {vpz({\coord1},{\coord2})}) coordinate #1;}
\pgfmathdeclarefunction{xcomp3}{3}{% x component of a 3-vector
\begingroup%
  \pgfmathparse{#1}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\pgfmathdeclarefunction{ycomp3}{3}{% y component of a 3-vector
\begingroup%
  \pgfmathparse{#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}  
\pgfmathdeclarefunction{zcomp3}{3}{% z component of a 3-vector
\begingroup%
  \pgfmathparse{#3}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
% vector product auxiliary functions
\newcommand{\vpauxx}[6]{(#2)*(#6)-(#3)*(#5)}     
\newcommand{\vpauxy}[6]{(#4)*(#3)-(#1)*(#6)}
\newcommand{\vpauxz}[6]{(#1)*(#5)-(#2)*(#4)}
% vector product pgf functions
\pgfmathdeclarefunction{vpx}{2}{% x component of vector product
  \begingroup%
  \pgfmathparse{\vpauxx#1#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\pgfmathdeclarefunction{vpy}{2}{% y component of vector product
  \begingroup%
  \pgfmathparse{\vpauxy#1#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\pgfmathdeclarefunction{vpz}{2}{% z component of vector product
  \begingroup%
  \pgfmathparse{\vpauxz#1#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
% original version of projection (works with symbolic coordinates)  
\tikzset{3d projection of point/.style args={(#1,#2,#3) on plane through (#4,#5,#6)
with normal (#7,#8,#9)}{
/utils/exec={\pgfmathsetmacro{\myprefactor}{(#7*(#1-#4)%
+#8*(#2-#5)+#9*(#3-#6))%
/(#7*#7+#8*#8+#9*#9)}
\pgfmathsetmacro{\myx}{#1-\myprefactor*#7}
\pgfmathsetmacro{\myy}{#2-\myprefactor*#8}
\pgfmathsetmacro{\myz}{#3-\myprefactor*#9}},
insert path={%
({\myx},{\myy},{\myz})}},% symbolic version
symbolic 3d projection of point/.style args={#1 on plane through #2
with normal #3}{insert path={let \p1=(#1),\p2=(#2),\p3=(#3) in 
[3d projection of point/.expanded=\coord1 on plane through \coord2 with normal \coord3]}}}

\begin{document}
    \tdplotsetmaincoords{70}{110}
    \begin{tikzpicture}[tdplot_main_coords,scale=1.5]
    \pgfmathsetmacro\a{4}
    \pgfmathsetmacro\b{3}
    \pgfmathsetmacro\c{4}
    % define the coordinates (note: \coordinate (A) at (0,0,0) does *NOT* work)
    \path (0,0,0) coordinate(A)
        (\a,0,0) coordinate (B)
        (0,\b,0) coordinate (C)                           
        (0,0,\c) coordinate (S);
    \lincomb(C-B)=1*(C)+(-1)*(B);
    \lincomb(S-B)=1*(S)+(-1)*(B);
    % compute the normal n
    \vecprod(n)=(C-B)x(S-B);
    % do the projection
    \path[symbolic 3d projection of point={A on plane through S with
          normal n}]  coordinate (H);
    % draw various parts          
    \draw[dashed,thick] (A) -- (B)  (A) -- (C)  (S)--(A) --(H) ;
    \draw[thick]    (S) -- (B) -- (C) -- cycle;
    \foreach \point/\position in {A/left,B/left,C/below,S/above,H/above}
    {
        \fill (\point) circle (1.5pt);
        \node[\position=3pt] at (\point) {$\point$};
    }
    \end{tikzpicture}
\end{document} 

enter image description here

These parsers also allow us to compute the projection directly. We have to subtract from A the projection of A-S on n, H = A - (((A-S).(n))/((n).(n))) * n. This can be done directly (and yields of course the same output).

\documentclass[border=3mm,12pt,tikz]{standalone}
\usepackage{tikz-3dplot} 
% allows us to do linear combinations
\def\lincomb#1=#2*#3+#4*#5;{%
\path[overlay] let \p1=#3,\p2=#5 in 
({(#2)*(xcomp3\coord1)+(#4)*(xcomp3\coord2)},%
 {(#2)*(ycomp3\coord1)+(#4)*(ycomp3\coord2)},%
 {(#2)*(zcomp3\coord1)+(#4)*(zcomp3\coord2)}) coordinate #1;}
% vector product
\def\vecprod#1=#2x#3;{%
\path[overlay] let \p1=#2,\p2=#3 in 
 ({vpx({\coord1},{\coord2})},%
 {vpy({\coord1},{\coord2})},%
 {vpz({\coord1},{\coord2})}) coordinate #1;}
% scalar product 
\makeatletter
\def\scalprod#1=#2.#3;{%
\path[overlay] let \p1=#2,\p2=#3 in 
\pgfextra{\pgfmathsetmacro\pgfutil@tmpa{scalarproduct({\coord1},{\coord2})}
\xdef\pgfutil@tmpa{\pgfutil@tmpa}};%
\edef#1{\pgfutil@tmpa}}%
\makeatother 
\newcommand{\spaux}[6]{(#1)*(#4)+(#2)*(#5)+(#3)*(#6)}  
\pgfmathdeclarefunction{scalarproduct}{2}{% scalar product of two 3-vectors
  \begingroup%
  \pgfmathparse{\spaux#1#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}  
% projections
\pgfmathdeclarefunction{xcomp3}{3}{% x component of a 3-vector
\begingroup%
  \pgfmathparse{#1}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\pgfmathdeclarefunction{ycomp3}{3}{% y component of a 3-vector
\begingroup%
  \pgfmathparse{#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}  
\pgfmathdeclarefunction{zcomp3}{3}{% z component of a 3-vector
\begingroup%
  \pgfmathparse{#3}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
% vector product auxiliary functions
\newcommand{\vpauxx}[6]{(#2)*(#6)-(#3)*(#5)}     
\newcommand{\vpauxy}[6]{(#4)*(#3)-(#1)*(#6)}
\newcommand{\vpauxz}[6]{(#1)*(#5)-(#2)*(#4)}
% vector product pgf functions
\pgfmathdeclarefunction{vpx}{2}{% x component of vector product
  \begingroup%
  \pgfmathparse{\vpauxx#1#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\pgfmathdeclarefunction{vpy}{2}{% y component of vector product
  \begingroup%
  \pgfmathparse{\vpauxy#1#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\pgfmathdeclarefunction{vpz}{2}{% z component of vector product
  \begingroup%
  \pgfmathparse{\vpauxz#1#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\begin{document}
    \tdplotsetmaincoords{70}{110}
    \begin{tikzpicture}[tdplot_main_coords,scale=1.5]
    \pgfmathsetmacro\a{4}
    \pgfmathsetmacro\b{3}
    \pgfmathsetmacro\c{4}
    % define the coordinates (note: \coordinate (A) at (0,0,0) does *NOT* work)
    \path (0,0,0) coordinate(A)
        (\a,0,0) coordinate (B)
        (0,\b,0) coordinate (C)                           
        (0,0,\c) coordinate (S);
    \lincomb(C-B)=1*(C)+(-1)*(B);
    \lincomb(S-B)=1*(S)+(-1)*(B);
    \lincomb(A-S)=1*(A)+(-1)*(S);
    % compute the normal n
    \vecprod(n)=(C-B)x(S-B);
    % projection of (A-S) on n
    \scalprod\mysp=(A-S).(n);
    % square of n
    \scalprod\myln=(n).(n);
    % H = A - (((A-S).(n))/((n).(n))) * n
    \lincomb(H)=1*(A)+{(-1*(\mysp)/\myln)}*(n);
    % draw various parts          
    \draw[dashed,thick] (A) -- (B)  (A) -- (C)  (S)--(A) --(H) ;
    \draw[thick]    (S) -- (B) -- (C) -- cycle;
    \foreach \point/\position in {A/left,B/left,C/below,S/above,H/above}
    {
        \fill (\point) circle (1.5pt);
        \node[\position=3pt] at (\point) {$\point$};
    }
    \end{tikzpicture}
\end{document} 
1

This can be easily done with the command planeproject of the module three of Asymptote.

enter image description here

// http://asymptote.ualberta.ca/
unitsize(1cm);
import three;
currentprojection=orthographic(2,4,1,zoom=.8);
triple A=(3,0,0), B=(0,6,0), C=(0,0,4);

path3 base=A--B--C--cycle; triple H=planeproject(base,normal(base))*O;

draw(O--A^^O--B^^O--C,dashed); draw(O--H,red); draw(base);

dot("$A$",A,W); dot("$B$",B,E); dot("$C$",C,N); dot("$O$",O,NE); dot("$H$",H,SW,red);

Black Mild
  • 17,569