WordCram Release 0.4

WordCram 0.4 is ready for consumption! Download the zip or the tar.

The high notes:

  • If you’re passing your own words, you can pre-set their color, font, size, angle, and placement: word.setColor(#f02939).setAngle(QUARTER_PI); These settings will override the WordColorer, WordAngler, etc. This should make it easier to control how specific words are drawn, but you can even use it for styling all your words.
  • If you’re not seeing as many words as you expected, you can call getSkippedWords() to see which words were skipped, and call wasSkippedBecause() on each one to see why it was skipped. If you’re troubleshooting the words that do show up, you can call getRenderedSize(), getRenderedColor(), etc, on each word. And if you want to do some interaction, getWordAt(x,y) will tell you which word is at the given [x,y] coordinates.
  • All the settings for fine-tuning a WordCram are now at your fingers. If your WordCram is too slow, too crowded, or too sparse, you can probably fix it: you can limit how many words WordCram will try to render, limit the size of the smallest word it’ll accept, and limit how many times it’ll try to place a word.
  • A bunch of new tutorial sketches will walk you through WordCram in (I hope) a sensible order. They cover all the features, both new and old.

See the Release notes, the tutorial sketches, and the javadoc for the details. If you have any questions or feedback, or just want to show off your word clouds, I’m @wordcram on twitter, and wordcram-at-gmail.

Posted in release, wordcram | Leave a comment

Golan Levin’s SubRip Processing Parser

Golan Levin just posted a Processing parser for SubRip subtitle files, and posted a demo applet that generates a tag clouds (via OpenCloud) from Star Wars.

It should be fun to try using his parser with WordCram.

Posted in related | Leave a comment

2011 State of the Union Address, WordCrammed

Twelve other runs:

The code for all of them:

import wordcram.*;
import wordcram.text.*;

void setup() {
  size(700, 500);
}

void draw() { 
  background(255);
  new WordCram(this)
    .fromTextFile("state-of-the-union.txt")
    .withColors(
      color(0), color(230, 0, 0), color(0, 0, 230))
    .withPlacer(Placers.centerClump())
    .sizedByWeight(10, 100)
    .drawAll();
  
  saveFrame("sotu-##.png");
}

Posted in examples, wordcram | 1 Comment

WordCram Interview

I just realised I never posted a link to the WordCram interview that Zoltán Varjú was kind enough to conduct!

Zoltán runs a blog called Számítógépes nyelvészet (which Google tells me is Hungarian for Computational Linguistics) where he regularly interviews people working in computational linguistics and related fields.  Impressive company for WordCram to keep. His blog is worth checking out — there are a number of English posts, and Google Translate helps with the rest, for non-Hungarian-speakers like me.

Zoltán, I’m terribly sorry for letting it slip.  Thanks again for the interview!

Posted in wordcram | Leave a comment

PDF Rendering Is Almost Ready

After poking around, it seems like PDF rendering might not be as far-fetched as I’d first thought. I’ve made some pretty good progress:

  • WordCram can tell when the sketch is rendering to PDF.  This means the API is unchanged: you just set up your sketch to render to PDF.
  • After cleaning up the innards a bit, rendering to PDF is pretty easy.

But I’m stuck at the last mile.  If you know how to use java’s PathIterator, Path2D, and/or Shape classes with Processing, or know Geomerative’s guts well (I think they have some similar problems), and don’t mind answering a few questions, I’d love to hear from you: I’m danbernier at Google’s famous e-mail domain.

Overall, I’m excited at the thought of real PDF rendering, and at how easy it’s been.  If you’re interested, check out the svn branch and let me know what you think.

Posted in wordcram | Leave a comment

WordCram Release 0.3

WordCram 0.3 is here, and it has some nice improvements.

Simpler to Use

It’s easier to create a WordCram: instead of that long list of parameters, you instantiate it with your sketch, and then call methods on your WordCram to customize it.

From this:

new WordCram(this,
  new TextSplitter(StopWords.ENGLISH + " shall")
    .split(loadStrings(myFile)),
  Fonters.pickFrom(createFont("serif", 1)),
  Sizers.byWeight(100, 1200),
  Colorers.twoHuesRandomSats(this),
  Anglers.mostlyHoriz(),
  Placers.swirl())
.drawAll();

To this:

new WordCram(this)
  .withStopWords(StopWords.ENGLISH + " shall")
  .fromTextFile(myFile)
  .withFont("serif")
  .sizedByWeight(100, 1200)
  .withPlacer(Placers.swirl())
  .drawAll();

With the new way, you don’t have to remember which order the parts go in. WordCram can provide defaults (notice the new version didn’t pick a Colorer or Angler?), and good overloads (for example, instead of sizedByWeight, you can use sizedByRank). The method names follow a convention, so they should be easy to remember.

Hopefully, this should make it easier to create WordCrams. If you have tons of critical-path legacy enterprise application layers written against the old stuff, don’t worry, you can still upgrade — the old methods are there, just deprecated.

New Text Sources

Another big plus is that you can make WordCrams from different text sources, like a web page:

new WordCram(this)
  .fromWebPage("http://wordcram.wordpress.com")
  .drawAll();

With the new stuff in place, it’ll become easier to add more text sources: delicious tags, twitter streams, RSS, all that.

Documentation

The last big news is documentation. There’s actual javadoc, and examples included. Once WordCram is installed into Processing, go to File > Sketchbook > libraries > WordCram > examples to see them.

Miscellany, Et Cetera

Throw in some new Anglers, Colorers, and Placers, Java stop-words (so you can WordCram java source code), bug fixes, and performance tweaks, and you’ve got a release. For all the messy details, see the release notes.

Coming Up

My next immediate goals are more tutorials, and a bunch of examples to show off the different ways you can control WordCram. After that, we’ll see — there’s still lots to do. If you have ideas for making WordCram better, I’d love to hear from you: wordcram at gmail dot com.

Go upgrade already!

Posted in release, wordcram | 2 Comments

Blog Header by WordCram

Here is, more-or-less, the sketch I used to generate the new WordCram blog header. About half of the sketch is Processing setup and interaction, so I could keep running it until I found one I liked.

When I get around to it, I want to make it easier to load a directory of source code files, but for now, cat `find -name *.java` > src.txt is good enough.

import wordcram.*;
import wordcram.text.*;

WordCram wc;

void setup() {
  colorMode(HSB);
  size(940, 198);
  background(0);

  initWordCram();
}

void initWordCram() {
  String license = join(loadStrings("LICENSE"), " ").toLowerCase();

  wc = new WordCram(this)
      .fromTextFile("src.txt")
      .withStopWords(StopWords.ENGLISH + StopWords.JAVA + license)
      .withFont("Droid Sans Mono")
      .sizedByWeight(12, 60)
      .withPlacer(new WordPlacer() {
          public PVector place(Word w, int wordCount, int numWords,
                               int wordWidth, int wordHeight,
                               int fieldWidth, int fieldHeight) {

            // x = weight, heavies on the left
            float x = (fieldWidth - wordWidth) * (1 - (float)w.weight);
            x *= random(0.6, 1); // fade them back a bit -- don't clump on the right

            // y = random around center horiz. line. Heavier words are less random.
            float y = random(1) *
                      (1 - (float)w.weight) *
                      (fieldHeight - wordHeight) / 2;
            y += (fieldHeight - wordHeight) / 2;

            return new PVector(x, y);
          }
      })
      .withAngler(new WordAngler() {
          public float angleFor(Word w) {

            // swing between -30 and 30 degrees -- heavy words swing less
            return (1 - (float)w.weight) * random(radians(-30), radians(30));
          }
      });
}

void draw() {
  if (wc.hasMore()) {
    wc.drawNext();
  }
  else {
    save("wordcram.png");
    println("done");
    noLoop();
  }
}

void mouseClicked() {
  background(0);
  initWordCram();
  loop();
}

Posted in examples, wordcram | 1 Comment