Cyril Rabat


Génération d'un plan en PHP

 15/11/2017     16/11/2017      Programmation PHP      Programmation client/serveur      Approche par composants   

Plan et image GD

   Cet article propose une classe Plan simplifiée, à modifier, et présente comment l'utiliser dans un document HTML, via un script PHP.

Mots-clefs :   PHP     GD   

Archive contenant les fichiers de cet article :

 plan.zip

La classe Plan

Le script PHP suivant correspond à la classe Plan qui permet de créer un plan dans une image à l'aide de GD.

<?php
// Constantes pour les données
define("VIDE", 0);                               // Place libre (vide)
define("OCCUPEE", 1);                            // Place occupée
define("SELECTION", 2);                          // Place sélectionnée
 
// Constantes pour les dimensions, etc.
define("LARGEUR_MIN", 100);                      // Largeur minimale de l'image
define("LARGEUR_MAX", 1000);                     // Largeur maximale de l'image
define("HAUTEUR_MIN", 100);                      // Hauteur minimale de l'image
define("HAUTEUR_MAX", 1000);                     // Hauteur maximale de l'image
define("RANGEES_MIN",   5);                      // Nombre minimum de rangées
define("RANGEES_MAX",  26);                      // Nombre maximum de rangées
define("PLACES_MIN",    5);                      // Nombre minimum de places par rangées
define("PLACES_MAX",   99);                      // Nombre maximum de places par rangées
 
// Couleurs par défaut
define("COULEUR_TEXTE",     array(255, 255, 255)); // Couleur du texte
define("COULEUR_VIDE",      array(50, 50, 50));  // Couleur d'un emplacement vide
define("COULEUR_OCCUPEE",   array(200, 200, 200)); // Couleur d'un emplacement occupé
define("COULEUR_SELECTION", array(255, 0, 0));   // Couleur de la sélection
 
// Marges, dimensions diverses
define("BORD_HAUT", 10);                         // Bord haut (marge en pixels)
define("BORD_BAS", 10);                          // Bord bas (marge en pixels)
define("BORD_DROITE", 10);                       // Bord droite (marge en pixels)
define("BORD_GAUCHE", 10);                       // Bord gauche (marge en pixels)
define("ESPACE_TEXTE", 2);                       // Espace entre le texte et les rectangles (en pixels)
define("POLICE", 5);                             // Taille de la police pour les numéros
 
/**
 * Classe permettant de créer une image d'un plan d'entrepôt de conteneurs.
 * Il est possible (et conseillé) de modifier cette classe pour le projet.
 * @author Cyril Rabat
 * @version 2017/11/15
 */
class Plan {
 
    private $largeur;                            // Largeur de l'image (en pixels)
    private $hauteur;                            // Hauteur de l'image (en pixels)
    private $rangees;                            // Nombre de rangées
    private $places;                             // Nombre de places par rangée (correspondant chacune à une pile)
 
    /**
     * Construit un plan.
     * @param largeur la largeur de l'image
     * @param hauteur la hauteur de l'image
     * @param rangees le nombre de rangées
     * @param places le nombre de places par rangée
     */
    function __construct($largeur, $hauteur, $rangees, $places) {		
        $this->largeur = $largeur;
        if($this->largeur <= LARGEUR_MIN)
            $this->largeur = LARGEUR_MIN;
        elseif($this->largeur > LARGEUR_MAX)
            $this->largeur = LARGEUR_MAX;
 
        $this->hauteur = $hauteur;
        if($this->hauteur <= HAUTEUR_MIN)
            $this->hauteur = HAUTEUR_MIN;
        elseif($this->hauteur > HAUTEUR_MAX)
            $this->hauteur = HAUTEUR_MAX;
 
        $this->rangees = $rangees;
        if($this->rangees <= RANGEES_MIN)
            $this->rangees = RANGEES_MIN;
        elseif($this->rangees > RANGEES_MAX)
            $this->rangees = RANGEES_MAX;
 
        $this->places = $places;
        if($this->places <= PLACES_MIN)
            $this->places = PLACES_MIN;
        elseif($this->places > RANGEES_MAX)
            $this->places = PLACES_MAX;
	} 
 
    /**
     * Calcule la hauteur et la largeur d'un texte.
     * @param image l'image
     * @param texte le texte
     * @param police le numéro de la police
     * @return un tableau contenant la largeur et la hauteur
     **/
    public static function getTaille($image, $texte, $police) {
        return array(imagefontwidth($police) * strlen($texte), imagefontheight($police));
    }
 
    /**
     * Construit l'image à partir d'un tableau de données. Chaque case correspond à VIDE, OCCUPEE ou SELECTION.
     * @param donnees les données sous forme d'un tableau de 'rangees' sur 'places' cases
     * @return l'image créée
     */
    function getImage($donnees) { 
        // Création de l'image
        $image = imagecreatetruecolor($this->largeur, $this->hauteur);
 
        // Préparation des couleurs
        $couleurs = array(imagecolorallocate($image, COULEUR_VIDE[0], COULEUR_VIDE[1], COULEUR_VIDE[2]),
                          imagecolorallocate($image, COULEUR_TEXTE[0], COULEUR_TEXTE[1], COULEUR_TEXTE[2]),
                          imagecolorallocate($image, COULEUR_OCCUPEE[0], COULEUR_OCCUPEE[1], COULEUR_OCCUPEE[2]),
                          imagecolorallocate($image, COULEUR_SELECTION[0], COULEUR_SELECTION[1], COULEUR_SELECTION[2]));
 
        // Calcul de la largeur/hauteur des conteneurs + de l'espace entre les rangées
        list($largeurLegende, $hauteurLegende) = Plan::getTaille($image, "AAA", POLICE);
        $hauteurRect = ($this->hauteur - BORD_HAUT - BORD_BAS - ESPACE_TEXTE - $hauteurLegende) / $this->places;
        $largeurRect = ($this->largeur - BORD_DROITE - BORD_GAUCHE - ESPACE_TEXTE - $largeurLegende) / $this->rangees;
        $espace = $largeurRect / 3;
        $largeurRect = $largeurRect / 3 * 2;
 
        // Affichage des numéros de places
        for($j = 0; $j < $this->places; $j += 5) {
            list($largeurTexte, $hauteurTexte) = Plan::getTaille($image, $j, POLICE);
            imagestring($image, POLICE,
                        BORD_GAUCHE + $largeurLegende - $largeurTexte,
                        $this->hauteur - BORD_BAS - $hauteurLegende - ESPACE_TEXTE - $j * $hauteurRect - $hauteurRect + ($hauteurRect - $hauteurTexte) / 2,
                        $j, $couleurs[1]);
        }
 
        // Affichage de tous les conteneurs
        for($i = 0; $i < $this->rangees; $i++) {
            // Affichage du numéro de rangée
            $texte = chr(ord('A') + $i);
            list($largeurTexte, $hauteurTexte) = Plan::getTaille($image, $texte, POLICE);
            imagestring($image, POLICE,
                        BORD_GAUCHE + $largeurLegende + ESPACE_TEXTE + $i * ($largeurRect + $espace) + ($largeurRect - $largeurTexte) / 2,
                        $this->hauteur - BORD_BAS - $hauteurTexte,
                        $texte, $couleurs[1]);
 
            // Affichage des rectangles de la rangée
            for($j = 0; $j < $this->places; $j++) {
                switch($donnees[$i][$j]) {
                    case OCCUPEE:
                        $couleur = $couleurs[2];
                        break;
                    case SELECTION:
                        $couleur = $couleurs[3];
                        break;
                    default:
                        $couleur = $couleurs[0];
                        break;
                }
                imagefilledrectangle($image,
                               BORD_GAUCHE + $largeurLegende + ESPACE_TEXTE + $i * ($largeurRect + $espace),
                               $this->hauteur - BORD_BAS - ESPACE_TEXTE - $hauteurLegende - $j * $hauteurRect,
                               BORD_GAUCHE + $largeurLegende + ESPACE_TEXTE + $i * ($largeurRect + $espace) + $largeurRect,
                               $this->hauteur - BORD_BAS - ESPACE_TEXTE - $hauteurLegende - $j * $hauteurRect - $hauteurRect,
                               $couleur);
 
            }
        }
 
        return $image;
    }
}
?>

 Télécharger le fichier

Génération d'un plan

Pour générer un plan, nous choisissons de passer par un script intermédiaire PHP qui exploite la classe Plan. Les dimensions de l'image contenant le plan sont spécifiées en GET, ainsi que le nombre de rangées et de places. Les données sont stockées en dur dans le script PHP.

<?php
include("Plan.php");
 
// Constantes : valeurs par défaut
define("LARGEUR", 300);                          // Largeur par défaut de l'image
define("HAUTEUR", 300);                          // Hauteur par défaut de l'image
define("RANGEES", 5);                            // Nombre de rangées
define("PLACES", 10);                            // Nombre de places par rangée
 
// Récupération des données envoyées au script via la méthode GET
if(isset($_GET['largeur']))
    $largeur = intval($_GET['largeur']);
else
    $largeur = LARGEUR;
if(isset($_GET['hauteur']))
    $hauteur = intval($_GET['hauteur']);
else
    $hauteur = HAUTEUR;
if(isset($_GET['rangees']))
    $rangees = intval($_GET['rangees']);
else
    $rangees = RANGEES;
if(isset($_GET['places']))
    $places = intval($_GET['places']);
else
    $places = PLACES;
 
// Création du plan
$plan = new Plan($largeur, $hauteur, $rangees, $places);
 
// Données quelconques pour l'histogramme : à remplacer par vos propres données (envoyées en POST)
$donnees = array();
for($i = 0; $i < $rangees; $i++) {
    $rangee = array();
    for($j = 0; $j < $places; $j++) {
        $rangee[] = rand(0, 1);
    }
    $donnees[] = $rangee;
}
 
// Sélectionne 10 conteneurs quelconques (ils seront affichés en rouge)
for($i = 0; $i < 10; $i++) {
    $x = rand(0, $rangees - 1);
    $y = rand(0, $places -1);
    $donnees[$x][$y] = SELECTION;
}
 
// Envoi de l'image
header("Content-type: image/png");
imagepng($plan->getImage($donnees));
?>

 Télécharger le fichier

Le document HTML

Le document HTML suivant inclut simplement le plan généré par le script PHP dans une balise img. La taille de l'image, le nombre de rangées et de places sont spécifiés dans l'URL.

<html lang="fr">
    <head>
        <title>Exemple de création d'un plan d'entrepôt</title>
        <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
        <meta name="description" content="Plan et image GD"/>
        <meta name="author" content="Cyril Rabat"/>
    </head>
    <body>
        <h1>Exemple d'utilisation de la classe Plan</h1>
 
        <p>
            Voici un plan d'entrepôt généré avec la classe Plan. 
            Les places occupées sont en gris clair, les places libres en gris foncé.
            Les places rouges correspondent aux conteneurs sélectionnés.
        </p>
 
        <img src='generateur.php?largeur=1000&hauteur=600&rangees=26&places=100'/>
    </body>
</html>

 Télécharger le fichier

Exécution

Pour exécuter les différents codes, il faut utiliser un serveur Web (par exemple Wamp ou UWamp, sous Windows). Les fichiers doivent être placés dans le répertoire www : on suppose ici qu'ils sont placés dans un sous-répertoire plan. Une fois le serveur exécuté, on accède à la page  http://localhost/plan/, suivi par le nom du script. Nous obtenons ainsi, le plan suivant (généré aléatoirement) :

Articles connexes


Version de cette page Mercredi 16 Décembre 2015

© Cyril Rabat 2018

Connexion

Mot de passe perdu

Dernières nouvelles

15/10/2018 Tous les étudiants de la Licence Informatique ont réunion sur la mobilité internationale, Mercredi 17 Octobre, de 13h30 à 14h00 (et non à 12h30), en Amphi 3.
02/10/2018 Pour la deuxième année consécutive, l'URCA est partenaire de l’événement Coding Battle. Tous les étudiants de Licence et de Master sont appelés à y participer le 17 octobre de 19h à 21h.
01/10/2018 Les emplois du temps sont maintenant accessibles depuis la page de la scolarité.
27/09/2018 Une page a été créée pour vous permettre d'obtenir toutes les informations concernant les stages pour la Licence. Contactez le responsable pour plus d'informations.

Contact

Courriel :
cyril.rabat [at] univ-reims.fr

Téléphone :
+33-326-91-33-81

Fax :
+33-326-91-33-97

Facebook :
lien Facebook direct