PVector & Distanz

In den heutigen Beispielen kombinieren wir bereits erlerntes Wissen ( z.B. Arrays, whileLoop und Distanzberechnung) mit neuen Werkzeugen, um die Grundlagen für die Themengebiete Animation und OOP zu erlernen.

PVector

Das erste neue Werkzeug ist PVector, ein Datencontainer, der zwei bis drei (x,y,z) Werte speichern kann. In der Regel verwendet man diese Klasse um Postionen, Geschwindigkeiten oder Beschleunigungen festzuhalten.

Die Idee des heutigen Beispieles ist, dass man einmalig eine Liste mit zufälligen Koordinaten erzeugt, die man in der Folge immer wieder verwenden kann.

Jede Koordinate wird als PVector festgehalten und besteht aus x und y. Gespeichert werden die Werte in einer Liste (Array). Die Erstellung erfolgt mit Hilfe eines while-Loops.

Beispiel: In der Methode setupDotList() wird die Liste erstellt.

void setupDotList()
{
  dotList = new PVector[ dotAmount ];
}

Beispiel:In der Methode createDotList() wird mit Hilfe eines while-Loops die Liste mit PVector-Instanzen befüllt.

void createDotList()
{  
  int count = 0;  
  int amount = dotList.length;
 
  while( count < amount )
  {
    dotList[ count ] = new PVector(random(width), random(height)); 
 
    count++; 
  }
}

Bis dato fehlt für die erstellten Punkte noch eine visuelle Repräsentanz. Eine einfache Testmethode, um Kreise an den entsprechenden Stellen zu erzeugen, könnte wie folgt aussehen.

void drawDotList()
{
  int count = 0;
  int amount = dotList.length;
 
  PVector currentDot;
 
  while( count < amount )
  {
    currentDot = dotList[ count ];
    ellipse( currentDot.x, currentDot.y, 10, 10 );
 
    count++;
  }
}

distance

Das Ziel dieser Übung ist es aber, dass wir die Distanz zwischen jeder Koordinate aus der Liste mit den anderen Koordinaten aus der Liste abgleichen.

Der Grundaufbau besteht dabei wieder aus einem while-Loop der über die Liste iteriert. Der aktuelle Punkt (currentDot) wird dann zur Überprüfung an die Funktion checkDistance übergeben.

Beispiel:

void drawLinesBetweendotList()
{
  int count = 0;
  int amount = dotList.length;
 
  PVector currentDot;
 
  while( count < amount )
  {
    currentDot = dotList[ count ];
    checkDistance( currentDot );
 
    count++;
  }
}

Die Funktion checkDistance überprüft die Distanz des übergebenden Punkt gegen die gesamte Liste an Koordinaten. Bewegt sich die Distanz zwischen dem definierten minimalen (minDistance) und maximalen (maxDistance) Wert, dann wird auf Basis des Abstandes eine Linie zwischen den Punkte gezeichnet. Die Linienstärke wird dabei mit strokeWeight gesetzt.

Beispiel:

void checkDistance( PVector currentDot )
{
 
  int count = 0;
  int amount = dotList.length;
 
  PVector checkDot;
 
  while( count < amount )
  {
    // Check-Punkt
    checkDot = dotList[ count ]; 
 
    // Distanz berechnen
    float distance = dist( currentDot.x, currentDot.y, 
checkDot.x, checkDot.y ); 
 
    // Distanz überprüfen
    if( distance < maxDistance && distance > minDistance )
    {
      strokeWeight( 15 / distance );
      stroke( 255, 255, 255, 20 );
 
      line( checkDot.x, checkDot.y,  currentDot.x, currentDot.y );
 
      addRect( distance, currentDot );
    }
 
    count++;
  }
}

Erweiterungen

Erweiterungsmöglichkeiten für dieses Beispiel gibt es viele. Eine Idee wäre, dass man an der Position des aktuell zu prüfenden Punktes bei der entsprechenden Distanz zusätzlich ein Rechteck zeichnet, dessen Aussehen sich an der Distanz orientiert. Für ein wenig Varianz sorgt dabei der Einsatz von rotate(), dass wie der Name schon sagte Objekt rotieren lässt.

Objekte werden immer zu ihrer relativen Position zum Ursprung rotiert. Positive Werte sorgen dabei für eine Rotation im Uhrzeigersinn. Eine gesetzte Rotation wirkt sich auf alle Objekte aus, die in der Folge gezeichnet werden.

Die Funktion rotate() erwartet als Parameter einen Winkel mit einem Wert zwischen 0 und TWO_PI. Um als Einheit die besser lesbaren Gradzahlen zu verwenden, kann man diese mit der Hilfsfunktion radians() in Radianten für die Funktion rotate() umwandeln.

Möchte man den aktuellen Zustand der Transformation festhalten, verwendet man den Befehl pushMatrix(). Um später diesen Zustand wieder herzustellen verwendet man den Befehl popMatrix().

Wichtig in diesem Zusammenhang ist auch der Einsatz und das Verständnis für den Befehl translate(). Dieser Befehl erwartet als Minimum die Parameter x und y und optional noch z. Mit translate() kann man den Koordinatenursprung des Sketches verändern, der sich in der Folge auf alle Zeichenvorgänge auswirkt.

Beispiel:

 
// Angabe in Grad
float degree1 = 45.0;
float degree2 = 45.0;
 
// Umwandlung in Radianten
float rad1 = radians( degree1 );
float rad2 = radians( degree2 );
 
// Urpsrungskoordinate auf den Mittelpunkt der Fenstergröße setzen
translate( width / 2, height / 2 );
 
// aktuelle Transformations-Matrix speichern
pushMatrix();
 
// Rotation 1 durchführen
rotate( rad1 );
 
rect( 50, 50, 50, 50 );
 
// alte Transformations-Matrix wiederherstellen
popMatrix();
 
// Rotation 2 durchführen
rotate( rad2 );
 
fill( 255, 0, 0 );
rect( 100, 100, 50, 50 );

Hausaufgabe

Erstellt drei Arbeiten, die mit Instanzen der Klasse PVector arbeiten und bei denen auf Basis von Distanzberechnungen visuelle Entscheidungen getroffen werden.

Zu allen Arbeiten sind auch jeweils die Sketch-Dateien abzugeben.

Informationen zum Dateiformat, der Bezeichnung und zum Upload der Dateien sind unter dem Punkt Prüfungsleistung zu finden.

Die Beispiele der Woche können hier herunter geladen werden.