Our Blog

Mi ha sempre affascinato l’idea di lavorare con i dati: manipolare e interpretare le informazioni per visualizzare o creare delle installazioni interattive è uno dei processi che amo di più nel mio lavoro. Non sono un esperto di data visualization e nemmeno aspiro ad esserlo. Raccontare con i dati, investigare per visualizzare delle informazioni è un processo interessante in quanto oltre che facilitarne la lettura si possono creare delle visualizzazioni estetiche molto funzionali. Non essendo questo il caso, sono più interessato a usare il cambiamento di un dato in tempo reale per attivare un processo nelle mie installazioni ( come in Natura non nisi parendo vincitur o 8 Minutes ).

Ho avuto il piacere di essere stato coinvolto insieme ad Enrico Viola nel progetto La Cura di Salvatore Iaconesi e Oriana Persico, dove stiamo preparando un workshop chiamato We are not Numbers. In questo workshop cercheremo di esplorare metodi di interazione con i dati grezzi provenienti dal mondo dei big data, nello specifico utilizzando le API di Human Ecosystem. Trovate una dettagliata documentazione sugli Endpoint di Human Ecosystem sul GitHub di Salvatore Iaconesi. Ecco una breve panoramica sulle loro API:

Per esempio se vogliamovisualizzare le statistiche relative alla distribuzione di emozioni nella città di Bologna sui Social Network. Usiamo l’endpoint tools-getProjectStatistics.php?w=bologna

Ora vi mostrerò come visualizzare una semplice esperienza interattiva caricando e ‘parsando’ un file JSON dentro Unity3D utilizzando una libreria per .Net chiamata LitJson DLL e a questo link potete scaricare la stessa già compilata pronta per essere importata dentro Unity nella folder Assets/Plugins. Una volta importata la dll dentro Unity dobbiamo creare un nuovo script che chiameremo LoadJson.cs e la prima cosa da fare è includere la libreria compilata LitJson sopra la classe:

using LitJson;

Nello script LoadJSON.cs  avremo bisogno di leggere il file JSON.


 IEnumerator Start () 
 {
 
     string HE_BO = "http://human-ecosystems.com/HE_BO/API/tools-getProjectStatistics.php?w=bologna";

     WWW www = new WWW(HE_BO);

     yield return www;

     if (www.error == null && www.isDone )
     { 
         //Sucessfully loaded the JSON string
         Debug.Log("Loaded following JSON string" + www.text);

         //Process JSON file
         LoadJsonLaCuraStatistics();
     }
     else
     {
        Debug.Log("ERROR: " + www.error);
     }
 }


In Unity esistono le Coroutine, funzioni speciali che permettono l’esecuzione e l’interruzione delle stesse usando lo stato yield. Con yield return specifico quando riprendere l’esecuzione della funzione.  In sostante anteponendo IEnumerator a Start() do la possibilità di ritornare nuovamente nello stato di inizializzazione.

L’oggetto www riferito alla classe WWW mi permette di accedere ad un link web e di scaricarlo. In questo caso scarichiamo il JSON all’indirizzo http://human-ecosystems.com/HE_BO/API/tools-getProjectStatistics.php?w=bologna. Se non ci sono errori e si è scaricato totalmente il file  richiamo la funzione LoadJsonLaCuraStatistics() mostrata di seguito


void LoadJsonLaCuraStatistics()
{
    string jsonString = www.text;
    JsonData emotionsObject = JsonMapper.ToObject(jsonString);

    Datas datas = new Datas();
    print("Emotions: " + emotionsObject["emotions"].Count);

    int numEmo = emotionsObject["emotions"].Count;
    GameObject[] emotions = new GameObject[numEmo];


    temp = new GameObject("temp");
    for(int i = 0; i < emotionsObject["emotions"].Count; i++)
    {
       float angle = i * Mathf.PI * 2 / emotionsObject["emotions"].Count;

       float[] values = new float[numEmo];
       values[i] = float.Parse(emotionsObject["emotions"][i]["value"].ToString()) / 100;
       print(emotionsObject["emotions"][i]["label"].ToString() + values[i]);

       Vector3 gapPos = new Vector3(i * 22, 0, 0);

       emotions[i] = Instantiate(myPrefab, gapPos, Quaternion.Euler(Vector3.forward)) as GameObject;
       emotions[i].transform.parent = temp.transform;
       emotions[i].transform.localScale = new Vector3(40, values[i], 40);
 

      emotions[i].GetComponent<Renderer>().material.color = new Color32( 255, 0, 0, 255);
 
 
 }

Vediamo le istruzioni principali della funzione LoadJsonLaCuraStatistics() Per prima cosa converto la stringa jsonString caricata in un oggetto JsonData chiamato emotionsObject con la classe statica JsonMapper come segue:

JsonData emotionsObject = JsonMapper.ToObject(jsonString);

Ora analizziamo per un momento il nostro file JSON e con una web application JSON Viewer apriamo lìindirizzo : http://human-ecosystems.com/HE_BO/API/tools-getProjectStatistics.php?w=bologna
Io ho usato questo: http://codebeautify.org/jsonviewer

{
    "contents": "149257",
    "users": "121326",
    "geocontents": "143260",
    "emotions": [
        {
            "label": "Joy",
            "value": "33737"
        },
        {
            "label": "Love",
            "value": "20548"
        },
        {
            "label": "Trust",
            "value": "15744"
        },
        { 
         .......

Ora possiamo accedere agli oggetti definiti nel JSON. Per esempio se volessimo stampare in console quante emozioni ci sono usiamo :

print("Emotions: " + emotionsObject["emotions"].Count);

emotionsObject[“emotions”] è un array di emotions e in modo semplice possiamo usare il ciclo for per iterare all’interno di esso per estrapolarci successivamente le “label” delle emozioni, e “value” per il valore riferito alla quantità di messaggi che parlano di quella determinata emozione.


for(int i = 0; i < emotionsObject["emotions"].Count; i++)
{
   print(emotionsObject["emotions"][i]["label"].ToString()); 
}

Con la stessa logica vado a estrapolarmi i valori delle emozioni e li salvo in una array di float values che divido per 100 per comodità di scala in Unity

float[] values = new float[numEmo];
values[i] = float.Parse(emotionsObject["emotions"][i]["value"].ToString()) / 100;

Ora vogliamo creare un array di GameObject dentro il quale istanzieremo successivamente dei cubi. Infine lo riempiamo con la quantità massima di emozioni trovate.


      int numEmo = emotionsObject["emotions"].Count;
      GameObject[] emotions = new GameObject[numEmo];

Sempre all’interno del ciclo for definisco una variabile Vector3 gap che è la distanza tra ciascun cubo nell’asse delle X. Instanziamo poi il prefab cubo per ogni posizione nell’array di GameObject emotions. Per semplicità definisco la quantità di messaggi assegnando il valore nella localScale.y di ciascun cubo.

 
Vector3 gapPos = new Vector3(i * 22, 0, 0); 
emotions[i] = Instantiate(myPrefab, gapPos, Quaternion.Euler(Vector3.forward)) as GameObject;
emotions[i].transform.localScale = new Vector3(40, values[i], 40);

Il risultato finale è la visualizzazione di 13 cubi che rappresentano le 13 emozioni trovate nel file json. Niente di esteticamente sorprendente ma è un primo approccio per iniziare a lavorare con i dati con Unity e stimolarvi per ideare visualizzazioni interattive.
data viz unity

Potete scaricare l’intero progetto open source sul mio repository di BitBucket a questo link :

https://bitbucket.org/robertofazio/humanecosystem_lacura ( work in progress )

Comments ( 0 )

    Leave A Comment

    Your email address will not be published. Required fields are marked *