Grafikbibliothek:imageline() liefert krumme Werte

Status
Dieses Thema wurde gelöst! Zur Lösung gehen…

tklustig

Erfahrenes Mitglied
Hallo Leute,
folgender Code liefert eine ungenau Ausgabe an Temperaturwerten aus der Datenbank. Die Achsenbeschriftungen stimmen soweit, allerdings wird die temperatur nur andeutungsweise ausgegeben. Die Temperaturwerte im Array lauten: 11,11,11,12,12,12,12,12,12,13,13,13
So sieht's aus:
tempgraphicsPHP.jpg

hier der Code:
PHP:
<?php

session_start();
error_reporting(E_ALL ^ E_NOTICE);
// Grafik erzeugen
$im = imagecreate(400, 400);
// Farben, Schriftart
$grau = imagecolorallocate($im, 192, 192, 192);
imagefill($im, 0, 0, $grau);
$s = imagecolorallocate($im, 0, 0, 0);
$r = imagecolorallocate($im, 255, 0, 0);
$folder = getcwd();
$schriftart = $folder . "/inc/Free Hustle Hardcore.ttf";
// Werte
spl_autoload_register('classAutoloader');
$DatabaseObject = new MySQLClass('root', '', 'mysql', '192.168.1.10', 'temperatur');
$connection = $DatabaseObject->Verbinden();
if (!$connection){
    print_r("MySQL-Aufbau ist gescheitert!");
    die();
}
if (isset($_SESSION['pk']))
    $id = $_SESSION['pk'];
else
    $id = 100;
$sql = "SELECT id,Temperatur_Celsius,Luftfeuchtigkeit_Prozent,datum,uhrzeit FROM temperaturs WHERE id>=$id ORDER BY id ASC LIMIT 12";
$query1 = $DatabaseObject->Abfragen($connection, $sql);
$temperaturA = array();
$uhrzeitA = array();
for ($i = 0; $i < count($query1); $i++) {
    $record = $query1[$i]['Temperatur_Celsius'];
    array_push($temperaturA, $record);
    $record = $query1[$i]['uhrzeit'];
    array_push($uhrzeitA, $record);
}
// Gitternetz, Beschriftung
for ($i = 0; $i < count($uhrzeitA); $i++) {
    imageline($im, 30, 30 + $i * 340 / count($uhrzeitA), 370, 30 + $i * 340 / count($uhrzeitA), $s);
    imagettftext($im, 11, 0, 375, 30 + $i * 340 / count($uhrzeitA), $s, $schriftart, max($temperaturA) - $i);
    imageline($im, 30 + $i * 340 / count($uhrzeitA), 30, 30 + $i * 340 / count($uhrzeitA), 370, $s);
    $time = date("G:i", strtotime($uhrzeitA[$i]));
    imagettftext($im, 11, 0, 25 + $i * 340 / count($uhrzeitA), 380, $s, $schriftart, $time);
}

// Temperatur darstellen:11,11,11,12,12,12,12,12,12,13,13,13
for ($i = 0; $i < count($temperaturA) - 1; $i++) {
    imageline($im, ($i + 1) * 300 / 10, 130 - $temperaturA[$i] * 130 / 50, ($i + 2) * 300 / 10, 130 - $temperaturA[$i + 1] * 130 / 50, $r);
}
// Grafik darstellen
header("Content-Type: image/jpeg");
imagejpeg($im);

// Speicher freigeben
imagedestroy($im);
?>
 

Anhänge

  • tempgraphicsPHP.jpg
    tempgraphicsPHP.jpg
    90,4 KB · Aufrufe: 3
Zuletzt bearbeitet:
Sieht vielversprechend aus.
Diesem Beispiel wird das Array übergeben, und Fertig! Genau das, was ich eigentlich brauche. Nichts desto Trotz: Vielleicht weiß der eine oder andere, wie man das Array $temperaturA grafisch darstellt? Eigentlich muß 'nur' die zählerindizierte Schleife
PHP:
// Temperatur darstellen:11,11,11,12,12,12,12,12,12,13,13,13
for ($i = 0; $i < count($temperaturA) - 1; $i++) {
    imageline($im, ($i + 1) * 300 / 10, 130 - $temperaturA[$i] * 130 / 50, ($i + 2) * 300 / 10, 130 - $temperaturA[$i + 1] * 130 / 50, $r);
}
korrekt implementiert werden...
 
Ich empfehle, die Umrechnung der Werte (Zeit, Temp., Feuchte) in Pixel-Koordinaten nicht bei jedem Gebrauch auszuformulieren, sondern dafür Funktionen zu definieren, dann wird das Ganze übersichtlicher:
Code:
// Grafik erzeugen
$im = imagecreate(400, 500);
// Farben, Schriftart
$grau = imagecolorallocate($im, 192, 192, 192);
imagefill($im, 0, 0, $grau);
$s = imagecolorallocate($im, 0, 0, 0);
$r = imagecolorallocate($im, 255, 0, 0);
$b = imagecolorallocate($im, 0, 0, 255);
$folder = getcwd();
$schriftart = $folder . "/century-gothic.ttf";

// die Daten, Temperatur und Feuchte (y-Achse) sowie Uhrzeit (x-Achse)
$temperaturA = [11,11,11,12,12,12,12,12,12,13,13,13];
$feuchteA = [70, 70, 75, 75, 80, 80, 85, 85, 90, 90, 85, 85];
$uhrzeitA = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];

// Ursprung des Koordinatensystems in px festlegen
$xursprung = 10;
$yursprung = 470;

// Faktoren für Umrechnung der Indizes in px
$factorx = 30;
$factory = 30;

// Faktor um die Darstellung der Feuchte umzurechnen
$factoryhum = 10;

// Anzahl der Rasterlinien
$nrx = 11;
$nry = 15;

// x-Koordinate in px aus x-Wert ermitteln
function getx($x) {
    global $xursprung, $factorx;
    return $xursprung + $x * $factorx;
}

// y-Koordinate in px aus y-Wert ermitteln
function gety($y) {
    global $yursprung, $factory;
    return $yursprung - $y * $factory;
}

// Gitternetz, Beschriftung

// vertikale Linien mit Beschriftung
for ($i = 0; $i <= $nrx; $i++) {
    imageline($im, getx($i), gety(0), getx($i), gety($nry), $s);
    imagettftext($im, 11, 0, getx($i), gety(0) + 15, $s, $schriftart, $uhrzeitA[$i]);
}

// horizontale Linien mit Beschriftung
for ($j = 0; $j <= $nry; $j++) {
    imageline($im, getx(0), gety($j), getx($nrx), gety($j), $s);
    imagettftext($im, 11, 0, getx($nrx) + 5, gety($j), $r, $schriftart, $j);
    imagettftext($im, 11, 0, getx($nrx) + 25, gety($j), $b, $schriftart, $j * $factoryhum);
}

// Temperatur- und Feuchtewerte eintragen
for ($k = 0; $k < $nrx; $k++) {
    imageline($im, getx($k), gety($temperaturA[$k]), getx($k + 1), gety($temperaturA[$k + 1]), $r);
    imageline($im, getx($k), gety($feuchteA[$k] / $factoryhum), getx($k + 1), gety($feuchteA[$k + 1] / $factoryhum), $b);
}

// Grafik darstellen
header("Content-Type: image/jpeg");
imagejpeg($im);

// Speicher freigeben
imagedestroy($im);
Man gewinnt dabei eine Vorstellung davon, wieviel Arbeit in solchen Bibliotheken für das Zeichnen von Diagrammen steckt. Was ich da gebaut habe ist ja bei weitem nicht so flexibel und anpassungsfähig wie diese.
 
Die Bibliothek erlaubt mir nicht die Verwendung von Arraywerten als Achenbezeichnungen und ist damit ungeeignet. Die horizontale Zeitachse sind Arraywerte aus der Datenbank in der Form von 0:00 bis 23:30! Deine Lösung sieht eigentlich ganz vielversprechend aus, allerdings sind die Werte zu statisch. Die Datenbankwerte können von 5 -34 alles enthalten. Wenn Dein Code Zufallswerte von 0-40 verarbeiten könnte, er wäre Gold wert. Hier eine Abwandlung, die allerdings so noch nicht funktioniert:
PHP:
/* die Daten, Temperatur und Feuchte (y-Achse) sowie Uhrzeit (x-Achse)
  $temperaturA = [11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13];
  $feuchteA = [70, 70, 75, 75, 80, 80, 85, 85, 90, 90, 85, 85];
  $uhrzeitA = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]; */

// Ursprung des Koordinatensystems in px festlegen
$xursprung = 20;
$yursprung = 470;

// Faktoren für Umrechnung der Indizes in px
$factorx = 30;
$factory = 30;

// Faktor um die Darstellung der Feuchte umzurechnen
$factoryhum = 10;

// Anzahl der Rasterlinien
$nrx = count($temperaturA) - 1;
$nry = count($uhrzeitA);

// x-Koordinate in px aus x-Wert ermitteln
function getx($x) {
    global $xursprung, $factorx;
    return $xursprung + $x * $factorx;
}

// y-Koordinate in px aus y-Wert ermitteln
function gety($y) {
    global $yursprung, $factory;
    return $yursprung - $y * $factory;
}

/* Gitternetz, Beschriftung
  vertikale Linien mit Beschriftung */
for ($i = 0; $i <= $nrx; $i++) {
    imageline($im, getx($i), gety(0), getx($i), gety($nry), $s);
    imagettftext($im, 11, 0, getx($i), gety(0) + 15, $s, $schriftart, $uhrzeitA[$i]);
}
// horizontale Linien mit Beschriftung
for ($j = min($temperaturA); $j <= max($temperaturA); $j++) {
    // Temperaturscala
    imageline($im, getx(0), gety($j), getx($nrx), gety($j), $s);
    imagettftext($im, 11, 0, getx($nrx) + 5, gety($j), $r, $schriftart, $j);
    /* Luftfeuchtigkeitsscala
      imagettftext($im, 11, 0, getx($nrx) + 25, gety($j), $b, $schriftart, $j * $factoryhum);
     */
}
// Temperaturwerte eintragen. Luftfeuchtigkeit folgt...
for ($k = 0; $k < $nrx; $k++) {
    imageline($im, getx($k), gety($temperaturA[$k]), getx($k + 1), gety($temperaturA[$k + 1]), $r);
    imagettftext($im, 20, 0, getx(0), gety(14), $s, $schriftart, $datumA[0]);
    //imageline($im, getx($k), gety($feuchteA[$k] / $factoryhum), getx($k + 1), gety($feuchteA[$k + 1] / $factoryhum), $b);
}
// Grafik darstellen
header("Content-Type: image/jpeg");
imagejpeg($im);
// Speicher freigeben
imagedestroy($im);
temppic.jpg
 
Zuletzt bearbeitet:
Die Bibliothek erlaubt mir nicht die Verwendung von Arraywerten als Achenbezeichnungen und ist damit ungeeignet. Die horizontale Zeitachse sind Arraywerte aus der Datenbank in der Form von 0:00 bis 23:30!
Null Problemo, solche Bibltiotheken sind i. allg flexibel. Die Beschriftung der x-Achse kann aus einem Array übernommen werden:
Code:
<?php // content="text/plain; charset=utf-8"
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
require_once 'jpgraph/jpgraph.php';
require_once 'jpgraph/jpgraph_line.php';

// $datay1 = array(20, 15, 23, 15);
// $datay2 = array(12, 9, 42, 8);
// $datay3 = array(5, 17, 32, 24);
// die Daten, Temperatur und Feuchte (y-Achse) sowie Uhrzeit (x-Achse)
$temperaturA = [11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13];
$feuchteA = [70, 70, 75, 75, 80, 80, 85, 85, 90, 90, 85, 85];
$uhrzeitA = ["10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", "17:00", "18:00", "19:00", "20:00", "21:00"];

// Setup the graph
$graph = new Graph(600, 500);
$graph->SetScale("textlin");

$theme_class = new UniversalTheme;

$graph->SetTheme($theme_class);
$graph->img->SetAntiAliasing(false);
$graph->title->Set('Filled Y-grid');
$graph->SetBox(false);

$graph->SetMargin(40, 20, 36, 63);

$graph->img->SetAntiAliasing();

$graph->yaxis->HideZeroLabel();
$graph->yaxis->HideLine(false);
$graph->yaxis->HideTicks(false, false);

$graph->xgrid->Show();
$graph->xgrid->SetLineStyle("solid");
$graph->xaxis->SetTickLabels($uhrzeitA);
$graph->xgrid->SetColor('#E3E3E3');

// Create the first line
$p1 = new LinePlot($temperaturA);
$graph->Add($p1);
$p1->SetColor("#6495ED");
$p1->SetLegend('Temperatur');

// Create the second line
$p2 = new LinePlot($feuchteA);
$graph->Add($p2);
$p2->SetColor("#B22222");
$p2->SetLegend('Luftfeuchtigkeit');

// Create the third line
// $p3 = new LinePlot($datay3);
// $graph->Add($p3);
// $p3->SetColor("#FF1493");
// $p3->SetLegend('Line 3');

$graph->legend->SetFrameWeight(1);

// Output line
$graph->Stroke();
In der Doku gibt es auch ein Kaptitel für "multiple y-axis", d. h. eine individuelle Beschriftung für Temp., Feuchte etc. sollte machbar sein.
 
Zuletzt bearbeitet:
Na gut, dann werde ich mal versuchen, die Libray in mein Temperaturprojekt zu integrieren. Was mich a bissel stört ist der enorme Umfang der zu integrierenden Klassen bzw. Dateien. Wenn es nur die
jpgraph.php und jpgraph_line.php wären, kein Problem. Allerdings enthält die jpgraph.php zahlreiche require_once Anweisungen, die wiederum andere Dateien integrieren. Eigentlich wollte ich das Projekt schlank halten, was bei Verwendung dieser Bibliothek so nicht mehr haltbar ist.
 
So, habe die Library jetzt initialisiert und werde im nächsten Schritt ma' eruiere, welche der Dateien ich löschen kann, um das Projekt so schmall wie möglich zu halten. Ein Dartsellungsfehler hat die ganze Sache allerdings noch. Für das Array:
PHP:
$temperaturA = [21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20];
ergibt sich folgende Ausgabe:
diagramm.jpg

Eigentlich sollten die Werte für 20 auch noch sichtbar sein; entweder knapp über der x-Achse oder auf der x-Achse. Momentan entsteht der Eindruck, ab 1:30 Uhr gäbe es keine Messwerte mehr...
 
Zuletzt bearbeitet:
Was mich a bissel stört ist der enorme Umfang der zu integrierenden Klassen bzw. Dateien.
Das stimmt, es sind mehrere Megabyte. Es erleichtert die Sache jedoch, dass sich das Ganze auf dem Server abspielt, die Dateien müssen ja nicht herunter geladen werden.

Eigentlich sollten die Werte für 20 auch noch sichtbar sein; entweder knapp über der x-Achse oder auf der x-Achse. Momentan entsteht der Eindruck, ab 1:30 Uhr gäbe es keine Messwerte mehr...
Das habe ich auch bemerkt und man kann etwas machen: Der Maximal- und Minimalwert des Gitters lassen sich verschieben, so dass die Linien nicht ganz oben oder ganz unten liegen:
Code:
<?php // content="text/plain; charset=utf-8"
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
require_once 'jpgraph/jpgraph.php';
require_once 'jpgraph/jpgraph_line.php';

// die Daten, Temperatur und Feuchte (y-Achse) sowie Uhrzeit (x-Achse)
$temperaturA = [11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13];
$feuchteA = [70, 70, 75, 75, 80, 80, 85, 85, 90, 90, 85, 85];
$uhrzeitA = ["10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", "17:00", "18:00", "19:00", "20:00", "21:00"];

$graph = new Graph(600, 500);
$graph->SetMargin(40, 150, 40, 30);
$graph->SetMarginColor('white');

// Hier wird der Min- und Max-Wert fuer die Feuchte festgelegt
$graph->SetScale('intlin', 0, 100);
$graph->yscale->ticks->Set(10);
$graph->title->Set('Using multiple Y-axis');
$graph->title->SetFont(FF_ARIAL, FS_NORMAL, 14);
$graph->xgrid->Show();
$graph->ygrid->Show();
$graph->xgrid->SetLineStyle("solid");
$graph->xgrid->SetColor('#E3E3E3');
$graph->xaxis->SetTickLabels($uhrzeitA);

// Hier wird der Min- und Max-Wert fuer die Temperatur festgelegt
$graph->SetYScale(0, 'lin', -20, 30);

$graph->yaxis->SetColor('blue');

$p1 = new LinePlot($feuchteA);
$graph->Add($p1);
$p1->SetColor('blue');
$p1->SetLegend('Luftfeuchtigkeit');

$p2 = new LinePlot($temperaturA);
$graph->AddY(0, $p2);
$p2->SetColor('red');
$p2->SetLegend('Temperatur');
$graph->ynscale[0]->ticks->Set(5);
$graph->ynaxis[0]->SetColor('red');

// Output line
$graph->Stroke();
Was ich ein wenig enttäuschend bei dieser Bibliothek finde ist, dass die automatische Konfiguration nicht so gut aussieht. Auch die Ticks musste ich anpassen.
Das Problem vom Anfang, dass die Linie nicht sichtbar ist, wenn sie ganz unten oder ganz oben liegt, kann man u. U. auch dadurch verbessern, indem man die Stärke vergrößert. Das habe ich jedoch noch nicht gefunden.
 
Vielen Dank für Deine Hilfe, Jetzt habe ich den grafischen Bereich so, wie ich ihn haben wollte. Was meinst du mit der Aussage, alles spiele sich auf dem Server ab, die Daten müssten nicht runtergeladen werden? Ich habe die Bibliothek runtergeladen und in mein Webserververzeichnis hinterlegt. Auf die JQuery-Bibliothek greife ich online zu:
HTML:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js" type="text/javascript" charset="utf-8"></script>
Wie kann ich auf die Bibliothek online zugreifen, ohne sie runterladen zu müssen? Folgender Einbindungsversuch funktioniert jedenfalls nicht:
PHP:
$path2Library="https://jpgraph.net/";
require_once $path2Library . 'jpgraph/jpgraph.php';
Folgender funktioniert hingegen:
PHP:
$folder = getcwd();
require_once $folder . '/inc/graphicsLibrary/jpgraph.php';
 
Zuletzt bearbeitet:
Status
Dieses Thema wurde gelöst! Zur Lösung gehen…
Zurück