7

Is it possible to position an anchor based on the value of a PGF key at the time the node is created? Here is one of my many attempts at getting this to work (all of which have been unsuccessful):

\documentclass{article} \usepackage{tikz} \newif\ifmarkisinside \pgfkeys{% /pgf/port 1 inside/.is if=markisinside, /pgf/port 1 inside/.initial=true, /pgf/port 1 inside/.default=true, } \pgfdeclareshape{mycircle}{% \nodeparts{text}% \inheritsavedanchors[from=circle] \inheritanchor[from=circle]{text}% \inheritanchor[from=circle]{center}% \inheritbackgroundpath[from=circle]% \savedmacro\portoneinside{% \pgfkeysgetvalue{/pgf/port 1 inside}{\portoneinside} }% \anchor{port 1}{% \pgfmathparse{ifthenelse(\portoneinside,0.5,1.5)} \let\portsep\pgfmathresult \pgfpointadd{\centerpoint}{\pgfpoint{\portsep*\radius}{0pt}}% }% %% Also does not work to do this: % \anchor{port 1}{% % \ifmarkisinside % \pgfpointadd{\centerpoint}{\pgfpoint{0.5*\radius}{0pt}}% % \else % \pgfpointadd{\centerpoint}{\pgfpoint{1.5*\radius}{0pt}}% % \fi % }% } \begin{document} \begin{tikzpicture} \node [draw,mycircle,minimum size=2cm] (c1) at (0,0) {}; \fill (c1.port 1) circle(0.05); \node [draw,mycircle,minimum size=2cm,port 1 inside=false] (c2) at (4,0) {}; \fill (c2.port 1) circle(0.05); \end{tikzpicture} \end{document} 

The desired outcome is that the left-hand dot is inside the circle, but the right-hand dot is outside it. enter image description here

I have tried using \ifmarkisinside in the anchor declaration, and I have tried making port 1 a deferred anchor, too, but that does not work either.

3
  • this isn't how pgfkeys works. the value of your key is always true. try just \pgfkeys{/pgf/port 1 inside=false} \pgfkeysgetvalue{/pgf/port 1 inside}\tempa\tempa without any node or picture. Commented Dec 26, 2024 at 17:33
  • @cfr I figured that part out, but using \ifmarkisinside [do stuff] \else [do other stuff] \fi does work ordinarily, just not as an anchor definition. I edited the original post to include the failed code. Commented Dec 26, 2024 at 17:57
  • I have made progress on this: the problem is that macros defined with \savedmacro are not available inside another \savedmacro definition, but the PGF keys' current values are available there. Conversely, the PGF key values are not available inside \anchor definitions, but \savedmacros are! So I can create a saved anchor (or macro, in the MWE here) that sets a multiplier, then use \radius inside the \anchor definition and do the multiplication there. Commented Dec 26, 2024 at 19:58

2 Answers 2

7

I wrote this while the OP was writing an answer. Since this solution is a bit simpler, it seems worth presenting as an alternative. However, I will delete this answer if the OP wishes.

One approach is just to save the 0.5 or 1.5 and then use that in the definition of the anchor. We can't save the dimension because we don't know \radius. We can't use the conditional directly in the definition of the anchor because the anchor isn't calculated until it is used, so the conditional may not have the same value when the anchor is actually accessed. It does, however, have the relevant value if we save the value to a macro. We can then use that macro to define the anchor.

\documentclass{article} % ateb: https://tex.stackexchange.com/a/733652/ % addaswyd o gwestiwn karlh: https://tex.stackexchange.com/q/733635/ \usepackage{tikz} \newif\ifmarkisinside \pgfkeys{% /pgf/port 1 inside/.is if=markisinside, /pgf/port 1 inside/.default=true, /pgf/port 1 inside=true, } \makeatletter \newdimen\tempdimen \pgfdeclareshape{mycircle}{% \nodeparts{text}% \inheritsavedanchors[from=circle] \inheritanchor[from=circle]{text}% \inheritanchor[from=circle]{center}% \inheritbackgroundpath[from=circle]% \savedmacro\portsep{% \ifmarkisinside \def\portsep{0.5}% \else \def\portsep{1.5}% \fi }% \anchor{port 1}{% \centerpoint \pgfmathsetlength\tempdimen{\portsep*\radius}% \advance \pgf@x by \tempdimen }% } \makeatother \begin{document} \begin{tikzpicture} \node [draw,mycircle,minimum size=2cm] (c1) at (0,0) {}; \fill (c1.port 1) circle(0.05); \node [draw,mycircle,minimum size=2cm,port 1 inside=false] (c2) at (4,0) {}; \fill (c2.port 1) circle(0.05); \end{tikzpicture} \end{document} 

offset anchor by one or half or three times radius

5

Eureka! The trick is that saved anchors such as \radius are not available inside \savedmacro definitions, but \savedmacro definitions can read the values of PGF keys when the shape is declared while \anchor definitions cannot. The solution is to mix the two:

\documentclass{article} \usepackage{tikz} \newif\ifmarkisinside \markisinsidetrue \pgfkeys{% /pgf/port 1 inside/.is if=markisinside, /pgf/port 1 inside/.initial=true, /pgf/port 1 inside/.default=true, } \makeatletter \pgfdeclareshape{mycircle}{% \nodeparts{text}% \inheritsavedanchors[from=circle]% \inheritanchor[from=circle]{text}% \inheritanchor[from=circle]{center}% \inheritbackgroundpath[from=circle]% \savedanchor\portone{ \ifmarkisinside \pgfpoint{0.5pt}{0pt} \else \pgfpoint{1.5pt}{0pt} \fi } \anchor{port 1}{% \portone \pgf@xa=\pgf@x \pgf@ya=\pgf@y \pgfmathsetlength{\pgf@xb}{\pgf@xa*\radius} \pgfmathsetlength{\pgf@yb}{\pgf@ya*\radius} \centerpoint \advance\pgf@x by\pgf@xb \advance\pgf@y by\pgf@yb }% } \makeatother \begin{document} \begin{tikzpicture} \node [draw,mycircle,minimum size=2cm] (c1) at (0,0) {}; \fill (c1.port 1) circle(0.05); \node [draw,mycircle,minimum size=2cm,port 1 inside=false] (c2) at (4,0) {}; \fill (c2.port 1) circle(0.05); \end{tikzpicture} \end{document} 

enter image description here

1
  • congratulations! I always forget how this works and by the time I'd reread the relevant bits of the manual and messed up a couple of times, you'd posted your own solution. I've posted mine as well, because it is a bit simpler and involves fewer calculations with pgfmath (always a good thing given how slow it is). however, I will delete it if you'd prefer. Commented Dec 26, 2024 at 21:55

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.