pggeodb.nancy.inra.fr/db_cefs - db_cefs on pggeodb.nancy.inra.fr
Previous topic Chapter index Next topic

Function: ps_analyse_geom

 

 

Schema

analyse

 

Owner

albenard

 

Descriptions

Cette fonction analyse l'objet géométrique passé en paramètre et retourne un ensemble d'indicateurs sur la situation qualitative de cet objet :
- is_null boolean précisant si l'objet est null
- is_valid boolean précisant si l'objet est valide
Si l'objet est invalide les indicateurs suivant sont renseignés :
- nb_geom nombre de géométries de l'objet
- nb_ring nombre d'anneaux présents dans l'objet
- nb_points nombre de point présents dans l'objet
- nb_geom_invalide nombre de géométries invalides de l'objet
- diffsurface différence de surface entre la géométrie initiale et la géométrie corrigée de manière automatique
- nb_ring_intersect nombre d'auto-intersection total de la géométrie.
- nb_ring_not_closed nombre d'anneaux non fermés dans l'objet
- nb_ring_fermeture_simple nombre d'anneaux ouverts qui peuvent être fermés sans doute sur la correction
- nb_ring_intersect_after_fermeture_ok nombre d'anneaux ouverts qui peuvent être fermés sans doute sur la correction même si la fermeture a engendré un autointersection
- nb_ring_intersect_after_fermeture_douteux nombre d'anneaux ouverts dont la fermeture engendre une autointersection dont le traitement est incertain (nécessite action humaine)
- nb_ring_not_closed_erreur nombre d'anneaux ouverts dont la fermeture est en erreur (nécessite action humaine)
- nb_geom_apres_correction nombre de géométries de l'objet corrige
- nb_ring_apres_correction nombre d'anneaux présents dans l'objet corrige
- nb_points_apres_correction nombre de point présents dans l'objet corrige

 

Options

Option

Value

Returns

record

Language

plpgsql

Parameters

geom public.geometry

out is_null boolean

out is_valid boolean

out nb_geom integer

out nb_ring integer

out nb_points integer

out nb_geom_invalide integer

out diffsurface double precision

out nb_ring_intersect integer

out nb_ring_not_closed integer

out nb_ring_fermeture_simple integer

out nb_ring_intersect_after_fermeture_ok integer

out nb_ring_intersect_after_fermeture_douteux integer

out nb_ring_not_closed_erreur integer

out nb_geom_apres_correction integer

out nb_ring_apres_correction integer

out nb_points_apres_correction integer

 

Definition

CREATE OR REPLACE FUNCTION "analyse".ps_analyse_geom (
 geom public.geometry,
 out is_null boolean,
 out is_valid boolean,
 out nb_geom integer,
 out nb_ring integer,
 out nb_points integer,
 out nb_geom_invalide integer,
 out diffsurface double precision,
 out nb_ring_intersect integer,
 out nb_ring_not_closed integer,
 out nb_ring_fermeture_simple integer,
 out nb_ring_intersect_after_fermeture_ok integer,
 out nb_ring_intersect_after_fermeture_douteux integer,
 out nb_ring_not_closed_erreur integer,
 out nb_geom_apres_correction integer,
 out nb_ring_apres_correction integer,
 out nb_points_apres_correction integer
)
RETURNS record AS
$span$
DECLARE

 -- constantes;
 c_intersect VARCHAR; -- Chaine retournée par la fonction st_isvalidreason en cas d'intersection
 c_not_closed varchar; -- Chaine retournée par la fonction st_isvalidreason en cas d'anneau non fermé
 -- variables;

 i integer; -- Variable de boucle
 j integer; -- Variable de boucle
 geom_validee public.geometry; -- VAriable pour stocker une géométrie corrigée (application de st_makevalid sur la géométrie passée en paramètre)
 geom_courant public.geometry; -- Variable pour stocker les geometries extraites
 nb_ring_encours integer; -- Nombre d'anneaux de la geometrie en cours de traitement
 nb_ring_interieur integer; -- Nombre d'anneaux intérieur de la geometrie en cours de traitement
 anneau_ferme geometry; -- Variable permettant le stockage d'un anneau spécifique
 fermeture_statut INTEGER; -- Variable stockant le statut retourné par la fonction ps_statut_non_ferme
 intersection_geom boolean; -- booléen permettant d'indiquer qu'au moins une intersection est présente
BEGIN
 -- Initialisation des constantes
 C_intersect = 'Ring Self-intersection' ;
 C_not_closed = 'IllegalArgumentException: Points of LinearRing do not form a closed linestring';
 
 -- Initialisation des variables de sortie
 nb_geom = 0;
 nb_ring = 0;
 nb_points = 0;
 nb_geom_invalide = 0;
 diffsurface = 0;
 nb_ring_intersect = 0;
 nb_ring_not_closed = 0;
 nb_ring_fermeture_simple = 0;
 nb_ring_intersect_after_fermeture_ok = 0;
 nb_ring_intersect_after_fermeture_douteux = 0;
 nb_ring_not_closed_erreur = 0;
 nb_geom_apres_correction = 0;
 nb_ring_apres_correction = 0;
 nb_points_apres_correction = 0;
 
 -- Initialisation des variables de foctionnement
 intersection_geom = false;
 
 -- Analyse si l'objet geometrique est null
 if geom is null
  then

    is_null = true;
       return;
  else
    is_null = false;
 end if;
 
 -- Analyse si l'objet geometrique est valide
 if st_isvalid(geom)
  then
    is_valid = true;
       return;
  else
    is_valid = false;
 end if;
 
 -- Extrait le nombre de geometrie(s) contenue(s) dans la géométrie passée en paramètre
 select st_numgeometries(geom) into nb_geom;
 
 -- Extrait le nombre d'anneau(x) contenu(s) dans la géométrie passée en paramètre
 select st_nrings(geom) into nb_ring;
 
 -- Extrait le nombre de points contenus dans la géométrie passée en paramètre
 select st_npoints(geom) into nb_points;
 
 -- Application de la correction automatique
 geom_validee = st_makevalid(geom);
 -- Renseignement de la variable de retour indiquant la différence de surface après correction automatique
 diffsurface = st_area(geom) - st_area(geom_validee);
 
  -- Extrait le nombre de geometrie(s) contenue(s) dans la géométrie corrigée
 select st_numgeometries(geom_validee) into nb_geom_apres_correction;
 
 -- Extrait le nombre d'anneau(x) contenu(s) dans la géométrie corrigée
 select st_nrings(geom_validee) into nb_ring_apres_correction;
 
 -- Extrait le nombre de points contenus dans la géométrie corrigée
 select st_npoints(geom_validee) into nb_points_apres_correction;
 
 FOR i IN 1..nb_geom LOOP
  geom_courant = (st_geometryn(geom,i));
  -- Test la validité de chaque geometrie
   if st_isvalid(geom_courant)
    then
   -- raise notice 'objet N° % , valide : %', i, 'T';
       else -- La sous geometrie en cours d'analyse n'est pas valide
        nb_geom_invalide = nb_geom_invalide + 1;
           nb_ring_encours = st_nrings(geom_courant);
           if nb_ring_encours > 1 -- Plusieurs anneaux dans la géométrie en cours d'analyse
            then
if not
(st_isring(ST_ExteriorRing(geom_courant))) -- Teste la validité de l'anneau extérieur
then -- l'anneau extérieur est incorrect
if st_isclosed(ST_ExteriorRing(geom_courant)) -- test la fermeture
then -- l'anneau incorrect est bien fermé donc il s'autointersecte
-- nb_ring_intersect = nb_ring_intersect + 1;

intersection_geom = true;
-- raise notice 'objet : % , anneau : %, anneau statut %' , i,'ext',' intersection' ;
else -- l'anneau n'est pas fermé
                                   nb_ring_not_closed = nb_ring_not_closed + 1;
                                   anneau_ferme = ST_AddPoint(ST_ExteriorRing(geom_courant), ST_StartPoint(ST_ExteriorRing(geom_courant)));
                                   fermeture_statut = "analyse".ps_statut_non_ferme(anneau_ferme);
                                   case fermeture_statut
                                       when 0 then -- Une erreur est survenue
                                           nb_ring_not_closed_erreur = nb_ring_not_closed_erreur+1;
                                       when 1 then -- La fermeture n'a pas engendré d'autointersection
                                           nb_ring_fermeture_simple = nb_ring_fermeture_simple +1;
                                       when 2 then -- La fermeture a engendré une autointersection bien gérée
                                           nb_ring_intersect_after_fermeture_ok = nb_ring_intersect_after_fermeture_ok +1;
                                       when 3 then -- La fermeture a engendré une autointersection gérée de manière douteuse
                                           nb_ring_intersect_after_fermeture_douteux = nb_ring_intersect_after_fermeture_douteux +1;
                                   end case;
end if;
end if;
nb_ring_interieur = ST_NumInteriorRings(geom_courant);
FOR j IN 1..nb_ring_interieur LOOP -- Pour chaque anneau intérieur on fait les mêmes tests que pour l'anneau externe  
if not (st_isring(ST_InteriorRingN(geom_courant,j))) -- Teste la validité de l'anneau intérieur en cours de validation
then -- l'anneau est incorrect
if st_isclosed(st_interiorringn(geom_courant,j)) -- test la fermeture
then -- l'anneau incorrect est bien fermé donc il s'autointersecte
--nb_ring_intersect = nb_ring_intersect + 1;

intersection_geom = true;
--raise notice 'objet : % , anneau : %, anneau statut %' , i,j,' intersection' ;
else -- l'anneau n'est pas fermé
                                       nb_ring_not_closed = nb_ring_not_closed + 1;
                                       anneau_ferme = ST_AddPoint(ST_InteriorRingN(geom_courant,j), ST_StartPoint(ST_InteriorRingN(geom_courant,j)));
                                       fermeture_statut = "analyse".ps_statut_non_ferme(anneau_ferme);
                                       case fermeture_statut
                                           when 0 then -- Une erreur est survenue
                                               nb_ring_not_closed_erreur = nb_ring_not_closed_erreur+1;
                                           when 1 then -- La fermeture n'a pas engendré d'autointersection
                                               nb_ring_fermeture_simple = nb_ring_fermeture_simple +1;
                                           when 2 then -- La fermeture a engendré une autointersection bien gérée
                                               nb_ring_intersect_after_fermeture_ok = nb_ring_intersect_after_fermeture_ok +1;
                                           when 3 then -- La fermeture a engendré une autointersection gérée de manière douteuse
                                               nb_ring_intersect_after_fermeture_douteux = nb_ring_intersect_after_fermeture_douteux +1;
                                       end case;
end if;
end if;
END LOOP;
               else -- Analyse l'unique anneau de la geometrie non valide.
                --raise NOTICE '1 seul anneau non conforme : %',st_isvalidreason(geom_courant);
                -- raise notice 'objet : % , anneau statut %', i, st_isvalidreason(geom_courant)  ;

                   if st_isvalidreason(geom_courant) = c_not_closed
                    THEN
                        nb_ring_not_closed = nb_ring_not_closed + 1;
                           anneau_ferme = ST_AddPoint(ST_ExteriorRing(geom_courant), ST_StartPoint(ST_ExteriorRing(geom_courant)));
                           fermeture_statut = "analyse".ps_statut_non_ferme(anneau_ferme);
                           case fermeture_statut
                            when 0 then -- Une erreur est survenue
                                nb_ring_not_closed_erreur = nb_ring_not_closed_erreur+1;
                               when 1 then -- La fermeture n'a pas engendré d'autointersection
                                nb_ring_fermeture_simple = nb_ring_fermeture_simple +1;
                               when 2 then -- La fermeture a engendré une autointersection bien gérée
                                nb_ring_intersect_after_fermeture_ok = nb_ring_intersect_after_fermeture_ok +1;
                               when 3 then -- La fermeture a engendré une autointersection gérée de manière douteuse
                                nb_ring_intersect_after_fermeture_douteux = nb_ring_intersect_after_fermeture_douteux +1;
                           end case;
                           
                       else
                        --raise NOTICE 'anneau intersect';
                        --nb_ring_intersect =  nb_ring_intersect + 1;                       

intersection_geom = true;
                   end if;
           end if;
   end if;
 END LOOP;
 if intersection_geom = true -- On calcule le nombre d'intersection sois-même car les fonctions postgis ne permettent pas de savoir si plusieurs auto-intersections sont présentes dans une même géométrie
then
with
listing_geometrie as
(select path[1] as num_geometrie, path[2] as num_anneaux, path[3] as num_point, st_astext(infos_points.geom) as geom_text from
(select (st_dumppoints(geom)).*) as infos_points
),
listing_intersections as
(select num_geometrie,num_anneaux,geom_text, count(num_point) from listing_geometrie
where num_point != 1
group by num_geometrie,num_anneaux,geom_text having count(num_point) >1)
select count(*) from listing_intersections into nb_ring_intersect;
 end if;
 return ;
EXCEPTION
WHEN
OTHERS THEN
 raise notice
'objet traité : %, détail  : i= % - j=%', st_asewkt(geom),i,j;
 raise notice 'Erreur ps_correction_geom : % %', sqlstate, sqlerrm;
END;
$span$
LANGUAGE
'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST
100;

COMMENT ON FUNCTION "analyse".ps_analyse_geom(geom public.geometry, out is_null boolean, out is_valid boolean, out nb_geom integer, out nb_ring integer, out nb_points integer, out nb_geom_invalide integer, out diffsurface double precision, out nb_ring_intersect integer, out nb_ring_not_closed integer, out nb_ring_fermeture_simple integer, out nb_ring_intersect_after_fermeture_ok integer, out nb_ring_intersect_after_fermeture_douteux integer, out nb_ring_not_closed_erreur integer, out nb_geom_apres_correction integer, out nb_ring_apres_correction integer, out nb_points_apres_correction integer)
IS 'Cette fonction analyse l''objet géométrique passé en paramètre et retourne un ensemble d''indicateurs sur la situation qualitative de cet objet :
- is_null boolean précisant si l''objet est null
  - is_valid boolean précisant si l''objet est valide
Si l''objet est invalide les indicateurs suivant sont renseignés :    
   - nb_geom nombre de géométries de l''objet
   - nb_ring nombre d''anneaux présents dans l''objet
- nb_points nombre de point présents dans l''objet
   - nb_geom_invalide nombre de géométries invalides de l''objet
- diffsurface différence de surface entre la géométrie initiale et la géométrie corrigée de manière automatique
- nb_ring_intersect nombre d''auto-intersection total de la géométrie.
- nb_ring_not_closed nombre d''anneaux non fermés dans l''objet
   - nb_ring_fermeture_simple nombre d''anneaux ouverts qui peuvent être fermés sans doute sur la correction
   - nb_ring_intersect_after_fermeture_ok nombre d''anneaux ouverts qui peuvent être fermés sans doute sur la correction même si la fermeture a engendré un autointersection
   - nb_ring_intersect_after_fermeture_douteux nombre d''anneaux ouverts dont la fermeture engendre une autointersection dont le traitement est incertain (nécessite action humaine)
   - nb_ring_not_closed_erreur nombre d''anneaux ouverts dont la fermeture est en erreur (nécessite action humaine)
- nb_geom_apres_correction nombre de géométries de l''objet corrige
- nb_ring_apres_correction nombre d''anneaux présents dans l''objet corrige
- nb_points_apres_correction nombre de point présents dans l''objet corrige
'
;

This file was generated with SQL Manager for PostgreSQL (www.pgsqlmanager.com) at 13/03/2014 13:23
Previous topic Chapter index Next topic