PnX-SI / gn_module_dashboard

Module GeoNature de tableau de bord
GNU Affero General Public License v3.0
4 stars 8 forks source link

st_simplifypreservetopology #9

Open ElsaGuilley opened 5 years ago

ElsaGuilley commented 5 years ago

Vérifier la cohérence topologique de l'ensemble des communes lors de leur insertion dans la BDD

sig-pnrnm commented 5 years ago

Eventuellement, vous pouvez regarder la formule que j'ai proposée dans cette issue : https://github.com/PnX-SI/GeoNature-atlas/issues/121#issuecomment-338980887 Si jamais la fonction ne gardait pas la cohérence topologique.

gildeluermoz commented 5 years ago

Merci Sylvain. Effectivement, dans le module dashbord, pour les communes, on n'a pas besoin de contours hyper précis. Et trop de précision alourdi énormément le geojson des communes. Le soucis c'est que le st_simplify tout seul, qui se fait très rapidement à la volée, nous créé des trous dans la couche. Je vais tester la génération des communes de notre territoire selon ta méthode mais il faut que j'en creuse un usage générique dans le dasbord. A voir si on ajouterait pas un champ geom_simplify pour ce genre d'usage (voir d'autres) dans ref_geo.l_areas ?

sig-pnrnm commented 5 years ago

A voir si on ajouterait pas un champ geom_simplify pour ce genre d'usage (voir d'autres) dans ref_geo.l_areas ?

Pour ma part, puisque ces géométries simplifiées sont systématiquement (et uniquement) utilisées pour les webmaps (Leaflet) en Geojson, j'ai tout bêtement créé un champ geojson, et c'est celui-ci qui est utilisé par Leaflet. Ajouter un champ supplémentaire de type géométrique + un autre de type geojson alourdirait peut-être inutilement la base ?

gildeluermoz commented 5 years ago

oui il n'en faut qu'un. Mais il me semble que le calcul du champ geojson n'est pas pénalisant et conserver l'info dans une vraie géométrie peu permettre d'en faire un autre usage. A trancher. Et surtout voir si on ajoute un champ à ref_geo.l_areas

sig-pnrnm commented 5 years ago

il me semble que le calcul du champ geojson n'est pas pénalisant

si c'est le cas, en effet, autant le calculer à la volée alors. Mais ça m'étonne que ça ne demande pas de ressources au serveur, s'il y a beaucoup de géométries à convertir (ex. si beaucoup de communes sont affichées). A tester !

A trancher. Et surtout voir si on ajoute un champ à ref_geo.l_areas

Je vote pour ! :+1:

camillemonchicourt commented 5 years ago

Désormais la simplification des géométries est faite à la volée : https://github.com/PnX-SI/gn_module_dashboard/commit/c6ca9c6722221341b0928c904503d319523fad67 Le niveau de simplification est en dur mais mériterait à être un paramètre.

sig-pnrnm commented 5 years ago

Désormais la simplification des géométries est faite à la volée

Si c'est uniquement la fonction st_simplifyPreserveTopology() qui est utilisée, il y aura je pense des problèmes de topologie sur les géométries des communes simplifiées.

Je vous invite à lire ce document très précis, qui fournit des requêtes SQL ou une fonction (simplifyLayerPreserveTopology()) permettant de simplifier les géométries d'une couche comme celle des communes.

gildeluermoz commented 5 years ago

Oui la simplification crée des trous. Pour le moment, il est préférable d'avoir des trous et un geojson de qq ko plutôt qu'un geojson de plusieurs Mo sans trou. C'est le choix qu'on a fait.

Je propose la modif suivante que j'ai testé sur ma base GN2.

--Suppression des index pour permettre l'ajout d'un champ dans un temps raisonnable
DROP INDEX IF EXISTS ref_geo.index_l_areas_geom;
DROP INDEX IF EXISTS ref_geo.index_l_areas_centroid;
DROP INDEX IF EXISTS ref_geo.i_lareas_area_code;
ALTER TABLE ref_geo.l_areas DROP COLUMN IF EXISTS simplified_geom ;
ALTER TABLE ref_geo.l_areas ADD COLUMN simplified_geom public.geometry(Geometry,2154);
--désactiver les triggers
ALTER TABLE ref_geo.l_areas DISABLE TRIGGER user;

--Création de la table temporaire avec les géométries simplifiées
--pour les communes de notre territoire
--pas testé sur un territoire plus large
--charge à chacun dele faire sur les unités geographiques qu'il a besoin d'utiliser en geojson simplifié
DROP TABLE IF EXISTS ref_geo.temp_simplified_areas;
CREATE TABLE ref_geo.temp_simplified_areas AS
with poly as (
        select a.id_area, (st_dump(a.geom)).*
        FROM ref_geo.l_areas a
        JOIN ref_geo.li_municipalities com ON com.id_area = a.id_area
        AND com.insee_dep IN ('04','05','06','38','73','26')
) select d.id_area, baz.geom
 from (
        select (st_dump(st_polygonize(distinct geom))).geom as geom
        from (
                select (st_dump(st_simplifyPreserveTopology(st_linemerge(st_union(geom)), 100))).geom as geom
                from (
                        select st_exteriorRing((st_dumpRings(geom)).geom) as geom
                        from poly
                ) as foo
        ) as bar
) as baz,
poly d
where st_intersects(d.geom, baz.geom)
and st_area(st_intersection(d.geom, baz.geom))/st_area(baz.geom) > 0.5;

--initialisation de simplified_geom avec les géom non simplifiés
--obligatoire sinon le dashobord qui utilise ce champ ne fonctionnerait pas
UPDATE ref_geo.l_areas
SET simplified_geom = geom
WHERE simplified_geom IS NULL;

--Insertion des geom simplifiés dans la table l_areas
UPDATE ref_geo.l_areas
SET simplified_geom = tmp.geom
FROM ref_geo.temp_simplified_areas tmp
WHERE tmp.id_area = ref_geo.l_areas.id_area;

--recréer les index
CREATE INDEX index_l_areas_geom ON ref_geo.l_areas USING gist (geom);
CREATE INDEX index_l_areas_centroid ON ref_geo.l_areas USING gist (centroid);
CREATE INDEX index_l_areas_simplified_geom ON ref_geo.l_areas USING gist (simplified_geom);
CREATE INDEX i_lareas_area_code ON ref_geo.l_areas (area_code);
--réactiver les triggers
ALTER TABLE ref_geo.l_areas DISABLE TRIGGER user;

Ensuite il faudra juste modifier le dashboard pour qu'il fonctionne sur le champ simplified_geom

sig-pnrnm commented 5 years ago

il est préférable d'avoir des trous et un geojson de qq ko plutôt qu'un geojson de plusieurs Mo sans trou

Tu es sûr du lien entre la présence des trous dans les géométries et le poids des fichiers ? Je ne suis pas sûr que ça : SPT_no_topo soit beaucoup plus léger que ça : SPT_dept_sim

Ce qui va jouer dans le poids des GeoJson, c'est le nombre de noeuds, et il est surtout dépendant du paramètre de distance de la simplification (qui pourrait être en effet un paramètre général, ou couche par couche)

camillemonchicourt commented 5 years ago

Oui bien sur, ce que veut dire Gil, c'est que pour l'instant on a préféré assumer de créer des trous mais fortement alléger le poids du GeoJson. Cependant si une meilleure méthode permet de simplifier sans générer des trous, c'est encore mieux. Pour commencer on a fait simple et toute contribution/amélioration comme tu proposes est bienvenue.

sig-pnrnm commented 5 years ago

Pas de souci, c'est juste que je ne suis pas sûr de cette affirmation "mais fortement alléger le poids du GeoJson." (puisque je pense que la différence de poids est négligeable).

Mais n'ayant pas les compétences pour intégrer les requêtes topologiques dans le code général, je me contenterai de la formule simple et efficace :wink:

(le sujet initial étant : "Vérifier la cohérence topologique de l'ensemble des communes lors de leur insertion dans la BDD", la réponse est non : les communes ne seront pas topologiques. Mais c'est sans-doute pas fondamental pour les GeoJson)

gildeluermoz commented 5 years ago

Je ne sais pas si on parle de la même chose. Je te laisse juger de l'exagération éventuelle du "fortement". Le geojson des communes (tel que fourni dans GeoNature 2), sans simplification, fait un peu plus de 3Mo. Après simplification selon ta méthode on passe à 260 Ko Soit un facteur supérieur à 10.

sylvain-m commented 5 years ago

260 Ko, c'est beaucoup moins que 3Mo ??? Tu ne t'es pas trompé d'unités ?

Et dans "ma" méthode, il y a le paramètre de distance qui est à ajuster, donc le résultat peut être complètement différent selon la valeur.

(désolé, j'ai répondu avec mon compte perso, je suis à la maison aujourd'hui)

gildeluermoz commented 5 years ago

Oui j'ai mis le paramètre de distance à 200 comme conseillé. Ca nous va bien et c'est effectivement un compromis acceptable quant au résultat. 3 Mo = 3072 Ko ? Non ? 260Ko * 10 = 2600 Ko = 2.54Mo ? Non ? J'ai raté qq chose ?

sylvain-m commented 5 years ago

J'ai raté qq chose ?

Ben non, on est d'accord. Et donc "ma" méthode produit un geojson 10x plus léger, puisque tu dis que

selon ta méthode on passe à 260 Ko

(contre 3 Mo initiaux)

N'est-ce pas le but recherché ?

(Il doit y avoir une incompréhension de ma part quelque part, car je pensais que tu disais que ma méthode créait un Geojson plus lourd)

camillemonchicourt commented 5 years ago

Incompréhension. Gil parlait uniquement de la différence entre la géométrie initiale et celle simplifiée. Quitte à avoir des trous. On n'a pas eu le temps de regarder tes propositions plus précises sans trous.

sylvain-m commented 5 years ago

Ok, pas de souci :wink:

gildeluermoz commented 5 years ago

Oui, imcompréhension. J'ai bien testé la création d'un champ simplified_geom avec la requête que tu proposes. Et le résultat produit un geojson 10 fois moins lourd que le geom des communes d'origine. Et sans trou. Donc parfait. Y'a plus qu'à proposer ça dans le code. One day !

camillemonchicourt commented 1 year ago

On utilise une simplification des géométries paramétrable (https://github.com/PnX-SI/gn_module_dashboard/blob/master/config/conf_gn_module.toml.example#L6), mais @ElsaGuilley avait fait des tests et détaillé cela dans son rapport de stage (https://geonature.fr/documents/2019-09-rapport-stage-Elsa-Guilley-Dashboard-Validation.pdf), ainsi que dans sa présentation de soutenance (https://geonature.fr/documents/2019-09-soutenance-stage-Elsa-Guilley-Dashboard-Validation.pptx) :

image

image

Et le stockage des géométries simplifiées en conservant leur topologie reste une piste très intéressante, potentiellement utile à d'autres endroits de GeoNature.