How to add new words in a string and display them to create a word-cloud

Hi everyone.
I’m doing an installation for a project, this is my stand point.

What do I want to achieve:
A program that display a word-cloud (the more a specific word has been say, the bigger it appears in the word cloud).
The input will be a microphone, the program will detect the word and then display it. (it will start with 0 word and then the number will incresce depending on how oft people will interact with it. The font size of the words already displayed should change and adapt in order to keep the chart true).

The code now:
I took two code I found online and I merge and edit them. The code integrate the function to detect the word from the microphone and display it in the console (is not yet displayed in the world-cloud).
The text to form the cloud now is an external text file (witch is not necessary but I keep it for testing).
When I run the sketch and I edit the text file (already full) and save it (with the sketch running) it does not update. I can’t really understand why.
If I run the sketch with only one word on it, then I add a new one and I save the text file, the code some times display the new word (smaller compere to the first one even if is repeated) other times he just repeat the last word he displayed but smaller then the previous one).

Help
I’m a beginner in processing, I would like if someone could take the time to guide me in order to fully understand the code and help me out to get the code running the way I would like it to.

here a link to download the zipped code with the text file and font
https://we.tl/t-BtzFRNh6JR

Thanks

/* 
  Voice recognition:
    run this sketch 
    open the link (with chrome) to record voice: 
      https://codepen.io/sandro-poli/pen/JmMKLw    
    speak and see console
 */

import java.util.Iterator;
import websockets.*;
import java.applet.*; 
import java.awt.*; 
import java.awt.image.*; 
import java.awt.event.*; 
import java.io.*; 
import java.net.*; 
import java.text.*; 
import java.util.*; 
import java.util.zip.*; 
import java.util.regex.*; 

WebsocketServer socket; //WebSockets Library: https://github.com/alexandrainst/processing_websockets

PFont font;
String fontFile = "MaisonNeue-Demi-96.vlw";
int fSize = 96;
int maxSize = 200; //font max size
int minSize = 50;  //font min size
String wordFile = "H-Farm.txt";
String[] words;
int[]  count;
int most;
int least;
float currentSize;
int currentIndex;

void setup(){
  size(900, 500);
  colorMode(HSB, TWO_PI, 1, 1, 1);
  socket = new WebsocketServer(this, 1337, "/p5websocket");
  rectMode(CORNER);
  background(color(0, 0, 1));
  smooth();
  font = loadFont(fontFile);
  //initializeWords();  // moved in draw function 
  //noLoop(); //don't needed i guess
}

void draw() {
  initializeWords();
  //while(currentIndex < words.length) /change while with if under
    if(currentIndex < words.length) {
    float relsize = map(count[currentIndex],least,most,minSize,maxSize);
    boolean drawn = false;  
    while (!drawn) {
      drawn = drawWord(words[currentIndex], relsize);
      if (!drawn)
       println("redrawing "+words[currentIndex]);
      //println(currentIndex); riconosce cambiamenti al salvataggio del documento di testo
        relsize = relsize * 0.95;
    }
    currentIndex++;
  }  
}

void webSocketServerEvent(String msg) {
  println(msg); // print dectected text from micorphone 
}

boolean drawWord(String word, float wordSize) {
  int intSize = (int)wordSize;
  textFont(font, wordSize);
  int w = int(textWidth(word));
  PGraphics g = createGraphics(w, intSize);
  g.beginDraw();
  g.background(color(0, 0, 1, 0));
  g.fill(color(0,0,0));
  g.textAlign(CENTER, CENTER);
  g.translate(w/2, wordSize/2);
  g.scale(wordSize / fSize);
  g.textFont(font);
  g.text(word, 0, 0);
  g.endDraw();

  PGraphics gMask = createGraphics(w, intSize);
  gMask.beginDraw();
  //gMask.background(color(0, 0, 1, 1));
  gMask.image(g, 0, 0);
  gMask.filter(ERODE);  
  gMask.filter(ERODE);
  gMask.endDraw();
  
  for (int tries=50; tries>0; tries--) {
    int x = (int)random(width-w);
    int y = (int)random(height-intSize);
    
    boolean fits = true;
    for (int dx = 0; dx< w && fits; dx++) {
      for (int dy = 0; dy<intSize && fits; dy++) {
        if (brightness(gMask.get(dx, dy))<0.5) {
          if (brightness(get(x+dx, y+dy))<0.5) {
            fits = false;
          }
        }
      }
    }
    if (fits) {
      image(g, x, y);
      return true;
    }
  }
  return false;
}

boolean equalColor(color c1, color c2) {
  String h1 = hex(color(c1));
  String h2 = hex(color(c2));
  return h1.equals(h2);
}


void initializeWords() {
  ArrayList ignore = new ArrayList();
  String[] ignoreStrs  = loadStrings("ignora.txt");
  for (int i = 0; i < ignoreStrs.length; i++) {
    ignore.add(ignoreStrs[i].trim().toUpperCase());
  }
  HashMap wordcount = new HashMap(); // similar to array but for string
  String[] lines = loadStrings(wordFile); // upload tex file
  for (int i = 0; i < lines.length; i++) {
    String[] words = split(lines[i], " ");  
    for (int j = 0; j < words.length; j++)  {
      String word = clean(words[j]).toUpperCase();
      if (word.length() == 0) {
        continue;
      }
      if (ignore.contains(word)) {
        continue;
      }
      Integer count = (Integer)wordcount.get(word); 
      if (count == null) {
         wordcount.put(word, new Integer(1));
       }
       else {
         int newCount = count.intValue() + 1;
         wordcount.put(word, new Integer(newCount));
       }
    }
  }
  words = new String[wordcount.size()];
  count = new int[wordcount.size()];
  int idx = 0;
  Iterator it = wordcount.entrySet().iterator();  // Get an iterator
  while (it.hasNext()) {
      Map.Entry me = (Map.Entry)it.next();
      words[idx] = (String)me.getKey();
      count[idx] = ((Integer)(me.getValue())).intValue();
      idx++;
  }
  sortWords();
  String[] sorted = new String[words.length];
  for (int i = 0; i < words.length; i++) {
    sorted[i] = count[i]+" "+words[i];
  }
  most = count[0];
  //least = count[count.length-1]; //maybe to delate???
  //saveStrings("totals.txt", sorted);
}

String clean(String word) {
  word = word.trim();
  if (word.endsWith(".") || word.endsWith(",") || word.endsWith(";"))
    word = word.substring(0, word.length() - 1);
  return word.trim();    
}


void sortWords() {
  boolean changed = true;
  while (changed) {
    boolean madeChange = false;
    for (int i = 0; i < count.length-1; i++) {
      if (count[i] < count[i+1]) {
        int temp = count[i];
        String tempW = words[i];
        count[i] = count[i+1];
        words[i] = words[i+1];
        count[i+1] = temp;
        words[i+1] = tempW;
        madeChange = true;
      }
    }
    changed = madeChange;
  }
}

 

There is an excellent library for creating wordclouds https://wordcram.org/

1 Like

hey, thanks for the answer!
I’ve tried to use it and it looks excellent if you have to upload a given text although, for my goal which is to start from no words and then add one after the other, it results difficult for me to do that there.

@GoToLoop I open another topic (hopefully) more specific then this one. I can’t delete this question by my self, i wonder if you could do it. Thanks

Hey @monkstone, I really struglle with Processing libraries outside the cozy IDE install. The wordcram official download link is broken, I can see lot’s of .jar files on their GitHub repo but I have no idea on how to manually arrange them in my local environment, I have tried for a few hours.

Could you share a link to a well formed library folder I could put insinde my libraries folder? :grimacing:

UPDATE: From the Internet Archive wayback machine (the original domain is gone): https://web.archive.org/web/20161126072647/http://wordcram.org/wordcram.1.0.0.zip