我刚刚开始学习使用 PGFPlots 的 TikZ,并尝试了一个简单的热力学 pV 图示例。我对图像很满意,但我知道使用 foreach 循环等可以使代码更加简洁。任何帮助都将不胜感激!
很多原始代码来自以前的 StackExchange 答案作者:Stefan Pinnow。
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{
decorations.markings,
}
\tikzset{
fleche/.style args={#1:#2}{
postaction=decorate,
decoration={
name=markings,
mark=at position #1 with {\arrow[#2,scale=2]{>}}
},
},
}
\pgfplotsset{
/pgf/declare function={
% define V1, V2 and P1
Vone = 3;
Vtwo = 6;
Pone = 6;
% calculate constant nRT
nRT = Vone * Pone;
% now any P can be calculated for a given V
P(\V) = nRT/\V;
% for simplicity of later use already calc P2 here and assign the
% result to a constant
Ptwo = P(Vtwo);
},
}
\pgfplotsset{
/pgf/declare function={
V1one = 3;
V1two = 6;
P1one = 4.56;
nRT1 = V1one * P1one;
P1(\V) = nRT1/\V;
P1two = P1(V1two);
},
}
\pgfplotsset{
/pgf/declare function={
V2one = 3;
V2two = 6;
P2one = 3;
nRT2 = V2one * P2one;
P2(\V) = nRT2/\V;
P2two = P2(V2two);
},
}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
axis x line=bottom,
axis y line=left,
xmin=0,xmax=10,
ymin=0,ymax=10,
ticks = none,
xlabel = Volume,
ylabel = Pressure,
]
\draw [thick, fleche = {0.6:black}] (9/7, 7) -- (18/7,7) node [right = 0.3 cm, fill = white] {Isobaric};
\draw [thick, fleche = {0.6:black}] (18/7,7) -- (18/7,7/2) node [below = 0.5 cm, fill = white] {Isochoric};
\draw [thick, fleche = {0.6:black}] (V1one, P1one) .. controls (4,2.6) .. (V2two, P2two) node[below = 0.2cm, fill = white] {Adiabatic};
\draw[fill = black] (V1one, P1one) circle (2pt);
\draw[fill = black] (V2two, P2two) circle (2pt);
\draw[fill = black] (Vone, Pone) circle (2pt);
\draw[fill = black] (Vtwo, Ptwo) circle (2pt);
\draw[fill = black] (9/7, 7) circle (2pt);
\draw[fill = black] (18/7, 7) circle (2pt);
\draw[fill = black] (18/7, 7/2) circle (2pt);
% Isothermal a bit different
addplot [
thick,
domain=Vone:Vtwo,
fleche={0.6:black},
] {P(x)} node [above = 0.4cm] {Isothermal}
;
\addplot [
thin,
domain=1:8,
] {P(x)};
\addplot [
thin,
domain=1:8,
] {P1(x)};
\addplot [
thin,
domain=1:8,
] {P2(x)};
\end{axis}
\end{tikzpicture}
\end{document}
答案1
总体来说,这对我来说看起来还不错。以下是您可以采取的措施,以避免重复并改善外观。
- 不需要添加几个形式的语句
\draw[fill = black] (V1one, P1one) circle (2pt);
,只需添加即可\addplot[only marks,mark=*] coordinates{ <list of coordinates>};
。 - 不要使用三个几乎相同的图
\pgfplotsinvokeforeach{P,P1,P2}{\addplot [thin,domain=1:8,] {#1(x)};}
。 - 而不是
fleche
使用能产生弯箭的东西。
\documentclass[tikz,border=3mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.17}
\usetikzlibrary{arrows.meta,bending,decorations.markings}
\tikzset{%
->-/.style={
decoration={
markings,
mark=at position 0 with {\pgfextra{%
\pgfmathsetmacro{\tmpArrowTime}{\pgfkeysvalueof{/tikz/arc arrow/length}/(\pgfdecoratedpathlength)}%
\xdef\tmpArrowTime{\tmpArrowTime}}},
mark=at position {#1-3*\tmpArrowTime} with {\coordinate(@1);},
mark=at position {#1-2*\tmpArrowTime} with {\coordinate(@2);},
mark=at position {#1-1*\tmpArrowTime} with {\coordinate(@3);},
mark=at position {#1+\tmpArrowTime/2} with {\coordinate(@4);
\draw[-{Stealth[length=\pgfkeysvalueof{/tikz/arc arrow/length},bend]}] plot[smooth]
coordinates {(@1) (@2) (@3) (@4)};},
},
postaction=decorate,
},
->-/.default=0.5,
arc arrow/.cd,length/.initial=2.5mm,
}
\pgfplotsset{
/pgf/declare function={
% define V1, V2 and P1
Vone = 3;
Vtwo = 6;
Pone = 6;
% calculate constant nRT
nRT = Vone * Pone;
% now any P can be calculated for a given V
P(\V) = nRT/\V;
% for simplicity of later use already calc P2 here and assign the
% result to a constant
Ptwo = P(Vtwo);
},
}
\pgfplotsset{
/pgf/declare function={
V1one = 3;
V1two = 6;
P1one = 4.56;
nRT1 = V1one * P1one;
P1(\V) = nRT1/\V;
P1two = P1(V1two);
},
}
\pgfplotsset{
/pgf/declare function={
V2one = 3;
V2two = 6;
P2one = 3;
nRT2 = V2one * P2one;
P2(\V) = nRT2/\V;
P2two = P2(V2two);
},
}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
axis x line=bottom,
axis y line=left,
xmin=0,xmax=10,
ymin=0,ymax=10,
ticks = none,
xlabel = Volume,
ylabel = Pressure,
]
\draw [thick, ->-] (9/7, 7) -- (18/7,7) node [right = 0.3 cm, fill = white] {Isobaric};
\draw [thick, ->-] (18/7,7) -- (18/7,7/2) node [below = 0.5 cm, fill = white] {Isochoric};
\draw [thick, ->-] (V1one, P1one) .. controls (4,2.6) .. (V2two, P2two) node[below = 0.2cm, fill = white] {Adiabatic};
\addplot[only marks,mark=*] coordinates{
(V1one, P1one)
(V2two, P2two)
(Vone, Pone)
(Vtwo, Ptwo)
(9/7, 7)
(18/7, 7)
(18/7, 7/2) };
% Isothermal a bit different
\addplot [
thick,
domain=Vone:Vtwo,
->-,
] {P(x)} node [above = 0.4cm] {Isothermal}
;
\pgfplotsinvokeforeach{P,P1,P2}{%
\addplot [
thin,
domain=1:8,
] {#1(x)};}
\end{axis}
\end{tikzpicture}
\end{document}