Subversion Repositories eFlore/Projets.eflore-projets

Rev

Blame | Last modification | View Log | RSS feed

<?php

class Altitude {
        
        private $parametres = array();
        private $ressources = array();
        private $coordonnees = null;
        private $fichierSrtm = '';
        
        const LONGUEUR_COTE = 1201;
        const OFFSET = 2;
        
        
        public function consulter($ressources, $parametres) {
                $this->ressources = $ressources;
                $this->parametres = $parametres;
                $retour = null;
                try {
                        $this->traiterCoordonnees();
                        $this->rechercherFichierSrtm();
                        $this->recupererAltitude();
                        $retour = $this->coordonnees;
                } catch (Exception $erreur) {
                        $retour = $erreur->getMessage();
                }
                return $retour;
        }
        
        private function traiterCoordonnees() {
                if ($this->estParametreExistant('latitude') && $this->estParametreExistant('longitude')) {
                        $longitude = $this->parametres['longitude'];
                        $latitude  = $this->parametres['latitude'];
                        if ($this->estUnFloat($longitude) && $this->estUnFloat($latitude)) {
                                $this->verifierValiditeCoordonnees($longitude, $latitude);
                        } else {
                                $message = "La valeur des coordonnées longitude ou latitude n'est pas correcte. ".
                                " Elle doit être pour les deux paramètres une valeur décimale.";
                                throw new Exception($message, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
                        }
                } else {
                        $message = "Tous les paramètres passés dans l'URL ne correspondent pas à ceux attendus. ".
                        "Le web service nécessite de lui fournir une longitude et une latitude pour son bon fonctionnement.";
                        throw new Exception($message, RestServeur::HTTP_CODE_CONTENU_REQUIS);
                }
        }
        
        private function estParametreExistant($nomParametre) {
                return in_array($nomParametre, array_keys($this->parametres));
        }
        
        private function estUnFloat($variable) {
                return (preg_match("/^(-)?\d+(\.\d+)?$/", $variable) == 1);
        }
        
        private function verifierValiditeCoordonnees($longitude, $latitude) {
                $longitude = floatval($longitude);
                $latitude  = floatval($latitude);
                $longitudeMax = Config::get("limite_longitude");
                $latitudeMax  = Config::get("limite_latitude");
                if (abs($longitude) > $longitudeMax || abs($latitude) > $latitudeMax) {
                        $message = "Les coordonnées passées en paramètres désignent un point qui se trouve ".
                        "en dehors des limites du monde. Elles doivent être comprises entre -{$longitudeMax} ".
                        "et $longitudeMax sur l'axe des longitudes, et entre -{$latitudeMax} et {$latitudeMax} ".
                        "sur l'axe des latitudes.";
                        throw new Exception($message, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
                } else {
                        $this->coordonnees = new StdClass();
                        $this->coordonnees->longitude = $longitude;
                        $this->coordonnees->latitude  = $latitude;
                }
        }
        
        private function rechercherFichierSrtm() {
                $nomFichierSrtm = $this->construireNomFichierSrtm();
                if (!file_exists($nomFichierSrtm)) {
                        $message = "Erreur interne : certaines ressources demandées n'ont pas pu être trouvées sur le serveur.";
                        throw new Exception($message, restServeur::HTTP_CODE_ERREUR);
                } else {
                        $this->fichierSrtm = $nomFichierSrtm;
                }
        }
        
        private function construireNomFichierSrtm() {
                $latitudeEntier = abs(floor($this->coordonnees->latitude));
                if ($latitudeEntier < 10) {
                        $latitudeEntier = "0".$latitudeEntier;
                }
                $suffixeLatitude = $this->coordonnees->latitude < 0 ? "S" : "N";
                $longitudeEntier = abs(floor($this->coordonnees->longitude));
                if ($longitudeEntier < 10) {
                        $longitudeEntier = "00".$longitudeEntier;
                } elseif ($longitudeEntier < 100) {
                        $longitudeEntier = "0".$longitudeEntier;
                }
                $suffixeLongitude = $this->coordonnees->longitude < 0 ? "W" : "E";
                $dossierSrtm = Config::get('dossier_srtm').DS;
                $nomFichierSrtm = $dossierSrtm.$suffixeLatitude.$latitudeEntier.$suffixeLongitude.$longitudeEntier.".hgt.zip";
                return $nomFichierSrtm;
        }
        
        private function recupererAltitude() {
                $zip = zip_open($this->fichierSrtm);
                $fichier = zip_read($zip);
                $donnees = zip_entry_read($fichier, zip_entry_filesize($fichier));
                zip_close($zip);
                                
                $xDepart = floor($this->coordonnees->longitude);
                $yDepart = floor($this->coordonnees->latitude);
                $longitude = $this->coordonnees->longitude;
                $latitude = $this->coordonnees->latitude;
                $positionX = (self::LONGUEUR_COTE-1) * ($longitude - $xDepart);
                $positionY = (self::LONGUEUR_COTE-1) * (1 - $latitude + $yDepart);
                $positionX = ($positionX + 0.5 > ceil($positionX)) ? ceil($positionX) : floor($positionX);
                $positionY = ($positionY + 0.5 > ceil($positionY)) ? ceil($positionY) : floor($positionY);
                
                $binaire = substr($donnees, ($positionY * self::LONGUEUR_COTE + $positionX) * self::OFFSET, self::OFFSET);
                $this->coordonnees->altitude = current(unpack("n*", $binaire));
                if (!$this->coordonnees->altitude) {
                        $this->coordonnees->altitude = 0;
                }
        }
        
}

?>