J'utilise une PL/R
fonction et PostGIS
génère des polygones de voronoï autour d'un ensemble de points. La fonction que j'utilise est définie ici . Lorsque j'utilise cette fonction sur un ensemble de données particulier, le message d'erreur suivant s'affiche:
Error : ERROR: R interpreter expression evaluation error
DETAIL: Error in pg.spi.exec(sprintf("SELECT %3$s AS id,
st_intersection('SRID='||st_srid(%2$s)||';%4$s'::text,'%5$s')
AS polygon FROM %1$s WHERE st_intersects(%2$s::text,'SRID='||st_srid(%2$s)||';%4$s');",
:error in SQL statement : Error performing intersection: TopologyException: found non-noded
intersection between LINESTRING (571304 310990, 568465 264611) and LINESTRING (568465
264611, 594406 286813) at 568465.05533706467 264610.82749605528
CONTEXT: In R support function pg.spi.exec In PL/R function r_voronoi
En examinant cette partie du message d'erreur:
Error performing intersection: TopologyException: found non-noded intersection between
LINESTRING (571304 310990, 568465 264611) and LINESTRING (568465 264611, 594406 286813)
at 568465.05533706467 264610.82749605528
Voici à quoi ressemble le problème mentionné ci-dessus:
J'ai d'abord pensé que ce message pouvait être causé par l'existence de points identiques et j'ai essayé de résoudre ce problème en utilisant la st_translate()
fonction utilisée de la manière suivante:
ST_Translate(geom, random()*20, random()*20) as geom
Cela résout le problème, mais ce qui me préoccupe, c’est que je traduis maintenant tous les points jusqu’à environ 20 m dans la direction x / y. Je ne peux pas non plus savoir quel montant de traduction est nécessaire. Par exemple, dans cet ensemble de données par essais et erreurs, un20m * random number
est ok, mais comment puis-je savoir si cela doit être plus grand?
Basé sur l'image ci-dessus, je pense que le problème est que le point intersecte la ligne alors que l'algorithme tente de l'intersecter du polygone. Je ne suis pas sûr de ce que je devrais faire pour m'assurer que le point se trouve dans un polygone, plutôt que de croiser une ligne. L'erreur se produit sur cette ligne:
"SELECT
%3$s AS id,
st_intersection(''SRID=''||st_srid(%2$s)||'';%4$s''::text,''%5$s'') AS polygon
FROM
%1$s
WHERE
st_intersects(%2$s::text,''SRID=''||st_srid(%2$s)||'';%4$s'');"
J'ai lu cette question précédente, qu'est-ce qu'une "intersection sans nœud"? pour essayer de mieux comprendre ce problème et apprécierait tout conseil sur la meilleure façon de le résoudre.
WHERE ST_IsValid(p.geom)
pour filtrer les points au départ.Réponses:
D'après mon expérience, ce problème est presque toujours causé par:
Le "coup de pouce" approche de la
ST_Buffer
solutions vous permet d’éviter 2, mais tout ce que vous pouvez faire pour résoudre ces causes sous-jacentes, telles que l’accrochage de votre géométrie sur une grille 1e-6, vous facilitera la vie. Les géométries mises en mémoire tampon conviennent généralement bien pour les calculs intermédiaires, tels que la zone de chevauchement, mais vous devrez faire attention à les conserver, car elles peuvent aggraver vos problèmes proches mais pas tout à fait graves à long terme.La capacité de gestion des exceptions de PostgreSQL vous permet d'écrire des fonctions de wrapper pour gérer ces cas particuliers, en mettant en mémoire tampon uniquement lorsque cela est nécessaire. Voici un exemple pour
ST_Intersection
; J'utilise une fonction similaire pourST_Difference
. Vous devrez décider si la mise en mémoire tampon et le retour potentiel d'un polygone vide sont acceptables dans votre situation.Un autre avantage de cette approche est que vous pouvez identifier les géométries qui causent réellement vos problèmes. ajoutez simplement quelques
RAISE NOTICE
instructions dans leEXCEPTION
bloc pour générer WKT ou autre chose qui vous aidera à localiser le problème.la source
Après beaucoup d'essais et d'erreurs, j'ai finalement réalisé que cela
non-noded intersection
résultait d'un problème d'auto-intersection. J'ai trouvé un fil qui suggère d'utiliserST_buffer(geom, 0)
peut être utilisé pour résoudre le problème (même si cela le rend beaucoup plus lent dans l'ensemble). J'ai ensuite essayé d'utiliserST_MakeValid()
et lorsqu'il est appliqué directement à la géométrie avant toute autre fonction. Cela semble résoudre le problème de manière robuste.J'ai marqué ceci comme étant la réponse car cela semble être la seule approche qui résout mon problème.
la source
J'ai rencontré ce même problème (Postgres 9.1.4, PostGIS 2.1.1), et la seule chose qui a fonctionné pour moi a été d'envelopper la géométrie avec un très petit tampon.
ST_MakeValid
n'a pas fonctionné pour moi, ni la combinaison deST_Node
etST_Dump
. La mémoire tampon ne semblait pas entraîner de dégradation des performances, mais si je la réduisais plus petite, je recevais quand même une erreur d'intersection sans nœud.Moche, mais ça marche.
Mise à jour:
La stratégie ST_Buffer semble bien fonctionner, mais j'ai rencontré un problème qui entraînait des erreurs lors de la conversion de la géométrie en géographie. Par exemple, si un point est à l'origine à -90.0 et qu'il est mis en mémoire tampon par 0.0000001, il est maintenant à -90.0000001, ce qui est une géographie non valide.
Cela signifie que même si
ST_IsValid(geom)
étaitt
, deST_Area(geom::geography)
retourNaN
pour de nombreuses fonctionnalités.Pour éviter le problème d'intersection non noded, tout en maintenant la géographie valide, je fini par utiliser
ST_SnapToGrid
comme sila source
Dans le postgis, ST_Node devrait interrompre une série de lignes aux intersections, ce qui devrait résoudre le problème des intersections sans nœud. Envelopper cela dans ST_Dump génère le tableau composite des lignes pointillées.
Légèrement lié, il y a une présentation géniale PostGIS: Conseils pour utilisateurs chevronnés qui décrit clairement ce type de problèmes et de solutions.
la source
ST_Node
etST_Dump
? J'imagine que je devrais les utiliser près de cette partie de la fonction, mais je ne suis pas certain:st_intersection(''SRID=''||st_srid(%2$s)||'';%4$s''::text,''%5$s'')
inst_node
ici - puis-je l'utiliser avantst_intersection
?D'après mon expérience, j'ai résolu mon
non-noded intersection
erreur en utilisant la fonction St_SnapToGrid qui résolvait le problème de la précision élevée des coordonnées du sommet des polygones.la source