<?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 &#187; Flock</title>
	<atom:link href="http://sandropaganotti.com/tag/flock/feed/" rel="self" type="application/rss+xml" />
	<link>http://sandropaganotti.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sun, 25 Jul 2010 12:45:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Uno stormo con processing.org</title>
		<link>http://sandropaganotti.com/2009/01/01/uno-stormo-con-processing/</link>
		<comments>http://sandropaganotti.com/2009/01/01/uno-stormo-con-processing/#comments</comments>
		<pubDate>Thu, 01 Jan 2009 16:56:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Algoritmi]]></category>
		<category><![CDATA[Algoritmo]]></category>
		<category><![CDATA[Engine]]></category>
		<category><![CDATA[Flock]]></category>
		<category><![CDATA[Processing]]></category>
		<category><![CDATA[Simulazione]]></category>
		<category><![CDATA[Stormo]]></category>

		<guid isPermaLink="false">http://sandropaganotti.com/?p=83</guid>
		<description><![CDATA[Esiste molta letteratura sul problema di simulazione di uno stormo (detto anche Flocking), queste sono le tre regole principali a cui ogni partecipante allo stormo deve obbedire: muoversi verso il centro del gruppo; mantenere una distanza minima dagli altri; muoversi con una velocità simile alla velocità del gruppo; Sulla base di queste tre regole ho [...]]]></description>
			<content:encoded><![CDATA[<p>Esiste molta letteratura sul problema di simulazione di uno stormo (detto anche <a href="http://en.wikipedia.org/wiki/Flocking_(behavior)">Flocking</a>), queste sono le tre regole principali a cui ogni partecipante allo stormo deve obbedire:</p>
<p><span id="more-83"></span></p>
<ul>
<li>muoversi verso il centro del gruppo;</li>
<li>mantenere una distanza minima dagli altri;</li>
<li>muoversi con una velocità simile alla velocità del gruppo;</li>
</ul>
<p>Sulla base di queste tre regole ho sviluppato un piccolo programma in <a href="http://processing.org">Processing.org</a> che simula il modello comportamentale di un gruppo (mantenendo le tre leggi sopra descritte) in questi passi:</p>
<ul>
<li>per ogni elemento dello stormo viene generata una posizione iniziale random all&#8217;interno del canvas;</li>
<li>per ogni ciclo di ridisegno, per ogni elemento dello stormo:
<ul>
<li>recupero la velocità dell&#8217;elemento più vicino e la assegno (leggermente variata) all&#8217;elemento corrente;</li>
<li>trovo il centro dello stormo (e lo modifico con un pò di noise);</li>
<li>avvicino l&#8217;elemento corrente verso il centro dello stormo alla velocità precedentemente impostata &#8211; eseguo quest&#8217;ultima operazione solo se l&#8217;elemento nella nuova posizione non è troppo vicino a qualche altro elemento dello stormo;</li>
</ul>
</li>
</ul>
<p>A questo ho aggiunto la possibilità, usando i tasti W,S,A,D di spostare il centro dello stormo calcolato automaticamente e, in questo modo, pilotare l&#8217;intero stormo.</p>
<p>Come al solito il codice nella sua interezza è presente <a href="http://github.com/sandropaganotti/processing.org-flock">sul mio account di GitHub</a>, posso però in questa sede mostrarvi una demo di quanto creato grazie alla potentissima libreria <a href="http://ejohn.org/blog/processingjs/">Processing.js</a> regalataci da Jhon Resing che consente di eseguire script scritti per Processing.org all&#8217;interno di un elemento &#8216;CANVAS&#8217; del browser.</p>
<p>Questa libreria non è però al momento 100% cross-browser: io ho personalmente testato il tutto con la versione più aggiornata di Firefox (3.0.5) senza riscontrare nessuna perdità di funzionalità (funzionano anche i comandi da tastiera!); lo stesso però non posso garantire per altri browser.</p>
<p>Per provare il programma non vi resta che cliccare sul link sottostante; ricordate che potete direzionare lo stormo usando la vostra tastiera (tasti: WSAD).</p>
<p><a onclick="$('processing_canvas').show();Processing( $('processing_canvas'), $('processing').textContent ); return false;">Lancia la simulazione di stormo in Processing</a></p>
<p><canvas id="processing_canvas" style="display:none;"></canvas></p>
<pre style="display:none;"><code id="processing">

class Creature {
 int sng_x;
 int sng_y;
 float sng_x_speed;
 float sng_y_speed;

 Creature(){
   sng_x = 0;
   sng_y = 0;
   sng_x_speed = 0;
   sng_y_speed = 0;
 }

 float calc_dist(Creature k){
   return sqrt(pow(this.sng_x - k.sng_x,2) + pow(this.sng_y - k.sng_y,2));
 }
 void to_text(){
   println("X: " + sng_x + " Y: " + sng_y);
 }
}

int canvas_width  = 400;
int canvas_height = 400;
int min_separation = 15;
int circle_size = 5;
int num_sheep = 20;
int max_noise = 250;
int mint_follow_x = 0;
int mint_follow_y = 0;
int follow_amount = 100;
float max_speed_variance = 0.001;
float min_speed = 0.005;
float max_speed = 0.01;

Creature[] flock = new Creature[num_sheep]; 

void setup(){
  int i;
  int j;
  boolean bln_separation;
  size(canvas_width,canvas_height);

  for(int x=0; x < flock.length; x++){
    bln_separation = false;
    flock[x] = new Creature();
    while(!bln_separation){
      flock[x].sng_x = int(random(1,canvas_width));
      flock[x].sng_y = int(random(1,canvas_height));
      bln_separation = true;
      for(int y=0; y < x; y++){
        if(flock[x].calc_dist(flock[y]) <= min_separation){
          bln_separation = false;
          break;
        }
      }
    }
  }
}

void draw(){
  background(100);
  float sng_dist;
  float sng_x_speed = 0.0;
  float sng_y_speed = 0.0;
  int sng_x_sum;
  int sng_y_sum;
  float sng_x_avg;
  float sng_y_avg;
  float sng_x_dist;
  float sng_y_dist;
  int sng_tmp_x;
  int sng_tmp_y;

  for(int x=0; x < flock.length; x++){
    sng_dist = 0;
    for(int y=0; y < flock.length; y++){
      if(x!=y){
        if(sng_dist == 0.0 || flock[x].calc_dist(flock[y]) < sng_dist){
          sng_dist = flock[x].calc_dist(flock[y]);
          sng_x_speed = flock[y].sng_x_speed;
          sng_y_speed = flock[y].sng_y_speed;
        }
      }
    }

    flock[x].sng_x_speed = sng_x_speed + max_speed_variance;
    flock[x].sng_y_speed = sng_y_speed + max_speed_variance;
    if(flock[x].sng_x_speed < min_speed) flock[x].sng_x_speed = min_speed;
    if(flock[x].sng_y_speed < min_speed) flock[x].sng_y_speed = min_speed;
    if(flock[x].sng_x_speed > max_speed) flock[x].sng_x_speed = max_speed;
    if(flock[x].sng_y_speed > max_speed) flock[x].sng_y_speed = max_speed;

    sng_x_sum = 0;
    sng_y_sum = 0;
    for(int y=0; y < flock.length; y++){
      sng_x_sum = sng_x_sum + flock[y].sng_x;
      sng_y_sum = sng_y_sum + flock[y].sng_y;
    }

    sng_x_avg = float(sng_x_sum / num_sheep) + (random(1) * max_noise) - (max_noise / 2.0) + mint_follow_x;
    sng_y_avg = float(sng_y_sum / num_sheep) + (random(1) * max_noise) - (max_noise / 2.0) + mint_follow_y;  

    sng_tmp_x = flock[x].sng_x;
    sng_tmp_y = flock[x].sng_y;
    sng_x_dist = sng_x_avg - flock[x].sng_x;
    sng_y_dist = sng_y_avg - flock[x].sng_y;
    flock[x].sng_x = int(flock[x].sng_x + sng_x_dist * flock[x].sng_x_speed);
    flock[x].sng_y = int(flock[x].sng_y + sng_y_dist * flock[x].sng_y_speed);

    for(int y=0; y < flock.length; y++){
      if( x!=y &#038;&#038; flock[x].calc_dist(flock[y]) <= min_separation ){
        flock[x].sng_x = sng_tmp_x;
        flock[x].sng_y = sng_tmp_y;
        break;
      }
    }

    if(flock[x].sng_x > canvas_width) flock[x].sng_x = flock[x].sng_x - canvas_width;
    if(flock[x].sng_x < 0) flock[x].sng_x = flock[x].sng_x + canvas_width;
    if(flock[x].sng_y > canvas_height) flock[x].sng_y = flock[x].sng_y - canvas_height;
    if(flock[x].sng_y < 0) flock[x].sng_y = flock[x].sng_y + canvas_height;

     ellipse(flock[x].sng_x,flock[x].sng_y,circle_size,circle_size);
  }
}

void keyPressed() {
  if (key == 'w') mint_follow_y = mint_follow_y - follow_amount;
  if (key == 's') mint_follow_y = mint_follow_y + follow_amount;
  if (key == 'a') mint_follow_x = mint_follow_x - follow_amount;
  if (key == 'd') mint_follow_x = mint_follow_x + follow_amount;
}

</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://sandropaganotti.com/2009/01/01/uno-stormo-con-processing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
