IMPRESSUM dotted_line KONTAKT dotted_line suchen dotted_line Kontakt dotted_line sitemap dotted_line ducken
203 PHP-Resource Mitglieder online

aktuelle Sprache Deutsch Umschalten auf andere Sprache Englisch

- Werbung-
php-resource

plotting masters - a professional guide - Teil I

Grafische Interpolation und Bestapproximation von numerischen Wertepaaren. Mit anderen Worten: Wir wollen Punkte auf einer Zeichenebene über verschiedene Verfahren miteinander verbinden. Die beispielorientierte Anwendung (Teil I) ist einfach und für jeden verständlich. Die formale Umsetzung (Teil II + III) sowie das individuelle Erweiterungspotential richtet sich hingegen an fortgeschrittene Programmierer.

|30.01.2010 | EVAMasters | 8413 | KAT : PHP | | Kommentare 0


1

1
                    Herkömmliche Programmiertechnik
                    mit PHP


                    1. Fassung Berlin Jun 09
                    Daniel Krompass
                    X.P.

                    2. Fassung Berlin Sep 09
                    Daniel Krompass
                    Prototyp

                    3. Fassung Berlin Feb 10
                    Daniel Krompass
                    Release



                    Ich habe mehr Werkzeuge,
                    als meine Freundin Schuhe hat.

Wir müssen die Freigabe verschieben, da ich entschieden habe, mit einer absoluten Basis anstelle der hier vorgestellten relativen Basis zu skalieren (siehe Beispiel 6). Ein absoluter Bezugspunkt (hier der Koordinatenursprung) führt je nach Werten zu einem Zuschnitt der jeweiligen Graphen. Um jeden Preis will ich auf den Algorithmus von Cohen-Sutherland verzichten. Ich denke, dass wir für unser Problem eine bessere Alternative angeben können.

Bevor es los geht, möchte ich mich bei den Plattformbetreibern für das regelmäßige Update meiner Dokumentation bedanken. Mit dem Erscheinen der Release-Version wurden die «prototypischen Schlampereien» bei der Rechnung mit Gleitkommazahlen durch geeignete Rundungstechniken besser konditioniert. Die diesbezüglich korrigierte Dokumentation zu Teil II) folgt in Kürze. Aus dem Inhalt:

  • Einleitung zur Spezifikation, Zielgruppe, Hintergrund, Motivation und Ausblick.

  • In Teil I vermitteln wir die Anwendung an konkreten Beispielen.

  • In Teil II werfen wir einen Blick in die Implementierung der verschiedenen Verfahren.

Informelle Spezifikation

    Es ist nach einem kleinen aber flexiblem PHP-Programm zum Zeichnen von kartesischen Diagrammen gesucht. Wir folgen dabei einer intuitiven Vorgehensweise: Eine Zeichenebene dient als Container für unterschiedliche Diagrammtypen, so z.B. Linien-, Punkt- oder Kurvendiagramme. Jeder derartigen Komponente werden numerische Wertepaare übergeben, die dann über die jeweiligen Verfahren interpoliert oder approximiert werden. Wir wollen hier eine stückweise lineare Interpolation (Polygonzug), sowie eine natürliche Spline-Interpolation von Wertepaaren realisieren. Ferner wollen wir noch eine optionale Flächenfüllung zwischen der jeweiligen Kurve und der X-Achse ermöglichen. Wir werden auch sehen, wie sich sogar Balkendiagramme mit diesem Kontext vertragen können.

Zielgruppe

    Jeder kann den PHP-Code privat wie auch kommerziell nutzen. Die Anwendung aus Teil I) ist einfach und für jeden verständlich. Haftungsansprüche sind ausgeschlossen. Die Dokumentation darf hingegen weder vervielfältigt, verändert noch anderweitig genutzt werden. Für den Einsteiger können einige grundlegende Gedankengänge am konkreten Beispiel lehrreich sein. Bei ausreichender Resonanz oder konkreten Fragen kann die Dokumentation auch intensiver ausgearbeitet werden, so dass der Interessierte näher an die Problemlösung herangeführt werden kann. Die Umsetzung in PHP und das individuelle Erweiterungspotenzial der vorliegenden Lösung aus Teil II) richtet sich hingegen an fortgeschrittene Programmierer mit teilweise erforderlichen Kenntnissen aus der numerischen Mathematik. Als praktisch orientierte Begleitlektüre kann Numerische Mathematik von Michael Knorrenschild hilfreich sein.

Hintergrund

    Bereits vorhandene Lösungen sind entweder fehlerhaft, zu kompliziert, oder haben nicht die gewünschte Leistung. Das folgende Programm zeigt, wie mit PHP die gewünschte Anforderung umgesetzt werden kann, auch wenn die formalen Techniken alles andere als ideal sind. In der Tat zeigt dieses Beispiel nur geringfügig die Schwächen einer durchaus etablierten Sprache, die in ihrer Entwicklung Jahrzehnte zurückliegt. Der Programmumfang umfasst keine 1000 Zeilen. Somit ist der geübte Programmierer in der Lage, das Programm an die jeweiligen Bedürfnisse anzupassen. Das Wissen über Kondition und Stabilität von Berechnungsvorgängen vermittelt ein solides Verständnis über die richtige und korrekte Formulierung einer Berechnungsvorschrift. Zuverlässige Programmierung kann i.A. ohne die Kenntnis über die spezifischen Schwerpunkte aus der höheren Mathematik nicht geleistet werden - der wesentliche Vorteil gegenüber herkömmlichem Programmierwissen. Das tägliche Brot unserer Arbeit ist durch gute Rekursionstechniken sowie Clock- und Gleitkommaarithmetiken geprägt.

Motivation

    Seit dem Ende der Amigaprogrammierung (Gehirn-Jogging über Speicheradressen) wende ich i.A. keine herkömmliche Programmierung mehr an, denn die meisten Webapplikationen löse ich technologisch und übe mich gleichzeitig darin mit modernen Webframeworks zu konkurrieren. Ein Stück amüsante Programmiergeschichte kann man in diesen Werken nachlesen: http://www.birdys.de/default.php?page=buecher&kat=11&menu=1. Die Autoren Amir und Höfler sind maßgeblich für meine Entwicklung verantwortlich, die auf Grund gewisser Nebenwirkungen 1998 ihr vorläufiges Ende fand und mit der Popularität des Internets 2002 wieder aufgenommen wurde. Der erneute Versuch dem Enthusiasmus durch ein Lehramtsstudium zu entkommen scheiterte erbärmlich.
    Ein wissenschaftlicher Schachzug brächte eine Technologie hervor, die auf Grund des vorhandenen Potenzials alle bisherigen Techniken überholt. Ob der König am Leben bleibt, muss noch entschieden werden.

Ausblick

    Neben den hier vorgestellten Interpolationsverfahren spielt ebenso die Ausgleichsrechnung (Bestapproximation) eine praktische Rolle, deren Graphen im Unterschied dazu nicht zwangsläufig durch alle Wertepaare hindurchgehen. Vielmehr ist man an einer bestmöglichen (gewichteten) Annäherung durch einen Graphen mit vorgegebenen Eigenschaften interessiert. Je nach freien Kapazitäten komme ich darauf zurück.

Teil I
   Benutzeranwendung

    Wir vermitteln die Anwendung des plotting masters durch einige konkrete Beispiele.

Beispiel 1

    Zu Beginn jeder grafischen Visualisierung von Wertepaaren initialisiert man stets ein Exemplar vom Typ Graph - unsere Zeichenebene. Diese Instanz nimmt anschließend die verschiedene Komponenten vom Typ GraphComponent auf. Der Zeichenvorgang berechnet aus allen Komponenten die jeweilige Skalierung der Wertepaare. Der Konstruktor von Graph hat kein Argument.

    1 
    2    $g = new Graph();
    3 


    Wir wollen folgend drei Komponenten mit gleichen Wertepaaren grafisch visualisieren, um die spezifischen Unterschiede zu demonstrieren. Die jeweiligen Konstruktoren nehmen einen hexadezimalcodierten RGB-Farbwert entgegen, in der die Komponente gezeichnet werden soll. Die Komponente c1 soll unsere Wertepaare durch Punkte interpolieren, d.h. die Punkte als «kleine Quadrate» zeichnen.

    1 
    2    $c1 = new GraphPoints(0x000000);
    3 


    Die Komponente c2 soll unsere Wertepaare als stückweise lineare Interpolierende darstellen, d.h. alle Punkte über eine blaue Linie verbinden.

    1 
    2    $c2 = new GraphLinear(0x0000FF);
    3 


    Die Komponente c3 soll schließlich unsere Wertepaare als natürliche Spline-Interpolierende darstellen, d.h. die Punkte werden über eine rote Kurve verbunden, die einem Polynom 3ten Grades entspricht.

    1 
    2    $c3 = new GraphNaturalSpline(0xFF0000);
    3 


    Die Komponenten müssen nun an die obige Zeichenebene g gebunden werden. Unser «Container» wird also über alle Komponenten, die wir zeichnen wollen, «informiert». Die Bindereihenfolge bestimmt dabei die Sichtbarkeit und die Verdeckung dieser Komponenten.

    1 
    2    $g->AddComponent($c1);
    3    $g->AddComponent($c2);
    4    $g->AddComponent($c3);
    5 


    Als nächstes übergeben wir den Komponenten konkrete Wertepaare. Wir wählen dabei für alle Komponenten dieselben Wertepaare um die spezifischen Unterschiede zu sehen.

     1 
     2    $c1->AddPoint(-1, 5);
     3    $c1->AddPoint(0, -2);
     4    $c1->AddPoint(1, 9);
     5    $c1->AddPoint(2, -4);
     6 
     7    $c2->AddPoint(-1, 5);
     8    $c2->AddPoint(0, -2);
     9    $c2->AddPoint(1, 9);
    10    $c2->AddPoint(2, -4);
    11 
    12    $c3->AddPoint(-1, 5);
    13    $c3->AddPoint(0, -2);
    14    $c3->AddPoint(1, 9);
    15    $c3->AddPoint(2, -4);
    16 


    Bemerkung

      Ob die Komponenten erst an die Zeichenebene gebunden und dann die Wertepaare hinzugefügt werden oder umgekehrt, spielt keine Rolle.

    Abschließend wollen wir das Gesamtdiagramm noch zeichnen. Die Funktion Draw liefert uns den Bildkontext, den wir entweder lokal speichern, oder über ein Netzwerk versenden können. Als Argument sind Vorder- und Hintergrundfarbe, Breite und Höhe, sowie die Anzahl der äquidistanten Intervalle auf der X- bzw. Y-Achse anzugeben. Letztere Angaben dienen ausschließlich der Achsenbeschriftung.

    1 
    2    $image = $g->Draw(0x000000, 0xFFFFCF, 500, 250, 3, 7);
    3    header("Content-type: image/gif");
    4    imagegif($image);
    5 


    Als Ausgabe erhalten wir:



    Es können anschließend problemlos weitere Wertepaare und/oder auch weitere Komponenten nachgetragen, und das Diagramm erneut gezeichnet werden.

     1 
     2    $c4 = new GraphNaturalSpline(0xFF0000);
     3    $g->AddComponent($c4);
     4    $c4->AddPoint(0, 10);
     5    $c4->AddPoint(1, 15);
     6    $c4->AddPoint(2, 10);
     7    $c4->AddPoint(3, -1);
     8 
     9    $c5 = new GraphPoints(0x000000);
    10    $g->AddComponent($c5);
    11    $c5->AddPoint(0, 10);
    12    $c5->AddPoint(1, 15);
    13    $c5->AddPoint(2, 10);
    14    $c5->AddPoint(3, -1);
    15 
    16    $image = $g->Draw(0x000000, 0xFFFFCF, 500, 250, 4, 19);
    17    header("Content-type: image/gif");
    18    imagegif($image);
    19 


    Mit den angepassten Werten 4 und 19 für die Anzahl der äquidistanten Intervalle auf den Koordinatenachsen erhalten wir:


Beispiel 2

    In vielen Fällen wünschen wir eine spezielle Formatierung der Achsenbeschriftungen, so z.B. Zeit- oder Währungsangaben. Dazu müssen wir die numerischen Werte so wählen, dass wir daraus andere Darstellungen berechnen können. Um den formalen Overhead gering zu halten, verzichten wir auf spezielle Typvereinbarungen, und nutzen die formalen Möglichkeiten der Sprache gezielt aus. Wir geben eine Funktion an, die wahlweise auf die numerischen X- bzw. Y-Werte angewendet wird. In der funktionalen Programmierung sprechen wir vom sog. Mapping. Wir definieren für unseren Fall zwei Beispielfunktionen.

     1 
     2    function ToCurrency($item)
     3    {
     4       return number_format($item * 100, 2, 0);
     5    }
     6    function ToDate($item)
     7    {
     8       return date("d.m.Y", time() + $item * 86400);
     9    }
    10 


    Abschließend veranlassen wir noch die (erneute) Zeichnung.

    1 
    2    $image = $g->Draw(0x000000, 0xFFFFCF, 600, 350, 3, 14, "ToDate", "ToCurrency");
    3    header("Content-type: image/gif");
    4    imagegif($image);
    5 


    Als Ausgabe erhalten wir:


Beispiel 3 (fortgeschritten)

    In vielen Webanwendungen wollen wir gerade die Daten aus einer Datenbank grafisch visualisieren. In diesem Beispiel wollen wie eine Gehaltskurve von Mitarbeitern zeichnen. Dazu benötigen wir zunächst eine geeignete Datentabelle.

    Id Name Gehalt
    1 Martin A. 3.230,00
    2 Theresa B. 3.032,00
    3 Andrea C. 1.897,00
    4 Günter D. 2.980,00

    Wie gehabt generieren wir wieder unseren Graphen in üblicher Form.

    1 
    2    $g  = new Graph();
    3    $c1 = new GraphNaturalSpline(0xFF0000);
    4    $c2 = new GraphPoints(0x000000);
    5    $g->AddComponent($c1);
    6    $g->AddComponent($c2);
    7 


    Die Werte lesen wir über eine entsprechende mySQL-Anweisung aus der obigen Datentabelle aus. Mehr zum Thema mySQL findet man unter http://www.php-resource.de/tutorials/tutorial,27 oder http://www.php-resource.de/tutorials/tutorial,44. Wir probieren zunächst einen offensichtlichen Ansatz:
    Zuerst überlegen wir uns, wie wir unsere Map-Funktion so definieren, dass wir auf der X-Achse die Namen der jeweilgen Mitarbeiter zu stehen haben. Wir müssen also von einer Zahl auf den zugehörigen Namen eindeutig schließen können. Es bietet sich dabei die Assoziation zwischen der Id-Nummer und dem zugehörigen Namen an.

     1 
     2    function ToEmployer($item)
     3    {
     4       $result = mysql_query("SELECT Name
     5                              FROM mitarbeiter
     6                              WHERE Id = $item");
     7 
     8       return mysql_result($result, 0, 0);
     9    }
    10 


    Sodann lesen wir die Werte aus der Datentabelle mit

    1 
    2    $result = mysql_query("SELECT Id, Name, Gehalt
    3                           FROM mitarbeiter");
    4    for ($i = 0; $row = mysql_fetch_array($result); $i++)
    5    {
    6       $c1->AddPoint((int)$row[0], (int)$row[2]);
    7       $c2->AddPoint((int)$row[0], (int)$row[2]);
    8    }
    9 


    aus und erhalten mit

    1 
    2    $image = $g->Draw(0x000000, 0xFFFFCF, 600, 350, 3, 5, "ToEmployer", "ToCurrency");
    3    header("Content-type: image/gif");
    4    imagegif($image);
    5 




    Wenn Sie nun eine spezielle Sortierung z.B. ORDER BY Gehalt ASC fordern, dann hätte dies keine Auswirkungen auf die grafische Ausgabe. Das liegt daran, dass der Spline seinen Kurvenzug unabhängig von der Einfügereihenfolge der Knotenpunkte zeichnet. Achten Sie stets darauf, dass jede mathematische Funktion strikt von links nach rechts gezeichnet wird. Insbesondere werden alle Punkte stets nach ihrem X-Wert aufsteigend sortiert, bevor diese zur Brechnung herangezogen werden. Wir können also nicht mit der Id aus der Datentabelle als X-Wert sinnvoll arbeiten, und müssen daher eine eigene Id auf Programmebene erzeugen:

     1 
     2    $result = mysql_query("SELECT Id, Name, Gehalt
     3                           FROM mitarbeiter2
     4                           ORDER BY Gehalt ASC");
     5 
     6    for ($i = 0; $row = mysql_fetch_array($result); $i++)
     7    {
     8       $mitarbeiter[$i] = $row[1];
     9       $c1->AddPoint($i, (int)$row[2]);
    10       $c2->AddPoint($i, (int)$row[2]);
    11    }
    12 
    13    function ToEmployer($item)
    14    {
    15       global $mitarbeiter;
    16       return $mitarbeiter[$item];
    17    }
    18 


    Nun erhalten wir jede gewünschte Sortierung «richtig» gezeichnet.


Beispiel 4

    Ein etwas abtrünniges Beispiel - Polygonzüge

     1 
     2    # Zeichenebene
     3    $g = new Graph();
     4 
     5    # Komponenten
     6    $c1 = new GraphLinear(0x0000FF);
     7    $c2 = new GraphLinear(0xFF0000);
     8 
     9    # Komponenten binden
    10    $g->AddComponent($c1);
    11    $g->AddComponent($c2);
    12 
    13    # Werte hinzufügen
    14    $c1->AddPoint(0, 2);
    15    $c1->AddPoint(1, 2);
    16    $c1->AddPoint(2, 3);
    17    $c1->AddPoint(2, 4);
    18    $c1->AddPoint(1, 5);
    19    $c1->AddPoint(0, 5);
    20    $c1->AddPoint(-1, 4);
    21    $c1->AddPoint(-1, 3);
    22    $c1->AddPoint(0, 2);
    23 
    24    $c2->AddPoint(0, 2);
    25    $c2->AddPoint(0, 1);
    26    $c2->AddPoint(-1, 0);
    27    $c2->AddPoint(-2, 0);
    28    $c2->AddPoint(-3, 1);
    29    $c2->AddPoint(-3, 2);
    30    $c2->AddPoint(-2, 3);
    31    $c2->AddPoint(-1, 3);
    32 
    33    # Ausgabe
    34    $image = $g->Draw(0x000000, 0xFFFFCF, 600, 350, 5, 5);
    35    header("Content-type: image/gif");
    36    imagegif($image);
    37 


    Wir erhalten:



    Der Sinn von sog. Linienzügen zeigt sich bei praktischen Vorgängen, die einen senkrechten Anstieg zur Folge haben. Dies können z.B. Gehalts- oder Auszahlungsänderungen sein. Wir betrachten ein Beispiel:

     1 
     2    include ("graph.php");
     3    
     4    # Zeichenebene
     5    $g = new Graph();
     6 
     7    # Komponenten
     8    $c1 = new GraphLinear(0x0000FF);
     9    $c2 = new GraphLinear(0xFF0000);
    10 
    11    # Komponenten binden
    12    $g->AddComponent($c1);
    13    $g->AddComponent($c2);
    14 
    15    # Werte hinzufügen
    16    $c1->AddPoint(0, 4);
    17    $c1->AddPoint(1, 4);
    18    $c1->AddPoint(1, 3);
    19    $c1->AddPoint(2, 3);
    20    $c1->AddPoint(2, 4);
    21    $c1->AddPoint(2.5, 4);
    22    $c1->AddPoint(2.5, -2);
    23    $c1->AddPoint(3.5, -2);
    24    $c1->AddPoint(3.5, 6);
    25 
    26    $c2->AddPoint(-1, 0);
    27    $c2->AddPoint(-1, 2);
    28    $c2->AddPoint(0, 2);
    29    $c2->AddPoint(0, 0);
    30    $c2->AddPoint(1, 0);
    31    $c2->AddPoint(1, 2);
    32    $c2->AddPoint(2, 2);
    33    $c2->AddPoint(2, 0);
    34    $c2->AddPoint(3, 0);
    35    $c2->AddPoint(3, 2);
    36    $c2->AddPoint(4, 2);
    37    $c2->AddPoint(4, 0);
    38 
    39    # Ausgabe
    40    $image = $g->Draw(0x000000, 0xFFFFCF, 500, 250, 5, 4, "ToDate", "ToCurrency");
    41    header("Content-type: image/gif");
    42    imagegif($image);
    43 


    Wir erhalten:



Beispiel 5 (fortgeschritten)

    Es gibt Fälle, bei denen es nicht erwünscht ist, dass der kleinste Y-Wert stets auf der X-Achse, oder der kleinste X-Wert stets auf der Y-Achse liegt. Wir werden weiter unten weitere Probleme ansprechen, die mit den folgenden Verfahren gelöst werden können. Um die Achsenbeschriftungen (nicht die Achsen selbst), und somit auch den gesamten Graphen horizontal und/oder vertikal zu stauchen (unsinnigerweise auch strecken), können zwei weitere Parameter für die X- bzw. Y-Stauchung angegeben werden. Mit

     1 
     2    # Zeichenebene
     3    $g = new Graph();
     4 
     5    # Komponenten
     6    $c1 = new GraphPoints(0x000000);
     7    $c2 = new GraphLinear(0x0000FF);
     8    $c3 = new GraphNaturalSpline(0xFF0000);
     9 
    10    # Komponenten binden
    11    $g->AddComponent($c1);
    12    $g->AddComponent($c2);
    13    $g->AddComponent($c3);
    14 
    15    # Wertepaare
    16    $c1->AddPoint(-1, 5);
    17    $c1->AddPoint(0, -2);
    18    $c1->AddPoint(1, 9);
    19    $c1->AddPoint(2, -4);
    20 
    21    $c2->AddPoint(-1, 5);
    22    $c2->AddPoint(0, -2);
    23    $c2->AddPoint(1, 9);
    24    $c2->AddPoint(2, -4);
    25 
    26    $c3->AddPoint(-1, 5);
    27    $c3->AddPoint(0, -2);
    28    $c3->AddPoint(1, 9);
    29    $c3->AddPoint(2, -4);
    30 


    und

    1 
    2    $image = $g->Draw(0x000000, 0xFFFFCF, 600, 350, 3, 7, "", "", 50, 50);
    3    header("Content-type: image/gif");
    4    imagegif($image);
    5 


    erhalten wir eine horizontale und eine vertikale Stauchung von 50 Pixel.


Beispiel 6 (fortgeschritten)

    Auch die X- und Y-Basis (kleinster X- und Y-Wert) einer Komponente kann über zwei weitere Parameter verschoben werden. Mit

     1 
     2    # Zeichenebene
     3    $g = new Graph();
     4 
     5    # Komponenten
     6    $c1 = new GraphPoints(0x000000);
     7    $c2 = new GraphLinear(0x0000FF);
     8    $c3 = new GraphNaturalSpline(0xFF0000, 1, 2);
     9 
    10    # Komponenten binden
    11    $g->AddComponent($c1);
    12    $g->AddComponent($c2);
    13    $g->AddComponent($c3);
    14 
    15    # Wertepaare
    16    $c1->AddPoint(-1, 5);
    17    $c1->AddPoint(0, -2);
    18    $c1->AddPoint(1, 9);
    19    $c1->AddPoint(2, -4);
    20 
    21    $c2->AddPoint(-1, 5);
    22    $c2->AddPoint(0, -2);
    23    $c2->AddPoint(1, 9);
    24    $c2->AddPoint(2, -4);
    25 
    26    $c3->AddPoint(-1, 5);
    27    $c3->AddPoint(0, -2);
    28    $c3->AddPoint(1, 9);
    29    $c3->AddPoint(2, -4);
    30 


    und

    1 
    2    $image = $g->Draw(0x000000, 0xFFFFCF, 600, 350, 3, 7, "", "", 50, 50);
    3    header("Content-type: image/gif");
    4    imagegif($image);
    5 


    erhalten wir eine Verschiebung



    Im Grunde passiert nichts weiter, als dass das X oder Y-Minimum um den angegebenen Wert (hier x=1, y=2) vermindert wird. Wir erhalten einen entsprechenden Abstand zu den Achsen.

Beispiel 7 (fortgeschritten)

    Die sog. Balkendiagramme sind etwas artfremd, und lassen sich daher nicht so offensichtlich in den vorgegeben mathematischen Kontext sinnvoll einbinden. Die beiden zuletzt vorgestellten Verfahrenstechniken werden uns dabei helfen. Betrachten wir zunächst in gewohnter Weise:

     1 
     2    # Zeichenebene
     3    $g = new Graph();
     4 
     5    # Komponenten
     6    $c1 = new GraphBar(0x000000, 0x0000FF, 30);
     7 
     8    # Komponenten binden
     9    $g->AddComponent($c1);
    10 
    11    # Wertepaare
    12    $c1->AddPoint(-1, 4);
    13    $c1->AddPoint(0, 7);
    14    $c1->AddPoint(1, 2);
    15    $c1->AddPoint(2, 9);
    16    $c1->AddPoint(3, 8);
    17    $c1->AddPoint(4, 4);
    18    $c1->AddPoint(5, 2);
    19 
    20    # Ausgabe
    21    $image = $g->Draw(0x000000, 0xFFFFCF, 500, 250, 6, 7);
    22    header("Content-type: image/gif");
    23    imagegif($image);
    24 


    Der Konstruktor nimmt zwei RGB-Farbwerte für den links-recht-Farbverlauf, sowie die Balkenbreite von 30 Pixel entgegen. Als Ausgabe erhalten wir:



    Es fallen zwei unschöne Dinge auf. Der linke Balken überschneidet unsere Y-Achse und es fehlen zwei Balken. Das erste Problem lösen wir mit einer horizontalen Stauchung von - sagen wir 20 Pixel. Mit

    1 
    2    $image = $g->Draw(0x000000, 0xFFFFCF, 500, 250, 6, 7, "", "", 20, 0);
    3 


    erhalten wir:



    Damit unsere kleinsten Balken sichtbar werden, erniedrigen wir die Y-Basis der Komponente um 2, d.h. der kleinste Y-Wert wird um 2 weiter minimiert. Mit

    1 
    2    $c1 = new GraphBar(0x000000, 0x0000FF, 30, 0, 2);
    3    $image = $g->Draw(0x000000, 0xFFFFCF, 500, 250, 6, 9, "", "", 20, 0);
    4 


    und den entsprechenden Wertepaaren erhalten wir die gewünschte Ausgabe:



    Achten Sie auf die Werte der Y-Achse. Natürlich bleibt die multible Anwendung mit

     1 
     2    include ("graph.php");
     3    
     4    # Zeichenebene
     5    $g = new Graph();
     6 
     7    # Komponenten
     8    $c1 = new GraphBar(0x000000, 0x0000FF, 30, 0, 2);
     9    $c2 = new GraphPoints(0x000000);
    10    $c3 = new GraphNaturalSpline(0xFF0000);
    11    
    12    # Komponenten binden
    13    $g->AddComponent($c1);
    14    $g->AddComponent($c2);
    15    $g->AddComponent($c3);
    16 
    17    # Wertepaare
    18    $c1->AddPoint(-1, 4);
    19    $c1->AddPoint(0, 7);
    20    $c1->AddPoint(1, 2);
    21    $c1->AddPoint(2, 9);
    22    $c1->AddPoint(3, 8);
    23    $c1->AddPoint(4, 4);
    24    $c1->AddPoint(5, 2);
    25    
    26    $c2->AddPoint(-1, 4);
    27    $c2->AddPoint(0, 7);
    28    $c2->AddPoint(1, 2);
    29    $c2->AddPoint(2, 9);
    30    $c2->AddPoint(3, 8);
    31    $c2->AddPoint(4, 4);
    32    $c2->AddPoint(5, 2);
    33 
    34    $c3->AddPoint(-1, 4);
    35    $c3->AddPoint(0, 7);
    36    $c3->AddPoint(1, 2);
    37    $c3->AddPoint(2, 9);
    38    $c3->AddPoint(3, 8);
    39    $c3->AddPoint(4, 4);
    40    $c3->AddPoint(5, 2);
    41    
    42    # Ausgabe
    43    $image = $g->Draw(0x000000, 0xFFFFCF, 500, 250, 6, 5, "", "", 20, 0);
    44    header("Content-type: image/gif");
    45    imagegif($image);
    46 


    erhalten.


Beispiel 8 (fortgeschritten)

    Eine Modifikation der Klasse GraphBar (siehe Teil II - Implementierungsdetails) ermöglicht Balkendiagramme zu zeichnen, deren «Fuss» nicht zwangsläufig auf der X-Achse liegt. Vielmehr wollen wir von einem gegebenen Punkt aus nicht nach «unten» zur X-Achse hin, sondern in einer vorgegebenen Länge nach «oben» zeichnen. Man betrachte dazu folgendes Szenario und man achte auf die Unterschiede der Methode AddPoint, denn das optionale dritte Argument gibt die Balkenlänge an.

     1 
     2    include ("graph.php");
     3    
     4    # Zeichenebene
     5    $g = new Graph();
     6 
     7    # Komponenten
     8    $c1 = new GraphBar(0x000000, 0xFFFF00, 15, 0, 2);
     9    $c2 = new GraphBar(0x000000, 0xFF0000, 15, 0, 2);
    10    $c3 = new GraphBar(0x000000, 0x0000FF, 15, 0, 2);
    11 
    12    # Komponenten binden
    13    $g->AddComponent($c1);
    14    $g->AddComponent($c2);
    15    $g->AddComponent($c3);
    16 
    17    # Werte hinzufügen
    18    $c1->AddPoint(-1, 4);
    19    $c1->AddPoint(0, 7);
    20    $c1->AddPoint(1, 2);
    21    $c1->AddPoint(2, 9);
    22    $c1->AddPoint(7, 4);
    23    $c1->AddPoint(8, 7);
    24    $c1->AddPoint(9, 2);
    25    $c1->AddPoint(10, 9);
    26 
    27    $c2->AddPoint(-1, 4, 4);
    28    $c2->AddPoint(0, 7, 2);
    29    $c2->AddPoint(1, 2, 3);
    30    $c2->AddPoint(2, 9, 5);
    31    $c2->AddPoint(3, 4, 4);
    32    $c2->AddPoint(4, 7, 2);
    33    $c2->AddPoint(5, 2, 3);
    34    $c2->AddPoint(6, 9, 5);
    35    
    36    $c3->AddPoint(7, 5, 4);
    37    $c3->AddPoint(8, 8, 2);
    38    $c3->AddPoint(9, 3, 3);
    39    $c3->AddPoint(10, 10, 5);
    40    
    41    # Ausgabe
    42    $image = $g->Draw(0x000000, 0xFFFFCF, 500, 250, 5, 4, "", "", 20, 0);
    43    header("Content-type: image/gif");
    44    imagegif($image);
    45 


    Als Ausgabe erhalten wir:



    Die Zeichnung von waagerechten Balken folgt.
Kommentare zum Tutorial
Tutorial kommentieren
 
Über den Autor
EVAMasters

EVAMasters

Status
Premium Mitglied

Beruf
Angestellter

Mitglied seit:
21.07.2009

letzte Aktivität
04.03.2010

 

Tutorial bewerten

Hat Ihnen dieses Tutorial gefallen? Dann bewerten Sie es jetzt! Fünf Sterne bedeutet "Sehr gut", ein Stern "Unzureichend".

webhosting und Server

 

aktuelle Artikel

PHP 5.3.2 60 Fehler weniger

PHP 5.3.2 60 Fehler wenigerDie Core-Developer von PHP haben ein weiteres Maintenance-Release von PHP 5.3 veröffentlicht. Neben dem schließen von Sicherheitslücken wurden 60 bekannte Fehler in der aktuellen PHP 5.3.2 Version behoben.

05.03.2010 | Neu | Berni

500. Artikel bei phphatesme.com

500. Artikel bei phphatesme.comDer 500. Artikel ist veröffentlicht. Eine Leistung, die den jungen Blog direkt an die Spitze der deutschsprachigen Bloggerszene katapultiert hat und das innnerhalb der letzten 1,5 Jahren.

22.02.2010 | Neu | phphatesme



1&1 Webhosting