Monthly Archives: June 2009

What have I been listening to?

0
Filed under cc2, referat
Listening History by Lee Bryon

- Last.fm Api basierte listening history Analyse
- Hörverhalten einer Users über spezifischen Zeitraum(im Beispiel 18 Monate)
- Core- und new discovery-musicians über Farbcodierung
- Spiegel für: Was gehört? Wann gehört? Trendänderungen und eventuellen Zusammenhang zwischen Genre, Interpret und den Hörgewohnheiten

Listening History by Lee Bryon

Referat 03.Juni 2009

0
Filed under cc1, referat

claytoncubitt_mp093
Metropop Denim
Fashion Photography and Generative Artwork by Clayton Cubitt and Tom Carden

Abschlussaufgabe CreativeCoding I

0
Filed under cc1

INPUT / OUTPUT
-
1. FINDE
Finde dein Ausgangsmaterial. Ein Video, ein Geräusch, ein Musikstück, ein Text (vom Gedicht bis zur Webseite), eine Fotografie, eine Grafik, ein Geruch,…

2. TRANSFORMIERE
Analysiere dein Ausgangsmaterial. Welche Charakteristika hat es? Was zeichnet es aus? Wie ist es beschaffen? Wie sieht es aus?
Interpretiere, Rekonstruiere, Transformiere dein Ausgangsmaterial zu etwas Neuem. Einer ästhetischen Form, ein Muster, einer generative Struktur, einer (Info)Grafik,… . Das Endergebnis kann eine Bildschirmmanwendung, ein Plakat oder ein Video sein. Die Analyse kann, muss aber nicht mit Processing stattfinden. Die eigentliche Transformation muss mit Processing gelöst werden.

3. PRÄSENTIERE
Präsentiere das von dir gewählte Ausgangsmaterial, den Transformationsprozess und das Endergebniss in einer 10 minütigen Beamerpräsentation.
Richtlinien: Screengröße: 1024 x 768, Schriftgröße min. 21 Pt.

Termin: 22.07.09

Zufällige Positionen in Freiform ermitteln (bitmap trick)

0
Filed under input, tipps

Der folgende Sketch ermittelt zufällige Positionen innerhalb einer vorgegebenen Maske (Freiform), und stellt diese durch kleine Kreuze im Sketchfenster dar.

Random point in shape

Die rein mathematische Lösung für einen zufälligen Punkt in einer Freiform ist für unser Anliegen zu aufwendig. Im Folgenden bedienen wir uns dem Trick einer Maskierung durch ein Pixelbild. Dieses besteht im Idealfall nur aus schwarzen und weißen Pixeln – wobei die schwarzen die Form bestimmen. Die get() Funktion, zum Auslesen von Farbwerten, wird in einer Funktion platziert, welche die zufällig ermittelte Position zurück gibt. Da sich eine Funktion auch selbst aufrufen kann (Rekursion), ist diese in der Lage so lange zu suchen, bis ein Punkt innerhalb der Form bestimmt wurde.

Weil eine Funktion nur eine Variable als Rückgabewert zur Verfügung hat, verwenden wir einen Vektor.

Beispiel runterladen

PVector imgPos; // Position der Maske im Sketch
PImage img; // Kontainer für die Masek

void setup () {
  size (240, 160);
  // Laden der Maske
  img = loadImage ("cloud.png");
  // Vektor für die Position der Maske im Sketch
  imgPos = new PVector ();
  // Maske im Fenster zentrieren
  imgPos.x = (width - img.width) / 2;
  imgPos.y = (height - img.height) / 2;
}

void draw () {
  background (255);

  for (int i=0; i < mouseX * 2; i++) {
    // Ermittle eine zufällige Position in der Maske
    PVector pos = randomPoint (img, imgPos);
    // Zeichne ein kleines Kreuz an dieser
    drawCross (pos);
  }
}

/**
 * Funktion ermittelt rekursiv die Position eines Pixels
 * in einem gegebenen Bild, welches schwarz ist. Diese
 * Koordinaten werden mit der Bildposition (Vektor)
 * summiert und zurückgegeben.
 */
PVector randomPoint (PImage theImage, PVector thePos) {
  // Zufallsposition im Bild
  int x = (int) random (theImage.width);
  int y = (int) random (theImage.height);

  // Wenn Pixel an Position x,y schwarz ist
  if (brightness (theImage.get (x, y)) == 0) {
    // Gibt die Position als Vektor zurück
    return new PVector (thePos.x + x, thePos.y + y);
  }else{
    // Sonst versuche es erneut
    return randomPoint (theImage, thePos);
  }
}

/**
 * Funktion zeichnet ein Kreuz an dessen Mittelpunkt.
 */
void drawCross (PVector thePos) {
  line (thePos.x-1, thePos.y-1, thePos.x+1, thePos.y+1);
  line (thePos.x-1, thePos.y+1, thePos.x+1, thePos.y-1);
}

Arbeiten mit Zeitangaben

0
Filed under input, tipps

Hier ein kleines Beispiel für alle die mit chronologischer Reihung von Inhalten arbeiten. Es basiert auf dem Beitrag Twitter in Processing und stellt die letzten 200 Nachrichten eines Nutzers innerhalb der vorliegenden Zeitspanne dar.

twitter timeline

Datumsangaben & Processing
Innerhalb von Processing nutzt man für Datumsangaben die Date-Klasse. Dabei dreht es sich (schrägerweise) um die verstrichenen Millisekunden seit dem 01.01.1970 (auch UNIX Time genannt). Durch diese abstrakte Repräsentation können Zeitpunkte einfach durch Operatoren verglichen bzw. Differenzen ermittelt werden. Der aktuelle Wert ist demnach ziemlich groß und passt nicht mehr in den Wertebereich eines Integers (int). Als nächst höhrerer Datentyp werden die Millisekunden deshalb in einer Variable vom Typ long gespeichert.

Axiale Verteilung
Um einen Datensatz chronologisch auf einer Achse zu verteilenen, benötigen wir drei Informationen:

  1. Startzeitpunkt, ältester Eintrag
  2. Endzeitpunkt, jüngster Eintrag
  3. die aus beiden Zeitpunkten resultierende Zeitspanne

Im setup() durchläuft eine for-Schleife alle Twitter-Nachrichten und ermittelt den Beginn und das Ende des Zeitraumes. Dieser wird direkt nach der Schleife festgelegt und in Zeile 45 berechnet. Am Ende des setup()-Blocks werden zum Überprüfen beide Grenzen als Datum formatiert in der Konsole ausgegeben.

Startzeitpunkt und Zeitspanne dienen als Grundlage zur Verortung der einzelnen Nachrichten auf der x-Achse im Sketch. Das Verhältnis einer jeden Nachricht (Zeitraum zwischen der Veröffentlichung zum Startzeitpunk) zur gesamten Zeitspanne ergibt einen Wert zwischen 0 und 1. Dabei ist 0 der Startzeitpunkt und 1 der Moment an dem der letzte Beitrag erschien. Dieser Wert mulipliziert mit der Länge der Zeitachse ergibt die Position auf ihr. Im unteren Beispiel wird die gesamte x-Achse als Zeitleiste angesehen. Folglich wird der Faktor auf die Breite des Fensters angewendet. Im letzten Schritt wird die Textlänge der Beiträge für die Lage der Linien genutzt.

Fazit
Knackpunkt bei der Verteilung ist die Berechnung in Zeile 68, durch das Mappen der relativen Position des Zeitpunktes in der Zeitspanne auf die Repräsentation mit der Länge der Zeitachse. Da die Twitter-Nachrichten chronologisch sortiert geladen werden, hätte man die erste Schleife im setup() enfallen lassen können. Zur Vollstänigkeit haben wir trotzdem die umständliche Version gewählt.

import twitter4j.org.json.*;
import twitter4j.*;
import twitter4j.http.*;
import twitter4j.examples.*;
import java.util.List;
import java.util.Date;

List stats;    // Liste der Twitter-Einträge
long timeMax;  // time-stamp aktuellster Eintrag
long timeMin;  // time-stamp ältester Eintrag
long timeDur;  // Zeit zwischen ältestem und aktuellstem

void setup () {
  size (580, 150);
  Twitter tw = new Twitter ("Benutzername", "Passwort");

  // Startwerte der von min und max definieren.
  // Diese Werte sind unrealistisch für beide Größen.
  timeMax = 0;
  timeMin = -1;

  try {
    // Die letzten 200 Twitter-Einträge des Benutzers.
    // (muss nicht der bei 'new Twitter(' angegebene sein)
    stats = tw.getUserTimeline ("Benutzername", 200);

    // Für jeden Twitter-Eintrag ('Status')
    for (int i=0; i < stats.size(); i++) {
      Status stat = (Status) stats.get (i);

      // Zeitpunkt der Veröffentlichung
      long time = stat.getCreatedAt ().getTime ();

      // Ist der Eintrag der erste?
      if (time < timeMin || timeMin == -1) {
        timeMin = time;
      }
      // oder der letzte?
      if (time > timeMax) {
        timeMax = time;
      }
    }
    // Zeitspanne zwischen dem ersten
    // und dem letzten Eintrag in der Liste
    timeDur = timeMax - timeMin;
  }catch (Exception e) {
    println (e);
  }
  println ("start: " + new Date (timeMin));
  println ("end:   " + new Date (timeMax));
}

void draw () {
  background (40);
  stroke (255, 150);

  Status stat;  // Var. zum Ablegen eines Eintrages
  double time;  // Var. für die Zeitspannenberechnung

  // Für jeden Twitter-Eintrag ('Status')
  for (int i=0; i < stats.size (); i++) {
    stat = (Status) stats.get (i);

    // Zeitspanne im Vergleich zum ältesten Eintrag
    time = stat.getCreatedAt ().getTime () - timeMin;

    // Lage auf der x-Achse
    float x = width * (float) (time / timeDur);
    // y-Position der Linienenden, bestimmt durch Textlänge
    float y1 = height / 2 - stat.getText ().length () / 2;
    float y2 = height / 2 + stat.getText ().length () / 2;

    line (x, y1, x, y2);
  }
}

Update

0
Filed under uncategorized

Anbei das Update. Im examples Ordner findet ihr zwei kleine Beispiele für den Umgang mit Tags und Bildern, sowie die Kombination Vektoren mit Lastfm-Daten.

schöne Grüße

Twitter in Processing

2
Filed under input, tipps

Hier kurz ein paar Zeilen zum Auslesen von Twitter-Profilen mit Processing.

Installation

  1. Laded die Bibliothek twitter4j, aktueller Stand ‘twitter4j-2.0.7′.
  2. Entpackt die zip und benennt die Datei ‘twitter4j-2.0.7.jar’ in ‘twitter4j.jar’ um.
  3. Geht in euren Processing-libraries Ordner und erstellt dort zwei Ordner: ‘Processing/libraries/twitter4j/library/’.
  4. Kopiert die gerade in ‘twitter4j.jar’ umbenannte Datei in den angelegten Ordner library.

Mit diesem ‘Trick’ kann das toolkit, zur Kommunikation mit twitter, in Processing geladen werden. Im üblichen Menü ‘Sketch’ -> ‘Import Library…’ erscheint nun ‘twitter4j’ neben allen weiteren Processing libraries. Mit einem Klick werden euch alle verfügbaren Klassen importiert.

Umgang
Der Umgang mit der library bedarf ein paar neuer Befehle. Try-Catch ist zum Ausführen von Prozessen die auch gerne mal nicht funktionieren können. In diesem Fall das Laden der Daten via Internet. Um direkt einen Plan-B anzugeben, gibt es den Catch-Block. Weiterhin werden die Ergebnisse in sog. Listen (ähnlich den ArrayList(s)) gespeichert. Damit Processing damit umgehen kann, muss diese Klasse ebenfalls am Anfang importiert werden. Hier ein Beispiel:

UPDATE: 08/06/2009

import twitter4j.org.json.*;
import twitter4j.*;
import twitter4j.http.*;
import twitter4j.examples.*;

// Liste wird gebraucht um timeline-
// Einträge zu speichern
import java.util.List;

// Liste an Twitter-Stats wird global abgelegt
List stats;

void setup () {
  // Erzeuge die 'Schnittstelle' zu twitter mit
  // eigenem Benutzer/Passwort
  Twitter tw = new Twitter ("Benutzername", "Passwort");

  // try-catch Kombination zum Abfangen von Fehlern
  try {
    // Lade die letzten 200 Einträge aus der
    // Twitter-timeline des users
    stats = tw.getUserTimeline ();

    // Für jede nachricht in der timeline
    for (int i=0; i < stats.size(); i++) {
      // Type-casten der Nachrichten als
      // Instanzen der Klasse 'Status'
      Status stat = (Status) stats.get (i);
      println (stat.getText ());
    }
  }catch (Exception e) {
    println (e);
  }
}

void draw () {
  // crazy stuff
}

Das JavaDoc enthält den kompletten Funktionsumfang (zum Start reicht aber erst mal die Twitter-Klasse der library).

Data Flow

0
Filed under cc1, cc2, input

Neben großartigen Schriften veröffentlichen »Die Gestalten« auch gute Bücher

50 Great Examples of Data Visualization

0
Filed under cc1, cc2, input

50