Re: Il disegno programmato nell’Arte di scrivere con LaTeX

#72835
Up
0
Down
::

lorenzo.pantieri” post=82961Ciao a tutti. Con TikZ una cosa si può fare in più e più modi. Per esempio, voglio disegnare un quadrato con ciascun vertice contrassegnato da un cerchietto ed etichettato. Il codice che userei io è molto ingenuo:
`\begin{tikzpicture}
\draw [help lines] (0,0) grid (2,2);
\coordinate (c1) at (1,0);
\coordinate (c2) at (0,1);
\coordinate (c3) at (1,2);
\coordinate (c4) at (2,1);

\node at (c1) [below] {$c_1$};
\node at (c2)

{$c_2$};
\node at (c3) [above] {$c_3$};
\node at (c4)

{$c_4$};

\draw (c1) circle (2pt);
\draw (c2) circle (2pt);
\draw (c3) circle (2pt);
\draw (c4) circle (2pt);

\draw (c1) — (c2) — (c3) — (c4) — cycle;
\end{tikzpicture}`
Insomma:
1. definisco sulla tela le 4 coordinate, una alla volta ;
2. inserisco, in corrispondenza di queste coordinate, le 4 etichette, una alla volta;
3. disegno i 4 cerchietti, uno alla volta (sempre usando le coordinate);
4. disegno il quadrato (sempre usando le coordinate).

Comprensibilissimo, ma tutte quelle istruzioni ripetute sono bruttine.

Ecco un codice più elegante:
`\begin{tikzpicture}
\draw [help lines] (0,0) grid (2,2);
\path (1,0) coordinate (c1)
(0,1) coordinate (c2)
(1,2) coordinate (c3)
(2,1) coordinate (c4);
\draw (c1) — (c2) — (c3) — (c4) — cycle;
\draw (c1) circle (2pt)
(c2) circle (2pt)
(c3) circle (2pt)
(c4) circle (2pt)
(c1) node [below] {$c_1$}
(c2) node

{$c_2$}
(c3) node [above] {$c_3$}
(c4) node

{$c_4$};
\end{tikzpicture} `
Quello che si fa qui è:
1. si traccia un “cammino invisibile” con il solo scopo di definire le coordinate dei vertici;
2. si disegna il quadrato (usando le coordinate);
3. si disegnano cerchietti ed etichette, usando un’unica istruzione \draw.

Questo secondo codice è elegante, ma lo trovo meno intuitivo. Mi date qualche delucidazione in più?

In particolare, è vero che se devo disegnare due oggetti diversi posso sempre farlo con un’unica istruzione \draw?
Per esempio.
`\begin{tikzpicture}
\draw [help lines] (0,0) grid (3,3);
\draw (0,0) rectangle (1,1)
(0,2) rectangle (1,3)
(2,2) rectangle (3,3)
(2,0) rectangle (3,1);
\end{tikzpicture}
`
è uguale al più goffo (ma per me più intuitivo)
`\begin{tikzpicture}
\draw [help lines] (0,0) grid (3,3);
\draw (0,0) rectangle (1,1);
\draw (0,2) rectangle (1,3);
\draw (2,2) rectangle (3,3);
\draw (2,0) rectangle (3,1);
\end{tikzpicture}`
Mi illuminate?

Grazie!

Partendo dal fondo: si è la stessa cosa in termini di risultato, tempi di compilazione e peso del pdf. I due documenti: `
\documentclass{article}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\draw [help lines] (0,0) grid (3,3);
\draw (0,0) rectangle (1,1)
(0,2) rectangle (1,3)
(2,2) rectangle (3,3)
(2,0) rectangle (3,1);
\end{tikzpicture}
\end{document}
` e `
\documentclass{article}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\draw [help lines] (0,0) grid (3,3);
\draw (0,0) rectangle (1,1);
\draw (0,2) rectangle (1,3);
\draw (2,2) rectangle (3,3);
\draw (2,0) rectangle (3,1);
\end{tikzpicture}
\end{document}
` mi forniscono 8468 Byte entrambi.

Passando al primo quesito. Userei un bel [tt]foreach[/tt] con cui si fa decisamente prima: `
\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\draw [help lines] (0,0) grid (2,2);
\coordinate (c1) at (1,0);
\coordinate (c2) at (0,1);
\coordinate (c3) at (1,2);
\coordinate (c4) at (2,1);

\node at (c1) [below] {$c_1$};
\node at (c2)

{$c_2$};
\node at (c3) [above] {$c_3$};
\node at (c4)

{$c_4$};

\foreach \x in {1,…,4}{
\draw (c\x) circle (2pt);
}

\draw (c1) — (c2) — (c3) — (c4) — cycle;
\end{tikzpicture}
\end{document}
` visto che l’operazione disegno dei cerchi era ripetuta. La macro [tt]\x[/tt] assume via via i valori nella lista (da 1 a 4: i tre puntini servono per velocizzare la scrittura) perciò tutto torna viste le definizioni delle coordinate. Poi, potresti dire: perché non applicarlo anche alla definizione delle coordinate? Ecco come: `
\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\draw [help lines] (0,0) grid (2,2);
\foreach \posizione/\x in {{1,0/1},{0,1/2},{1,2/3},{2,1/4}}{
\coordinate (c\x) at (\posizione);
}

\node at (c1) [below] {$c_1$};
\node at (c2)

{$c_2$};
\node at (c3) [above] {$c_3$};
\node at (c4)

{$c_4$};

\foreach \x in {1,…,4}{
\draw (c\x) circle (2pt);
}

\draw (c1) — (c2) — (c3) — (c4) — cycle;
\end{tikzpicture}
\end{document}
` Occorre proteggere fra [tt]{ }[/tt] ogni elemento della lista altrimenti le virgole fra coordinate vengono confuse con quelle di demarcazione dei vari elementi.

In realtà però, il costrutto [tt]foreach[/tt] è dotato di una comodissima chiave [tt]count[/tt] che conta gli elementi nella lista, quindi non c’è motivo di usare due variabili esplicite: `
\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\draw [help lines] (0,0) grid (2,2);
\foreach \posizione[count=\x] in {{1,0},{0,1},{1,2},{2,1}}{
\coordinate (c\x) at (\posizione);
}

\node at (c1) [below] {$c_1$};
\node at (c2)

{$c_2$};
\node at (c3) [above] {$c_3$};
\node at (c4)

{$c_4$};

\foreach \x in {1,…,4}{
\draw (c\x) circle (2pt);
}

\draw (c1) — (c2) — (c3) — (c4) — cycle;
\end{tikzpicture}
\end{document}
` funziona bene ugualmente. Siccome poi si è capito il sistema, applichiamolo anche ai nodi: `
\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\draw [help lines] (0,0) grid (2,2);
\foreach \posizione[count=\x] in {{1,0},{0,1},{1,2},{2,1}}{
\coordinate (c\x) at (\posizione);
}

\foreach \posizione[count=\x] in {below,left,above,right}{
\node at (c\x) [\posizione] {$c_\x$};
}
\foreach \x in {1,…,4}{
\draw (c\x) circle (2pt);
}

\draw (c1) — (c2) — (c3) — (c4) — cycle;
\end{tikzpicture}
\end{document}
` Nota che si possono tranquillamente riutilizzare le variabili di prima e il [tt]foreach[/tt] tratta benissimo anche liste non numeriche (chiavi in questo caso). Siccome poi con un minimo di conoscenze matematiche si può tranquillamente calcolare la sequenza numerica (1,2,3,4,1) del percorso, ecco che un’altra delle opzioni di [tt]foreach[/tt] è di aiuto: `
\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\draw [help lines] (0,0) grid (2,2);
\foreach \posizione[count=\x] in {{1,0},{0,1},{1,2},{2,1}}{
\coordinate (c\x) at (\posizione);
}

\foreach \posizione[count=\x] in {below,left,above,right}{
\node at (c\x) [\posizione] {$c_\x$};
}
\foreach \x in {1,…,4}{
\draw (c\x) circle (2pt);
}

\foreach \x[evaluate=\x as \nextx using {int(mod(\x,4)+1)}] in {1,…,4}{
\draw (c\x) — (c\nextx);
}
\end{tikzpicture}
\end{document}
` Ovviamente tutti questi codici forniscono lo stesso risultato 🙂

Nota, a me non piace molto avere un solo [tt]path[/tt] con miliardi di istruzioni, ma è una preferenza personale; dipende tutto da quante istruzioni devi scrivere: se sono 4 o 5 va bene, se sono di più è indubbio: meglio usare il [tt]foreach[/tt].

Ciao
Claudio

Go to top