Re: [concorsone#2] disegnare schema…

#84783
robitex
Amministratore del forum
    Up
    0
    Down
    ::


    Eccomi qua con notevole e colpevole ritardo.
    Vi riporto i codici sorgente pervenuti per il presente concorsone ed alla fine dichiarerò il vincitore.
    Ecco quello che avevo scritto io, mirando a scrivere il codice che soddisfacesse allo schema grafico nel più breve tempo possibile:
    ho utilizzato l’oggetto nodo multiparte ed un comando appositamente definito che sovrapponesse il disegno di un nodo a due parti con il disegno della freccia ad onda:
    `\documentclass

    {standalone}
    \usepackage{inconsolata}

    \usepackage{tikz}
    \usetikzlibrary{shapes.multipart}

    \tikzstyle{var}=[draw,
    line width=.4pt,
    rectangle split,
    rectangle split parts=2,
    minimum width=14.8mm,
    rectangle split part align={center},
    text depth=0pt]

    \tikzstyle{data}=[draw,
    line width=0.4pt,
    minimum width=14.8mm,
    rectangle split,
    rectangle split parts=2]

    \def\cbox{\rule[-4pt]{0pt}{14pt}}
    \newdimen\step
    \step=17mm

    \def\var(#1,#2)#3{
    \node[var] at (#1, #2) {
    \texttt{#3}
    \nodepart{two}
    \cbox
    };

    \begin{scope}[xshift=#1-6mm,yshift=#2-2mm]
    \draw[line width=1pt,->,scale=0.32] (0,0) ..
    controls (0.6,0.4) and (1,0.5) .. (1.3,-0.1) ..
    controls (1.5,-.8) and (2.2, -0.7) ..(3.5,.7);
    \end{scope}
    }

    \def\data(#1,#2)#3{
    \node[data] at (#1,#2) {
    \nodepart{two}
    \cbox#3
    };

    \begin{scope}[xshift=#1-3.5mm,yshift=#2+3.5mm,scale=.22]
    \draw[line width=1pt,->] (0,0) ..
    controls (0.6,0.4) and (1,0.5) .. (1.3,-0.1) ..
    controls (1.5,-.8) and (2.2, -0.7) ..(3.5,.7);
    \end{scope}
    }

    \begin{document}
    \begin{tikzpicture}

    % assegnazione variabile v
    \node[anchor=west] at (0, 2.5*\step) {\texttt{v = 10}};
    \var(3cm, 2.5*\step){v}
    \data(7.5cm, 2.5*\step){10}

    % assegnazione variabile q
    \node[anchor=west] at (0, 1.5*\step) {\texttt{q = v}};
    \var(3cm, 1.5*\step){v}
    \var(5cm, 1.5*\step){q}
    \data(7.5cm, 1.5*\step){10}

    % modifica della variabile v
    \node[anchor=west] at (0, 0.5*\step) {\texttt{v = v – 5}};
    \var(3cm, 0.5*\step){v}
    \var(5cm, 0.5*\step){q}
    \data(7.5cm, 0.5*\step){5}

    % disegno partizioni
    \foreach \y in {0,1,2,3}
    \draw (0,\y*\step) — (8.5,\y*\step);

    \end{tikzpicture}
    \end{document}
    `

    Francesco Endrici mi ha inviato una soluzione completamente diversa, tra l’altro riuscendo a definire così bene i punti di controllo da aver fornito il codice più bello per il disegno della freccia ad onda:
    Come potete vedere Francesco ha visto lo schema come una tabella.
    `\documentclass[a4paper]{article}
    \usepackage[T1]{fontenc}%per il commento
    \usepackage[utf8]{inputenc}%per il commento
    \usepackage[italian]{babel}%per il commento
    \usepackage{booktabs}
    \usepackage{tikz}
    \usepackage{array}
    \title{Concorsone n. 2}
    \author{Francesco Endrici}
    \date{18 aprile 2013}
    % definisco un comando per creare le sottotabelle
    % il comando genera una tabellina. Se il primo argomento, opzionale, è “u” (up) allora nella cella in alto mette una freccia con scala=1 e nella cella in basso mette il contenuto dell'argomento 2. Altrimenti (se è “d”, che è anche il valore di default) sopra va #2 e sotto va una freccia con scala=1.5.
    \newcolumntype{M}{>{\sffamily\centering\arraybackslash}m{3em}}
    \newcommand{\subtab}[2][d]{%
    \ifx#1u%
    \def\firstcell{\robyarrow}%
    \def\secondcell{#2}%
    \else
    \ifx#1d%
    \def\firstcell{#2}%
    \def\secondcell{\robyarrow[1.5]}%
    \else
    \errmessage{Eh no mio caro, puoi usare solo u e d come argomenti opzionali!}%
    \fi
    \fi
    \begin{tabular}{|M|}
    \hline
    \firstcell\\
    \hline
    \rule[-0.67em]{0pt}{2em}\secondcell\\
    \hline
    \end{tabular}
    }
    % creo la freccia, di dimensioni variabili. (voelndo il “thock” potrebbe diventare “very thick”)
    \newcommand{\robyarrow}[1][1]{%
    \begin{tikzpicture}[baseline=(current bounding box.south),scale=#1]
    \path[use as bounding box] (0, 0.3em) rectangle (1.7em, -0.2em);
    \draw [->,thick] (0,0.0) .. controls (1em,0.8em) and (0.2em,-1.4em) .. (2em,0.4em);
    \end{tikzpicture}
    }

    \begin{document}

    \begin{tabular}{@{\hspace{0.4em}}>\sffamily l@{\hspace{2.1em}} c@{\hspace{1.5em}} c@{\hspace{2.8em}} c}% misure messe a occhio per rendere la tabella simile all'originale, ma anche la spaziatura di default andava benissimo!
    \toprule
    v = 10 &\subtab{v}& &\subtab{10}\\
    \midrule
    q = v &\subtab{v}&\subtab{q}&\subtab{10}\\
    \midrule
    v = v – 5 &\subtab{v}&\subtab{q}&\subtab{5}\\
    \bottomrule
    \end{tabular}

    \end{document}
    `

    Ecco invece la soluzione di Claudio Fiandrino:
    mentre ha esagerato nel voler disegnare la freccia ad onda addirittura con il pacchetto hobby, ha poi snocciolato un codice programmando TikZ come solo lui sa fare.
    `\documentclass[11pt,a4paper]{article}
    \usepackage{charter}
    \usepackage{tikz}
    \usepackage{pdftexcmds}
    \usepackage{etoolbox}
    \usetikzlibrary{calc,hobby,matrix}

    % codice di Enrico:
    % http://www.guitex.org/home/it/forum/5-tex-e-latex/83195-la-libreria-hobby-tikz-non-funziona-piu#83203
    \ExplSyntaxOn
    \cs_if_exist:NF \prg_stepwise_function:nnnN { \cs_gset_eq:NN \prg_stepwise_function:nnnN \int_step_function:nnnN }
    \cs_if_exist:NF \prg_stepwise_inline:nnnn { \cs_gset_eq:NN \prg_stepwise_inline:nnnn \int_step_inline:nnnn }
    \ExplSyntaxOff

    \newcommand{\smootharrow}[1][1]{%
    \begin{tikzpicture}[scale=#1]
    \draw[->](0,0) to[curve through={(0.01,0.01)..(0.19,0.1)..(0.3,-0.05)..(0.7,0.115)}](0.8,0.21);
    \end{tikzpicture}
    }

    \makeatletter
    \tikzset{item style/.style={
    inner ysep=2pt,
    outer sep=0pt,
    text depth=0pt,
    },
    assignment style/.style={
    align=left,
    minimum width=2cm,
    text width=2cm,
    minimum height=0.5cm,
    text height=3pt,
    text depth=0pt,
    },
    item/.code args={#1 and #2}{
    \ifnum\pdf@strcmp{#1}{smooth arrow}=\z@%
    \draw(0,-0.3)rectangle(1,0.2)node[midway,item style]{#2};
    \draw(0,0.2)rectangle(1,0.55)node[midway]{\smootharrow[0.5]};
    \else%
    \ifnum\pdf@strcmp{#2}{smooth arrow}=\z@%
    \draw(0,-0.3)rectangle(1,0.2)node[midway]{\smootharrow[0.75]};
    \draw(0,0.2)rectangle(1,0.55)node[midway,item style]{#1};
    \else%
    \draw(0,-0.3)rectangle(1,0.2)node[midway]{#2};
    \draw(0,0.2)rectangle(1,0.55)node[midway]{#1};
    \fi%
    \fi%
    },
    smootharrow/.code={
    \draw[->](0,0) to[curve through={(0.01,0.01)..(0.19,0.1)..(0.3,-0.05)..(0.7,0.115)}](0.8,0.21);
    },
    every picture/.style={font=\sffamily,},
    }

    \newcounter{lines}
    \setcounter{lines}{1}

    % that's just an alias for \node
    \def\variable#1{\node[item=#1 and smooth arrow]{};}
    \def\value#1{\node(m-\thelines-4)[item=smooth arrow and #1]{};}
    \def\assignment#1{\node(m-\thelines-1)[assignment style]{#1};}
    \def\void{\node[]{};}
    \def\endline{\stepcounter{lines}\\}
    \def\endenv{\\}
    \makeatother

    % code by Andrew:
    % http://tex.stackexchange.com/a/28452/13304
    \let\matamp=&
    \catcode`\&=13
    \makeatletter
    \def&{\iftikz@is@matrix
    \pgfmatrixnextcell
    \else
    \matamp
    \fi}
    \makeatother

    \pgfkeys{/show variables environment/.cd,
    column sep/.initial={1em},
    column sep/.get=\columnsep,
    column sep/.store in=\columnsep,
    row sep/.initial={1ex},
    row sep/.get=\rowsep,
    row sep/.store in=\rowsep,
    scale factor/.initial={1},
    scale factor/.get=\scalefactor,
    scale factor/.store in=\scalefactor,
    }

    \tikzset{matrix aspect/.style={
    column sep=\columnsep,
    column 1/.style={column sep=1.2*\columnsep},
    row sep=\rowsep
    }
    }

    \usepackage{environ}
    \NewEnviron{showvariables}[1][]{%
    \pgfkeys{/show variables environment/.cd,#1}
    \setcounter{lines}{1}
    \scalebox{\scalefactor}{
    \begin{tikzpicture}[baseline]
    \matrix[matrix aspect]{
    \BODY
    };
    \pgfmathtruncatemacro\endloop{\thelines-1}
    \foreach \nline[evaluate=\nline as \nextline using (int(\nline+1))] in {1,…,\endloop}{
    \draw[shorten <=-0.5cm, shorten >=-1.25cm]
    ($(m-\nline-1.south west)!0.3!(m-\nextline-1.north west)$)–
    ($(m-\nline-4.south east)!0.35!(m-\nextline-4.north east)$);
    }
    % last
    \draw[shorten <=-0.5cm, shorten >=-1.25cm]
    ([yshift=-0.18cm]m-\thelines-1.south west)–([yshift=-0.3cm]m-\thelines-4.south east);
    % first
    \draw[shorten <=-0.5cm, shorten >=-1.25cm]
    ([yshift=0.425cm]m-1-1.north west)–([yshift=0.545cm]m-1-4.north east);
    \end{tikzpicture}
    }
    }

    \BeforeBeginEnvironment{showvariables}{\medskip\par}
    \AfterEndEnvironment{showvariables}{\par\medskip\noindent}

    \begin{document}
    \thispagestyle{empty}

    \begin{showvariables}
    \assignment{v = 10} & \variable{v} & \void & \value{10}\endline
    \assignment{ q = v} & \variable{v} & \variable{q} & \value{10}\endline
    \assignment{ v = v – 5} & \variable{v} & \variable{q} & \value{5}\endenv
    \end{showvariables}

    Un esempio con distanze di riga e di colonna personalizzate:

    \begin{showvariables}[column sep=3em,row sep=3ex]
    \assignment{v = 10} & \variable{v} & \void & \value{10}\endline
    \assignment{ q = v} & \variable{v} & \variable{q} & \value{10}\endline
    \assignment{v = v – 5} & \variable{v} & \variable{q} & \value{5}\endline
    \assignment{ z = v} & \variable{v} & \variable{z} & \value{5}\endenv
    \end{showvariables}

    Scalare l'ambiente:

    \begin{showvariables}[scale factor=1.5]
    \assignment{v = 10} & \variable{v} & \void & \value{10}\endline
    \assignment{ q = v} & \variable{v} & \variable{q} & \value{10}\endline
    \assignment{ v = v – 5} & \variable{v} & \variable{q} & \value{5}\endenv
    \end{showvariables}
    \end{document}`

    Visto il regolamento del concorsone #2 apparso nel primo post,
    visto che sia Francesco che Claudio hanno presentato due soluzione valide entro i termini,
    visto che oggi è una bella giornata di sole,
    consultata la commissione in seduta pomeridiana,

    annuncio quindi il vincitore del concorsone #2 è Claudio Fiandrino.

    Motivazione: proprio perché il codice presentato è complesso, più da sviluppatore di pacchetti che non da semplice utente, Claudio è pervenuto alla definizione di alcuni comandi definendo lo schema in modo semantico. Poiché la commissione riserva enorme importanza al linguaggio come essenziale mezzo di utilizzo e sviluppo dei sistemi basati su TeX, si è premiata la soluzione di Claudio.
    Francesco, ha proposto un codice pragmatico dimostrando che le soluzioni possono presentare sorprendenti e diversi punti di vista, e riuscendo a trovare la più bella definizione possibile per il disegno della freccia ad onda.

    Grazie a tutti i partecipanti per aver contribuito con ironia al concorsone.
    R.

    Go to top