
Tikz имеет кучу полезных цифровых компонентов схем, базовых или сложных. Здесь мне нужнонекоторыйиз моих собственных, не обязательно даже из удобных. Но давайте возьмем один, довольно удобный пример: Компаратор величин.
Я хотел бы иметь этокомпаратор величинкомпонент для моей задачи, с его сигнальными портами, определенными как anchor
s. Я могу сделать коробку с метками на портах и именем на ней, но этонедостаточно!
Мне нужно показать, что внутри. Подробности не должны выходить за рамки ворот, я не хочу, чтобы транзисторы были рядом, но мне нужны воротца.
Вот что у меня на руках на данный момент, большая часть из этого просто скопирована/подражаемаэтот (знаменитый?) пример переворота данных:
\makeatletter
% Magnitude Comparator (magn comparator) shape
\pgfdeclareshape{magn comparator}
{
% The 'minimum width' and 'minimum height' keys, not the content, determine
% the size
\savedanchor\northeast
{%
\pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
\pgfmathsetlength\pgf@y{\pgfshapeminheight}%
\pgf@x=0.5\pgf@x
\pgf@y=0.5\pgf@y
}
% This is redundant, but makes some things easier:
\savedanchor\southwest
{%
\pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
\pgfmathsetlength\pgf@y{\pgfshapeminheight}%
\pgf@x=-0.5\pgf@x
\pgf@y=-0.5\pgf@y
}
% Inherit from rectangle
\inheritanchorborder[from=rectangle]
% Define same anchor a normal rectangle has
\anchor{center}{\pgfpointorigin}
\anchor{north}{\northeast \pgf@x=0pt}
\anchor{east}{\northeast \pgf@y=0pt}
\anchor{south}{\southwest \pgf@x=0pt}
\anchor{west}{\southwest \pgf@y=0pt}
\anchor{north east}{\northeast}
\anchor{north west}{\northeast \pgf@x=-\pgf@x}
\anchor{south west}{\southwest}
\anchor{south east}{\southwest \pgf@x=-\pgf@x}
\anchor{text}
{
\pgfpointorigin
\advance\pgf@x by -.5\wd\pgfnodeparttextbox%
\advance\pgf@y by -.5\ht\pgfnodeparttextbox%
\advance\pgf@y by +.5\dp\pgfnodeparttextbox%
}
% Define anchors for input signal ports
\anchor{input gt}
{
\pgf@process{\southwest}%
\pgf@y=-.5\pgf@y%
}
\anchor{input eq}
{
\pgf@process{\southwest}%
\pgf@y=0pt%
}
\anchor{input lt}
{
\pgf@process{\southwest}%
\pgf@y=.5\pgf@y%
}
\anchor{input a}
{
\pgf@process{\northeast}%
\pgf@x=-.3\pgf@x%
}
\anchor{input b}
{
\pgf@process{\northeast}%
\pgf@x=.3\pgf@x%
}
% Define anchors for output signal ports
\anchor{output gt}
{
\pgf@process{\northeast}%
\pgf@y=.5\pgf@y%
}
\anchor{output eq}
{
\pgf@process{\northeast}%
\pgf@y=0pt%
}
\anchor{output lt}
{
\pgf@process{\northeast}%
\pgf@y=-.5\pgf@y%
}
% Draw the rectangle box and the port labels
\backgroundpath
{
% Rectangle box
\pgfpathrectanglecorners{\southwest}{\northeast}
% \node [and gate] (kek) at (0, 0) {};
}
}
% Define default style for this node
\tikzset
{
every magn comparator node/.style =
{
draw,
minimum width = 2cm,
minimum height = 2cm,
thick,
inner sep = 1mm,
outer sep = 0pt,
cap = round
}
}
\makeatother
Это отдельный файл, который я включаю в преамбулу моего основного файла LaTeX.
Здесь нет никаких вентилей, он просто рисует ящик. Я попытался просто поставить случайный вентиль И обычным способом, который я делаю вне этой \pgfdeclareshape
штуки, что, конечно, не сработало. Я закомментировал это, эту попытку.
Должен быть способ определить дополнительные формы поверх существующих. Что это?
Редактировать:Я ожидаю, что у меня в руках окажется что-то вроде этого, что я смогу разместить и к портам которого я смогу легко добраться как к якорям, подобно тому, как это происходит с вентилем AND/OR/NOR/XOR/NAND:
Обратите внимание, что внутренняя часть коробки на самом деле не выполняет функцию компаратора величин, это просто фиктивный пример того, что я ожидаю.
решение1
В зависимости от сложности ваших вариантов использования и того, сколько таких форм вам нужно... вот начало.
Ответ состоит в следующем:
Декларация формы, которая заимствует
rectangle ee
определение изcircuits.ee
(которая является просто заимствованнойrectangle
формой с якорями.input
и.output
).Я также заимствую из ссылкиTeXampleдля текста внутри определения фигуры. Якоря устанавливаются с помощью
\pgfpointlineattime
(это похоже наpos
ключ вдоль прямой линии или фактор внутриcalc
нотации($(<p1>)!<factor>!(<p2>)$)
).Если у вас есть намного больше таких фигур, которым нужно несколько разных якорей вдоль границы прямоугольника, это можно сериализовать с помощью ключей fey и цикла внутри объявления фигуры. Это также применимо к текстам.
Теперь, когда у нас есть форма с якорями и текстами, мы можем ее использовать. Для правильной формы схемы мы объявляем символ с помощью
circuit declare symbol
и устанавливаем его с помощьюset <symbol name> graphic
.Ключи
circuit symbol size
устанавливаютminimum width
иminimum height
по отношению кcircuit symbol unit
(измерение TeX под капотом). Это делает его масштабируемым по отношению к другим символам схемы. Ключtransform shape
необходим для вращения поcircuits
'to
путям.A
path picture
, который использует предложенный код изеще один мой ответ. Чтобы настроить локальную систему координат, которая вращается и масштабируется вместе со своим узлом: Координата(0, 0)
находится в центре узла.Иксвектор указывает наeast
(=output
),увектор к северному якорю. Это важно для спецификаций координат, например,(left:.2)
так как он использует.2
половину горизонтального размера узлаиприменяемое вращение.Символы схемы внутри
path picture
получают опцииgray
(как и линии) иcircuit symbol unit=.1cm
которые уменьшают масштаб символов до подходящего размера. Может потребоваться поиграться с этим значением, чтобы получить правильный размер. Также может быть возможно сделать это зависимым от вышеупомянутой локальной системы координат с размерами\pgf@xx
и\pgf@yy
.Очевидно, если вам нужно несколько символов с одинаковой схемой привязки и соединения, но с разными затворами, можно сделать определение фигур гибким в соответствии с тремя ключами-значениями, которые в этом случае будут установлены на
not gate
,nand gate
иnor gate
.
Я использовал свойpaths.ortho
библиотекадля соединений внутри path picture
. Очевидно, что вы можете использовать любой способ для соединения этих линий.
Код
\documentclass[tikz]{standalone}
\usetikzlibrary{circuits.ee,circuits.logic.US,paths.ortho}
\makeatletter
\pgfdeclareshape{my complicated box}{%
\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}
\inheritanchor[from=rectangle ee]{output}
\inheritanchorborder[from=rectangle ee]
\inheritbackgroundpath[from=rectangle ee]
\anchor{eq in} {\pgf@sh@reanchor{\pgf@sm@shape@name}{input}}
\anchor{eq out}{\pgf@sh@reanchor{\pgf@sm@shape@name}{output}}
\anchor{lt in}{%
\pgfpointlineattime{.2}{\southwest}
{\southwest\pgf@xc\pgf@x\northeast\pgf@x\pgf@xc}}
\anchor{gt in}{%
\pgfpointlineattime{.8}{\southwest}
{\southwest\pgf@xc\pgf@x\northeast\pgf@x\pgf@xc}}
\anchor{gt out}{%
\pgfpointlineattime{.3}{\northeast}
{\southwest\pgf@yc\pgf@y\northeast\pgf@y\pgf@yc}}
\anchor{lt out}{%
\pgfpointlineattime{.7}{\northeast}
{\southwest\pgf@yc\pgf@y\northeast\pgf@y\pgf@yc}}
\anchor{a}{%
\pgfpointlineattime{.4}
{\southwest\pgf@xc\pgf@x\northeast\pgf@x\pgf@xc}{\northeast}}
\anchor{b}{%
\pgfpointlineattime{.6}
{\southwest\pgf@xc\pgf@x\northeast\pgf@x\pgf@xc}{\northeast}}
\beforebackgroundpath{%
\begingroup
\tikzset{my complicated box/labels/.try}\tikz@textfont
\pgf@sh@reanchor{\pgf@sm@shape@name}{eq in}
\pgftext[at=\pgfqpoint{\pgf@x}{\pgf@y},left,%
x=\pgfkeysvalueof{/pgf/inner xsep}]{$\mathrm{eq}_{\mathrm{in}}$}
\pgf@sh@reanchor{\pgf@sm@shape@name}{eq out}
\pgftext[at=\pgfqpoint{\pgf@x}{\pgf@y},right,%
x=-\pgfkeysvalueof{/pgf/inner xsep}]{$\mathrm{eq}_{\mathrm{out}}$}
\pgf@sh@reanchor{\pgf@sm@shape@name}{gt in}
\pgftext[at=\pgfqpoint{\pgf@x}{\pgf@y},left,%
x=\pgfkeysvalueof{/pgf/inner xsep}]{$\mathrm{gt}_{\mathrm{in}}$}
\pgf@sh@reanchor{\pgf@sm@shape@name}{gt out}
\pgftext[at=\pgfqpoint{\pgf@x}{\pgf@y},right,%
x=-\pgfkeysvalueof{/pgf/inner xsep}]{$\mathrm{gt}_{\mathrm{out}}$}
\pgf@sh@reanchor{\pgf@sm@shape@name}{lt in}
\pgftext[at=\pgfqpoint{\pgf@x}{\pgf@y},left,%
x=\pgfkeysvalueof{/pgf/inner xsep}]{$\mathrm{lt}_{\mathrm{in}}$}
\pgf@sh@reanchor{\pgf@sm@shape@name}{lt out}
\pgftext[at=\pgfqpoint{\pgf@x}{\pgf@y},right,%
x=-\pgfkeysvalueof{/pgf/inner xsep}]{$\mathrm{lt}_{\mathrm{out}}$}
\pgf@sh@reanchor{\pgf@sm@shape@name}{a}
\pgftext[at=\pgfqpoint{\pgf@x}{\pgf@y},top,%
y=-\pgfkeysvalueof{/pgf/inner ysep}]{a\vphantom{b}}
\pgf@sh@reanchor{\pgf@sm@shape@name}{b}
\pgftext[at=\pgfqpoint{\pgf@x}{\pgf@y},top,%
y=-\pgfkeysvalueof{/pgf/inner ysep}]{b}
\endgroup}
}
\makeatother
\tikzset{my complicated box/labels/.style={font=\footnotesize, inner sep=.1667em}}
\tikzset{
circuit declare symbol=my complicated symbol,
set my complicated symbol graphic={
draw, shape=my complicated box, circuit symbol size=width 10 height 8,
transform shape,
path picture={
\expandafter\let\expandafter\tfn\csname tikz@fig@name\endcsname
\pgftransformshift{\pgfpointanchor{\tfn}{center}}%
\pgfsetxvec{\pgfpointdiff{\pgfpointanchor{\tfn}{center}}
{\pgfpointanchor{\tfn}{east}}}%
\pgfsetyvec{\pgfpointdiff{\pgfpointanchor{\tfn}{center}}
{\pgfpointanchor{\tfn}{north}}}
\tikzset{every circuit symbol/.append style={circuit symbol unit=.1cm, gray}}
\path[thin, draw=gray]
(\tfn.eq in) to[not gate=near end] (\tfn.eq out)
(\tfn.lt out) to ++ (left:.2)
node[anchor=output, logic gate inputs=nn, nand gate] (\tfn-nand) {}
(\tfn-nand.input 2) to[-|-=.6] (\tfn.lt in)
(\tfn-nand.input 1) to[-|] (\tfn.a)
(\tfn.gt out) to ++ (left:.2)
node[anchor=output, logic gate inputs=nn, nor gate] (\tfn-nor) {}
(\tfn-nor.input 2) to[-|-=.6] (\tfn.gt in)
(\tfn-nor.input 1) to[-|] (\tfn.b);
}},
}
\begin{document}
\begin{tikzpicture}[circuit logic US]
\draw (0,0) to[my complicated symbol] ++ (30:4);
\end{tikzpicture}
\end{document}
Выход
решение2
Возможное решение с pics
. Его трудно использовать pic-anchors
для позиционирования (Закрепление фотографий TiKZ), но они служат опорными точками для установления связей между ними.
\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{positioning,circuits.logic.US, fit}
\tikzset{
mycircuit/.pic={
\begin{scope}[circuit logic US]
\node[gray, thick, draw, nor gate] (-gt) at (2,0.75) {};
\node[gray, thick, draw, not gate] (-eq) at (2,0) {};
\node[gray, thick, draw, nand gate] (-lt) at (2,-0.75) {};
\draw[gray] (-gt.output)--++(3mm,0)
coordinate[label={[black]left:$\mathrm{gt}_\mathrm{out}$}] (-gtout);
\draw[gray] (-eq.output)--(-eq.output-|-gtout)
coordinate[label={[black]left:$\mathrm{eq}_\mathrm{out}$}] (-eqout);
\draw[gray] (-lt.output)--(-lt.output-|-gtout)
coordinate[label={[black]left:$\mathrm{lt}_\mathrm{out}$}] (-eqout);
\draw[gray] (-gt.input 1)-|++(-3mm,.5cm)
coordinate[label={[black]below:$\mathrm{b}$}] (-b);
\draw[gray] (-lt.input 1)-|([xshift=-6mm]-b.center)
coordinate[label={[black]below:$\mathrm{a}$}] (-a);
\draw[gray] (-eq.input)--++(-2cm,0)
coordinate[label={[black]right:$\mathrm{eq}_\mathrm{in}$}] (-eqin);
\draw[gray] (-gt.input 2)--++(-1.2cm,0) |- ([yshift=1cm]-eqin.center)
coordinate[label={[black]right:$\mathrm{gt}_\mathrm{in}$}] (-gtin);
\draw[gray] (-lt.input 2)--++(-1.2cm,0) |- ([yshift=-1cm]-eqin.center)
coordinate[label={[black]right:$\mathrm{lt}_\mathrm{in}$}] (-ltin);
\node[draw, fit={(-ltin) (-b) ([yshift=-.5cm]-lt.input 2) (-gtout)},
inner sep=0pt] (-box) {};
\end{scope}
}}
\begin{document}
\begin{tikzpicture}
\pic (a) at (0,0) {mycircuit};
\pic (b) at (5,1) {mycircuit};
\draw (a-gtout) -- (b-gtin);
\draw ([yshift=2cm]a-a) coordinate (aux)--(a-a);
\draw ([yshift=-5mm]aux)-|(b-a);
\end{tikzpicture}
\end{document}