# Describing "fluent" circuits in circuitikz

I went to draw my first circuit with circuitikz a few days ago—it's a fairly simple hierarchical logic gate—and I struggled more than I thought I would after looking at some samples. I had to wrestle with a lot of absolute positioning; some things were too wide; but most importantly, I was only either placing one node or drawing one wire. Every example I had seen had just a few semantic groups of draw commands, and mine were, well, clumpy.

Eventually I went from

\begin{circuitikz}
\draw
(0,4) node[left](A){$A$}
(0,3) node[left](B){$B$}
(0,2) node[left](C){$C$}
(0,1) node[left](D){$D$}
(0,0) node[left](E){$E$}
(2,3.5) node[or port](AoB){}
(A) -| (AoB.in 1)
(B) -| (AoB.in 2)
(2,1.5) node[or port](CoD){}
(C) -| (CoD.in 1)
(D) -| (CoD.in 2)
(5,2.5) node[and port](t1){}
(AoB.out) -| (t1.in 1)
(CoD.out) -| (t1.in 2)
(8, 1.25) node[or port](Y){} ++(1,0) node[right]{$Y$}
(t1.out) -| (Y.in 1)
(E) -| (Y.in 2);
\end{circuitikz}


to

\begin{circuitikz}
\draw

(0,4) node[left](A){$A$}
++(0,-1) node[left](B){$B$}
++(2,0.5) node[or port](AoB){}

(A) -| (AoB.in 1)
(B) -| (AoB.in 2)

(0,2) node[left](C){$C$}
++(0,-1) node[left](D){$D$}
++(2,0.5) node[or port](CoD){}

(C) -| (CoD.in 1)
(D) -| (CoD.in 2)

(5,2.5) node[and port](t1){}
(AoB.out) -| (t1.in 1)
(CoD.out) -| (t1.in 2)

(0,0) node[left](E){$E$}

(8, 1.25) node[or port](Y){} ++(1,0) node[right]{$Y$}
(t1.out) -| (Y.in 1)
(E) -| (Y.in 2);

\end{circuitikz}


but neither feels idiomatic or fluent.

I do apologize if this is too subjective; it's hard for me to describe what I dislike about the code. It does work. I still feel like I'm missing something fundamental that would make it easier to see more structure in the code.

• I added an image, I hope you don't mind. I find the code quite ok (especially, for my tastes, the second one which uses far less absolute coords). I would use IEEE ports and avoid "stairs" in the connections, by compacting the list of input labels so that they are at the same distance than input leads, but otherwise I think it's fine. Aug 25 '20 at 6:39
• @Rmano thanks! I couldn’t figure out how to get rid of the stairs unfortunately :( and it looks like I forgot to make then IEEE 😂 I was so caught up in getting the thing working I forgot to check the style! Aug 25 '20 at 11:39

This is a suggestion to obtain:

• a compact drawing (maybe too much?)
• the list of inputs at a constant vertical distance
• an almost automatic positioning (you just have a magic number, the shift to position (A).

The trick is to use a 3-inputs OR for gates 1 and 2 so that when stacked they do not touch (maybe I should think a better way to achieve this? Another parameter for the ports? The problem is that it's complex to think about it for a generic number of inner/outer inputs).

\documentclass[border=10pt]{standalone}
\usepackage[siunitx, RPvoltages]{circuitikz}
\ctikzset{logic ports=ieee}
% we will use 3-inputs ports with just input 1 and 2. We suppress
% input leads to use them.

\begin{document}
\begin{circuitikz}
% first gate to "guide" everything.
\draw (0,10) node[or port, asymmetric](OR1){};
% inputs position
\draw (OR1.bin 1) -- ++(-1,0) node[left](A){$A$};
\draw (OR1.bin 3) -- (OR1.bin 3-|A.east) node[left](B){$B$};
% use calc to put the input at the same vertical distance
\foreach \inode [count=\iy from 2] in {C, D, E}
\path ($(A.east)!\iy!(B.east)$) node [left](\inode){$\inode$};
% position second or an connect it
\draw (C.east) -- (C.east -| OR1.bin 1)
node [or port, asymmetric, anchor=bin 1](OR2){};
\draw (D.east) -- (OR2.bin 3);
% position the and port (this is a normal 2-port)
\node [and port, anchor=west](AND1) at ($(OR1.out)!0.5!(OR2.out)$) {};
\draw (OR1.out) -- (AND1.in 1) (AND1.in 2) -- (OR2.out);
% find the position for the last OR; first move (E) under AND1
\coordinate (E1) at (E.east -| AND1.out);
% position the or and connect
\node [or port, anchor=west](OR3) at ($(AND1.out)!0.5!(E1)$) {};
\draw (AND1.out) -- (OR3.in 1) (OR3.in 2) |- (E.east);
% and output
\node [right](Y) at (OR3.out) {Y};
\end{circuitikz}
\end{document}


Notice that a bad effect here is that using so many different \draw the path unions are far from perfect (using to [short, .-.] will make a better union; for example change

\draw (OR1.out) -- (AND1.in 1) (AND1.in 2) -- (OR2.out);


to

\draw (OR1.out) to[short, .-.] (AND1.in 1)
(AND1.in 2) to[short, .-.]  (OR2.out);

• This is pretty over my head, but thanks! Much to learn. Aug 25 '20 at 16:02
• If you have specific questions, fire! --- I'll try to help. ;-) Aug 25 '20 at 17:38