Rev 880 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/*** Classe unique du web service nasa-srtm qui détermine l'altitude d'un point à partir de ses coordonnees* Les coordonnees sont definies dans des fichiers au format HGT dans un dossier specifique* (dont le chemin est defini dans le fichier de configuration propre au web service).* Les ressources utilisees sont les donnees issues du programme SRTM-3 de la NASA qui couvre* l'ensemble terrestre du monde. La precision des points dont on renvoie l'altitude est de 90 metres.* Chaque fichier couvre un secteur de 1 degre sur 1 degre et contient un tableau de 1201 lignes* (axe des latitudes) sur 1201 colonnes (axe des longitudes) contenant l'altitude en metres* correspondant a des point precis. L'ecart entre chaque entree des tableaux est constant, ce qui* permet de calculer la latitude et la longitude de chaque point. L'altitude du point le plus proche* de celui passe en parametres sera renvoyee au client.** Parametres du web service :* - latitude : latitude du point dont on recherche les coordonnees* - longitude : longitude du point dont on recherche les coordonnees** @package framework-0.4* @author Alexandre GALIBERT <alexandre.galibert@tela-botanica.org>* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>* @version $Id$* @copyright 2013 Tela Botanica (accueil@tela-botanica.org)**/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('lat') && $this->estParametreExistant('lon')) {$longitude = $this->parametres['lon'];$latitude = $this->parametres['lat'];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;}}}?>