As an attempt to solve my Define a 2D canvas using preexisting points, I came across the idea of @andrew swann's answer to Pass a 3d coordinate via pgfkeys and tried to adapt it.
This is how the 3d coordinates are stored additionally to the 3d coordinate being transformed into 2d coordinates.
% save 3d coordinates of point
\def\tdcoord #1 at (#2,#3,#4);{\pgfkeys{/tdcoords/#1/.is
family,/tdcoords/#1,x/.initial=#2,y/.initial=#3,z/.initial=#4}}
And while everything works fine and i was able to adapt the canvas just giving points defined with an additional \tdcoords, it only works when that call is not in a foreach loop.
The Error messages are
- Undefined controll sequence
- Missing number, treated as zero
- Argument of \pgfmath@dimen@@ has an extra }
- Paragraph ended before \pgfmath@dimen@@ was complete
- Extra }, or forgotten \endgroup
Anyone have an idea why or how to fix it?
Adapted MWE:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{tikz-3dplot}
% my adaption attempt
\makeatletter
\tikzoption{canvasP}[]{\@setPOxy#1}
\def\@setPOxy #1,#2,#3%
{\def\tikz@plane@origin{\pgfpointxyz{\GetX(#1)}{\GetY(#1)}{\GetZ(#1)}}%
\def\tikz@plane@x{\pgfpointxyz{\GetX(#2)}{\GetY(#2)}{\GetZ(#2)}}%
\def\tikz@plane@y{\pgfpointxyz{\GetX(#3)}{\GetY(#3)}{\GetZ(#3)}}%
\tikz@canvas@is@plane}
\makeatother
% save 3d coordinates of point
\def\tdcoord #1 at (#2,#3,#4);{\pgfkeys{/tdcoords/#1/.is
family,/tdcoords/#1,x/.initial=#2,y/.initial=#3,z/.initial=#4}}
% Get the 3d coordinate components of a point
\def\GetX(#1){\pgfkeysvalueof{/tdcoords/(#1)/x}}
\def\GetY(#1){\pgfkeysvalueof{/tdcoords/(#1)/y}}
\def\GetZ(#1){\pgfkeysvalueof{/tdcoords/(#1)/z}}
% Define multiple 3d points following tkz-euclide notation
\newcommand{\tkzDefdPoints}[2][]{
\foreach \ptx/\pty/\ptz/\name in {#2}{
\path [#1] (\ptx,\pty,\ptz) coordinate (\name);
\tdcoord (\name) at (\ptx,\pty,\ptz);
}
}
\tdplotsetmaincoords{70}{110}
\begin{document}
\begin{tikzpicture}[tdplot_main_coords]
\draw[->] (0,0,0) -- (5,0,0) node[right]{$x$};
\draw[->] (0,0,0) -- (0,5,0) node[above]{$y$};
\draw[->] (0,0,0) -- (0,0,5) node[below left]{$z$};
\tkzDefdPoints{2/2/2/A,2/3/2/B,2/2/3/C,
2/2/2/D,2/3/2/E,2/2/3/F}
\tdcoord (A) at (2,2,2);
\tdcoord (B) at (2,3,2);
\tdcoord (C) at (2,2,3);
\draw (A) -- (B) -- (C) -- cycle;
\begin{scope}[canvasP={A,B,C}]
\draw[red] (1,0) -- (1,1) -- (0,1);
\end{scope}
% \begin{scope}[canvasP={D,E,F}]
% \draw[blue] (0,1) -- (1,2) -- (2,1) -- (1,0);
% \end{scope}
\end{tikzpicture}
\end{document}
Update: While renaming points, I just realized that this might have nothing to do with the foreach statement. Changing the coordinate names to something that is not a single letter, like \tdcoord (AX) at (2,2,2); produces the exact same error, even when it is called outside of the foreach loop.
\foreachparses list items starting with(different, we could define@def dPointsso that we can use\tkzDefdPoints{(2,2,2)/A, (2,3,2)/B, (2,2,3)/C, (2,2,2)/D,(2,3,2)/E, (2,2,3)/F}. It probably is still a good idea to.expandedall values forx,yandzanyway. On another note: Nodes and coordinates are declared global by PGF/TikZ, so that one an reference a coordinate defined inside a scope (or even another picture). Unless you want to use\tkzDefdPointsinside a group (or a more complex\foreachloop) I wouldn't bother with it, though. – Qrrbrbirlbel Aug 28 '22 at 16:52Two things: I would be interested in a pointer on how you would solve it differently. And since you also answered my other question, would you drop the short form of your answer there too? I can do it as well, but wouldn't want to take your credit away since your answer here is the complete solution.
– Shakaja Aug 28 '22 at 20:02