Parametric Pics : Pic Actions at Infinity - TeX - LaTeX Stack Exchange most recent 30 from tex.stackexchange.com 2024-09-27T07:36:51Z https://tex.stackexchange.com/feeds/question/315672 https://creativecommons.org/licenses/by-sa/4.0/rdf https://tex.stackexchange.com/q/315672 4 Parametric Pics : Pic Actions at Infinity Carel https://tex.stackexchange.com/users/14593 2016-06-20T11:00:34Z 2016-07-03T12:35:04Z <p>This question tries to expand upon the <a href="https://tex.stackexchange.com/q/315412/14593">another</a> both of which aim at providing a "Best" practices for tikz-pics or atleast a couple of how to examples clarifying some of the more advanced trickery that one may employ.</p> <h1>Requirements :</h1> <p>It typically makes sense to have a set of base dimensions for a pic. Allowing the user to alter these dimensions enables them to customize the pic in some small way. This is useful under various circumstances. TikZ collects the options for a pic into the <code>pic actions</code> for commands reading <code>\draw pic[PIC ACTIONS] {...}</code>. It would seem sensible to allow options specified within <code>pic actions</code> to be passed through to a branch in the pgf tree, pick of any relevant keys and pass the remaining keys back up the tree to some other family that knows how to process them. </p> <h1>Code :</h1> <p>This questions takes the cleaner code from <a href="https://tex.stackexchange.com/a/315464/14593">@LoopSpace</a>, strips away the calligraphy code to focus upon handling <code>pic actions</code>. I have tried four methods in the code which basically try to pass the keys into the correct branch and if they re not present pass them up the tree. Mostly I'm trying this against the <code>.search also</code> handler.</p> <pre><code>\documentclass[tikz]{standalone} \usetikzlibrary{calc,calligraphy} \makeatletter \def\inf@key#1{% \pgfkeysvalueof{/tikz/infinity dimensions/#1}% } \tikzset{ % Dimensions infinity dimensions/.is family, infinity dimensions/width/.initial =1 em, infinity dimensions/height/.initial=1 em, infinity dimensions/upper target/.initial=0.2, infinity dimensions/lower target/.initial=0.8, infinity dimensions/.search also={/tikz, /pgf}, % Method 1 %infinity dimensions/.style={infinity dimensions/.cd,}, % Method 2 %infinity dimensions/.style={infinity dimensions/#1}, % Method 3 infinity dimensions/.style={infinity dimensions/.cd,#1}, % Method 4 %infinity dimensions/.style={@infinity dimensions/.list={#1}}, %@infinity dimensions/.style={/tikz/infinity dimensions/#1} % Pic/Symbol infinity symbol/.pic = { % Method 1 %\draw[infinity dimensions, pic actions] % Method 2 %\draw[infinity dimensions=pic actions] % Method 3 \draw[infinity dimensions=pic actions] % Method 4 %\draw[infinity dimensions={pic actions}] let \p1=(0,0) in (\p1) .. controls (-\inf@key{upper target}*\inf@key{width}, \inf@key{height}) and (-\inf@key{lower target}*\inf@key{width},-\inf@key{height}) .. (\p1) .. controls ( \inf@key{lower target}*\inf@key{width}, \inf@key{height}) and ( \inf@key{upper target}*\inf@key{width},-\inf@key{height}) .. cycle; }, } \makeatother \begin{document} \begin{tikzpicture} \draw pic[double] {infinity symbol}; \end{tikzpicture} \begin{tikzpicture} \draw pic[height=2em] {infinity symbol}; \end{tikzpicture} \end{document} </code></pre> <h1>Problem :</h1> <p>Method(s) 1 and 4 return an error stating that <code>/tikz/height</code> does not exist. Method(s) 2 and 3 return an error stating that <code>/tikz/infinity dimensions/pic actions</code> does not exist. It seems the code either jumps up a level to the <code>/tikz</code> and <code>/pgf</code> roots and fails to recognize something from the <code>/tikz/infinity dimensions</code> branch or it fails to recognize <code>pic actions</code> within the <code>/tikz/infinity dimensions</code>. </p> <h1>Question :</h1> <p>How does one pass the <code>pic actions</code> to some underlying style such that parts of that style may be set and that style options not covered by that style get passed back up to the <code>/tikz</code> and <code>/pgf</code> branches.</p> <p>The simplest mechanism for this might be the use of the <code>.search also</code> handlers, but my atempts with this seem to fail. Perhaps it is more complex and one really requires key filtering.</p> <h1>Background :</h1> <p><a href="https://tex.stackexchange.com/q/215580/14593">This</a> question implies that <code>pic actions</code> are limited in some way. <a href="https://tex.stackexchange.com/a/125700/14593">@Qrrbrbirlbel</a> provides some alternate strategies but I haven't succeeded with any of them.</p> https://tex.stackexchange.com/questions/315672/-/315789#315789 3 Answer by cfr for Parametric Pics : Pic Actions at Infinity cfr https://tex.stackexchange.com/users/39222 2016-06-21T00:59:23Z 2016-06-21T00:59:23Z <p>It is a bit misleading to say <code>pic actions</code> are limited. <em>Of course,</em> they are limited, just like everything else. A hammer is limited: it can't boil water. </p> <p>I think the problem is that you are trying to make them do something they are not designed for and, possibly, trying to use <code>pic</code>s for something they weren't designed for. <code>pic</code>s are easy to create but, as is usually the case, that convenience has a cost in terms of power and flexibility. You can have the power and flexibility without the convenience, of course, by not using a <code>pic</code>.</p> <p>This is not the way I usually configure <code>pic</code>s because I didn't want to overwrite your configuration simply because I tend to do things differently. But I think the key is that the easiest way to set options flexibly is to pass them as an argument to the particular <code>pic</code> rather than passing them as options to the <code>pic</code> path.</p> <p>For example,</p> <pre><code>\documentclass[tikz,border=10pt,multi]{standalone} \usetikzlibrary{calc} \makeatletter \def\inf@key#1{% \pgfkeysvalueof{/tikz/infinity dimensions/#1}% } \tikzset{ % Dimensions infinity dimensions/.is family, infinity dimensions/width/.initial =1 em, infinity dimensions/height/.initial=1 em, infinity dimensions/upper target/.initial=0.2, infinity dimensions/lower target/.initial=0.8, infinity dimensions/.search also={/tikz,/pgf}, infinity setup/.code={% \tikzset{% infinity dimensions/.cd, #1, /tikz/.cd, }% }, infinity symbol/.pic = {% \draw [infinity dimensions/.cd, pic actions, infinity setup=#1] let \p1=(0,0) in (\p1) .. controls (-\inf@key{upper target}*\inf@key{width}, \inf@key{height}) and (-\inf@key{lower target}*\inf@key{width},-\inf@key{height}) .. (\p1) .. controls ( \inf@key{lower target}*\inf@key{width}, \inf@key{height}) and ( \inf@key{upper target}*\inf@key{width},-\inf@key{height}) .. cycle; }, } \makeatother \begin{document} \begin{tikzpicture} \draw pic [rotate=-45] {infinity symbol={height=2em, line width=2mm, double=blue, draw=green}}; \end{tikzpicture} \end{document} </code></pre> <p><a href="https://i.sstatic.net/5O4c0.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/5O4c0.png" alt="lurid infinity"></a></p> https://tex.stackexchange.com/questions/315672/-/317765#317765 0 Answer by Carel for Parametric Pics : Pic Actions at Infinity Carel https://tex.stackexchange.com/users/14593 2016-07-03T12:35:04Z 2016-07-03T12:35:04Z <p>This answer is meant as a compliment to @cfr's one.</p> <h2>Observations:</h2> <p>@cfr's answer is more flexible then he's shown for instance one can readily use the following invocation to draw the symbol</p> <pre><code>\draw pic [rotate=-45, infinity setup={height=2em, line width=2mm, double=blue, draw=green}] {infinity symbol}; </code></pre> <h2>Code :</h2> <p>While playing with the code from @cfr code I stumbled upon an alternate way of implementing the same mechanism that he/she provided posted <a href="https://tex.stackexchange.com/a/216315">here</a>. Execution wise it does not appear to add but it cleans up the code a little.</p> <pre><code>\documentclass[tikz]{standalone} \usetikzlibrary{calc,calligraphy} \makeatletter \def\inf@key#1{% \pgfkeysvalueof{/tikz/infinity dimensions/#1}% } </code></pre> <p>The initial part reads the same and simply sets up the dimensions.</p> <pre><code>\tikzset{ % Dimensions infinity dimensions/.is family, %infinity dimensions/.search also={/tikz, /pgf}, infinity dimensions/width/.initial =1 em, infinity dimensions/height/.initial=1 em, infinity dimensions/upper target/.initial=0.2, infinity dimensions/lower target/.initial=0.8, } </code></pre> <p>Then we adapt @cfr's code as follows, based upon the other answer. It seems common practice to provide an <code>every KEY</code> and a corresponding <code>KEY</code> that sets it. Supposedly this is done every where within tikz but I haven't confirmed this.</p> <pre><code>\tikzset{ every infinity/.style={pic actions, infinity dimensions/.cd}, infinity/.style={every infinity/.append style={#1}}, } </code></pre> <p>The use of <code>#1</code> enables the <code>\draw pic {infinity={...}};</code> call signature, removing it causes tikz to simply ignore the input. That is one is enforcing the use of <code>\draw pic[infinity={...}] {infinity};</code> instead. The latter syntax passes the options to <code>every infinity/.style</code> via <code>infinity/.syle</code>, providing an interface similar to @cfr's code.</p> <pre><code>\tikzset{ % Pic/Symbol infinity symbol/.pic = { \path[every infinity, #1] let \p1=(0,0) in (\p1) .. controls (-\inf@key{upper target}*\inf@key{width}, \inf@key{height}) and (-\inf@key{lower target}*\inf@key{width},-\inf@key{height}) .. (\p1) .. controls ( \inf@key{lower target}*\inf@key{width}, \inf@key{height}) and ( \inf@key{upper target}*\inf@key{width},-\inf@key{height}) .. cycle; }, } \makeatother \begin{document} \begin{tikzpicture} \draw pic[draw] at (0,-0.5em) {infinity symbol}; \draw pic[draw, double,infinity={lower target=1.5,upper target=0.5}] at (0, 0.5em) {infinity symbol}; \draw pic[double,draw] at (0, 1.0em) {infinity symbol={lower target=1.5,upper target=1.5}}; \end{tikzpicture} \end{document} </code></pre> <p>The last thing that might be of interest is that I pass <code>pic actions</code> to the base style, <code>every infinity</code>, but I do so before the path change. Similarly one might remove it from the base style placing it into the call to draw instead as in <code>\draw[pic actions, every infinity] ...</code>. The effect is the same either way, the latter being slightly more 'hard coded'. There is a caveat though if <code>pic actions</code> is placed after the path change as in <code>every infinity={infinity dimensions/.cd, pic actions}</code> or as <code>\draw[every infinity, pica actions]</code> then one must enable the line <code>infinity dimensions/.serach also={/tikz, /pgf}</code> otherwise you will get error messages indicating that the key is unrecognised.</p> <h2>Notes:</h2> <p>It wasn't initially obvious to me that <code>pic actions</code> really dislikes being under any path other then <code>/tikz</code>. You can pass it to say <code>infinity dimensions/.style={}</code> provided that the <code>.search also</code> handler is correctly set e.g. <code>infinity dimensions/.search also={/tikz}</code>. As it acts in this root, anything within <code>pic actions</code> is also bound to this root so <code>upper target=...</code> in <code>infinity dimensions/.style{upper target=...}</code> fails as it is now being called within the <code>/tikz</code> path and not <code>/tikz/infinity dimensions</code>. So anything contained within <code>pic actions</code> is executed within the <code>/tikz</code> path. Originally I thought <code>pic actions</code> were more like a container that one could pass around and unpack at will which was incorrect.</p>