<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Flying memes</title>
	<atom:link href="http://sandropaganotti.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://sandropaganotti.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Wed, 03 Mar 2010 22:40:36 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Language switch</title>
		<link>http://sandropaganotti.com/2010/03/03/language-switch/</link>
		<comments>http://sandropaganotti.com/2010/03/03/language-switch/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 22:40:36 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Annunci]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=321</guid>
		<description><![CDATA[After a lot of reasonings I come to the decision to switch the language of this blog from italian to english, this change is going to cost me more time every time I decide to post something but it will also work as a training center for my foreign language skills. Plus it is probable [...]]]></description>
			<content:encoded><![CDATA[<p>After a lot of reasonings I come to the decision to switch the language of this blog from italian to english, this change is going to cost me more time every time I decide to post something but it will also work as a training center for my foreign language skills. Plus it is probable that most (if not all) of my current followers will keep reading and understand english posts while new non-italian readers may be attracted due to this change.</p>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2010/03/03/language-switch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Abacus, Pierre Hérigone e la mnemotecnica</title>
		<link>http://sandropaganotti.com/2010/02/28/abacus-pierre-herigone-e-la-mnemotecnica/</link>
		<comments>http://sandropaganotti.com/2010/02/28/abacus-pierre-herigone-e-la-mnemotecnica/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 16:31:04 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Librerie]]></category>
		<category><![CDATA[abacus]]></category>
		<category><![CDATA[Hérigone]]></category>
		<category><![CDATA[mnemotecnica]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=306</guid>
		<description><![CDATA[Ho recentemente acquistato un libro che mi stà regalando una serie di spunti per interessanti approfondimenti e delle simpatiche occasioni per scrivere due righe di codice. Il libro in questione si chiama &#8220;Enigmi e giochi matematici&#8221; di Martin Gardner e raccoglie gli articoli che lo stesso Martin pubblicò negli anni sulla rivista Scientific American.

Il capitolo [...]]]></description>
			<content:encoded><![CDATA[<p>Ho recentemente acquistato un libro che mi stà regalando una serie di spunti per interessanti approfondimenti e delle simpatiche occasioni per scrivere due righe di codice. Il libro in questione si chiama &#8220;<a href="http://www.ibs.it/code/9788817127479/gardner-martin/enigmi-giochi-matematici.html" target="_blank">Enigmi e giochi matematici</a>&#8221; di <a href="http://it.wikipedia.org/wiki/Martin_Gardner" target="_blank">Martin Gardner</a> e raccoglie gli articoli che lo stesso Martin pubblicò negli anni sulla rivista Scientific American.</p>
<p><span id="more-306"></span></p>
<p>Il capitolo numero 11 tratta di mnemotecnica, la disciplina che studia il modo di memorizzare lunghe sequenze di numeri, e tratta del metodo di <a href="http://en.wikipedia.org/wiki/Herigone%27s_mnemonic_system" target="_blank">Pierre Hérigone</a>, che può essere riassunto nel seguente modo:</p>
<ol>
<li>Associa le cifre del numero che vuoi memorizzare a delle consonanti secondo <a href="http://it.wikipedia.org/wiki/Mnemotecnica#La_conversione_fonetica" target="_blank">una tabella nota</a>; ad esempio la temperatura di ebollizione del mercurio, 357°C, diverrebbe mlk;</li>
<li>Trova una parola che contenga quelle consonanti in quell&#8217;ordine (senza altre &#8216;consonanti di disturbo in mezzo&#8217;); ad esempio per mlk andrebbe benissimo milk, mentre non andrebbe bene multik;</li>
<li>Associa la parola appena trovata ad una frase che in qualche modo leghi con il significato originario della cifra, possibilmente in modo che la frase risultante contenga uno stimolo visuale; ad esempio si può immaginare un allevatore stupito dal fatto che le sue mucche producano mercurio invece che latte.</li>
<li>Se la cifra dovesse essere molto lunga utilizza una sequenza di più parole seguendo lo schema appena descritto.</li>
</ol>
<p>Nel tempo libero stò cercando di trasporre questi quattro semplici passaggi all&#8217;interno di una gemma: <a href="http://rubygems.org/gems/abacus" target="_blank">abacus</a>, della quale ho rilasciato giusto oggi la versione 0.0.1; vediamo come si usa:</p>
<pre><code class="ruby">&gt;&gt; require 'abacus'
=&gt; true
&gt;&gt; include Abacus
=&gt; Object
&gt;&gt; number = HerigoneNumber.find_by_number(357)
=&gt; #&lt;Abacus::HerigoneNumber id: 19081, system: "default", number: 357&gt;
&gt;&gt; number.article_keys.map{|article_key| article_key.the_key}
=&gt; ["hemlock", "milk", "milky"]
</code></pre>
<p>Per poter funzionare Abacus utilizza un database sqllite che crea all&#8217;interno della cartella home dell&#8217;utente (il percorso in realtà è configurabile, ma per questi dettagli vi rimando <a href="http://github.com/sandropaganotti/Abacus/blob/master/README.markdown" target="_blank">alle note di installazione su github</a>) e nel quale struttura il/i dizionari di riferimento.</p>
<p>Abacus implementa un parser (molto base ad oggi) <a href="http://xdxf.sourceforge.net/" target="_blank">XDXF</a>, un formato open per la memorizzazione di dizionari: esistono già parecchie opere convertite più o meno bene in questo formato che possono essere <a href="http://xdxf.revdanica.com/down/" target="_blank">scaricate gratuitamente</a>, io ad esempio ho utilizzato <a href="http://downloads.sourceforge.net/xdxf/comn_sdict05_eng_eng_main.tar.bz2" target="_blank">questo dizionario base di inglese</a>:</p>
<pre><code># da shell:
sudo gem install abacus
wget http://downloads.sourceforge.net/xdxf/comn_sdict05_eng_eng_main.tar.bz2
tar -xjvf comn_sdict05_eng_eng_main.tar.bz2
abacus db:create
abacus db:xdxf:import  eng_eng_main/dict.xdxf
abacus db:herigone:generate
</code></pre>
<p>La sfida più interessante di questo piccolo progetto è stata mantenere delle performances adeguate durante la sessione di traduzione numero -&gt; parola, per fare questo in fase di import (con il comando db:herigone:generate) la gemma traduce ogni lemma del dizionario nel suo corrispettivo numerico rendendo la fase di ricerca una semplice SELECT su di un campo indicizzato.</p>
<p>In futuro vorrei estendere questo piccolo progetto aggiungendo due funzionalità di aggregazione semantica: in caso di sequenze di cifre lunghe mi piacerebbe infatti includere un generatore di linguaggio naturale con l&#8217;obiettivo creare una frase che almento nell&#8217;apparenza manifesti una certa correttezza (sarebbe bellissimo tradurre le prima 1000 cifre del PI in uno strampalato poema no?). Sarebbe inoltre interessante utilizzare <a href="http://wordnet.princeton.edu/" target="_blank">wordnet</a> per ridurre la variabilità semantica delle singole parole trovate a quanto di più vicino ad una parola che serva da &#8216;rappresentante logico&#8217; per la cifra in ingresso (ad esempio per 357 il rappresentante logico sarebbe &#8216;mercurio&#8217;).</p>
<p>Nel frattempo, per chiunque fosse interessato, i sorgenti della gemma sono disponibili <a href="http://github.com/sandropaganotti/Abacus" target="_blank">sul mio account di GitHub</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2010/02/28/abacus-pierre-herigone-e-la-mnemotecnica/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby linguistic, Wordnet e LinkParser su Snow Leopard</title>
		<link>http://sandropaganotti.com/2010/02/03/ruby-linguistic-wordnet-e-linkparser-su-snow-leopard/</link>
		<comments>http://sandropaganotti.com/2010/02/03/ruby-linguistic-wordnet-e-linkparser-su-snow-leopard/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 22:46:09 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Librerie]]></category>
		<category><![CDATA[linguistics]]></category>
		<category><![CDATA[link parser]]></category>
		<category><![CDATA[link-grammar]]></category>
		<category><![CDATA[natural language generator]]></category>
		<category><![CDATA[natural language parser]]></category>
		<category><![CDATA[wordnet]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=292</guid>
		<description><![CDATA[Update, 05/02/10: Ecco il link alle slide della presentazione! Ringrazio tutti i partecipanti alla bellissima serata!
Il prossimo giovedì (4 febbraio 2010) terrò un Lightning Talk al Ruby Social Club su alcuni strumenti interessanti che orbitano attorno al concetto di Natural Language Generation/Parsing. In particolare vedremo due librerie che consentono di interfacciarsi con  WordNet e Link-Grammar.
Non [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Update, 05/02/10: </strong>Ecco il <a title="Natural Languages and Ruby" href="http://prezi.com/hdlhowymuge2/" target="_blank">link alle slide della presentazione</a>! Ringrazio tutti i partecipanti alla bellissima serata!</p>
<p>Il prossimo giovedì (4 febbraio 2010) terrò un Lightning Talk al <a href="http://therubymine.com/2010/01/25/primo-ruby-social-club-del-2010/" target="_blank">Ruby Social Club</a> su alcuni strumenti interessanti che orbitano attorno al concetto di Natural Language Generation/Parsing. In particolare vedremo due librerie che consentono di interfacciarsi con  <a href="http://wordnet.princeton.edu/" target="_blank">WordNet</a> e <a href="http://www.link.cs.cmu.edu/link/" target="_blank">Link-Grammar</a>.</p>
<p>Non voglio svelare nulla dello speech in questo post (anche se sicuramente venerdi farò un update allegando le slide della presentazione) ma solamente fornire a coloro che lo ritengano utile le istruzioni su come installare tali librerie sul proprio Mac.</p>
<p><span id="more-292"></span></p>
<h3>WordNet</h3>
<p><strong>Update, 05/02/10:</strong> mi segnalano <a href="http://github.com/roja/words" target="_blank">Words</a>, un wrapper analogo a quello che presento nelle prossime righe ma decisamente più aggiornato, it worths a look.</p>
<p>Partiamo da WordNet; la prima cosa da fare è installare la gemma BerkleyDB, il che comporta in primis l&#8217;installazione dello stesso BDB, quindi il primo comando è:</p>
<pre><code>sudo port install db47
</code></pre>
<p>Fatto questo <a href="ftp://ftp.eenet.ee/pub/FreeBSD/distfiles/ruby/bdb-0.6.4.tar.gz" target="_blank">scarichiamo la versione vecchia della gemma BDB</a> (<a href="http://github.com/mattbauer/bdb" target="_blank">quella su GitHub</a> non va bene, hanno cambiato i nomi alle costanti), decomprimiamola e modifichiamo la chiamata alla funzione &#8216;have_library&#8217; nel file src/extconf.rb (riga 72 e riga 79) come segue:</p>
<pre><code>have_library("db-#{with_ver}", db_version)
</code></pre>
<p>lanciamo infine la compilazione e l&#8217;installazione della libreria con i comandi (da eseguire all&#8217;interno della cartella di BDB):</p>
<pre><code>sudo env ARCHFLAGS="-arch x86_64" ruby extconf.rb  -- --with-db-include=/opt/local/include/db46 --with-db-lib=/opt/local/lib/db46 --with-db-version=4.6
make
sudo make install
</code></pre>
<p>Ok, ora installiamo la gemma di wordnet:</p>
<pre><code>sudo gem install wordnet
</code></pre>
<p>modifichiamo quindi il file &#8216;lib/wordnet/lexicon.rb&#8217; all&#8217;interno della gemma impostando alla riga 68 un path assoluto come ad esempio:</p>
<pre><code>DEFAULT_DB_ENV = File::join( '/Library/Ruby/Gems/1.8/gems/wordnet-0.0.5/ruby-wordnet' )
</code></pre>
<p>A questo punto non ci resta che  scaricare e convertire il database di wordnet nel formato BDB richiesto dalla gemma, per fare questo recuperiamo <a href="http://wordnetcode.princeton.edu/3.0/WordNet-3.0.tar.gz" target="_blank">l&#8217;ultima versione di wordnet disponibile</a> e decomprimiamola. Poi eseguiamo da linea di comando lo script presente nella cartella della gemma &#8216;convertdb.db&#8217; e, quando ci viene chiesto, inseriamo il percorso assoluto alla cartella &#8216;dict&#8217; all&#8217;interno dell&#8217;archivio di wordnet appena decompresso.<br />
Testiamo il funzionamento del tutto eseguendo questo semplice script:</p>
<pre><code class="ruby">require 'rubygems'
require 'wordnet'
include WordNet::Constants

lex     = WordNet::Lexicon::new
origins = lex.lookup_synsets( "house", Noun )
puts "#{(o=origins.first).words}: #{o.lex_info}"
[:meronyms,:hypernyms,:derivations,:hyponyms].each do |m|
  puts "#{m}: #{o.send(m).map{|s| s.words}.flatten.uniq.join(",")}"
end</code></pre>
<h3>Link Grammar</h3>
<p>Installiamo link grammar usando i MacPort:</p>
<pre><code>sudo port install link-grammar</code></pre>
<p>quindi <a href="http://deveiate.org/projects/Ruby-LinkParser" target="_blank">scarichiamo il sorgente della gemma</a> che fungerà da wrapper e decomprimiamolo in una cartella a nostro piacimento. Dall&#8217;interno di questa cartella compiliamo ed installiamo la gemma con questi comandi:</p>
<pre><code>ARCHFLAGS="-arch x86_64" rake --  --with-link-grammar-include=/opt/local/include/link-grammar --with-link-grammar-lib=/opt/local/lib
sudo rake install
</code></pre>
<p>Testiamo anche questa installazione eseguendo questo piccolo script:</p>
<pre><code class="ruby">require 'rubygems'
require 'linkparser'

dict = LinkParser::Dictionary.new('en')
sent = dict.parse( "People use Ruby for all kinds of nifty things." )

puts sent.subject
puts sent.verb
puts sent.object
</code></pre>
<h3>Linguistic</h3>
<p>Questa gemma funziona un pò da meta-wrapper raggruppando le funzionalità delle due gemme finora installate in un unico e omogeneo set di API. Installiamola con rubygems:</p>
<pre><code>sudo gem install linguistics</code></pre>
<p>quindi modifichiamo il file &#8216;lib/linguistics/en/linkparser.rb&#8217; all&#8217;interno della cartella dove risiede la gemma sistemando la riga 90 come segue:</p>
<pre><code>return @lp_dict ||= LinkParser::Dictionary.new('en', :verbosity =&gt; 0 )
</code></pre>
<p>Eseguiamo quindi un piccolo script di prova per sancirne la riuscita installazione:</p>
<pre><code class="ruby">require 'rubygems'
require 'linguistics'

Linguistics::use( :en )
frase = "the cat chased a snake"

puts &lt;&lt;-EOS
  Sogg:        #{frase.en.sentence.subject}
  Verbo:       #{frase.en.sentence.verb}
  Comp.ogg:    #{frase.en.sentence.object}
  Verbo (inf): #{frase.en.sentence.verb.en.infinitive}
EOS
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2010/02/03/ruby-linguistic-wordnet-e-linkparser-su-snow-leopard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Isocrono e Google Map API</title>
		<link>http://sandropaganotti.com/2010/01/18/isocrono-e-google-map-api/</link>
		<comments>http://sandropaganotti.com/2010/01/18/isocrono-e-google-map-api/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 22:23:02 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Algoritmi]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[Google Map]]></category>
		<category><![CDATA[isocrono]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=287</guid>
		<description><![CDATA[Un isocrono non è nient&#8217;altro che una curva che unisce su di una mappai punti che distano uno stesso intervallo temporale (a piedi, o con un mezzo di trasporto) da un punto dato. In questo articolo, che funge da approfondimento della homepage del progetto, vorrei entrare un pò nel merito del piccolo script da utilizzare [...]]]></description>
			<content:encoded><![CDATA[<p>Un <a href="http://it.wikipedia.org/wiki/Isoclina#Scienze_Sociali" target="_blank">isocrono</a> non è nient&#8217;altro che una curva che unisce su di una mappai punti che distano uno stesso intervallo temporale (a piedi, o con un mezzo di trasporto) da un punto dato. In questo articolo, che funge da approfondimento <a href="http://sandropaganotti.com/generate-an-isochrone-map-using-google-maps-api/" target="_blank">della homepage del progetto</a>, vorrei entrare un pò nel merito del piccolo script da utilizzare per calcolare un&#8217;approssimazione di isocrono usando le API di Google Maps.</p>
<p><span id="more-287"></span>Lo script si compone di tre parti, una (classica) funzione di inizializzazione,  una funzione che effettua il <a href="http://code.google.com/intl/it/apis/maps/documentation/services.html#Geocoding" target="_blank">GeoCoding</a> della località della quale si vuole calcolare l&#8217;isocrono e la funzione chiave, che cicla su ognuno dei raggi (il numero di raggi è impostabile, di default 10) della circonferenza costruita intorno a tale località e per ogni raggio si muove verso l&#8217;esterno misurando la distanza in minuti dal centro, quando trova un punto che sorpassa il tempo limite dato lo script mette un marker.</p>
<p>Lo script passa al raggio successivo quando rileva una misurazione che supera del 50% il tempo limite dato.</p>
<pre><code class="javascript">
    function crawlpoint(px,py,mins){
        var point      = new GPoint(px,py);
        var destpoint  = new GPoint(px + x,py + y);   

        directions.loadFromWaypoints(new Array(point.y + "," + point.x ,destpoint.y + "," + destpoint.x),{preserveViewport:true});
        x = x + (inc_x * Math.sin(start_s));
        y = y + (inc_y * Math.cos(start_s));
        m = m + 1;

        if (directions.getNumRoutes() &gt; 0){
            document.getElementById('txt1').value = 'y' + document.getElementById('txt1').value
            var curr_meas = directions.getDuration().seconds/60;
            if (prev_meas &lt;= mins &amp;&amp; curr_meas &gt; mins ){
                map.addOverlay(new GMarker(prev_dest,{title:'Distance: ' + directions.getDuration().html}));
                found     = 1;
            }else{
                prev_dest = destpoint;
                prev_meas = curr_meas;
            }

            if(curr_meas &gt; (mins + (mins * 0.4)) || (m &gt; 20 &amp;&amp; found ==1) || m &gt; 50){
                points.push(new GLatLng(prev_dest.y, prev_dest.x));
                start_s = start_s + slice;
                x = inc_x;
                y = inc_y;
                m = 0;
                found = 0;
                prev_meas = 0;
                curr_meas = 0;
                prev_dest = point;
                directions.clear();

                if(start_s &gt;= (2*Math.PI)){
                    start_s = 0;
                    $('#loader').hide();
                    clearInterval(intval);
                }
            }

        }else{
            document.getElementById('txt1').value = 'n' + document.getElementById('txt1').value
        }
    }
</code></pre>
<p>Possiamo spezzare la funzione in tre punti distinti, la prima parte invoca le <a href="http://code.google.com/intl/it/apis/maps/documentation/services.html#Directions" target="_blank">Directions API</a>, per calcolare la distanza tra il centro e un punto (destpoint) posizionato sul raggio attivo (il cui angolo è memorizzato in start_s, inizialmente a 0) ad una distanza espressa da due variabili x e y. Una volta calcolato il percorso x e y vengono incrementate in modo che al prossimo giro puntino ad un punto sullo stesso raggio un poco più avanti.</p>
<p>La seconda parte aggiunge un marker se tra la durata del percorso attuale supera per la prima volta il limite di tempo inserito.</p>
<p>La terza parte resetta tutti i contatori e avanza al raggio successivo se la misurazione temporale corrente eccede del 50% il tempo limite inserito o se sono state effettuate più di venti misurazioni con l&#8217;identificazione di un marker o più di 50 misurazioni.</p>
<p>Trovate il codice nella sua interezza sul mio account di <a href="http://github.com/sandropaganotti/isochrone-with-google-map" target="_blank">github</a>, potete inoltre testare il tutto su di una <a href="http://sandropaganotti.com/wp-content/goodies/demos/isochrone/index.html" target="_blank">pagina di demo</a>.</p>
<p>PS: credo che l&#8217;algoritmo sia altamente perfezionabile, ad esempio introducendo alcuni concetti di reinforcement learning per la ricerca degli zeri della funzione T(R(p1,p2)) &#8211; t dove T(R(p1,p2)) è il tempo di percorrenza del percorso tra p1 e p2 e t è il tempo limite dell&#8217;isocrono.</p>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2010/01/18/isocrono-e-google-map-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>QBox: uno slideshow in WebGL</title>
		<link>http://sandropaganotti.com/2010/01/05/qbox-uno-slideshow-in-webgl/</link>
		<comments>http://sandropaganotti.com/2010/01/05/qbox-uno-slideshow-in-webgl/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 15:52:26 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Algoritmi]]></category>
		<category><![CDATA[QBox]]></category>
		<category><![CDATA[Slideshow]]></category>
		<category><![CDATA[WebGL]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=274</guid>
		<description><![CDATA[Di ritorno da un bellissimo capodanno a Nantes ho deciso di spendere ancora qualche ora sul nuovo binding tra Javascript e OpenGL ES 2.0, formalmente noto col nome di WebGL; il risultato ha preso il nome di QBox, uno slideshow che recupera un certo numero di immagini mappandole su di un cubo rotante (le immagini [...]]]></description>
			<content:encoded><![CDATA[<p>Di ritorno da un bellissimo capodanno a <a href="http://maps.google.it/maps?q=nantes&amp;oe=utf-8&amp;client=firefox-a&amp;ie=UTF8&amp;hq=&amp;hnear=Nantes,+Loira+Atlantica,+Paesi+della+Loira,+Francia&amp;gl=it&amp;ei=Cl1DS5f9O42anwPfv9X6CQ&amp;ved=0CBMQ8gEwAA&amp;t=h&amp;z=11" target="_blank">Nantes</a> ho deciso di spendere ancora qualche ora sul nuovo binding tra Javascript e OpenGL ES 2.0, formalmente noto col nome di WebGL; il risultato ha preso il nome di QBox, uno slideshow che recupera un certo numero di immagini mappandole su di un cubo rotante (le immagini possono essere anche più di quattro, c&#8217;è un meccanismo di sostituzione automatico).</p>
<p><span id="more-274"></span>Non mi dilungo oltre ne nella descrizione ne nelle procedure di installazione in quanto è tutto specificato <a href="http://sandropaganotti.com/qbox-a-webgl-photo-slideshow-for-your-website/" target="_blank">sulla homepage del progetto</a> (c&#8217;è anche un <a href="http://www.youtube.com/watch?v=5ui-XBVChmE" target="_blank">video</a> e una <a href="http://sandropaganotti.com/wp-content/goodies/demos/qbox/" target="_blank">demo live</a> se il vostro browser supporta WebGL, testato con Webkit); vorrei invece spendere questo post nello spiegare un paio di funzioni che ho scritto e che potrebbero IMHO rivelarsi utili a qualche lettore, ecco la prima:</p>
<pre><code class="javascript">function createTextureFromCanvas(ctx, canvas_imagedata) {

    var pixels = new WebGLUnsignedByteArray(canvas_imagedata.data);
    var texture = ctx.createTexture();
    ctx.bindTexture(ctx.TEXTURE_2D, texture);
    ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_S, ctx.CLAMP_TO_EDGE);
    ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_T, ctx.CLAMP_TO_EDGE);
    ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.NEAREST);
    ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.NEAREST);
    ctx.pixelStorei(ctx.UNPACK_ALIGNMENT, 1);
    ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, canvas_imagedata.width, canvas_imagedata.height, 0, ctx.RGBA, ctx.UNSIGNED_BYTE, pixels);
    ctx.generateMipmap(ctx.TEXTURE_2D)
    ctx.bindTexture(ctx.TEXTURE_2D, null);

    return texture;
}
</code></pre>
<p>In questa funzione si concentra il cuore dello slideshow, non tanto dal punto di vista operativo, quanto di mio personale sforzo concettuale; il principale problema che ho incontrato nello sviluppo di questo script infatti riguardava la necessità di mappare immagini di dimensioni potenzialmente diverse su di un cubo (le cui facce devono essere tutte uguali). Ecco quindi il passaggio forzato attraverso dei canvas bidimensionali di appoggio, sui quali effettuare le operazioni di resize delle immagini prima di passarle come textures sul cubo. Questi canvas sono anche serviti per gestire i margini neri che venivano a crearsi naturalmente in quanto la proporzione tra le dimensioni delle fotografie non è sempre 1:1.</p>
<p>Ma una volta ottenuto questi canvas contenenti le immagini normalizzate come procedere per metterle su di una texture ? Dopo aver seguito senza successo <a href="http://gist.github.com/215896">un gist sul tema</a> mi sono imbattuto nel salvifico esempio &#8216;<a href="https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/demos/google/procedural-texture-test/index.html" target="_blank">Texture test</a>&#8216; che contiene una funzione che disegna 4 pixel su di una texture:</p>
<pre><code class="javascript">
function createCheckerboardTexture() {
    var pixels = new WebGLUnsignedByteArray([255, 255, 255,
                                             0,   0,   0,
                                             0,   0,   0,
                                             255, 255, 255]);
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    //  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    //  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 2, 2, 0, gl.RGB, gl.UNSIGNED_BYTE, pixels);
    return texture;
}
</code></pre>
<p>Da qui è stato facile; al posto che specificare i singoli bit dell&#8217;immagine ho passato nella variabile pixels il contenuto dei miei canvas di appoggio e, con un paio di altre modifiche sono riuscito ad ottenere l&#8217;effetto desiderato.</p>
<p>La seconda funzione di cui vorrei far menzione è invece quella che recupera un immagine e la mappa, centrata, su di un canvas 2d, per scrivere queste righe ho utilizzato il metodo drawImage del context 2D in un modo che non conoscevo (<a href="https://developer.mozilla.org/En/Canvas_tutorial/Using_images#Scaling" target="_blank">suggeritomi da qui</a>), cioè con 5 parametri:</p>
<ul>
<li>Canvas di destinazione;</li>
<li>Posizione x e y da cui disgnare l&#8217;immagine sul canvas di destinazione;</li>
<li>Dimensioni dell&#8217;immagine sul canvas di destinazione (width e height).</li>
</ul>
<p>Ecco la funzione, in ingresso riceve l&#8217;&lt;img&gt; da adattare al canvas:</p>
<pre><code class="javascript">function initTexture(e)
{
  var textureWidth  = 500;

  if($(e).width() &gt; $(e).height()){
     var magnitude = textureWidth/$(e).width();
  } else {
     var magnitude = textureWidth/$(e).height();
  }

  var new_width  = Math.floor($(e).width()*magnitude);
  var new_height = Math.floor($(e).height()*magnitude);
  var textureCanvas     = document.createElement("canvas");
  textureCanvas.width   = textureCanvas.height = textureWidth;
  var textureContext    = textureCanvas.getContext("2d");
  textureContext.drawImage(e,Math.floor((textureWidth-new_width)/2.0),Math.floor((textureWidth-new_height)/2.0),new_width,new_height); 

  return textureCanvas;
}</code></pre>
<p>Se la cosa vi interessa sappiate che tutto il progetto è, come al solito, <a href="http://github.com/sandropaganotti/QBox--a-WebGL-photo-slideshow" target="_blank">disponibile sul mio account di github</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2010/01/05/qbox-uno-slideshow-in-webgl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Streamlined e Rails 3.0</title>
		<link>http://sandropaganotti.com/2009/12/19/streamlined-e-rails-3-0/</link>
		<comments>http://sandropaganotti.com/2009/12/19/streamlined-e-rails-3-0/#comments</comments>
		<pubDate>Sat, 19 Dec 2009 14:06:12 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Annunci]]></category>
		<category><![CDATA[Rails 3.0]]></category>
		<category><![CDATA[Streamlined]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=256</guid>
		<description><![CDATA[Ammiro moltissimo Streamlined ed ho letto con dispiacere la notizia della sospensione del suo sviluppo; ho deciso quindi di imbarcarmi nell&#8217;opera di porting di questo framework con l&#8217;obiettivo di renderlo compatibile con Rails 3.0. La strada da percorrere è ancora lunga ma find&#8217;ora è disponibile su github una pre-alpha funzionante, almeno nelle sue features essenziali [...]]]></description>
			<content:encoded><![CDATA[<p>Ammiro moltissimo <a href="http://streamlinedframework.org/" target="_blank">Streamlined</a> ed ho letto con dispiacere la notizia della <a href="http://streamlinedframework.org/articles/2009/08/21/streamlined-end-of-life" target="_blank">sospensione del suo sviluppo</a>; ho deciso quindi di imbarcarmi nell&#8217;opera di porting di questo framework con l&#8217;obiettivo di renderlo compatibile con Rails 3.0. La strada da percorrere è ancora lunga ma find&#8217;ora è disponibile su <a href="http://github.com/sandropaganotti/streamlined" target="_blank">github</a> una pre-alpha funzionante, almeno nelle sue features essenziali (CRUD, listing e search).</p>
<p>Per ulteriori dettagli vi rimando al <a href="http://www.railsonwave.com/2009/12/19/streamlined-a-new-fork-for-rails-3-0" target="_blank">post su RailsOnWave contenente l&#8217;annuncio ufficiale</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2009/12/19/streamlined-e-rails-3-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby e Gosu: un multiplayer a schermo condiviso</title>
		<link>http://sandropaganotti.com/2009/12/08/ruby-e-gosu-un-multiplayer-a-schermo-condiviso/</link>
		<comments>http://sandropaganotti.com/2009/12/08/ruby-e-gosu-un-multiplayer-a-schermo-condiviso/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 20:21:42 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Algoritmi]]></category>
		<category><![CDATA[Librerie]]></category>
		<category><![CDATA[Gosu]]></category>
		<category><![CDATA[multiplayer]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=246</guid>
		<description><![CDATA[Tutto è nato da una bellissima presentazione che ho seguito ormai quasi un anno fa: si parla dell&#8217;Euruko 2009 in quel di Barcellona; lo speech in oggetto si intitolava &#8216;Fun with ruby (and without r***s). Program your own games with gosu&#8216; e trattava di una libreria per lo sviluppo di giochi scritta in Ruby chiamata [...]]]></description>
			<content:encoded><![CDATA[<p>Tutto è nato da una bellissima presentazione che ho seguito ormai quasi un anno fa: si parla dell&#8217;Euruko 2009 in quel di Barcellona; lo speech in oggetto si intitolava <a href="http://app.euruko2009.org/talks/9-fun-with-ruby-and-without-r-s-program-your-own-games-with-gosu" target="_blank">&#8216;Fun with ruby (and without r***s). Program your own games with gosu</a>&#8216; e trattava di una libreria per lo sviluppo di giochi scritta in Ruby chiamata <a href="http://code.google.com/p/gosu/" target="_blank">Gosu</a>.</p>
<p><span id="more-246"></span></p>
<p>Per tutta una serie di impegni/dimenticanze/ritardi/&#8230; non sono più riuscito ad avvicinarmi a Gosu anche se le sue potenzialità sembravano quantomeno interessanti; oggi approfittando del piovoso ponte lavorativo  mi sono cimentato nella stesura di  una piccolissima applicazione (non la si può nemmeno chiamare gioco) che gestisca, su un unico schermo, una moltitudine di client associando ad ognuno di essi uno sprite e consentendogli di pilotarlo con dei semplici comandi.</p>
<p>In questa proof-of-concept ogni client può connettersi alla porta 8888 del server e dialogando in TCP può pilotare il proprio areo da caccia sullo schermo dell&#8217;applicazione; la sintassi del messaggio è semplicissima:</p>
<pre><code>codice_client|comando</code></pre>
<p>I comandi supportati sono, al momento, solo &#8216;left&#8217;, &#8216;right&#8217;, &#8216;close&#8217; e &#8216;welcome&#8217; ma ben presto introdurrò almeno &#8217;shot&#8217; per consentire all&#8217;areo di difendersi dai (futuri) nemici. L&#8217;intera implementazione è come al solito presente sul mio <a href="http://github.com/sandropaganotti/Gosu-Multiplayer-Shared-Screen" target="_blank">account di github</a>; a seguire invece uno screenshot dell&#8217;applicazione con due client connessi:</p>
<div id="attachment_248" class="wp-caption aligncenter" style="width: 650px"><img class="size-full wp-image-248" title="Multiplayer, shared screen" src="http://sandropaganotti.com/wp-content/uploads/2009/12/ishot-55.png" alt="Ogni aereo è controllato da un client diverso" width="640" height="502" /><p class="wp-caption-text">Ogni aereo è controllato da un client diverso</p></div>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2009/12/08/ruby-e-gosu-un-multiplayer-a-schermo-condiviso/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flex4 e layouts su html.it</title>
		<link>http://sandropaganotti.com/2009/12/06/flex4-e-layouts-su-html-it/</link>
		<comments>http://sandropaganotti.com/2009/12/06/flex4-e-layouts-su-html-it/#comments</comments>
		<pubDate>Sun, 06 Dec 2009 12:06:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Annunci]]></category>
		<category><![CDATA[flex4]]></category>
		<category><![CDATA[html.it]]></category>
		<category><![CDATA[layouts]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=243</guid>
		<description><![CDATA[E&#8217; stato appena pubblicata su flash.html.it la prima parte di una serie di due articoli che ho scritto incentrati sulle classi layout per Flex4. Le potenzialità messe a disposizione dalla nuova release del prodotto Adobe sono veramente impressionanti, mi sono ritrovato a pensare che con quest&#8217;ultima versione sia ora l&#8217;HTML classico ad essere in debito [...]]]></description>
			<content:encoded><![CDATA[<p>E&#8217; stato appena pubblicata su <a href="http://flash.html.it/" target="_blank">flash.html.it</a> la <a href="http://flash.html.it/articoli/leggi/3226/flex-4-e-i-layout/" target="_blank">prima parte</a> di una serie di due articoli che ho scritto incentrati sulle classi <a href="http://help.adobe.com/en_US/Flex/4.0/langref/spark/layouts/supportClasses/LayoutBase.html" target="_blank">layout</a> per <a href="http://opensource.adobe.com/wiki/display/flexsdk/Gumbo" target="_blank">Flex4</a>. Le potenzialità messe a disposizione dalla nuova release del prodotto Adobe sono veramente impressionanti, mi sono ritrovato a pensare che con quest&#8217;ultima versione sia ora l&#8217;HTML classico ad essere in debito di pattern strutturali. Basti pensare alle <a href="http://scalenine.com/blog/2008/07/17/jumping-into-skinning-with-flex-4/" target="_blank">Skin</a>, che consentono di descrivere un componente in tutti i suoi attributi, da quelli fisici (altezza, larghezza, etc..) a quelli di interazione (stati, animazioni tra stati, etc..) diventando una sovrastruttura più importante ed utile dei normali CSS che l&#8217;html mette a disposizione (forse ci si stà avvicinando con i CSS3) in quanto attiva non solo sul piano del design ma anche su quello importantissimo e spesso trascurato dell&#8217;interazione.</p>
<p>Non mi dilungo oltre e lascio gli interessati alla <a href="http://flash.html.it/articoli/leggi/3226/flex-4-e-i-layout/">lettura della prima parte dell&#8217;articolo</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2009/12/06/flex4-e-layouts-su-html-it/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Prime prove con WebKit e WebGL</title>
		<link>http://sandropaganotti.com/2009/11/16/webkit-firefox-e-webgl/</link>
		<comments>http://sandropaganotti.com/2009/11/16/webkit-firefox-e-webgl/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 21:14:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Librerie]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[WebGL]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=233</guid>
		<description><![CDATA[Dal 19 ottobre i nightly builds di Webkit (e anche di Firefox credo) offrono il supporto per le interessantissime estensioni Javascript WebGL. Da quanto ho appreso nel tutorial sembra che il set di API ricalchi abbastanza fedelmente quello delle note OpenGL ES 2.0.

Scaricando il primo esempio e dandogli una veloce occhiata mi è sembrato tutto [...]]]></description>
			<content:encoded><![CDATA[<p>Dal 19 ottobre i nightly builds di Webkit (e anche di Firefox credo) <a href="http://webkit.org/blog/603/webgl-now-available-in-webkit-nightlies/" target="_blank">offrono il supporto per le interessantissime estensioni Javascript WebGL</a>. Da quanto ho appreso nel tutorial sembra che il set di API ricalchi abbastanza fedelmente quello delle note OpenGL ES 2.0.</p>
<p><span id="more-233"></span></p>
<p>Scaricando il primo esempio e dandogli una veloce occhiata mi è sembrato tutto abbastanza lineare e comprensibile, dopo pochissimo sono riuscito senza particolari problemi ad individuare il punto di loading della texture e a modificarlo come segue:</p>
<p><img class="aligncenter size-full wp-image-234" title="Primi esperimenti con WebGL" src="http://sandropaganotti.com/wp-content/uploads/2009/11/ishot-45.png" alt="Primi esperimenti con WebGL" width="587" height="648" /></p>
<p>Ora stò importando <a href="http://jquery.com/" target="_blank">JQuery</a>, il prossimo passo è utilizzare questa famosissima libreria per recuperare alcune immagini dalla <a href="http://www.flickr.com/photos/22085175@N02/" target="_blank">mia gallery di Flickr</a> e mostrarle sul cubo.</p>
<p>Stay Tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2009/11/16/webkit-firefox-e-webgl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby, Rails e CouchDB</title>
		<link>http://sandropaganotti.com/2009/11/10/ruby-rails-e-couchdb/</link>
		<comments>http://sandropaganotti.com/2009/11/10/ruby-rails-e-couchdb/#comments</comments>
		<pubDate>Tue, 10 Nov 2009 22:16:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Annunci]]></category>
		<category><![CDATA[Couch DB]]></category>
		<category><![CDATA[CouchRest]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=229</guid>
		<description><![CDATA[Su ruby.html.it e su database.html.it potrete trovare due articoli &#8216;gemelli&#8217; di cui sono l&#8217;autore che hanno come soggetto CouchDB, un database non relazionale (schema-less) scritto interamente in Erlang e pensato per gestire dati non strutturati su un&#8217;architettura che scala molto facilmente. Il primo articolo &#8216;Introduzione a CouchDB, il dbms document-oriented da interrogare con JavaScript&#8216; illustra [...]]]></description>
			<content:encoded><![CDATA[<p>Su <a title="Html.it - Ruby " href="http://ruby.html.it" target="_blank">ruby.html.it</a> e su <a title="Html.it - Database " href="http://database.html.it" target="_blank">database.html.it</a> potrete trovare due articoli &#8216;gemelli&#8217; di cui sono l&#8217;autore che hanno come soggetto <a href="http://couchdb.apache.org/" target="_blank">CouchDB</a>, un database non relazionale (schema-less) scritto interamente in Erlang e pensato per gestire dati non strutturati su un&#8217;architettura che scala molto facilmente. Il primo articolo &#8216;<a title="  Database  »  Articoli  »  Altri Database   Pagine:     1. 1    2. 2    3. 3    4. 4  RSS Introduzione a CouchDB, il dbms document-oriented da interrogare con JavaScript" href="http://database.html.it/articoli/leggi/3203/introduzione-a-couchdb-il-dbms-documentoriented-da-interrogare-con-javascript/" target="_blank">Introduzione a CouchDB, il dbms document-oriented da interrogare con JavaScript</a>&#8216; illustra in poche pagine le principali caratteristiche del database e aiuta ad orientarsi nella sua interfaccia web di gestione/amministrazione: Futon. Il secondo: &#8216;<a title="  Ruby  »  Articoli  »  Rails   Pagine:     1. 1    2. 2    3. 3  RSS Download CouchDB e Rails: la gemma sul divano" href="http://ruby.html.it/articoli/leggi/3208/couchdb-e-rails-la-gemma-sul-divano/" target="_blank">CouchDB e Rails: la gemma sul divano</a>&#8216; si concentra invece su come integrare CouchDB con le nostre applicazioni Rails rinunciando il meno possibile ai vantaggi offerti dall&#8217;ORM di questo framework.</p>
<p>Senza aggiungere altri spoiler rimando, a chi è interessato, alla lettura dei due scritti.</p>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2009/11/10/ruby-rails-e-couchdb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
