Subversion Repositories eFlore/Applications.cel

Rev

Rev 2743 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2743 Rev 2747
1
<?php
1
<?php
2
class CelStreets extends Cel {
2
class CelStreets extends Cel {
3
 
3
 
4
	/**
4
	/**
5
	 * Méthode appelée avec une requête de type GET.
5
	 * Méthode appelée avec une requête de type GET.
6
	 */
6
	 */
7
	public function getRessource() {
7
	public function getRessource() {
8
		$this->getStreetGeom();
8
		$this->getStreetGeom();
9
	}
9
	}
10
	
10
	
11
	private function getStreetGeom() {
11
	private function getStreetGeom() {
12
		
12
		
13
		$erreurs = $this->verifierParametres();
13
		$erreurs = $this->verifierParametres();
14
		if(!empty($erreurs)) {
14
		if(!empty($erreurs)) {
15
			$this->envoyerMessageErreur(400, implode("\n", $erreurs));
15
			$this->envoyerMessageErreur(400, implode("\n", $erreurs));
16
			exit;
16
			exit;
17
		}
17
		}
18
		
18
		
19
		$latitude_debut = $_GET['latitude_debut'];
19
		$latitude_debut = $_GET['latitude_debut'];
20
		$longitude_debut = $_GET['longitude_debut'];
20
		$longitude_debut = $_GET['longitude_debut'];
21
		$latitude_fin = $_GET['latitude_fin'];
21
		$latitude_fin = $_GET['latitude_fin'];
22
		$longitude_fin = $_GET['longitude_fin'];
22
		$longitude_fin = $_GET['longitude_fin'];
23
		
23
		
24
		$dist_max = round(self::haversineGreatCircleDistance($latitude_debut, $longitude_debut, $latitude_fin, $longitude_fin)/2);
24
		$dist_max = round(self::haversineGreatCircleDistance($latitude_debut, $longitude_debut, $latitude_fin, $longitude_fin)/2);
25
 
25
 
26
		$url_tpl = $this->getUrlRequeteOverPass().urlencode($this->getRequetePasLoin($latitude_debut, $longitude_debut, $latitude_fin, $longitude_fin, $dist_max));
26
		$url_tpl = $this->getUrlRequeteOverPass().urlencode($this->getRequetePasLoin($latitude_debut, $longitude_debut, $latitude_fin, $longitude_fin, $dist_max));
27
		$json = file_get_contents($url_tpl);
27
		$json = file_get_contents($url_tpl);
28
		
28
		
29
		$infos = json_decode($json, true);
29
		$infos = json_decode($json, true);
30
		$this->filtrerNoeuds($infos, $latitude_debut, $longitude_debut, $latitude_fin, $longitude_fin);
30
		$this->filtrerNoeuds($infos, $latitude_debut, $longitude_debut, $latitude_fin, $longitude_fin);
31
		
31
		
32
		header('Content-type: application/json');
32
		header('Content-type: application/json');
33
		echo json_encode($infos); exit;
33
		echo json_encode($infos); exit;
34
	}
34
	}
35
	
35
	
36
	private function verifierParametres() {
36
	private function verifierParametres() {
37
		$parametres_obligatoires = array('latitude_debut', 'longitude_debut', 'latitude_fin', 'longitude_fin');
37
		$parametres_obligatoires = array('latitude_debut', 'longitude_debut', 'latitude_fin', 'longitude_fin');
38
		$erreurs = array();
38
		$erreurs = array();
39
		foreach($parametres_obligatoires as $param) {
39
		foreach($parametres_obligatoires as $param) {
40
			if(empty($_GET[$param]) || !is_numeric($_GET[$param])) {
40
			if(empty($_GET[$param]) || !is_numeric($_GET[$param])) {
41
				$erreurs[] = "Le paramètre $param est obligatoire et doit être un flottant";
41
				$erreurs[] = "Le paramètre $param est obligatoire et doit être un flottant";
42
			}
42
			}
43
		}
43
		}
44
		return $erreurs;
44
		return $erreurs;
45
	}
45
	}
46
	
46
	
47
	function getUrlRequeteOverPass() {
47
	function getUrlRequeteOverPass() {
48
		return $this->config['cel']['url_service_rue'];
48
		return $this->config['cel']['url_service_rue'];
49
	}
49
	}
50
	
50
	
51
	function getRequetePasLoin($latitude_debut, $longitude_debut, $latitude_fin, $longitude_fin, $dist = 50) {
51
	function getRequetePasLoin($latitude_debut, $longitude_debut, $latitude_fin, $longitude_fin, $dist = 50) {
52
		$req = 'way["highway"]
52
		$req = 'way["highway"]
53
			(around:'.$dist.','.$latitude_debut.','.$longitude_debut.')
53
			(around:'.$dist.','.$latitude_debut.','.$longitude_debut.')
54
			(around:'.$dist.','.$latitude_fin.','.$longitude_fin.')
54
			(around:'.$dist.','.$latitude_fin.','.$longitude_fin.')
55
			;
55
			;
56
			(
56
			(
57
			._;
57
			._;
58
			>;
58
			>;
59
			);
59
			);
60
		out geom;';
60
		out geom;';
61
		
61
		
62
		return $req;
62
		return $req;
63
	}
63
	}
64
	
64
	
65
	function getRequete($nord, $sud, $est, $ouest) {		
65
	function getRequete($nord, $sud, $est, $ouest) {		
66
		return '(
66
		return '(
67
			way["highway"]
67
			way["highway"]
68
			('.$sud.','.$ouest.','.$nord.','.$est.');
68
			('.$sud.','.$ouest.','.$nord.','.$est.');
69
			>;
69
			>;
70
		);out geom;';
70
		);out geom;';
71
	}
71
	}
72
	
72
	
73
	function filtrerNoeuds(&$infos, $latitude_debut, $longitude_debut, $latitude_fin, $longitude_fin) {	
73
	function filtrerNoeuds(&$infos, $latitude_debut, $longitude_debut, $latitude_fin, $longitude_fin) {	
74
		$distances_debut = array();
74
		$distances_debut = array();
75
		$distances_fin = array();
75
		$distances_fin = array();
76
		
76
		
77
		foreach($infos['elements'] as $index_e => &$element) {
77
		foreach($infos['elements'] as $index_e => &$element) {
78
			if(empty($element['geometry'])) {
78
			if(empty($element['geometry'])) {
79
				unset($infos['elements'][$index_e]);
79
				unset($infos['elements'][$index_e]);
80
			} else {
80
			} else {
81
				$index_fin_tableau = count($element['geometry']) - 1;
81
				$index_fin_tableau = count($element['geometry']) - 1;
82
				
82
				
83
				$distances_debut[$index_e] = -1;
83
				$distances_debut[$index_e] = -1;
84
				$distances_fin[$index_e] = -1;
84
				$distances_fin[$index_e] = -1;
85
				
85
				
86
				$index_point_plus_proche_debut = 0;
86
				$index_point_plus_proche_debut = 0;
87
				$dist_point_plus_proche_debut = 999999999;
87
				$dist_point_plus_proche_debut = 999999999;
88
				$index_point_plus_proche_fin = $index_fin_tableau;
88
				$index_point_plus_proche_fin = $index_fin_tableau;
89
				$dist_point_plus_proche_fin = 9999999999;
89
				$dist_point_plus_proche_fin = 9999999999;
90
				
90
				
91
				$index_debut = array(0, 1);
91
				$index_debut = array(0, 1);
92
				$index_fin = array($index_fin_tableau -1, $index_fin_tableau);
92
				$index_fin = array($index_fin_tableau -1, $index_fin_tableau);
93
				
93
				
94
				$element['geometryOrig'] = $element['geometry'];
94
				$element['geometryOrig'] = $element['geometry'];
95
				
95
				
96
				foreach($element['geometry'] as $index_g => &$geometry) {					
96
				foreach($element['geometry'] as $index_g => &$geometry) {					
97
					// Calcul de la plus petite distance de la droite de rue au point
97
					// Calcul de la plus petite distance de la droite de rue au point
98
					// pour sélectionner la rue la plus proche des deux points
98
					// pour sélectionner la rue la plus proche des deux points
99
					if($index_g + 1 < count($element['geometry'])) {
99
					if($index_g + 1 < count($element['geometry'])) {
100
						$geom_next = $element['geometry'][$index_g + 1];
100
						$geom_next = $element['geometry'][$index_g + 1];
101
						$this->stockerDistancePlusCourte($distances_debut, $index_debut, $index_e, $index_g, $geometry, $geom_next, $latitude_debut, $longitude_debut);
101
						$this->stockerDistancePlusCourte($distances_debut, $index_debut, $index_e, $index_g, $geometry, $geom_next, $latitude_debut, $longitude_debut);
102
						$this->stockerDistancePlusCourte($distances_fin, $index_fin, $index_e, $index_g, $geometry, $geom_next, $latitude_fin, $longitude_fin);
102
						$this->stockerDistancePlusCourte($distances_fin, $index_fin, $index_e, $index_g, $geometry, $geom_next, $latitude_fin, $longitude_fin);
103
					}
103
					}
104
					
104
					
105
					$dist_debut= self::haversineGreatCircleDistance($latitude_debut, $longitude_debut, $geometry['lat'], $geometry['lon']);
105
					$dist_debut= self::haversineGreatCircleDistance($latitude_debut, $longitude_debut, $geometry['lat'], $geometry['lon']);
106
					$dist_fin = self::haversineGreatCircleDistance($latitude_fin, $longitude_fin, $geometry['lat'], $geometry['lon']);
106
					$dist_fin = self::haversineGreatCircleDistance($latitude_fin, $longitude_fin, $geometry['lat'], $geometry['lon']);
107
					if($dist_point_plus_proche_debut > $dist_debut) {
107
					if($dist_point_plus_proche_debut > $dist_debut) {
108
						$dist_point_plus_proche_debut = $dist_debut;
108
						$dist_point_plus_proche_debut = $dist_debut;
109
						$index_point_plus_proche_debut = $index_g;
109
						$index_point_plus_proche_debut = $index_g;
110
					}
110
					}
111
					
111
					
112
					if($dist_point_plus_proche_fin > $dist_fin) {
112
					if($dist_point_plus_proche_fin > $dist_fin) {
113
						$dist_point_plus_proche_fin = $dist_fin;
113
						$dist_point_plus_proche_fin = $dist_fin;
114
						$index_point_plus_proche_fin = $index_g;
114
						$index_point_plus_proche_fin = $index_g;
115
					}
115
					}
116
				}
116
				}
117
				
117
				
118
				$index_min = min($index_point_plus_proche_debut, $index_point_plus_proche_fin);
118
				$index_min = min($index_point_plus_proche_debut, $index_point_plus_proche_fin);
119
				$index_max = max($index_point_plus_proche_debut, $index_point_plus_proche_fin);
119
				$index_max = max($index_point_plus_proche_debut, $index_point_plus_proche_fin);
120
								
120
								
121
				$infos_debut = array('lat' => (float)$latitude_debut, 'lon' => (float)$longitude_debut);
121
				$infos_debut = array('lat' => (float)$latitude_debut, 'lon' => (float)$longitude_debut);
122
				$infos_fin = array('lat' => (float)$latitude_fin, 'lon' => (float)$longitude_fin);
122
				$infos_fin = array('lat' => (float)$latitude_fin, 'lon' => (float)$longitude_fin);
123
				
123
				
124
				// Inversion des points de début et de fin si le début donné par l'utilisateur est plus 
124
				// Inversion des points de début et de fin si le début donné par l'utilisateur est plus 
125
				// proche de la fin
125
				// proche de la fin
126
				if($index_min != $index_point_plus_proche_debut) {
126
				if($index_min != $index_point_plus_proche_debut) {
127
					$tmp = $infos_debut;
127
					$tmp = $infos_debut;
128
					$infos_debut = $infos_fin;
128
					$infos_debut = $infos_fin;
129
					$infos_fin = $tmp;
129
					$infos_fin = $tmp;
130
				}
130
				}
131
								
131
								
132
				// Projection des points de début et d'arrivée sur le segment de rue
132
				// Projection des points de début et d'arrivée sur le segment de rue
133
				if($index_min < $index_fin_tableau) {
133
				if($index_min < $index_fin_tableau) {
134
					$proj_debut = $this->getOrthoPoint($element['geometry'][$index_min], $element['geometry'][$index_min+1], $infos_debut);
134
					$proj_debut = $this->getOrthoPoint($element['geometry'][$index_min], $element['geometry'][$index_min+1], $infos_debut);
135
					$index_insertion_point_debut = $this->getIndexInsertionDebut($element, $index_min, $infos_debut);
135
					$index_insertion_point_debut = $this->getIndexInsertionDebut($element, $index_min, $infos_debut);
136
				} else {
136
				} else {
137
					$proj_debut = $infos_debut;
137
					$proj_debut = $infos_debut;
138
					$index_insertion_point_debut = 0;
138
					$index_insertion_point_debut = 0;
139
				}
139
				}
140
				
140
				
141
				if($index_max > 0) {
141
				if($index_max > 0) {
142
					$proj_fin = $this->getOrthoPoint($element['geometry'][$index_max], $element['geometry'][$index_max-1], $infos_fin);
142
					$proj_fin = $this->getOrthoPoint($element['geometry'][$index_max], $element['geometry'][$index_max-1], $infos_fin);
143
					$index_insertion_point_fin = $this->getIndexInsertionFin($element, $index_max, $infos_fin);
143
					$index_insertion_point_fin = $this->getIndexInsertionFin($element, $index_max, $infos_fin);
144
				} else {
144
				} else {
145
					$proj_fin = $infos_fin;
145
					$proj_fin = $infos_fin;
146
					$index_insertion_point_fin = $index_fin_tableau;
146
					$index_insertion_point_fin = $index_fin_tableau;
147
				}
147
				}
148
 
148
 
149
				$index_insertion_point_debut = $index_insertion_point_debut < 0 ? 0 : $index_insertion_point_debut;
149
				$index_insertion_point_debut = $index_insertion_point_debut < 0 ? 0 : $index_insertion_point_debut;
150
				$index_insertion_point_fin = $index_insertion_point_fin > $index_fin_tableau ? $index_fin_tableau : $index_insertion_point_fin;
150
				$index_insertion_point_fin = $index_insertion_point_fin > $index_fin_tableau ? $index_fin_tableau : $index_insertion_point_fin;
151
				
151
				
152
				$rd = array();
152
				$rd = array();
153
				for($ii = $index_insertion_point_debut+1; $ii <= $index_insertion_point_fin; $ii++) {
153
				for($ii = $index_insertion_point_debut+1; $ii <= $index_insertion_point_fin; $ii++) {
154
					$rd[] = $element['geometry'][$ii];
154
					$rd[] = $element['geometry'][$ii];
155
				}
155
				}
-
 
156
				
-
 
157
				$proj_debut = $infos_debut;
-
 
158
				$proj_fin = $infos_fin;
156
				
159
				
157
				// Insertion des points utilisateurs en début et fin de tableau
160
				// Insertion des points utilisateurs en début et fin de tableau
158
				array_unshift($rd, $proj_debut);
161
				array_unshift($rd, $proj_debut);
159
				array_push($rd, $proj_fin);
162
				array_push($rd, $proj_fin);
160
				
163
				
161
				$element['geometry'] = $rd;
164
				$element['geometry'] = $rd;
162
			}
165
			}
163
		}
166
		}
164
		
167
		
165
		if(!empty($distances_debut)) {
168
		if(!empty($distances_debut)) {
166
			asort($distances_debut);
169
			asort($distances_debut);
167
			reset($distances_debut);
170
			reset($distances_debut);
168
			$cle_plus_courte_debut = key($distances_debut);
171
			$cle_plus_courte_debut = key($distances_debut);
169
		}
172
		}
170
		
173
		
171
		if(!empty($distances_fin)) {
174
		if(!empty($distances_fin)) {
172
			asort($distances_fin);
175
			asort($distances_fin);
173
			reset($distances_fin);
176
			reset($distances_fin);
174
			$cle_plus_courte_fin = key($distances_fin);
177
			$cle_plus_courte_fin = key($distances_fin);
175
		}
178
		}
-
 
179
		
176
		
180
		if(!empty($distances_fin)) {
177
		$cle_choisie = $this->choisirIndexRuePlusProchePourDebutEtFin($cle_plus_courte_debut, $cle_plus_courte_fin, $distances_debut, $distances_fin);	
181
			$cle_choisie = $this->choisirIndexRuePlusProchePourDebutEtFin($cle_plus_courte_debut, $cle_plus_courte_fin, $distances_debut, $distances_fin);	
178
		$rue_plus_proche = $distances_fin[$cle_choisie];			
182
			$rue_plus_proche = $distances_fin[$cle_choisie];			
179
		unset($distances_fin[$cle_choisie]);
183
			unset($distances_fin[$cle_choisie]);
-
 
184
			$distances_fin = array($cle_choisie => $rue_plus_proche) + $distances_fin;
180
		$distances_fin = array($cle_choisie => $rue_plus_proche) + $distances_fin;
185
		}
181
		
186
		
182
		$elements_fmt = array();
187
		$elements_fmt = array();
183
		foreach($distances_fin as $index => $distance) {
188
		foreach($distances_fin as $index => $distance) {
184
			//echo '<pre>'.print_r($infos['elements'][$index], true).'</pre>';exit;
189
			//echo '<pre>'.print_r($infos['elements'][$index], true).'</pre>';exit;
185
			$rue_proche = $infos['elements'][$index];
190
			$rue_proche = $infos['elements'][$index];
186
			$rue_proche['dist_min'] = $distance;
191
			$rue_proche['dist_min'] = $distance;
187
			$elements_fmt[] = $rue_proche;
192
			$elements_fmt[] = $rue_proche;
188
		}
193
		}
189
		$infos['elements'] = $elements_fmt;
194
		$infos['elements'] = $elements_fmt;
190
	}
195
	}
191
	
196
	
192
	function choisirIndexRuePlusProchePourDebutEtFin($cle_plus_courte_debut, $cle_plus_courte_fin, $distances_debut, $distances_fin) {
197
	function choisirIndexRuePlusProchePourDebutEtFin($cle_plus_courte_debut, $cle_plus_courte_fin, $distances_debut, $distances_fin) {
193
		
198
		
194
		$cle_choisie = $cle_plus_courte_fin;
199
		$cle_choisie = $cle_plus_courte_fin;
195
		// Si la rue la plus proche n'est pas la même pour les deux points
200
		// Si la rue la plus proche n'est pas la même pour les deux points
196
		if($cle_plus_courte_debut != $cle_plus_courte_fin) {
201
		if($cle_plus_courte_debut != $cle_plus_courte_fin) {
197
			// on calcule celle qui est la mieux positionnée en moyenne
202
			// on calcule celle qui est la mieux positionnée en moyenne
198
			$index_debut_tab_debut = array_search($cle_plus_courte_debut, array_keys($distances_debut));
203
			$index_debut_tab_debut = array_search($cle_plus_courte_debut, array_keys($distances_debut));
199
			$index_debut_tab_fin = array_search($cle_plus_courte_debut, array_keys($distances_fin));
204
			$index_debut_tab_fin = array_search($cle_plus_courte_debut, array_keys($distances_fin));
200
			
205
			
201
			$index_fin_tab_debut = array_search($cle_plus_courte_fin, array_keys($distances_debut));
206
			$index_fin_tab_debut = array_search($cle_plus_courte_fin, array_keys($distances_debut));
202
			$index_fin_tab_fin = array_search($cle_plus_courte_fin, array_keys($distances_fin));
207
			$index_fin_tab_fin = array_search($cle_plus_courte_fin, array_keys($distances_fin));
203
			
208
			
204
			$moy_index_debut = ($index_debut_tab_debut + $index_debut_tab_fin)/2;
209
			$moy_index_debut = ($index_debut_tab_debut + $index_debut_tab_fin)/2;
205
			$moy_index_fin = ($index_fin_tab_debut + $index_fin_tab_fin)/2;
210
			$moy_index_fin = ($index_fin_tab_debut + $index_fin_tab_fin)/2;
206
			
211
			
207
			$cle_choisie = ($moy_index_debut < $moy_index_fin) ? $cle_plus_courte_debut : $cle_plus_courte_fin;
212
			$cle_choisie = ($moy_index_debut < $moy_index_fin) ? $cle_plus_courte_debut : $cle_plus_courte_fin;
208
			
213
			
209
			// Si ça ne suffit pas on prend celle qui a la distance moyenne la plus courte aux deux points
214
			// Si ça ne suffit pas on prend celle qui a la distance moyenne la plus courte aux deux points
210
			if ($moy_index_debut ==  $moy_index_fin) {
215
			if ($moy_index_debut ==  $moy_index_fin) {
211
				$moyenne_dist_cle_debut = ($distances_debut[$cle_plus_courte_debut] + $distances_fin[$cle_plus_courte_debut])/2;
216
				$moyenne_dist_cle_debut = ($distances_debut[$cle_plus_courte_debut] + $distances_fin[$cle_plus_courte_debut])/2;
212
				$moyenne_dist_cle_fin = ($distances_debut[$cle_plus_courte_fin] + $distances_fin[$cle_plus_courte_fin])/2;
217
				$moyenne_dist_cle_fin = ($distances_debut[$cle_plus_courte_fin] + $distances_fin[$cle_plus_courte_fin])/2;
213
					
218
					
214
				$cle_choisie =  ($moyenne_dist_cle_debut < $moyenne_dist_cle_fin) ? $cle_plus_courte_debut : $cle_plus_courte_fin;
219
				$cle_choisie =  ($moyenne_dist_cle_debut < $moyenne_dist_cle_fin) ? $cle_plus_courte_debut : $cle_plus_courte_fin;
215
			}
220
			}
216
		}
221
		}
217
		
222
		
218
		return $cle_choisie;
223
		return $cle_choisie;
219
	}
224
	}
220
	
225
	
221
	function getIndexInsertionDebut($element, $index_min, $debut) {
226
	function getIndexInsertionDebut($element, $index_min, $debut) {
222
		// le point de début est situé entre $index_debut et $index_debut + 1
227
		// le point de début est situé entre $index_min et $index_min + 1
223
		$proj_debut = $this->getOrthoPoint($element['geometry'][$index_min], $element['geometry'][$index_min+1], $debut);		
228
		$proj_debut = $this->getOrthoPoint($element['geometry'][$index_min], $element['geometry'][$index_min+1], $debut);		
224
		$point_deb = $element['geometry'][$index_min];
229
		$point_deb = $element['geometry'][$index_min];
225
		$point_deb_plus_un = $element['geometry'][$index_min+1];
230
		$point_deb_plus_un = $element['geometry'][$index_min+1];
226
		$distance_point_deb_plus_un_proj = self::haversineGreatCircleDistance($point_deb_plus_un['lat'], $point_deb_plus_un['lon'], $proj_debut['lat'], $proj_debut['lon']);
231
		$distance_point_deb_plus_un_proj = self::haversineGreatCircleDistance($point_deb_plus_un['lat'], $point_deb_plus_un['lon'], $proj_debut['lat'], $proj_debut['lon']);
227
		$distance_point_deb_deb_plus_un = self::haversineGreatCircleDistance($point_deb['lat'], $point_deb['lon'], $point_deb_plus_un['lat'], $point_deb_plus_un['lon']);
232
		$distance_point_deb_deb_plus_un = self::haversineGreatCircleDistance($point_deb['lat'], $point_deb['lon'], $point_deb_plus_un['lat'], $point_deb_plus_un['lon']);
228
		
233
		
229
		if($distance_point_deb_plus_un_proj < $distance_point_deb_deb_plus_un) {
234
		if($distance_point_deb_plus_un_proj < $distance_point_deb_deb_plus_un) {
230
			// le point le plus proche doit être éliminé
235
			// le point le plus proche doit être éliminé
231
			return $index_min + 1;
236
			return $index_min + 1;
232
		} else {
237
		} else {
233
			// il doit être gardé
238
			// il doit être gardé
234
			return $index_min;	
239
			return $index_min;	
235
		}
240
		}
236
	}
241
	}
237
	
242
	
238
	function getIndexInsertionFin($element, $index_max, $fin) {
243
	function getIndexInsertionFin($element, $index_max, $fin) {
239
		$proj_fin = $this->getOrthoPoint($element['geometry'][$index_max], $element['geometry'][$index_max-1], $fin);
244
		$proj_fin = $this->getOrthoPoint($element['geometry'][$index_max], $element['geometry'][$index_max-1], $fin);
240
		$point_fin = $element['geometry'][$index_max];
245
		$point_fin = $element['geometry'][$index_max];
241
		$point_fin_moins_un = $element['geometry'][$index_max-1];
246
		$point_fin_moins_un = $element['geometry'][$index_max-1];
242
		$distance_point_fin_moins_un_proj = self::haversineGreatCircleDistance($point_fin_moins_un['lat'], $point_fin_moins_un['lon'], $proj_fin['lat'], $proj_fin['lon']);
247
		$distance_point_fin_moins_un_proj = self::haversineGreatCircleDistance($point_fin_moins_un['lat'], $point_fin_moins_un['lon'], $proj_fin['lat'], $proj_fin['lon']);
243
		$distance_point_fin_fin_moins_un = self::haversineGreatCircleDistance($point_fin['lat'], $point_fin['lon'], $point_fin_moins_un['lat'], $point_fin_moins_un['lon']);
248
		$distance_point_fin_fin_moins_un = self::haversineGreatCircleDistance($point_fin['lat'], $point_fin['lon'], $point_fin_moins_un['lat'], $point_fin_moins_un['lon']);
244
	
249
	
245
		if($distance_point_fin_moins_un_proj < $distance_point_fin_fin_moins_un) {
250
		if($distance_point_fin_moins_un_proj < $distance_point_fin_fin_moins_un) {
246
			// le point le plus proche doit être éliminé
251
			// le point le plus proche doit être éliminé
247
			return $index_max;
252
			return $index_max - 1;
248
		} else {
253
		} else {
249
			// il doit être gardé
254
			// il doit être gardé
250
			return $index_max + 1;
255
			return $index_max;
251
		}
256
		}
252
	}
257
	}
253
	
258
	
254
	function stockerDistancePlusCourte(&$distances, &$infos_index_position_point, $index_e, $index_g, $geometry, $geom_next, $latitude_point, $longitude_point) {
259
	function stockerDistancePlusCourte(&$distances, &$infos_index_position_point, $index_e, $index_g, $geometry, $geom_next, $latitude_point, $longitude_point) {
255
		$a = $geometry['lat'];
260
		$a = $geometry['lat'];
256
		$b = $geometry['lon'];
261
		$b = $geometry['lon'];
257
		$c = $geom_next['lat'];
262
		$c = $geom_next['lat'];
258
		$d = $geom_next['lon'];
263
		$d = $geom_next['lon'];
259
		$x = $latitude_point ;
264
		$x = $latitude_point ;
260
		$y = $longitude_point ;
265
		$y = $longitude_point ;
261
		$dist = $this->getShortestDistance($a, $b, $c, $d, $x, $y);
266
		$dist = $this->getShortestDistance($a, $b, $c, $d, $x, $y);
262
		if($distances[$index_e] == -1 || $dist < $distances[$index_e]) {
267
		if($distances[$index_e] == -1 || $dist < $distances[$index_e]) {
263
			$distances[$index_e] = $dist;
268
			$distances[$index_e] = $dist;
264
			$infos_index_position_point = array($index_g, $index_g+1);
269
			$infos_index_position_point = array($index_g, $index_g+1);
265
		}
270
		}
266
	}
271
	}
267
	
272
	
268
	// projette le point C sur le segment AB
273
	// projette le point C sur le segment AB
269
	function getOrthoPoint($a, $b, $c) {		
274
	function getOrthoPoint($a, $b, $c) {		
270
		$x1 = $a['lat']; 
275
		$x1 = $a['lat']; 
271
		$y1 = $a['lon']; 
276
		$y1 = $a['lon']; 
272
		$x2 = $b['lat']; 
277
		$x2 = $b['lat']; 
273
		$y2 = $b['lon']; 
278
		$y2 = $b['lon']; 
274
		$x3 = $c['lat']; 
279
		$x3 = $c['lat']; 
275
		$y3 = $c['lon'];
280
		$y3 = $c['lon'];
276
		$px = $x2-$x1;
281
		$px = $x2-$x1;
277
		$py = $y2-$y1;
282
		$py = $y2-$y1;
278
		$dAB = $px*$px + $py*$py;
283
		$dAB = $px*$px + $py*$py;
279
		$u = (($x3 - $x1) * $px + ($y3 - $y1) * $py) / $dAB;
284
		$u = (($x3 - $x1) * $px + ($y3 - $y1) * $py) / $dAB;
280
		$x = $x1 + $u * $px;
285
		$x = $x1 + $u * $px;
281
		$y = $y1 + $u * $py;
286
		$y = $y1 + $u * $py;
282
		return array('lat' => $x, 'lon' => $y);  
287
		return array('lat' => $x, 'lon' => $y);  
283
	}
288
	}
284
	
289
	
285
	function getShortestDistance($a, $b, $c, $d, $x, $y) {
290
	function getShortestDistance($a, $b, $c, $d, $x, $y) {
286
		//Coordinates are (a,b) and (c,d)
291
		//Coordinates are (a,b) and (c,d)
287
		//the point (x,y) is the required point.
292
		//the point (x,y) is the required point.
288
		//echo 'nagi ';
293
		//echo 'nagi ';
289
		//echo $c.' - '.$a." = ".($c-$a).'<br />';
294
		//echo $c.' - '.$a." = ".($c-$a).'<br />';
290
		if(($c-$a) == 0) {
295
		if(($c-$a) == 0) {
291
			return 56465465456485;
296
			return 56465465456485;
292
		}
297
		}
293
		
298
		
294
		$m=($d-$b)/($c-$a);
299
		$m=($d-$b)/($c-$a);
295
		//echo $m."\n";
300
		//echo $m."\n";
296
		
301
		
297
		//echo $y-($m*$x)-$b+($m*$a)."\n";
302
		//echo $y-($m*$x)-$b+($m*$a)."\n";
298
		$distance=abs($y-($m*$x)-$b+($m*$a))/sqrt(1+($m*$m));
303
		$distance=abs($y-($m*$x)-$b+($m*$a))/sqrt(1+($m*$m));
299
		return  $distance;
304
		return  $distance;
300
	}
305
	}
301
	
306
	
302
	function haversineGreatCircleDistance(
307
	function haversineGreatCircleDistance(
303
			$latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)
308
			$latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)
304
	{
309
	{
305
		// convert from degrees to radians
310
		// convert from degrees to radians
306
		$latFrom = deg2rad($latitudeFrom);
311
		$latFrom = deg2rad($latitudeFrom);
307
		$lonFrom = deg2rad($longitudeFrom);
312
		$lonFrom = deg2rad($longitudeFrom);
308
		$latTo = deg2rad($latitudeTo);
313
		$latTo = deg2rad($latitudeTo);
309
		$lonTo = deg2rad($longitudeTo);
314
		$lonTo = deg2rad($longitudeTo);
310
	
315
	
311
		$latDelta = $latTo - $latFrom;
316
		$latDelta = $latTo - $latFrom;
312
		$lonDelta = $lonTo - $lonFrom;
317
		$lonDelta = $lonTo - $lonFrom;
313
	
318
	
314
		$angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
319
		$angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
315
				cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
320
				cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
316
		return $angle * $earthRadius;
321
		return $angle * $earthRadius;
317
	}
322
	}
318
	
323
	
319
	public static function vincentyGreatCircleDistance($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)
324
	public static function vincentyGreatCircleDistance($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)
320
	{
325
	{
321
		// convert from degrees to radians
326
		// convert from degrees to radians
322
		$latFrom = deg2rad($latitudeFrom);
327
		$latFrom = deg2rad($latitudeFrom);
323
		$lonFrom = deg2rad($longitudeFrom);
328
		$lonFrom = deg2rad($longitudeFrom);
324
		$latTo = deg2rad($latitudeTo);
329
		$latTo = deg2rad($latitudeTo);
325
		$lonTo = deg2rad($longitudeTo);
330
		$lonTo = deg2rad($longitudeTo);
326
	
331
	
327
		$lonDelta = $lonTo - $lonFrom;
332
		$lonDelta = $lonTo - $lonFrom;
328
		$a = pow(cos($latTo) * sin($lonDelta), 2) +
333
		$a = pow(cos($latTo) * sin($lonDelta), 2) +
329
		pow(cos($latFrom) * sin($latTo) - sin($latFrom) * cos($latTo) * cos($lonDelta), 2);
334
		pow(cos($latFrom) * sin($latTo) - sin($latFrom) * cos($latTo) * cos($lonDelta), 2);
330
		$b = sin($latFrom) * sin($latTo) + cos($latFrom) * cos($latTo) * cos($lonDelta);
335
		$b = sin($latFrom) * sin($latTo) + cos($latFrom) * cos($latTo) * cos($lonDelta);
331
	
336
	
332
		$angle = atan2(sqrt($a), $b);
337
		$angle = atan2(sqrt($a), $b);
333
		return $angle * $earthRadius;
338
		return $angle * $earthRadius;
334
	}
339
	}
335
}
340
}
336
?>
341
?>