
Was ist ein Nomogramm
"ANomogramm, auch Nomograph, Alignment-Chart oder Abaque genannt, ist ein grafisches Rechengerät, ein zweidimensionales Diagramm, das die ungefähre grafische Berechnung einer Funktion ermöglicht.“
Beispiel
Die Raketengleichung, die oben in diesem Nomogramm angegeben ist, kann gelöst werden, indem man eine Linie von der Skala links zur Skala rechts zieht. Die Lösung kann man auf der Skala in der Mitte ablesen.
Frage
Wie kann ich die obige Abbildung in LaTeX reproduzieren? Gibt es einen TikZ-Ansatz?
Bonus-Frage
Wie kann ich mit LaTeX beliebige Nomogramme erstellen?
zusätzliche Information
Die obige Abbildung wurde erstellt mit:http://pynomo.org/wiki/index.php?title=Main_Page
Mehr zur Nomographie:http://www.slideshare.net/arulalan/nomography
Antwort1
Haftungsausschluss
Nehmen Sie dies als Ausgangspunkt: Damit die Lösung wirklich in allen Fällen funktioniert, müssen einige Dinge getan werden. Und zwar:
- Behandeln Sie Fälle, in denen Rest (max./min.)! = 0
Griff min!=0Griff Skala von max bis min neben min bis max
Eine Möglichkeit:
\documentclass[tikz,border=10pt]{standalone}
\usepackage{pdftexcmds,etoolbox}
\makeatletter
\newif\ifroundedenabled%
\newif\ifscalemaxtomin%
\newif\ifscalefromzero%
\pgfkeys{/nomogram/.cd,
% keys for a single diagram
part 1/.style={},
part 2/.style={},
part 3/.style={},
single diagram/.cd,
scale max to min/.is if=scalemaxtomin,
scale max to min=false,
scale from zero/.is if=scalefromzero,
scale from zero=true,
at pos/.store in=\dgrposition,
at pos={(0,0)},
height/.store in=\dgrheight,
height=10cm,
min value/.store in=\minval,
min value=0,
max value/.store in=\maxval,
max value=10,
step/.store in=\incstep,
step=1,
horizontal rule width/.store in=\horulewidth,
horizontal rule width=1cm,
min step/.store in=\minstep,
min step={\incstep/2},
minor tick rule width/.store in=\minortickrulewidth,
minor tick rule width=3mm,
little tick rule width/.store in=\litteltickrulewidth,
little tick rule width=1mm,
tick direction/.store in=\tickpos,
tick direction=left,
label above/.store in=\lababove,
label above={},
label sloped/.store in=\labsloped,
label sloped={},
label above rotation/.store in=\rotation,
label above rotation=0,
diagram/.code={
\path \dgrposition node(A){};
\pgfgetlastxy{\xA}{\yA};
\ifscalemaxtomin%
\pgfmathsetmacro\sndval{\maxval-\incstep}
\foreach \y[count=\yi from 0] in {\maxval,\sndval,...,\minval}{
\global\let\maxitems\yi%
}%
\else%
\pgfmathsetmacro\sndval{\minval+\incstep}
\foreach \y[count=\yi from 0] in {\minval,\sndval,...,\maxval}{
\global\let\maxitems\yi%
}%
\fi
\draw(\xA,\yA)--++(0,\dgrheight)
node[pos=0.5,sloped,above]{\labsloped}
node[above,rotate=\rotation,transform shape]{\lababove};% vertical line+above label
\pgfmathsetmacro\actualstep{\dgrheight/\maxitems}%
% little ticks
\pgfmathsetmacro\littletickstep{\actualstep/10}
\foreach \y in {0,\littletickstep,...,\dgrheight}{
\ifnum\pdf@strcmp{\tickpos}{left}=\z@%
\draw(\xA,\yA+\y pt) --++(-\litteltickrulewidth,0);
\fi%
\ifnum\pdf@strcmp{\tickpos}{right}=\z@%
\draw(\xA,\yA+\y pt) --++(\litteltickrulewidth,0);
\fi%
}%
% min step
\pgfmathsetmacro\mintickstep{\actualstep/2}
\ifscalemaxtomin%
\foreach \y [count=\yi from 0,
evaluate=\yi as \ytext using ((\maxval-\yi*\incstep+\yi*\incstep/2))]
in {0,\mintickstep,...,\dgrheight}{%
\ifnumodd{\yi}{% true
\ifnum\pdf@strcmp{\tickpos}{left}=\z@%
\draw (\xA,\yA+\y pt) --++(-\minortickrulewidth,0)
node[left,font=\footnotesize]{\pgfmathprintnumber{\ytext}};
\fi%
\ifnum\pdf@strcmp{\tickpos}{right}=\z@%
\draw (\xA,\yA+\y pt) --++(\minortickrulewidth,0)
node[right,font=\footnotesize]{\pgfmathprintnumber{\ytext}};
\fi%
}{}%
}%
\else%
\foreach \y [count=\yi from 0,
evaluate=\yi as \ytext using ((\yi*\incstep+2*\minval)/2)] in
{0,\mintickstep,...,\dgrheight}{%
\ifnumodd{\yi}{% true
\ifnum\pdf@strcmp{\tickpos}{left}=\z@%
\draw (\xA,\yA+\y pt) --++(-\minortickrulewidth,0)
node[left,font=\footnotesize]{\pgfmathprintnumber{\ytext}};
\fi%
\ifnum\pdf@strcmp{\tickpos}{right}=\z@%
\draw (\xA,\yA+\y pt) --++(\minortickrulewidth,0)
node[right,font=\footnotesize]{\pgfmathprintnumber{\ytext}};
\fi%
}{}%
}%
\fi%
% main step
\ifscalemaxtomin%
\ifscalefromzero%
\foreach \y[count=\yi from 0,
evaluate=\yi as \ytext using (\maxval-\yi*\incstep)] in
{0,\actualstep,...,\dgrheight}{%
\ifnum\pdf@strcmp{\tickpos}{left}=\z@%
\pgfkeys{/pgf/number format/.cd,fixed,precision=2}
\draw (\xA,\yA+\y pt) --++(-\horulewidth,0)
node[left]{\pgfmathprintnumber{\ytext}};
\fi%
\ifnum\pdf@strcmp{\tickpos}{right}=\z@%
\pgfkeys{/pgf/number format/.cd,fixed,precision=2}
\draw (\xA,\yA+\y pt) --++(\horulewidth,0)
node[right]{\pgfmathprintnumber{\ytext}};
\fi%
}%
\else%
\foreach \y[count=\yi from 0,
evaluate=\yi as \ytext using (\maxval-\yi*\incstep)] in
{0,\actualstep,...,\dgrheight}{%
\ifnum\pdf@strcmp{\tickpos}{left}=\z@%
\pgfkeys{/pgf/number format/.cd,fixed,precision=2}
\draw (\xA,\yA+\y pt) --++(-\horulewidth,0)
node[left]{\pgfmathprintnumber{\ytext}};
\fi%
\ifnum\pdf@strcmp{\tickpos}{right}=\z@%
\pgfkeys{/pgf/number format/.cd,fixed,precision=2}
\draw (\xA,\yA+\y pt) --++(\horulewidth,0)
node[right]{\pgfmathprintnumber{\ytext}};
\fi%
}%
\fi%
\else%
\ifscalefromzero%
\foreach \y[count=\yi from 0,
evaluate=\yi as \ytext using (\yi*\sndval+\minval)] in
{0,\actualstep,...,\dgrheight}{%
\ifnum\pdf@strcmp{\tickpos}{left}=\z@%
\pgfkeys{/pgf/number format/.cd,fixed,precision=2}
\draw (\xA,\yA+\y pt) --++(-\horulewidth,0)
node[left]{\pgfmathprintnumber{\ytext}};
\fi%
\ifnum\pdf@strcmp{\tickpos}{right}=\z@%
\pgfkeys{/pgf/number format/.cd,fixed,precision=2}
\draw (\xA,\yA+\y pt) --++(\horulewidth,0)
node[right]{\pgfmathprintnumber{\ytext}};
\fi%
}%
\else%
\foreach \y[count=\yi from 0,
evaluate=\yi as \ytext using (\yi*\incstep+\minval)] in
{0,\actualstep,...,\dgrheight}{%
\ifnum\pdf@strcmp{\tickpos}{left}=\z@%
\pgfkeys{/pgf/number format/.cd,fixed,precision=2}
\draw (\xA,\yA+\y pt) --++(-\horulewidth,0)
node[left]{\pgfmathprintnumber{\ytext}};
\fi%
\ifnum\pdf@strcmp{\tickpos}{right}=\z@%
\pgfkeys{/pgf/number format/.cd,fixed,precision=2}
\draw (\xA,\yA+\y pt) --++(\horulewidth,0)
node[right]{\pgfmathprintnumber{\ytext}};
\fi%
}%
\fi%
\fi%
}%
}
% that's just an alias for \node
\def\drawnomogrampart{\tikz@path@overlay{node}}
\makeatother
\begin{document}
\begin{tikzpicture}
\drawnomogrampart[/nomogram/single diagram/.cd,
height=7cm,
min value=50,
max value=130,
step=10,
label above=$\Delta v$,
scale from zero=false,
diagram]{};
\begin{scope}[rotate=-30,transform shape]
\drawnomogrampart[/nomogram/single diagram/.cd,
horizontal rule width=0.5cm,
height=8cm,
min value=0,
max value=0.901,% for rounding purposes
step=0.1,
label above rotation=30,
label above={$M_f=1-\textrm{e}^{-\Delta v/9.81*I_{sp}}$},
label sloped={Mass Fraction $(M_f)$},
tick direction=right,
diagram]{};
\end{scope}
\drawnomogrampart[/nomogram/single diagram/.cd,
scale from zero=false,
height=7cm,
scale max to min=true,
min value=400,
max value=2000,
step=200,
at pos={(7,0)},
tick direction=right,
label above=IPS (s),
diagram]{};
\end{tikzpicture}
\end{document}
Das Ergebnis:
Antwort2
Aufgrund von Genauigkeitsproblemen bei der Berechnung mit TikZ
ändere ich den Ansatz und verwende ein kleines pearl
Skript für diese Berechnungen. Ausführen mitpdflatex -shell-script
Ich verwende decorations.markings
die Bibliothek, um Abstufungen auf allen Pfadarten vorzunehmen. (Keine Probleme mehr mit Markierungsansammlungen).
Ich habe versucht, einige Erklärungen in den Code einzufügen.
Der Code :
\documentclass[tikz,margin=2pt]{standalone}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.markings,intersections}
%%%% ---- Use path several times
%%%% ---- thanks to Andrew Stacey
\makeatletter
\tikzset{
use path for main/.code={%
\tikz@addmode{%
\expandafter\pgfsyssoftpath@setcurrentpath\csname tikz@intersect@path@name@#1\endcsname
}%
},
use path for actions/.code={%
\expandafter\def\expandafter\tikz@preactions\expandafter{\tikz@preactions\expandafter\let\expandafter\tikz@actions@path\csname tikz@intersect@path@name@#1\endcsname}%
},
use path/.style={%
use path for main=#1,
use path for actions=#1,
}
}
\pgfkeys{/MonoG/.cd,
% foot of the scale
path/.store in=\p@th,
path={(0,0)--(0,10)},
% minimale value
min/.store in=\Min,
min=0,
% maximale value
max/.store in=\Max,
max=10,
% Major graduation Step
step/.store in=\Step,
step=1,
% Big ticks
% tick length
big ticks/.store in=\BTick,
big ticks=.7,
% font (whatever compatible with tikz font parameter)
big ticks font/.store in=\BFont,
big ticks font=\small,
% line width
big ticks width/.store in=\BWidth,
big ticks width=thick,
% medium ticks (same choices)
med ticks/.store in=\MTick,
med ticks=.4,
med ticks font/.store in=\MFont,
med ticks font=\footnotesize,
med ticks width/.store in=\MWidth,
med ticks width=thin,
% small ticks
small ticks/.store in=\STick,
small ticks=.2,
small ticks width/.store in=\SWidth,
small ticks width=very thin,
% number of sublevel of small tick
small ticks level/.store in=\STlevel,
small ticks level=1,
% tick direction
tick direction/.store in=\TickPos,
tick direction=right,
% bottom label
bottom label/.store in=\BotLabel,
bottom label={},
% midway label
midway label/.store in=\MidLabel,
midway label={},
% top label
top label/.store in=\TopLabel,
top label={},
% Reverse graduation
reverse/.store in=\Reverse,
reverse=false,
diagram/.code={%
% draw the path and place the nodes for labelling
\draw[\BWidth,name path=Path] \p@th
node[pos=1,above] (MnAbove) {\TopLabel}
node[midway,sloped,above] (MnMid) {\MidLabel}
node[pos=0,below] (MnBelow) {\BotLabel} ;
% left right position flag
\ifnum\pdf@strcmp{\TickPos}{left}=\z@%
\def\TPos{1}
\fi%
\ifnum\pdf@strcmp{\TickPos}{right}=\z@%
\def\TPos{-1}
\fi%
% reverse scale flag
\def\Rev{1}
\ifnum\pdf@strcmp{\Reverse}{true}=\z@%
\def\Rev{-1}
\fi%
% set the style for the tick labels
\tikzset{Big/.style={font=\BFont,\TickPos,transform shape,rotate=-90},
Med/.style={font=\MFont,\TickPos,transform shape,rotate=-90},
/pgf/decoration/reset marks % Reset marks each time
% to avoid accumulation problems
} ;
% Call of external calculation script
\immediate\write18{%
./script.pl \Min\space%
\Max\space%
\Step\space%
\STlevel\space\STick\space > Sortie.tex}
\input{Sortie}
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\path[/MonoG/.cd,
step=5,
min=5,
max=25.01,
path={(4,0) parabola (8,10)},
diagram
] ;
\path[/MonoG/.cd,
step=1000,
max=4500,
tick direction=left,
small ticks=.2,
small ticks level=2,
top label=$\Delta_V$,
diagram
] ;
% to avoid 5.10e-2
\pgfkeys{/pgf/number format/.cd,fixed,precision=3}
\path[/MonoG/.cd,
path={(11,0)--(11,10)},
step=100,
max=800,
min=199.9,
reverse=true,
small ticks level=2,
small ticks = .3,
top label=IPS (s),
diagram
] ;
\path[/MonoG/.cd,
step=.1,
max=.9,
path={(0,0)--(4,10)},
midway label=Mass Fraction $(M_f)$,
top label={$M_f=1-\textrm{e}^{-\Delta v/9.81*I_{sp}}$},
diagram
] ;
\end{tikzpicture}
\begin{tikzpicture}
\path[/MonoG/.cd,
step=10,
max=12,
small ticks level=2,
diagram
] ;
\path[/MonoG/.cd,
step=1,
max=10.01,
min=0,
tick direction=left,
diagram
] ;
\path[/MonoG/.cd,
path={(3,0)--(3,10)},
min=.2,
step=5,
max=9.7,
diagram
] ;
\path[/MonoG/.cd,
tick direction=left,
path={(3,0)--(3,10)},
min=-5,
step=5,
max=15,
diagram
] ;
\path[/MonoG/.cd,
path={(12,0) arc (0:180:3)},
min=0,
step=30,
small ticks level=2,
max=180.01,
diagram
] ;
\end{tikzpicture}
\end{document}
Das pearl
Drehbuch
#!/usr/bin/perl -w
use POSIX "fmod" ;
$Min = $ARGV[0] ; # Minimum
$Max = $ARGV[1] ; # Maximum
$Step = $ARGV[2] ; # Step of graduation
$Level = $ARGV[3] ; # level of small ticks default 1
$TickL = $ARGV[4] ; # length of small ticks (1st level)
$Coeff = $Max-$Min ; # Scale on the path from 0 to 1
$Begin = $Min - fmod($Min,$Step) ; # Calculation of the place
if ( $Begin < $Min ) { # of the first Label
$Begin += $Step ; }
$X = $Begin ;
$Y = ($X - $Min) / $Coeff ;
print "\\begin{scope}[decoration={markings," ;
while ($X <= $Max) {
print "mark=at position $Y*\\Rev with {\\draw[\\BWidth] (0,0) --++ (0,\\BTick*\\TPos) node[Big] {\\pgfmathprintnumber{$X}} ;},\n" ;
$X += $Step ;
$Y = ($X - $Min) / $Coeff ;
}
print "}]\n" ;
print "\\draw[postaction={decorate},use path=Path];\n" ;
print "\\end{scope}\n" ;
## half step
$X = $Begin - $Step/2 ; # Calculation of
if ( $X < $Min ) { $X += $Step ; } # the first Label
$Y = ($X - $Min) / $Coeff ;
print "\\begin{scope}[decoration={markings," ;
while ($X <= $Max) {
print "mark=at position $Y*\\Rev with {\\draw[\\MWidth] (0,0) --++ (0,\\MTick*\\TPos) node[Med] {\\pgfmathprintnumber{$X}} ;},\n" ;
$X += $Step ;
$Y = ($X - $Min) / $Coeff ;
}
print "}]\n" ;
print "\\draw[postaction={decorate},use path=Path];\n" ;
print "\\end{scope}\n" ;
## 10e ...
$Step /= 10 ;
$Begin = $Min - fmod($Min,$Step) ; # Calculation of
if ( $Begin < $Min ) { # the first Label
$Begin += $Step ; }
if ( $Begin < $Min ) { $Begin += $Step ; } # the first Label
for (my $i = 1; $i <= $Level ; $i++) {
$X = $Begin ;
$Y = ($X - $Min) / $Coeff ;
print "\\begin{scope}[decoration={markings," ;
while ($X <= $Max) {
print "mark=at position $Y*\\Rev with {\\draw[very thin] (0,0) --++ (0,$TickL*\\TPos) ;},\n" ;
$X += $Step ;
$Y = ($X - $Min) / $Coeff ;
}
print "}]\n" ;
print "\\draw[postaction={decorate},use path=Path];\n" ;
print "\\end{scope}\n" ;
$Step /= 2 ;
$TickL /= 2 ;
}