Inserito da: robitex | Novembre 23, 2009

Il fiocco di Von Koch in METAPOST

La curva di Von Koch

Il bellissimo fiocco di neve di Niels Fabian Helge von Koch, matematico svedese vissuto a cavallo del 1900, è una delle prime strutture frattali mai descritte.

Naturalmente è utile consultare la pagina web sull’argomento su wikipedia e quella dedicata da Wolfram MathWorld, ma certo non sarà difficile reperire in rete altre notizie se ancora non bastasse.

Si tratta di una curva chiusa di perimetro infinito ma di area finita, molto nota. Potevamo perdere l’occasione di generarla in METAPOST?

Effettivamente la curva si può costruire con il pacchetto METAOBJ, ma come problema ricorsivo non è male da implementare con quello che sappiamo già dai precedenti post.

La costruzione

Per ciascun lato di un triangolo equilatero, si trovano i due punti che lo dividono in tre parti uguali, poi si costruisce il triangolo equilatero sul tratto centrale che si eliminerà, e si reitera all’infinito.

Building the Von Koch's curve

Building the Von Koch's curve

Come si vede dalla figura qui sopra il procedimento è semplice, ed avremo potuto introdurlo su un solo segmento. Si vedono le curve di Von Koch di livello 0, 1 e 2, con rispettivamente 3, 12, e 48 segmenti distinti.

METAPOST in action

Diciamo che nella variabile numerica lato memorizziamo la lunghezza del lato del triangolo di base che darà origine alla curva di Von Koch snowflake. Il codice per disegnare l’iterazione successiva deve trovare i due punti intermedi sul lato e costruire il triangolo equilatero sul terzo medio. Ecco il codice METAPOST:

beginfig(1);
numeric lato;
lato := 100;

pair a,b,p,q,r;

a := origin;
b := (lato,0);
p := 1/3[a,b];
q := 1/3[b,a];
r := q rotatedabout(p,-60);

draw a--p--r--q--b
withcolor .625red;
endfig;
end

Abbiamo fatto uso della comoda notazione per ricavare i punti P e Q che tripartiscono il segmento AB disteso sull’asse x e di lunghezza lato, e l’altrettanto comoda funzione rotatedabout() non nativa ma costruita con trasformazioni elementari, con la quale si crea il punto R, vertice del triangolo di prima iterazione.

Non rimane che costruire la funzione ricorsiva.
Faremo così: accetteremo in input i punti estremi del segmento ed il livello fino a cui la funzione disegnarà la curva di Koch, e su questo baseremo il controllo di terminazione della ricorsione:

se il livello richiesto è zero, allora disegna il segmento AB, altrimenti trova i punti intermedi P, Q ed R e lancia la funzione stessa sui quattro sotto lati AP, PR, RQ e QB

Invece di elaborare oggetti path lavoriamo così più semplicemente sui punti vertice della curva. Lo stack delle chiamate ricorsive ci darà gratis l’ordine di disegno tra i punti fino al livello desiderato.

Il numero dei segmenti disegnati n è una funzione esponziale del livello v, si ha infatti (per il numero dei segmenti della la curva di Kock completa moltiplicare ulteriormente per 3):

\displaystyle n = 4^v

Ecco il codice completo:

beginfig(1);
pickup pencircle scaled .75pt;

vardef koch(expr aa,zz,level)=
save p,q,r;
pair p,q,r;

if level=0:
draw aa -- zz
withcolor .625red;
else:
p := 1/3[aa,zz];
q := 1/3[zz,aa];
r := q rotatedabout(p,-60);

koch(aa, p,level-1);
koch( p, r,level-1);
koch( r, q,level-1);
koch( q,zz,level-1);
fi
enddef;

numeric lato ;
numeric n;

lato := 420pt;
n := 5;
koch( origin , (lato,0) , n);
koch( (lato,0) , lato*dir(60) , n);
koch( lato*dir(60) , origin , n);

endfig;
end

dove abbiamo utilizzato una macro vardef dando istruzione di utilizzo di p, q, ed r come variabili locali (comando save).

Pronti a scaricare il risultato nel formato PDF? Fate click allora sull’immagine sottostante.

A Von Koch flake with level 5

A Von Koch flake with level 5

Alla prossima.

Inserito da: robitex | Novembre 13, 2009

Dalla Pretesting alla TeX Live 2009

Ciao a te,
con l’arrivo della versione ufficiale della TeX Live 2009, l’11 novembre scorso, la versione Pretesting resa pubblica a scopi di test e feedback, ha perso i suoi repository.

Gli utenti che hanno installato la TeX Live Pretesting cosa devono fare?
La risposta è moooolto semplice e non è installare tutto da zero, ma basta rilocalizzare il repository!.

Dalla TeX Live Pretesting alla 2009 senza passare dal VIA!

Dunque, intanto sistemate sul Desktop in modo che stia comoda, una finestra di console (che abbiate a che fare con l’Explorer di Windows o con il DE di Linux è la stessa cosa).
Possibilmente sorseggiando un buon te, selezionate il mirror CTAN di cui vi fidate per esempio ftp.snt.utwente.nl con il comando (servono i diritti di root):

tlmgr option repository ftp://ftp.snt.utwente.nl/pub/software/tex/systems/texlive/tlnet

From TeX Live Pretesting to TeX Live 2009

From TeX Live Pretesting to TeX Live 2009, tlmgr command

Benvenuti nella TeX Live 2009!!!

Inserito da: robitex | Novembre 7, 2009

Il triangolo di Sierpiński con METAPOST

La ricorsione è sempre la via migliore?

A not recursive algorithm for the Sierpinski fractal triangle

A not recursive algorithm for the Sierpinski fractal triangle

Sembra che il miglior modo di affrontare una struttura ricorsiva come il triangolo del matematico polacco sia appunto un algoritmo ricorsivo.

Tuttavia leggendo il codice relativo nel post predecente ho cominciato a ragionare sulla possibilità di chiamare ricorsivamente la funzione di disegno nominata sierpinski() una sola volta anziché tre volte, una per ciascun triangolo del livello inferiore.

L’idea che mi è venuta è quella di disegnare il triangolo dal basso, triplicando per ciascun livello successivo il disegno. Tuttavia questo si può elegantemente fare con un ciclo iterativo semplice!

Dunque vi propongo una seconda soluzione (scritta in METAPOST) in cui il disegno è ottenuto con un normalissimo ciclo for.

Il codice spiegato passo passo

Come d’abitudine propongo l’implementazione dell’idea sviluppandola di pari passo con il codice, seguito dal disegno che ne deriva.

Per prima cosa disegniamo il primo triangolo equilatero (per una breve e mirata introduzione a METAPOST potete far riferimento utile al post precedente su questo stesso blog).

beginfig(1);

u = 40 mm;
fill origin -- (u,0) -- u * dir(60)-- cycle
withcolor .625red;
drawarrow origin -- u * dir(60)
withpen pencircle scaled 5 pt;
endfig;
end

An example with the dir() METAPOST function

An example with the dir() METAPOST function

Impostare una variabile unità qui settata a 40 mm è molto comodo, ma quello che dovreste notare di questo codice è l’uso della funzione dir() per fornire al path le coordinate del vertice alto del triangolo equilatero. La funzione restituisce un vettore unitario che forma l’angolo specificato con l’asse x di senso antiorario con centro nell’origine.
Questo vettore viene visualizzato con il comando drawarrow seguente.

METAPOST disegna il vettore restituito da dir() come un punto corrispondente al secondo estremo dello stesso. Del resto sarebbe scomodo se nel path andasse il vettore piuttosto che il punto.

Nel prossimo esempio possiamo vedere l’uso del costrutto for impiegando la funzione dir() a riprova che dir(angolo) produce il disegno di un punto:

beginfig(2);
numeric u;
u = 40 mm;

for ang = 0 step 15 until 345:
draw u * dir(ang)
withpen pencircle scaled 12 pt;
endfor;
endfig;

A polar example with dir() METAPOST function

A polar example with dir() METAPOST function

Per andare avanti sul nostro obbiettivo Sierpinski, occorre spiegare il concetto di picture. I comandi grafici non fanno altro che plottare disegni in una picture. Ci sono sempre disponibili due oggetti picture, quella corrente detta currentpicture e quella vuota detta nullpicture. Un po’ di codice chiarirà di cosa si tratta:

beginfig(3);
% set the thin of the pen
pickup pencircle scaled 3pt;

draw fullcircle scaled 80pt
withcolor 0.5 green;

picture pic;
pic := currentpicture;
currentpicture := nullpicture;

draw pic;
draw pic shifted (80pt,0);
endfig;

The METAPOST picture concept at work

The METAPOST picture concept at work

All’oggetto pic di tipo picture viene assegnato il disegno corrente, che in quel momento contiene un cerchio verde, poi il disegno viene cancellato. In questo momento il cerchio verde si trova memorizzato in un solo luogo: la picture pic.
Allora possiamo tornare a riempire currentpicture disegnando prima pic nella sua posizione e poi in quella traslata a destra.

L’idea iterativa Sierpinski

% set the unit size
u = 10 mm;

% a picture object
picture sier;

sier:= currentpicture;
draw sier shifted (u,0);
draw sier shifted (dir(60) scaled u);

The basic idea for a iterative Sierpinski drawing method

The basic idea for a iterative Sierpinski drawing method

Questo frammento di codice è il cuore del programma che disegna il triangolo frattale in maniera iterativa e non ricorsiva.
Si presuppone che la currentpicture contenga all’inizio il triangolino di base molto piccolo. Dapprima si memorizza il disegno corrente nella variabile sier, di tipo picture naturalmente, e semplicemente l’aggiungiamo al disegno corrente stesso prima a destra e poi in alto a 60° al posto giusto.

In altre parole come si vede in figura, il triangolo rosso viene memorizzato in una picture e poi viene riaggiunto due volte nella posizione dei triangoli blu. Basterà iterare all’infinito questo procedimento!

Il ciclo for Sierpinski

beginfig(4);
% set the unit size
u = 0.65 mm;

% draw the basic smallest triangle
fill origin--(u,0)-- dir(60) scaled u --cycle
withcolor .625red;

% a picture object
picture sier;

% recursive level
level = 8;

% main drawing cycle
for i=0 upto level-1:
tmp := u * (2**i);
sier:= currentpicture;
draw sier shifted (tmp,0);
draw sier shifted (dir(60) scaled tmp);
endfor;

endfig;

Adesso il codice è completo. L’operazione precedente di copia a destra ed a 60° è inserita nel ciclo iterativo for che produce il triangolo del livello desiderato (ho scelto il livello 8).
Aggiungo che ad un dato livello i la copia del disegno deve esser fatta ad una distanza di u \cdot 2^i, poichè ogni volta che si sale di un livello, il lato del triangolo raddoppia (il doppio asterisco significa quindi elevamento a potenza).

Alla prossima!

Inserito da: robitex | Novembre 5, 2009

Introduzione a METAPOST

METAPOST

Il linguaggio METAPOST possiede alcune caratteristiche peculiari come la possibilità di risolvere sistemi di equazioni lineari, ma la cosa che mi ha convinto a provare il babbo di Asymptote è stata la decisione degli sviluppatori di luatex di includerlo come libreria nativa con il nome di MPlib.

La sintassi di METAPOST sviluppato originariamente da John D. Hobby, è piuttosto asciutta, del resto deriva dal METAFONT l’originale programma di creazione di font tipografici dello stesso Donald Knuth, creatore di TeX, a differenza del quale produce un output Postscript (quindi il nome), digeribile anche da pdflatex (i disegni possono essere inseriti nel documento direttamente senza conversioni).

Naturalmente una qualsiasi distribuzione LaTeX (che sia TeX Live, MiKTeX o MacTeX), installarerà sul vostro sistema (che sia Linux, Windows o MacOS), la più recente versione di METAPOST.

Primo codice

La funzione primitiva per disegnare è chiamata (ovviamente) draw ed accetta come argomenti percorsi ed anche intere figure chiamate picture. Per esempio per disegnare un rettangolo 36×28 mm si scrive:

draw origin -- (36mm,0) -- (36mm,28mm) -- (0,28mm) -- cycle;

od anche (aggiungendo un po’ di colore):

u = 1mm;
draw origin -- (36u,0) -- (36u,28u) -- (0,28u) -- cycle
withcolor .625red;

I punti del tipo pair vengono istanziati descrivendone le coordinate tra parentesi tonde ed equiparando l’idea di punto a vettore con il primo estremo nell’origine, così da poter effettuare trasformazioni geometriche come traslazioni (chiave shifted) oppure rotazioni (chiave rotated) od ancora operazioni di scala (chiavi scaled, xscaled, yscaled, zscaled).

Definiamo il rettangolo come percorso e disegnamolo due volte, la prima con riepimento grigio e la seconda solo con il contorno ma traslato del vettore (2mm,2mm), vediamo l’esempio (completando l’esempio con le istruzioni iniziali e finali indispensabili per la corretta compilazione):

% prima prova con METAPOST
beginfig(1);
u = 1.0mm;
path p;
p = origin -- (36u,0) -- (36u,28u) -- (0,28u) -- cycle;

fill p shifted (2u,2u) withcolor .75white;
draw p withcolor .625red;

endfig;
end

ed ecco il risultato:

First test of the METAPOST language

First test of the METAPOST language

Il parametro 1 passato alla funzione beginfig() non è altro che il numero che viene assegnato come estensione al file del disegno. Vengono infatti creati tanti file di output quanti ambienti beginfig()…endfig vi sono nel sorgente e quel numero serve appunto a numerarli.

Il codice va inserito in un file di testo con estensione .mp e poi compilato per ottenere i file dei disegni (il piccolo grande editor SciTE può essere di (grande) aiuto, come pure un visualizzatore Postscript).

Come vedete ci sono i punti e virgola finali che consentono di impaginare il sorgente come si desidera, i commenti che iniziano con il simbolo di percento, ed una sinteticità espressiva generale che in qualche modo esalta la potenza grafica di METAPOST (non lasciatevi ingannare dalla sua modestia…).

Esiste anche la possibilità di instanziare il vettore unitario con direzione specificata per mezzo della funzione dir() che accetta il valore dell’angolo con verso antiorario dall’asse x (così il punto dir(0) è del tutto equivalente al punto (1,0) ).

Per individuare un punto su un segmento è possibile utilizzare l’espressione factor[p1,p2], se factor = 0.50 verrà restituito il punto di mezzo.

Ecco l’ultimo esempio:

% seconda prova con METAPOST
beginfig(1);
% disegnamo un triangolo equilatero
u = 5 mm;

pair A; A=origin;
pair B; B=(7u,0);
pair C; C=(dir(60) scaled 7u);

pair m; m = 0.5[B,C];
pair g; g = 2/3[A,m];

path p; p = A--B--C--cycle;

% regolazione dello spessore della penna
pickup pencircle scaled 4pt;

draw p
withcolor .625red;
fill p scaled .8 shifted .2 g
withcolor .565blue;

endfig;
end

More difficult METAPOST example

More difficult METAPOST example

Bene, ora ne sappiamo abbastanza per procedere, ma mi raccomando, la comprensione dei concetti qui esposti è molto superiore se eseguirete anche degli esercizi con METAPOST, pertanto fateli!!! Ne ricaverete ottime basi e grande soddisfazione.

Happy METAPOST!

Inserito da: robitex | Novembre 4, 2009

Testare i server europei di CTAN

L’idea

Qualche tempo fa, durante i test della TeX Live 2009, la distribuzione TeX di imminente rilascio, proposi agli sviluppatori di dotare lo script tlmgr della possibilità di scaricare i file da più di un mirror CTAN allo stesso tempo per superare eventuali problemi con il server abituale (in quel momento il server ufficiale italiano era lentissimo).

L’idea venne rifiutata adducendo problemi tecnici, allora non ci rimane che ingegnarci per rispondere alla domanda qual’è il server mirror più veloce da settare come fonte di default per la nostra distribuzione?

netselect

L’utility netselect fa al caso nostro: prende in input una serie di url server e ne stila una classifica impietosa!!. Naturalmente il risultato non ha un valore assoluto poiché dipende dalla connessione che si sta utilizzando e dal traffico in quel momento presente, ecc.

CTAN test server

CTAN european server test result

Installiamolo in un attimo

Apriamo un terminale e digitiamo con i diritti di root:
apt-get install netselect

naturalmente stiamo parlando di un sistema Debian Like, per esempio Ubuntu.

Test sui server CTAN!

Copiate in un file il testo seguente, non è altro che il lancio di netselect su TUTTI i server europei di CTAN alla data di oggi (ci vuole un po’ di pazienza ma la faticaccia l’ho fatta io per voi :-) ), rendetegli i permessi di esecuzione e lanciatelo da terminale.

#!/bin/sh
netselect -vvv ftp.univie.ac.at gd.tuwien.ac.at mirrors.dotsrc.org \
mirrors.dotsrc.org ftp.linux.ee ftp.funet.fi ctan.mines-albi.fr \
distrib-coffee.ipsl.jussieu.fr distrib-coffee.ipsl.jussieu.fr \
ftp.inria.fr ftp.oleane.net mirrors.ircam.fr \
ftp.fernuni-hagen.de ftp.fu-berlin.de ftp.gwdg.de \
ftp.join.uni-muenster.de \
ftp.mpi-sb.mpg.de ftp.tu-chemnitz.de ftp.uni-erlangen.de \
sunsite.informatik.rwth-aachen.de ftp.cc.uoc.gr ftp.ntua.gr \
ftp.uoi.gr ftp.sztaki.hu ftp.heanet.ie \
ftp.heanet.ie ftp.uniRoma2.it ftp.fagskolen.gjovik.no \
ftp.fagskolen.gjovik.no ftp.gust.org.pl ftp.tpnet.pl \
mirror.icis.pcz.pl ftp.piotrkosoft.net \
piotrkosoft.net sunsite.icm.edu.pl ftp.di.uminho.pt \
ftp.eq.uc.pt ftp.ist.utl.pt neacm.fe.up.pt ftp.roedu.net \
ftp.chg.ru ftp.vsu.ru mirror.macomnet.net tex.ihep.su \
ftp.gui.uva.es ftp.rediris.es ftp.udc.es mirror.switch.ch \
ftp.cstug.cz ftp.cvut.cz ftp.ntg.nl www.cs.ruu.nl \
ftp.snt.utwente.nl anorien.csc.warwick.ac.uk \
anorien.csc.warwick.ac.uk mirror.ox.ac.uk

Chiamate il file contenente il comando con il nome di mirtest.sh e lanciatelo come root da terminale con l’istruzione: sudo ./mirtest.sh, ecco fatto.

Risultato

Anche in questo caso l’Italia non brilla, con un solo server ufficiale sito a Roma (punteggio 413), ma sarete senz’altro curiosi di conoscere il vincitore:

The winner is: ftp.snt.utwente.nl !!!

Il server ha ottenuto un punteggio di 165.
Fate anche voi la prova riportando qui un commento con il vostro vincitore.
Alla prossima! e buona gara.

Inserito da: robitex | Novembre 2, 2009

Simmetria e spazio carta

Villette a schiera in AutoCAD

Ammettiamo che vi stiate occupando del disegno di una struttura simmetrica (semplice o multipla), come per esempio una villetta bifamigliare.

In teoria basta disegnare la metà dell’oggetto per definire tutto l’insieme, ma è necessario fornire disegni completi pertanto daremo un bel comando mirror per specchiare sull’asse di simmetria la parte opposta.

La soluzione va benissimo ma comporta un problema: in caso di modifiche occorre procedere di nuovo alla specchiatura, cosa che può essere piuttosto noiosa specie se sono richieste modifiche frequenti e se magari gli oggetti simmetrici si ripetono.

Nel nosto caso di riferimento, la pianta è composta da una parte sinistra ‘A’ ed una parte destra simmetrica ‘B’. Il disegno finale avrà schema AB. Se invece ci sono ripetizioni tipo ABABAB, allora gestire il disegno può diventare scomodo.

Soluzione spazio carta

Sappiamo come fare a risolvere con lo spazio carta quetso problema? Certo basta seguire questa semplice procedura che porterà il disegno nello spazio modello da così:

Model Space symetric object

Model Space symmetric object

a così nello spazio carta.

Final result in paper space

Final result in paper space

La procedura

Premessa: parleremo del caso con simmetria rispetto ad un asse parallelo ad Y con una versione 2004 di AutoCAD (segnalatemi eventuali problemi con le versioni più recenti).
Disegnamo nello spazio modello solamente la porzione A come per esempio quello della figura sopra e passiamo ad un layout dello spazio carta.
Creiamo una viewport che rappresenti nella scala voluta la parte A, e facciamone una copia accanto. Abbiamo adesso due viewport che rappresentano la stessa parte A.

Accediamo al menù Visualizza->Vista con nome… per attivare il dialogo corrispondente. Scegliamo come vista corrente “Basso” e premiamo il pulsante accanto “Imposta corrente”. Adesso diamo l’OK ed alla chiusura del dialogo selezioniamo la viewport di destra.

AutoCAD view dialog

AutoCAD view dialog

Non ci rimane che risettare i parametri della viewport specchio come scala ed inquadramento, e spostarla in modo da far corrispondere le due parti A e B.
Se volete potete cambiare colore al bordo della viewport per individuare meglio quella della parte destra da quella sinistra.

Difetti

Naturalmente una singola modifica nel modello si ripeterà allo stesso modo in tutte le altre porzioni del disegno che siano traslate o simmetriche alla porzione base.
Il risultato è ottimo, ma per la mia esperienza gestire in questo modo la simmetria comporta comunque degli svantaggi.

Il principale è senz’altro quello dovuto all’aumentata complessità dei layout, consiglio quindi di applicare il metodo comunque per un vostro disegno in modo che possiate valutarne l’efficienza.

Un secondo svantaggio è che non è possibile quotare in modo associativo nello spazio carta per i punti di quota appartenenti a diverse viewport, e quindi si perde il vantaggio eventuale di utilizzare un solo stile di quota per tutti gli oggetti dei layout (come vi segnalavo in questo post).

Dimenticavo…

Se l’asse di simmetria non è parallelo all’asse Y, potete sempre inserire il vostro disegno come un xrif ruotato in un altro, dove comporre i layout.
Scaricate pure il PDF di esempio, pesa solo 10 KB cliccando quì Drawing test in pdf format o sull’immagine seguente:

Pdf Example drawiong test

Pdf Example drawing test

Bye.

Inserito da: robitex | Ottobre 30, 2009

Il triangolo di Sierpiński

Il disegno della ricorsione

Visualizzare la ricorsione è l’idea di questo post. E la figura ricorsiva più semplice da disegnare mi sembra proprio il triangolo di Sierpiński. Dopo qualche notizia essenziale sul software che userò, passeremo al codice…

Sierpinski Triangle

Sierpinski Triangle of 6 level (click to download the pdf file)

Il linguaggio grafico di Asymptote

Per le nostre sperimentazioni useremo un software chiamato Asymptote, che consiste in un linguaggio di alto livello derivato dal METAPOST, piuttosto espressivo, simile a C++ e Java, quindi fortemente tipizzato.

Si possono instanziare i classici tipi numerici come int o real, e produrne di nuovi per mezzo del costrutto struct.

Infine, occorre terminare le istruzioni con il punto e virgola, utilizzare le parentesi graffe per definire i blocchi di codice, e produrre i commenti nel formato C++, ma vediamo subito un esempio (supporremo che una versione di Asymptote sia installata sul vostro sistema Windows, Linux o Mac OS che sia, magari tramite la TeX Live 2009).

Per disegnare una spezzata scrivete in un file di testo con estensione .asy il seguente codice, dove le coordinate sono separate da un doppio trattino che significa come in molti altri linguaggi del mondo LaTeX, una linea retta:

draw((0,0)--(2.5,2.5)--(5,0.5)--(7.5,5));

Poi in una finestra di console, date il comando di compilazione: asy -f pdf nomefile.asy. Al termine dell’elaborazione verrà rilasciato un file pdf contenente il risultato grafico desiderato.

Qualcosa di più complesso

Cominciamo a disegnare quello che sarà il triangolo di livello 0, utilizzando il tipo pair ovvero il tipo che in Asymptote corrisponde ad una coppia di numeri reali:

// triangle line length
real ell = 100;

// level 0 triangle:
pair p1 = (0,0);
pair p2 = (ell,0);
pair p3 = (ell/2,sqrt(3)*ell/2);
draw(p1--p2--p3--cycle);

Il termine cycle specifica che il percorso da disegnare sarà chiuso e corrisponde di fatto al primo punto p1.

Sierpiński

Il triangolo del matematico polacco venne da lui elaborato nel 1915, quando i sovietici tentavano di impossessarsi del cuore di quel popolo.

Disegnato un triangolo (che supporremo equilatero) detto di livello 0, si disegna il triangolo i cui vertici sono i punti di mezzo dei lati del triangolo principale, poi si applica ricorsivamente lo stesso procedimento ai tre sotto triangoli nord, sud-est e sud-ovest.

La struttura è un frattale in quanto è autosomigliante. Una semplice osservazione ci dice che man mano che si scende di livello le lunghezze dei lati dei triangoli si dimezzano, per cui se l_0 è la misura del lato del triangolo del livello 0, quella del lato a livello n sarà:

\displaystyle l_n = \frac{l_0}{2^n}.

Il numero dei triangoli t in funzione del livello v si ottiene considerando che scendendo di un livello il loro numero cresce di 3^v-1. In formule:

\displaystyle t = 1 + \sum_{i=1}^v 3^{i-1}

Per esempio al livello 5 i triangoli disegnati sono 122, ma al 10° salgono a 29.525 ed al 14° sono ben 2.391.485.

Il codice (non ottimizzato)

Per terminare i cicli ricorsivi altrimenti infiniti, è possibile utilizzare un criterio grafico: se lo spessore di tracciamento delle linee è tale che i triangoli dei livelli ulteriori risultano coperti, è inutile proseguire con il disegno.

La funzione ricorsiva chiamata sierpinski() prende i tre punti vertici del triangolo ed effettua immediatamente il test seguente (s è lo spessore del tratto ed l la lunghezza del lato del triangolo):

\displaystyle \frac{s}{2}\geq \frac{l}{2\sqrt{3}}

Se il test è falso significa che possiamo procedere al disegno del sotto-triangolo con i vertici nei punti di mezzo dei lati del triangolo principale, ed incrementare l’intero che conterrà alla fine il numero totale dei triangoli disegnati.

Il passo finale è lanciare ricorsivamente tre volte la funzione stessa sui sotto-triangoli del livello successivo.

Il codice non è ottimizzato perché in realtà non serve calcolare la distanza tra due punti per ottenere la lunghezza del lato del triangolo del livello attuale perché è ottenibile semplicemente dimezzando quella corrispondente al livello precedente.

Ecco il listato:

//
// Sierpinsky triangle: draw it with a recursive function
// Copyright (c) 2009 Roberto Giacomelli
// Term of licence see: http://robitex.wordpress.com/legalese/
//

// var setup
int n = 1;
real l0 = 100;
real s = 1.0;

// set the linewidth
defaultpen(s);

// main triangle
pair p1 = (0,0);
pair p2 = (l0,0);
pair p3 = (l0/2,sqrt(3)*l0/2);
draw(p1--p2--p3--cycle);

// function med() return the midpoint
// of the line ab
pair med(pair a, pair b){
return ((a.x+b.x)/2 , (a.y+b.y)/2);
}

// function dist() computes the length
// of line ab
real dist(pair a, pair b){
return sqrt((a.x-b.x)^2+(a.y-b.y)^2);
}

// main recursive function
void sierpinski(pair a, pair b, pair c){
// check graphic stop condition
if ( s<= dist(a,b)/sqrt(3) ){return;}

// draw subtriangle of the level
pair am = med(b,c);
pair bm = med(a,c);
pair cm = med(a,b);
draw(am--bm--cm--cycle);
++n;

//well, and now recursive running
// sublevel south east triangle
sierpinski(a,cm,bm);
// sublevel south west triangle
sierpinski(cm,b,am);
// sublevel north triangle
sierpinski(c,bm,am);
}
// draw the Sierpinski figure
sierpinski(p1,p2,p3);

// write on console the number
// of drawed triangles
write(n);

Scarica l’esempio in pdf : Sierpinski Triangle Figure
Alla prossima!

Inserito da: robitex | Ottobre 29, 2009

Cucinare tabelle numeriche con verbatim

Impaginare lunghissime tabelle numeriche? Impossibile, ma…

Alcuni programmi forniscono in output un file in formato rtf, contenenti lunghissime tabelle numeriche che arrivano a centinaia di pagine. La soluzione più semplice per stampare questo particolare tipo di documento è elaborarlo con MS Word o Writer di OpenOffice.org.

Se tuttavia il numero delle pagine potesse essere fortemente ridotto con semplici accorgimenti d’impaginazione si incorrerebbe immediatamente in alcuni problemi nel metterli in pratica.

Per loro natura i word processor devono visualizzare a schermo il risultato dell’impaginazione quindi se devono occuparsi d’impaginare all’istante un’enorme tabella numerica con layout a più colonne per pagina, magari anche diverso per le pagine dispari e per quelle pari, cadono rendendo di fatto impossibile perseguire il proprio obiettivo.

E qui che LaTeX entra in scena, essendo appunto un compositore di testi asincrono, basta copiare l’enorme tabella in un foglio di calcolo, aggiungere una colonna con i due \\ di fine riga, esportare il tutto nel formato CSV con il carattere & come simbolo di separazione tra i campi, ed aggiungere i comandi LaTeX necessari in un veloce file di testo che darà il file pdf finale.

Ma, vi voglio descrivere una seconda procedura che ho messo a punto or ora: si tratta di esportare la tabella come se fosse testo normale, con l’incolonnamento reso da caratteri spazio che compensano la diversa lunghezza del testo nelle celle, per poi comporre il tutto con un font monospaziato tramite l’ambiente verbatim.

La procedura è più semplice della precedente, anche se si perde la possibilità automatica di ripetere la prima riga di descrizione ad ogni cambio di colonna.

Occorrente

Procedimento

Rilassatevi un po’, magari al pensiero di un buon caffè che non avreste potuto gustare nella necessità di stampare ed impaginare un documento di 650 pagine fronte retro.

Dunque, nel quieto clima autunnale, aprite il file sorgente con la megatabella, in OpenOffice.org (oppure in Word), selezionate la tabella come sapete fare voi e copiatela negli appunti (CTRL+C).

Aprite anche una sessione di Calc, il foglio di calcolo di OpenOffice.org, e date un comando Incolla speciale… (CTRL+Maiusc+V), scegliendo l’opzione “Testo non formattato”.

Special Paste in OpenOffice.org Calc

Incolla speciale in OpenOffice.org Calc

Nel dialogo “Importazione testo…”, selezionate la prima colonna e, tenendo premuto il tasto Shift, selezionate anche l’ultima. In questo modo tutte le colonne saranno selezionate. Assegnatele il tipo Testo e date l’ok.

In questo modo si evita il problema del punto decimale che viene interpretato come separatore di un valore temporale (ore.minuti anziché parteintera.partedecimale), ma se la vostra tabella non comporta questo problema, fate pure direttamente il CTRL+V in Calc.

Import taxt dialog...

Il dialogo Importa testo

A questo punto salvate il file e subito dopo date un “Salva con nome…” per esportarlo in CSV (Comma Separated Values). Scegliete infatti tale formato nel dialogo e spuntate l’opzione “Modifica impostazioni filtro” che appare se appunto selezionate il formato di salvataggio CSV.

Save dialog

State per salvare un nuovo file...

Eventualmente, scegliete l’opzione “Mantiene il formato corrente” se Calc ve lo chiedesse in alternativa a “Salva in formato ODF”, premendo il corrispondente pulsante, e nell’ultimo dialogo attivate la miracolosa opzione “Ampiezza colonna fissa”

Last step

Ultimo passo per la creazione del file

Avete appena prodotto il file di testo giustamente incolonnato con caratteri spazio pronto per essere composto con LaTeX.

Se il risultato non fosse perfetto e di vostro gradimento, ritornate a Calc ed aggiustate la larghezza delle colonne per riesportate il tutto, infatti il testo monospaziato a tabella è ottenuto tenendo conto della larghezza delle colonne del foglio di calcolo, e questa è l’unica eventuale scocciaturina.

Il risultato aperto con l'editor Scite

Il risultato aperto con l'editor Scite

Ultimo passo: cottura della tabella

Aggiunto un \begin{verbatim} come prima riga del file testo esportato e un \end{verbatim} come ultima riga, scrivete in un sorgente .tex il codice seguente (be è solo un esempio…), ed a questo punto, mettete a cuocere il file a fuoco lento con pdflatex (lento si fa per dire naturalmente).

\documentclass[a4paper]{article}
% Seleziona un font monospaziato adatto
\usepackage{inconsolata}

% setta il margine di pagina
\usepackage[margin=10mm]{geometry}

% elimina testatine e piè di pagina
\pagestyle{empty}

\begin{document}
% riduzione dimensione del font
\footnotesize
% impaginazione standard su due colonne
\twocolumn

% inserisce il contenuto del file CSV
\input{carichi}
\end{document}

Vi troverete con il pdf finale pronto per essere servito (intanto ecco il pdf finale che ho ottenuto per illustrarvi i vari passaggi condito a dovere, scaricatelo è un esempio di 9,8 KB!).

Buon Appetito!

Inserito da: robitex | Ottobre 22, 2009

La tabellina pitagorica con PGF

Recentemente un utente del forum del GuIT chiedeva lumi per la composizione in LaTeX di una tabella relativa alla tabellina pitagorica.

Ho provato a fornirgli una riposta fino a che i guru di TeX hanno risolto, ma mi rimaneva da realizzare un idea: disegnare la tabella con il pacchetto grafico PGF.

La tabellina pitagorica compilata in LaTeX con PGF

La tabellina pitagorica compilata in LaTeX con PGF

Disegno della griglia

Per disegnare la griglia della tabella pitagorica utilizziamo il comando \draw specificando un quadrato di 10 unità di lato (se non si specificano unità PGF intenderà i centimetri), ecco il comando:

\draw (0,0) grid (10,10);

Riempimento della tabella

Per inserire i numeri nelle celle, risultato del prodotto tra il numero della colonna per quello della riga, basta scrivere due cicli \foreach; nidificati che eseguono il disegno di un nodo al cui centro è composto il testo del numero.

Abbiamo quindi due variabili \x ed \y. Al primo ciclo entrambe avranno valore 1 pertanto per individuare il centro del quadratino occorre dare molto comodamente l’opzione shift di (-0.5,-0.5) che applicate al punto (1,1) fornirà appunto le coordinate (0.5,0.50) ovvero il centro della prima casellina.

Ho copiato, questo si, il codice TeX per calcolare il risultato dell’espressione x * (11-y) che da il valore del prodotto in tabellina, poiché PGF risolve eventuali espressioni solo se si tratta di coordinate mentre per il testo da associare al nodo non effettua alcun parsing:

\foreach \x in {1,2,3,...,10}
\foreach \y in {1,2,3,...,10}
\draw[shift={(-.5,-.5)}] (\x ,\y) node
{\number\numexpr\x*(11-\y)\relax};

Mettendo insieme il codice ecco il primo risultato che da la tabellina pitagorica con griglia di 1cm x 1cm:

% copiare ed incollare questo codice in un file
% testuale con estensione .tex, poi compilarlo con pdflatex
\documentclass[a4paper]{article}

\usepackage{tikz}
\pagestyle{empty}

\begin{document}

\begin{tikzpicture}
% grid definition
\draw (0,0) grid (10,10);

% fill numbers
\foreach \x in {1,2,3,...,10}
\foreach \y in {1,2,3,...,10}
\draw[shift={(-.5,-.5)}] (\x ,\y) node
{\number\numexpr\x*(11-\y)\relax};
\end{tikzpicture}

\end{document}

Completando e raffinando un po’ il codice, si ottiene il seguente listato, dove la cosa più importante è l’aggiunta dell’opzione scale all’ambiente tikzpicture che scala tutto tranne che il testo assegnato agli oggetti nodo, pertanto modificando un unico parametro si può regolare le dimensione della tabella.

% copiare ed incollare questo codice in un file
% testuale con estensione .tex, poi compilarlo con pdflatex
\documentclass[a4paper]{article}

\usepackage{tikz}
\pagestyle{empty}

\begin{document}

\begin{tikzpicture}[scale=0.675]
% grid definition
\draw (-1,0) grid (10,10);
\draw (0,10) grid (10,11);
\draw[line width=1pt, color=blue] (0,0) rectangle (10,10);

% fill numbers
\foreach \x in {1,2,3,...,10}
\foreach \y in {1,2,3,...,10}
\draw[shift={(-.5,-.5)}] (\x ,\y) node
{\number\numexpr\x*(11-\y)\relax};

% fill first row
\foreach \x in {1,2,3,...,10}
\draw[shift={(-.5,-.5)}] (\x , 11) node {\x};

% fill first column
\foreach \y in {1,2,3,...,10}
\draw[shift={(-.5,-.5)}] (0, 11-\y) node {\y};
\end{tikzpicture}

\end{document}

Il risultato è visibile nell’immagine iniziale, mentre per ottenere il risultato finale in formato PDF scontornato basta fare un click ;-) .

Alla prossima.

Inserito da: robitex | Ottobre 19, 2009

GuIT meeting 2009

Un convegno ancora più TeXnico

L’incontro annuale aperto a tutti del GuIT (Gruppo utilizzatori italiani di TeX) si è appena svolto nella solita cornice dell’Aula Magna della Scuola Sant’Anna a Pisa.

L’impressione che ne ho tratto è che quest’anno i contenuti sono stati ancora più tecnici, o meglio ancora più TeXnici per dirla con Donald Knuth. Mi ha colpito in particolare l’intervento di Luigi Scarso riguardante un estensione di LuaTeX chiamata lunatic, che permette di far girare codice Python all’interno di LuaTeX su una piattaforma Linux. Tecnologia piuttosto sofisticata che dimostra come il motore TeX stia entrando in una nuova fase specie quando arriverà LaTeX3 e la versione stabile di LuaTeX stessa (nella foto Luigi Scarso svolge la sua presentazione).

Parla Luigi Scarso

Parla Luigi Scarso

Naturalmente oltre agli argomenti specifici su LaTeX il meeting è un occasione assai piacevole per ritrovarsi, scherzare e scambiarsi opinioni con i guru del GuIT come il Prof. Enrico Gregorio e l’attivissimo Prof. Claudio Beccari. Nella foto seguente mi vedete accanto ad Agostino De Marco esperto utilizzatore delle tecnologie LaTeX relative alla grafica vettoriale nonchè relatore al convegno (grande ago).

Io ed Agostino De Marco

Io ed Agostino De Marco

Gli interventi in rete

La fondamentale foto di gruppo dei partecipanti con le altre immagini è già disponibile sul sito GuIT.

Tutti caduti nella rete invece gli interventi filmati da Kabeh Bazargan di River Valley Technologies con le sue diavolerie tecnologiche (il convegno è andato perfino in diretta streaming) e sono disponibili a questo link.

Gli articoli dei lavori presentati al meeting li trovate anche in ArsTeXnica n.8 la rivista semestrale del GuIT, naturalmente composta con LaTeX (per leggerla subito iscrivetevi al GuIT).

Per dirla in un unica frase “qualità elevata della conoscenza”.
O no…
Ciao.

Articoli precedenti »

Categorie