Wie kann ich in LaTeX Nomogramme zeichnen?

Wie kann ich in LaTeX Nomogramme zeichnen?

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.

Nomogramm für die Raketengleichung

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!=0
  • Griff 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:

Bildbeschreibung hier eingeben

Antwort2

Aufgrund von Genauigkeitsproblemen bei der Berechnung mit TikZändere ich den Ansatz und verwende ein kleines pearlSkript für diese Berechnungen. Ausführen mitpdflatex -shell-script

Ich verwende decorations.markingsdie Bibliothek, um Abstufungen auf allen Pfadarten vorzunehmen. (Keine Probleme mehr mit Markierungsansammlungen).

Ich habe versucht, einige Erklärungen in den Code einzufügen.

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

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 pearlDrehbuch

#!/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 ;
    }

verwandte Informationen