Anwendung ebener Transformationen: Konstruktion eines Malteserkreuzes

Die "t...-Funktionen" und die "ut...-Funktionen" in CanvasGI

Diese Animation ist das Ziel, das am Ende der Einführung in das Thema "Ebene Transformation" erreicht wird

Die Funktionen in CanvasGI, die mit der ebenen Transformation korrespondieren, lassen sich in zwei Gruppen einteilen:

Nicht zu allen "u...-Funktionen" existieren auch die entsprechenden "zeichnenden ut...-Funktionen", konsequent kann das Prinzip der Vorab-Transformation ohnehin nur für die Argumente realisiert werden, die Punkt-Koordinaten beschreiben ("Move to", "Line to", "Polygon", ...). Die "ut...-Funktionen", mit denen Kreise bzw. Kreisbögen mit Mittelpunkt und Radius beschrieben werden, wenden auf den Radius z. B. nur die eingestellte Skalierung an.

Nachfolgend werden das Prinzip des Arbeitens mit den "t...-Funktionen" und den "ut...-Funktionen" und die Verwendung der wichtigsten Funktionen am Beispiel des Programms c_malteser.html (Zeichnen eines symbolischen Malteserkreuz-Getriebes) dargestellt, das schrittweise entwickelt wird.

Aufgabe, Zeichnen des Malteserkreuzes

Die rechts zu sehende Skizze zeigt das Schema des Getriebes, das nach dem Prinzip arbeitet, das in der Animation oben zu sehen ist. Das Malteserkreuz der dargestellten Variante besteht aus 6 jeweils um 60° versetzten "Schwalbenschwänzen", die jeweils durch einen Schlitz mit halbkreisförmigem Grund getrennt sind. Der eingezeichnete Winkel hat für das Abmessungsverhältnis R/L = 0,5 den Wert φ* = 30°.

Es bietet sich also an, nur ein Sechstel des Bildes zu programmieren und mit geeigneten Rotationstransformationen wiederholt zu erzeugen. Die Abbildung links zeigt das zu programmierende Sechstel. Schon für das Erzeugen dieses Teilbildes werden mit Vorteil Rotationstransformationen eingesetzt (der Schlitz kann auf diese Weise in vertikaler Lage programmiert werden).

Im Body-Teil der HTML-Datei c_malteser.html wird der Canvas-Bereich mit der id="canvas" erzeugt, die Zeichenaktion wird gestart durch eine Anweisung im Body-Tag:

<body onLoad="init();">

In der JavaScript-Funktion init werden vorbereitend folgende Aktionen ausgeführt:

      function draw () {
         gi.clearcanvas    ("silver" , "black") ;  // ... fuellt Canvas-Bereich mit Hintergrundfarbe
                                                   //     ("silver") und zeichnet schwarzen Rahmen
         crank  () ;                               // ... zeichnet die Kurbel
         cross  () ;                               // ... zeichnet das Malteserkreuz
         pivots () ;                               // ... zeichnet die Lager
      }

      function init () {
         gi = new canvasGI ("canvas") ;            // Ein "CanvasGI-Objekt" wird erzeugt
         gi.setusercoordsi (-L , -L , L , L+R+Rs) ;
         draw () ;
      }

Zunächst wird nur die Funktion cross betrachtet, die das Malteserkreuz erzeugt. Um den nachfolgenden Ausschnitt aus dem Programmcode besser zu verstehen, zeigt die nebenstehende Skizze die typischen Abmessungen, die die Geometrie des Malteserkreuzes bestimmen:

Die Mittelpunkte der beiden Drehzapfen Z1 und Z2 bilden mit dem Punkt H ein rechtwinkliges Dreieck. Die eingezeichneten Winkel und die Abmessungen L, R, RC und RS definieren die aus Kreisbögen und Geraden aufgebaute Kontur. Das Koordinatensystem wurde so definiert, dass es sinnvoll ist, den unteren Drehzapfen in den Nullpunkt zu legen.

Alle Abmessungen werden als globale Variablen vereinbart, so dass sie in allen Funktionen verfügbar sind.

Die einzelnen Anweisungen der Funktion cross werden nachfolgend erläutert (die "vorbereitenden t...-Funktionen" sieht man in grüner Farbe, die "zeichnenden ut...-Funktionen" sind hellblau):

      function cross () {
         gi.tinit     () ;   
         gi.beginpath () ;
         for (var i = 0 ; i < 6 ; i++) {
            gi.utarc    (0 , L , Rc , 5*Math.PI/6 , Math.PI/6 , true);
            gi.trot     (0 , 0 , -Math.PI/6) ;      // ... Rotation um 30° im Uhrzeigersinn 
            gi.utlineto (-Rs , Rm) ;
            gi.utlineto (-Rs , L - R) ;
            gi.utarc    (0 , L - R , Rs , Math.PI , 0 , true);
            gi.utlineto ( Rs , Rm) ;
            gi.trot     (0 , 0 , -Math.PI/6) ;      // ... und noch einmal 30°            
            gi.utlineto (-xA , yA) ;
         }
         gi.fillstyle ("blue") ;
         gi.fill   () ;
         gi.stroke () ;
      }

Zeichnen der Kurbel und der symbolischen Drehzapfen

Natürlich wird die Kurbel (in der Funktion crank) auch in der nebenstehend dargestellten vertikalen Stellung programmiert, um sie durch eine vorangestellte Transformation um den Winkel phi0 = −Math.PI/3 im Uhrzeigersinn (grüne Zeile im folgenden Listing) in der gewünschten Lage erscheinen zu lassen (phi0 ist wie die Abmessungen als globale Variable definiert):

      function crank () {
         gi.tinit     () ;
         gi.beginpath () ;
         gi.trot      (0 , L , phi0) ;       // ... Rotation im Uhrzeigersinn
         gi.utarc (0 , L , Rc , 7*Math.PI/6 , 11*Math.PI/6 , false);  // ... oberer
         gi.utlineto  (xA*0.7 , yB)  ;                                 //     Bogen
         gi.utlineto  ( Rs , L - R)  ;
         gi.utlineto  (-Rs , L - R)  ;
         gi.utlineto  (-xA*0.7 , yB) ;
         gi.closepath () ;
         gi.fillstyle ("maroon") ;
         gi.fill   () ;
         gi.stroke () ;
         gi.utdrawfcirc (0 , L - R , Rs , "red") ;                // ... Mitnehmer
      }

Bleibt noch das Zeichnen der beiden symbolischen Drehzapfen, das in der Funktion pivots erledigt wird. Hierfür wird keine Transformation benötigt, deshalb kann eine "u...-Funktion" verwendet werden:

      function pivots () {

         var phi1 = 0 ;
         var yM   = 0 ;                            // ... Mittelpunkt des unteren Lagers
         var fillcol = "black" ;
         for (var j = 0 ; j < 2 ; j++) {
            for (var i = 0 ; i < 4 ; i++) {
               gi.udrawfpie (0 , yM , 0.9*Rs , phi1 , phi1 + Math.PI/2 , fillcol , "black") ;
               phi1 += Math.PI/2 ;
               fillcol = (fillcol == "yellow") ? "black" : "yellow" ;
            }
            phi1 = 0 ;
            yM   = L ;                             // ... Mittelpunkt des oberen Lagers
         }
      }

Die komplette HTML-Datei c_malteser.html kann in einem neuen Browser-Fenster ausgeführt werden. Sie liefert mit den hier beschriebenen Funktionen das nebenstehend zu sehende Bild.

Weiterlesen

Folgende Seiten werden als Einführung in die Thematik "Transformationen" empfohlen: