Processing‎ > ‎CreativeCoding‎ > ‎

Events

http://sites.prenninger.com/arduino-uno-r3/processing/creativecoding/events

http://www.linksammlung.info/

http://www.schaltungen.at/

                                                                                            Wels, am 2015-01-12

BITTE nützen Sie doch rechts OBEN das Suchfeld  [                                                              ] [ Diese Site durchsuchen]

DIN A3 oder DIN A4 quer ausdrucken
**********************************************************************************
DIN A4  ausdrucken
*********************************************************


06. Events


1. Mausinteraktion

Bisher haben wir um den Programmfluss zu steuern zwei Funktionsblöcke kennengelernt:
void setup() als statischen Modus der nur einmal ausgeführt wird und dem Befehle nacheinander einmal ausgeführt werden
void draw(), das solange wiederholt wird, bis der Benutzer das Programm unterbricht.
Um verschiedene Tastatureingaben oder Mausbefehle (man spricht auch von Tastatur oder Maus Events) abzufragen gibt es neben der der if() abfrage von Processing eigens zur Verfügung gestellte Funktionen.
Diese Funktionen werden nach dem draw() block geschrieben.
Den Abfrage ob die Maus gedrückt wurde haben wir bisher mit

if (mousePressed) {
  //tue etwas
}

kennengelernt.

Um komplexere Programme zu schreiben und den Programmfluss sinnvoll und übersichtlich zu gestalten bedienen wir uns nun der Funktion:

void mousePressed () {
  //tue etwas
}

Wie alle Funktionen wird auch diese mit void eingeleitet und von geschweiften Klammern umrahmt.
Diese Funktion wird einmal aufgerufen, nachdem ein Mausknopf gedrückt wurde und unterscheidet sich dadurch durch die if(mousePressed) Abfrage, da diese, solange sie im draw() loop steht immer wieder durchlaufen wird.

06.1.1 mousePressed()



//Processing-Sketch: Punkte mit der Maus setzen_1a.pde

void setup () {
  size(350, 100);   //setze die gröe der Zeichenfläche auf 100 *100 Pixel
  background(255);  // lösche die Zeichenfläche und fülle sie mit weiß
  smooth();         //antialiasing aktivieren
}

void draw () {      // draw muss existieren damit unser programm am Leben bleibt
}

void mousePressed() {
  noStroke();       // Outline deaktivieren
  fill(0, 125);     // Füllfarbe auf schwarz & semitransparent setzen
  ellipse(mouseX, mouseY, 10, 10);    // Kreis an der Mausposition zeichnen
}

Man kann nicht nur abfragen, ob die Maus gedrückt wurde, sondern auch auf die anderen Stati können wir wie folgt zugreifen:
  • mousePressed() die Maustaste wurde gedrückt
  • mouseReleased() die Maustaste wurde losgelassen
  • mouseMoved() die Maus wird bewegt & es ist kein Knopf gedrückt
  • mouseDragged() der Mausknopf ist gedrückt und die Maus wird dabei bewegt
Auch für diese Stati müssen wir natürlich Funktionen festlegen:


06.1.2 mousePressed() & mouseReleased()



//Processing-Sketch: Punkte_Rechteck mit der Maus setzen_1a.pde

void setup () {
  size(400,100);   // setze die größe der Zeichenfläche auf 300x100 Pixel
  background (255); // lösche die Zeichenfläche und fülle sie mit weiss
  smooth ();        // Antialiasing aktivieren
}

void draw() {
}

void mousePressed() {                // die Maustaste wurde gedrückt
  noStroke ();                       // Outline deaktivieren
  fill (0, 125);               // Füllfarbe auf schwarz & semitransparent setzen
  ellipse (mouseX, mouseY, 10, 10);  // Punkt an der Mausposition zeichnen
}

void mouseReleased() {             // die Maustaste wurde losgelassen
  noFill ();                       // Füllfarbe deaktivieren
  stroke (255,0,0, 125);         // Strichfarbe auf rot & semitransparent setzen
  rectMode (CENTER);               // Rechteck von der Mitte aus zeichnen
  rect (mouseX,mouseY, 15,15);   // Rechteck an der Mausposition zeichnen
}




06.1.3 mousePressed() & mouseReleased() & mouseMoved()

Nun soll noch ein Punkt an den Maus-X & Maus-Y Koordinaten gezeichnet werden, sobald die Maus bewegt wurde, aber keine Taste gedrückt ist.



//Processing-Sketch: Punkte_Rechteck&Mausspur_1a.pde

void setup () {
  size(350, 100);    // setze die größe der Zeichenfläche auf 350x100 Pixel
  background (255);  // lösche die Zeichenfläche und fülle sie mit weiss
  smooth ();         // Antialiasing aktivieren
}

void draw () {
}

void mousePressed () {               // die Maustaste wurde gedrückt
  noStroke ();                       // Outline deaktivieren
  fill (0, 125);               // Füllfarbe auf schwarz & semitransparent setzen
  ellipse (mouseX,mouseY, 10,10);  // Punkt an der Mausposition zeichnen
}

void mouseReleased() {            // die Maustaste wurde losgelassen
  noFill ();                      // Strichfarbe deaktivieren
  stroke (255,0,0, 125);        // Strichfarbe auf rot & semitransparent setzen
  rectMode (CENTER);              // Rechteck vom Mittelpunkt aus zeichnen
  rect (mouseX,mouseY, 15,15);  // Rechteck an der Mausposition zeichnen
}

void mouseMoved() {         // mouseMoved() die Maus wird bewegt & es ist kein Knopf gedrückt
  stroke (0,255,255);       // Strichfarbe auf cyan setzen
  point (mouseX, mouseY);   //Punkt an der Mausposition zeichnen
}


06.1.4 mousePressed() & mouseReleased() & mouseDragged()


Im nächsten Beispiel soll der Punkt nur dann gezeichnet werden, wenn der Mausknopf gedrückt und die Maus dabei bewegt wird.
Dazu müssen wir lediglich den mouseMoved() Block in mouseDragged() umbenennen:


//Processing-Sketch: Punkt Mausspur Rechteck_1a.pde

void setup() {
  size(350, 100);    // setze die größe der Zeichenfläche auf 350x100 Pixel
  background (255);  // lösche die Zeichenfläche und fülle sie mit weiss
  smooth ();         // Antialiasing aktivieren
}

void draw () {
}

void mousePressed () {
  noStroke ();                      // Outline deaktivieren
  fill (0, 255, 0);                 // Füllfarbe grün setzen
  ellipse(mouseX, mouseY, 10, 10);  // Punkt an der Mausposition zeichnen
}

void mouseReleased () {
  noFill ();                      // Strichfarbe deaktivieren
  stroke (255,0,0);             // Strichfarbe auf rot
  rectMode (CENTER);              // Rechteck vom Mittelpunkt aus zeichnen
  rect (mouseX,mouseY, 15,15);  // Rechteck an der Mausposition zeichnen
}

void mouseDragged() {       //mouseDragged() der Mausknopf ist gedrückt und die Maus wird dabei bewegt
  stroke (0);               // Strichfarbe auf schwarz setzen
  point (mouseX, mouseY);   // Punkt an der Mausposition zeichnen
}


2. Tastaturinteraktion

Genau wie mit der Maus können auch Tastatur Events abgefragt werden.
Dabei wird jeder Tastendruck durch die Funktion

keyPressed
() (Taste wurde gedrückt)
keyReleased
() (Taste wurde losgelassen) registriert.


Wie oben beschrieben wird der Code in dem keyPressed() Block einmal ausgeführt, wenn eine Taste gedrückt wurde.

06.2.1 keyPressed()


//Processing-Sketch: Tastendruck keyPressed_1a.pde

void setup () {
  size(300, 200);    // setze die größe der Zeichenfläche auf Breite, Höhe
  background (235);  // lösche die Zeichenfläche und fülle sie mit hell-grau
  smooth();          // Antialiasing aktivieren
}

void draw () {
}

void keyPressed () {
  noStroke();                                     // Outline deaktivieren
  fill(0,255,255, 125);                         // Füllfarbe auf cyan & semitransparent setzen
  //rect(random(height), random(width), 20, 20);  // Quadrat an einer zufälligen Position in der Zeichenfläche zeichnen
  rect(random(width), random(height), 20, 20);    // Quadrat-Postition Breite Höhe
}



06.2.2 keyPressed() 2
Im keyPressed() Block ist es zusätzlich möglich abzufragen, ob die Taste e ODER r gedrückt wurde:


//Processing-Sketch: Tastendruck Taste e ODER r_1a.pde

void setup () {

  size(150, 150);    // Setze die größe der Zeichenfläche auf 100x100 Pixel
  background(225);   // lösche die Zeichenfläche und fülle sie mit hell-grau
  smooth();          //antialiasing aktivieren
}

void draw() {
}

void keyPressed() {
  if (key == 'e') {     // Abfrage ob die Taste 'e' gedrückt wurde
    noStroke ();        // Outline deaktivieren
    fill(0, 125); // Füllfarbe auf schwarz & semitransparent setzen
    ellipse(random(height), random(width), 10, 10);     // Punkt an einer zufälligen Position in der Zeichenfläche zeichnen
  }

  if (key == 'r') {          // Abfrage ob die Taste 'r' gedrückt wurde
    noFill ();               // Füllfarbe deaktivieren
    stroke (255,0,0, 125); //Strichfarbe auf rot & semitransparent setzen
    rect (random (height), random (width), 15, 15);     //Rechteck an einer zufälligen Position in der Zeichenfläche zeichnen
  }
}



06.2.3 keyPressed() 3

Neben den Buchstabentasten kennt Processing soggenannte Konstanten für die Abfrage spezieller Tasten:
 BACKSPACE,   TAB,   ENTER,   RETURN,   ESC,    DELETE,    UP,    DOWN,    LEFT   RIGHT


//Processing-Sketch: Abfrage Steuertasten_1a.pde

void setup() {  
  size(100, 100);    // Setze die Größe der Zeichenfläche auf 100x100 Pixel
  background(200);   // lösche die Zeichenfläche und fülle sie mit hell-grau
  smooth();
}
 
void draw() {        // Antialiasing aktivieren
}
 
void keyPressed() {
  if (key == 'e') {  // Abfrage ob die Taste 'e' gedrückt wurde
    noStroke();      // Outline deaktivieren
    fill (0, 125);   // Füllfarbe auf schwarz & semitransparent setzen
    ellipse(random (height), random (width), 10, 10);  // Punkt an einer zufälligen Position in der Zeichenfläche zeichnen
  }
 
  if(key == 'r') {           // Abfrage ob die Taste 'r' gedrückt wurde
    noFill ();               // Füllfarbe deaktivieren
    stroke (255,0,0, 125);   //Strichfarbe auf rot & semitransparent setzen
    rect (random (height), random (width), 10, 10); //Rechteck an einer zufälligen Position in der Zeichenfläche zeichnen
  }
  
  if (key == BACKSPACE) {background(255,0,0);}  // Taste Pfeil-links         Rot
  if (key == TAB) {background(0,255,0);}        // Taste Pfeil-links/rechts  Grün
  if (key == ENTER) {background(0,0,255);}      // Taste CR                  Blau    
  if (key == RETURN) {background(255,255,0);}   // Taste CR                  yellow
  if (key == ESC) {background(0,255,255);}      // Taste Esc Grafik löschen  cyan
  if (key == DELETE) {background(255,0,255);}   // Taste Entf                 magenta 
}



*********************************************************

07. Variablen 2

Variablen und ihre Sichtbarkeit

1. Gültigkeit von Variablen


Erläutert den Unterschied zwischen lokalen und globalen Variablen und warum lokale Variablen dabei helfen, Fehler vorzubeugen.

1. Gültigkeit von Variablen

Um die Verwendung von Variablen zu strukturieren gelten diese stets nur für einen bestimmten Bereich des Programms - einem Block.
Blöcke werden durch geschweifte Klammern gebildet.
Das bedeutet, dass setup(), draw(), mousePressed(), etc. als auch if-Abfragen und for-Schleifen eigene Blöcke bilden.
Das folgende Bild zeigt die Blockstruktur an einem Beispiel.
Variablen können in all diesen Blöcken deklariert und verwendet werden, und sind von dort an nur innerhalb des selben Blocks, sowie Blöcken eines niedrigeren Levels innerhalb dieses Blocks verfügbar.
Dieses Konzept nennt man »Gültigkeit von Variablen«.

//Processing-Sketch: Globale Variable_1a.pde

int zahl = 20;  // Globale Variable

void setup() {
  size(200, 200);
  background(200);
  ellipse(100, 100, zahl, zahl);
}

void draw() {
}

void mousePressed() {
  ellipse(mouseX, mouseY, zahl, zahl);
}

Hier ist zahl eine sogenannte Globale Variable, da sie im obersten Block initialisiert wurde und demzufolgen in allen unterliegenden Blöcken verfügbar ist.
"Lokale" Variablen sind demzufolge alle Variablen, die nicht global und somit in einigen Teilen des Programms nicht verfügbar sind.

//Processing-Sketch: Lokale Variable_1a.pde

void setup() {
  int zahl = 5;
  println(zahl); // nur im Bereich setup gültig
}

void draw() {
  println(zahl); // Fehlermeldung - Cannot find anything named "zahl"
}

Globale Variablen können also für alle Funktionen des gesamten Programms verwendet werden,
z.B. um verschieden Parameter im Programmverlauf mitzuzählen.

//Processing-Sketch: Globale Variable_1a.pde

int count = 0;

void setup() {
  size(110, 110);
  background(0);
  stroke(255);
}

void draw() {
  background(0);
  count = count + 1;
  line(0, count, 100, count);

  if (count == 100) {
    count = 0;
  }
}


Lokale Variablen werden vorzugsweise bei allen Aufgaben verwendet, die nur in einem kleinen Teil des Programms stattfinden und demzufolge in anderen Teilen nicht benötigt werden. Die Verwendung von lokalen Variablen wann immer es möglich ist, gehört zu einem guten Programmierstil und hilft Fehler zu vermeiden.
Desweiteren haben lokale Variablen den Vorteil, das Namen in unterschiedlichen Blöcken mehrfach verwendet werden können.

//Processing-Sketch: Lokale Variable_1a.pde

void setup() {
  size(200, 200);
}

void draw() {
  int zahl = 4;
  ellipse(random(200), random(200), zahl, zahl);
}

void mousePressed() {
  int zahl = 20;
  ellipse(mouseX, mouseY, zahl, zahl);
}




*********************************************************

08. Freiformen

Zeichnen komplexer Formen

Führt die Befehle vertex() und curveVertex() für das Zeichnen komplexerer Vektor-basierter Formen ein und erklärt die unterschiedlichen Zeichenmodi die beim Zeichnen von Pfaden und geschlossenen Formen in Processing zur Verfügung stehen.

1. Vertex

Bereits aus Grafikprogrammen wie Photoshop und Illustrator ist uns das Zeichnen von Pfaden bekannt.
Durch das Aneinanderreihen von Punkten legt man eine Abfolge von Linien fest, welche als Außenhaut der Form fungieren.
In Processing werden diese Punkte durch den Aufruf von vertex() erzeugt.
Begonnen und beendet wird das Zeichnen mit beginShape() und endShape():
  • beginShape() der Aufruf leitet das Zeichnen einer Freiform ein.
  • Parameter benötigt dieser Befehlt nicht.
  • Durch die Angabe von POINTS, LINES, TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP, QUADS und QUAD_STRIP kann die resultierende Form eingeschränkt werden(keine vollwertige Freiform mehr). beginShape()

beginShape ();        // beginne eine Freiform
beginShape (POINTS);  // beginne nur Punkte zu zeichnen, die aber nicht zu verbinden
beginShape (LINES);   // beginne nur Linien zu zeichnen, die resultierende Fläche aber nicht zu füllen


  • endShape() der Aufruf beendet das Zeichnen der Freiform. Diese setzt sich aus allen zwischen beginShape() und endShape() ausgeführten Zeichenbefehlen (z.B. vertex()) zusammen. Wenn bei beginShape() ein Parameter verwendet wurde, sollte dieser hier ebenfalls angegeben werden. endShape()

    endShape ();// beendet das zeichnen einer Freiform
  • vertex() erweitert den formbeschreibenden Pfad um einen neuen Ankerpunkt.
  • Da wir uns in einer zweidimensionalen Zeichenfläche bewegen geben wir die Position durch x und y Koordinate an. vertex()

    vertex (30, 40);    // vertex (x-koordinate, y-koordinate)
    vertex (90, 20);
    vertex (60, 70);
    ...
Processing teilt den Ablauf des Zeichnens von Freiformen demnach in drei Schritte:
  1. Einleiten: Mittels beginShape() teilen dem Programm mit, das wir gleich eine Form zeichnen werden. Alle nun folgenden Punkte sollen zu einer Form bzw. Umrandung, abhänig vom angewendeten Modus, zusammengeführt werden. Modi wie TRIANGLE_FAN, TRIANGLE_STRIP, etc. stellen zu Beginn große Fehlerquellen dar. Jegliche Form kann auch ohne Angabe solcher Parameter erzeugt werden.
  2. Zeichnen: In diesem Teil folgt die Formulierung der Freiform. Dies geschieht durch die Angabe der Ankerpunkte - Gestaltung der Outline. In diesem Abschnitt dürfen keine Aufrufe der bisherigen Zeichenbefehle erfolgen! Erst nach dem Schließen der Form können ellipse(), rect() wieder zur Verwendung kommen.
  3. Beenden: Processing bekommt nun durch endShape() die Anweisung mit allen, seit beginShape() angegebenen Punkten, eine Umriss zu generieren. Je nach vorheriger Angabe von fill() und stroke() ist dieser gefüllt bzw. sichtbar. Der Einsatz von ellipse(), rect(), etc. ist nun wieder gestattet.

08.1.1 Freiform 1

In diesem Beispiel wird eine durch fünf Punkte beschriebene Form gezeichnet.
Sie ist axial symmetrisch zur y-Achse (Spiegelachse befindet sich auf y=100, die Hälfte der Zeichenfläche) und weiß gefüllt. Rechts, neben dem gerenderten Ergebnis, ist eine Grafik, welche die Lage der formbeschreibenden Punkte verdeutlicht.
Wir beginnen oben-links mit dem Punkt (20, 40) und arbeiten uns Schritt für Schritt an der Outline entlang.
Jeder Punkt wird dabei durch den Aufruf von vertex(x,y) definiert.


//Processing-Sketch: 08.1.1 Freiform 1_1a.pde

size(220, 220);   // Größe der Zeichenfläche festlegen
smooth ();        // Kantenglättung aktivieren
beginShape ();    // Zeichnen einleiten
vertex (20, 40);  // Freiform durch Angabe der Vertexpunkte beschreiben (muss nicht geschlossen sein)
vertex (60, 150);
vertex (110, 190);
vertex (160, 150);
vertex (200, 40);
endShape ();       // Zeichnen beenden




08.1.2 Freiform 2
Mit dem im Vorherigen angesprochenen Parameter des beginShape() Befehls legt man die Art der Verbindungen zwischen den Vertexpunkten für den gesamten Zeichenprozess fest. Wenn die Initialisierung mit beginShape(LINES) durchgeführt wurde, werden immer zwei aufeinander folgende Punkte zu einer Linie verbunden.
TRIANGLES
erzeugt aus drei Punkten ein Dreieck - ignoriert jedoch in unserem Beispiel den vierten Punkt;
QUADS generiert ein geschlossenen Viereck.
Alle oben abgebildeten Beispiele wurden auf Basis des unteren Scripts erstellt.
Lediglich der Zeichenmodi (im Beispiel LINES) wurde ausgetauscht.


//Processing-Sketch: 08.1.1 Freiform 2_1a.pde

smooth ();  // Kantenglättung aktivieren
beginShape (LINES);  // Zeichnen Einleiten 
// Zeichnen der vier Vertexpunkte
vertex (20, 20); // Linie a, Punkt 1 vertex (40, 80); // Linie a, Punkt 2 vertex (80, 80); // Linie b, Punkt 1 vertex (60, 20); // Linie b, Punkt 2 endShape(); // Zeichnen Beenden


            

2. Curve Vertex

Kurven werden wie die oben kennengelernte Vertexoutline durch eine Reihung von Punkten bestimmt.
Jedoch werden die Punkte nicht geradlinig verbunden.
Beeinflusst von allen Vertexelementen bewegt sich das "Zeichenwerkzeug" von Anfangs- zu Endpunkt und hinterlässt einen weichen, nicht kantigen, Pfad.
Jeder Vertexpunkt wird dabei vom Pfad geschnitten.
Processing benötigt mindestens vier Punkte um eine Kurve abzubilden.
Durch die Interpolation müssen Anfangs- und Endpunkt doppelt angegeben werden.
Anderenfalls ist die Darstellung verschoben.
  • curveVertex() definiert mit x und y-Koordinate einen Kontrollpunkt der Kurve.
  • Mindestens vier dieser Punkte müssen zwischen beginShape() und endShape() stehen. 
  • curveVertex()

08.2.1 Kurve



Bezogen auf das Beispiel "Freiform 1" sind nun die vertex() Aufrufe durch curveVertex() ersetzt worden.
Ebenfalls haben wir Start- und Endpunkt dupliziert.
Wir erhalten, wie in der bekannten Version, einen Fläche - mit einer abgerundeten Outline.

//Processing-Sketch: 08.2.1 Kurve_1a.pde

size(220, 220); // Größe der Zeichenfläche festlegen
smooth (); // Kantenglättung aktivieren

beginShape ();  // Zeichnen einleiten
// Freiform durch Angabe der Kurvenkontrollpunkte beschreiben
curveVertex (20, 40);
curveVertex (20, 40);
curveVertex (60, 150);
curveVertex (110, 190);
curveVertex (160, 150);
curveVertex (200, 40);
curveVertex (200, 40);
endShape ();  // Zeichnen beenden

08.2.2 Kurve modifizieren



Im folgenden Beispiel werden drei Punkte einer Kurve definiert.
Um keine fehlerhafter Darstellung zu erhalten sind Punkt 1 (0,0) und Punkt 3 (100, 100) doppelt angegeben.
Modifiziert wird der Verlauf der Kurve durch die Position der Maus im Sketchfenster.
Auf Grundlage derer Koordinaten wird der mittlere Punkt gesetzt.

//Processing-Sketch: 08.2.2 Kurve mit Maus modifizieren_1a.pde

void setup() {
  smooth ();        // Kantenglättung aktivieren
  noFill();         // Füllung deaktivieren
}

void draw() {
  background(255);  // Leere die Zeichenfläche
  beginShape();     // Zeichnen Einleiten
  curveVertex(0, 0);
  //curveVertex(0, 0);
  curveVertex(mouseX, mouseY);
  curveVertex(100, 100);
  curveVertex(100, 100); // um keine fehlerhafter Darstellung zu erhalten doppelt angegeben
  endShape();            // Zeichnen beenden
}



08.2.3 dynamische Pfaderzeugung



Das dritte Beispiel veranschaulicht neben der Verwendung des Befehls curveVertex() die Einbindung einer for-Schleife, sowie der random() Funktion.
Im globalen Bereich werden zwei elementare Variablen unseres Programms festgelegt:
  • step repräsentiert den Abstand zwischen den einzelnen Kurvenkontrollpunkten auf der x-Achse - Weg welcher von Schleifendurchgang zu Schleifendurchgang durch Multiplikation mit der Zählvariable i variiert.
  • points steht für die Anzahl an Kontrollpunkten, welche die Kurve beschreiben. int da es nur eine ganze Menge an Punkten geben kann.
Nach der Initialisierung im setup() Block setzen wir noch den Inhalt der Variable step.
Dazu teilen wir die Breite der Zeichenfläche durch die Anzahl an Punkten minus eins.
Wir erhalte die nötige Distanz zwischen den Kontrollpunkten für eine gleichmäßige Verteilung.
Im draw() Block leeren wir das Sketchfenster zu Beginn.
Anschließend weisen wir Processing mit dem Aufruf von beginShape() an aus alle folgenden Punkte ein grafisches Element zu erzeugen.
Folgend werden die benötigten Punkte in einer for-Schleife generiert.
Diese läuft beginnend von der linken Seite der Zeichenfläche bis zur Rechten - startet dann wieder von Neuem. Innerhalb wird jeweils die x und y Koordinate für den Punkt der aktuellen Position berechnet.
Der y-Wert ist dabei zufällig (in den Grenzen der Mausposition) beeinflusst.
Um den Ersten und Letzten Punkt doppelt anzugeben gibt es für beide Fälle jeweils eine if Bedingung.
Am Ende schließen wir das Erstellen unseres Elementes mit dem Befehl endShape() ab.


Lege die beiden globalen Variablen "step" und "points" fest.
Sie stehen außerhalb von setup bzw. draw und sind deshalb überall im Programm  erreichbar.
Der Inhalt von step wird im setup-Block gesetzt.
Bewege die Maus hoch und runter um die Amplitude der horizontalen Kurve zu ändern.



//Processing-Sketch: 08.2.3 dynamische Pfaderzeugung_1a.pde

float step;
int points = 15;     // führe diese Schleife für die Anzahl von "points" aus (15 mal)

void setup () {
  size (500, 140);   // Größe der Zeichenfläche definieren
  smooth ();         // Kantenglättung aktivieren
  frameRate (5);     // Anzahl der Einzelbilder pro Sekunde auf fünf beschränken

// lege die Schrittweite pro for-Schleifen-durchgang auf der x-Achse fest. Abstand der Kurvenkontrollpunkte auf der x-Achse.   step = float (width) / (points - 1); } void draw () {   background (255); // lösche den Inhalt der Zeichfläche   beginShape (); // Zeichnen einleiten   for (int i=0; i < points; i = i + 1) { // führe diese Schleife für die Anzahl von "points" aus (15 mal) – Kontrollpunkte der Kurve     float posx = i * step; // berechne die x-Position des Kurvenpunktes     float posy = height / 2 + random (-mouseY, mouseY); // berechne die y-Position des Kurvenpunktes     curveVertex (posx, posy); // füge den Punkt unserer Fläche hinzu     if (i == 0) { // füge den ersten Punkt doppelt ein       curveVertex (posx, posy);     }     if (i == points - 1) { // füge den letzten Punkt doppelt ein       curveVertex (posx, posy);     }   }   endShape (); // beende das Zeichnen der Freiform }



*********************************************************

09. Bilder

Arbeiten mit Bildern zur Darstellung, Manipulation und als Grundlage zu Zeichnen weiterer Formen



Nach einem weiterführenden Teil zu Farben in Processing, in dem u.a. die Extrahierung von Farben aus Pixeln erklärt wird, beschäftigt sich diese Lesson mit dem Laden, Darstellen und Verändern von Bildern in Processing.

Anhand mehrerer, visueller Beispiele wird danach die Verwendung von Bildern als Datengrundlage für das Zeichnen anderer Formen eingeführt.

1. Farben II

In der ersten Lesson[1] wurde das Festlegen von Farbwerten für die Füllung und Umrandung von Elementen vorgestellt.
Mittels der Befehle fill() und stroke() definieren wir seither, in unterschiedlichen Parameterkombinationen, die Anteiligkeit des Rot-, Grün-, Blau- und Alphakanals.
Die Angabe aller drei bis vier Werte in den oben genannten Befehlen limitiert unser Arbeiten, da wir immer alle drei (bzw. vier) kennen müssen.
Stellen wir uns vor das wir von einer beliebigen Farbe den Rotanteil um 40 erhöhen möchten - fill() erlaubt dies aber nur wenn wir auch die beiden anderen Kanäle (grün und blau) nennen können. Processing bietet für das Ablegen aller vier Werte den Datentyp color():

color rot = color (255,0,0); // volles Rot
color grün = color (0,255,0); // volles Grün
color blau = color (0,0,255, 150); //  Blau
semitransparent

Hinter den Variablen rot und blau befindet sich eine komplexe Zahlenkombination, welche mit folgenden Befehlen dekodiert werden kann:
  • alpha() auf die Farbe anzuwendende Transparenz zwischen 0-255. alpha()
  • blue() Blauanteil der Farbe zwischen 0-255. blue()
  • brightness() brightness()
  • green() Grünanteil der Farbe zwischen 0-255. green()
  • red() Rotanteil der Farbe zwischen 0-255. red()
  • saturation() Sättigung der Farbe zwischen 0-255. saturation()
Obacht ist geboten, denn all diese Befehle geben eine Gleitkommazahl zurück.
Wenn das Resultat in einer Variable abgelegt werden soll, hat diese vom Typ float zu sein.
Den Versuch das Speichern auf eine int Variable vorzunehmen wird Processing mit einer Fehlermeldung vergelten.
Das oben angesprochene Problem können wir nun mittels der kennengelernten Befehle lösen:

// Erhöhen des Rotanteils einer beliebigen Farbe "c" um 40
float r = red (c) + 40;
float g = green (c);
float b = blue (c);
c = color (r, g, b);

Folgendes passiert bei der Durchführung dieser Zeile:
Wir greifen auf die Variable vom Datentyp color zu und modifizieren den Anteil des Rotwertes - Grün und Blau bleiben gleich.
Dabei wird mit color() eine neue Farbe generiert; c wird überschrieben.
Als Parameter für das Erzeugen der neuen Farbe greifen wir aber auf die Originalwerte von c zurück; modifizieren dabei den Rotanteil.


09.1.1 Datentyp color




Auf Mausklick wird in diesem Beispiel die Anteiligkeit des Rot in der globalen Variable c verändert.
Im setup() werden zu Beginn alle drei Kanäle definiert, Rot in dem Fall 0.
Während im draw() permanent der Hintergrund mit der Farbe c gefüllt wird, greift der Block mousePressed() in die Farbgebung ein.

//Processing-Sketch: 09.1.1 Datentyp color mit Mausklick ändern_1a.pde

color c;        // Globale Farbvariable "c" ist überall im Programm erreichbar

void setup () {
  c = color (0, 150, 255);   // einmaliges setzen der Anteile für grün und blau
}

void draw () {
  background (c);  // permanentes Zeichnen des Hintergrunds mit der aktuellen Farbe
}

void mousePressed () {     // führe einmalig pro Mausklick aus
  float r = red (c) + 40;  // Auslesen der Farbkanäle und Erhöhung des Rotanteils
  float g = green (c);
  float b = blue (c);
  if (r > 255) {           // Überprüfe ob der Rotanteil nicht zu hoch wird
    r = 0;
  }
  c = color (r, g, b);     // setze die Anteile von "c" neu
  println ("Rot: " + r);   // Ausgabe im Nachrichtenfenster zur Überprüfung
}



2. Pixelbilder in Processing verwenden

2.1 Abbilden

In Processing können Bilder geladen, dargestellt und auf komplexe Weise modifiziert werden.
Um ein Bild zu laden benötigen wir den Datentyp PImage
Genau wie Ganzzahlen in dem Variablentyp int und Flieskommazahlen im float abgespeichert werden, werden Bilder in dem Variablentyp PImage gespeichert.
Bevor wir Bilder im Sketchfenster anzeigen können, müssen wir sie mittels der Funktion loadImage() laden.
Dabei ist es WICHTIG die Dateiendung ( *.jpg   *.png   *.gif ) mit einzubeziehen und das Ganze in Anführungszeichen zu setzen ( "meinBild.jpg" ).
Um anschliessend Bilder im Sketchfenster anzuzeigen bedarf es des image() Aufrufs.
Ihm wird das Bildobjekt und die x,y Koordinaten zur Positionierung mitgegeben.
Ausgerichtet wird das Bild auf der Zeichenfläche wie ein mit rect() gezeichnetes Rechteck.
Grundsätzlich befindet sich der Ursprung oben links, kann aber mittels imageMode() auf das Zentrum verschoben werden.
  • image() darstellen eines Pixelbildes an einer durch x und y Koordinate angegebenen Position.
  • Zwei weitere optionale Parameter erlauben das Festlegen der Größenverhältnisse (wenn nicht angegeben werden die Originalwerte benutzt). image()
    PImage img;
    ...
    image (img, 0, 0);
  • imageMode() legt den Punkt fest an welchem die Position ausgerichtet wird.
  • Es besteht die Wahl zwischen CORNER, CORNERS und CENTER. imageMode()
    imageMode (CENTER); // Zentrum des Bildes
    imageMode (CORNER); // obere linke Ecke des Bildes
  • loadImage() läd ein Bilddokument aus dem data-Ordner (dieser Ordner muss sich im Sketch-Ordner befinden).
  • Das Resultat sollte immer einer PImage Variable zugewiesen werden. loadImage()
    PImage img = loadImage ("test.jpg");
    image (img, 0, 0);

WICHTIG:
Alle Inhalten die in Processing verwendet werden sollen (z.B. Bilder) müssen sich in einem Ordner namens "data", im jeweiligen Sketchordner, befinden.
Dieser Ordner wird nicht automatisch mit dem Erstellen eines neuen Sketches angelegt.
Navigiere über den Explorer  in den Ordner des aktuellen Projektes und lege den Ordner "data" an.
Alternativ kann eine Datei über MENU > Sketch >  Add File > Bild.jpg zum Programm hinzugefügt werden.
Hierbei legt Processing selbst den "data" Ordner im Projekt Ordner an.



09.2.1.1 Bild laden/darstellen




Dieses Beispiel beinhaltet zwei der drei oben aufgeführten Befehle.
Wir erzeugen ein Objekt "img" und weisen ihm das Resultat unseres Aufrufs zum Bildladen zu("img" beinhaltet nun alle Bilddaten).
In der nächsten Zeile rufen wir den image() Befehl auf und teilen Processing mit das geladene Bild an der Position 0,0 im Sketchfenster abzubilden.
Da unser simples Programm keinen setup() oder draw() Block besitzt ist dies eine einmalige Sache.

//Processing-Sketch: 09.2.1.1 Bild laden/darstellen_1a.pde

// Variable "meinBild" zum halten des Bildes festlegen. Bild hinein laden.
PImage meinBild = loadImage ("Drehspul-Weitwinkel GOSSEN Skalen 122x75 (100 200 500mV)NEU_1a.jpg");  

size (715, 442);    // Zeichenfläche auf Größe des zu ladenden Bildes festlegen

//image (meinBild, 0, 0);  // Bild mittels image() Befehl an der Position 0,0 (oben links) abbilden.
image (meinBild, 20, 20, width-40, height-40);  // Bild einpassen


2.2 Bilder modifizieren

Bilder werden mit der tint() Funktion eingefärbt.
Diese funktioniert genauso wie wir es von fill() & stroke() kennen, bezieht sich aber nur auf Pixelbilder.
tint (Rot, Grün, Blau, Alpha);
Alle anschliessend dargestellten Bilder werden eingefärbt bis der Befehl noTint() ausgeführt wird.

09.2.2.1 Bilder einfärben


//Processing-Sketch: 09.2.2.1 Bilder einfärben_1a.pde

PImage meinBild;    // Variable "meinBild" zum halten des Bildes festlegen. Bild hinein laden.
size (715, 442);    // Zeichenfläche auf Größe des zu ladenden Bildes festlegen
meinBild = loadImage ("Drehspul-Weitwinkel GOSSEN Skalen 122x75 (100 200 500mV)NEU_1a.jpg");
tint (255, 228, 196);                               //Bild mit Farbe "bisque" einfärben
image (meinBild, 20, 20, width-40, height-40);      // Bild einpassen
noTint ();                                          //Einfärbung deaktivieren
image (meinBild, 300, 190, width-310, height-200);  // Bild mittels image() Befehl an der Position abbilden.



09.2.2.2 Bilder mittels color() einfärben
Um mehrere Farben zu benutzen können wir uns der Farbwert Variable color() bedienen und so mehrere Farbwerte abspeichern.




//Processing-Sketch: 09.2.2.2 Bilder mittels color einfaerben_1a.pde

color yellow = color (220, 214, 41);
color green = color (110, 164, 32);
color red = color (255, 0, 0);

PImage meinBild; // Variable "meinBild" zum halten des Bildes festlegen. Bild hinein laden.
size (600, 400);    // Zeichenfläche auf Größe des zu ladenden Bildes festlegen
meinBild = loadImage ("Voltmeters_1a.jpg");

tint (yellow);                       //Bild mit Farbe "yellow" einfärben
image (meinBild, 0, 0);  // Bild einpassen

tint (green);                       //Bild mit Farbe "Grün" einfärben
image (meinBild, 150, 50);  // Bild einpassen

tint (red);                       //Bild mit Farbe "Rot" einfärben
image (meinBild, 300, 100);  // Bild einpassen


2.3 Auslesen

Die bekannte Vorgehensweise durch Angabe von x und y Koordinate bei der Positionierung und Skalierung von Elementen auf der Zeichenfläche liegt auch bei dem Auslesen von Bildern vor.
Alle Bildpunkte (Pixel) sind in einem kartesischen Koordinatensystem angeordnet.
Wie im Sketchfenster starten beide Achsen in der oberen linken Ecke an der Position 0,0.
Jeder einzelne Pixel ist auf diese Weise eindeutig, durch die Angabe von x und y, identifizierbar.
Wenn wir von Bildpunkten bzw. Pixeln sprechen, beziehen wir uns immer auf den Farbwert an einer bestimmten Stelle.
In Processings Funktionsumfang existiert der Befehl get() zum Erfragen von Farbwerten:
  • get() gibt den Farbwert eines Bildes oder Pixels zurück, bzw. Bildausschnitt.
  • Das Ergebnis ist vom Datentyp color. get()
  • PImage img = loadImage ("test.jpg");
     
    // Farbmittelwert des gesamten Bildes
    color bild = img.get ();
     
    // Farbwert des Bildpunktes an der Position x:30, y:87
    color pixel = img.get (30, 87);
     
    // Bildabschnittes der sich von Position
    // x:10, y:10 um 20 Pixel nach rechts unten erstreckt
    color bereich = img.get (10, 10, 20, 20);

Fritz-Portrait_1a.JPG

Zwischen dem Namen des PImage Objekts und dem get() Befehl wird ein Punkt gesetzt.
Dieser bedeutet wörtlich: Wende den Befehl get() auf das Bildobjekt img an.


09.2.3.1 Color picker




Unser Farbsucher tritt nur in Aktion, wenn sich der Mauszeiger über dem Bild befindet.
Da wir dieses direkt in der oberen linken Ecke positioniert haben, überprüfen wir ob die Maus-x-Position kleiner als die Breite des Bildes ist.
Innerhalb des if Blocks sucht der get() Aufruf nach dem Farbwert an der Mausposition im Bild und definiert damit eine Variable vom Datentyp color.
Diese Variable c nutzen wir im letzten Schritt um die aktuelle Füllfarbe zu setzen.
Befindet sich die Maus nicht über dem Bild - wird der if Block nicht ausgeführt; kein Rechteck wird gezeichnet.

//Processing-Sketch: 09.2.3.1 Color picker_1a.pde

PImage img; // definiere die globale Variable "img" damit sie überall im Programm verfügbar ist 

void setup () {
  size (480, 375);   // Zeichenfläche auf Größe des zu ladenden Bildes festlegen  
  smooth (); // Kantenglättung aktivieren  
  noStroke (); // Outline deaktivieren  
  // Variable "img" zum halten des Bildes festlegen. Bild hinein laden.
  img = loadImage ("Fritz-Portrait_1a.JPG");
}

void draw () {  
  background (255); // Hintergrund mit weiß füllen  
  image (img, 0, 0); // Bild darstellen
  //image (img, 20, 20, width-40, height-40);      // Bild einpassen  
  if (mouseX < img.width) { // Wenn sich die Maus außerhalb  dem Bild befindet    
    color c = img.get (mouseX, mouseY); // lies Farbe an Mausposition aus    
    fill (c);// setze Farbe als Füllfarbe  
    rect (405, 5, 70, 365); // zeichne ein Rechteck in den rechten Sketchpart
  }
}


09.2.3.2 Lego image scretch

Lego_1a.png



Bilder Scratch in Processing
//Processing-Sketch: 09.2.3.2 Lego image scretch_1a.pde

PImage img; // Globale Variable zum Ablegen des Bildes (Überall erreichbar)

void setup () {
  size (490, 400);   // Zeichenfläche auf Größe des zu ladenden Bildes festlegen
  img = loadImage ("lego_1a.png");  // Variable "img" zum halten des Bildes festlegen. Bild hinein laden.
}

void draw () {
  image (img, 0, 0);  // Bild mittels image() Befehl an der Position 0,0 (oben links) abbilden.
  for (int i=0; i < img.height; i=i+1) {  // für alle Pixel in der Spalte der Mausposition
    color c = img.get (mouseX, i);  // Farbwert auslesen
    stroke (c);  // Linienfarbe definieren
    line (0, i, mouseX, i);  // Linie von Mausposition an den rechten Bildrand zeichnen
  }
  println ("mouseX = " + mouseX);
}

Eigene Bildeffekte programmieren in Processing
Bilder können uns auch als reine Datengrundlage dienen.
Das Beispiel veranschaulicht einen Zeichenprozess der durch die Anteiligkeit der Farbe Rot Ellipsen auf der Zeichenfläche verteilt.
Diese werden je nach Stärke des Rotkanals mit einem Grauton gefüllt.
Zum Auslesen des Bildes werden zwei for Schleifen ineinander verschachtelt.
Spalte für Spalte werden damit alle Pixel analysiert und jeweils die Entscheidung gefällt ob eine Ellipse an dieser Position gezeichnet werden soll oder nicht (wenn Rotanteil größer als 190 ist).


//Processing-Sketch: 09.2.3.3 Lego image customer filter_1a.pde

size (500, 420); // Zeichenfläche auf Größe des zu ladenden Bildes festlegen
smooth ();       // Kantenglättung aktivieren
noStroke ();     // Outline deaktivieren
background (10); // Hintergrund abdunkeln

PImage img = loadImage ("lego_1a.png"); // Variable "img" zum halten des Bildes festlegen. Bild hinein laden.

for (int px = 0; px < img.width; px = px + 1) {     // Schleife für die Pixelzeilen des Bildes
  for (int py = 0; py < img.height; py = py + 1) {  // Schleife für die Pixelreihen des Bildes
    color c = img.get (px, py);  // Farbwert des Bildpixels an der Position px,py  
    float r = red (c);           // Rotanteil aus der Farbe "c"
    if (r > 190) {               // Wenn der Rotanteil größer als 190 ist 
      fill (img.get (px, py));   // Füllfarbe aus Bild übernehmen
      ellipse (px, py, 3, 3);    // Kreis an der Bild-Pixelposition im Sketchfenster zeichnen
    }
  }
}




Bilder Kopieren in Processing

Da wir über den get() Befehl auch beliebig grosse Ausschnitte aus einem Bild kopieren können haben wir viele Möglichkeiten kleine Teile des Bildes zu nutzen um neue Bilder zu erzeugen.

In diesem Beispiel zeichnen wir ein kleines dynamisches Mosaik, indem wir über die Mauseposition einen Bildausschnitt wählen und nur diesen wiederholt auf der Bildfläche zeichnen.


//Processing-Sketch: 09.2.3.4 Lego Kopieren in Processing_1a.pde
PImage img; // unser Lego Bild // die Breite und Höhe einer Kachel, diese berechnen wir über die Anzahl der Zeilen und Spalten  int gridStepX; int gridStepY; int numRows = 5; // aus wieviel Zeilen besteht das Gittermuster int numCols = 5; // aus wieviel Spalten besteht das Gittermuster void setup() {   size(400, 375); // Größe der Anwendung = Größe des Bildes   background(255); // Hintergrund weiß   img = loadImage("lego_1a.png"); // LEGO-Bild laden   // Größe der Kachel berechnen - Größe = Gesamtgrösse / Anzahl der Spalten   gridStepX = width / numRows;   gridStepY = height / numCols; } void draw() {   // wir "schneiden" uns unser Kachelstück an der aktuellen Mausposition heraus, und speichern dies in einem neuen Bild   PImage imgPart = img.get(mouseX, mouseY, gridStepX, gridStepY);   for (int x=0; x < width; x = x + gridStepX) { // gehe in 'Kachelschritten' entlang der Breite     for (int y=0; y < width; y = y + gridStepY) { // gehe in 'Kachelschritten' entlang der Hoehe       image(imgPart, x, y); // zeichne das aktuelle Kachelbild an der jeweiligen Stelle     }   } }



2.4 Modifizieren

Umgekehrt lassen sich Farbwerte von Bildpunkten durch den Aufruf von set() ändern/modifizieren.
Der Aufruf des Befehls muss immer die x und y Koordinaten, sowie ein Farbwert enthalten.
Abwandlungen der Parameteranzahl, siehe get(), sind nicht möglich.
  • set() setzt den Farbwert eines Bildpunktes an einer bestimmten Position. set()
    PImage img = loadImage ("test.jpg");
    img.set (29, 18, color (255, 0, 0));

2.5 Sketch als Bild

Jeglicher grafischer Inhalt der von unseren Programmen im Sketchfenster erzeugt wurde und für uns sichtbar ist, stellt ein Bild (PImage) dar.
Dadurch können Anweisungen wie get() und set() zum Auslesen und ändern der Zeichfläche dienen.

09.2.4.1 Zeichenfläche einfärben

Alle oberhalb abgebildeten Verläufe wurden durch die unten stehenden Zeilen dieses Beispiels generiert.
In der dritten Stunde schufen wir erstmals ähnliche Ergebnisse - griffen dabei aber auf Linien zurück, welche unterschiedlich eingefärbt wurden.
Nun definieren wir für jeden einzelnen Punkt auf unserer Zeichenfläche die mittels set() Farbe neu.

//Processing-Sketch: 09.2.4.1 Zeichenfläche einfaerben_1a.pde

size(355, 255); 
for (int px = 0; px < width; px = px + 1) {    // für jede der 255 pixel Spalten
  for (int py = 0; py < height; py = py + 1) { // für jede der 255 pixel Zeilen
    set (px, py, color (px, py, 0)); // setze den Farbwert für jeden Pixel auf der Zeichenfläche
    print(width + "  ");
    println(height);
  }  
}

2.6 *.SVG

Type_B_Plug_Coloured.svg

*.SVG (Scaleable Vector Graphics) sind wie der Name schon sagt skalierbare Vektor Dateien, die wir im Adobe Illustrator oder Freehand erzeugen können.
Der Vorteil dieser Grafiken ist, dass man im Gegensatz zu Pixelbildern ohne Qualitätsverlust skalieren kann.
Um eine eine *.SVG im Illustrator zu erzeugen, wählt man bei dem Menüpunkt Speichern unter... *.SVG ( *.svg ).
Die selbige Datei muss sich, um sie in Processing laden zu können, ebenfalls im ORDNER  "data"  unseres Sketches befinden.
Wie auch bei dem laden eines Bildes, brauchen wir eine Globale Variable, in der die Grafik gespeichert wird.

Der Datentyp dazu nennt sich PShape > PShape und der Befehl zum laden loadShape().
https://www.processing.org/reference/PShape.html
https://www.processing.org/reference/loadShape_.html
https://www.processing.org/reference/shape_.html

PShape meineGrafik;
meineGrafik = loadShape("NameMeinerGrafik.svg");

In den beiden Zeilen wird die Variable meineGrafik des Typs *.SVG angelegt und anschliessend die .svg Datei geladen und in der Variable gespeichert.
Um die Grafik anschliessend auch darzustellen benötigen wir den Befehl shape(meineGrafik, xPosition, yPosition);
Optional zur x- und yPosition kann auch die Weite und Höhe angegeben werden.
Lässt man die Werte raus, werden die Ursprungswerte (Höhe & Weite) der Grafik übernommen.


09.2.6.1 Laden & darstellen von *.svg

//Processing-Sketch: SVG (Scaleable Vector Graphics) _1a.pde

PShape meineGrafik;    //Variable anlegen
size(150, 150);        // Größe der Anwendung = Größe des Bildes 
meineGrafik = loadShape("Type_B_Plug_Coloured.svg"); //SVG laden 
shape(meineGrafik, 10, 10, 80, 80);                  //SVG darstellen


Der zweite Vorteil an *.SVG ist, dass man diese mittels Processing im Nachhinein beeinflussen kann.
So kann die Füllfarbe und die Strichfarbe wie gewohnt modifiziert werden.
Mittels dem Befehl
 [[processing.org/reference/PShape_getWidth_.html|getWidth()]]
ist es möglich auf die Weite der geladenen *.SVG zuzugreifen und so
z.B. die Ursprungsgrösse proportional zu vergrössern / zu verkleinern.

Das gleiche gilt respektive für die Höhe mit getHeight()


09.2.6.2 SVG laden & modifizieren



// Processing-Sketch: 09.2.6.2 SVG laden u modifizieren_1a.pde
// Die Datei "Type_B_Plug_Coloured.svg" muss sich im ORDNER "data" des aktuellen Sketches befinden, um geladen zu werden

PShape Grafik; // Variable initalisieren

void setup() { 
  size(1400, 800);
  background(255);

  Grafik = loadShape("Type_B_Plug_Coloured.svg");   // USB Grafik.svg laden
  smooth();
}

void draw() {
  noLoop();   // durch noLoop() wird der ganze block nur 1* ausgeführt
  noFill();   // keine Flächenfüllung

  shape(Grafik, 10, 10, 80, 80);      // Grafik.SVG darstellen, X-Y-Position
  shape(Grafik, 10, 10, 160, 160);    // Grafik.SVG darstellen
  //shape(Grafik, 10, 10, 320, 320);  // Grafik.SVG darstellen

  // *.SVG darstellen und die Ursprungsgröße um ein 2- bzw. 4-faches verkleinern
  shape(Grafik, 90, 90, Grafik.getWidth() /4, Grafik.getHeight()/4);
  shape(Grafik, 80, 80, Grafik.getWidth() /2, Grafik.getHeight()/2); 
  shape(Grafik, 50, 50, Grafik.getWidth() *1, Grafik.getHeight()*1);

  Grafik.disableStyle();      // den Stil der SVG ausschalten
  strokeWeight(0.5);          // Strichbreite überschreiben
  fill(255, 255, 0, 70);      // Füllfarbe, Transparent
  stroke(255, 0, 0);          // Strichfarbe rot

  // *.SVG darstellen und die Ursprungsgröße um das 1.5faches vergrössern
  shape(Grafik, 200, 50, Grafik.getWidth()*1.5, Grafik.getHeight()*1.5); // 1,5 mal größer
}


Weiter Befehle findet ihr in der Referenz von PShape





*********************************************************

10. Typografie, Schriften  Segment7.vlw

12  18  24  36  48  60  72pixel

Laden und Darstellen von Text




Diese Lesson erläutert die Besonderheiten zu Processings Umgang mit Schrift und der Darstellung von Text.

Darüber hinaus werden die Grundfunktionen wie Schriftgröße, Zeilenhöhe, Beschränkung des Textfelds, sowie dem Ausrichten und Einfärben von Text eingeführt.


1. Schriften in Processing

Innerhalb von Processing wird das Schriftformat *.vlw verwendet.
Anders als bei Vektorschriften liegt dabei jedes Zeichen seperat als gerastertes Bild vor.
Diese Bildinformationen beschränken sich pro Pixel auf die Angabe von schwarz(1) oder weiß (0) - wird das Pixel gefüllt oder nicht.
Eine solche Schrift nennt man deshalb Bitmap-Font (Bit), da nur zwei Möglichkeiten existieren.
Grund für diese umständliche und qualitativ ungünstige Lösung ist die Funktion des Webexports.
Da die Verfügbarkeit der Schriften im Betriebssystem von Betrachtern im Internet keine Vorraussetzung darstellen soll.

1.1 Laden von Schriften

Das laden von Schriften verhält sich ähnlich wie das Laden von Bildern.
Mussten wir bei Bildern, diese vorher manuell in den data-Ordner unserer Sketch kopieren
(alternativ auch über das Menü "Sketch→Add File...")
gibt es bei Schriften noch einen zusätzlichen Schritt vor dem Kopieren: das Erstellen der Bitmap-Font aus der auf dem Rechner installierten Schrift.
Diese Aufgabe übernimmt komplett das Tool "Create Font"  MENU > Tools > Create Font.. > Segment7.vlw
Einmal geöffnet, wählt man die Schrift, die man verwenden möchte aus, woraufhin sie automatisch in den ORDNER "data" kopiert wird.
Damit kann sie verwendet werden.
Wie Bilder werden auch Schriften in einem eigenen Datentypen gespeichert:
PFont myFont;
und können nach der Deklaration auch in die neu erstellte Variable geladen werden:
myFont = loadFont ("Arial.vlw");

1.2 Abbilden im Sketch

Nach dem Erfolgreichen Laden der Font kann diese endlich verwendet werden.
Dazu muss Processing zu erst mitgeteilt werden welche Font verwendet werden soll.
Das ist insbesondere deswegen nötig, da natürlich auch mehrere Schrift geladen und verwendet werden können.
In Processing wird die zu verwendende Schrift über den Befehl textFont(font, size); definiert.
Diese Einstellung gilt dann bis zum erneuten Aufruf von textFont();
Beim festlegen der Schriftgröße sollte darauf geachtet werden, dass die Font vorher in einer bestimmten Größe gerastert (in Bitmap-Schrift umgewandelt) wurde, was dazu führen kann, dass die Pixel der Schrift sichtbar werden, wenn die Darstellungsgröße die Rastergröße übersteigt.

Allgemein gilt:
Schriften die klein gerastert wurden werden schneller dargestellt.

Als letzter Schritt ist lediglich die Verwendung von text("mein Text", xpos, ypos); nötig um Text in Processing darzustellen.
Die drei Parameter der text() Funktion bestimmem hierbei den darzustellenden Text als String, sowie die x und y-Position an der der Text dargestellt werden soll.

Anders jedoch als bei rect() oder image() liegt der Orientierungspunkt für das Zeichnen von Text in der linken, unteren Ecke.

ACHTUNG:
Nur Schriften die am Rechner geladen sind können verwendet werden.
Siehe
MENU > Tools > Create Font... > Arial-48.vlw  (früher Helvetica) die Techniker-Schrift

10.1.2.1  Darstellung



// Processing-Sketch: 10.1.2.1  Schrift Darstellung Arial_1a.pde

PFont font;              // Variable zum Ablegen des Schriftabschnittes

size (520, 100);         // Größe der Grafikausgabefläche
background (148, 0, 211);  // Hintergrund Farbe

font = loadFont ("Arial-BoldMT-48.vlw");   // Laden der Schrift in die Variable 'font'
// Setze die Schrift 'font' als Standardschrift für alle nun folgenden 'text()' Aufrufe
textFont (font);
text ("Arial-BoldMT-48.vlw", 30, 70);      // Textausgabe X-Y links unten



10.1.2.2 Darstellung im Block


// Processing-Sketch: 10.1.2.2 Darstellung der Schrift im Block_1a.pde

PFont font;              // Variable zum Ablegen des Schriftabschnittes

size (500, 160);         // Größe der Grafikausgabefläche
background (255, 110, 180);  // Hintergrund Farbe
font = loadFont ("Arial-BoldMT-48.vlw");   // Laden der Schrift in die Variable 'font'
// Setze die Schrift 'font' als Standardschrift für alle nun folgenden 'text()' Aufrufe
textFont (font);                           // Schriftgröße
textSize (24);
//text ("Arial-BoldMT-48.vlw", 30, 70);    // Textausgabe X-Y links unten
text ("Arduino fritzing Processing für Anfänger und leicht Fortgeschrittene. 
Grundlagen, Befehle, Muster-Sketche alles in www.schaltungen.at
fritz prenninger"
, 20, 30, 480, 130); // Text fließt innerhalb Textfeld

1.3 Schriftgröße

Die Schriftgröße lässt sich auf zwei Wegen definieren:
A
  • textFont(font, size) setzt sowohl die zukünftig zu verwendende Schrift, sowie gleichzeitig die Schriftgröße.
  •  textFont()

10.1.3.0  Mehrere Schriftarten

14 Arial-BoldMT
11 ArialMT (früher Helvetica) Techniker Schrift
27 Digital-7
01 01_Digit
03 5x8-LCD-HD44780U-A02
85 06   7Segment
18 LEDCounter7
90 LCDBold
81 Verdana
02 Segment7Standard
003 Digital-7Mono
05 LiquidCrystal
07 Patopian1986
08 LiquidCrystal-Light
09 LiquidCrystal-Regular
10 LiquidCrystal-Bold
005 7LED
21 DISPLAYFREETFB
23 DS-Digital
26 DS-Digital-Bold



Ein kleiner Auszug aus
// Processing-Sketch: 10.1.3.0  Mehrere Schriftarten A_1a.pde
// loadFont Schriftart wird mitgespeichert
// MENU > Tools > Create Font... > Arial-48.vlw  (früher Helvetica) die Techniker-Schrift
// 12  18  24  36  48  60  72pixel
PFont font_14;  // eine PFont-ObjektVariable deklarieren
PFont font_11;
PFont font_85;

size (800, 1100);
background (150);  // Hintergrund-Farbe hgrau
smooth (); // Aktiviere Kantenglättung

font_14 = loadFont ("Arial-BoldMT-48.vlw"); // sucht im ORDNER "data" nach Fontname-Fontgröße.vlw
//textFont (font_14);   // Setze die Schrift 'font_14' als Standardschrift
//textSize (24);        // Setze Schriftgröße auf 24px
textFont (font_14, 24); // Fontname, Fontgröße mit Qualitätsverlust wird skaliert
text ("14 Arial-BoldMT-24.vlw", 20, 30);  // Text  X-Y Position

font_11 = loadFont ("ArialMT-48.vlw");    
textFont (font_11, 24);
text ("11 ArialMT-24.vlw", 20, 50); 

font_85 = loadFont ("7Segment-48.vlw"); 
textFont (font_85, 72);
fill (0, 255, 255);
text ("85 7Seg-72 1999 -888 ", 20, 230); 






Ein kleiner Auszug aus
// Processing-Sketch: 10.1.3.0  Mehrere Schriftarten B_1a.pde

28 Digital-7Mono
31 Dotf1
33 EnhancedLEDBoard-7
34 Epson1
35 Erbos-Draco-1st-NBP
43 LCDDot-TR
45 LEDBoard-7
60 Patopian1986
61 Piece
64 ScoreBoard
66 Segment7Standard
71 Swiss721BT-BoldOutline
72 TPFDisplay
73 Tahoma
74 Texas-Instruments-TI-84-series-PIXELLATED
75 TexasLED
76 TimesNewRomanPSMT
82 VinetaBT
86 CourierNewPS-BoldMT





// Processing-Sketch: 10.1.3.0  Mehrere Schriftarten B_1a.pde
// loadFont Schriftart wird mitgespeichert
// MENU > Tools > Create Font... > Arial-48.vlw  (früher Helvetica) die Techniker-Schrift
// 12  18  24  36  48  60  72pixel
PFont font_28;  // eine PFont-ObjektVariable deklarieren
PFont font_31;

size (800, 1000);
background (150);  // Hintergrund-Farbe hgrau
smooth (); // Aktiviere Kantenglättung

font_28 = loadFont ("Digital-7Mono-48.vlw"); // sucht im ORDNER "data" nach Fontname-Fontgröße.vlw
//textFont (font_28);   // Setze die Schrift 'font_14' als Standardschrift
//textSize (24);        // Setze Schriftgröße auf 24px
textFont (font_28, 48); // Fontname, Fontgröße wird mit Qualitätsverlust skaliert
text ("28 Digital-7Mono-48.vlw", 20, 40);  // Text  X-Y Position


font_31 = loadFont ("Dotf1-48.vlw"); 
textFont (font_31, 48);
fill (0);
text ("31 Dotf1-48.vlw 1999", 20, 100); 
usw. usw. usw.



10.1.3.1  Schriftgröße
B
textSize(size) diese Variante ist besser geeignet, wenn nur die Schriftgröße und nicht die Schrift geändert werden soll.
textSize()



// Processing-Sketch: 10.1.3.1  Schriftgroesse_1a.pde

PFont font;                  // Variable zum Ablegen des Schriftschnittes

size (500, 100);
background (193, 205, 193);  // Hintergrund-Farbe
smooth ();                   // Aktiviere Kantenglättung

font = loadFont ("Arial-BoldMT-48.vlw"); // Laden der Schrift in die Variable 'font'
textFont (font);                         // Setze die Schrift 'font' als Standardschrift

textSize (24);                           // Setze Schriftgröße auf 24px
text ("Arial-BoldMT-24.vlw", 20, 30);    // Text  X-Y Position

textSize (48);                           // Setze Schriftgröße auf 48px
text ("Arial-BoldMT-24.vlw", 20, 80);    // Text  X-Y Position

                                                                                                                                                                                                                                                                  

1.4 Zeilenhöhe

Für die Darstellung von mehrzeiligem Text ist die Anpassung des Zeilenabstands unabdingbar um eine gute Lesbarkeit zu gewährleisten.
Die Zeilenhöhe lässt sich über die Funktion textLeading() einstellen.

textLeading(distance);

10.1.4.1  Zeilenhöhe


// Processing-Sketch: 10.1.4.1 Zeilenhoehe_1b.pde

PFont font;         // Variable zum Ablegen des Schriftschnittes

size(600, 200);     // Größe des Grafik-Bereiches
background (230);   // Hintergrund Farbe hell-grau
// laden der Schrift  MENU>Tools>Create Font.>ArialMT-48.vlw  (früher Helvetica)
font = loadFont ("ArialMT-48.vlw"); 
textFont (font);    // Setze die Schrift 'font' als Standardschrift
textLeading (40);   // Setze die Zeilehöhe auf 40px (pixel)
fill (255, 0, 255);  // Schriftfarbe magenta
// Schreibe 'typo' an die Position x:40 und y:20, nutze dafür eine Fläche von 420x180 Pixel
text ("Arduino UNO R3 Processing und fritzing für Anfänger.", 40, 20, 420, 180);



1.5 Einfärben

Das Einfärben von Schrift funktioniert in Processing auf die selbe Art und Weise wie das auch bei den Grundformen wie rect() oder ellipse() der Fall ist.
Das heisst, ein Aufruf von fill(r, g, b); ändert die Füllfarbe für alle folgenden gezeichneten Texte (und Formen!).
Auch die Verwendung von Transparenzen über fill(r, g, b, a); ist möglich.
Die Strichfarbe hingegen lässt sich bei Schriften nicht definieren, was mit dem Umstand zu tun hat, dass Texte in Processing generell Pixelbilder sind.

10.1.5.1   Text einfärben


// Processing-Sketch: 10.1.5.1 Text einfaerben_1a.pde

PFont font;         // Variable zum Ablegen des Schriftschnittes

size(360, 300);     // Größe des Grafik-Bereiches
background (180);   // Hintergrund Farbe hell-grau
// laden der Schrift  MENU>Tools>Create Font.>ArialMT-48.vlw  (früher Helvetica)
font = loadFont ("ArialMT-48.vlw"); 
textFont (font);    // Setze die Schrift 'font' als Standardschrift

fill (0,0,205);  // Schriftfarbe blau
line(20,60, 280,60);
text ("creative", 50,60);
fill (139, 69, 19);  // Schriftfarbe braun
line(20,100, 280,100);
text ("coding", 40, 100);
fill (0,100,0);  // Schriftfarbe grün
line(20,140, 280,140);
text ("fritz", 30,140);
fill (255, 127, 0);  // Schriftfarbe orange
line(20,180, 280,180);
text ("prenninger", 20, 180);
fill (191,62,255);  // Schriftfarbe violett
line(20,220, 280,220);
text ("haidestrasse", 10,220);
fill (255, 231, 186);  // Schriftfarbe beige
line(20,260, 280,260);
text ("wels", 0, 260);


1.6 Ausrichtung

Texte können auf beiden Achsen, Horizontale und Vertikale, unter der Verwendung von textAlign() ausgerichtet werden.
Die Vertikale (y-Achse) ist dabei nur ein optionaler Wert - die x-Achse muss jedoch immer angegeben werden.
  • textAlign() setzt die Ausrichtung alle danach folgenden mit text() dargestellte Texte.
  • Diese Funktion kann mit einem oder zwei Parametern aufgerufen werden.
  • Der erste definiert die x-Achse (Horizontale), optional kann mit dem Zweiten die y-Achse (Vertikale) angegeben werden.
  • Als ersten Wert können folgende Angaben genutzt werden: LEFT, CENTER, RIGHT.
  • Als Standard wird von Processing LEFT verwendet. Für die y-Achse finden folgende Werte Verwendung: TOP, CENTER, BOTTOM. textAlign()

textAlign (RIGHT);           // Ausrichtung rechts
textAlign (BOTTOM, RIGHT);  // Ausrichtung unten rechts



Die Begriffe zur Festlegung der Ausrichtung (LEFT, TOP, RIGHT, etc.) müssen in Versalien geschrieben werden.

10.1.6.1 Text horizontal ausrichten


Im unteren Beispiel legt die Variable xpos die x-Position beider Textschnippsel fest.
Text 1 ("creative") wird links ausgerichtet - wie in Processing standardisiert.
Der zweite Text ("coding") wird an selbiger Position platziert, aber mittels textAlign(RIGHT); rechts ausgerichtet.
Text 2 endet deshalb an der Startposition von Text 1.


// Processing-Sketch: 10.1.6.1 Text horizontal ausrichten_1a.pde

PFont font;        // Variable zum Ablegen des Schriftschnittes

size(450, 180);    // Größe des Grafikfensters
background (225);  // Hintergrund hell-grau einfärben
fill (0);          // Schriftfarbe schwarz

font = loadFont ("ArialMT-48.vlw"); // Laden der Schrift in die Variable 'font'
textFont (font);   // Setze die Schrift 'font' als Standardschrift

float X_pos = 150;  // Variable für die x-Position des Textes
line (X_pos, 0, X_pos, height);  // vertikale Linie an der Textposition 
textAlign (LEFT);              // Text links ausgerichtet
text ("LEFT", X_pos, 70); 
textAlign (CENTER);            // Text mittig ausgerichtet
text ("CENTER", X_pos, 110);
textAlign (RIGHT);             // Text rechts ausgerichtet
text ("RIGHT", X_pos, 150);



// Processing-Sketch: 10.1.6.1 Text vertikal ausrichten_4a.pde

PFont font;        // Variable zum Ablegen des Schriftschnittes

size(500, 180);    // Größe des Grafikfensters
background (225);  // Hintergrund hell-grau einfärben
fill (0);          // Schriftfarbe schwarz
stroke(153);

font = loadFont ("ArialMT-48.vlw"); // Laden der Schrift in die Variable 'font'
textFont (font);   // Setze die Schrift 'font' als Standardschrift

float Y_pos = 90;  // Variable für die x-Position des Textes
line (0, Y_pos, width, Y_pos);  // horizontale Linie an der Textposition 

textAlign(LEFT, BOTTOM);  // Text links-unten ausgerichtet
line(0, 50, width, 50);
text("LEFT g BOTTOM", 0, 50);

textAlign(CENTER, CENTER); // Text mittig ausgerichtet
line(0, 90, width, 90);
text("CENTER g CENTER", width/2, 90);

textAlign(RIGHT, TOP);     // Text rechts-oben ausgerichtet
line(0, 130, width, 130);
text("RIGHT g TOP", width, 130);

1.7 Textbreite

Um Texte in Proportionen zur Zeichenfläche platzieren zu können, benötigen wir Informationen zur Breite.
Processing gibt uns Antwort auf diese Frage mit dem Aufruf von textWidth().
Trotz der durch Pixel limitierten Darstellung auf dem Bildschirm erhalten wir eine Fließkommazahl (Datentyp float) der uns bei der Positionierung von Textschnippseln dient.
Bei der Berechnung dieses Wertes spielen die aktuellen Einstellungen wie
textFont() (aktuelle Schriftart)
textSize() (Größe der Schrift)

eine Rolle.
Bei zwischenzeitlicher änderungen dieser Optionen, muss die Textbreite neu berechnet werden.
  • textWidth() gibt die Breite eines Textes für die aktuell mit textFont() gesetzte Schrift zurück - in Abhänigkeit von textSize().
  • Als einzigen Parameter wird der Text übergeben. textWidth()
  • float breite = textWidth("Wie breit bin ich?");

10.1.7.1 Textbreite

Wir arbeiten in diesem Beispiel mit zwei Variablen (xpos1 und xpos2), die jeweils die x-Position eines der beiden Textschnippsel beinhalten. xpos1 wird von uns statisch ein Wert von 40 zugewiesen. Variable "xpos2" bekommt den Wert der Summe von xpos1 (in diesem Fall 40) und der von Processing berechneten Breite unseres ersten Textes ("Fritz").
Beide Texte, bzw. Wörter, sind dadurch direkt aneinandergereiht.




// Processing-Sketch: 10.1.7.1 Textbreite_1a.pde

PFont font;  // Variable zum Ablegen des Schriftschnittes

size(420, 80);  // Größe der Grafik-Fläche
background (150);  // Hintergrund dunkel-grau einfärben

// Laden der Schrift in die Variable 'font'
font = loadFont ("ArialMT-48.vlw");  // früher Helvetica
textFont (font); // Setze die Schriftart

// Variable für die x-Position der Texte  'xpos2' ist die Summe aus 'xpos1' + der Breite des zweiten Textes in Pixel
float xpos1 = 40;
float xpos2 = xpos1 + textWidth ("Fritz");  // Bindestrich = Abstand 1 Leerzeichen

// Text darstellen an den x-Positionen, die y-Position ist bei beiden die Selbe
text ("Fritz", xpos1, 60);
text ("Prenninger", xpos2, 60);

line (xpos1, 0, xpos1, height);  // Linie-1 zur Überprüfung der x1-Positionen
line (xpos2, 0, xpos2, height);  // Linie-2 zur Überprüfung der x2-Positionen

http://www.creativecoding.org/lesson/basics/processing/typografie





DIN A4  ausdrucken
*********************************************************
Impressum: Fritz Prenninger, Haidestr. 11A, A-4600 Wels, Ober-Österreich, mailto:schaltungen@schaltungen.at
ENDE













Comments