Selbst definierte Funktionen in PGF Thema ist als GELÖST markiert

Tabellen und Grafiken erstellen und anordnen


Rolli
Forum-Guru
Forum-Guru
Beiträge: 382
Registriert: Mi 15. Feb 2017, 08:50
Wohnort: Mittelfranken

Selbst definierte Funktionen in PGF

Beitrag von Rolli »

Hallo,

mit
  • declare function
kann man ja eine Funktion selber definieren. So wie ich es verstanden habe, sind dafür die Standard-Funktionen verfügbar.

Was ich benötige, ist eine abschnittsweise definierte Funktion. Also so etwas wie im Pseudocode:
if x> 10 then f(x) = f1(x)
else if x > 9 then f(x) = f2(x)
else if x > 8 then f(x) = f3(x)
...
Eine Lösung wäre natürlich:
\addplot[domain=9:10] {f1(x)};
\addplot[domain=8:9]  {f2(x)};
\addplot[domain=7:8]  {f3(x)};
...
Der Nachteil dieser Lösung: Wenn sich an der Grenze eines dieser Definitionsbereiche ein Sprung ergibt, sieht man das am Ergebnis.

Gibt es eine Möglichkeit, eine Funktion selber in irgend einer Programmiersprache zu erstellen, und diese dann in pgf zu verwenden?
Im Manual zu pgf habe ich dazu nichts gefunden.

Das Beispiel zeigt die unschönen Ecken an den Sprungstellen:
% !TeX Program = pdflatex
% !TeX encoding = UTF-8 Unicode
% !TeX spellcheck = de-DE

\documentclass{scrartcl}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{document}

\begin{tikzpicture}
\begin{axis}
    \addplot[ultra thick,domain=0:1] {1-e^(-8*x)}; 
    \addplot[ultra thick,domain=1:2] {e^(-8*(x-1))};    
    \addplot[ultra thick,domain=2:3] {1-e^(-8*(x-2))};      
    \addplot[ultra thick,domain=3:4] {e^(-8*(x-3))}; 
\end{axis}
\end{tikzpicture}

\end{document}
Gruß vom Rolli

Rolli
Forum-Guru
Forum-Guru
Beiträge: 382
Registriert: Mi 15. Feb 2017, 08:50
Wohnort: Mittelfranken

Beitrag von Rolli »

Eine "Pfrimel-Bastel-Lösung" wäre natürlich, die einzelnen Abschnitte des Definitionsbereiches überlappend zu gestalten, wie im unteren Beispiel.

Abgesehen davon, dass dies völlig "unmathematisch" wäre, ist das wirklich Gebastele, weil es von der Skalierung und den Liniendicken abhängt, also nur eine Notlösung wäre.
% !TeX Program = pdflatex
% !TeX encoding = UTF-8 Unicode
% !TeX spellcheck = de-DE

\documentclass{scrartcl}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{document}

\begin{tikzpicture}
\begin{axis}[samples=101]
    \addplot[ultra thick,domain=0:1.01] {1-e^(-8*x)}; 
    \addplot[ultra thick,domain=1:2.01] {e^(-8*(x-1))};    
    \addplot[ultra thick,domain=2:3.01] {1-e^(-8*(x-2))};      
    \addplot[ultra thick,domain=3:4.01] {e^(-8*(x-3))}; 
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}
    \addplot[ultra thick,domain=0:1] {1}; 
    \addplot[ultra thick,domain=1:2] {0};    
    \addplot[ultra thick,domain=2:3] {1};      
    \addplot[ultra thick,domain=3:4] {0};
    \draw[ultra thick] (0,1) -- ++ (0,-1);    
    \draw[ultra thick] (1,1) -- ++ (0,-1);
    \draw[ultra thick] (2,1) -- ++ (0,-1);
    \draw[ultra thick] (3,1) -- ++ (0,-1);
    \draw[ultra thick] (4,1) -- ++ (0,-1);
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}[samples=102]
    \addplot[ultra thick,domain=-0.01:1.01] {1}; 
    \addplot[ultra thick,domain=0.99:2.01] {0};    
    \addplot[ultra thick,domain=1.99:3.01] {1};      
    \addplot[ultra thick,domain=2.99:4.01] {0};
    \draw[ultra thick] (0,1) -- ++ (0,-1);    
    \draw[ultra thick] (1,1) -- ++ (0,-1);
    \draw[ultra thick] (2,1) -- ++ (0,-1);
    \draw[ultra thick] (3,1) -- ++ (0,-1);
    \draw[ultra thick] (4,1) -- ++ (0,-1);
\end{axis}
\end{tikzpicture}

\end{document}
Gruß vom Rolli

Gast

Beitrag von Gast »

Die mit declare function definierten Funktionen dürfen ja alles enthalten, was in math expressions von pgf erlaubt ist. Dazu gehören auch Bedingungen. Also kann man auch abschnittsweise definieren:
\documentclass{scrartcl}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{document}

\begin{tikzpicture}
  \begin{axis}[
    samples=100,
    declare function={
      mypartial(\x)={(\x > 3) ? ( e^(-8*(\x-3)) ) :
        ( (\x > 2) ? ( 1-e^(-8*(\x-2)) ) :
        ( (\x > 1) ? ( e^(-8*(\x-1)) ) :
         ( 1-e^(-8*\x) ) ) )
       };
    }
  ]
  \addplot[ultra thick,domain=0:4] { mypartial(x)};    
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}
    \addplot[ultra thick,domain=0:1] {1-e^(-8*x)};
    \addplot[ultra thick,domain=1:2] {e^(-8*(x-1))};    
    \addplot[ultra thick,domain=2:3] {1-e^(-8*(x-2))};      
    \addplot[ultra thick,domain=3:4] {e^(-8*(x-3))};
\end{axis}
\end{tikzpicture}

\end{dcoument}

Rolli
Forum-Guru
Forum-Guru
Beiträge: 382
Registriert: Mi 15. Feb 2017, 08:50
Wohnort: Mittelfranken

Beitrag von Rolli »

Danke, das hilft etwas weiter. pgf kann also C.

Allerdings: Mit nur 100 Samples sieht man an den Unstetigkeitsstellen eine deutliche "Unschönheit". D.h., die Anzahl Stützstellen muss erhöht werden. Das erhöht dramatisch die Übersetzungszeit.

Ich muss etwas ausholen - dann wird mein Minimalbeispiel allerdings nicht mehr "minimal".

Letztendlich möchte ich Augendiagramme zeichnen. In Matlab (oder Octave) kann man ja 1000 einzelne Wellenzüge übereinander legen und erhält nach gefühlt dutzend Millisekunden ein "nett anzuschauendes" Ergebnis.

Nun möchte ich es aber Standalone mit pgf machen und keine Matlab-Grafik als PDF einbinden (es sollen auch Leute bearbeiten können, die Matlab weder installiert haben noch damit umgehen können).

VORSICHT: Mein untenstehendes Beispiel zeigt deutlich die "Unschönheiten", braucht aber dutzende Sekunden zum Übersetzen!

\documentclass{scrartcl}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{document}

\def\aDamp{-8 }
\def\aNoise{0.35*rand }
\def\aStyle{thick}

\begin{tikzpicture}
  \begin{axis}[
    samples=100,
    declare function={
      mypartial(\x)={(\x > 4) ? ( 1-e^(\aDamp *(\x-4)) ) :
        ( (\x > 3) ? ( e^(\aDamp *(\x-3)) ) :
        ( (\x > 2) ? ( 1-e^(\aDamp *(\x-2)) ) :
        ( (\x > 1) ? ( e^(\aDamp *(\x-1)) ) :
         ( 1-e^(\aDamp *\x) ) ) ) )
       };
    }
  ]
  \addplot[\aStyle,domain=0:3.15] { mypartial(x)};    
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
  \begin{axis}[
    samples=30,
    declare function={
      mypartial(\x)={(\x > 4) ? ( 1-e^(\aDamp *(\x-4)) ) :
        ( (\x > 3) ? ( e^(\aDamp *(\x-3)) ) :
        ( (\x > 2) ? ( 1-e^(\aDamp *(\x-2)) ) :
        ( (\x > 1) ? ( e^(\aDamp *(\x-1)) ) :
         ( 1-e^(\aDamp *\x) ) ) ) )
        +\aNoise 
       };
    }
  ]
  \foreach \aCount in {1,2,...,20} {
    \addplot[\aStyle,domain=0:3.15] { mypartial(x)};
    \addplot[\aStyle,domain=0:3.15] { mypartial(x+1)};
  }  
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
  \begin{axis}[
    samples=150,
    declare function={
      mypartial(\x)={(\x > 4) ? ( 1-e^(\aDamp *(\x-4)) ) :
        ( (\x > 3) ? ( e^(\aDamp *(\x-3)) ) :
        ( (\x > 2) ? ( 1-e^(\aDamp *(\x-2)) ) :
        ( (\x > 1) ? ( e^(\aDamp *(\x-1)) ) :
         ( 1-e^(\aDamp *\x) ) ) ) )
        +\aNoise 
       };
    }
  ]
  \foreach \aCount in {1,2,...,20} {
    \addplot[\aStyle,domain=0:3.15] { mypartial(x)};
    \addplot[\aStyle,domain=0:3.15] { mypartial(x+1)};
  }  
\end{axis}
\end{tikzpicture}


\end{document}
Gruß vom Rolli

P.S.: Seit heute muss man sich für Overleaf anmelden? ?? ???

Gast

Beitrag von Gast »

Hier kann LuaTeX eine Stärke ausspielen. Allerdings sollten dann in Funktionen keine Makros verwendet werden, weshalb ich stattdessen ebenfalls Funktionen verwende. Während dein Versuch bei mir mit pdflatex rund 50 Sekunden benötigt, braucht das folgende mit lualatex nur 4 Sekunden:
\documentclass{scrartcl}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{document}

\def\aStyle{thick}

\begin{tikzpicture}
  \begin{axis}[
    samples=100,
    declare function={
      aDamp=-8;
      mypartial(\x)={(\x > 4) ? ( 1-e^(aDamp *(\x-4)) ) :
        ( (\x > 3) ? ( e^(aDamp *(\x-3)) ) :
        ( (\x > 2) ? ( 1-e^(aDamp *(\x-2)) ) :
        ( (\x > 1) ? ( e^(aDamp *(\x-1)) ) :
         ( 1-e^(aDamp *\x) ) ) ) )
       };
    }
  ]
  \addplot[\aStyle,domain=0:3.15] { mypartial(x)};    
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
  \begin{axis}[
    samples=30,
    declare function={
      aDamp=-8;
      aNoise=0.35*rand;
      mypartial(\x)={(\x > 4) ? ( 1-e^(aDamp *(\x-4)) ) :
        ( (\x > 3) ? ( e^(aDamp *(\x-3)) ) :
        ( (\x > 2) ? ( 1-e^(aDamp *(\x-2)) ) :
        ( (\x > 1) ? ( e^(aDamp *(\x-1)) ) :
         ( 1-e^(aDamp *\x) ) ) ) )
        +aNoise
       };
    }
  ]
  \foreach \aCount in {1,2,...,20} {
    \addplot[\aStyle,domain=0:3.15] { mypartial(x)};
    \addplot[\aStyle,domain=0:3.15] { mypartial(x+1)};
  }  
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
  \begin{axis}[
    samples=150,
    declare function={
      aDamp=-8;
      aNoise=0.35*rand;
      mypartial(\x)={(\x > 4) ? ( 1-e^(aDamp *(\x-4)) ) :
        ( (\x > 3) ? ( e^(aDamp *(\x-3)) ) :
        ( (\x > 2) ? ( 1-e^(aDamp *(\x-2)) ) :
        ( (\x > 1) ? ( e^(aDamp *(\x-1)) ) :
         ( 1-e^(aDamp *\x) ) ) ) )
        +aNoise
       };
    }
  ]
  \foreach \aCount in {1,2,...,20} {
    \addplot[\aStyle,domain=0:3.15] { mypartial(x)};
    \addplot[\aStyle,domain=0:3.15] { mypartial(x+1)};
  }  
\end{axis}
\end{tikzpicture}


\end{document}
Achtung: Falls lualatex das erste Mal verwendet wird, muss es eventuell die Font-Datenbank noch neu aufbauen. Für Zeitvergleiche mit lualatex sollte man daher immer min. zwei Versuche starten und den ersten wegwerfen.

Rolli
Forum-Guru
Forum-Guru
Beiträge: 382
Registriert: Mi 15. Feb 2017, 08:50
Wohnort: Mittelfranken

Beitrag von Rolli »

Danke, das probiere ich gleich mal aus.
Allerdings hatte ich mit lualatex früher einige Male das Problem, daß "ß" als "SS" ausgegeben wird - habe mich damit aber noch nicht näher beschäftigt.

Gast

Beitrag von Gast »

Bei lualatex weder fontenc noch inputenc (oder selinput) laden! Die Dateien sollten natürlich utf8-codiert sein. Dann klappt das mit dem ß auch.

Rolli
Forum-Guru
Forum-Guru
Beiträge: 382
Registriert: Mi 15. Feb 2017, 08:50
Wohnort: Mittelfranken

Beitrag von Rolli »

Danke!!!

Mit lualatex geht es tatsächlich gefühlte 30-fach schneller.

Gruß vom Rolli

Antworten