Schema
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 |
|
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 |