更新:

更新:

有更新,见下文

我正在设计 mosfet 符号,应该可以翻转。翻转的关键在于与定位库应该保持不变,例如,将镜像节点放置在镜像节点的右侧应该与放置在“正常”节点右侧的“正常”节点保持相同的距离。为此,我考虑使用.is if处理程序并相应地替换锚点和背景路径。在使用原始代码尝试此操作时,我可以更改路径,但不能更改锚点。在为此处的问题创建 MWE 时,我做错了什么,所以现在 .is if 处理程序什么也不做。现在我很困惑。有人能给我指出正确的方向吗?

注意:我知道xscale=-1镜像节点的解决方案,但这需要手动覆盖节点的相关锚点。我想避免这种情况,并且我愿意接受各种(优雅/易于使用的)解决方案。

以下是 MWE:

\documentclass[parskip=half]{scrartcl}

\pagestyle{empty}

\usepackage{tikz}
\usetikzlibrary{positioning}

\newif\ifmirrorshape
\pgfkeys{
    /tikz/mirror/.is if=mirrorshape
}

\pgfdeclareshape{testshape}
{
    \ifmirrorshape
        \savedanchor{\center}{
            \pgfpointorigin
        }
        \savedanchor{\left}{
            \pgfpointadd{\pgfpointorigin}{\pgfpoint{0.5cm}{0cm}}
        }
        \savedanchor{\upperright}{
            \pgfpointadd{\pgfpointorigin}{\pgfpoint{-0.5cm}{0.5cm}}
        }
        \savedanchor{\lowerright}{
            \pgfpointadd{\pgfpointorigin}{\pgfpoint{-0.5cm}{-0.5cm}}
        }
        \anchor{center}{\center}
        \anchor{north}{\pgfpointadd{\pgfpointorigin}{\pgfpoint{0cm}{0.25cm}}}
        \anchor{south}{\pgfpointadd{\pgfpointorigin}{\pgfpoint{0cm}{-0.25cm}}}
        \anchor{west}{\left}
        \anchor{east}{\pgfpointadd{\pgfpointorigin}{\pgfpoint{-0.5cm}{0cm}}}
    \else
        \savedanchor{\center}{
            \pgfpointorigin
        }
        \savedanchor{\left}{
            \pgfpointadd{\pgfpointorigin}{\pgfpoint{-0.5cm}{0cm}}
        }
        \savedanchor{\upperright}{
            \pgfpointadd{\pgfpointorigin}{\pgfpoint{0.5cm}{0.5cm}}
        }
        \savedanchor{\lowerright}{
            \pgfpointadd{\pgfpointorigin}{\pgfpoint{0.5cm}{-0.5cm}}
        }
        \anchor{center}{\center}
        \anchor{north}{\pgfpointadd{\pgfpointorigin}{\pgfpoint{0cm}{0.25cm}}}
        \anchor{south}{\pgfpointadd{\pgfpointorigin}{\pgfpoint{0cm}{-0.25cm}}}
        \anchor{west}{\left}
        \anchor{east}{\pgfpointadd{\pgfpointorigin}{\pgfpoint{0.5cm}{0cm}}}
    \fi
    \backgroundpath{
        \pgfpathmoveto{\left}
        \pgfpathlineto{\upperright}
        \pgfpathlineto{\lowerright}
        \pgfpathclose
        \pgfusepath{stroke}
    }
}

\begin{document}
\begin{tikzpicture}[every node/.style={align=center}]
    \node[testshape] (s1) at(0, 0) { };
    \node[red, testshape, right=of s1, mirror] { };
\end{tikzpicture}
\end{document}

在此处输入图片描述

更新:

我对 @cfr 的回答进行了进一步的了解,但仍然不太正确。我需要的是根据“镜像状态”放置锚点(外部可见,我不关心内部)。

以下是一个例子:

\newif\ifmirrorshape
\pgfkeys{
    /tikz/mirror/.is if=mirrorshape
}

\pgfdeclareshape{testshape}
{
    \savedanchor{\center}{
        \pgfpointorigin
    }
    \savedanchor{\left}{
        \pgfpointadd{\pgfpointorigin}{\pgfpoint{-0.5cm}{0cm}}
    }
    \savedanchor{\right}{
        \pgfpointadd{\pgfpointorigin}{\pgfpoint{0.5cm}{0cm}}
    }
    \savedanchor{\upperright}{
        \pgfpointadd{\pgfpointorigin}{\pgfpoint{0.5cm}{0.5cm}}
    }
    \savedanchor{\lowerright}{
        \pgfpointadd{\pgfpointorigin}{\pgfpoint{0.5cm}{-0.5cm}}
    }
    \savedanchor{\upperleft}{
        \pgfpointadd{\pgfpointorigin}{\pgfpoint{-0.5cm}{0.5cm}}
    }
    \savedanchor{\lowerleft}{
        \pgfpointadd{\pgfpointorigin}{\pgfpoint{-0.5cm}{-0.5cm}}
    }
    \anchor{center}{\center}
    \anchor{north}{\pgfpointadd{\pgfpointorigin}{\pgfpoint{0cm}{0.25cm}}}
    \anchor{south}{\pgfpointadd{\pgfpointorigin}{\pgfpoint{0cm}{-0.25cm}}}
    \anchor{right}{\right}
    \anchor{left}{\left}
    \anchor{west}{\left}
    \anchor{east}{\right}
    \backgroundpath{
        \ifmosfetmirror
            \pgfpathmoveto{\right}
            \pgfpathlineto{\upperleft}
            \pgfpathlineto{\lowerleft}
        \else
            \pgfpathmoveto{\left}
            \pgfpathlineto{\upperright}
            \pgfpathlineto{\lowerright}
        \fi
        \pgfpathclose
        \pgfusepath{stroke}
    }
}

测试用例:

\begin{tikzpicture}[every node/.style={align=center}]
    \node[testshape] (s1) { };
    \node[testshape, mirror, right=of s1] (s2) { };
\end{tikzpicture}

我尝试以不同的方式放置 \savedanchor(不起作用):

\ifmirrorshape
    \savedanchor...
\else
    \savedanchor...
\fi

我试图在 \deferredanchor 中更改锚点(不起作用):

\deferredanchor{...}{\ifmirrorshape ... \else ... \fi}

我不知道如何解决这个问题,如能得到任何帮助我将不胜感激。

答案1

我认为您正在尝试使用在使用时不合法的方法。特别是,您需要区分定义形状时执行的代码和调用形状时执行的代码。

请注意,为了使定位按预期工作,我认为您希望将westeast锚点放置在西边和东边,而不是在节点镜像时翻转。

保存镜像敏感锚点的关键在于仔细考虑何时执行哪些代码。

\documentclass[border=10pt,multi,tikz]{standalone}
\usetikzlibrary{positioning}

\newif\ifmirrorshape
\tikzset{
  mirror me/.is if=mirrorshape
}
\makeatletter
\newdimen\pgf@testxb
\newdimen\pgf@testxa
\pgfdeclareshape{testshape}
{
  \savedanchor{\center}{%
    \pgfpointorigin
  }%
  \anchor{center}{\center}
  \anchor{north}{%
      \pgfpointorigin
      \pgf@x=0pt
      \pgf@y=2.5mm
  }%
  \anchor{south}{%
      \pgfpointorigin
      \pgf@x=0pt
      \pgf@y=-2.5mm
  }%
  \anchor{west}{%
    \pgfpointorigin
    \pgf@x=-5mm
    \pgf@y=0pt
  }%
  \anchor{east}{%
    \pgfpointorigin
    \pgf@x=5mm
    \pgf@y=0pt
  }%
  \savedanchor{\apex}{%
    \pgfpointorigin
    \ifmirrorshape
      \pgf@x=5mm
    \else
      \pgf@x=-5mm
    \fi
    \pgf@y=0pt
  }%
  \savedanchor{\base}{%
    \pgfpointorigin
    \ifmirrorshape
      \pgf@x=-5mm
    \else
      \pgf@x=5mm
    \fi
    \pgf@y=0pt
  }%
  \savedanchor{\upbase}{%
    \pgfpointorigin
    \ifmirrorshape
      \pgf@x=-5mm
    \else
      \pgf@x=5mm
    \fi
    \pgf@y=5mm
  }%
  \savedanchor{\downbase}{%
    \pgfpointorigin
    \ifmirrorshape
      \pgf@x=-5mm
    \else
      \pgf@x=5mm
    \fi
    \pgf@y=-5mm
  }%
  \deferredanchor{apex}{%
    \apex
  }%
  \deferredanchor{base}{%
    \base
  }%
  \deferredanchor{upper base}{%
    \upbase
  }%
  \deferredanchor{lower base}{%
    \downbase
  }%
  \backgroundpath{%
    \ifmirrorshape
      \pgf@testxa=5mm
      \pgf@testxb=-5mm
    \else
      \pgf@testxa=-5mm
      \pgf@testxb=5mm
    \fi
    \pgfpathmoveto{\pgfpoint{\pgf@testxa}{0pt}}%
    \pgfpathlineto{\pgfpoint{\pgf@testxb}{5mm}}%
    \pgfpathlineto{\pgfpoint{\pgf@testxb}{-5mm}}%
    \pgfpathclose
  }%
}
\makeatother
\begin{document}
\begin{tikzpicture}[every node/.style={align=center}]
  \node [testshape, draw, minimum size=15mm] (s1) at (0,0) { };
  \node (s2) [red, mirror me, testshape, draw, right=15mm of s1, minimum size=15mm] { };
  \foreach \i/\k/\l in {center/below/gray,north/above/gray,south/below/gray,west/left/gray,east/right/gray,apex/above/blue!50!cyan,base/above/magenta,upper base/above/orange,lower base/below/green!50!black}
  \foreach \j in {1,2}
  \path [fill, fill opacity=.5, text opacity=1, draw opacity=1, \l] (s\j.\i) circle (1pt) node [\k, font=\tiny, \l] {\i};
\end{tikzpicture}
\end{document}

镜像节点

\backgroundpath不应该绘制或填充任何东西。如果总是要绘制路径,则\beforebackgroundpath应该使用。虽然手册没有说明原因,但这不可能是灵活性的问题:绘制路径\beforebackgroundpath与绘制路径一样不灵活\backgroundpath。我怀疑有些情况下绘制路径\backgroundpath会做错事,因为绘制是在节点构造的不同点完成的。因此,除非你的 TikZ 代码从不将某些技术与你的自定义节点混合使用,否则描边这条路径可能会在某些时候导致令人讨厌的意外。这些技术不需要非常奇特。如果将节点作为的一部分进行描边,则以下任何一种方法都无法正常工作\backgroundpath

  • fill=yellow
  • drop shadow(当然,无论如何我都不想在没有填充的情况下使用它)

当然,更多奇特的事物也可能会失败。

相关内容