source: spip-zone/_plugins_/gis_geometries/gisgeom_fonctions.php @ 104891

Last change on this file since 104891 was 104891, checked in by marcimat@…, 3 years ago

Grammaire.

  • Property svn:executable set to *
File size: 6.8 KB
Line 
1<?php
2
3if (!defined('_ECRIRE_INC_VERSION')) {
4        return;
5}
6
7/**
8 * Balise GEOMETRY pour afficher le champ geo de la table spip_gis au format WKT
9 *
10 * @param $p
11 * @return mixed
12 */
13function balise_geometry_dist($p) {
14        $p->code = '$Pile[$SP][\'geometry\']';
15        return $p;
16}
17
18/**
19 * Balise GEOMETRY_STYLES pour afficher la représentation JSON des styles
20 *
21 * @param $p
22 * @return mixed
23 */
24function balise_geometry_styles_dist($p) {
25        $p->code = '$Pile[$SP][\'geometry_styles\']';
26        return $p;
27}
28
29/**
30 * Filtre wkt_to_json converti une chaine au format WKT en GeoJSON
31 *
32 * @param string $wkt
33 * @return string
34 */
35function wkt_to_json($wkt) {
36        if (!$wkt) {
37                return false;
38        }
39        // include_spip cherche les fichier .php, on utilise find_in_path avec l'option $include à true
40        find_in_path(_DIR_LIB_GEOPHP.'geoPHP.inc', '', true);
41        $geometry = geoPHP::load($wkt, 'wkt');
42        return $geometry->out('json');
43}
44
45/**
46 * Filtre json_to_wkt converti une chaine au format GeoJSON en WKT
47 *
48 * @param string $json
49 * @return string
50 */
51function json_to_wkt($json) {
52        if (!$json) {
53                return false;
54        }
55        find_in_path(_DIR_LIB_GEOPHP.'geoPHP.inc', '', true);
56        $geometry = geoPHP::load($json, 'json');
57        return $geometry->out('wkt');
58}
59
60/**
61 * Filtre wkt_to_kml converti une chaine au format WKT en KML
62 *
63 * @param string $wkt
64 * @return string
65 */
66function wkt_to_kml($wkt) {
67        if (!$wkt) {
68                return false;
69        }
70        // include_spip cherche les fichier .php, on utilise find_in_path avec l'option $include à true
71        find_in_path(_DIR_LIB_GEOPHP.'geoPHP.inc', '', true);
72        $geometry = geoPHP::load($wkt, 'wkt');
73        return $geometry->out('kml');
74}
75
76/**
77 * Filtre wkt_to_gpx converti une chaine au format WKT en GPX
78 *
79 * @param string $wkt
80 * @return string
81 */
82function wkt_to_gpx($wkt) {
83        if (!$wkt) {
84                return false;
85        }
86        // include_spip cherche les fichier .php, on utilise find_in_path avec l'option $include à true
87        find_in_path(_DIR_LIB_GEOPHP.'geoPHP.inc', '', true);
88        $geometry = geoPHP::load($wkt, 'wkt');
89        return $geometry->out('gpx');
90}
91
92/**
93 * Filtre geometry_styles_to_json converti une chaine de valeurs séparées par des virugles au format JSON
94 *
95 * @param string $geometry_styles
96 * @return string
97 */
98function geometry_styles_to_json($geometry_styles) {
99        $values = explode(',', $geometry_styles);
100        if (count(array_filter($values)) < 1) {
101                return false;
102        }
103        $styles = array();
104        $keys = array('color', 'weight', 'opacity', 'fillColor', 'fillOpacity');
105        foreach ($keys as $index => $key) {
106                if (strlen($values[$index])) {
107                        $styles[$key] = $values[$index];
108                }
109        }
110        return json_encode($styles);
111}
112
113
114
115/**
116 * Renvoie une géométrie couvrant tous les points à une distance donnée de la géométrie d'entrée.
117 *
118 * Cela permet de calculer une zone autour d’un point, d’une ligne ou d’un polygone, à une certaine distance.
119 * Retourne une géométrie (polygone) simplifiée.
120 *
121 * @filtre
122 * @example
123 *     ```
124 *     Dans une boucle GIS :
125 *     #SET{poly,#GEOMETRY|zoner_geometrie{wkt,0.05}}
126 *     #SET{poly,#GEOMETRY|zoner_geometrie{wkt,0.05,0.005}}
127 *     ```
128 *
129 * @note
130 *     Nécessite Mysql 5.6+ ou Mariadb.
131 *
132 * @param string $geometrie
133 *     Géométrie
134 * @param float $distance
135 *     En degrés décimal (si l’unité de géométrie est latitude / longitude…)
136 * @param float|null $tolerance
137 *     Tolérance de simplification des tracés (null, appliquera la valeur par défaut ($distance/20)),
138 *     en degré décimal (si l’unité de géométrie est latitude / longitude…) ;
139 * @return mixed
140 */
141function zoner_geometrie($geometrie, $type = 'wkt', $distance = 0.05, $tolerance = null) {
142        // tolérance… à peu près 1/20 de l’unité de distance (pifomètre)
143        if (is_null($tolerance)) {
144                $tolerance = $distance / 20;
145        }
146
147        // Simplifier le tracé d’origine… le récupérer en wkt
148        $geometrie = simplifier_geometrie($geometrie, $type, $tolerance, 'wkt');
149
150        // Obtenir le zonage demandé
151        $select = 'GeomFromText(' . sql_quote($geometrie) . ')';
152        $select = 'ST_Buffer(' . $select . ', ' . floatval($distance) . ')';
153        #$select = 'ST_Simplify(' . $select . ', ' . floatval($tolerance) . ')'; // mysql 5.7+ (non testé)
154        $select = 'ST_AsText(' . $select . ')';
155        $zone = sql_getfetsel($select);
156
157        // Simplifier le tracé de la zone, le récupérer au format d’entrée
158        $zone = simplifier_geometrie($zone, 'wkt', $tolerance, $type);
159        return $zone;
160}
161
162/**
163 * Simplifier une forme géométrique
164 *
165 * Diminue le nombre de points d’une forme géométrique (lignes, polygones, ...)
166 *
167 * @param mixed $data
168 *     Forme à simplifer, pouvant être lue par geoPHP (json, wkt, ...)
169 * @param string $type
170 *     Type d’entrée de `$data` (json, wkt, ...)
171 * @param float|null $tolerance
172 *     Tolérance de la réduction (en degré décimal si les unités sont latitude/longitude)
173 * @param string $type_sortie
174 *     Type de sortie de la simplification de `$data` (json, wkt, ...)
175 *     Par défaut, le type indiqué en entrée.
176 * @retrun mixed
177 *     Forme simplifiée, dans le même format qu’en entrée.
178 */
179function simplifier_geometrie($data, $type = 'wkt', $tolerance = null, $type_sortie = null) {
180        if (!class_exists('geoPHP_Simplify')) {
181                include_spip('inc/geoPHP_Simplify');
182        }
183        $geometry = geoPHP::load($data, $type);
184        $geometry = geoPHP::geometryReduce($geometry);
185        $geometry = geoPHP_Simplify::geometrySimplify($geometry, $tolerance);
186        $data = $geometry->out($type_sortie ? $type_sortie : $type);
187        return $data;
188}
189
190
191/**
192 * Compile le critère `geometrie_dans_polygone` qui sélectionne des points contenus dans un polygone donné.
193 *
194 * @critere
195 * @see zoner_geometrie() pour créer une zone (polygone) à partir d’un tracé.
196 * @example
197 *     ```
198 *     Dans une boucle GIS : #SET{poly,#GEOMETRY|zoner_geometrie{wkt,0.05}}
199 *     Puis :
200 *     <BOUCLE_points_proches(GIS){type=Point}{geometrie_dans_polygone #GET{poly}}> ...
201 *     ```
202 * @note
203 *     - Nécessite Mysql 5.6 ou Mariadb
204 *     - Si le polygone est trop complexe (nombreux points, le calcul peut être trop long),
205 *       c'est pour cela que zoner_geometrie() simplifie le tracé automatiquement.
206 *
207 * @param string $idb Identifiant de la boucle
208 * @param array $boucles AST du squelette
209 * @param Critere $crit Paramètres du critère dans cette boucle
210 * @return void
211 **/
212function critere_geometrie_dans_polygone_dist($idb, &$boucles, $crit) {
213        $not = $crit->not;
214        $boucle = &$boucles[$idb];
215
216        // prendre en priorite un identifiant en parametre {branche XX}
217        if (isset($crit->param[0])) {
218                $polygon = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent);
219                // sinon on le prend chez une boucle parente
220        } else {
221                return array('zbug_critere_inconnu', array('critere' => $crit->op));
222        }
223
224        $polygon = kwote($polygon, $boucle->sql_serveur, 'TEXT');
225        if ($not) {
226                $boucle->where[] = array("'='", "'ST_WITHIN(gis.geo, GeomFromText(' . $polygon . '))'", "'0'");
227        } else {
228                $boucle->where[] = array("'='", "'ST_WITHIN(gis.geo, GeomFromText(' . $polygon . '))'", "'1'");
229        }
230
231}
Note: See TracBrowser for help on using the repository browser.