Subversion Repositories eFlore/Projets.eflore-projets

Rev

Rev 742 | Rev 1091 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 742 Rev 743
1
<?php
1
<?php
-
 
2
 
-
 
3
/**
-
 
4
 * Classe unique du web service nasa-srtm qui détermine l'altitude d'un point à partir de ses coordonnees
-
 
5
 * Les coordonnees sont definies dans des fichiers au format HGT dans un dossier specifique
-
 
6
 * (dont le chemin est defini dans le fichier de configuration propre au web service).
-
 
7
 * Les ressources utilisees sont les donnees issues du programme SRTM-3 de la NASA qui couvre
-
 
8
 * l'ensemble terrestre du monde. La precision des points dont on renvoie l'altitude est de 90 metres.
-
 
9
 * Chaque fichier couvre un secteur de 1 degre sur 1 degre et contient un tableau de 1201 lignes
-
 
10
 * (axe des latitudes) sur 1201 colonnes (axe des longitudes) contenant l'altitude en metres
-
 
11
 * correspondant a des point precis. L'ecart entre chaque entree des tableaux est constant, ce qui
-
 
12
 * permet de calculer la latitude et la longitude de chaque point. L'altitude du point le plus proche
-
 
13
 * de celui passe en parametres sera renvoyee au client.
-
 
14
 * 
-
 
15
 * Parametres du web service :
-
 
16
 *   - latitude : latitude du point dont on recherche les coordonnees
-
 
17
 *   - longitude : longitude du point dont on recherche les coordonnees
-
 
18
 * 
-
 
19
 * @package framework-0.4
-
 
20
 * @author Alexandre GALIBERT <alexandre.galibert@tela-botanica.org>
-
 
21
 * @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
-
 
22
 * @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
-
 
23
 * @version $Id$
-
 
24
 * @copyright 2013 Tela Botanica (accueil@tela-botanica.org)
-
 
25
 *
-
 
26
 */
-
 
27
 
2
 
28
 
3
class Altitude {
29
class Altitude {
4
	
30
	
5
	private $parametres = array();
31
	private $parametres = array();
6
	private $ressources = array();
32
	private $ressources = array();
7
	private $coordonnees = null;
33
	private $coordonnees = null;
8
	private $fichierSrtm = '';
34
	private $fichierSrtm = '';
9
	
35
	
10
	const LONGUEUR_COTE = 1201;
36
	const LONGUEUR_COTE = 1201;
11
	const OFFSET = 2;
37
	const OFFSET = 2;
12
	
38
	
13
	
39
	
14
	public function consulter($ressources, $parametres) {
40
	public function consulter($ressources, $parametres) {
15
		$this->ressources = $ressources;
41
		$this->ressources = $ressources;
16
		$this->parametres = $parametres;
42
		$this->parametres = $parametres;
17
		$retour = null;
43
		$retour = null;
18
		try {
44
		try {
19
			$this->traiterCoordonnees();
45
			$this->traiterCoordonnees();
20
			$this->rechercherFichierSrtm();
46
			$this->rechercherFichierSrtm();
21
			$this->recupererAltitude();
47
			$this->recupererAltitude();
22
			$retour = $this->coordonnees;
48
			$retour = $this->coordonnees;
23
		} catch (Exception $erreur) {
49
		} catch (Exception $erreur) {
24
			$retour = $erreur->getMessage();
50
			$retour = $erreur->getMessage();
25
		}
51
		}
26
		return $retour;
52
		return $retour;
27
	}
53
	}
28
	
54
	
29
	private function traiterCoordonnees() {
55
	private function traiterCoordonnees() {
30
		if ($this->estParametreExistant('latitude') && $this->estParametreExistant('longitude')) {
56
		if ($this->estParametreExistant('lat') && $this->estParametreExistant('lon')) {
31
			$longitude = $this->parametres['longitude'];
57
			$longitude = $this->parametres['lon'];
32
			$latitude  = $this->parametres['latitude'];
58
			$latitude  = $this->parametres['lat'];
33
			if ($this->estUnFloat($longitude) && $this->estUnFloat($latitude)) {
59
			if ($this->estUnFloat($longitude) && $this->estUnFloat($latitude)) {
34
				$this->verifierValiditeCoordonnees($longitude, $latitude);
60
				$this->verifierValiditeCoordonnees($longitude, $latitude);
35
			} else {
61
			} else {
36
				$message = "La valeur des coordonnées longitude ou latitude n'est pas correcte. ".
62
				$message = "La valeur des coordonnées longitude ou latitude n'est pas correcte. ".
37
				" Elle doit être pour les deux paramètres une valeur décimale.";
63
				" Elle doit être pour les deux paramètres une valeur décimale.";
38
				throw new Exception($message, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
64
				throw new Exception($message, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
39
			}
65
			}
40
		} else {
66
		} else {
41
			$message = "Tous les paramètres passés dans l'URL ne correspondent pas à ceux attendus. ".
67
			$message = "Tous les paramètres passés dans l'URL ne correspondent pas à ceux attendus. ".
42
			"Le web service nécessite de lui fournir une longitude et une latitude pour son bon fonctionnement.";
68
			"Le web service nécessite de lui fournir une longitude et une latitude pour son bon fonctionnement.";
43
			throw new Exception($message, RestServeur::HTTP_CODE_CONTENU_REQUIS);
69
			throw new Exception($message, RestServeur::HTTP_CODE_CONTENU_REQUIS);
44
		}
70
		}
45
	}
71
	}
46
	
72
	
47
	private function estParametreExistant($nomParametre) {
73
	private function estParametreExistant($nomParametre) {
48
		return in_array($nomParametre, array_keys($this->parametres));
74
		return in_array($nomParametre, array_keys($this->parametres));
49
	}
75
	}
50
	
76
	
51
	private function estUnFloat($variable) {
77
	private function estUnFloat($variable) {
52
		return (preg_match("/^(-)?\d+(\.\d+)?$/", $variable) == 1);
78
		return (preg_match("/^(-)?\d+(\.\d+)?$/", $variable) == 1);
53
	}
79
	}
54
	
80
	
55
	private function verifierValiditeCoordonnees($longitude, $latitude) {
81
	private function verifierValiditeCoordonnees($longitude, $latitude) {
56
		$longitude = floatval($longitude);
82
		$longitude = floatval($longitude);
57
		$latitude  = floatval($latitude);
83
		$latitude  = floatval($latitude);
58
		$longitudeMax = Config::get("limite_longitude");
84
		$longitudeMax = Config::get("limite_longitude");
59
		$latitudeMax  = Config::get("limite_latitude");
85
		$latitudeMax  = Config::get("limite_latitude");
60
		if (abs($longitude) > $longitudeMax || abs($latitude) > $latitudeMax) {
86
		if (abs($longitude) > $longitudeMax || abs($latitude) > $latitudeMax) {
61
			$message = "Les coordonnées passées en paramètres désignent un point qui se trouve ".
87
			$message = "Les coordonnées passées en paramètres désignent un point qui se trouve ".
62
			"en dehors des limites du monde. Elles doivent être comprises entre -{$longitudeMax} ".
88
			"en dehors des limites du monde. Elles doivent être comprises entre -{$longitudeMax} ".
63
			"et $longitudeMax sur l'axe des longitudes, et entre -{$latitudeMax} et {$latitudeMax} ".
89
			"et $longitudeMax sur l'axe des longitudes, et entre -{$latitudeMax} et {$latitudeMax} ".
64
			"sur l'axe des latitudes.";
90
			"sur l'axe des latitudes.";
65
			throw new Exception($message, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
91
			throw new Exception($message, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
66
		} else {
92
		} else {
67
			$this->coordonnees = new StdClass();
93
			$this->coordonnees = new StdClass();
68
			$this->coordonnees->longitude = $longitude;
94
			$this->coordonnees->longitude = $longitude;
69
			$this->coordonnees->latitude  = $latitude;
95
			$this->coordonnees->latitude  = $latitude;
70
		}
96
		}
71
	}
97
	}
72
	
98
	
73
	private function rechercherFichierSrtm() {
99
	private function rechercherFichierSrtm() {
74
		$nomFichierSrtm = $this->construireNomFichierSrtm();
100
		$nomFichierSrtm = $this->construireNomFichierSrtm();
75
		if (!file_exists($nomFichierSrtm)) {
101
		if (!file_exists($nomFichierSrtm)) {
76
			$message = "Erreur interne : certaines ressources demandées n'ont pas pu être trouvées sur le serveur.";
102
			$message = "Erreur interne : certaines ressources demandées n'ont pas pu être trouvées sur le serveur.";
77
			throw new Exception($message, restServeur::HTTP_CODE_ERREUR);
103
			throw new Exception($message, restServeur::HTTP_CODE_ERREUR);
78
		} else {
104
		} else {
79
			$this->fichierSrtm = $nomFichierSrtm;
105
			$this->fichierSrtm = $nomFichierSrtm;
80
		}
106
		}
81
	}
107
	}
82
	
108
	
83
	private function construireNomFichierSrtm() {
109
	private function construireNomFichierSrtm() {
84
		$latitudeEntier = abs(floor($this->coordonnees->latitude));
110
		$latitudeEntier = abs(floor($this->coordonnees->latitude));
85
		if ($latitudeEntier < 10) {
111
		if ($latitudeEntier < 10) {
86
			$latitudeEntier = "0".$latitudeEntier;
112
			$latitudeEntier = "0".$latitudeEntier;
87
		}
113
		}
88
		$suffixeLatitude = $this->coordonnees->latitude < 0 ? "S" : "N";
114
		$suffixeLatitude = $this->coordonnees->latitude < 0 ? "S" : "N";
89
		$longitudeEntier = abs(floor($this->coordonnees->longitude));
115
		$longitudeEntier = abs(floor($this->coordonnees->longitude));
90
		if ($longitudeEntier < 10) {
116
		if ($longitudeEntier < 10) {
91
			$longitudeEntier = "00".$longitudeEntier;
117
			$longitudeEntier = "00".$longitudeEntier;
92
		} elseif ($longitudeEntier < 100) {
118
		} elseif ($longitudeEntier < 100) {
93
			$longitudeEntier = "0".$longitudeEntier;
119
			$longitudeEntier = "0".$longitudeEntier;
94
		}
120
		}
95
		$suffixeLongitude = $this->coordonnees->longitude < 0 ? "W" : "E";
121
		$suffixeLongitude = $this->coordonnees->longitude < 0 ? "W" : "E";
96
		$dossierSrtm = Config::get('dossier_srtm').DS;
122
		$dossierSrtm = Config::get('dossier_srtm').DS;
97
		$nomFichierSrtm = $dossierSrtm.$suffixeLatitude.$latitudeEntier.$suffixeLongitude.$longitudeEntier.".hgt.zip";
123
		$nomFichierSrtm = $dossierSrtm.$suffixeLatitude.$latitudeEntier.$suffixeLongitude.$longitudeEntier.".hgt.zip";
98
		return $nomFichierSrtm;
124
		return $nomFichierSrtm;
99
	}
125
	}
100
	
126
	
101
	private function recupererAltitude() {
127
	private function recupererAltitude() {
102
		$zip = zip_open($this->fichierSrtm);
128
		$zip = zip_open($this->fichierSrtm);
103
		$fichier = zip_read($zip);
129
		$fichier = zip_read($zip);
104
		$donnees = zip_entry_read($fichier, zip_entry_filesize($fichier));
130
		$donnees = zip_entry_read($fichier, zip_entry_filesize($fichier));
105
		zip_close($zip);
131
		zip_close($zip);
106
				
132
				
107
		$xDepart = floor($this->coordonnees->longitude);
133
		$xDepart = floor($this->coordonnees->longitude);
108
		$yDepart = floor($this->coordonnees->latitude);
134
		$yDepart = floor($this->coordonnees->latitude);
109
		$longitude = $this->coordonnees->longitude;
135
		$longitude = $this->coordonnees->longitude;
110
		$latitude = $this->coordonnees->latitude;
136
		$latitude = $this->coordonnees->latitude;
111
		$positionX = (self::LONGUEUR_COTE-1) * ($longitude - $xDepart);
137
		$positionX = (self::LONGUEUR_COTE-1) * ($longitude - $xDepart);
112
		$positionY = (self::LONGUEUR_COTE-1) * (1 - $latitude + $yDepart);
138
		$positionY = (self::LONGUEUR_COTE-1) * (1 - $latitude + $yDepart);
113
		$positionX = ($positionX + 0.5 > ceil($positionX)) ? ceil($positionX) : floor($positionX);
139
		$positionX = ($positionX + 0.5 > ceil($positionX)) ? ceil($positionX) : floor($positionX);
114
		$positionY = ($positionY + 0.5 > ceil($positionY)) ? ceil($positionY) : floor($positionY);
140
		$positionY = ($positionY + 0.5 > ceil($positionY)) ? ceil($positionY) : floor($positionY);
115
		
141
		
116
		$binaire = substr($donnees, ($positionY * self::LONGUEUR_COTE + $positionX) * self::OFFSET, self::OFFSET);
142
		$binaire = substr($donnees, ($positionY * self::LONGUEUR_COTE + $positionX) * self::OFFSET, self::OFFSET);
117
		$this->coordonnees->altitude = current(unpack("n*", $binaire));
143
		$this->coordonnees->altitude = current(unpack("n*", $binaire));
118
		if (!$this->coordonnees->altitude) {
144
		if (!$this->coordonnees->altitude) {
119
			$this->coordonnees->altitude = 0;
145
			$this->coordonnees->altitude = 0;
120
		}
146
		}
121
	}
147
	}
122
	
148
	
123
}
149
}
124
 
150
 
125
?>
151
?>