Ancora un disegno con TikZ

  • Creatore
    Topic
  • #83482
    lorenzo.pantieri
    Partecipante
      Up
      0
      Down
      ::


      Ciao a tutti. Anche se in questo periodo non sto studiando LaTeX (mi limito a usarlo per i miei documenti), ho (finalmente, dirà qualcuno…) maturato la consapevolezza che imparare il disegno programmato con LaTeX sia essenziale, se si desidera un documento finito di altissima qualità.

      Appena avrò tempo a disposizione lo dedicherò a imparare TikZ. L’Arte del futuro colmerà l’attuale, vistosa, lacuna e conterrà un corposo capitolo su TikZ.

      Per il momento, però, ho bisogno di voi.

      Qualcuno sa suggerirmi il codice per riprodurre questo disegno?

      Grazie anticipate,
      L.

    Visualizzazione 3 filoni di risposte
    • Autore
      Risposte
      • #83483
        Up
        0
        Down
        ::

        lorenzo.pantieri” post=82804Ciao a tutti. Anche se in questo periodo non sto studiando LaTeX (mi limito a usarlo per i miei documenti), ho (finalmente, dirà qualcuno…) maturato la consapevolezza che imparare il disegno programmato con LaTeX sia essenziale, se si desidera un documento finito di altissima qualità.

        Appena avrò tempo a disposizione lo dedicherò a imparare TikZ. L’Arte del futuro colmerà l’attuale, vistosa, lacuna e conterrà un corposo capitolo su TikZ.

        Per il momento, però, ho bisogno di voi.

        Qualcuno sa suggerirmi il codice per riprodurre questo disegno?

        Grazie anticipate,
        L.

        Ottima domanda… disegnare oggetti 3D con TikZ non è affatto facile, ma con un po’ di ingengo si possono fare cose interessanti.

        Il problema principale che vedo è come fare per dividere la piramide all’interno: inserire le etichette o colorare lo sfondo sono cose del tutto secondarie una volta effettuata la divisione. A tal proposito ho semi-riciclato il codice usato in hf-tikz per “contraddistinguere” punti di un segmento (basato a sua volta su How to draw tangent line of an arbitrary point on a path in TikZ): quello presentato qui è meno automatico perché si deve inserire il nome del marcatore oltre che alla posizione. Ogni segmento, di qualsiasi lunghezza, può essere contrassegnato con la libreria apposita con posizioni che vanno da 0 a 1 (inizio e fine del segmento rispettivamente) e quel codice sfrutta proprio questa filosofia.

        Il codice: `
        \documentclass{article}
        \usepackage{tikz}
        \usetikzlibrary{backgrounds,calc,decorations.markings}

        % Codice basato su hf-tikz e la risposta di Jake in:
        % http://tex.stackexchange.com/questions/25928/how-to-draw-tangent-line-of-an-arbitrary-point-on-a-path-in-tikz/25940#25940

        \newif\ifshowmarkers
        \pgfkeys{/tikz/show markers/.is if=showmarkers}
        \pgfkeys{/tikz/show markers=false}

        \pgfkeys{/tikz/.cd,%
        marker color/.initial=blue,
        marker color/.get=\colmarker,
        marker color/.store in=\colmarker,
        marker size/.initial=1pt,
        marker size/.get=\sizemarker,
        marker size/.store in=\sizemarker,
        }

        \tikzset{
        mark at/.style args={#1 named #2}{
        decoration={
        markings,
        mark=
        at position #1
        with
        {
        \coordinate (marker point-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (0pt,0pt);
        \coordinate (marker unit vector-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (1,0pt);
        \coordinate (marker orthogonal unit vector-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (0pt,1);
        \node[coordinate] (#2) at (0pt,0pt){};
        \ifshowmarkers% conditional to make them appear just when invoked
        \draw[draw=none,fill=\colmarker,radius=\sizemarker] (0,0) circle ;
        \else
        \relax
        \fi
        }
        },
        postaction=decorate
        },
        use marker id/.style={
        shift=(marker point-#1),
        x=(marker unit vector-#1),
        y=(marker orthogonal unit vector-#1)
        },
        use marker id/.default=1,
        }

        \begin{document}
        \begin{tikzpicture}[marker size=2pt]
        \draw[show markers,mark at=0.4 named x1,mark at=0.675 named x2] (0,0) –(2,5);
        \draw[show markers,mark at=0.4 named y1,mark at=0.675 named y2] (3.25,-0.25) –(2,5);
        \draw[show markers,mark at=0.4 named z1,mark at=0.675 named z2] (4.5,0.25) –(2,5);

        % Base
        \draw(0,0)–(3.25,-0.25)–(4.5,0.25);

        % Connessioni intermedie:
        % meglio fare pezzo per pezzo così da annotare il punto intermedio
        % della piramide in luce per inserire le percentuali
        \draw[mark at=0.5 named inter-x1] (x1)–(y1);
        \draw[mark at=0.5 named inter-x2] (x2)–(y2);

        \draw(z1)–(y1);
        \draw(z2)–(y2);

        % Etichette con percentuali
        \node[above=0.5cm,rotate=-3.5] at (inter-x1) {20-30\%};
        \node[below=0.5cm,rotate=-3.5] at (inter-x1) {60-70\%};
        \node[above=0.1cm,rotate=-3.5] at (inter-x2) {10\%};

        % Coloriamo la piramide usando le coordinate note
        \begin{scope}[on background layer]
        \fill[blue!30!cyan!30](x1) — (y1) — (3.25,-0.25)–(0,0)–cycle;
        \fill[blue!50!cyan!40](z1) — (y1) — (3.25,-0.25)–(4.5,0.25)–cycle;

        \fill[green!30!lime!30](x2) — (y2) — (2,5) — cycle;
        \fill[green!60!lime!40](z2) — (y2) — (2,5) — cycle;

        \tikzset{etichette/.style={
        inner sep=0pt,
        anchor=east,
        align=center,
        font=\footnotesize,
        }
        }

        % Altre etichette
        \path let \p1=(0,0), \p2=(x1) in
        node[etichette,text width=2cm]
        at (\x1,0.5*\y2) {Metabolismo basale};
        \path let \p1=(x1), \p2=(x2) in
        node[etichette] at (\x1,0.8*\y2) {Attività Fisica};
        \path let \p1=(x2), \p2=(2,5) in
        node[etichette,text width=1.75cm] at (\x1,0.875*\y2) {TID termogenesi indotta degli alimenti};
        \end{scope}
        \end{tikzpicture}

        \end{document}
        ` Nel disegno finale si rimuovano i [tt]show markers[/tt] usati come debug per capire dove i marcatori vengono posizionati.

        Il risultato:

        [attachment=619]Senzanome_2013-03-10.jpg[/attachment]

        Questa è una grande idea per il prossimo tipo di diagramma in smartdiagram 😉

        Ciao
        Claudio

        Attachments:
        You must be logged in to view attached files.
      • #83484
        Up
        0
        Down
        ::


        Ciao,

        Lorenzo, il livello di padronanza di [tt]TikZ[/tt] che ha Claudio è per me (per il momento almeno) inarrivabile. Tuttavia mi sono divertito a vedere come io sarei riuscito a realizzare quel disegno con le mie conoscenze ridotte e usando comandi meno complicati. Ecco il mio risultato:
        `\documentclass{article}

        \usepackage[T1]{fontenc}
        \usepackage[utf8]{inputenc}

        \usepackage{tikz}
        \usetikzlibrary{backgrounds,calc}

        \begin{document}

        \begin{tikzpicture}[x={(1cm,-.15cm)}, y={(0.55cm,0.55cm)}, z={(0cm,1cm)}]

        % definizioni e macro
        \def\lbase{3}
        \def\altezza{7}
        \def\primoLiv{.4}
        \def\secondoLiv{.2}
        \pgfmathsetmacro{\fineSecondoLiv}{\primoLiv+\secondoLiv}

        % coordinate
        \coordinate (baseA) at (0,0,0);
        \coordinate (baseB) at (\lbase,0,0);
        \coordinate (baseC) at (\lbase,\lbase,0);
        \coordinate (baseD) at (0,\lbase,0);
        \coordinate (vertice) at (\lbase/2,\lbase/2,\altezza);

        \coordinate (primoLivelloA) at ($(baseA)!\primoLiv!(vertice)$);
        \coordinate (primoLivelloB) at ($(baseB)!\primoLiv!(vertice)$);
        \coordinate (primoLivelloC) at ($(baseC)!\primoLiv!(vertice)$);

        \coordinate (secondoLivelloA) at ($(baseA)!\fineSecondoLiv!(vertice)$);
        \coordinate (secondoLivelloB) at ($(baseB)!\fineSecondoLiv!(vertice)$);
        \coordinate (secondoLivelloC) at ($(baseC)!\fineSecondoLiv!(vertice)$);

        \node [text width=2cm, align=center, color=blue, anchor=east,xshift=-.5cm] (etichettaPrimoLivello) at ($(baseA)!.5!(primoLivelloA)$) {Metabolismo \\ basale};
        \node [text width=2cm, align=center, color=darkgray, anchor=east,xshift=-.5cm] (etichettaSecondoLivello) at ($(primoLivelloA)!.5!(secondoLivelloA)$) {Attività \\ fisica};
        \node [text width=3cm, align=center, color=red, anchor=east,xshift=-.5cm] (etichettaTerzoLivello) at ($(secondoLivelloA)!.5!(vertice)$) {TID \\ Termogenesi \\ Indotta \\ dagli Alimenti};

        % riempimento primo livello
        \fill [blue!55] (baseA) — (baseB) — (primoLivelloB) — (primoLivelloA);
        \fill [blue!75] (baseB) — (baseC) — (primoLivelloC) — (primoLivelloB);

        % riempimento secondo livello
        \fill [white] (primoLivelloA) — (primoLivelloB) — (secondoLivelloB) — (secondoLivelloA);
        \fill [gray!35] (primoLivelloB) — (primoLivelloC) — (secondoLivelloC) — (secondoLivelloB);

        % riempimento terzo livello
        \fill [red!55] (secondoLivelloA) — (secondoLivelloB) — (vertice);
        \fill [red!75] (secondoLivelloB) — (secondoLivelloC) — (vertice);

        % bordo piramide
        \draw (baseA) — (baseB) — (baseC);
        \draw (baseA) — (vertice);
        \draw (baseB) — (vertice);
        \draw (baseC) — (vertice);

        % primo livello
        \draw (primoLivelloA) — (primoLivelloB) — (primoLivelloC);
        \node at ($($(baseA)!.5!(primoLivelloA)$)!.5!($(baseB)!.5!(primoLivelloB)$)$) {$60 \div 70\%$};

        % secondo livello
        \draw (secondoLivelloA) — (secondoLivelloB) — (secondoLivelloC);
        \node [text width=1cm, align=center] at ($($(primoLivelloA)!.5!(secondoLivelloA)$)!.5!($(primoLivelloB)!.5!(secondoLivelloB)$)$) {$20$ \\ $\div$ \\ $30\%$};

        % terzo livello
        \node at ($($(secondoLivelloA)!.2!(vertice)$)!.5!($(secondoLivelloB)!.2!(vertice)$)$) {$10\%$};

        \end{tikzpicture}

        \end{document}`
        Probabilmente a te non interessa molto questa soluzione, avendo a disposizione quella più raffinata di Claudio. In ogni caso, spero che possa essere utile a qualche utente che, non avendo le conoscenze di Claudio, voglia comunque realizzare quel disegno.

        Ciao e buona giornata,
        Marco.

        P.S. Allego il pdf del mio disegno.

        [attachment=620]piramide.pdf[/attachment]

        Attachments:
        You must be logged in to view attached files.
      • #83485
        lorenzo.pantieri
        Partecipante
          Up
          0
          Down
          ::


          Ringrazio entrambi per le soluzioni.

          Che dire, TikZ è uno strumento formidabile, anche se il codice è ostico.

          Mi sono (in parte) convertito. Ora la vedo così:
          1. se un utente desidera comporre grafici che abbiano una qualità tipografica senza compromessi, TikZ è la soluzione;
          2. per un utente che è disposto a compromessi sulla qualità in nome della semplicità e della velocità, un software WYSIWYG va bene.

          Quest’estate mi ci metto, vediamo che cosa ne esce. 😉

        • #83486
          Up
          0
          Down
          ::


          Marco,

          come dicevo, la parte di codice “importante” non è interamente mio, anzi. È una delle tante “magie” di Jake (per rendere l’idea, in TeX.SX, è il top scorer per tikz-pgf) che ho semplicemente adattato allo scopo, ossia fornire un riferimento arbitrariamente posizionato su segmenti. Non che il codice iniziale non lo facesse, ma creava disambiguità quando si trattava di “usare” i riferimenti: in pratica introducendo un numero arbitrario di markers n, si poteva fare rifermento al secondo con “use marker id=2”; il problema sorge quando ci sono diversi segmenti ognuno con diversi marker: come fare ad identificare esattamente a quale segmento appartiene “use marker id=2” se ci sono tre segmenti tutti suddivisi con lo stesso numero di marker? Inserendo un nodo con una propria label semplifica di molto le cose (così ho distinto x,y e z). Notare che ora, per modificare la divisione della piramide è sufficiente modificare la posizione dei markers (da 0.4 a 0.5) e automaticamente si spostano le label con le percentuali (con la rotazione sembra che cifre e – si sovrappongano.. 😕 ), le linee di divisione e la colorazione.

          Lorenzo,

          più che ostico, direi che ci vuole pazienza quando si tratta di creare figure abbastanza complesse. Come hai visto, per l’esempio con cerchio e triangolo le cose sono semplici mentre in questo caso meno, ma dal codice di Marco si vede come con un po’ di pazienza, definendo bene tutte le posizioni di coordinate e nodi si riesca benissimo lo stesso.

          Ciao
          Claudio

      Visualizzazione 3 filoni di risposte
      • Devi essere connesso per rispondere a questo topic.

      Go to top