为 TikZ 电路创建自定义逻辑符号

为 TikZ 电路创建自定义逻辑符号

我想在 TikZcircuit库中使用自定义逻辑符号。例如 7400 系列的一些符号。轻松创建无法与circuit库一起使用的不同符号的最佳方法是什么?

这里是 74hc238 的一个示例:

74hc238

答案1

代码

\documentclass[tikz]{standalone}
\usetikzlibrary{circuits.ee.IEC}
\makeatletter
\let\pgfutil@Alph\@Alph % should be the proper definition for use outside of LaTeX
\let\pgfutil@alph\@alph % dito
\pgfmathdeclarefunction{Alph}{1}{%
  \begingroup\edef\pgfmathresult{\pgfutil@Alph{#1}}%
  \pgfmath@smuggleone\pgfmathresult\endgroup}
\pgfmathdeclarefunction{alph}{1}{%
  \begingroup\edef\pgfmathresult{\pgfutil@alph{#1}}%
  \pgfmath@smuggleone\pgfmathresult\endgroup}
\pgfdeclareshape{gLogic}{%
  \savedmacro\gLogicparameters{%
    \pgfmathtruncatemacro\eports{\pgfkeysvalueof{/pgf/gLogic east ports}}%
    \pgfmathtruncatemacro\wports{\pgfkeysvalueof{/pgf/gLogic west ports}}%
    \pgfmathtruncatemacro\nports{\pgfkeysvalueof{/pgf/gLogic north ports}}%
    \pgfmathtruncatemacro\sports{\pgfkeysvalueof{/pgf/gLogic south ports}}%
    \addtosavedmacro\eports \addtosavedmacro\wports
    \addtosavedmacro\nports \addtosavedmacro\sports
    \let\pgf@gLogic@i\relax
    \let\pgf@gLogic@n\relax
    \edef\efunction{\pgfkeysvalueof{/pgf/@gLogic east function/.@cmd}{\pgf@gLogic@i}{\pgf@gLogic@n}\pgfeov}
    \edef\wfunction{\pgfkeysvalueof{/pgf/@gLogic west function/.@cmd}{\pgf@gLogic@i}{\pgf@gLogic@n}\pgfeov}
    \edef\nfunction{\pgfkeysvalueof{/pgf/@gLogic north function/.@cmd}{\pgf@gLogic@i}{\pgf@gLogic@n}\pgfeov}
    \edef\sfunction{\pgfkeysvalueof{/pgf/@gLogic south function/.@cmd}{\pgf@gLogic@i}{\pgf@gLogic@n}\pgfeov}
    \addtosavedmacro\efunction \addtosavedmacro\wfunction
    \addtosavedmacro\nfunction \addtosavedmacro\sfunction
  }
  \saveddimen\pinlength{\pgfmathsetlength\pgf@x{\pgfkeysvalueof{/pgf/gLogic pin length}}}%
  \inheritsavedanchors[from=rectangle ee]
  \inheritanchor[from=rectangle ee]{center}
  \inheritanchor[from=rectangle ee]{north}
  \inheritanchor[from=rectangle ee]{south}
  \inheritanchor[from=rectangle ee]{east}
  \inheritanchor[from=rectangle ee]{west}
  \inheritanchor[from=rectangle ee]{north east}
  \inheritanchor[from=rectangle ee]{north west}
  \inheritanchor[from=rectangle ee]{south east}
  \inheritanchor[from=rectangle ee]{south west}
  \inheritanchor[from=rectangle ee]{input} % eh?
  \inheritanchor[from=rectangle ee]{output}% eh?
  \inheritanchorborder[from=rectangle ee]
  \inheritbackgroundpath[from=rectangle ee]
  \behindbackgroundpath{%
    \pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/gLogic pin length}}%
    \pgfmathtruncatemacro\pgf@gLogic@t{\eports+\nports+\wports+\sports}%
    \pgfextract@process\southeast{\csname pgf@anchor@gLogic@south east\endcsname}%
    \pgfextract@process\northwest{\csname pgf@anchor@gLogic@north west\endcsname}%
    \c@pgf@counta\eports
    \let\pgf@gLogic@n\eports
    \pgfmathloop\ifnum\c@pgf@counta>0
      \let\pgf@gLogic@i\pgfmathcounter
      \pgfextract@process\pgf@temp{\pgfpointlineattime{\efunction}{\southeast}{\northeast}}%
      \pgfpathmoveto{\pgf@temp}%
      \pgfpathlineto{\pgfpointadd{\pgf@temp}{\pgfqpoint{\pgfutil@tempdima}{0pt}}}%
      \advance\c@pgf@counta-1
      \pgftext[bottom,left,at=\pgf@temp,y=2\pgflinewidth,x=2\pgflinewidth]{\pgfkeysvalueof{/pgf/@gLogic east label/.@cmd}{\pgf@gLogic@i}{\pgf@gLogic@n}{\pgf@gLogic@t}\pgfeov}
    \repeatpgfmathloop
    \pgf@gLogic@makeanchors{e}{\csname pgf@anchor@gLogic@south east\endcsname}{\csname northeast\endcsname}{\noexpand\pinlength}{0pt}%
    %
    \c@pgf@counta\nports
    \let\pgf@gLogic@n\nports
    \pgfmathloop\ifnum\c@pgf@counta>0
      \let\pgf@gLogic@i\pgfmathcounter
      \pgfextract@process\pgf@temp{\pgfpointlineattime{\nfunction}{\northeast}{\northwest}}%
      \pgfpathmoveto{\pgf@temp}%
      \pgfpathlineto{\pgfpointadd{\pgf@temp}{\pgfqpoint{0pt}{\pgfutil@tempdima}}}%
      \advance\c@pgf@counta-1
      \pgftext[right,bottom,at=\pgf@temp,x=-2\pgflinewidth,y=2\pgflinewidth]{\pgfkeysvalueof{/pgf/@gLogic north label/.@cmd}{\pgf@gLogic@i}{\pgf@gLogic@n}{\pgf@gLogic@t}\pgfeov}
    \repeatpgfmathloop
    \pgf@gLogic@makeanchors{n}{\csname northeast\endcsname}{\csname pgf@anchor@gLogic@north west\endcsname}{0pt}{\noexpand\pinlength}%
    %
    \c@pgf@counta\wports
    \let\pgf@gLogic@n\wports
    \pgfmathloop\ifnum\c@pgf@counta>0
      \let\pgf@gLogic@i\pgfmathcounter
      \pgfextract@process\pgf@temp{\pgfpointlineattime{\wfunction}{\northwest}{\southwest}}%
      \pgfpathmoveto{\pgf@temp}%
      \pgfpathlineto{\pgfpointadd{\pgf@temp}{\pgfqpoint{-\pgfutil@tempdima}{0pt}}}%
      \advance\c@pgf@counta-1
      \pgftext[bottom,right,at=\pgf@temp,y=2\pgflinewidth,x=-2\pgflinewidth]{\pgfkeysvalueof{/pgf/@gLogic west label/.@cmd}{\pgf@gLogic@i}{\pgf@gLogic@n}{\pgf@gLogic@t}\pgfeov}
    \repeatpgfmathloop
    \pgf@gLogic@makeanchors{w}{\csname pgf@anchor@gLogic@north west\endcsname}{\csname southwest\endcsname}{-\noexpand\pinlength}{0pt}%
    %
    \c@pgf@counta\sports
    \let\pgf@gLogic@n\sports
    \pgfmathloop\ifnum\c@pgf@counta>0
      \let\pgf@gLogic@i\pgfmathcounter
      \pgfextract@process\pgf@temp{\pgfpointlineattime{\sfunction}{\southwest}{\southeast}}%
      \pgfpathmoveto{\pgf@temp}%
      \pgfpathlineto{\pgfpointadd{\pgf@temp}{\pgfqpoint{0pt}{-\pgfutil@tempdima}}}%
      \advance\c@pgf@counta-1
      \pgftext[right,top,at=\pgf@temp,x=-2\pgflinewidth,y=-2\pgflinewidth]{\pgfkeysvalueof{/pgf/@gLogic south label/.@cmd}{\pgf@gLogic@i}{\pgf@gLogic@n}{\pgf@gLogic@t}\pgfeov}%
    \repeatpgfmathloop
    \pgf@gLogic@makeanchors{s}{\csname southwest\endcsname}{\csname pgf@anchor@gLogic@south east\endcsname}{0pt}{-\noexpand\pinlength}%
  }
}
\def\pgf@gLogic@makeanchors#1#2#3#4#5{%
  \c@pgf@counta\pgf@gLogic@n
  \let\pgf@gLogic@n\relax
  \pgfmathloop%
    \ifnum\c@pgf@counta>0\relax%
      \pgfutil@ifundefined{pgf@anchor@gLogic@#1Pin\space\the\c@pgf@counta}{%
        \expandafter\xdef\csname pgf@anchor@gLogic@#1Pin\space\the\c@pgf@counta\endcsname{%
          \noexpand\gLogicparameters
          \let\noexpand\pgf@gLogic@n\expandafter\noexpand\csname #1ports\endcsname
          \edef\noexpand\pgf@gLogic@i{\the\c@pgf@counta}%
          \noexpand\pgfpointadd{\noexpand\pgfpointlineattime
            {\expandafter\noexpand\csname #1function\endcsname}{\expandafter\noexpand#2}{\expandafter\noexpand#3}}{\noexpand\pgfqpoint{#4}{#5}}%
        }%
      }{\c@pgf@counta0\relax}% 
    \advance\c@pgf@counta-1\relax%
  \repeatpgfmathloop%  
}
\makeatother
\pgfset{
  gLogic east ports/.initial =2,
  gLogic west ports/.initial =2,
  gLogic north ports/.initial=2,
  gLogic south ports/.initial=2,
  gLogic ports/.style args={#1:#2:#3:#4}{
    /pgf/gLogic east ports ={#1},/pgf/gLogic west ports ={#3},
    /pgf/gLogic north ports={#2},/pgf/gLogic south ports={#4}},
  set gLogic east function/.style ={/pgf/@gLogic east function/.code 2 args={#1}},
  set gLogic west function/.style ={/pgf/@gLogic west function/.code 2 args={#1}},
  set gLogic north function/.style={/pgf/@gLogic north function/.code 2 args={#1}},
  set gLogic south function/.style={/pgf/@gLogic south function/.code 2 args={#1}},
  set gLogic east function ={(#1)/(#2+1)}, set gLogic west function ={(#1)/(#2+1)},
  set gLogic north function={(#1)/(#2+1)}, set gLogic south function={(#1)/(#2+1)},
  gLogic pin length/.initial=+2\tikzcircuitssizeunit,
  set gLogic west label/.style={/pgf/@gLogic west label/.code n args={3}{#1}},
  set gLogic east label/.style={/pgf/@gLogic east label/.code n args={3}{#1}},
  set gLogic north label/.style={/pgf/@gLogic north label/.code n args={3}{#1}},
  set gLogic south label/.style={/pgf/@gLogic south label/.code n args={3}{#1}},
  set gLogic east label ={\scriptsize\pgfmathprint{Alph(#1)}},%
  set gLogic north label={\scriptsize\pgfmathprint{Alph(\eports+#1)}},%
  set gLogic west label ={\scriptsize\pgfmathprint{Alph(\eports+\nports+#1)}},%
  set gLogic south label={\scriptsize\pgfmathprint{Alph(\eports+\nports+\wports+#1)}},%
}
\tikzset{
  circuit declare symbol=gLogic,
  set gLogic graphic={draw, shape=gLogic, circuit symbol size=width 6 height 15, outer sep=+.5\pgflinewidth}
}
\begin{document}
\begin{tikzpicture}
  \node[gLogic,
    gLogic ports=8:0:6:0,
    align=center,
    set gLogic west function={ifthenelse(#1<4,#1,(#1+2))/9},
    set gLogic east label={\scriptsize$Y_{\pgfmathprint{int(\eports-#1+1)}}$},
    set gLogic west label={\scriptsize\ifnum#1<4\pgfmathprint{Alph(#1)}\else$E_{\pgfmathprint{int(#1-3)}}$\fi}] (n) {R2D2-\\Decoder};
  \draw (n.ePin 1) to[bend right] (n.ePin 8);
  \draw (n.wPin 1) to [bend right] (n.wPin 3);

  \node[gLogic, circuit symbol size=width 4 height 8] (m) at (4,0) {};
  \draw (m.ePin 1) to [bend right] (m.ePin 2);
  \draw (m.wPin 1) to [bend right] (m.wPin 2);

  \draw[line cap=rect] (n.ePin 2) --++ (right:.5cm) |- (m.sPin 1);
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

答案2

我刚刚开始创建自定义形状。结果看起来还不错:

结果

实际上我只有很少的时间和一点 TeX 经验。无论如何我都会发布它,但要注意:有龙!只有勇敢的灵魂才能继续。任何提示和帮助都值得感激 ;)

\documentclass{article}
\usepackage{etoolbox}
\usepackage{tikz}
\usetikzlibrary{circuits.ee.IEC}

\usetikzlibrary{positioning}


\makeatletter

%TODO allow easier usage, like:
%\node[glogic={parameter=name,...}] {};
%TODO better input?

%TODO remove max values
\def\maxVPins{20}
\def\maxHPins{20}

\newcounter{pinCounter}
\def\getPinNumber#1{\csname #1Pin\Roman{pinCounter}\endcsname}

\tikzset{%
    gLogic/pin spacing/.initial=3mm,
    gLogic/contact length/.initial=10pt,
    gLogic/horizontal pins/.initial=2,
    gLogic/vertical pins/.initial=2,
    gLogic/pin labels/.initial={},
    gLogic/bottom text/.initial=\empty,
}


\pgfdeclareshape{gLogic}{
    \savedanchor{\upperrightcorner}{
        \pgf@y=.5\ht\pgfnodeparttextbox %
        \pgf@x=.5\wd\pgfnodeparttextbox %
    }

    \anchor{text}{%
        \upperrightcorner%
        \pgf@x=-\pgf@x%
        \pgf@y=-\pgf@y%
    }

    \anchor{center}{\pgfpointorigin}

    \def\pinspacing{\noexpand\pgfkeysvalueof{/tikz/gLogic/pin spacing}}
    \def\myWidth{\pinspacing*\noexpand\pgfkeysvalueof{/tikz/gLogic/horizontal pins}}
    \def\myHight{\pinspacing*\noexpand\pgfkeysvalueof{/tikz/gLogic/vertical pins}}

    %create some anchors to make the positioning library happy ;)
    \edef\defineAnchors{%
        \noexpand\deferredanchor{south west}{\noexpand\pgfpoint{-\myHight/2}{-\myWidth/2}}%
        \noexpand\anchor{south}{\noexpand\pgfpoint{0pt}{-\myWidth/2}}%
        \noexpand\anchor{south east}{\noexpand\pgfpoint{\myHight/2}{-\myWidth/2}}%
        \noexpand\anchor{east}{\noexpand\pgfpoint{\myHight/2}{0pt}}%
        \noexpand\anchor{north east}{\noexpand\pgfpoint{\myHight/2}{\myWidth/2}}%
        \noexpand\anchor{north}{\noexpand\pgfpoint{0pt}{\myWidth/2}}%
        \noexpand\anchor{north west}{\noexpand\pgfpoint{-\myHight/2}{\myWidth/2}}%
        \noexpand\anchor{west}{\noexpand\pgfpoint{-\myHight/2}{0pt}}}
    \defineAnchors

    %TODO make this prettier...
    \def\createAnchorsB{%
        \noexpand\savedanchor\getPinNumber{b}{\noexpand\pgfpoint{\pinspacing * (\n-.5)-\myWidth/2}{-\myHight/2}}%
        \noexpand\anchor{pinB\n}{\getPinNumber{b}}%
    }

    \def\createAnchorsT{%
        \noexpand\savedanchor\getPinNumber{t}{\noexpand\pgfpoint{-\pinspacing * (\n-.5)+\myWidth/2}{\myHight/2}}%
        \noexpand\anchor{pinT\n}{\getPinNumber{t}}%
    }

    \def\createAnchorsL{%
        \noexpand\savedanchor\getPinNumber{l}{\noexpand\pgfpoint{-\myWidth/2}{-\pinspacing * (\n-.5)+\myHight/2}}%
        \noexpand\anchor{pinL\n}{\getPinNumber{l}}%
    }

    \def\createAnchorsR{%
        \noexpand\savedanchor\getPinNumber{r}{\noexpand\pgfpoint{\myWidth/2}{\pinspacing * (\n-.5)-\myHight/2}}%
        \noexpand\anchor{pinR\n}{\getPinNumber{r}}%
    }

    %TODO remove max values and use the real values (some expansion problem)
    \foreach \n  in {1,...,\maxVPins} {
        \pgfmathsetcounter{pinCounter}{\n}
        \edef\expandThis{%
            \createAnchorsL
            \createAnchorsR
        }
        \expandThis
    }
    \foreach \n  in {1,...,\maxHPins} {
        \pgfmathsetcounter{pinCounter}{\n}
        \edef\expandThis{%
            \createAnchorsB%
            \createAnchorsT
        }
        \expandThis
    }


    \foregroundpath{
        \edef\myLabels{\pgfkeysvalueof{/tikz/gLogic/pin labels}}

        %TODO look for a cleaner solution
        \foreach \x [count=\n] in \myLabels {
            \ifx \x\empty\else%don't draw connectors without label
            \ifnumcomp{\n}{<}{\pgfkeysvalueof{/tikz/gLogic/horizontal pins}+1}{
                %bootom row
                \pgfmathsetcounter{pinCounter}{\n}
                \pgfpathmoveto{\getPinNumber{b}}
                \pgftext[top, right,at= \pgfpointadd{\pgfpoint{-1pt}{-1pt}}{\getPinNumber{b}}]{\scriptsize \x}
                \pgfpathlineto{\pgfpointadd{\getPinNumber{b}}{\pgfpoint{0}{-\pgfkeysvalueof{/tikz/gLogic/contact length}}}}
            }{\ifnumcomp{\n}{<}{\pgfkeysvalueof{/tikz/gLogic/horizontal pins}+\pgfkeysvalueof{/tikz/gLogic/vertical pins}+1}{
                %right column
                \pgfmathparse{\n-\pgfkeysvalueof{/tikz/gLogic/horizontal pins}};
                \pgfmathsetcounter{pinCounter}{\pgfmathresult}
                \pgftext[base, left,at= \pgfpointadd{\pgfpoint{2pt}{1pt}}{\getPinNumber{r}}]{\scriptsize \x}
                \pgfpathmoveto{\getPinNumber{r}}
                \pgfpathlineto{\pgfpointadd{\getPinNumber{r}}{\pgfpoint{\pgfkeysvalueof{/tikz/gLogic/contact length}}{0}}}
            }{\ifnumcomp{\n}{<}{2*\pgfkeysvalueof{/tikz/gLogic/horizontal pins}+\pgfkeysvalueof{/tikz/gLogic/vertical pins}+1}{
                %top row
                \pgfmathparse{\n-\pgfkeysvalueof{/tikz/gLogic/horizontal pins}-\pgfkeysvalueof{/tikz/gLogic/vertical pins}};
                \pgfmathsetcounter{pinCounter}{\pgfmathresult}
                \pgftext[bottom, right, at=\pgfpointadd{\pgfpoint{-1pt}{1pt}}{\getPinNumber{t}}]{\scriptsize \x}
                \pgfpathmoveto{\getPinNumber{t}}
                \pgfpathlineto{\pgfpointadd{\getPinNumber{t}}{\pgfpoint{0}{\pgfkeysvalueof{/tikz/gLogic/contact length}}}}
            }{\ifnumcomp{\n}{<}{2*\pgfkeysvalueof{/tikz/gLogic/horizontal pins}+2*\pgfkeysvalueof{/tikz/gLogic/vertical pins}+1}{
                %left column
                \pgfmathparse{\n-2*\pgfkeysvalueof{/tikz/gLogic/horizontal pins}-\pgfkeysvalueof{/tikz/gLogic/vertical pins}};
                \pgfmathsetcounter{pinCounter}{\pgfmathresult}
                \pgftext[base, right, at=\pgfpointadd{\pgfpoint{-2pt}{1pt}}{\getPinNumber{l}}]{\scriptsize \x}
                \pgfpathmoveto{\getPinNumber{l}}
                \pgfpathlineto{\pgfpointadd{\getPinNumber{l}}{\pgfpoint{-\pgfkeysvalueof{/tikz/gLogic/contact length}}{0}}}
            }{}}}}\fi%closing all the ifs ;-/
        }

        %TODO don't define them twice with different expanding behaviours?
        \def\myWidth{\pgfkeysvalueof{/tikz/gLogic/horizontal pins}%
            *\pgfkeysvalueof{/tikz/gLogic/pin spacing}}
        \def\myHight{\pgfkeysvalueof{/tikz/gLogic/vertical pins}%
            *\pgfkeysvalueof{/tikz/gLogic/pin spacing}}

        \pgftext[bottom, at=\pgfpoint{-0pt}{-\myHight/2+2pt}]{\footnotesize \pgfkeysvalueof{/tikz/gLogic/bottom text}}

        % rectangle around the logic gate
        \pgfpathrectanglecorners{\pgfpoint{-\myWidth/2}{-\myHight/2}}%
            {\pgfpoint{\myWidth/2}{\myHight/2}}

        \pgfusepath{draw}% draw all the lines :D
    }
}

\makeatother

\begin{document}

\def\labels{A,B,C,D,E, F, G, H, I, J,K, L, M, N,O, P, Q, R, S, T}

\begin{tikzpicture}[circuit ee IEC]
    \node[gLogic, gLogic/pin spacing=7mm, gLogic/horizontal pins=3, gLogic/pin labels={A,B,~,D,,F}] (IC1) {funny IC};

    \node[gLogic, gLogic/pin spacing=5mm, gLogic/horizontal pins=4, gLogic/vertical pins=6, gLogic/pin labels=\labels, gLogic/bottom text=IC-42-42, above right=3 of IC1] (IC2) {IC};


    \draw (IC1.pinR1)  to [diode={light emitting, name=LED}] ($(IC1.pinR1)+(2,0)$) -| (IC2.pinB4);
\end{tikzpicture}


\end{document}

相关内容