tikzset does not work in foreach loop
I tried to use a foreach loop to define a new style. However, the code within the loop seems to have no effect. The following MWE ilustrates my problem:
documentclass[tikz]{standalone}
tikzset{
mystyle/.code=
{
%tikzset{very thick}, % This line has an effect (if uncommented)
foreach pos in {0.1, 0.2, 0.3, 0.4} % **EDIT**: Should be a list of names in the end.
{
% There will be other statements here that actually use the list members
tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
}
}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}
When I compile this document, the console shows the messages
...
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3
======== Foreach: pos=0.4 [1] (./mwe.aux))
...
so I believe the tikzset is actually run. There are no error messages.
So, why does the tikzset command not make my line thick? And how can I get this to work?
EDIT:
Context:
This is (of course) part of a bigger thing. In the end, I want to create transistor stick diagrams like shown here: http://www.southampton.ac.uk/~bim/notes/cad/guides/sticks.html
(Summary: Chip-level transistor layouts are sketched using mere lines of different colours. Where a line with the "Polysilicon" colour crosses a line with the "N Diffusion" oder "P Diffusion" colour, there is a transistor gate.
For this I first created some line and node styles, borrowing code from Loop Space and circuitikz (for the node styles). With this, I can draw my diagrams, but it is still rather manual since I have to draw multiple lines to create a transistor: The diffusion and polysilicon lines.
So, I decided to create a new line style, that would allow me to place the transistor gates automatically. Using code borrowed from Casimir, I was able to create the following:
documentclass[tikz]{standalone}
% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}
%{{{ Transistor Stick Diagrams
%{{{ Layer Magic
% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}
makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}
defnode@on@layer{aftergroupnode@@on@layer}
%}}}
%{{{ Declare the Node shapes
% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm
%% Left out, boring and too long
makeatother
%}}}
%{{{ Line Styles
tikzstyle{M3} = [draw=green, line width=0.3, on layer=M3L ] % Metal 3 Path
tikzstyle{M2} = [draw=yellow, line width=0.3, on layer=M2L ] % Metal 2 Path
tikzstyle{M1} = [draw=turquoise, line width=0.3, on layer=M1L ] % Metal 1 Path
tikzstyle{PO} = [draw=blue, line width=0.3, on layer=POL ] % Poly-Silicon Path (Gate)
tikzstyle{PD} = [draw=red!50, line width=0.3, on layer=DDL ] % P-Diffusion Path (PMOS)
tikzstyle{ND} = [draw=red, line width=0.3, on layer=DDL ] % N-Diffusion Path (NMOS)
tikzstyle{air} = [draw=black,dashed,line width=0.1, on layer=CONTL] % N-Diffusion Path (NMOS)
%}}}
%{{{ Port Styles
tikzstyle{M3P} = [stickport, color=green, node on layer=M3L ] % Metal 3 Terminal
tikzstyle{M2P} = [stickport, color=yellow, node on layer=M2L ] % Metal 2 Terminal
tikzstyle{M1P} = [stickport, color=turquoise, node on layer=M1L ] % Metal 1 Terminal
tikzstyle{POP} = [stickport, color=blue, node on layer=POL ] % Poly-Silicon Terminal
tikzstyle{PDP} = [stickport, color=red!50, node on layer=DDL ] % P-Diffusion Terminal (PMOS)
tikzstyle{NDP} = [stickport, color=red, node on layer=DDL ] % N-Diffusion Terminal (NMOS)
tikzstyle{CON} = [stickcontact, color=black, node on layer=CONTL] % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
tikzstyle{TAP} = [sticktap, color=black, node on layer=CONTL] % Substrate Tap (between touching M1,Diff,N-Diff)
tikzstyle{TAPCON} = [sticktapcon, color=black, node on layer=CONTL] % Merged Tap and Via
%}}}
%{{{ Automatic Transistors
tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
foreach name in {#1}
{
% Calculate pos somehow, I'm not there yet
tikzset{gate={pos}{name}}
}
}
}
%}}}
%}}}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);
draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);
end{tikzpicture}
end{document}
This thing is quite near to what I want to get. Yet, the last part is what inspired this question: The gate/.list handler will not allow me to automate the node placement (or I just did not find how to do it), so I wanted to do the looping myself. The manual, section 82.4.6 says, that the /.list handler uses a foreach loop internally, so I tried it and met the problems.
The MWE I created is suboptimal in that it uses a list of numbers for the loop, while the final version should be a loop over names. Sorry for that.
tikz-pgf tikz-styles
|
show 2 more comments
I tried to use a foreach loop to define a new style. However, the code within the loop seems to have no effect. The following MWE ilustrates my problem:
documentclass[tikz]{standalone}
tikzset{
mystyle/.code=
{
%tikzset{very thick}, % This line has an effect (if uncommented)
foreach pos in {0.1, 0.2, 0.3, 0.4} % **EDIT**: Should be a list of names in the end.
{
% There will be other statements here that actually use the list members
tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
}
}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}
When I compile this document, the console shows the messages
...
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3
======== Foreach: pos=0.4 [1] (./mwe.aux))
...
so I believe the tikzset is actually run. There are no error messages.
So, why does the tikzset command not make my line thick? And how can I get this to work?
EDIT:
Context:
This is (of course) part of a bigger thing. In the end, I want to create transistor stick diagrams like shown here: http://www.southampton.ac.uk/~bim/notes/cad/guides/sticks.html
(Summary: Chip-level transistor layouts are sketched using mere lines of different colours. Where a line with the "Polysilicon" colour crosses a line with the "N Diffusion" oder "P Diffusion" colour, there is a transistor gate.
For this I first created some line and node styles, borrowing code from Loop Space and circuitikz (for the node styles). With this, I can draw my diagrams, but it is still rather manual since I have to draw multiple lines to create a transistor: The diffusion and polysilicon lines.
So, I decided to create a new line style, that would allow me to place the transistor gates automatically. Using code borrowed from Casimir, I was able to create the following:
documentclass[tikz]{standalone}
% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}
%{{{ Transistor Stick Diagrams
%{{{ Layer Magic
% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}
makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}
defnode@on@layer{aftergroupnode@@on@layer}
%}}}
%{{{ Declare the Node shapes
% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm
%% Left out, boring and too long
makeatother
%}}}
%{{{ Line Styles
tikzstyle{M3} = [draw=green, line width=0.3, on layer=M3L ] % Metal 3 Path
tikzstyle{M2} = [draw=yellow, line width=0.3, on layer=M2L ] % Metal 2 Path
tikzstyle{M1} = [draw=turquoise, line width=0.3, on layer=M1L ] % Metal 1 Path
tikzstyle{PO} = [draw=blue, line width=0.3, on layer=POL ] % Poly-Silicon Path (Gate)
tikzstyle{PD} = [draw=red!50, line width=0.3, on layer=DDL ] % P-Diffusion Path (PMOS)
tikzstyle{ND} = [draw=red, line width=0.3, on layer=DDL ] % N-Diffusion Path (NMOS)
tikzstyle{air} = [draw=black,dashed,line width=0.1, on layer=CONTL] % N-Diffusion Path (NMOS)
%}}}
%{{{ Port Styles
tikzstyle{M3P} = [stickport, color=green, node on layer=M3L ] % Metal 3 Terminal
tikzstyle{M2P} = [stickport, color=yellow, node on layer=M2L ] % Metal 2 Terminal
tikzstyle{M1P} = [stickport, color=turquoise, node on layer=M1L ] % Metal 1 Terminal
tikzstyle{POP} = [stickport, color=blue, node on layer=POL ] % Poly-Silicon Terminal
tikzstyle{PDP} = [stickport, color=red!50, node on layer=DDL ] % P-Diffusion Terminal (PMOS)
tikzstyle{NDP} = [stickport, color=red, node on layer=DDL ] % N-Diffusion Terminal (NMOS)
tikzstyle{CON} = [stickcontact, color=black, node on layer=CONTL] % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
tikzstyle{TAP} = [sticktap, color=black, node on layer=CONTL] % Substrate Tap (between touching M1,Diff,N-Diff)
tikzstyle{TAPCON} = [sticktapcon, color=black, node on layer=CONTL] % Merged Tap and Via
%}}}
%{{{ Automatic Transistors
tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
foreach name in {#1}
{
% Calculate pos somehow, I'm not there yet
tikzset{gate={pos}{name}}
}
}
}
%}}}
%}}}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);
draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);
end{tikzpicture}
end{document}
This thing is quite near to what I want to get. Yet, the last part is what inspired this question: The gate/.list handler will not allow me to automate the node placement (or I just did not find how to do it), so I wanted to do the looping myself. The manual, section 82.4.6 says, that the /.list handler uses a foreach loop internally, so I tried it and met the problems.
The MWE I created is suboptimal in that it uses a list of numbers for the loop, while the final version should be a loop over names. Sorry for that.
tikz-pgf tikz-styles
1
Because the contents offoreach
are executed inside a group (actually two), so local definitions (tikzset
does local definitions) are lost when the loop ends. Depending on what the "statements" you mentioned do you can use different approaches to overcome the grouping offoreach
. That or use another looping command.
– Phelype Oleinik
Jan 30 at 18:07
I am going to add further tikzset commands. I have written a style which takes two parameters and draws a line crossing my line. In the end this is for creating transistor stick diagrams.
– mox
Jan 30 at 18:34
With othertikzset
commands the solution I proposed will work fine. Depending on how you are drawing the diagrams, this can perhaps be achieved with styles. But we'd probably need to see the whole drawing to say for sure.
– Phelype Oleinik
Jan 30 at 18:46
First: Thank you! (forgot that in my first comment) I added the context and how I want to use the code. It should be compilable if you comment out the last two lines inside the tikzpicture. They cannot work yet. Could you give an example how to make the code work if the list is not numbers, or -- even better -- how the <key>/.list handler works around this problem?
– mox
Jan 30 at 19:49
In the advanced code you already use all theaftergroup
trickery, which you could also use fortikzset
. So, to some extent you may benefit from smuggling. Yet I fail to see the purpose of all this here.
– marmot
Jan 30 at 20:02
|
show 2 more comments
I tried to use a foreach loop to define a new style. However, the code within the loop seems to have no effect. The following MWE ilustrates my problem:
documentclass[tikz]{standalone}
tikzset{
mystyle/.code=
{
%tikzset{very thick}, % This line has an effect (if uncommented)
foreach pos in {0.1, 0.2, 0.3, 0.4} % **EDIT**: Should be a list of names in the end.
{
% There will be other statements here that actually use the list members
tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
}
}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}
When I compile this document, the console shows the messages
...
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3
======== Foreach: pos=0.4 [1] (./mwe.aux))
...
so I believe the tikzset is actually run. There are no error messages.
So, why does the tikzset command not make my line thick? And how can I get this to work?
EDIT:
Context:
This is (of course) part of a bigger thing. In the end, I want to create transistor stick diagrams like shown here: http://www.southampton.ac.uk/~bim/notes/cad/guides/sticks.html
(Summary: Chip-level transistor layouts are sketched using mere lines of different colours. Where a line with the "Polysilicon" colour crosses a line with the "N Diffusion" oder "P Diffusion" colour, there is a transistor gate.
For this I first created some line and node styles, borrowing code from Loop Space and circuitikz (for the node styles). With this, I can draw my diagrams, but it is still rather manual since I have to draw multiple lines to create a transistor: The diffusion and polysilicon lines.
So, I decided to create a new line style, that would allow me to place the transistor gates automatically. Using code borrowed from Casimir, I was able to create the following:
documentclass[tikz]{standalone}
% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}
%{{{ Transistor Stick Diagrams
%{{{ Layer Magic
% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}
makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}
defnode@on@layer{aftergroupnode@@on@layer}
%}}}
%{{{ Declare the Node shapes
% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm
%% Left out, boring and too long
makeatother
%}}}
%{{{ Line Styles
tikzstyle{M3} = [draw=green, line width=0.3, on layer=M3L ] % Metal 3 Path
tikzstyle{M2} = [draw=yellow, line width=0.3, on layer=M2L ] % Metal 2 Path
tikzstyle{M1} = [draw=turquoise, line width=0.3, on layer=M1L ] % Metal 1 Path
tikzstyle{PO} = [draw=blue, line width=0.3, on layer=POL ] % Poly-Silicon Path (Gate)
tikzstyle{PD} = [draw=red!50, line width=0.3, on layer=DDL ] % P-Diffusion Path (PMOS)
tikzstyle{ND} = [draw=red, line width=0.3, on layer=DDL ] % N-Diffusion Path (NMOS)
tikzstyle{air} = [draw=black,dashed,line width=0.1, on layer=CONTL] % N-Diffusion Path (NMOS)
%}}}
%{{{ Port Styles
tikzstyle{M3P} = [stickport, color=green, node on layer=M3L ] % Metal 3 Terminal
tikzstyle{M2P} = [stickport, color=yellow, node on layer=M2L ] % Metal 2 Terminal
tikzstyle{M1P} = [stickport, color=turquoise, node on layer=M1L ] % Metal 1 Terminal
tikzstyle{POP} = [stickport, color=blue, node on layer=POL ] % Poly-Silicon Terminal
tikzstyle{PDP} = [stickport, color=red!50, node on layer=DDL ] % P-Diffusion Terminal (PMOS)
tikzstyle{NDP} = [stickport, color=red, node on layer=DDL ] % N-Diffusion Terminal (NMOS)
tikzstyle{CON} = [stickcontact, color=black, node on layer=CONTL] % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
tikzstyle{TAP} = [sticktap, color=black, node on layer=CONTL] % Substrate Tap (between touching M1,Diff,N-Diff)
tikzstyle{TAPCON} = [sticktapcon, color=black, node on layer=CONTL] % Merged Tap and Via
%}}}
%{{{ Automatic Transistors
tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
foreach name in {#1}
{
% Calculate pos somehow, I'm not there yet
tikzset{gate={pos}{name}}
}
}
}
%}}}
%}}}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);
draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);
end{tikzpicture}
end{document}
This thing is quite near to what I want to get. Yet, the last part is what inspired this question: The gate/.list handler will not allow me to automate the node placement (or I just did not find how to do it), so I wanted to do the looping myself. The manual, section 82.4.6 says, that the /.list handler uses a foreach loop internally, so I tried it and met the problems.
The MWE I created is suboptimal in that it uses a list of numbers for the loop, while the final version should be a loop over names. Sorry for that.
tikz-pgf tikz-styles
I tried to use a foreach loop to define a new style. However, the code within the loop seems to have no effect. The following MWE ilustrates my problem:
documentclass[tikz]{standalone}
tikzset{
mystyle/.code=
{
%tikzset{very thick}, % This line has an effect (if uncommented)
foreach pos in {0.1, 0.2, 0.3, 0.4} % **EDIT**: Should be a list of names in the end.
{
% There will be other statements here that actually use the list members
tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
}
}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}
When I compile this document, the console shows the messages
...
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3
======== Foreach: pos=0.4 [1] (./mwe.aux))
...
so I believe the tikzset is actually run. There are no error messages.
So, why does the tikzset command not make my line thick? And how can I get this to work?
EDIT:
Context:
This is (of course) part of a bigger thing. In the end, I want to create transistor stick diagrams like shown here: http://www.southampton.ac.uk/~bim/notes/cad/guides/sticks.html
(Summary: Chip-level transistor layouts are sketched using mere lines of different colours. Where a line with the "Polysilicon" colour crosses a line with the "N Diffusion" oder "P Diffusion" colour, there is a transistor gate.
For this I first created some line and node styles, borrowing code from Loop Space and circuitikz (for the node styles). With this, I can draw my diagrams, but it is still rather manual since I have to draw multiple lines to create a transistor: The diffusion and polysilicon lines.
So, I decided to create a new line style, that would allow me to place the transistor gates automatically. Using code borrowed from Casimir, I was able to create the following:
documentclass[tikz]{standalone}
% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}
%{{{ Transistor Stick Diagrams
%{{{ Layer Magic
% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}
makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}
defnode@on@layer{aftergroupnode@@on@layer}
%}}}
%{{{ Declare the Node shapes
% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm
%% Left out, boring and too long
makeatother
%}}}
%{{{ Line Styles
tikzstyle{M3} = [draw=green, line width=0.3, on layer=M3L ] % Metal 3 Path
tikzstyle{M2} = [draw=yellow, line width=0.3, on layer=M2L ] % Metal 2 Path
tikzstyle{M1} = [draw=turquoise, line width=0.3, on layer=M1L ] % Metal 1 Path
tikzstyle{PO} = [draw=blue, line width=0.3, on layer=POL ] % Poly-Silicon Path (Gate)
tikzstyle{PD} = [draw=red!50, line width=0.3, on layer=DDL ] % P-Diffusion Path (PMOS)
tikzstyle{ND} = [draw=red, line width=0.3, on layer=DDL ] % N-Diffusion Path (NMOS)
tikzstyle{air} = [draw=black,dashed,line width=0.1, on layer=CONTL] % N-Diffusion Path (NMOS)
%}}}
%{{{ Port Styles
tikzstyle{M3P} = [stickport, color=green, node on layer=M3L ] % Metal 3 Terminal
tikzstyle{M2P} = [stickport, color=yellow, node on layer=M2L ] % Metal 2 Terminal
tikzstyle{M1P} = [stickport, color=turquoise, node on layer=M1L ] % Metal 1 Terminal
tikzstyle{POP} = [stickport, color=blue, node on layer=POL ] % Poly-Silicon Terminal
tikzstyle{PDP} = [stickport, color=red!50, node on layer=DDL ] % P-Diffusion Terminal (PMOS)
tikzstyle{NDP} = [stickport, color=red, node on layer=DDL ] % N-Diffusion Terminal (NMOS)
tikzstyle{CON} = [stickcontact, color=black, node on layer=CONTL] % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
tikzstyle{TAP} = [sticktap, color=black, node on layer=CONTL] % Substrate Tap (between touching M1,Diff,N-Diff)
tikzstyle{TAPCON} = [sticktapcon, color=black, node on layer=CONTL] % Merged Tap and Via
%}}}
%{{{ Automatic Transistors
tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
foreach name in {#1}
{
% Calculate pos somehow, I'm not there yet
tikzset{gate={pos}{name}}
}
}
}
%}}}
%}}}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);
draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);
end{tikzpicture}
end{document}
This thing is quite near to what I want to get. Yet, the last part is what inspired this question: The gate/.list handler will not allow me to automate the node placement (or I just did not find how to do it), so I wanted to do the looping myself. The manual, section 82.4.6 says, that the /.list handler uses a foreach loop internally, so I tried it and met the problems.
The MWE I created is suboptimal in that it uses a list of numbers for the loop, while the final version should be a loop over names. Sorry for that.
tikz-pgf tikz-styles
tikz-pgf tikz-styles
edited Jan 30 at 19:42
mox
asked Jan 30 at 17:59
moxmox
263
263
1
Because the contents offoreach
are executed inside a group (actually two), so local definitions (tikzset
does local definitions) are lost when the loop ends. Depending on what the "statements" you mentioned do you can use different approaches to overcome the grouping offoreach
. That or use another looping command.
– Phelype Oleinik
Jan 30 at 18:07
I am going to add further tikzset commands. I have written a style which takes two parameters and draws a line crossing my line. In the end this is for creating transistor stick diagrams.
– mox
Jan 30 at 18:34
With othertikzset
commands the solution I proposed will work fine. Depending on how you are drawing the diagrams, this can perhaps be achieved with styles. But we'd probably need to see the whole drawing to say for sure.
– Phelype Oleinik
Jan 30 at 18:46
First: Thank you! (forgot that in my first comment) I added the context and how I want to use the code. It should be compilable if you comment out the last two lines inside the tikzpicture. They cannot work yet. Could you give an example how to make the code work if the list is not numbers, or -- even better -- how the <key>/.list handler works around this problem?
– mox
Jan 30 at 19:49
In the advanced code you already use all theaftergroup
trickery, which you could also use fortikzset
. So, to some extent you may benefit from smuggling. Yet I fail to see the purpose of all this here.
– marmot
Jan 30 at 20:02
|
show 2 more comments
1
Because the contents offoreach
are executed inside a group (actually two), so local definitions (tikzset
does local definitions) are lost when the loop ends. Depending on what the "statements" you mentioned do you can use different approaches to overcome the grouping offoreach
. That or use another looping command.
– Phelype Oleinik
Jan 30 at 18:07
I am going to add further tikzset commands. I have written a style which takes two parameters and draws a line crossing my line. In the end this is for creating transistor stick diagrams.
– mox
Jan 30 at 18:34
With othertikzset
commands the solution I proposed will work fine. Depending on how you are drawing the diagrams, this can perhaps be achieved with styles. But we'd probably need to see the whole drawing to say for sure.
– Phelype Oleinik
Jan 30 at 18:46
First: Thank you! (forgot that in my first comment) I added the context and how I want to use the code. It should be compilable if you comment out the last two lines inside the tikzpicture. They cannot work yet. Could you give an example how to make the code work if the list is not numbers, or -- even better -- how the <key>/.list handler works around this problem?
– mox
Jan 30 at 19:49
In the advanced code you already use all theaftergroup
trickery, which you could also use fortikzset
. So, to some extent you may benefit from smuggling. Yet I fail to see the purpose of all this here.
– marmot
Jan 30 at 20:02
1
1
Because the contents of
foreach
are executed inside a group (actually two), so local definitions (tikzset
does local definitions) are lost when the loop ends. Depending on what the "statements" you mentioned do you can use different approaches to overcome the grouping of foreach
. That or use another looping command.– Phelype Oleinik
Jan 30 at 18:07
Because the contents of
foreach
are executed inside a group (actually two), so local definitions (tikzset
does local definitions) are lost when the loop ends. Depending on what the "statements" you mentioned do you can use different approaches to overcome the grouping of foreach
. That or use another looping command.– Phelype Oleinik
Jan 30 at 18:07
I am going to add further tikzset commands. I have written a style which takes two parameters and draws a line crossing my line. In the end this is for creating transistor stick diagrams.
– mox
Jan 30 at 18:34
I am going to add further tikzset commands. I have written a style which takes two parameters and draws a line crossing my line. In the end this is for creating transistor stick diagrams.
– mox
Jan 30 at 18:34
With other
tikzset
commands the solution I proposed will work fine. Depending on how you are drawing the diagrams, this can perhaps be achieved with styles. But we'd probably need to see the whole drawing to say for sure.– Phelype Oleinik
Jan 30 at 18:46
With other
tikzset
commands the solution I proposed will work fine. Depending on how you are drawing the diagrams, this can perhaps be achieved with styles. But we'd probably need to see the whole drawing to say for sure.– Phelype Oleinik
Jan 30 at 18:46
First: Thank you! (forgot that in my first comment) I added the context and how I want to use the code. It should be compilable if you comment out the last two lines inside the tikzpicture. They cannot work yet. Could you give an example how to make the code work if the list is not numbers, or -- even better -- how the <key>/.list handler works around this problem?
– mox
Jan 30 at 19:49
First: Thank you! (forgot that in my first comment) I added the context and how I want to use the code. It should be compilable if you comment out the last two lines inside the tikzpicture. They cannot work yet. Could you give an example how to make the code work if the list is not numbers, or -- even better -- how the <key>/.list handler works around this problem?
– mox
Jan 30 at 19:49
In the advanced code you already use all the
aftergroup
trickery, which you could also use for tikzset
. So, to some extent you may benefit from smuggling. Yet I fail to see the purpose of all this here.– marmot
Jan 30 at 20:02
In the advanced code you already use all the
aftergroup
trickery, which you could also use for tikzset
. So, to some extent you may benefit from smuggling. Yet I fail to see the purpose of all this here.– marmot
Jan 30 at 20:02
|
show 2 more comments
1 Answer
1
active
oldest
votes
As I said in the comment, this happens because the contents of foreach
are executed inside a group, so when the group ends, the value of line width
(modified by the very thick
key) is restored to the previous value. That's why doing it outside the foreach
loop works okay.
Solution to the first code
Here's a simple solution by changing the looping command. There are several options, here I used expl3
's fp_step_variable:nnnNn
.
First I make a copy of fp_step_variable:nnnNn
called fpStepVariable
. The syntax of fp_step_variable:nnnNn
is:
fp_step_variable:nnnNn {<initial value>} {<step>} {<final value>} <tl var> {<code>}
so I replaced:
foreach pos in {0.1, 0.2, 0.3, 0.4}
by
fpStepVariable {0.1} {0.1} {0.4} pos
I also added two typeout
s to show the effect. After running the code the console shows:
Line width before: 0.4pt
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3 ======== Foreach: pos=0.4
Line width after: 1.2pt
Full code:
documentclass[tikz]{standalone}
usepackage{expl3}
ExplSyntaxOn
cs_set_eq:NN fpStepVariable fp_step_variable:nnnNn
ExplSyntaxOff
tikzset{
mystyle/.code=
{
typeout{Line width before: thepgflinewidth}
fpStepVariable {0.1} {0.1} {0.4} pos
{
tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
typeout{Line width after: thepgflinewidth}
}
}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}
Solution to the second code
The solution I used here is very similar to the previous one except for a few details.
Previously I used fp_step_variable:nnnNn
because you had an uniform sequence of numbers. Now you have letters. One way to approach the problem is to use a clist_map_...
function to loop through a comma-separated list of things. To keep the usage syntax similar I used clist_map_variable:nNn
, whose syntax is:
clist_map_variable:nNn {<comma list>} <tl var> {<code>}
I copied clist_map_variable:nNn
into ClistMapVariable
and used:
ClistMapVariable{#1}name
where #1
is the list a,b,c
, which you passed to the pmos
key. One problem you'll face is that the variable name
expands to the name (a
, b
, or c
), but it's not the name itself, so you need to expand it first. For that I used:
edeftempa{noexpandtikzset{gate={pos}{name}}}
tempa
after the edef
, tempa
will be something like tikzset{gate={0.12345}{a}}
which does what we want.
Finally, I used
pgfmathparse{rnd}
edefpos{pgfmathresult}
to give a value to pos
.
Full code:
documentclass[tikz]{standalone}
usepackage{expl3}
ExplSyntaxOn
cs_set_eq:NN ClistMapVariable clist_map_variable:nNn
ExplSyntaxOff
% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}
%{{{ Transistor Stick Diagrams
%{{{ Layer Magic
% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}
makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}
defnode@on@layer{aftergroupnode@@on@layer}
%}}}
%{{{ Declare the Node shapes
% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm
%% Left out, boring and too long
makeatother
%}}}
%{{{ Line Styles
tikzset{
M3/.style = { draw=green, line width=0.3, on layer=M3L }, % Metal 3 Path
M2/.style = { draw=yellow, line width=0.3, on layer=M2L }, % Metal 2 Path
M1/.style = { draw=turquoise, line width=0.3, on layer=M1L }, % Metal 1 Path
PO/.style = { draw=blue, line width=0.3, on layer=POL }, % Poly-Silicon Path (Gate)
PD/.style = { draw=red!50, line width=0.3, on layer=DDL }, % P-Diffusion Path (PMOS)
ND/.style = { draw=red, line width=0.3, on layer=DDL }, % N-Diffusion Path (NMOS)
air/.style = { draw=black,dashed,line width=0.1, on layer=CONTL }, % N-Diffusion Path (NMOS)
}
%}}}
%{{{ Port Styles
tikzset{
M3P/.style = {stickport, color=green, node on layer=M3L }, % Metal 3 Terminal
M2P/.style = {stickport, color=yellow, node on layer=M2L }, % Metal 2 Terminal
M1P/.style = {stickport, color=turquoise, node on layer=M1L }, % Metal 1 Terminal
POP/.style = {stickport, color=blue, node on layer=POL }, % Poly-Silicon Terminal
PDP/.style = {stickport, color=red!50, node on layer=DDL }, % P-Diffusion Terminal (PMOS)
NDP/.style = {stickport, color=red, node on layer=DDL }, % N-Diffusion Terminal (NMOS)
CON/.style = {stickcontact, color=black, node on layer=CONTL}, % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
TAP/.style = {sticktap, color=black, node on layer=CONTL}, % Substrate Tap (between touching M1,Diff,N-Diff)
TAPCON/.style = {sticktapcon, color=black, node on layer=CONTL}, % Merged Tap and Via
}
%}}}
%{{{ Automatic Transistors
tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
ClistMapVariable{#1}name
{
pgfmathparse{rnd}
edefpos{pgfmathresult}
edeftempa{noexpandtikzset{gate={pos}{name}}}
tempa
}
}
}
%}}}
%}}}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);
draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);
end{tikzpicture}
end{document}
Remarks
This is one way to do it. There are many more. You could use Mr. marmot's suggestion to "smuggle" the
tikzset
outside the groups, or you could use some other looping function, or even do something clever with styles.I used
clist_map_variable:nNn
to keep the syntax similar to before. You could useclist_map_inline:nn
, which would spare you from doing that expansion shenanigan. I'll leave this one for you.The syntax
tikzstyle{a}=[b]
is deprecated. You should usetikzset{s/.style={b}}
. I changed it in your code.
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f472607%2ftikzset-does-not-work-in-foreach-loop%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
As I said in the comment, this happens because the contents of foreach
are executed inside a group, so when the group ends, the value of line width
(modified by the very thick
key) is restored to the previous value. That's why doing it outside the foreach
loop works okay.
Solution to the first code
Here's a simple solution by changing the looping command. There are several options, here I used expl3
's fp_step_variable:nnnNn
.
First I make a copy of fp_step_variable:nnnNn
called fpStepVariable
. The syntax of fp_step_variable:nnnNn
is:
fp_step_variable:nnnNn {<initial value>} {<step>} {<final value>} <tl var> {<code>}
so I replaced:
foreach pos in {0.1, 0.2, 0.3, 0.4}
by
fpStepVariable {0.1} {0.1} {0.4} pos
I also added two typeout
s to show the effect. After running the code the console shows:
Line width before: 0.4pt
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3 ======== Foreach: pos=0.4
Line width after: 1.2pt
Full code:
documentclass[tikz]{standalone}
usepackage{expl3}
ExplSyntaxOn
cs_set_eq:NN fpStepVariable fp_step_variable:nnnNn
ExplSyntaxOff
tikzset{
mystyle/.code=
{
typeout{Line width before: thepgflinewidth}
fpStepVariable {0.1} {0.1} {0.4} pos
{
tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
typeout{Line width after: thepgflinewidth}
}
}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}
Solution to the second code
The solution I used here is very similar to the previous one except for a few details.
Previously I used fp_step_variable:nnnNn
because you had an uniform sequence of numbers. Now you have letters. One way to approach the problem is to use a clist_map_...
function to loop through a comma-separated list of things. To keep the usage syntax similar I used clist_map_variable:nNn
, whose syntax is:
clist_map_variable:nNn {<comma list>} <tl var> {<code>}
I copied clist_map_variable:nNn
into ClistMapVariable
and used:
ClistMapVariable{#1}name
where #1
is the list a,b,c
, which you passed to the pmos
key. One problem you'll face is that the variable name
expands to the name (a
, b
, or c
), but it's not the name itself, so you need to expand it first. For that I used:
edeftempa{noexpandtikzset{gate={pos}{name}}}
tempa
after the edef
, tempa
will be something like tikzset{gate={0.12345}{a}}
which does what we want.
Finally, I used
pgfmathparse{rnd}
edefpos{pgfmathresult}
to give a value to pos
.
Full code:
documentclass[tikz]{standalone}
usepackage{expl3}
ExplSyntaxOn
cs_set_eq:NN ClistMapVariable clist_map_variable:nNn
ExplSyntaxOff
% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}
%{{{ Transistor Stick Diagrams
%{{{ Layer Magic
% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}
makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}
defnode@on@layer{aftergroupnode@@on@layer}
%}}}
%{{{ Declare the Node shapes
% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm
%% Left out, boring and too long
makeatother
%}}}
%{{{ Line Styles
tikzset{
M3/.style = { draw=green, line width=0.3, on layer=M3L }, % Metal 3 Path
M2/.style = { draw=yellow, line width=0.3, on layer=M2L }, % Metal 2 Path
M1/.style = { draw=turquoise, line width=0.3, on layer=M1L }, % Metal 1 Path
PO/.style = { draw=blue, line width=0.3, on layer=POL }, % Poly-Silicon Path (Gate)
PD/.style = { draw=red!50, line width=0.3, on layer=DDL }, % P-Diffusion Path (PMOS)
ND/.style = { draw=red, line width=0.3, on layer=DDL }, % N-Diffusion Path (NMOS)
air/.style = { draw=black,dashed,line width=0.1, on layer=CONTL }, % N-Diffusion Path (NMOS)
}
%}}}
%{{{ Port Styles
tikzset{
M3P/.style = {stickport, color=green, node on layer=M3L }, % Metal 3 Terminal
M2P/.style = {stickport, color=yellow, node on layer=M2L }, % Metal 2 Terminal
M1P/.style = {stickport, color=turquoise, node on layer=M1L }, % Metal 1 Terminal
POP/.style = {stickport, color=blue, node on layer=POL }, % Poly-Silicon Terminal
PDP/.style = {stickport, color=red!50, node on layer=DDL }, % P-Diffusion Terminal (PMOS)
NDP/.style = {stickport, color=red, node on layer=DDL }, % N-Diffusion Terminal (NMOS)
CON/.style = {stickcontact, color=black, node on layer=CONTL}, % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
TAP/.style = {sticktap, color=black, node on layer=CONTL}, % Substrate Tap (between touching M1,Diff,N-Diff)
TAPCON/.style = {sticktapcon, color=black, node on layer=CONTL}, % Merged Tap and Via
}
%}}}
%{{{ Automatic Transistors
tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
ClistMapVariable{#1}name
{
pgfmathparse{rnd}
edefpos{pgfmathresult}
edeftempa{noexpandtikzset{gate={pos}{name}}}
tempa
}
}
}
%}}}
%}}}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);
draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);
end{tikzpicture}
end{document}
Remarks
This is one way to do it. There are many more. You could use Mr. marmot's suggestion to "smuggle" the
tikzset
outside the groups, or you could use some other looping function, or even do something clever with styles.I used
clist_map_variable:nNn
to keep the syntax similar to before. You could useclist_map_inline:nn
, which would spare you from doing that expansion shenanigan. I'll leave this one for you.The syntax
tikzstyle{a}=[b]
is deprecated. You should usetikzset{s/.style={b}}
. I changed it in your code.
add a comment |
As I said in the comment, this happens because the contents of foreach
are executed inside a group, so when the group ends, the value of line width
(modified by the very thick
key) is restored to the previous value. That's why doing it outside the foreach
loop works okay.
Solution to the first code
Here's a simple solution by changing the looping command. There are several options, here I used expl3
's fp_step_variable:nnnNn
.
First I make a copy of fp_step_variable:nnnNn
called fpStepVariable
. The syntax of fp_step_variable:nnnNn
is:
fp_step_variable:nnnNn {<initial value>} {<step>} {<final value>} <tl var> {<code>}
so I replaced:
foreach pos in {0.1, 0.2, 0.3, 0.4}
by
fpStepVariable {0.1} {0.1} {0.4} pos
I also added two typeout
s to show the effect. After running the code the console shows:
Line width before: 0.4pt
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3 ======== Foreach: pos=0.4
Line width after: 1.2pt
Full code:
documentclass[tikz]{standalone}
usepackage{expl3}
ExplSyntaxOn
cs_set_eq:NN fpStepVariable fp_step_variable:nnnNn
ExplSyntaxOff
tikzset{
mystyle/.code=
{
typeout{Line width before: thepgflinewidth}
fpStepVariable {0.1} {0.1} {0.4} pos
{
tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
typeout{Line width after: thepgflinewidth}
}
}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}
Solution to the second code
The solution I used here is very similar to the previous one except for a few details.
Previously I used fp_step_variable:nnnNn
because you had an uniform sequence of numbers. Now you have letters. One way to approach the problem is to use a clist_map_...
function to loop through a comma-separated list of things. To keep the usage syntax similar I used clist_map_variable:nNn
, whose syntax is:
clist_map_variable:nNn {<comma list>} <tl var> {<code>}
I copied clist_map_variable:nNn
into ClistMapVariable
and used:
ClistMapVariable{#1}name
where #1
is the list a,b,c
, which you passed to the pmos
key. One problem you'll face is that the variable name
expands to the name (a
, b
, or c
), but it's not the name itself, so you need to expand it first. For that I used:
edeftempa{noexpandtikzset{gate={pos}{name}}}
tempa
after the edef
, tempa
will be something like tikzset{gate={0.12345}{a}}
which does what we want.
Finally, I used
pgfmathparse{rnd}
edefpos{pgfmathresult}
to give a value to pos
.
Full code:
documentclass[tikz]{standalone}
usepackage{expl3}
ExplSyntaxOn
cs_set_eq:NN ClistMapVariable clist_map_variable:nNn
ExplSyntaxOff
% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}
%{{{ Transistor Stick Diagrams
%{{{ Layer Magic
% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}
makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}
defnode@on@layer{aftergroupnode@@on@layer}
%}}}
%{{{ Declare the Node shapes
% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm
%% Left out, boring and too long
makeatother
%}}}
%{{{ Line Styles
tikzset{
M3/.style = { draw=green, line width=0.3, on layer=M3L }, % Metal 3 Path
M2/.style = { draw=yellow, line width=0.3, on layer=M2L }, % Metal 2 Path
M1/.style = { draw=turquoise, line width=0.3, on layer=M1L }, % Metal 1 Path
PO/.style = { draw=blue, line width=0.3, on layer=POL }, % Poly-Silicon Path (Gate)
PD/.style = { draw=red!50, line width=0.3, on layer=DDL }, % P-Diffusion Path (PMOS)
ND/.style = { draw=red, line width=0.3, on layer=DDL }, % N-Diffusion Path (NMOS)
air/.style = { draw=black,dashed,line width=0.1, on layer=CONTL }, % N-Diffusion Path (NMOS)
}
%}}}
%{{{ Port Styles
tikzset{
M3P/.style = {stickport, color=green, node on layer=M3L }, % Metal 3 Terminal
M2P/.style = {stickport, color=yellow, node on layer=M2L }, % Metal 2 Terminal
M1P/.style = {stickport, color=turquoise, node on layer=M1L }, % Metal 1 Terminal
POP/.style = {stickport, color=blue, node on layer=POL }, % Poly-Silicon Terminal
PDP/.style = {stickport, color=red!50, node on layer=DDL }, % P-Diffusion Terminal (PMOS)
NDP/.style = {stickport, color=red, node on layer=DDL }, % N-Diffusion Terminal (NMOS)
CON/.style = {stickcontact, color=black, node on layer=CONTL}, % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
TAP/.style = {sticktap, color=black, node on layer=CONTL}, % Substrate Tap (between touching M1,Diff,N-Diff)
TAPCON/.style = {sticktapcon, color=black, node on layer=CONTL}, % Merged Tap and Via
}
%}}}
%{{{ Automatic Transistors
tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
ClistMapVariable{#1}name
{
pgfmathparse{rnd}
edefpos{pgfmathresult}
edeftempa{noexpandtikzset{gate={pos}{name}}}
tempa
}
}
}
%}}}
%}}}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);
draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);
end{tikzpicture}
end{document}
Remarks
This is one way to do it. There are many more. You could use Mr. marmot's suggestion to "smuggle" the
tikzset
outside the groups, or you could use some other looping function, or even do something clever with styles.I used
clist_map_variable:nNn
to keep the syntax similar to before. You could useclist_map_inline:nn
, which would spare you from doing that expansion shenanigan. I'll leave this one for you.The syntax
tikzstyle{a}=[b]
is deprecated. You should usetikzset{s/.style={b}}
. I changed it in your code.
add a comment |
As I said in the comment, this happens because the contents of foreach
are executed inside a group, so when the group ends, the value of line width
(modified by the very thick
key) is restored to the previous value. That's why doing it outside the foreach
loop works okay.
Solution to the first code
Here's a simple solution by changing the looping command. There are several options, here I used expl3
's fp_step_variable:nnnNn
.
First I make a copy of fp_step_variable:nnnNn
called fpStepVariable
. The syntax of fp_step_variable:nnnNn
is:
fp_step_variable:nnnNn {<initial value>} {<step>} {<final value>} <tl var> {<code>}
so I replaced:
foreach pos in {0.1, 0.2, 0.3, 0.4}
by
fpStepVariable {0.1} {0.1} {0.4} pos
I also added two typeout
s to show the effect. After running the code the console shows:
Line width before: 0.4pt
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3 ======== Foreach: pos=0.4
Line width after: 1.2pt
Full code:
documentclass[tikz]{standalone}
usepackage{expl3}
ExplSyntaxOn
cs_set_eq:NN fpStepVariable fp_step_variable:nnnNn
ExplSyntaxOff
tikzset{
mystyle/.code=
{
typeout{Line width before: thepgflinewidth}
fpStepVariable {0.1} {0.1} {0.4} pos
{
tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
typeout{Line width after: thepgflinewidth}
}
}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}
Solution to the second code
The solution I used here is very similar to the previous one except for a few details.
Previously I used fp_step_variable:nnnNn
because you had an uniform sequence of numbers. Now you have letters. One way to approach the problem is to use a clist_map_...
function to loop through a comma-separated list of things. To keep the usage syntax similar I used clist_map_variable:nNn
, whose syntax is:
clist_map_variable:nNn {<comma list>} <tl var> {<code>}
I copied clist_map_variable:nNn
into ClistMapVariable
and used:
ClistMapVariable{#1}name
where #1
is the list a,b,c
, which you passed to the pmos
key. One problem you'll face is that the variable name
expands to the name (a
, b
, or c
), but it's not the name itself, so you need to expand it first. For that I used:
edeftempa{noexpandtikzset{gate={pos}{name}}}
tempa
after the edef
, tempa
will be something like tikzset{gate={0.12345}{a}}
which does what we want.
Finally, I used
pgfmathparse{rnd}
edefpos{pgfmathresult}
to give a value to pos
.
Full code:
documentclass[tikz]{standalone}
usepackage{expl3}
ExplSyntaxOn
cs_set_eq:NN ClistMapVariable clist_map_variable:nNn
ExplSyntaxOff
% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}
%{{{ Transistor Stick Diagrams
%{{{ Layer Magic
% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}
makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}
defnode@on@layer{aftergroupnode@@on@layer}
%}}}
%{{{ Declare the Node shapes
% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm
%% Left out, boring and too long
makeatother
%}}}
%{{{ Line Styles
tikzset{
M3/.style = { draw=green, line width=0.3, on layer=M3L }, % Metal 3 Path
M2/.style = { draw=yellow, line width=0.3, on layer=M2L }, % Metal 2 Path
M1/.style = { draw=turquoise, line width=0.3, on layer=M1L }, % Metal 1 Path
PO/.style = { draw=blue, line width=0.3, on layer=POL }, % Poly-Silicon Path (Gate)
PD/.style = { draw=red!50, line width=0.3, on layer=DDL }, % P-Diffusion Path (PMOS)
ND/.style = { draw=red, line width=0.3, on layer=DDL }, % N-Diffusion Path (NMOS)
air/.style = { draw=black,dashed,line width=0.1, on layer=CONTL }, % N-Diffusion Path (NMOS)
}
%}}}
%{{{ Port Styles
tikzset{
M3P/.style = {stickport, color=green, node on layer=M3L }, % Metal 3 Terminal
M2P/.style = {stickport, color=yellow, node on layer=M2L }, % Metal 2 Terminal
M1P/.style = {stickport, color=turquoise, node on layer=M1L }, % Metal 1 Terminal
POP/.style = {stickport, color=blue, node on layer=POL }, % Poly-Silicon Terminal
PDP/.style = {stickport, color=red!50, node on layer=DDL }, % P-Diffusion Terminal (PMOS)
NDP/.style = {stickport, color=red, node on layer=DDL }, % N-Diffusion Terminal (NMOS)
CON/.style = {stickcontact, color=black, node on layer=CONTL}, % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
TAP/.style = {sticktap, color=black, node on layer=CONTL}, % Substrate Tap (between touching M1,Diff,N-Diff)
TAPCON/.style = {sticktapcon, color=black, node on layer=CONTL}, % Merged Tap and Via
}
%}}}
%{{{ Automatic Transistors
tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
ClistMapVariable{#1}name
{
pgfmathparse{rnd}
edefpos{pgfmathresult}
edeftempa{noexpandtikzset{gate={pos}{name}}}
tempa
}
}
}
%}}}
%}}}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);
draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);
end{tikzpicture}
end{document}
Remarks
This is one way to do it. There are many more. You could use Mr. marmot's suggestion to "smuggle" the
tikzset
outside the groups, or you could use some other looping function, or even do something clever with styles.I used
clist_map_variable:nNn
to keep the syntax similar to before. You could useclist_map_inline:nn
, which would spare you from doing that expansion shenanigan. I'll leave this one for you.The syntax
tikzstyle{a}=[b]
is deprecated. You should usetikzset{s/.style={b}}
. I changed it in your code.
As I said in the comment, this happens because the contents of foreach
are executed inside a group, so when the group ends, the value of line width
(modified by the very thick
key) is restored to the previous value. That's why doing it outside the foreach
loop works okay.
Solution to the first code
Here's a simple solution by changing the looping command. There are several options, here I used expl3
's fp_step_variable:nnnNn
.
First I make a copy of fp_step_variable:nnnNn
called fpStepVariable
. The syntax of fp_step_variable:nnnNn
is:
fp_step_variable:nnnNn {<initial value>} {<step>} {<final value>} <tl var> {<code>}
so I replaced:
foreach pos in {0.1, 0.2, 0.3, 0.4}
by
fpStepVariable {0.1} {0.1} {0.4} pos
I also added two typeout
s to show the effect. After running the code the console shows:
Line width before: 0.4pt
======== Foreach: pos=0.1 ======== Foreach: pos=0.2 ======== Foreach: pos=0.3 ======== Foreach: pos=0.4
Line width after: 1.2pt
Full code:
documentclass[tikz]{standalone}
usepackage{expl3}
ExplSyntaxOn
cs_set_eq:NN fpStepVariable fp_step_variable:nnnNn
ExplSyntaxOff
tikzset{
mystyle/.code=
{
typeout{Line width before: thepgflinewidth}
fpStepVariable {0.1} {0.1} {0.4} pos
{
tikzset{very thick}, %This line is an exact copy of the comented line but has no effect.
message{======== Foreach: pos=pos}
}
typeout{Line width after: thepgflinewidth}
}
}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[mystyle] (0,0) --++ (5,0);
end{tikzpicture}
end{document}
Solution to the second code
The solution I used here is very similar to the previous one except for a few details.
Previously I used fp_step_variable:nnnNn
because you had an uniform sequence of numbers. Now you have letters. One way to approach the problem is to use a clist_map_...
function to loop through a comma-separated list of things. To keep the usage syntax similar I used clist_map_variable:nNn
, whose syntax is:
clist_map_variable:nNn {<comma list>} <tl var> {<code>}
I copied clist_map_variable:nNn
into ClistMapVariable
and used:
ClistMapVariable{#1}name
where #1
is the list a,b,c
, which you passed to the pmos
key. One problem you'll face is that the variable name
expands to the name (a
, b
, or c
), but it's not the name itself, so you need to expand it first. For that I used:
edeftempa{noexpandtikzset{gate={pos}{name}}}
tempa
after the edef
, tempa
will be something like tikzset{gate={0.12345}{a}}
which does what we want.
Finally, I used
pgfmathparse{rnd}
edefpos{pgfmathresult}
to give a value to pos
.
Full code:
documentclass[tikz]{standalone}
usepackage{expl3}
ExplSyntaxOn
cs_set_eq:NN ClistMapVariable clist_map_variable:nNn
ExplSyntaxOff
% Code adapted from: https://tex.stackexchange.com/a/393496/69074
usetikzlibrary{decorations.markings}
%{{{ Transistor Stick Diagrams
%{{{ Layer Magic
% Source: Adapted from https://tex.stackexchange.com/a/20426/69074
pgfdeclarelayer{M3L} % Metal 3
pgfdeclarelayer{M2L} % Metal 1
pgfdeclarelayer{M1L} % Metal 1
pgfdeclarelayer{POL} % Poly-Silicon
pgfdeclarelayer{DDL} % Diffusion
pgfdeclarelayer{CONTL} % Contacts
pgfsetlayers{DDL,POL,M1L,M2L,M3L,CONTL,main}
makeatletter
pgfkeys{%
/tikz/on layer/.code={
pgfonlayer{#1}begingroup
aftergroupendpgfonlayer
aftergroupendgroup
},
/tikz/node on layer/.code={
gdefnode@@on@layer{%
setboxtikz@tempbox=hboxbgrouppgfonlayer{#1}unhboxtikz@tempboxendpgfonlayeregroup}
aftergroupnode@on@layer
},
/tikz/end node on layer/.code={
endpgfonlayerendgroupendgroup
}
}
defnode@on@layer{aftergroupnode@@on@layer}
%}}}
%{{{ Declare the Node shapes
% Code stolen (and slightly adapted from Circuitikz:
% Source: /usr/share/texmf-dist/tex/generic/circuitikz/pgfcircshapes.tex
makeatletter
newdimensticknodewidth
sticknodewidth=1cm
%% Left out, boring and too long
makeatother
%}}}
%{{{ Line Styles
tikzset{
M3/.style = { draw=green, line width=0.3, on layer=M3L }, % Metal 3 Path
M2/.style = { draw=yellow, line width=0.3, on layer=M2L }, % Metal 2 Path
M1/.style = { draw=turquoise, line width=0.3, on layer=M1L }, % Metal 1 Path
PO/.style = { draw=blue, line width=0.3, on layer=POL }, % Poly-Silicon Path (Gate)
PD/.style = { draw=red!50, line width=0.3, on layer=DDL }, % P-Diffusion Path (PMOS)
ND/.style = { draw=red, line width=0.3, on layer=DDL }, % N-Diffusion Path (NMOS)
air/.style = { draw=black,dashed,line width=0.1, on layer=CONTL }, % N-Diffusion Path (NMOS)
}
%}}}
%{{{ Port Styles
tikzset{
M3P/.style = {stickport, color=green, node on layer=M3L }, % Metal 3 Terminal
M2P/.style = {stickport, color=yellow, node on layer=M2L }, % Metal 2 Terminal
M1P/.style = {stickport, color=turquoise, node on layer=M1L }, % Metal 1 Terminal
POP/.style = {stickport, color=blue, node on layer=POL }, % Poly-Silicon Terminal
PDP/.style = {stickport, color=red!50, node on layer=DDL }, % P-Diffusion Terminal (PMOS)
NDP/.style = {stickport, color=red, node on layer=DDL }, % N-Diffusion Terminal (NMOS)
CON/.style = {stickcontact, color=black, node on layer=CONTL}, % Via (between touching M3,M2,M1,PO,P-Diff,N-Diff)
TAP/.style = {sticktap, color=black, node on layer=CONTL}, % Substrate Tap (between touching M1,Diff,N-Diff)
TAPCON/.style = {sticktapcon, color=black, node on layer=CONTL}, % Merged Tap and Via
}
%}}}
%{{{ Automatic Transistors
tikzset{
gate/.style 2 args=
{
thick,decoration=
{
markings, mark=at position {#1} with
{
draw[PO] (0,-0.25)coordinate(m#2ga)--(0,0.25)coordinate(m#2gb);
node[inner xsep=0, inner ysep=0.1mm,above left,font=tiny,rotate=pgfdecoratedangle-90](x) {$M_{#2}$};
}
},
postaction={decorate}
},
stick pmos/.style=
{
PD,
gate/.list={#1}
},
pmos/.code=
{
ClistMapVariable{#1}name
{
pgfmathparse{rnd}
edefpos{pgfmathresult}
edeftempa{noexpandtikzset{gate={pos}{name}}}
tempa
}
}
}
%}}}
%}}}
begin{document}
begin{tikzpicture}
draw [help lines] (-10,-10) grid (10,10);
draw[stick pmos={{0.333}{1},{0.666}{2}}] (0,0)--++(0,2);
draw[PO] (m1ga)--++(0.5,0.5);
draw[PO] (m2gb)--++(-0.5,-0.5);
draw[pmos={a,b,c}] (3,0)--++(0,2); % Gates spaced automatically
draw[PO] (maga)--++(0.5,0.5);
draw[PO] (magb)--++(-0.5,-0.5);
end{tikzpicture}
end{document}
Remarks
This is one way to do it. There are many more. You could use Mr. marmot's suggestion to "smuggle" the
tikzset
outside the groups, or you could use some other looping function, or even do something clever with styles.I used
clist_map_variable:nNn
to keep the syntax similar to before. You could useclist_map_inline:nn
, which would spare you from doing that expansion shenanigan. I'll leave this one for you.The syntax
tikzstyle{a}=[b]
is deprecated. You should usetikzset{s/.style={b}}
. I changed it in your code.
edited Jan 30 at 21:21
answered Jan 30 at 18:20
Phelype OleinikPhelype Oleinik
22.6k54482
22.6k54482
add a comment |
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f472607%2ftikzset-does-not-work-in-foreach-loop%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Because the contents of
foreach
are executed inside a group (actually two), so local definitions (tikzset
does local definitions) are lost when the loop ends. Depending on what the "statements" you mentioned do you can use different approaches to overcome the grouping offoreach
. That or use another looping command.– Phelype Oleinik
Jan 30 at 18:07
I am going to add further tikzset commands. I have written a style which takes two parameters and draws a line crossing my line. In the end this is for creating transistor stick diagrams.
– mox
Jan 30 at 18:34
With other
tikzset
commands the solution I proposed will work fine. Depending on how you are drawing the diagrams, this can perhaps be achieved with styles. But we'd probably need to see the whole drawing to say for sure.– Phelype Oleinik
Jan 30 at 18:46
First: Thank you! (forgot that in my first comment) I added the context and how I want to use the code. It should be compilable if you comment out the last two lines inside the tikzpicture. They cannot work yet. Could you give an example how to make the code work if the list is not numbers, or -- even better -- how the <key>/.list handler works around this problem?
– mox
Jan 30 at 19:49
In the advanced code you already use all the
aftergroup
trickery, which you could also use fortikzset
. So, to some extent you may benefit from smuggling. Yet I fail to see the purpose of all this here.– marmot
Jan 30 at 20:02