source: spip-zone/_plugins_/gis/trunk/gis_fonctions.php @ 70457

Last change on this file since 70457 was 70457, checked in by cedric@…, 7 years ago

Refactoring du js du modele carte_gis :
Plutot que generer plein de JS specifique a la carte, on rend tout le js generique et on lui passe simplement un tableau de configuration contenant toutes les specificites de la carte a afficher
par compatibilite l'objet map construit reste attache a la globale map#ENV{id} mais il est aussi attache a l'objet du DOM qui porte la carte.
On peut donc toujours le retrouver par $('#maptruc').get(0).map ce qui est plus generique
Les methodes AddJSON et removeAllMarkers compatibilite GIS 3 y sont attaches
Les methodes setGeoJsonFeatureIcon, setGeoJsonFeaturePopup et parseGeoJson y sont egalement attachees (on peut donc avoir une map avec cluster et une map sans cluster dans la meme page sans risque de conflit de fonction)

La lib leafclusterer.js est inclue par gis.js a la demande (via argument de #PRODUIRE_FOND) ce qui evite de charger les libs en 2 hits quand on utilise les clusters

  • Property svn:executable set to *
File size: 10.5 KB
Line 
1<?php
2
3if (!defined('_ECRIRE_INC_VERSION')) return;
4
5include_spip('inc/config');
6include_spip('inc/json');
7
8/**
9 * Filtre dec_to_dms, http://www.statemaster.com/encyclopedia/Geographic-coordinate-conversion
10 *
11 * @param decimal $coord
12 * @return string
13 */
14function dec_to_dms($coord) {
15        return sprintf(
16                "%0.0f° %2.3f",
17                floor(abs($coord)),
18                60*(abs($coord)-floor(abs($coord)))
19        );
20}
21
22/**
23 * Filtre dms_to_dec, http://www.statemaster.com/encyclopedia/Geographic-coordinate-conversion
24 *
25 * @param string $ref N, E, S, W
26 * @param int $deg
27 * @param int $min
28 * @param int $sec
29 * @return decimal
30 */
31function dms_to_dec($ref,$deg,$min,$sec) {
32
33        $arrLatLong = array();
34        $arrLatLong["N"] = 1;
35        $arrLatLong["E"] = 1;
36        $arrLatLong["S"] = -1;
37        $arrLatLong["W"] = -1;
38
39        return ($deg+((($min*60)+($sec))/3600)) * $arrLatLong[$ref];
40}
41
42/**
43 * Filtre distance pour renvoyer la distance entre deux points
44 * http://snipplr.com/view/2531/calculate-the-distance-between-two-coordinates-latitude-longitude/
45 * sinon voir ici : http://zone.spip.org/trac/spip-zone/browser/_plugins_/forms/geoforms/inc/gPoint.php
46 *
47 * @param int|array $from
48 *     id_gis du point de référence ou tableau de coordonnées
49 * @param int|array $to
50 *     id_gis du point distant ou tableau de coordonnées
51 * @param bool $miles
52 *     Renvoyer le résultat en miles (kilomètres par défaut)
53 * @return float
54 *     Retourne la distance en kilomètre ou en miles
55 */
56function distance($from, $to, $miles=false) {
57        // On ne travaille que si on a toutes les infos
58        if (
59                // Le départ est soit un tableau soit un entier
60                (
61                        (is_array($from) and isset($from['lat']) and isset($from['lon']))
62                        or
63                        ($from = intval($from) and $from > 0 and $from = sql_fetsel('lat,lon','spip_gis',"id_gis=$from"))
64                )
65                and
66                // Le distant est soit un tableau soit un entier
67                (
68                        (is_array($to) and isset($to['lat']) and isset($to['lon']))
69                        or
70                        ($to = intval($to) and $to > 0 and $to = sql_fetsel('lat,lon','spip_gis',"id_gis=$to"))
71                )
72        ){
73                $pi80 = M_PI / 180;
74                $from['lat'] *= $pi80;
75                $from['lon'] *= $pi80;
76                $to['lat'] *= $pi80;
77                $to['lon'] *= $pi80;
78
79                $r = 6372.797; // mean radius of Earth in km
80                $dlat = $to['lat'] - $from['lat'];
81                $dlng = $to['lon'] - $from['lon'];
82                $a = sin($dlat / 2) * sin($dlat / 2) + cos($from['lat']) * cos($to['lat']) * sin($dlng / 2) * sin($dlng / 2);
83                $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
84                $km = $r * $c;
85
86                return ($miles ? ($km * 0.621371192) : $km);
87        }
88       
89        return false;
90}
91
92/**
93 * Compilation du critère {distancefrom}
94 *
95 * Critère {distancefrom} qui permet de ne sélectionner que les objets se trouvant à une distance comparée avec un point de repère.
96 * On doit lui passer 3 paramètres obligatoires :
97 * - le point de repère qui est un tableau avec les clés "lat" et "lon"
98 * - l'opérateur de comparaison
99 * - la distance à comparer, en kilomètres
100 * Cela donne par exemple :
101 *   {distancefrom #ARRAY{lat,#LAT,lon,#LON} < 30}
102 *   {distancefrom #ARRAY{lat,#ENV{lat},lon,#ENV{lon}} <= #ENV{distance}}
103 *
104 * @param unknown $idb
105 * @param unknown &$boucles
106 * @param unknown $crit
107 */
108function critere_distancefrom_dist($idb, &$boucles, $crit) {
109        $boucle = &$boucles[$idb];
110        $id_table = $boucle->id_table; // articles
111        $primary = $boucle->primary; // id_article
112        $objet = objet_type($id_table); // article
113       
114        if (
115                // Soit depuis une boucle (GIS) soit un autre objet mais avec {gis}
116                ($id_table == 'gis' or isset($boucle->join['gis']))
117                // Il faut aussi qu'il y ait 3 critères obligatoires
118                and count($crit->param) == 3
119        ){
120                $point_reference = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent);
121                $operateur = calculer_liste($crit->param[1], array(), $boucles, $boucles[$idb]->id_parent);
122                $distance = calculer_liste($crit->param[2], array(), $boucles, $boucles[$idb]->id_parent);
123
124                // Si le point de référence est un entier, on essaye de récupérer les coordonnées du point GIS
125                // Et si on a toujours pas de tableau correct, on met false
126                $boucle->hierarchie .= '$point_reference = '.$point_reference.';';
127                $boucle->hierarchie .= 'if (is_numeric($point_reference)){ $point_reference = sql_fetsel("lat,lon", "spip_gis", "id_gis = ".intval($point_reference)); }';
128                $boucle->hierarchie .= 'if (!is_array($point_reference) or !isset($point_reference["lat"]) or !isset($point_reference["lon"])){ $point_reference = false; }';
129                // L'opérateur doit exister dans une liste précise
130                $boucle->hierarchie .= '$operateur_distance = trim('.$operateur.');';
131                $boucle->hierarchie .= 'if (!in_array($operateur_distance, array("=","<",">","<=",">="))){ $operateur_distance = false; }';
132                $boucle->hierarchie .= '$distance = '.$distance.';';
133               
134                $boucle->select[] = '".(!$point_reference ? "\'\' as distance" : "(6371 * acos( cos( radians(".$point_reference["lat"].") ) * cos( radians( gis.lat ) ) * cos( radians( gis.lon ) - radians(".$point_reference["lon"].") ) + sin( radians(".$point_reference["lat"].") ) * sin( radians( gis.lat ) ) ) ) AS distance")."';
135                $boucle->having[] = '((!$point_reference or !$operateur_distance or !$distance) ? "1=1" : "distance $operateur_distance ".sql_quote($distance))';
136        }
137}
138
139/**
140 * Critere {gis distance<XX} pour filtrer une liste de points par rapport à la distance du point de l'env
141 *
142 * @param unknown_type $idb
143 * @param unknown_type $boucles
144 * @param unknown_type $crit
145 */
146function critere_gis_dist($idb, &$boucles, $crit) {
147        $boucle = &$boucles[$idb];
148        $id_table = $boucle->id_table; // articles
149        $primary = $boucle->primary; // id_article
150        $objet = objet_type($id_table); // article
151       
152        if ($id_table == 'gis') {
153                // exclure l'élément en cours des résultats
154                $id_gis = calculer_argument_precedent($idb,$primary, $boucles);
155                $boucle->where[]= array("'!='", "'$boucle->id_table." . "$primary'", $id_gis);
156               
157                // récupérer les paramètres du critère
158                $op='';
159                $params = $crit->param;
160                $type = array_shift($params);
161                $type = $type[0]->texte;
162                if(preg_match(',^(\w+)([<>=]+)([0-9]+)$,',$type,$r)){
163                        $type=$r[1];
164                        $op=$r[2];
165                        $op_val=$r[3];
166                }
167                if ($op)
168                        $boucle->having[]= array("'".$op."'", "'".$type."'",$op_val);
169               
170                // récupérer lat/lon du point de la boucle englobante
171                $lat = calculer_argument_precedent($idb,'lat', $boucles);
172                $lon = calculer_argument_precedent($idb,'lon', $boucles);
173               
174                // http://www.awelty.fr/developpement-web/php/
175                // http://www.movable-type.co.uk/scripts/latlong-db.html
176                // http://code.google.com/intl/fr/apis/maps/articles/geospatial.html#geospatial
177                $select = "(6371 * acos( cos( radians(\".$lat.\") ) * cos( radians( gis.lat ) ) * cos( radians( gis.lon ) - radians(\".$lon.\") ) + sin( radians(\".$lat.\") ) * sin( radians( gis.lat ) ) ) ) AS distance";
178                $order = "'distance'";
179               
180                $boucle->select[]= $select;
181                $boucle->order[]= $order;
182        } else {
183                // ajouter tous les champs du point au select
184                // et les suffixer pour lever toute ambiguite avec des champs homonymes
185                $boucle->select[]= 'gis.titre AS titre_gis';
186                $boucle->select[]= 'gis.descriptif AS descriptif_gis';
187                $boucle->select[]= 'gis.adresse AS adresse_gis';
188                $boucle->select[]= 'gis.pays AS pays_gis';
189                $boucle->select[]= 'gis.code_pays AS code_pays_gis';
190                $boucle->select[]= 'gis.region AS region_gis';
191                $boucle->select[]= 'gis.ville AS ville_gis';
192                $boucle->select[]= 'gis.code_postal AS code_postal_gis';
193                // jointure sur spip_gis_liens/spip_gis
194                // cf plugin notation
195                // $boucle->join["surnom (as) table de liaison"] = array("surnom de la table a lier", "cle primaire de la table de liaison", "identifiant a lier", "type d'objet de l'identifiant");
196                $boucle->from['gis_liens'] = 'spip_gis_liens';
197                $boucle->join['gis_liens']= array("'$id_table'","'id_objet'","'$primary'","'gis_liens.objet='.sql_quote('$objet')");
198                $boucle->from['gis'] = 'spip_gis';
199                $boucle->join['gis']= array("'gis_liens'","'id_gis'");
200                // bien renvoyer tous les points qui son attachés à l'objet
201                $boucle->group[] = 'gis_liens.id_gis';
202                // ajouter gis aux jointures et spécifier les jointures explicites pour pouvoir utiliser les balises de la table de jointure
203                // permet de passer dans trouver_champ_exterieur() depuis index_tables_en_pile()
204                // cf http://article.gmane.org/gmane.comp.web.spip.zone/6628
205                $boucle->jointures[] = 'gis';
206                if (empty($boucle->jointures_explicites)){
207                        $boucle->jointures_explicites = 'gis_liens gis';
208                }
209                else{
210                        $boucle->jointures_explicites .= ' gis_liens gis';
211                }
212        }
213}
214
215/**
216 * Balise #DISTANCE issue du critère {gis distance<XX}
217 * merci marcimant : http://formation.magraine.net/spip.php?article61
218 *
219 * @param unknown_type $p
220 */
221function balise_distance_dist($p) {
222        return rindex_pile($p, 'distance', 'gis');
223}
224
225/**
226 * Balise #TITRE_GIS : retourne le titre du point
227 * Necessite le critere {gis} sur la boucle
228 *
229 * @param unknown_type $p
230 */
231function balise_titre_gis_dist($p) {
232        return rindex_pile($p, 'titre_gis', 'gis');
233}
234
235/**
236 * Balise #DESCRIPTIF_GIS : retourne le descriptif du point
237 * Necessite le critere {gis} sur la boucle
238 *
239 * @param unknown_type $p
240 */
241function balise_descriptif_gis_dist($p) {
242        return rindex_pile($p, 'descriptif_gis', 'gis');
243}
244
245/**
246 * Définition du fond de carte à utiliser par défaut en prenant compte les defines
247 */
248function gis_layer_defaut(){
249        $defaut = 'openstreetmap_mapnik';
250        if(defined('_GIS_LAYER_DEFAUT_FORCE')){
251                return _GIS_LAYER_DEFAUT_FORCE;
252        }else{
253                if(defined('_GIS_LAYER_DEFAUT')){
254                        $defaut = _GIS_LAYER_DEFAUT;
255                }
256                $config = lire_config('gis/layer_defaut');
257                return $config ? $config : $defaut;
258        }
259}
260
261/**
262 * Recuperer les cles primaires du env pour l'appel a l'url json des points
263 * @param $env
264 * @return array
265 */
266function gis_modele_url_json_env($env){
267        $contexte = array();
268        if (is_string($env))
269                $env = unserialize($env);
270        if ($env){
271                // d'abord toutes les cles primaires connues
272                $tables_sql = lister_tables_objets_sql();
273                foreach (array_keys($tables_sql) as $table){
274                        $primary = id_table_objet($table);
275                        if (isset($env[$primary]))
276                                $contexte[$primary] = $env[$primary];
277                }
278                // puis cas particuliers
279                $keys = array("id_objet","id_secteur","id_parent","media","recherche","mots");
280                foreach ($keys as $key){
281                        if (isset($env[$key]))
282                                $contexte[$key] = $env[$key];
283                }
284        }
285        return $contexte;
286}
287
288/**
289 * Transformer le tableau de kml en tableau d'urls :
290 *   si numerique c'est un id de document
291 *   si chaine c'est une url qu'on rapatrie en local
292 * @param array $kml
293 * @return array
294 */
295function gis_kml_to_urls($kml){
296        if ($kml AND count($kml)){
297                include_spip("inc/filtres_mini");
298                include_spip("inc/distant");
299                foreach($kml as $k=>$v){
300                        if (is_numeric($v)){
301                                $kml[$k] = url_absolue(generer_url_entite($v,"document"));
302                        }
303                        else
304                                $kml[$k] = _DIR_RACINE.copie_locale($kml[$k]);
305                }
306        }
307        return $kml;
308}
309?>
Note: See TracBrowser for help on using the repository browser.