Hi, ich habe nach einer Funktion zum Ermitteln der Einzelkomponenten (x,y) eines Punktes gesucht und bin bei Tex.SX fündig geworden. Im folgenden Beispiel habe ich zwei Varianten ausprobiert und habe ein Problem mit der zweiten (\getxyother higher level, da nur LaTeX).

Open in writeLaTeX
\documentclass{scrartcl}

\usepackage{tikz}

\makeatletter
\newcommand{\getxy}[3]{% 1: point, 2: x-dimen, 3: y-dimen
  \tikz@scan@one@point\pgfutil@firstofone#1\relax
  \edef#2{\the\pgf@x}%
  \edef#3{\the\pgf@y}%
}
\makeatother

\newcommand{\getxyother}[3]{% 1: point, 2: x-dimen, 3: y-dimen
    \newdimen{#2}
    \newdimen{#3}
    \coordinate (temp) at #1;
    \pgfextractx{#2}{\pgfpointanchor{temp}{center}}
    \pgfextracty{#3}{\pgfpointanchor{temp}{center}}
}

\begin{document}

\begin{tikzpicture}
    \coordinate (temp) at (3,2);
    \getxy{(temp)}{\x}{\y};
    \getxyother{(temp)}{\xother}{\yother};
    \draw (\x,\y) -- (\yother,\xother);
    \node[green] at (\x,\y) {\x\ : \y};
    \node[red] at (\yother,\xother) {\the\yother\ : \the\xother};
\end{tikzpicture}

\end{document}

Warum muss bei der zweiten Variante \the bei textueller Ausgabe verwendet werden und bei der ersten nicht?

gefragt 10 Aug '14, 14:33

ErnstZ's gravatar image

ErnstZ
61182833
Akzeptiert-Rate: 62%

bearbeitet 10 Aug '14, 14:37


Was tut \the?

Es gibt verschiedene Arten von Tokens in TeX. Da sind einmal die Control Sequences die man über \def definiert. Dann gibt es noch die Register, wir beschränken uns hier auf Register vom Typ dimen. Ein solches Register alloziert man mittels \newdimen.

Sei der Token \getxy eine Control Sequence. Um TeX dazu zu bringen ihn zu expandieren, also seinen Replacement Text einzusetzen schreibt man im Dokument einfach

Open in writeLaTeX
\def\getxy{...}
\getxy

Bei Registern sieht das anders aus. Man kann nicht das Register an sich expandieren sondern nur seinen Wert setzen oder auslesen. Sei dazu \xother ein Register vom Typ dimen. Wir setzen den Wert mittels

Open in writeLaTeX
\newdimen\xother
\xother=5pt
\xother1cm

Das Gleichheitszeichen ist optional hilft aber der Lesbarkeit. Um nun den Wert des Registers zu erhalten benötigen wir eine Control Sequence die auf den Inhalt des Registers expandiert. Genau das tut \the.

Open in writeLaTeX
\the\xother

Es dürfte offensichtlich sein, warum

Open in writeLaTeX
\xother

den Fehler ! Missing number, treated as zero. hervorruft.

Warum tut in TikZ beides?

Seien zwei Punkte definiert als

Open in writeLaTeX
\def\x{55pt}
\def\y{86pt}
\newdimen\xother
\newdimen\yother
\xother=55pt
\yother=86pt

Dies ist offensichtlich beides mal der gleiche Punkt. In TikZ kann ich nun Nodes an die Punkte setzen mittels

Open in writeLaTeX
\node at (\x,\y) {...};
\node at (\xother,\yother) {...};

Die Koordinaten werden gelesen mit etwas das so ähnlich ist wie

Open in writeLaTeX
\pgf@x=#1
\pgf@y=#2

wobei \pgf@x und \pgf@y Register vom Typ dimen sind und #1 und #2 die x- und y-Koordinate des Punktes sind. Im Fall von \xother und \yother haben wir bereits zwei dimen-Register und die Zuweisung funktioniert ohne Probleme. Im Fall von \x und \y muss einmal expandiert werden aber dann stehen auch zwei Längen da, viz. der Replacement Text 55pt und 86pt, respektive.

Dein Code ohne \the

Ich habe übrigens keine Ahnung was Du mit high-level und low-level meinst.

Open in writeLaTeX
\documentclass{article}
\pagestyle{empty}
\usepackage{tikz}

\makeatletter
\newcommand{\getxy}[3]{% 1: point, 2: x-dimen, 3: y-dimen
  \tikz@scan@one@point\pgfutil@firstofone#1\relax
  \edef#2{\the\pgf@x}%
  \edef#3{\the\pgf@y}%
}
\makeatother

\newcommand{\getxyother}[3]{% 1: point, 2: x-dimen, 3: y-dimen
    \coordinate (temp) at #1;
    \pgfextractx{\dimen0}{\pgfpointanchor{temp}{center}}
    \edef#2{\the\dimen0}
    \pgfextracty{\dimen0}{\pgfpointanchor{temp}{center}}
    \edef#3{\the\dimen0}
}

\begin{document}

\begin{tikzpicture}
    \coordinate (temp) at (3,2);
    \getxy{(temp)}{\x}{\y};
    \getxyother{(temp)}{\xother}{\yother};
    \draw (\x,\y) -- (\yother,\xother);
    \node[green] at (\x,\y) {\x\ : \y};
    \node[red] at (\yother,\xother) {\yother\ : \xother};
\end{tikzpicture}

\end{document}

alt text

Dein Code in Plain TeX

Open in writeLaTeX
\nopagenumbers
\input tikz

\catcode`\@=11
\def\getxy#1#2#3{% 1: point, 2: x-dimen, 3: y-dimen
  \tikz@scan@one@point\pgfutil@firstofone#1\relax
  \edef#2{\the\pgf@x}%
  \edef#3{\the\pgf@y}%
}
\catcode`\@=12

\def\getxyother#1#2#3{% 1: point, 2: x-dimen, 3: y-dimen
    \coordinate (temp) at #1;
    \pgfextractx{\dimen0}{\pgfpointanchor{temp}{center}}
    \edef#2{\the\dimen0}
    \pgfextracty{\dimen0}{\pgfpointanchor{temp}{center}}
    \edef#3{\the\dimen0}
}

\tikzpicture
    \coordinate (temp) at (3,2);
    \getxy{(temp)}{\x}{\y};
    \getxyother{(temp)}{\xother}{\yother};
    \draw (\x,\y) -- (\yother,\xother);
    \node[green] at (\x,\y) {\x\ : \y};
    \node[red] at (\yother,\xother) {\yother\ : \xother};
\endtikzpicture

\bye
Permanenter link

beantwortet 10 Aug '14, 14:55

Henri's gravatar image

Henri
15.7k133943
Akzeptiert-Rate: 46%

bearbeitet 11 Aug '14, 10:05

Danke @Henri. Sehr schöne ausführliche Antwort. Vor allem die Erklärung, warum in TikZ beides geht.

Mit high und low level meinte ich, dass ersteres LaTeX-Bordmittel benutzt und zweiteres TeX-Bordmittel.

(10 Aug '14, 14:59) ErnstZ

@ErnstZ Ich glaube Du definierst den Unterschied darüber, dass \getxy private Makros mit @ im Namen verwendet (was nichts mit einem Unterschied zwischen Plain TeX und LaTeX zu tun hat). Das einzige was \getxy und \getxyother von einer Plain TeX Implementierung unterscheidet ist die Verwendung von \newcommand statt \def und \makeatletter statt \catcode`\@=11, der ganze Rest tut auch wunderbar in Plain TeX.

(11 Aug '14, 10:03) Henri
Deine Antwort
Vorschau umschalten

Folgen dieser Frage

Per E-Mail:

Wenn sie sich anmelden, kommen Sie für alle Updates hier in Frage

Per RSS:

Antworten

Antworten und Kommentare

Markdown-Grundlagen

  • *kursiv* oder _kursiv_
  • **Fett** oder __Fett__
  • Link:[Text](http://url.com/ "Titel")
  • Bild?![alt Text](/path/img.jpg "Titel")
  • nummerierte Liste: 1. Foo 2. Bar
  • zum Hinzufügen ein Zeilenumbruchs fügen Sie einfach zwei Leerzeichen an die Stelle an der die neue Linie sein soll.
  • grundlegende HTML-Tags werden ebenfalls unterstützt

Frage-Themen:

×728

gestellte Frage: 10 Aug '14, 14:33

Frage wurde gesehen: 4,877 Mal

zuletzt geändert: 11 Aug '14, 10:05