Tikz: Pfade (lokal) als Variable oder Ähnliches speichern

Tabellen und Grafiken erstellen und anordnen


guy.brush™
Forum-Century
Forum-Century
Beiträge: 185
Registriert: So 8. Aug 2010, 19:43
Wohnort: Earth

Tikz: Pfade (lokal) als Variable oder Ähnliches speichern

Beitrag von guy.brush™ »

Hallo,

ich hätte eine weitere kleine Frage. Und zwar möchte ich (kompliziertere) Pfade, die ich gezeichnet habe, gerne irgendwie lokal unter einem Namen oder einer Variablen speichern, um später auf sie leichter zugreifen zu können. Eigentlich möchte ich erreichen, dass ich später mithilfe der Variable den Pfad einfach noch einmal zeichnen kann.
\documentclass[a4paper,%
	       11pt,%
	       DIV=10,%
	       BCOR=0mm,%
	       twoside=semi,%
	       footnotes=multiple]{scrartcl}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows,intersections,calc}

\begin{document}

\begin{tikzpicture}
  \draw[name path=test] (0,0) -- (2,3) -- (4,2) -- (3,1);
  \begin{scope}[xshift=10]
    \draw (test) -- (5,5);  % so funktioniert das nicht :(
  \end{scope}
\end{tikzpicture}

\end{document}
Der Grund ist einfach: Um, wie hier ursprünglich gefragt, komplexere Gebilde unterschiedlich einzufärben, kann es nötig sein, den \fill Befehl getrennt vom gezeichneten Rand (\draw) auszuführen. Unter gerade genannten Link habe ich es z.B. so gemacht, dass ich ein gefärbtes Gebilde genommen habe, dass dieselbe "Strecke" innerhalb des Dreiecks zurücklegt wie das "Gewirr" im Inneren. Außerhalb des Dreiecks einfach beliebig vergrößern und dann mit einem \clip in der Dreiecksform abschneiden. Ich hoffe, es ist verständlich, was ich meine ;). Es sieht dann etwa wie folgt aus:
\begin{figure}[!ht]
  \centering
  \begin{tikzpicture}
    \def\gewirrpath{(0,7.42) -- (0,6)
		   -- (-1,5.5)
		   -- (0.1,4.2)
		   -- (0.1,2.1)
		   -- (2.1,2.1)
		   -- (3,2.5)
		   -- (2,1.7)
		   -- (2,1)
		   -- (0,0.5)
		   -- (0,0)}
%     \draw (-5,0) -- (5,0) -- (0,7.42) -- cycle;
    \begin{scope}[fill=blue!42]
      \fill[clip] (-5,0) -- (5,0) -- (0,7.42) -- cycle;
      
      \fill[red!42] (2,1.7) -- (4.2,1.7)
		    -- (5.5,1.7)
		    -- (5.5,-1)
		    -- (0,-1)
		    -- (0,0)
		    -- (0,0.5)
		    -- (2,1)
		    -- cycle;
      % horizontaler Strich im Dreieck (clipped)
      \draw (2,1.7) -- (4.2,1.7);
    \end{scope}
    
    % Dreieck
    \draw[very thick] (-5,0) -- (5,0) -- (0,7.42) -- cycle;
    
    % komisches Gewirr im inneren des Dreiecks
    % Ist die Formatierung im Folgenden so in Ordnung oder kann das zu Problemen führen?
    \draw[name path=gewirr] \gewirrpath;
    \begin{scope}[yshift=-10cm]
      \draw \gewirrpath;
    \end{scope}
%       \draw (gewirr) -- (6,4) -- cycle;
  \end{tikzpicture}
  \caption{Kurioses Dreieck}
  \label{fig:kurioses_dreieck}
\end{figure}
Hier habe ich noch \def verwendeet, aber diese Lösung dürfte nicht sonderlich schön sein :).


Viele Grüße,

\\ guy.brush
Arch Linux - KDE - TeXLive - Kile - \me = Advanced Newbie

Interessensschwerpunkte: Mathematik- und Formelsatz sowie mathematische (Mikro-)Typographie
Offenes Problem: negierte \xarrow-Pfeile beliebiger Länge

Benutzeravatar
bloodworks
Moderator
Moderator
Beiträge: 1425
Registriert: Mo 19. Jan 2009, 10:52
Wohnort: /dev/null

Beitrag von bloodworks »

Hallo du kannst natürlich leere nodes einsetzten und diese benennen.
Deine Lösung ist imo nicht so schlecht, wenn du deine Punkte benennen willst, musst du die erstmal bekannt machen. Dazu ist das imho einfachste die Koordinaten in einem Makro zu speichern und mehrfach aufzurufen. Theoretisch kann tikz auch Pfade speichern, ich halte es so aber für übersichtlicher und mir wäre nciht bekannt, dass das mehrfache definieren von nodes ein Problem geben sollte. Grüße
\documentclass{scrartcl} 
\usepackage[T1]{fontenc} 
\usepackage[ngerman]{babel} 
\usepackage[latin1]{inputenc} 
\usepackage{tikz} 
\usetikzlibrary{matrix,arrows,intersections,calc} 

\begin{document} 

\begin{tikzpicture} 
   \draw (0,0) -- (2,3) -- (4,2)node (anderer Test) {} -- (3,1) node(test) {}; 
   \begin{scope}[xshift=10] 
     \draw (test.center) -- (5,5)--(anderer Test.center);  % so funktioniert das   
   \end{scope} 
\end{tikzpicture} 



 
 
   \begin{tikzpicture} 
  
%     \draw (-5,0) -- (5,0) -- (0,7.42) -- cycle; 


\def\gewirr{(0,7.42) -- (0,6) 
          -- (-1,5.5) 
          -- (0.1,4.2) 
          -- (0.1,2.1) 
          -- (2.1,2.1) 
          -- (3,2.5) 
          -- (2,1.7) node(d) {}
          -- (2,1) node(c) {}
          -- (0,0.5) node(b) {}
          -- (0,0) node(a) {} }       
\def\dreck{(-5,0) node(li u) {}-- (5,0)node(re u){} -- (0,7.42) -- cycle}

 \begin{scope}[fill=blue!42]
       \fill[clip] (-5,0) -- (5,0) -- (0,7.42) -- cycle; 
     
     % Dreieck 
      \path \dreck; 
        \path\gewirr ;
                         \fill[red!42] (a.center)--(b.center)--(c.center)--(d.center)--(8,1.7)--(re u.center)--(a.center) --cycle; 
                 \draw \gewirr ; 
                 \draw[very thick] \dreck;
          \end{scope}
  %die 8,1.7 solltest du dir natürlich auerechnen. 


   \end{tikzpicture}
   
   
   
   
\end{document} 
  
[1] Nützliche Webdokumente für Anfänger und Fortgeschrittene
[2]Minimalbeispiel | [3]FAQ
[4]Regelwerk | [5] Knigge
Wenn nicht anderst angegeben ist mein System: texlive 2012, pdflatex, x86-64, Snow Leopard utd.
Angehöriger der Liga zur Verwendung von texdoc
texdoc mathmode koma l2picfaq l2tabu lshort-en
Achtung: Aufforderungen ein Minimalbeispiel oder mehr Erklärungen zu einer Frage zu liefern sind keine persönlichen Angriffe. Sie dienen viel mehr dazu die Kommunikation zwischen Fragendem und potentiellen Helfern zu erleichtern und zu präzisieren.


guy.brush™
Forum-Century
Forum-Century
Beiträge: 185
Registriert: So 8. Aug 2010, 19:43
Wohnort: Earth

Beitrag von guy.brush™ »

Hallo,

vielen Dank erst einmal für deine Antwort :). Aber mir sind ein paar Dinge noch nicht ganz klar. Erst einmal zu deiner Antwort selbst:
bloodworks hat geschrieben:Deine Lösung ist imo nicht so schlecht [...]
Meinst du damit die \def-Variante? \def soll man doch eigentlich nicht verwenden (außer man weiß, wieso man es jetzt unbedingt braucht). Außerdem sind die definierten "Dinger" dann global unter dem Namen verfügbar.
bloodworks hat geschrieben: [...] wenn du deine Punkte benennen willst, musst du die erstmal bekannt machen. Dazu ist das imho einfachste die Koordinaten in einem Makro zu speichern und mehrfach aufzurufen.
Mit Makro meinst du also die \def-Variante (siehe oben)?
bloodworks hat geschrieben:Theoretisch kann tikz auch Pfade speichern [...]
Und wie ginge das? Oder meinst du mithilfe von \def?
bloodworks hat geschrieben:[...] dass das mehrfache definieren von nodes ein Problem geben sollte. Grüße
Die Aussage verstehe ich nicht ganz. Hast du vielleicht ein kurzes Beispiel?


Dann noch zu deinen Lösungsvorschlägen: Also bei der ersten (kleineren) Tikz-Umgebung hast du mich falsch verstanden bzw. ich mich wohl nicht genau genug ausgedrückt.

Mein Anliegen war, dass ich denselben Pfad, den ich im ersten Minimalbeispiel "test" genannt habe, um 10 nach rechts geshiftet, noch einmal zeichnen lasse und zusätzlich noch eine weitere Strecke zur Koordinate (5,5) (also eigentlich, wegen Shift, (15,15)) anhänge. Die beiden Pfade sollten eigentlich nicht zusammenhängend sein :).

[Wenn ich nämlich einen extra \fill ausführe, dann verwende ich zwar dengleichen Pfad, aber nicht denselben *g*. Ich hänge mein \fill also nicht an die gezeichnete Linie dran, sondern der Rahmen des \fill läuft den Pfad selbst noch einmal ab und hängt dann hinten noch einen weiteren Weg mit dran. Bildlich gesprochen: Ein Männlein läuft vorweg und malt die Grenzlinien, dann läuft ein weiteres Männlein den inneren Weg hinterher und füllt nach innen die Farbe in das Gebiet hinein. Am Rand des Gebiets ist das zweite Männlein frech und geht über die Grenze hinaus und malt kräftig weiter, bis es zum Ursprungspunkt zurückkommt. Dann geht ein drittes Männlein her und nimmt eine riesen, beliebig geformte, Plätzchenaussteckform und trennt die überstehende Farbe vom eigentlichen Gebiet ab (das wäre dann \clip).]

Zum zweiten Lösungsvorschlag: Erst einmal, der Name "dreck" für "Dreieck" ist witzig :D. Ich glaube, ich verstehe, was du machst, bin aber noch etwas verwirrt, warum deine Variante "besser" sein sollte, als die Variante, die ich hatte (mit \def). Ach ... ich sehe gerade, ich habe das gar nicht komplet angepasst *g*. Hier ist ein Beispiel, wie ich es meinte:
\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage[latin1]{inputenc}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows,intersections,calc}

\begin{document}

\begin{figure}[!ht]
  \centering
  \begin{tikzpicture}
    % Ist die Formatierung im Folgenden so in Ordnung oder kann das zu Problemen führen?
    \def\gewirrpath{(0,7.42) -- (0,6)
         -- (-1,5.5)
         -- (0.1,4.2)
         -- (0.1,2.1)
         -- (2.1,2.1)
         -- (3,2.5)
         -- (2,1.7)
         -- (2,1)
         -- (0,0.5)
         -- (0,0)}
    \begin{scope}[fill=blue!42]
      \fill[clip] (-5,0) -- (5,0) -- (0,7.42) -- cycle;
     
      \fill[red!42] \gewirrpath -- (0,-1)
				-- (6,-1)
				-- (6,7.42);
      % horizontaler Strich im Dreieck (clipped)
      \draw (2,1.7) -- (4.2,1.7);
    \end{scope}
   
    % Dreieck
    \draw[very thick] (-5,0) -- (5,0) -- (0,7.42) -- cycle;
   
    % komisches Gewirr im inneren des Dreiecks
    \draw[name path=gewirr] \gewirrpath;
  \end{tikzpicture}
  \caption{Kurioses Dreieck}
  \label{fig:kurioses_dreieck}
\end{figure}

\end{document}
Wenn du den \clip-Befehl auskommentierst, siehst du, wie ich das mit dem Füllen meine. Zum Glück wird nachher das Bild nur auf den sichtbaren Bereich zentriert und es zählt nicht auch noch das zum Bild, was "weggeclipped" wurde :).

Aber genau das wollte ich eben erreichen, indem ich beim Konstruieren des \fill-Befehls eben vorher kein \def brauche (global definiert), sondern mit z.B. "(gewirr)" arbeiten kann, was mein "name path" davon ist. Oder eine andere, ähnliche Lösung.

[Bei dir fehlt übrigens der horizontale Strich, aber ich habe ihn jetzt nicht genau suchen wollen, vermutlich fehlt der nur irgendwo im Code und wurde nicht "übermalt" ... aber das sollte kein Problem darstellen.]


Viele Grüße,

\\ guy.brush
Arch Linux - KDE - TeXLive - Kile - \me = Advanced Newbie

Interessensschwerpunkte: Mathematik- und Formelsatz sowie mathematische (Mikro-)Typographie
Offenes Problem: negierte \xarrow-Pfeile beliebiger Länge

Benutzeravatar
cgnieder
Forum-Meister
Forum-Meister
Beiträge: 730
Registriert: Fr 22. Okt 2010, 18:37
Wohnort: Herrenberg
Kontaktdaten:

Beitrag von cgnieder »

\def definiert die Befehle nur lokal, also innerhalb einer TeX-Gruppe. Da jede Umgebung eine solche Gruppe öffnet (und wieder schließt) sollte alles, was Du mit \def innerhalb der tikzpicture Umgebung definierst, außerhalb nicht definiert sein.

Wenn Dir \def nicht behagt, kannst Du ja \newcommand verwenden:
\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage[utf8]{inputenc}
\usepackage{tikz}

\begin{document}
 \begin{tikzpicture}
  \def\test{ (0,0) -- (2,3) -- (4,2) -- (3,1)}
  \begin{scope}
    \draw \test -- (5,5);
  \end{scope}
  \begin{scope}[xshift=4cm]
    \draw \test -- (0,0) ;
  \end{scope}
\end{tikzpicture}
% Verwendung hier gibt einen Fehler, da \test nur innerhalb des tikzpictures definiert:
% \test

 \begin{tikzpicture}
  \newcommand\test{ (0,0) -- (2,3) -- (4,2) -- (3,1)}
  \begin{scope}
    \draw \test -- (5,5);
  \end{scope}
  \begin{scope}[xshift=4cm]
    \draw \test -- (0,0) ;
  \end{scope}
\end{tikzpicture}
% Verwendung hier gibt einen Fehler, da \test nur innerhalb des tikzpictures definiert:
% \test
\end{document}
Oder auch eigene Befehle fürs speichern und verwenden (ist aber wohl etwas übertrieben):
\begin{filecontents}{savepath.sty}
\ProvidesPackage{savepath}[2011/11/27 0.1 (nicht nur) TikZ-Pfade speichern]

% für die \ifcsdef und \csundef Befehle:
\RequirePackage{etoolbox}

% Pfad speichern; Fehler, wenn der gleiche Identifier schon verwendet wurde:
\providecommand\savepath[2]{\ifcsdef{path@#1}{\PackageError{savepath}{Pfad `#1' schon gespeichert.}{Der Pfad mit dem Namen `#1' wurde schon gespeichert. Bitte waehlen Sie einen anderen Namen.}}{\@namedef{path@#1}{#2}}}

% Pfad überschreiben; Fehler, wenn er noch definiert wurde:
\providecommand\renewpath[2]{\ifcsdef{path@#1}{\@namedef{path@#1}{#2}}{\PackageError{savepath}{Der Pfad `#1' existiert nicht.}{}}}

% Pfad verwenden; Fehler, wenn er noch nicht definiert wurde:
\providecommand\usepath[1]{\ifcsdef{path@#1}{\@nameuse{path@#1}}{\PackageError{savepath}{Der Pfad `#1' existiert nicht.}{}}}

% Pfad löschen; Warnung,  wenn er noch nicht definiert wurde:
\providecommand\deletepath[1]{\ifcsdef{path@#1}{\csundef{path@#1}}{\PackageWarning{savepath}{Der Pfad `#1' existiert nicht.}{Der Pfad `#1' existiert nicht und kann nicht geloescht werden.}}}
\endinput
\end{filecontents}

\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage[utf8]{inputenc}
\usepackage{tikz,savepath}

\begin{document}

\begin{tikzpicture}
  \savepath{test}{ (0,0) -- (2,3) -- (4,2) -- (3,1)}
  \begin{scope}
    \draw \usepath{test} -- (5,5);
  \end{scope}
  \renewpath{test}{ (0,0) -- (3,2) -- (2,4) -- (1,3)}
  \begin{scope}[xshift=4cm]
    \draw \usepath{test} -- (0,0) ;
  \end{scope}
  \deletepath{test}
  \savepath{test}{\node[below] (test) at (0,0) {test} ;}
  \usepath{test}
\end{tikzpicture}
% Verwendung hier gibt einen Fehler,  da nur innerhalb des tikzpictures definiert:
% \usepath{test}

\end{document}
Clemens
Paketauthor

guy.brush™
Forum-Century
Forum-Century
Beiträge: 185
Registriert: So 8. Aug 2010, 19:43
Wohnort: Earth

Beitrag von guy.brush™ »

Tatsächlich, \newcommand und \def wirken nur lokal innerhalb der tikzpicture-Umgebung, scheinbar sogar bei einer einer scope-Umgebung nur lokal innerhalb von der. Ich war mir aber recht sicher, dass ich schon einmal ausprobierte und das ganze dann global bekannt gewesen wäre. Muss ich damals irgendwas falsch gemacht haben.

Was wäre denn hier der Vorteil von \def im Vergleich zu \newcommand?


Und der 2. Vorschlag von dir ist vermutlich tatsächlich etwas "overpowered", aber mal schauen. Hast du das jetzt extra für mich geschrieben?
Arch Linux - KDE - TeXLive - Kile - \me = Advanced Newbie

Interessensschwerpunkte: Mathematik- und Formelsatz sowie mathematische (Mikro-)Typographie
Offenes Problem: negierte \xarrow-Pfeile beliebiger Länge

Benutzeravatar
cgnieder
Forum-Meister
Forum-Meister
Beiträge: 730
Registriert: Fr 22. Okt 2010, 18:37
Wohnort: Herrenberg
Kontaktdaten:

Beitrag von cgnieder »

guy.brush™ hat geschrieben:Tatsächlich, \newcommand und \def wirken nur lokal innerhalb der tikzpicture-Umgebung, scheinbar sogar bei einer einer scope-Umgebung nur lokal innerhalb von der.
Wie gesagt, die Neudefinition findet nur innerhalb einer TeX-Gruppe statt. Möchte man einen Befehl global definieren, muss man das a) in der "äußersten Gruppe" machen:
\documentclass{article}
\def\meinbefehlA{blabla}
\begin{document}
{ \meinbefehlA } \meinbefehlA

\def\meinbefehlB{blablub} { \meinbefehlB } \meinbefehlB
\end{document}
oder b) \gdef verwenden:
\documentclass{article}
\begin{document}
lokal: { \def\meinbefehlA{blabla} \meinbefehlA }% nicht definiert: \meinbefehlA

global: { \gdef\meinbefehlB{blablub} \meinbefehlB } \meinbefehlB
\end{document}
guy.brush™ hat geschrieben:Was wäre denn hier der Vorteil von \def im Vergleich zu \newcommand?
Im Gegensatz zu \def gibt \newcommand einen Fehler aus, wenn man damit einen existierenden Befehl überschreiben würde. Dafür muss man dann bewusst \renewcommand verwenden. Also kann man nicht aus Versehen einen wichtigen Befehl löschen. Bei Namen wie \gewirr sollte das allerdings recht gefahrlos sein.
guy.brush™ hat geschrieben:Und der 2. Vorschlag von dir ist vermutlich tatsächlich etwas "overpowered", aber mal schauen. Hast du das jetzt extra für mich geschrieben?
Hat nur fünf Minuten gedauert...
Clemens
Paketauthor

guy.brush™
Forum-Century
Forum-Century
Beiträge: 185
Registriert: So 8. Aug 2010, 19:43
Wohnort: Earth

Beitrag von guy.brush™ »

Hallo,

sorry für die späte Rückmeldung.

Eine letzte Frage noch: Was würdest du mir empfehlen, \def oder \newcommand?

Irgendwie muss ich da beim Testen damals, ob \def nur lokal oder auch global wirkt, mind. 1 Fehler gemacht haben ... denn ich war fest davon überzeugt, dass es stets global wirkt.

Aber dann kennt LaTeX ja quasi doch lokale Variablen und man kann zur not in einer align(-Umgebung ein längeres Gewirr speichern :). [Noch ungetestet ;).]
Arch Linux - KDE - TeXLive - Kile - \me = Advanced Newbie

Interessensschwerpunkte: Mathematik- und Formelsatz sowie mathematische (Mikro-)Typographie
Offenes Problem: negierte \xarrow-Pfeile beliebiger Länge

Benutzeravatar
cgnieder
Forum-Meister
Forum-Meister
Beiträge: 730
Registriert: Fr 22. Okt 2010, 18:37
Wohnort: Herrenberg
Kontaktdaten:

Beitrag von cgnieder »

Wenn man LaTeX (und eben nicht TeX) verwendet, dann würde ich \newcommand und \renewcommand verwenden. Das sind ja genau die LaTeX-Befehle für eigene Makros.

Ob es so einfach ist, sich längeres Zeug, etwa Formeln innerhalb einer Matheumgebung zu speichern und wiederzuverwenden, wage ich zu bezweifeln.
\documentclass{article}
\usepackage{amsmath}
\begin{document}
Geht:
\begin{equation}
 \newcommand\summe{a+b=c}
 \summe
\end{equation}

Geht nicht:
\begin{align}
 \newcommand\summe{d+e&=f}
 \summe \\
 \summe
\end{align}

\end{document}
Ich habe es nicht überprüft, aber es sieht so aus, als ob bei align einzelne Zeilen in einer eigenen Gruppe sind.
Clemens
Paketauthor

Antworten